meta-flow: Add OF1.2-like MFF_VLAN_VID and MFF_VLAN_PCP.
authorBen Pfaff <blp@nicira.com>
Mon, 23 Jul 2012 06:20:22 +0000 (23:20 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 23 Jul 2012 16:21:37 +0000 (09:21 -0700)
OpenFlow 1.0 and 1.2 have notions of VLAN that are different
enough to warrant separate "meta-flow" fields, which this commit
adds.

Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Simon Horman <horms@verge.net.au>
lib/classifier.c
lib/classifier.h
lib/flow.c
lib/flow.h
lib/meta-flow.c
lib/meta-flow.h

index 42e200d0ad38226851d1425b063a5819cd9a9634..38f1a4feaf27838928c810ccd3a272bad854b8f3 100644 (file)
@@ -274,6 +274,31 @@ cls_rule_set_dl_vlan(struct cls_rule *rule, ovs_be16 dl_vlan)
     }
 }
 
+/* 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. */
index b76b9573cde66c8a85acf498ffe591727e24a592..932234503b29246ea1862ca6fecbc23ea6713f1d 100644 (file)
@@ -112,6 +112,9 @@ 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_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);
index 984f5d9805be09da8c98463b71a2bffb5e739aa9..6129703a2025314d1c644ecd5598c2b59981d6ac 100644 (file)
@@ -979,6 +979,17 @@ flow_set_dl_vlan(struct flow *flow, ovs_be16 vid)
     }
 }
 
+/* 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.
  *
index 315ca3650755ef1f2ae3edca17291c76888d3746..5e78f7963b1dfbb72b1915e4a7089a793f28db90 100644 (file)
@@ -118,6 +118,7 @@ static inline bool flow_equal(const struct flow *, const struct flow *);
 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 *);
index 27f3bca73ba128c543af5dee5b374ef9cff9f37a..101409a2cbaefcdc8458a35b2827fe0685e71b83 100644 (file)
@@ -163,6 +163,15 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
         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",
     }, {
@@ -172,6 +181,15 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
         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",
     },
@@ -590,7 +608,10 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
         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:
@@ -681,7 +702,11 @@ mf_get_mask(const struct mf_field *mf, const struct flow_wildcards *wc,
     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;
 
@@ -888,8 +913,11 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
 
     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:
@@ -942,8 +970,12 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
     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;
 
@@ -1081,8 +1113,12 @@ mf_set_value(const struct mf_field *mf,
     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;
 
@@ -1220,8 +1256,12 @@ mf_set_flow_value(const struct mf_field *mf,
     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;
 
@@ -1375,10 +1415,12 @@ mf_set_wild(const struct mf_field *mf, struct cls_rule *rule)
         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;
 
@@ -1505,6 +1547,7 @@ mf_set(const struct mf_field *mf,
     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:
@@ -1550,6 +1593,10 @@ mf_set(const struct mf_field *mf,
         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;
@@ -1726,8 +1773,12 @@ mf_random_value(const struct mf_field *mf, union mf_value *value)
     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;
 
index e4237d1cbd12b91e2756b044062c5a78f7b21c26..28d43ebc78e4de62236308f93bd82616602fe729 100644 (file)
@@ -67,7 +67,9 @@ enum mf_field_id {
 
     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 */