From: pravin <pshe...@nicira.com>

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

---
 datapath/actions.c                      |   63 +++++++++++++++++++++---------
 datapath/datapath.c                     |    8 ++--
 include/openvswitch/datapath-protocol.h |    4 +-
 lib/dpif-netdev.c                       |    8 ++--
 lib/odp-util.c                          |   12 +++---
 ofproto/ofproto-dpif-sflow.c            |    2 +-
 ofproto/ofproto-dpif.c                  |   17 +++++---
 7 files changed, 72 insertions(+), 42 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/dpif-netdev.c b/lib/dpif-netdev.c
index 3b93a4c..5c52ea6 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:
@@ -1304,11 +1304,11 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
                                      key, nl_attr_get_u64(a));
             break;
 
-        case ODP_ACTION_ATTR_SET_DL_TCI:
+        case ODP_ACTION_ATTR_PUSH_VLAN_TCI:
             eth_set_vlan_tci(packet, nl_attr_get_be16(a));
             break;
 
-        case ODP_ACTION_ATTR_STRIP_VLAN:
+        case ODP_ACTION_ATTR_POP_VLAN_TCI:
             dp_netdev_strip_vlan(packet);
             break;
 
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/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.1

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

Reply via email to