odp-util: Correctly [de]serialize mask for ND attributes.
authorDaniele Di Proietto <diproiettod@vmware.com>
Wed, 9 Dec 2015 02:39:18 +0000 (18:39 -0800)
committerDaniele Di Proietto <diproiettod@vmware.com>
Fri, 11 Dec 2015 01:38:23 +0000 (17:38 -0800)
When converting between ODP attributes and struct flow_wildcards, we
check that all the prerequisites are exact matched on the mask.

For ND(ICMPv6) attributes, an exact match on tp_src and tp_dst
(which in this context are the icmp type and code) shold look like
htons(0xff), not htons(0xffff).  Fix this in two places.

The consequences were that the ODP mask wouldn't include the ND
attributes and the flow would be deleted by the revalidation.

lib/odp-util.c

index 3717aee..aa5bd6b 100644 (file)
@@ -4358,8 +4358,12 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms,
             if (flow->tp_dst == htons(0)
                 && (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)
                     || flow->tp_src == htons(ND_NEIGHBOR_ADVERT))
-                && (!export_mask || (data->tp_src == htons(0xffff)
-                                     && data->tp_dst == htons(0xffff)))) {
+                /* Even though 'tp_src' and 'tp_dst' are 16 bits wide, ICMP
+                 * type and code are 8 bits wide.  Therefore, an exact match
+                 * looks like htons(0xff), not htons(0xffff).  See
+                 * xlate_wc_finish() for details. */
+                && (!export_mask || (data->tp_src == htons(0xff)
+                                     && data->tp_dst == htons(0xff)))) {
 
                 struct ovs_key_nd *nd_key;
 
@@ -4904,9 +4908,14 @@ parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
                     flow->arp_sha = nd_key->nd_sll;
                     flow->arp_tha = nd_key->nd_tll;
                     if (is_mask) {
+                        /* Even though 'tp_src' and 'tp_dst' are 16 bits wide,
+                         * ICMP type and code are 8 bits wide.  Therefore, an
+                         * exact match looks like htons(0xff), not
+                         * htons(0xffff).  See xlate_wc_finish() for details.
+                         * */
                         if (!is_all_zeros(nd_key, sizeof *nd_key) &&
-                            (flow->tp_src != htons(0xffff) ||
-                             flow->tp_dst != htons(0xffff))) {
+                            (flow->tp_src != htons(0xff) ||
+                             flow->tp_dst != htons(0xff))) {
                             return ODP_FIT_ERROR;
                         } else {
                             expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ND;