[ovs-dev] [PATCH] OF11: push_vlan support
Isaku Yamahata
yamahata at valinux.co.jp
Thu Oct 25 05:42:23 UTC 2012
This implementes push_vlan with 802.1Q.
NOTE: 802.1AD (QinQ) is not supported. It requires another effort.
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
---
lib/ofp-actions.c | 25 +++++++++++++++++++++++++
lib/ofp-actions.h | 9 +++++++++
lib/ofp-parse.c | 13 +++++++++++++
lib/ofp-util.def | 2 +-
lib/packets.h | 7 ++++++-
ofproto/ofproto-dpif.c | 5 +++++
tests/ofp-actions.at | 3 +++
7 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index c6ba131..ed22db9 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -714,6 +714,11 @@ ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out)
ofpact_put_SET_VLAN_PCP(out)->vlan_pcp = a->vlan_pcp.vlan_pcp;
break;
+ case OFPUTIL_OFPAT11_PUSH_VLAN:
+ ofpact_put_PUSH_VLAN(out)->ethertype =
+ ((const struct ofp11_action_push *)a)->ethertype;
+ break;
+
case OFPUTIL_OFPAT11_POP_VLAN:
ofpact_put_STRIP_VLAN(out);
break;
@@ -1062,6 +1067,13 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports)
case OFPACT_BUNDLE:
return bundle_check(ofpact_get_BUNDLE(a), max_ports, flow);
+ case OFPACT_PUSH_VLAN:
+ if (ofpact_get_PUSH_VLAN(a)->ethertype != htons(ETH_TYPE_VLAN_8021Q)) {
+ /* TODO:XXX 802.1AD(QinQ) isn't supported at the moment */
+ return OFPERR_OFPET_BAD_ACTION;
+ }
+ return 0;
+
case OFPACT_SET_VLAN_VID:
case OFPACT_SET_VLAN_PCP:
case OFPACT_STRIP_VLAN:
@@ -1358,6 +1370,7 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
case OFPACT_SET_VLAN_VID:
case OFPACT_SET_VLAN_PCP:
case OFPACT_STRIP_VLAN:
+ case OFPACT_PUSH_VLAN:
case OFPACT_SET_ETH_SRC:
case OFPACT_SET_ETH_DST:
case OFPACT_SET_IPV4_SRC:
@@ -1456,6 +1469,7 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
= htons(ofpact_get_SET_L4_DST_PORT(a)->port);
break;
+ case OFPACT_PUSH_VLAN:
case OFPACT_CLEAR_ACTIONS:
case OFPACT_GOTO_TABLE:
/* TODO:XXX */
@@ -1548,6 +1562,11 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
ofputil_put_OFPAT11_POP_VLAN(out);
break;
+ case OFPACT_PUSH_VLAN:
+ ofputil_put_OFPAT11_PUSH_VLAN(out)->ethertype =
+ ofpact_get_PUSH_VLAN(a)->ethertype;
+ break;
+
case OFPACT_SET_ETH_SRC:
memcpy(ofputil_put_OFPAT11_SET_DL_SRC(out)->dl_addr,
ofpact_get_SET_ETH_SRC(a)->mac, ETH_ADDR_LEN);
@@ -1711,6 +1730,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port)
case OFPACT_SET_VLAN_VID:
case OFPACT_SET_VLAN_PCP:
case OFPACT_STRIP_VLAN:
+ case OFPACT_PUSH_VLAN:
case OFPACT_SET_ETH_SRC:
case OFPACT_SET_ETH_DST:
case OFPACT_SET_IPV4_SRC:
@@ -1894,6 +1914,11 @@ ofpact_format(const struct ofpact *a, struct ds *s)
ds_put_cstr(s, "strip_vlan");
break;
+ case OFPACT_PUSH_VLAN:
+ ds_put_format(s, "push_vlan:%#"PRIx16,
+ ntohs(ofpact_get_PUSH_VLAN(a)->ethertype));
+ break;
+
case OFPACT_SET_ETH_SRC:
ds_put_format(s, "mod_dl_src:"ETH_ADDR_FMT,
ETH_ADDR_ARGS(ofpact_get_SET_ETH_SRC(a)->mac));
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index 410103e..26ce791 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -60,6 +60,7 @@
DEFINE_OFPACT(SET_VLAN_VID, ofpact_vlan_vid, ofpact) \
DEFINE_OFPACT(SET_VLAN_PCP, ofpact_vlan_pcp, ofpact) \
DEFINE_OFPACT(STRIP_VLAN, ofpact_null, ofpact) \
+ DEFINE_OFPACT(PUSH_VLAN, ofpact_push, ofpact) \
DEFINE_OFPACT(SET_ETH_SRC, ofpact_mac, ofpact) \
DEFINE_OFPACT(SET_ETH_DST, ofpact_mac, ofpact) \
DEFINE_OFPACT(SET_IPV4_SRC, ofpact_ipv4, ofpact) \
@@ -309,6 +310,14 @@ struct ofpact_reg_load {
union mf_subvalue subvalue; /* Least-significant bits are used. */
};
+/* OFPACT_PUSH_VLAN/MPLS/PBB
+ *
+ * used for NXAST_PUSH_MPLS, OFPAT13_PUSH_VLAN/MPLS/PBB */
+struct ofpact_push {
+ struct ofpact ofpact;
+ ovs_be16 ethertype;
+};
+
/* OFPACT_SET_TUNNEL.
*
* Used for NXAST_SET_TUNNEL, NXAST_SET_TUNNEL64. */
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 33065aa..fce3c51 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -384,6 +384,7 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
{
struct ofpact_tunnel *tunnel;
uint16_t vid;
+ uint16_t ethertype;
ovs_be32 ip;
uint8_t pcp;
uint8_t tos;
@@ -424,6 +425,18 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
ofpact_put_STRIP_VLAN(ofpacts);
break;
+ case OFPUTIL_OFPAT11_PUSH_VLAN:
+ ethertype = str_to_u16(arg, "ethertype");
+ if (ethertype != ETH_TYPE_VLAN_8021Q &&
+ ethertype != ETH_TYPE_VLAN_8021AD &&
+ ethertype != ETH_TYPE_VLAN_QINQ1 &&
+ ethertype != ETH_TYPE_VLAN_QINQ2 &&
+ ethertype != ETH_TYPE_VLAN_QINQ3) {
+ ovs_fatal(0, "%s: not a valid VLAN ethertype", arg);
+ }
+ ofpact_put_PUSH_VLAN(ofpacts)->ethertype = htons(ethertype);
+ break;
+
case OFPUTIL_OFPAT10_SET_DL_SRC:
case OFPUTIL_OFPAT11_SET_DL_SRC:
str_to_mac(arg, ofpact_put_SET_ETH_SRC(ofpacts)->mac);
diff --git a/lib/ofp-util.def b/lib/ofp-util.def
index 0b867c2..39575ba 100644
--- a/lib/ofp-util.def
+++ b/lib/ofp-util.def
@@ -30,7 +30,7 @@ OFPAT11_ACTION(OFPAT11_SET_NW_TOS, ofp_action_nw_tos, 0, "mod_nw_tos")
//OFPAT11_ACTION(OFPAT11_SET_NW_ECN, ofp11_action_nw_ecn, "0, mod_nw_ecn")
OFPAT11_ACTION(OFPAT11_SET_TP_SRC, ofp_action_tp_port, 0, "mod_tp_src")
OFPAT11_ACTION(OFPAT11_SET_TP_DST, ofp_action_tp_port, 0, "mod_tp_dst")
-//OFPAT11_ACTION(OFPAT11_PUSH_VLAN, ofp11_action_push, 0, "push_vlan")
+OFPAT11_ACTION(OFPAT11_PUSH_VLAN, ofp11_action_push, 0, "push_vlan")
OFPAT11_ACTION(OFPAT11_POP_VLAN, ofp_action_header, 0, "pop_vlan")
//OFPAT11_ACTION(OFPAT11_SET_QUEUE, ofp11_action_set_queue, 0, "set_queue")
//OFPAT11_ACTION(OFPAT11_SET_NW_TTL, ofp11_action_nw_ttl, 0, "set_nw_ttl")
diff --git a/lib/packets.h b/lib/packets.h
index 24b51da..960af20 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -177,12 +177,17 @@ void eth_addr_bitand(const uint8_t src[ETH_ADDR_LEN],
#define ETH_TYPE_IP 0x0800
#define ETH_TYPE_ARP 0x0806
-#define ETH_TYPE_VLAN 0x8100
+#define ETH_TYPE_VLAN_8021Q 0x8100
+#define ETH_TYPE_VLAN ETH_TYPE_VLAN_8021Q
+#define ETH_TYPE_VLAN_8021AD 0x88a8
#define ETH_TYPE_IPV6 0x86dd
#define ETH_TYPE_LACP 0x8809
#define ETH_TYPE_RARP 0x8035
#define ETH_TYPE_MPLS 0x8847
#define ETH_TYPE_MPLS_MCAST 0x8848
+#define ETH_TYPE_VLAN_QINQ1 0x9100
+#define ETH_TYPE_VLAN_QINQ2 0x9200
+#define ETH_TYPE_VLAN_QINQ3 0x9300
/* Minimum value for an Ethernet type. Values below this are IEEE 802.2 frame
* lengths. */
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index c800386..fea4dac 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -5500,6 +5500,11 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
ctx->flow.vlan_tci = htons(0);
break;
+ case OFPACT_PUSH_VLAN:
+ /* TODO:XXX 802.1AD(QinQ) */
+ ctx->flow.vlan_tci = htons(VLAN_CFI);
+ break;
+
case OFPACT_SET_ETH_SRC:
memcpy(ctx->flow.dl_src, ofpact_get_SET_ETH_SRC(a)->mac,
ETH_ADDR_LEN);
diff --git a/tests/ofp-actions.at b/tests/ofp-actions.at
index 4875844..0785130 100644
--- a/tests/ofp-actions.at
+++ b/tests/ofp-actions.at
@@ -169,6 +169,9 @@ AT_DATA([test-data], [dnl
# actions=strip_vlan
0012 0008 00000000
+# actions=push_vlan:0x8100
+0011 0008 8100 0000
+
# actions=resubmit:5
ffff 0010 00002320 0001 0005 00000000
--
1.7.10.4
More information about the dev
mailing list