Signed-off-by: Simon Horman <ho...@verge.net.au>
---
 lib/classifier.c | 30 ++++++++++++++++++++++++++----
 lib/classifier.h |  1 +
 lib/meta-flow.c  |  5 ++++-
 3 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/lib/classifier.c b/lib/classifier.c
index e74817e..964db25 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -229,14 +229,36 @@ cls_rule_set_any_vid(struct cls_rule *rule)
  *   - Otherwise, makes 'rule' match only packets with an 802.1Q header whose
  *     VID equals the low 12 bits of 'dl_vlan'.
  */
+static void
+cls_rule_set_dl_vlan_masked__(struct cls_rule *rule, ovs_be16 dl_vlan,
+                              ovs_be16 mask)
+{
+    mask |= htons(VLAN_CFI);
+    flow_set_vlan_vid(&rule->flow, dl_vlan & mask);
+    rule->wc.vlan_tci_mask = mask;
+}
+
 void
 cls_rule_set_dl_vlan(struct cls_rule *rule, ovs_be16 dl_vlan)
 {
-    flow_set_vlan_vid(&rule->flow, dl_vlan);
-    if (dl_vlan == htons(OFP_VLAN_NONE)) {
-        rule->wc.vlan_tci_mask = htons(UINT16_MAX);
+    ovs_be16 mask;
+
+    if (dl_vlan == htons(OFPVID12_NONE)) {
+        mask = htons(UINT16_MAX);
+    } else {
+        mask = rule->wc.vlan_tci_mask |= htons(VLAN_VID_MASK);
+    }
+    cls_rule_set_dl_vlan_masked__(rule, dl_vlan, mask);
+}
+
+void
+cls_rule_set_dl_vlan_masked(struct cls_rule *rule, ovs_be16 dl_vlan,
+                            ovs_be16 mask)
+{
+    if ((mask & htons(VLAN_VID_MASK)) == 0) {
+        cls_rule_set_dl_vlan(rule, htons(OFP_VLAN_NONE));
     } else {
-        rule->wc.vlan_tci_mask |= htons(VLAN_VID_MASK | VLAN_CFI);
+        cls_rule_set_dl_vlan_masked__(rule, dl_vlan, mask);
     }
 }
 
diff --git a/lib/classifier.h b/lib/classifier.h
index 7aca7db..a8663d5 100644
--- a/lib/classifier.h
+++ b/lib/classifier.h
@@ -106,6 +106,7 @@ void cls_rule_set_dl_tci_masked(struct cls_rule *,
                                 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_dl_vlan_masked(struct cls_rule *, ovs_be16, ovs_be16);
 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_dl_vlan_tpid(struct cls_rule *, ovs_be16);
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index eb34aa3..72ed108 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -1706,7 +1706,6 @@ mf_set(const struct mf_field *mf,
     switch (mf->id) {
     case MFF_IN_PORT:
     case MFF_ETH_TYPE:
-    case MFF_VLAN_VID:
     case MFF_VLAN_PCP:
     case MFF_VLAN_TPID:
     case MFF_VLAN_QINQ_VID:
@@ -1747,6 +1746,10 @@ mf_set(const struct mf_field *mf,
         cls_rule_set_dl_src_masked(rule, value->mac, mask->mac);
         break;
 
+    case MFF_VLAN_VID:
+        cls_rule_set_dl_vlan_masked(rule, value->be16, mask->be16);
+        break;
+
     case MFF_VLAN_TCI:
         cls_rule_set_dl_tci_masked(rule, value->be16, mask->be16);
         break;
-- 
1.7.10.2.484.gcd07cc5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to