[ovs-dev] [PATCH 4/5 V6] Actions changes 802.1ad Customer TCI
Thomas F Herbert
thomasfherbert at entpnt.com
Thu Jan 8 21:29:14 UTC 2015
This patch changes the actions processing to support popping and pushing of
double stacked vlans (qinq.)
Signed-off-by: Thomas F Herbert <thomasfherbert at entpnt.com>
---
lib/ofp-actions.c | 32 +++++++++++++++++++-------------
lib/ofp-actions.h | 9 ++++++++-
lib/packets.c | 2 +-
lib/packets.h | 7 +++++++
ofproto/ofproto-dpif-xlate.c | 13 ++++++++++++-
5 files changed, 47 insertions(+), 16 deletions(-)
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 4680d81..7414a78 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -1266,16 +1266,20 @@ format_STRIP_VLAN(const struct ofpact_null *a, struct ds *s)
static enum ofperr
decode_OFPAT_RAW11_PUSH_VLAN(ovs_be16 eth_type, struct ofpbuf *out)
{
- if (eth_type != htons(ETH_TYPE_VLAN_8021Q)) {
- /* XXX 802.1AD(QinQ) isn't supported at the moment */
+ struct ofpact_push_vlan *oam;
+
+ if (!eth_type_vlan(eth_type)) {
+ /* XXX Only 802.1q and 802.1AD(QinQ) is supported. */
return OFPERR_OFPBAC_BAD_ARGUMENT;
}
- ofpact_put_PUSH_VLAN(out);
+ oam = ofpact_put_PUSH_VLAN(out);
+ oam->ethertype = eth_type;
+
return 0;
}
static void
-encode_PUSH_VLAN(const struct ofpact_null *null OVS_UNUSED,
+encode_PUSH_VLAN(const struct ofpact_push_vlan *push_vlan,
enum ofp_version ofp_version, struct ofpbuf *out)
{
if (ofp_version == OFP10_VERSION) {
@@ -1283,7 +1287,7 @@ encode_PUSH_VLAN(const struct ofpact_null *null OVS_UNUSED,
* follow this action. */
} else {
/* XXX ETH_TYPE_VLAN_8021AD case */
- put_OFPAT11_PUSH_VLAN(out, htons(ETH_TYPE_VLAN_8021Q));
+ put_OFPAT11_PUSH_VLAN(out, push_vlan->ethertype);
}
}
@@ -1295,25 +1299,25 @@ parse_PUSH_VLAN(char *arg, struct ofpbuf *ofpacts,
char *error;
*usable_protocols &= OFPUTIL_P_OF11_UP;
- error = str_to_u16(arg, "ethertype", ðertype);
+ error = str_to_u16(arg, "push_vlan", ðertype);
if (error) {
return error;
}
- if (ethertype != ETH_TYPE_VLAN_8021Q) {
- /* XXX ETH_TYPE_VLAN_8021AD case isn't supported */
+ if (!eth_type_vlan(htons(ethertype))) {
+ /* Check for valid VLAN ethertypes */
return xasprintf("%s: not a valid VLAN ethertype", arg);
}
- ofpact_put_PUSH_VLAN(ofpacts);
+ ofpact_put_PUSH_VLAN(ofpacts)->ethertype = htons(ethertype);
return NULL;
}
static void
-format_PUSH_VLAN(const struct ofpact_null *a OVS_UNUSED, struct ds *s)
+format_PUSH_VLAN(const struct ofpact_push_vlan *a OVS_UNUSED, struct ds *s)
{
/* XXX 802.1AD case*/
- ds_put_format(s, "push_vlan:%#"PRIx16, ETH_TYPE_VLAN_8021Q);
+ ds_put_format(s, "push_vlan:%#"PRIx16, ntohs(a->ethertype));
}
/* Action structure for OFPAT10_SET_DL_SRC/DST and OFPAT11_SET_DL_SRC/DST. */
@@ -5357,8 +5361,9 @@ ofpact_check__(enum ofputil_protocol *usable_protocols, struct ofpact *a,
return 0;
case OFPACT_PUSH_VLAN:
- if (flow->vlan_tci & htons(VLAN_CFI)) {
- /* Multiple VLAN headers not supported. */
+ if (flow->vlan_tci & htons(VLAN_CFI) &&
+ flow->vlan_ctci & htons(VLAN_CFI)) {
+ /* More then 2 levels of VLAN headers not supported. */
return OFPERR_OFPBAC_BAD_TAG;
}
/* Temporary mark that we have a vlan tag. */
@@ -5971,6 +5976,7 @@ ofpacts_get_meter(const struct ofpact ofpacts[], size_t ofpacts_len)
/* Formatting ofpacts. */
+
static void
ofpact_format(const struct ofpact *a, struct ds *s)
{
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index 8362aa8..6c55356 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -66,7 +66,7 @@
OFPACT(SET_VLAN_VID, ofpact_vlan_vid, ofpact, "set_vlan_vid") \
OFPACT(SET_VLAN_PCP, ofpact_vlan_pcp, ofpact, "set_vlan_pcp") \
OFPACT(STRIP_VLAN, ofpact_null, ofpact, "strip_vlan") \
- OFPACT(PUSH_VLAN, ofpact_null, ofpact, "push_vlan") \
+ OFPACT(PUSH_VLAN, ofpact_push_vlan, ofpact, "push_vlan") \
OFPACT(SET_ETH_SRC, ofpact_mac, ofpact, "mod_dl_src") \
OFPACT(SET_ETH_DST, ofpact_mac, ofpact, "mod_dl_dst") \
OFPACT(SET_IPV4_SRC, ofpact_ipv4, ofpact, "mod_nw_src") \
@@ -401,6 +401,13 @@ struct ofpact_push_mpls {
ovs_be16 ethertype;
};
+/* OFPACT_PUSH_VLAN
+ *
+ * Used for OFPAT11_PUSH_VLAN. */
+struct ofpact_push_vlan {
+ struct ofpact ofpact;
+ ovs_be16 ethertype;
+};
/* OFPACT_POP_MPLS
*
* Used for NXAST_POP_MPLS, OFPAT11_POP_MPLS.. */
diff --git a/lib/packets.c b/lib/packets.c
index af99e3b..f5b4526 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -217,7 +217,7 @@ set_ethertype(struct ofpbuf *packet, ovs_be16 eth_type)
return;
}
- if (eh->eth_type == htons(ETH_TYPE_VLAN)) {
+ if (eth_type_vlan(eh->eth_type)) {
ovs_be16 *p;
char *l2_5 = ofpbuf_l2_5(packet);
diff --git a/lib/packets.h b/lib/packets.h
index 65d2274..b6596bd 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -252,6 +252,13 @@ static inline bool eth_type_mpls(ovs_be16 eth_type)
eth_type == htons(ETH_TYPE_MPLS_MCAST);
}
+static inline bool eth_type_vlan(ovs_be16 eth_type)
+{
+ return eth_type == htons(ETH_TYPE_VLAN_8021Q) ||
+ eth_type == htons(ETH_TYPE_VLAN_8021AD);
+}
+
+
/* Minimum value for an Ethernet type. Values below this are IEEE 802.2 frame
* lengths. */
#define ETH_TYPE_MIN 0x600
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 4a5b7fd..97ef9fe 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -2627,6 +2627,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
struct flow *flow = &ctx->xin->flow;
struct flow_tnl flow_tnl;
ovs_be16 flow_vlan_tci;
+ ovs_be16 flow_vlan_ctci;
uint32_t flow_pkt_mark;
uint8_t flow_nw_tos;
odp_port_t out_port, odp_port;
@@ -2635,7 +2636,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
/* If 'struct flow' gets additional metadata, we'll need to zero it out
* before traversing a patch port. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 29);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 30);
memset(&flow_tnl, 0, sizeof flow_tnl);
if (!xport) {
@@ -2732,6 +2733,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
}
flow_vlan_tci = flow->vlan_tci;
+ flow_vlan_ctci = flow->vlan_ctci;
flow_pkt_mark = flow->pkt_mark;
flow_nw_tos = flow->nw_tos;
@@ -2851,6 +2853,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
out:
/* Restore flow */
flow->vlan_tci = flow_vlan_tci;
+ flow->vlan_ctci = flow_vlan_ctci;
flow->pkt_mark = flow_pkt_mark;
flow->nw_tos = flow_nw_tos;
}
@@ -3877,6 +3880,14 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
/* XXX 802.1AD(QinQ) */
memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci);
flow->vlan_tci = htons(VLAN_CFI);
+ if (ofpact_get_PUSH_VLAN(a)->ethertype == htons(ETH_TYPE_VLAN_8021AD)) {
+ memset(&wc->masks.vlan_ctci, 0xff, sizeof wc->masks.vlan_ctci);
+ flow->vlan_ctci |= htons(VLAN_CFI);
+ memset(&wc->masks.vlan_tpid, 0xff, sizeof wc->masks.vlan_tpid);
+ flow->vlan_tpid = htons(ETH_TYPE_VLAN_8021AD);
+ } else if (ofpact_get_PUSH_VLAN(a)->ethertype == htons(ETH_TYPE_VLAN_8021Q)) {
+ flow->vlan_tpid = htons(ETH_TYPE_VLAN_8021Q);
+ }
break;
case OFPACT_SET_ETH_SRC:
--
1.8.3.2
More information about the dev
mailing list