OF11: push_vlan support
authorIsaku Yamahata <yamahata@valinux.co.jp>
Fri, 26 Oct 2012 04:43:19 +0000 (13:43 +0900)
committerBen Pfaff <blp@nicira.com>
Fri, 26 Oct 2012 16:49:05 +0000 (09:49 -0700)
This implementes push_vlan with 802.1Q.
NOTE: 802.1AD (QinQ) is not supported. It requires another effort.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: Ben Pfaff <blp@nicira.com>
lib/ofp-actions.c
lib/ofp-actions.h
lib/ofp-parse.c
lib/ofp-util.def
lib/packets.h
ofproto/ofproto-dpif.c
tests/ofp-actions.at
utilities/ovs-ofctl.8.in

index c6ba131..170e796 100644 (file)
@@ -714,6 +714,15 @@ 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:
+        if (((const struct ofp11_action_push *)a)->ethertype !=
+            htons(ETH_TYPE_VLAN_8021Q)) {
+            /* TODO:XXX 802.1AD(QinQ) isn't supported at the moment */
+            return OFPERR_OFPET_BAD_ACTION;
+        }
+        ofpact_put_PUSH_VLAN(out);
+        break;
+
     case OFPUTIL_OFPAT11_POP_VLAN:
         ofpact_put_STRIP_VLAN(out);
         break;
@@ -1065,6 +1074,7 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports)
     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:
@@ -1358,6 +1368,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 +1467,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 +1560,12 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
         ofputil_put_OFPAT11_POP_VLAN(out);
         break;
 
+    case OFPACT_PUSH_VLAN:
+        /* TODO:XXX ETH_TYPE_VLAN_8021AD case */
+        ofputil_put_OFPAT11_PUSH_VLAN(out)->ethertype =
+            htons(ETH_TYPE_VLAN_8021Q);
+        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 +1729,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 +1913,11 @@ ofpact_format(const struct ofpact *a, struct ds *s)
         ds_put_cstr(s, "strip_vlan");
         break;
 
+    case OFPACT_PUSH_VLAN:
+        /* TODO:XXX 802.1AD case*/
+        ds_put_format(s, "push_vlan:%#"PRIx16, ETH_TYPE_VLAN_8021Q);
+        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));
index 410103e..b6cf4ba 100644 (file)
@@ -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_null,          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)    \
index 33065aa..dedfb7e 100644 (file)
@@ -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,15 @@ 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) {
+            /* TODO:XXXX ETH_TYPE_VLAN_8021AD case isn't supported */
+            ovs_fatal(0, "%s: not a valid VLAN ethertype", arg);
+        }
+        ofpact_put_PUSH_VLAN(ofpacts);
+        break;
+
     case OFPUTIL_OFPAT10_SET_DL_SRC:
     case OFPUTIL_OFPAT11_SET_DL_SRC:
         str_to_mac(arg, ofpact_put_SET_ETH_SRC(ofpacts)->mac);
index 0b867c2..39575ba 100644 (file)
@@ -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")
index 24b51da..e550be0 100644 (file)
@@ -177,7 +177,9 @@ 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
index c800386..fea4dac 100644 (file)
@@ -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);
index 4875844..e232435 100644 (file)
@@ -169,6 +169,12 @@ AT_DATA([test-data], [dnl
 # actions=strip_vlan
 0012 0008 00000000
 
+dnl 802.1ad isn't supported at the moment
+dnl # actions=push_vlan:0x88a8
+dnl 0011 0008 88a8 0000
+# actions=push_vlan:0x8100
+0011 0008 8100 0000
+
 # actions=resubmit:5
 ffff 0010 00002320 0001 0005 00000000
 
index 8c175ba..9ea0973 100644 (file)
@@ -897,6 +897,12 @@ as necessary to match the value specified.  Valid values are between 0
 .IP \fBstrip_vlan\fR
 Strips the VLAN tag from a packet if it is present.
 .
+.IP \fBpush_vlan\fR:\fIethertype\fR
+Push a new VLAN tag onto the packet.  Ethertype is used as the the Ethertype
+for the tag. Only ethertype 0x8100 should be used. (0x88a8 which the spec
+allows isn't supported at the moment.)
+A priority of zero and the tag of zero are used for the new tag.
+.
 .IP \fBmod_dl_src\fB:\fImac\fR
 Sets the source Ethernet address to \fImac\fR.
 .