aboutsummaryrefslogtreecommitdiff
path: root/datapath
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2011-06-06 16:11:47 -0700
committerJesse Gross <jesse@nicira.com>2011-06-16 14:41:15 -0700
commit1d0f14d4c1da6e67234c0c43db66721cd7fbac98 (patch)
treef3ba010705e2368e9ead7872d4824ab0299b78e1 /datapath
parentb328b55b4a34b2bb4ea22d5a58ae10f3779cb761 (diff)
datapath: Use strip_vlan() for modify_vlan_tci().
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>
Diffstat (limited to 'datapath')
-rw-r--r--datapath/actions.c30
1 files changed, 8 insertions, 22 deletions
diff --git a/datapath/actions.c b/datapath/actions.c
index 6c1ca49c..319c783f 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -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)