As we have discussed offline, When ethertype attribute is not specified in the key filed but specified in the mask filed, we treat to mean a special ether type, namely the 802.2 ether type.
The incremental over V5 of the mega flow patch are attached. V6 will be sent shortly after all V5 feedback are received. --andy --- datapath/flow.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/datapath/flow.c b/datapath/flow.c index f6674fd..2b7d9ed 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -135,6 +135,9 @@ static bool ovs_match_validate(const struct sw_flow_match *match, | (1ULL << OVS_KEY_ATTR_ARP) | (1ULL << OVS_KEY_ATTR_ND)); + if (match->key->eth.type == htons(ETH_P_802_2)) + mask_allowed |= (1ULL << OVS_KEY_ATTR_ETHERTYPE); + /* Check key attributes. */ if (match->key->eth.type == htons(ETH_P_ARP) || match->key->eth.type == htons(ETH_P_RARP)) { @@ -1349,7 +1352,7 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs, const struct ovs_key_ipv6 *ipv6_key; ipv6_key = nla_data(a[OVS_KEY_ATTR_IPV6]); - if (ipv6_key->ipv6_frag > OVS_FRAG_TYPE_MAX) + if (!is_mask && ipv6_key->ipv6_frag > OVS_FRAG_TYPE_MAX) return -EINVAL; SW_FLOW_KEY_PUT(match, ipv6.label, ipv6_key->ipv6_label, is_mask); @@ -1534,6 +1537,15 @@ int ovs_match_from_nlattrs(struct sw_flow_match *match, ovs_sw_flow_mask_set(match->mask, &match->range, 0xff); } + if (!(key_attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE))) { + if (match->mask) + if (match->mask->key.eth.type != htons(0xffff) + && (match->mask->key.eth.type != htons(0))) + return -EINVAL; + + match->key->eth.type = htons(ETH_P_802_2); + } + if (ovs_match_validate(match, key_attrs, mask_attrs) == false) return -EINVAL; @@ -1607,32 +1619,34 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, nla_put_u32(skb, OVS_KEY_ATTR_SKB_MARK, output->phy.skb_mark)) goto nla_put_failure; - nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key)); - if (!nla) - goto nla_put_failure; + if (!is_all_zero((u8 *)&output->eth, 2 * ETH_ALEN)) { + nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key)); + if (!nla) + goto nla_put_failure; - eth_key = nla_data(nla); - memcpy(eth_key->eth_src, output->eth.src, ETH_ALEN); - memcpy(eth_key->eth_dst, output->eth.dst, ETH_ALEN); + eth_key = nla_data(nla); + memcpy(eth_key->eth_src, output->eth.src, ETH_ALEN); + memcpy(eth_key->eth_dst, output->eth.dst, ETH_ALEN); + } if (swkey->eth.tci || swkey->eth.type == htons(ETH_P_8021Q)) { __be16 eth_type; - eth_type = (swkey == output) ? htons(ETH_P_8021Q) : 0 ; + eth_type = (swkey == output) ? htons(ETH_P_8021Q) : htons(0xffff) ; if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, eth_type) || - nla_put_be16(skb, OVS_KEY_ATTR_VLAN, output->eth.tci)) + nla_put_be16(skb, OVS_KEY_ATTR_VLAN, output->eth.tci)) goto nla_put_failure; encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP); if (!swkey->eth.tci) goto unencap; - } else { + } else encap = NULL; - } - if (swkey->eth.type == htons(ETH_P_802_2)) + if ((swkey == output) && (swkey->eth.type == htons(ETH_P_802_2))) goto unencap; - if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, output->eth.type)) - goto nla_put_failure; + if (output->eth.type != 0) + if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, output->eth.type)) + goto nla_put_failure; if (swkey->eth.type == htons(ETH_P_IP)) { struct ovs_key_ipv4 *ipv4_key; -- 1.7.9.5 --- lib/odp-util.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/odp-util.c b/lib/odp-util.c index a126148..a243adc 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -1316,18 +1316,19 @@ odp_flow_format(const struct nlattr *key, size_t key_len, if (key_len) { const struct nlattr *a; unsigned int left; + bool has_ethtype_key = false; + const struct nlattr *ma = NULL; NL_ATTR_FOR_EACH (a, left, key, key_len) { - const struct nlattr *ma = NULL; - if (a != key) { ds_put_char(ds, ','); } - + if (nl_attr_type(a) == OVS_KEY_ATTR_ETHERTYPE) { + has_ethtype_key = true; + } if (mask && mask_len) { ma = nl_attr_find__(mask, mask_len, nl_attr_type(a)); } - format_odp_key_attr(a, ma, ds); } if (left) { @@ -1342,6 +1343,13 @@ odp_flow_format(const struct nlattr *key, size_t key_len, } ds_put_char(ds, ')'); } + if (!has_ethtype_key) { + ma = nl_attr_find__(mask, mask_len, OVS_KEY_ATTR_ETHERTYPE); + if (ma) { + ds_put_format(ds, ",eth_type(0/0x%04"PRIx16")", + ntohs(nl_attr_get_be16(ma))); + } + } } else { ds_put_cstr(ds, "<empty>"); } @@ -1659,7 +1667,9 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names, if (mask && sscanf(s, "eth_type(%i/%i)%n", ð_type, ð_type_mask, &n) > 0 && n > 0) { - nl_msg_put_be16(key, OVS_KEY_ATTR_ETHERTYPE, htons(eth_type)); + if (eth_type != 0) { + nl_msg_put_be16(key, OVS_KEY_ATTR_ETHERTYPE, htons(eth_type)); + } nl_msg_put_be16(mask, OVS_KEY_ATTR_ETHERTYPE, htons(eth_type_mask)); return n; } else if (sscanf(s, "eth_type(%i)%n", ð_type, &n) > 0 && n > 0) { -- 1.7.9.5
_______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev