int match_len;
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 13);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 14);
/* Metadata. */
if (!(wc & FWW_IN_PORT)) {
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)) {
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)) {
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. */