}
}
+/* Sets the VLAN VID that 'flow' matches to 'vid', which is interpreted as an
+ * OpenFlow 1.2 "vlan_vid" value, that is, the low 13 bits of 'vlan_tci' (VID
+ * plus CFI). */
+void
+cls_rule_set_vlan_vid(struct cls_rule *rule, ovs_be16 vid)
+{
+ cls_rule_set_vlan_vid_masked(rule, vid, htons(VLAN_VID_MASK | VLAN_CFI));
+}
+
+
+/* Sets the VLAN VID that 'flow' matches to 'vid', which is interpreted as an
+ * OpenFlow 1.2 "vlan_vid" value, that is, the low 13 bits of 'vlan_tci' (VID
+ * plus CFI), with the corresponding 'mask'. */
+void
+cls_rule_set_vlan_vid_masked(struct cls_rule *rule,
+ ovs_be16 vid, ovs_be16 mask)
+{
+ ovs_be16 pcp_mask = htons(VLAN_PCP_MASK);
+ ovs_be16 vid_mask = htons(VLAN_VID_MASK | VLAN_CFI);
+
+ mask &= vid_mask;
+ flow_set_vlan_vid(&rule->flow, vid & mask);
+ rule->wc.vlan_tci_mask = mask | (rule->wc.vlan_tci_mask & pcp_mask);
+}
+
/* Modifies 'rule' so that the VLAN PCP is wildcarded. If the VID is already
* wildcarded, then 'rule' will match a packet regardless of whether it has an
* 802.1Q header or not. */
ovs_be16 tci, ovs_be16 mask);
void cls_rule_set_any_vid(struct cls_rule *);
void cls_rule_set_dl_vlan(struct cls_rule *, ovs_be16);
+void cls_rule_set_vlan_vid(struct cls_rule *, ovs_be16);
+void cls_rule_set_vlan_vid_masked(struct cls_rule *,
+ ovs_be16 vid, ovs_be16 mask);
void cls_rule_set_any_pcp(struct cls_rule *);
void cls_rule_set_dl_vlan_pcp(struct cls_rule *, uint8_t);
void cls_rule_set_tp_src(struct cls_rule *, ovs_be16);
}
}
+/* Sets the VLAN VID that 'flow' matches to 'vid', which is interpreted as an
+ * OpenFlow 1.2 "vlan_vid" value, that is, the low 13 bits of 'vlan_tci' (VID
+ * plus CFI). */
+void
+flow_set_vlan_vid(struct flow *flow, ovs_be16 vid)
+{
+ ovs_be16 mask = htons(VLAN_VID_MASK | VLAN_CFI);
+ flow->vlan_tci &= ~mask;
+ flow->vlan_tci |= vid & mask;
+}
+
/* Sets the VLAN PCP that 'flow' matches to 'pcp', which should be in the
* range 0...7.
*
static inline size_t flow_hash(const struct flow *, uint32_t basis);
void flow_set_dl_vlan(struct flow *, ovs_be16 vid);
+void flow_set_vlan_vid(struct flow *, ovs_be16 vid);
void flow_set_vlan_pcp(struct flow *, uint8_t pcp);
void flow_compose(struct ofpbuf *, const struct flow *);
MFS_DECIMAL,
MFP_NONE,
true,
+ 0, NULL,
+ 0, NULL,
+ }, {
+ MFF_VLAN_VID, "vlan_vid", NULL,
+ sizeof(ovs_be16), 12,
+ MFM_FULLY, 0,
+ MFS_DECIMAL,
+ MFP_NONE,
+ true,
OXM_OF_VLAN_VID, "OXM_OF_VLAN_VID",
OXM_OF_VLAN_VID, "OXM_OF_VLAN_VID",
}, {
MFS_DECIMAL,
MFP_NONE,
true,
+ 0, NULL,
+ 0, NULL,
+ }, {
+ MFF_VLAN_PCP, "vlan_pcp", NULL,
+ 1, 3,
+ MFM_NONE, 0,
+ MFS_DECIMAL,
+ MFP_NONE,
+ true,
OXM_OF_VLAN_PCP, "OXM_OF_VLAN_PCP",
OXM_OF_VLAN_PCP, "OXM_OF_VLAN_PCP",
},
return !wc->vlan_tci_mask;
case MFF_DL_VLAN:
return !(wc->vlan_tci_mask & htons(VLAN_VID_MASK));
+ case MFF_VLAN_VID:
+ return !(wc->vlan_tci_mask & htons(VLAN_VID_MASK | VLAN_CFI));
case MFF_DL_VLAN_PCP:
+ case MFF_VLAN_PCP:
return !(wc->vlan_tci_mask & htons(VLAN_PCP_MASK));
case MFF_IPV4_SRC:
case MFF_DL_VLAN:
mask->be16 = wc->vlan_tci_mask & htons(VLAN_VID_MASK);
break;
+ case MFF_VLAN_VID:
+ mask->be16 = wc->vlan_tci_mask & htons(VLAN_VID_MASK | VLAN_CFI);
+ break;
case MFF_DL_VLAN_PCP:
+ case MFF_VLAN_PCP:
mask->u8 = vlan_tci_to_pcp(wc->vlan_tci_mask);
break;
case MFF_DL_VLAN:
return !(value->be16 & htons(VLAN_CFI | VLAN_PCP_MASK));
+ case MFF_VLAN_VID:
+ return !(value->be16 & htons(VLAN_PCP_MASK));
case MFF_DL_VLAN_PCP:
+ case MFF_VLAN_PCP:
return !(value->u8 & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT));
case MFF_IPV6_LABEL:
case MFF_DL_VLAN:
value->be16 = flow->vlan_tci & htons(VLAN_VID_MASK);
break;
+ case MFF_VLAN_VID:
+ value->be16 = flow->vlan_tci & htons(VLAN_VID_MASK | VLAN_CFI);
+ break;
case MFF_DL_VLAN_PCP:
+ case MFF_VLAN_PCP:
value->u8 = vlan_tci_to_pcp(flow->vlan_tci);
break;
case MFF_DL_VLAN:
cls_rule_set_dl_vlan(rule, value->be16);
break;
+ case MFF_VLAN_VID:
+ cls_rule_set_vlan_vid(rule, value->be16);
+ break;
case MFF_DL_VLAN_PCP:
+ case MFF_VLAN_PCP:
cls_rule_set_dl_vlan_pcp(rule, value->u8);
break;
case MFF_DL_VLAN:
flow_set_dl_vlan(flow, value->be16);
break;
+ case MFF_VLAN_VID:
+ flow_set_vlan_vid(flow, value->be16);
+ break;
case MFF_DL_VLAN_PCP:
+ case MFF_VLAN_PCP:
flow_set_vlan_pcp(flow, value->u8);
break;
break;
case MFF_DL_VLAN:
+ case MFF_VLAN_VID:
cls_rule_set_any_vid(rule);
break;
case MFF_DL_VLAN_PCP:
+ case MFF_VLAN_PCP:
cls_rule_set_any_pcp(rule);
break;
case MFF_ETH_TYPE:
case MFF_DL_VLAN:
case MFF_DL_VLAN_PCP:
+ case MFF_VLAN_PCP:
case MFF_IP_PROTO:
case MFF_IP_TTL:
case MFF_IP_DSCP:
cls_rule_set_dl_tci_masked(rule, value->be16, mask->be16);
break;
+ case MFF_VLAN_VID:
+ cls_rule_set_vlan_vid_masked(rule, value->be16, mask->be16);
+ break;
+
case MFF_IPV4_SRC:
cls_rule_set_nw_src_masked(rule, value->be32, mask->be32);
break;
case MFF_DL_VLAN:
value->be16 &= htons(VLAN_VID_MASK);
break;
+ case MFF_VLAN_VID:
+ value->be16 &= htons(VLAN_VID_MASK | VLAN_CFI);
+ break;
case MFF_DL_VLAN_PCP:
+ case MFF_VLAN_PCP:
value->u8 &= 0x07;
break;
MFF_VLAN_TCI, /* be16 */
MFF_DL_VLAN, /* be16 (OpenFlow 1.0 compatibility) */
+ MFF_VLAN_VID, /* be16 (OpenFlow 1.2 compatibility) */
MFF_DL_VLAN_PCP, /* u8 (OpenFlow 1.0 compatibility) */
+ MFF_VLAN_PCP, /* be16 (OpenFlow 1.2 compatibility) */
/* L3. */
MFF_IPV4_SRC, /* be32 */