nx-match: Check prerequisites for ICMPv6 before outputting subfields.
[sliver-openvswitch.git] / lib / nx-match.c
index 4d2e590..4a41136 100644 (file)
@@ -176,9 +176,6 @@ parse_nxm_entry(struct cls_rule *rule, const struct nxm_field *f,
         /* Metadata. */
     case NFI_NXM_OF_IN_PORT:
         flow->in_port = ntohs(get_unaligned_be16(value));
-        if (flow->in_port == OFPP_LOCAL) {
-            flow->in_port = ODPP_LOCAL;
-        }
         return 0;
 
         /* Ethernet header. */
@@ -680,7 +677,7 @@ nxm_put_eth(struct ofpbuf *b, uint32_t header,
 
 static void
 nxm_put_eth_dst(struct ofpbuf *b,
-                uint32_t wc, const uint8_t value[ETH_ADDR_LEN])
+                flow_wildcards_t wc, const uint8_t value[ETH_ADDR_LEN])
 {
     switch (wc & (FWW_DL_DST | FWW_ETH_MCAST)) {
     case FWW_DL_DST | FWW_ETH_MCAST:
@@ -739,9 +736,6 @@ nx_put_match(struct ofpbuf *b, const struct cls_rule *cr)
     /* Metadata. */
     if (!(wc & FWW_IN_PORT)) {
         uint16_t in_port = flow->in_port;
-        if (in_port == ODPP_LOCAL) {
-            in_port = OFPP_LOCAL;
-        }
         nxm_put_16(b, NXM_OF_IN_PORT, htons(in_port));
     }
 
@@ -839,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;
             }
         }
@@ -1272,7 +1272,7 @@ nxm_read_field(const struct nxm_field *src, const struct flow *flow)
 {
     switch (src->index) {
     case NFI_NXM_OF_IN_PORT:
-        return flow->in_port == ODPP_LOCAL ? OFPP_LOCAL : flow->in_port;
+        return flow->in_port;
 
     case NFI_NXM_OF_ETH_DST:
         return eth_addr_to_uint64(flow->dl_dst);