nx-match: Check prerequisites for ICMPv6 before outputting subfields.
authorBen Pfaff <blp@nicira.com>
Mon, 9 May 2011 23:21:00 +0000 (16:21 -0700)
committerBen Pfaff <blp@nicira.com>
Fri, 27 May 2011 22:42:19 +0000 (15:42 -0700)
nicira-ext.h documents that NXM_NX_ND_TARGET requires ND_NEIGHBOR_SOLICIT
or ND_NEIGHBOR_ADVERT, that NXM_NX_ND_SLL requires ND_NEIGHBOR_SOLICIT,
and that NXM_NX_ND_TLL requires ND_NEIGHBOR_ADVERT, but nx_put_match()
would add them to the match regardless of whether these prerequisites were
satisfied.  On the other side, nx_pull_match() did check the prerequisites,
so this was a case where OVS could output flows that it would refused to
parse.  This fixes the problem.

Found by inspection.

lib/nx-match.c

index f5d62de2f0349a3cadc0cc59016a4a9c88552037..4a41136ea9f36c4f25ea756b3d04442487ecb18b 100644 (file)
@@ -833,20 +833,26 @@ nx_put_match(struct ofpbuf *b, const struct cls_rule *cr)
             case IPPROTO_ICMPV6:
                 if (!(wc & FWW_TP_SRC)) {
                     nxm_put_8(b, NXM_NX_ICMPV6_TYPE, ntohs(flow->tp_src));
+
+                    if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
+                        flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
+                        if (!(wc & FWW_ND_TARGET)) {
+                            nxm_put_ipv6(b, NXM_NX_ND_TARGET, &flow->nd_target,
+                                         &in6addr_exact);
+                        }
+                        if (!(wc & FWW_ARP_SHA)
+                            && flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
+                            nxm_put_eth(b, NXM_NX_ND_SLL, flow->arp_sha);
+                        }
+                        if (!(wc & FWW_ARP_THA)
+                            && flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
+                            nxm_put_eth(b, NXM_NX_ND_TLL, flow->arp_tha);
+                        }
+                    }
                 }
                 if (!(wc & FWW_TP_DST)) {
                     nxm_put_8(b, NXM_NX_ICMPV6_CODE, ntohs(flow->tp_dst));
                 }
-                if (!(wc & FWW_ND_TARGET)) {
-                    nxm_put_ipv6(b, NXM_NX_ND_TARGET, &flow->nd_target,
-                            &in6addr_exact);
-                }
-                if (!(wc & FWW_ARP_SHA)) {
-                    nxm_put_eth(b, NXM_NX_ND_SLL, flow->arp_sha);
-                }
-                if (!(wc & FWW_ARP_THA)) {
-                    nxm_put_eth(b, NXM_NX_ND_TLL, flow->arp_tha);
-                }
                 break;
             }
         }