From: Ben Pfaff Date: Mon, 23 Jul 2012 06:20:22 +0000 (-0700) Subject: meta-flow: Add OF1.2-like MFF_VLAN_VID and MFF_VLAN_PCP. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=openvswitch;a=commitdiff_plain;h=cc34bc8c8611868474253b8fbd9e79cd66c60c94 meta-flow: Add OF1.2-like MFF_VLAN_VID and MFF_VLAN_PCP. 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 Acked-by: Simon Horman --- diff --git a/lib/classifier.c b/lib/classifier.c index 42e200d0..38f1a4fe 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -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. */ diff --git a/lib/classifier.h b/lib/classifier.h index b76b9573..93223450 100644 --- a/lib/classifier.h +++ b/lib/classifier.h @@ -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); diff --git a/lib/flow.c b/lib/flow.c index 984f5d98..6129703a 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -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. * diff --git a/lib/flow.h b/lib/flow.h index 315ca365..5e78f796 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -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 *); diff --git a/lib/meta-flow.c b/lib/meta-flow.c index 27f3bca7..101409a2 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -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; diff --git a/lib/meta-flow.h b/lib/meta-flow.h index e4237d1c..28d43ebc 100644 --- a/lib/meta-flow.h +++ b/lib/meta-flow.h @@ -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 */