datapath: Use strip_vlan() for modify_vlan_tci().
authorJesse Gross <jesse@nicira.com>
Mon, 6 Jun 2011 23:11:47 +0000 (16:11 -0700)
committerJesse Gross <jesse@nicira.com>
Thu, 16 Jun 2011 21:41:15 +0000 (14:41 -0700)
The sematics for setting a vlan tag are to modify the existing tag
if one exists.  This can be expressed as removing the existing tag
first and then adding a new one.  This simplifies the code by not
requiring two copies of the logic that manipulates non-accelerated
vlans and should not make a performance difference because the vlan
tag is contained in a single cache line.

Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
datapath/actions.c

index 6c1ca49..319c783 100644 (file)
@@ -62,7 +62,7 @@ static struct sk_buff *strip_vlan(struct sk_buff *skb)
                return skb;
        }
 
-       if (unlikely(vlan_eth_hdr(skb)->h_vlan_proto != htons(ETH_P_8021Q) ||
+       if (unlikely(skb->protocol != htons(ETH_P_8021Q) ||
            skb->len < VLAN_ETH_HLEN))
                return skb;
 
@@ -86,30 +86,16 @@ static struct sk_buff *strip_vlan(struct sk_buff *skb)
 
 static struct sk_buff *modify_vlan_tci(struct sk_buff *skb, __be16 tci)
 {
-       struct vlan_ethhdr *vh;
-       __be16 old_tci;
-
-       if (vlan_tx_tag_present(skb) || skb->protocol != htons(ETH_P_8021Q))
-               return __vlan_hwaccel_put_tag(skb, ntohs(tci));
-
-       skb = make_writable(skb, 0);
-       if (unlikely(!skb))
-               return NULL;
-
-       if (unlikely(skb->len < VLAN_ETH_HLEN))
-               return skb;
-
-       vh = vlan_eth_hdr(skb);
-
-       old_tci = vh->h_vlan_TCI;
-       vh->h_vlan_TCI = tci;
+       if (!vlan_tx_tag_present(skb) && skb->protocol == htons(ETH_P_8021Q)) {
+               if (unlikely(skb->len < VLAN_ETH_HLEN))
+                       return skb;
 
-       if (get_ip_summed(skb) == OVS_CSUM_COMPLETE) {
-               __be16 diff[] = { ~old_tci, vh->h_vlan_TCI };
-               skb->csum = ~csum_partial((char *)diff, sizeof(diff), ~skb->csum);
+               skb = strip_vlan(skb);
+               if (unlikely(!skb))
+                       return NULL;
        }
 
-       return skb;
+       return __vlan_hwaccel_put_tag(skb, ntohs(tci));
 }
 
 static bool is_ip(struct sk_buff *skb)