@@ -197,6 +197,8 @@ void match_set_tp_dst_masked(struct match *, ovs_be16 port, ovs_be16 mask);
void match_set_tcp_flags(struct match *, ovs_be16);
void match_set_tcp_flags_masked(struct match *, ovs_be16 flags, ovs_be16 mask);
void match_set_nw_proto(struct match *, uint8_t);
+void match_set_nw_proto_masked(struct match *match,
+ const uint8_t nw_proto, const uint8_t mask);
void match_set_nw_src(struct match *, ovs_be32);
void match_set_nw_src_masked(struct match *, ovs_be32 ip, ovs_be32 mask);
void match_set_nw_dst(struct match *, ovs_be32);
@@ -210,6 +212,9 @@ void match_set_nw_frag(struct match *, uint8_t nw_frag);
void match_set_nw_frag_masked(struct match *, uint8_t nw_frag, uint8_t mask);
void match_set_icmp_type(struct match *, uint8_t);
void match_set_icmp_code(struct match *, uint8_t);
+void match_set_arp_opcode_masked(struct match *match,
+ const uint8_t opcode,
+ const uint8_t mask);
void match_set_arp_sha(struct match *, const struct eth_addr);
void match_set_arp_sha_masked(struct match *,
const struct eth_addr arp_sha,
@@ -218,6 +223,12 @@ void match_set_arp_tha(struct match *, const struct eth_addr);
void match_set_arp_tha_masked(struct match *,
const struct eth_addr arp_tha,
const struct eth_addr mask);
+void match_set_arp_spa_masked(struct match *match,
+ const ovs_be32 arp_spa,
+ const ovs_be32 mask);
+void match_set_arp_tpa_masked(struct match *match,
+ const ovs_be32 arp_tpa,
+ const ovs_be32 mask);
void match_set_ipv6_src(struct match *, const struct in6_addr *);
void match_set_ipv6_src_masked(struct match *, const struct in6_addr *,
const struct in6_addr *);
@@ -940,6 +940,14 @@ match_set_nw_proto(struct match *match, uint8_t nw_proto)
match->wc.masks.nw_proto = UINT8_MAX;
}
+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)
{
@@ -1033,6 +1041,30 @@ match_set_icmp_code(struct match *match, uint8_t icmp_code)
match_set_tp_dst(match, htons(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)
{
@@ -543,6 +543,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);
}
@@ -1521,6 +1529,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;
@@ -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 ?
+ UINT16_MAX: htons(flow->nw_proto);
arp->arp_sha = flow->arp_sha;
arp->arp_tha = flow->arp_tha;
}
@@ -313,6 +313,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, },
@@ -417,6 +435,45 @@ static const struct nl_policy tca_flower_policy[] = {
.optional = true, },
};
+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)
{
@@ -1735,6 +1792,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);
@@ -2712,6 +2770,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);
@@ -121,6 +121,14 @@ struct tc_flower_key {
uint32_t ct_mark;
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;