In preparation for supporting the OpenFlow 1.2 VLAN_VID and VLAN_PCP matches, internally honour the CFI bit and add come special cases to provide backwards-compatible behaviour for ovs-ofputil add-flows dl_vlan.
Signed-off-by: Simon Horman <ho...@verge.net.au> --- lib/classifier.c | 14 +------------- lib/flow.c | 13 +++++-------- lib/ofp-parse.c | 20 ++++++++++++++++++++ lib/packets.h | 1 + 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/lib/classifier.c b/lib/classifier.c index 2d9fd0a..18be0e1 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -235,23 +235,11 @@ cls_rule_set_any_vid(struct cls_rule *rule) } } -/* Modifies 'rule' depending on 'dl_vlan': - * - * - If 'dl_vlan' is htons(OFP_VLAN_NONE), makes 'rule' match only packets - * without an 802.1Q header. - * - * - Otherwise, makes 'rule' match only packets with an 802.1Q header whose - * VID equals the low 12 bits of 'dl_vlan'. - */ 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(OFP10_VLAN_NONE)) { - rule->wc.vlan_tci_mask = htons(UINT16_MAX); - } else { - rule->wc.vlan_tci_mask |= htons(VLAN_VID_MASK | VLAN_CFI); - } + rule->wc.vlan_tci_mask |= htons(VLAN_VID_MASK | VLAN_CFI); } /* Modifies 'rule' so that the VLAN PCP is wildcarded. If the VID is already diff --git a/lib/flow.c b/lib/flow.c index 9ad1898..3c0efc5 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -947,13 +947,9 @@ flow_hash_fields_valid(enum nx_hash_fields fields) void flow_set_vlan_vid(struct flow *flow, ovs_be16 vid) { - if (vid == htons(OFP10_VLAN_NONE)) { - flow->vlan_tci = htons(0); - } else { - vid &= htons(VLAN_VID_MASK); - flow->vlan_tci &= ~htons(VLAN_VID_MASK); - flow->vlan_tci |= htons(VLAN_CFI) | 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 @@ -966,9 +962,10 @@ flow_set_vlan_vid(struct flow *flow, ovs_be16 vid) void flow_set_vlan_pcp(struct flow *flow, uint8_t pcp) { + uint16_t cfi = (pcp & VLAN_PCP_SET_CFI_FLAG) ? VLAN_CFI : 0; pcp &= 0x07; flow->vlan_tci &= ~htons(VLAN_PCP_MASK); - flow->vlan_tci |= htons((pcp << VLAN_PCP_SHIFT) | VLAN_CFI); + flow->vlan_tci |= htons((pcp << VLAN_PCP_SHIFT) | cfi); } /* Puts into 'b' a packet that flow_extract() would parse as having the given diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index 32d3836..1df3275 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -528,6 +528,26 @@ parse_field(const struct mf_field *mf, const char *s, struct cls_rule *rule) ovs_fatal(0, "%s", error); } + if (mf->id == MFF_VLAN_VID) { + /* Provide backwards compatibility for ovs-ofctl to set 'dl_vlan' + * via code that supports OpenFlow 1.2 VLAN_VID. */ + if (value.be16 == htons(OFP10_VLAN_NONE)) { + /* Special case for OFP10_VLAN_NONE, map to OFPVID12_NONE + * which provides the desired behaviour. */ + value.be16 = htons(OFPVID12_NONE); + } else { + /* Else, ensure the CFI bit set set */ + value.be16 |= htons(VLAN_CFI); + } + } + else if (mf->id == MFF_VLAN_PCP) { + /* Provide backwards compatibility for ovs-ofctl to set * 'dl_vlan_pcp' + * via code that supports OpenFlow 1.2 VLAN_PCP. + * Set the most significant bit, which is otherwise unused, + * to indicate that the CFI bit should be set internally */ + value.u8 |= VLAN_PCP_SET_CFI_FLAG; + } + mf_set(mf, &value, &mask, rule); } diff --git a/lib/packets.h b/lib/packets.h index ad5631d..8fb6d4b 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -255,6 +255,7 @@ BUILD_ASSERT_DECL(RARP_HEADER_LEN == sizeof(struct rarp_header)); #define VLAN_PCP_SHIFT 13 #define VLAN_CFI 0x1000 +#define VLAN_PCP_SET_CFI_FLAG 0x8 /* Given the vlan_tci field from an 802.1Q header, in network byte order, * returns the VLAN ID in host byte order. */ -- 1.7.10.2.484.gcd07cc5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev