following patch changes OVS VLAN actions from MODIFY and
 STRIP to more generic PUSH and POP.  As this patch
 replaces MODIFY with PUSH semantic, action  mapping done in userpace is
 fixed accordingly.


---
 datapath/actions.c                      |   63 +++++++++++++++++++++---------
 datapath/datapath.c                     |    8 ++--
 include/openvswitch/datapath-protocol.h |    4 +-
 lib/bond.c                              |    2 +-
 lib/dpif-netdev.c                       |   14 +++---
 lib/odp-util.c                          |   12 +++---
 lib/packets.c                           |   27 +++++--------
 lib/packets.h                           |    2 +-
 ofproto/ofproto-dpif-sflow.c            |    2 +-
 ofproto/ofproto-dpif.c                  |   17 +++++---
 10 files changed, 88 insertions(+), 63 deletions(-)

diff --git a/datapath/actions.c b/datapath/actions.c
index ed61039..a91eca5 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -39,19 +39,12 @@ static int make_writable(struct sk_buff *skb, int write_len)
        return pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
 }
 
-static int strip_vlan(struct sk_buff *skb)
+static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci)
 {
        struct ethhdr *eh;
+       struct vlan_ethhdr *veth;
        int err;
 
-       if (vlan_tx_tag_present(skb)) {
-               vlan_set_tci(skb, 0);
-               return 0;
-       }
-
-       if (unlikely(skb->protocol != htons(ETH_P_8021Q) ||
-           skb->len < VLAN_ETH_HLEN))
-               return 0;
 
        err = make_writable(skb, VLAN_ETH_HLEN);
        if (unlikely(err))
@@ -61,6 +54,9 @@ static int strip_vlan(struct sk_buff *skb)
                skb->csum = csum_sub(skb->csum, csum_partial(skb->data
                                        + ETH_HLEN, VLAN_HLEN, 0));
 
+       veth = (struct vlan_ethhdr *) skb->data;
+       *current_tci = veth->h_vlan_TCI;
+
        memmove(skb->data + VLAN_HLEN, skb->data, 2 * ETH_ALEN);
 
        eh = (struct ethhdr *)skb_pull(skb, VLAN_HLEN);
@@ -71,21 +67,48 @@ static int strip_vlan(struct sk_buff *skb)
        return 0;
 }
 
-static int modify_vlan_tci(struct sk_buff *skb, __be16 tci)
+static int pop_vlan_tci(struct sk_buff *skb)
 {
-       if (!vlan_tx_tag_present(skb) && skb->protocol == htons(ETH_P_8021Q)) {
-               int err;
+       __be16 tci;
+       int err;
 
-               if (unlikely(skb->len < VLAN_ETH_HLEN))
+       if (vlan_tx_tag_present(skb)) {
+               vlan_set_tci(skb, 0);
+       } else {
+               if (unlikely(skb->protocol != htons(ETH_P_8021Q) ||
+                   skb->len < VLAN_ETH_HLEN))
                        return 0;
 
-               err = strip_vlan(skb);
-               if (unlikely(err))
+               err = __pop_vlan_tci(skb, &tci);
+               if (err)
                        return err;
        }
 
+       /* move next vlan tag to hw accel tag */
+
+       if (likely(skb->protocol != htons(ETH_P_8021Q) ||
+           skb->len < VLAN_ETH_HLEN))
+               return 0;
+
+       err = __pop_vlan_tci(skb, &tci);
+       if (err)
+               return err;
+
        __vlan_hwaccel_put_tag(skb, ntohs(tci));
+       return 0;
+}
+
+static int push_vlan_tci(struct sk_buff *skb, __be16 new_tci)
+{
+       if (vlan_tx_tag_present(skb)) {
+               u16 current_tag;
+
+               current_tag = vlan_tx_tag_get(skb);
 
+               if (!__vlan_put_tag(skb, current_tag))
+                       return -ENOMEM;
+       }
+       __vlan_hwaccel_put_tag(skb, ntohs(new_tci));
        return 0;
 }
 
@@ -270,12 +293,14 @@ static int do_execute_actions(struct datapath *dp, struct 
sk_buff *skb,
                        OVS_CB(skb)->tun_id = nla_get_be64(a);
                        break;
 
-               case ODP_ACTION_ATTR_SET_DL_TCI:
-                       err = modify_vlan_tci(skb, nla_get_be16(a));
+               case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
+                       err = push_vlan_tci(skb, nla_get_be16(a));
+                       if (unlikely(err)) /* skb already freed */
+                               return err;
                        break;
 
-               case ODP_ACTION_ATTR_STRIP_VLAN:
-                       err = strip_vlan(skb);
+               case ODP_ACTION_ATTR_POP_VLAN_TCI:
+                       err = pop_vlan_tci(skb);
                        break;
 
                case ODP_ACTION_ATTR_SET_DL_SRC:
diff --git a/datapath/datapath.c b/datapath/datapath.c
index d149344..9c9b70d 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -553,8 +553,8 @@ static int validate_actions(const struct nlattr *attr)
                static const u32 action_lens[ODP_ACTION_ATTR_MAX + 1] = {
                        [ODP_ACTION_ATTR_OUTPUT] = 4,
                        [ODP_ACTION_ATTR_CONTROLLER] = 8,
-                       [ODP_ACTION_ATTR_SET_DL_TCI] = 2,
-                       [ODP_ACTION_ATTR_STRIP_VLAN] = 0,
+                       [ODP_ACTION_ATTR_PUSH_VLAN_TCI] = 2,
+                       [ODP_ACTION_ATTR_POP_VLAN_TCI] = 0,
                        [ODP_ACTION_ATTR_SET_DL_SRC] = ETH_ALEN,
                        [ODP_ACTION_ATTR_SET_DL_DST] = ETH_ALEN,
                        [ODP_ACTION_ATTR_SET_NW_SRC] = 4,
@@ -576,7 +576,7 @@ static int validate_actions(const struct nlattr *attr)
                        return -EINVAL;
 
                case ODP_ACTION_ATTR_CONTROLLER:
-               case ODP_ACTION_ATTR_STRIP_VLAN:
+               case ODP_ACTION_ATTR_POP_VLAN_TCI:
                case ODP_ACTION_ATTR_SET_DL_SRC:
                case ODP_ACTION_ATTR_SET_DL_DST:
                case ODP_ACTION_ATTR_SET_NW_SRC:
@@ -594,7 +594,7 @@ static int validate_actions(const struct nlattr *attr)
                                return -EINVAL;
                        break;
 
-               case ODP_ACTION_ATTR_SET_DL_TCI:
+               case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
                        if (nla_get_be16(a) & htons(VLAN_CFI_MASK))
                                return -EINVAL;
                        break;
diff --git a/include/openvswitch/datapath-protocol.h 
b/include/openvswitch/datapath-protocol.h
index e7708ef..d972a25 100644
--- a/include/openvswitch/datapath-protocol.h
+++ b/include/openvswitch/datapath-protocol.h
@@ -410,8 +410,8 @@ enum odp_action_type {
        ODP_ACTION_ATTR_UNSPEC,
        ODP_ACTION_ATTR_OUTPUT,       /* Output to switch port. */
        ODP_ACTION_ATTR_CONTROLLER,   /* Send copy to controller. */
-       ODP_ACTION_ATTR_SET_DL_TCI,   /* Set the 802.1q TCI value. */
-       ODP_ACTION_ATTR_STRIP_VLAN,   /* Strip the 802.1q header. */
+       ODP_ACTION_ATTR_PUSH_VLAN_TCI,   /* push 802.1q header with new TCI 
value. */
+       ODP_ACTION_ATTR_POP_VLAN_TCI,     /* pop the 802.1q header. */
        ODP_ACTION_ATTR_SET_DL_SRC,   /* Ethernet source address. */
        ODP_ACTION_ATTR_SET_DL_DST,   /* Ethernet destination address. */
        ODP_ACTION_ATTR_SET_NW_SRC,   /* IPv4 source address. */
diff --git a/lib/bond.c b/lib/bond.c
index 9a13874..72ee607 100644
--- a/lib/bond.c
+++ b/lib/bond.c
@@ -532,7 +532,7 @@ bond_send_learning_packet(struct bond *bond,
     compose_benign_packet(&packet, "Open vSwitch Bond Failover", 0xf177,
                           eth_src);
     if (vlan) {
-        eth_set_vlan_tci(&packet, htons(vlan));
+        dp_netdev_push_vlan(&packet, htons(vlan));
     }
     error = netdev_send(slave->netdev, &packet);
     ofpbuf_uninit(&packet);
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 3b93a4c..f30941c 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -710,7 +710,7 @@ dpif_netdev_validate_actions(const struct nlattr *actions,
         case ODP_ACTION_ATTR_CONTROLLER:
             break;
 
-        case ODP_ACTION_ATTR_SET_DL_TCI:
+        case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
             *mutates = true;
             if (nl_attr_get_be16(a) & htons(VLAN_CFI)) {
                 return EINVAL;
@@ -724,7 +724,7 @@ dpif_netdev_validate_actions(const struct nlattr *actions,
             }
             break;
 
-        case ODP_ACTION_ATTR_STRIP_VLAN:
+        case ODP_ACTION_ATTR_POP_VLAN_TCI:
         case ODP_ACTION_ATTR_SET_DL_SRC:
         case ODP_ACTION_ATTR_SET_DL_DST:
         case ODP_ACTION_ATTR_SET_NW_SRC:
@@ -1132,7 +1132,7 @@ dpif_netdev_wait(struct dpif *dpif)
 }
 
 static void
-dp_netdev_strip_vlan(struct ofpbuf *packet)
+dp_netdev_pop_vlan(struct ofpbuf *packet)
 {
     struct vlan_eth_header *veh = packet->l2;
     if (packet->size >= sizeof *veh
@@ -1304,12 +1304,12 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
                                      key, nl_attr_get_u64(a));
             break;
 
-        case ODP_ACTION_ATTR_SET_DL_TCI:
-            eth_set_vlan_tci(packet, nl_attr_get_be16(a));
+        case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
+            dp_netdev_push_vlan(packet, nl_attr_get_be16(a));
             break;
 
-        case ODP_ACTION_ATTR_STRIP_VLAN:
-            dp_netdev_strip_vlan(packet);
+        case ODP_ACTION_ATTR_POP_VLAN_TCI:
+            dp_netdev_pop_vlan(packet);
             break;
 
         case ODP_ACTION_ATTR_SET_DL_SRC:
diff --git a/lib/odp-util.c b/lib/odp-util.c
index d7a3118..32fb722 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -42,8 +42,8 @@ odp_action_len(uint16_t type)
     switch ((enum odp_action_type) type) {
     case ODP_ACTION_ATTR_OUTPUT: return 4;
     case ODP_ACTION_ATTR_CONTROLLER: return 8;
-    case ODP_ACTION_ATTR_SET_DL_TCI: return 2;
-    case ODP_ACTION_ATTR_STRIP_VLAN: return 0;
+    case ODP_ACTION_ATTR_PUSH_VLAN_TCI: return 2;
+    case ODP_ACTION_ATTR_POP_VLAN_TCI: return 0;
     case ODP_ACTION_ATTR_SET_DL_SRC: return ETH_ADDR_LEN;
     case ODP_ACTION_ATTR_SET_DL_DST: return ETH_ADDR_LEN;
     case ODP_ACTION_ATTR_SET_NW_SRC: return 4;
@@ -106,13 +106,13 @@ format_odp_action(struct ds *ds, const struct nlattr *a)
         ds_put_format(ds, "set_tunnel(%#"PRIx64")",
                       ntohll(nl_attr_get_be64(a)));
         break;
-    case ODP_ACTION_ATTR_SET_DL_TCI:
-        ds_put_format(ds, "set_tci(vid=%"PRIu16",pcp=%d)",
+    case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
+        ds_put_format(ds, "push_tci(vid=%"PRIu16",pcp=%d)",
                       vlan_tci_to_vid(nl_attr_get_be16(a)),
                       vlan_tci_to_pcp(nl_attr_get_be16(a)));
         break;
-    case ODP_ACTION_ATTR_STRIP_VLAN:
-        ds_put_format(ds, "strip_vlan");
+    case ODP_ACTION_ATTR_POP_VLAN_TCI:
+        ds_put_format(ds, "pop_vlan");
         break;
     case ODP_ACTION_ATTR_SET_DL_SRC:
         eth = nl_attr_get_unspec(a, ETH_ADDR_LEN);
diff --git a/lib/packets.c b/lib/packets.c
index e05e3eb..a4823dd 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -81,27 +81,22 @@ compose_benign_packet(struct ofpbuf *b, const char *tag, 
uint16_t snap_type,
  *
  * Also sets 'packet->l2' to point to the new Ethernet header. */
 void
-eth_set_vlan_tci(struct ofpbuf *packet, ovs_be16 tci)
+dp_netdev_push_vlan(struct ofpbuf *packet, ovs_be16 tci)
 {
     struct eth_header *eh = packet->data;
     struct vlan_eth_header *veh;
 
-    if (packet->size >= sizeof(struct vlan_eth_header)
-        && eh->eth_type == htons(ETH_TYPE_VLAN)) {
-        veh = packet->data;
-        veh->veth_tci = tci;
-    } else {
-        /* Insert new 802.1Q header. */
-        struct vlan_eth_header tmp;
-        memcpy(tmp.veth_dst, eh->eth_dst, ETH_ADDR_LEN);
-        memcpy(tmp.veth_src, eh->eth_src, ETH_ADDR_LEN);
-        tmp.veth_type = htons(ETH_TYPE_VLAN);
-        tmp.veth_tci = tci;
-        tmp.veth_next_type = eh->eth_type;
-
-        veh = ofpbuf_push_uninit(packet, VLAN_HEADER_LEN);
-        memcpy(veh, &tmp, sizeof tmp);
-    }
+    /* Insert new 802.1Q header. */
+    struct vlan_eth_header tmp;
+    memcpy(tmp.veth_dst, eh->eth_dst, ETH_ADDR_LEN);
+    memcpy(tmp.veth_src, eh->eth_src, ETH_ADDR_LEN);
+    tmp.veth_type = htons(ETH_TYPE_VLAN);
+    tmp.veth_tci = tci;
+    tmp.veth_next_type = eh->eth_type;
+
+    veh = ofpbuf_push_uninit(packet, VLAN_HEADER_LEN);
+    memcpy(veh, &tmp, sizeof tmp);
+
     packet->l2 = packet->data;
 }
 
diff --git a/lib/packets.h b/lib/packets.h
index 8e13a25..b9cfa1d 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -131,7 +131,7 @@ void compose_benign_packet(struct ofpbuf *, const char *tag,
                            uint16_t snap_type,
                            const uint8_t eth_src[ETH_ADDR_LEN]);
 
-void eth_set_vlan_tci(struct ofpbuf *, ovs_be16 tci);
+void dp_netdev_push_vlan(struct ofpbuf *, ovs_be16 tci);
 
 /* Example:
  *
diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index d2da42b..e9dc756 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -538,7 +538,7 @@ dpif_sflow_received(struct dpif_sflow *ds, const struct 
dpif_upcall *upcall,
             n_outputs++;
             break;
 
-        case ODP_ACTION_ATTR_SET_DL_TCI:
+        case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
             tci = nl_attr_get_be16(a);
             switchElem.flowType.sw.dst_vlan = vlan_tci_to_vid(tci);
             switchElem.flowType.sw.dst_priority = vlan_tci_to_pcp(tci);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 7264355..1bcd81f 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -2241,11 +2241,11 @@ facet_account(struct ofproto_dpif *ofproto,
             }
             break;
 
-        case ODP_ACTION_ATTR_STRIP_VLAN:
+        case ODP_ACTION_ATTR_POP_VLAN_TCI:
             vlan_tci = htons(0);
             break;
 
-        case ODP_ACTION_ATTR_SET_DL_TCI:
+        case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
             vlan_tci = nl_attr_get_be16(a);
             break;
         }
@@ -2790,9 +2790,11 @@ commit_odp_actions(struct action_xlate_ctx *ctx)
 
     if (base->vlan_tci != flow->vlan_tci) {
         if (!(flow->vlan_tci & htons(VLAN_CFI))) {
-            nl_msg_put_flag(odp_actions, ODP_ACTION_ATTR_STRIP_VLAN);
+            nl_msg_put_flag(odp_actions, ODP_ACTION_ATTR_POP_VLAN_TCI);
         } else {
-            nl_msg_put_be16(odp_actions, ODP_ACTION_ATTR_SET_DL_TCI,
+           if (base->vlan_tci & htons(VLAN_CFI))
+                  nl_msg_put_flag(odp_actions, ODP_ACTION_ATTR_POP_VLAN_TCI);
+            nl_msg_put_be16(odp_actions, ODP_ACTION_ATTR_PUSH_VLAN_TCI,
                             flow->vlan_tci & ~htons(VLAN_CFI));
         }
         base->vlan_tci = flow->vlan_tci;
@@ -3461,13 +3463,16 @@ compose_actions(struct action_xlate_ctx *ctx, uint16_t 
vlan,
         }
         if (dst->vlan != cur_vlan) {
             if (dst->vlan == OFP_VLAN_NONE) {
-                nl_msg_put_flag(ctx->odp_actions, ODP_ACTION_ATTR_STRIP_VLAN);
+                nl_msg_put_flag(ctx->odp_actions, 
ODP_ACTION_ATTR_POP_VLAN_TCI);
             } else {
                 ovs_be16 tci;
+
+               if (cur_vlan & htons(VLAN_CFI))
+                    nl_msg_put_flag(ctx->odp_actions, 
ODP_ACTION_ATTR_POP_VLAN_TCI);
                 tci = htons(dst->vlan & VLAN_VID_MASK);
                 tci |= ctx->flow.vlan_tci & htons(VLAN_PCP_MASK);
                 nl_msg_put_be16(ctx->odp_actions,
-                                ODP_ACTION_ATTR_SET_DL_TCI, tci);
+                                ODP_ACTION_ATTR_PUSH_VLAN_TCI, tci);
             }
             cur_vlan = dst->vlan;
         }
-- 
1.7.6.134.gcf13f

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to