ofp-util: Work on decoding OF1.1 flow_mods.
[openvswitch] / lib / nx-match.c
index 8b2a82292e9e37eab5c9fc7a46ef39f6a877c7f4..893566da4b0daf66e38e15e0908280e7ecce7924 100644 (file)
@@ -67,7 +67,8 @@ nx_entry_ok(const void *p, unsigned int match_len)
 
     if (match_len < 4) {
         if (match_len) {
-            VLOG_DBG_RL(&rl, "nx_match ends with partial nxm_header");
+            VLOG_DBG_RL(&rl, "nx_match ends with partial (%u-byte) nxm_header",
+                        match_len);
         }
         return 0;
     }
@@ -492,7 +493,7 @@ nx_put_match(struct ofpbuf *b, bool oxm, const struct cls_rule *cr,
     int match_len;
     int i;
 
-    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 14);
 
     /* Metadata. */
     if (!(wc & FWW_IN_PORT)) {
@@ -514,10 +515,24 @@ nx_put_match(struct ofpbuf *b, bool oxm, const struct cls_rule *cr,
                    ofputil_dl_type_to_openflow(flow->dl_type));
     }
 
-    /* 802.1Q.
-     *
-     * XXX missing OXM support */
-    nxm_put_16m(b, NXM_OF_VLAN_TCI, flow->vlan_tci, cr->wc.vlan_tci_mask);
+    /* 802.1Q. */
+    if (oxm) {
+        ovs_be16 vid = flow->vlan_tci & htons(VLAN_VID_MASK | VLAN_CFI);
+        ovs_be16 mask = cr->wc.vlan_tci_mask & htons(VLAN_VID_MASK | VLAN_CFI);
+
+        if (mask == htons(VLAN_VID_MASK | VLAN_CFI)) {
+            nxm_put_16(b, OXM_OF_VLAN_VID, vid);
+        } else if (mask) {
+            nxm_put_16m(b, OXM_OF_VLAN_VID, vid, mask);
+        }
+
+        if (vid && vlan_tci_to_pcp(cr->wc.vlan_tci_mask)) {
+            nxm_put_8(b, OXM_OF_VLAN_PCP, vlan_tci_to_pcp(flow->vlan_tci));
+        }
+
+    } else {
+        nxm_put_16m(b, NXM_OF_VLAN_TCI, flow->vlan_tci, cr->wc.vlan_tci_mask);
+    }
 
     /* L3. */
     if (!(wc & FWW_DL_TYPE) && flow->dl_type == htons(ETH_TYPE_IP)) {
@@ -539,25 +554,21 @@ nx_put_match(struct ofpbuf *b, bool oxm, const struct cls_rule *cr,
                    oxm ? OXM_OF_ICMPV6_TYPE : NXM_NX_ICMPV6_TYPE,
                    oxm ? OXM_OF_ICMPV6_CODE : NXM_NX_ICMPV6_CODE, oxm);
 
-        if (!(wc & FWW_IPV6_LABEL)) {
-            nxm_put_32(b, oxm ? OXM_OF_IPV6_FLABEL : NXM_NX_IPV6_LABEL,
-                       flow->ipv6_label);
-        }
+        nxm_put_32m(b, oxm ? OXM_OF_IPV6_FLABEL : NXM_NX_IPV6_LABEL,
+                    flow->ipv6_label, cr->wc.ipv6_label_mask);
 
         if (flow->nw_proto == IPPROTO_ICMPV6
             && (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
                 flow->tp_src == htons(ND_NEIGHBOR_ADVERT))) {
             nxm_put_ipv6(b, oxm ? OXM_OF_IPV6_ND_TARGET : NXM_NX_ND_TARGET,
                          &flow->nd_target, &cr->wc.nd_target_mask);
-            if (!(wc & FWW_ARP_SHA)
-                && flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
-                nxm_put_eth(b, oxm ? OXM_OF_IPV6_ND_SLL : NXM_NX_ND_SLL,
-                            flow->arp_sha);
+            if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
+                nxm_put_eth_masked(b, oxm ? OXM_OF_IPV6_ND_SLL : NXM_NX_ND_SLL,
+                                   flow->arp_sha, cr->wc.arp_sha_mask);
             }
-            if (!(wc & FWW_ARP_THA)
-                && flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
-                nxm_put_eth(b, oxm ? OXM_OF_IPV6_ND_TLL : NXM_NX_ND_TLL,
-                            flow->arp_tha);
+            if (flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
+                nxm_put_eth_masked(b, oxm ? OXM_OF_IPV6_ND_TLL : NXM_NX_ND_TLL,
+                                   flow->arp_tha, cr->wc.arp_tha_mask);
             }
         }
     } else if (!(wc & FWW_DL_TYPE) && flow->dl_type == htons(ETH_TYPE_ARP)) {
@@ -570,14 +581,10 @@ nx_put_match(struct ofpbuf *b, bool oxm, const struct cls_rule *cr,
                     flow->nw_src, cr->wc.nw_src_mask);
         nxm_put_32m(b, oxm ? OXM_OF_ARP_TPA : NXM_OF_ARP_TPA,
                     flow->nw_dst, cr->wc.nw_dst_mask);
-        if (!(wc & FWW_ARP_SHA)) {
-            nxm_put_eth(b, oxm ? OXM_OF_ARP_SHA : NXM_NX_ARP_SHA,
-                        flow->arp_sha);
-        }
-        if (!(wc & FWW_ARP_THA)) {
-            nxm_put_eth(b, oxm ? OXM_OF_ARP_THA : NXM_NX_ARP_THA,
-                        flow->arp_tha);
-        }
+        nxm_put_eth_masked(b, oxm ? OXM_OF_ARP_SHA : NXM_NX_ARP_SHA,
+                           flow->arp_sha, cr->wc.arp_sha_mask);
+        nxm_put_eth_masked(b, oxm ? OXM_OF_ARP_THA : NXM_NX_ARP_THA,
+                           flow->arp_tha, cr->wc.arp_tha_mask);
     }
 
     /* Tunnel ID. */