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