summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTonghao Zhang <xiangxia.m.yue@gmail.com>2020-06-05 21:17:29 +0800
committerSimon Horman <simon.horman@netronome.com>2020-06-08 11:08:05 +0200
commita3db6e473d9fb6558d0dc065bc4b3e4e1c2f9455 (patch)
treee3f84e59ee4e9a8204aa13e9bbe9b3a1807a06ec /lib
parent5db012c4ac3630ec99fa6c64bbae38cbbcd0544e (diff)
downloadopenvswitch-a3db6e473d9fb6558d0dc065bc4b3e4e1c2f9455.tar.gz
netdev-offload-tc: Allow installing arp rules to TC dp.
This patch allows to install arp rules to tc dp. In the future, arp will be offloaded to hardware to be processed. So OvS enable this now. $ ovs-appctl dpctl/add-flow 'recirc_id(0),in_port(3),eth(),\ eth_type(0x0806),arp(op=2,tha=00:50:56:e1:4b:ab,tip=10.255.1.116)' 2 $ ovs-appctl dpctl/dump-flows ... arp(tip=10.255.1.116,op=2,tha=00:50:56:e1:4b:ab) ... $ tc filter show dev <ethx> ingress ... eth_type arp arp_tip 10.255.1.116 arp_op reply arp_tha 00:50:56:e1:4b:ab not_in_hw action order 1: mirred (Egress Redirect to device <ethy>) stolen ... Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com> Signed-off-by: Simon Horman <simon.horman@netronome.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/match.c32
-rw-r--r--lib/netdev-offload-tc.c27
-rw-r--r--lib/odp-util.c3
-rw-r--r--lib/tc.c66
-rw-r--r--lib/tc.h8
5 files changed, 135 insertions, 1 deletions
diff --git a/lib/match.c b/lib/match.c
index 29b25a73b..a77554851 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -941,6 +941,14 @@ match_set_nw_proto(struct match *match, uint8_t nw_proto)
}
void
+match_set_nw_proto_masked(struct match *match,
+ const uint8_t nw_proto, const uint8_t mask)
+{
+ match->flow.nw_proto = nw_proto;
+ match->wc.masks.nw_proto = mask;
+}
+
+void
match_set_nw_src(struct match *match, ovs_be32 nw_src)
{
match->flow.nw_src = nw_src;
@@ -1034,6 +1042,30 @@ match_set_icmp_code(struct match *match, uint8_t icmp_code)
}
void
+match_set_arp_opcode_masked(struct match *match,
+ const uint8_t opcode,
+ const uint8_t mask)
+{
+ match_set_nw_proto_masked(match, opcode, mask);
+}
+
+void
+match_set_arp_spa_masked(struct match *match,
+ const ovs_be32 arp_spa,
+ const ovs_be32 mask)
+{
+ match_set_nw_src_masked(match, arp_spa, mask);
+}
+
+void
+match_set_arp_tpa_masked(struct match *match,
+ const ovs_be32 arp_tpa,
+ const ovs_be32 mask)
+{
+ match_set_nw_dst_masked(match, arp_tpa, mask);
+}
+
+void
match_set_arp_sha(struct match *match, const struct eth_addr sha)
{
match->flow.arp_sha = sha;
diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index 19295573f..aa6d22e74 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -589,6 +589,14 @@ parse_tc_flower_to_match(struct tc_flower *flower,
match->flow.mpls_lse[0] = key->mpls_lse & mask->mpls_lse;
match->wc.masks.mpls_lse[0] = mask->mpls_lse;
match_set_dl_type(match, key->encap_eth_type[0]);
+ } else if (key->eth_type == htons(ETH_TYPE_ARP)) {
+ match_set_arp_sha_masked(match, key->arp.sha, mask->arp.sha);
+ match_set_arp_tha_masked(match, key->arp.tha, mask->arp.tha);
+ match_set_arp_spa_masked(match, key->arp.spa, mask->arp.spa);
+ match_set_arp_tpa_masked(match, key->arp.tpa, mask->arp.tpa);
+ match_set_arp_opcode_masked(match, key->arp.opcode,
+ mask->arp.opcode);
+ match_set_dl_type(match, key->eth_type);
} else {
match_set_dl_type(match, key->eth_type);
}
@@ -1558,6 +1566,25 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
mask->dl_type = 0;
mask->in_port.odp_port = 0;
+ if (key->dl_type == htons(ETH_P_ARP)) {
+ flower.key.arp.spa = key->nw_src;
+ flower.key.arp.tpa = key->nw_dst;
+ flower.key.arp.sha = key->arp_sha;
+ flower.key.arp.tha = key->arp_tha;
+ flower.key.arp.opcode = key->nw_proto;
+ flower.mask.arp.spa = mask->nw_src;
+ flower.mask.arp.tpa = mask->nw_dst;
+ flower.mask.arp.sha = mask->arp_sha;
+ flower.mask.arp.tha = mask->arp_tha;
+ flower.mask.arp.opcode = mask->nw_proto;
+
+ mask->nw_src = 0;
+ mask->nw_dst = 0;
+ mask->nw_proto = 0;
+ memset(&mask->arp_sha, 0, sizeof mask->arp_sha);
+ memset(&mask->arp_tha, 0, sizeof mask->arp_tha);
+ }
+
if (is_ip_any(key)) {
flower.key.ip_proto = key->nw_proto;
flower.mask.ip_proto = mask->nw_proto;
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 72601dc6b..9b31244c2 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -7993,7 +7993,8 @@ get_arp_key(const struct flow *flow, struct ovs_key_arp *arp)
arp->arp_sip = flow->nw_src;
arp->arp_tip = flow->nw_dst;
- arp->arp_op = htons(flow->nw_proto);
+ arp->arp_op = flow->nw_proto == UINT8_MAX ?
+ OVS_BE16_MAX : htons(flow->nw_proto);
arp->arp_sha = flow->arp_sha;
arp->arp_tha = flow->arp_tha;
}
diff --git a/lib/tc.c b/lib/tc.c
index 9e51ac155..29b4328d8 100644
--- a/lib/tc.c
+++ b/lib/tc.c
@@ -318,6 +318,24 @@ static const struct nl_policy tca_flower_policy[] = {
.min_len = ETH_ALEN,
.optional = true, },
[TCA_FLOWER_KEY_ETH_TYPE] = { .type = NL_A_U16, .optional = false, },
+ [TCA_FLOWER_KEY_ARP_SIP] = { .type = NL_A_U32, .optional = true, },
+ [TCA_FLOWER_KEY_ARP_TIP] = { .type = NL_A_U32, .optional = true, },
+ [TCA_FLOWER_KEY_ARP_SHA] = { .type = NL_A_UNSPEC,
+ .min_len = ETH_ALEN,
+ .optional = true, },
+ [TCA_FLOWER_KEY_ARP_THA] = { .type = NL_A_UNSPEC,
+ .min_len = ETH_ALEN,
+ .optional = true, },
+ [TCA_FLOWER_KEY_ARP_OP] = { .type = NL_A_U8, .optional = true, },
+ [TCA_FLOWER_KEY_ARP_SIP_MASK] = { .type = NL_A_U32, .optional = true, },
+ [TCA_FLOWER_KEY_ARP_TIP_MASK] = { .type = NL_A_U32, .optional = true, },
+ [TCA_FLOWER_KEY_ARP_SHA_MASK] = { .type = NL_A_UNSPEC,
+ .min_len = ETH_ALEN,
+ .optional = true, },
+ [TCA_FLOWER_KEY_ARP_THA_MASK] = { .type = NL_A_UNSPEC,
+ .min_len = ETH_ALEN,
+ .optional = true, },
+ [TCA_FLOWER_KEY_ARP_OP_MASK] = { .type = NL_A_U8, .optional = true, },
[TCA_FLOWER_FLAGS] = { .type = NL_A_U32, .optional = false, },
[TCA_FLOWER_ACT] = { .type = NL_A_NESTED, .optional = false, },
[TCA_FLOWER_KEY_IP_PROTO] = { .type = NL_A_U8, .optional = true, },
@@ -428,6 +446,45 @@ static const struct nl_policy tca_flower_terse_policy[] = {
};
static void
+nl_parse_flower_arp(struct nlattr **attrs, struct tc_flower *flower)
+{
+ const struct eth_addr *eth;
+
+ if (attrs[TCA_FLOWER_KEY_ARP_SIP_MASK]) {
+ flower->key.arp.spa =
+ nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ARP_SIP]);
+ flower->mask.arp.spa =
+ nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ARP_SIP_MASK]);
+ }
+ if (attrs[TCA_FLOWER_KEY_ARP_TIP_MASK]) {
+ flower->key.arp.tpa =
+ nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ARP_TIP]);
+ flower->mask.arp.tpa =
+ nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ARP_TIP_MASK]);
+ }
+ if (attrs[TCA_FLOWER_KEY_ARP_SHA_MASK]) {
+ eth = nl_attr_get_unspec(attrs[TCA_FLOWER_KEY_ARP_SHA], ETH_ALEN);
+ memcpy(&flower->key.arp.sha, eth, sizeof flower->key.arp.sha);
+
+ eth = nl_attr_get_unspec(attrs[TCA_FLOWER_KEY_ARP_SHA_MASK], ETH_ALEN);
+ memcpy(&flower->mask.arp.sha, eth, sizeof flower->mask.arp.sha);
+ }
+ if (attrs[TCA_FLOWER_KEY_ARP_THA_MASK]) {
+ eth = nl_attr_get_unspec(attrs[TCA_FLOWER_KEY_ARP_THA], ETH_ALEN);
+ memcpy(&flower->key.arp.tha, eth, sizeof flower->key.arp.tha);
+
+ eth = nl_attr_get_unspec(attrs[TCA_FLOWER_KEY_ARP_THA_MASK], ETH_ALEN);
+ memcpy(&flower->mask.arp.tha, eth, sizeof flower->mask.arp.tha);
+ }
+ if (attrs[TCA_FLOWER_KEY_ARP_OP_MASK]) {
+ flower->key.arp.opcode =
+ nl_attr_get_u8(attrs[TCA_FLOWER_KEY_ARP_OP]);
+ flower->mask.arp.opcode =
+ nl_attr_get_u8(attrs[TCA_FLOWER_KEY_ARP_OP_MASK]);
+ }
+}
+
+static void
nl_parse_flower_eth(struct nlattr **attrs, struct tc_flower *flower)
{
const struct eth_addr *eth;
@@ -1760,6 +1817,7 @@ nl_parse_flower_options(struct nlattr *nl_options, struct tc_flower *flower,
}
nl_parse_flower_eth(attrs, flower);
+ nl_parse_flower_arp(attrs, flower);
nl_parse_flower_mpls(attrs, flower);
nl_parse_flower_vlan(attrs, flower);
nl_parse_flower_ip(attrs, flower);
@@ -2745,6 +2803,14 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower)
FLOWER_PUT_MASKED_VALUE(dst_mac, TCA_FLOWER_KEY_ETH_DST);
FLOWER_PUT_MASKED_VALUE(src_mac, TCA_FLOWER_KEY_ETH_SRC);
+ if (host_eth_type == ETH_P_ARP) {
+ FLOWER_PUT_MASKED_VALUE(arp.spa, TCA_FLOWER_KEY_ARP_SIP);
+ FLOWER_PUT_MASKED_VALUE(arp.tpa, TCA_FLOWER_KEY_ARP_TIP);
+ FLOWER_PUT_MASKED_VALUE(arp.sha, TCA_FLOWER_KEY_ARP_SHA);
+ FLOWER_PUT_MASKED_VALUE(arp.tha, TCA_FLOWER_KEY_ARP_THA);
+ FLOWER_PUT_MASKED_VALUE(arp.opcode, TCA_FLOWER_KEY_ARP_OP);
+ }
+
if (host_eth_type == ETH_P_IP || host_eth_type == ETH_P_IPV6) {
FLOWER_PUT_MASKED_VALUE(ip_ttl, TCA_FLOWER_KEY_IP_TTL);
FLOWER_PUT_MASKED_VALUE(ip_tos, TCA_FLOWER_KEY_IP_TOS);
diff --git a/lib/tc.h b/lib/tc.h
index 11f3231f9..028eed5d0 100644
--- a/lib/tc.h
+++ b/lib/tc.h
@@ -122,6 +122,14 @@ struct tc_flower_key {
ovs_u128 ct_label;
struct {
+ ovs_be32 spa;
+ ovs_be32 tpa;
+ struct eth_addr sha;
+ struct eth_addr tha;
+ uint8_t opcode;
+ } arp;
+
+ struct {
ovs_be32 ipv4_src;
ovs_be32 ipv4_dst;
uint8_t rewrite_ttl;