summaryrefslogtreecommitdiff
path: root/datapath
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2011-06-07 17:09:35 -0700
committerJesse Gross <jesse@nicira.com>2011-06-16 14:41:15 -0700
commitbf16ba4a9b1b4a38c867349e70e39d551b406b32 (patch)
treefe9e3f995004621b6b4026e89153beb601354916 /datapath
parent10db8b20d2ed55417f625a3212db3b5cef0331d2 (diff)
downloadopenvswitch-bf16ba4a9b1b4a38c867349e70e39d551b406b32.tar.gz
tunneling: Avoid extra copying if expanding headroom.
Currently if we need additional headroom before encapsulating a packet a clone is made before expanding headroom or if we are just trying to make the headroom writable then we copy both the struct sk_buff and the paged data. Both of these are unnecessary and we end up freeing the original copy. We can remove these copies and simplify the code by just expanding the linear data area. Signed-off-by: Jesse Gross <jesse@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'datapath')
-rw-r--r--datapath/tunnel.c33
1 files changed, 8 insertions, 25 deletions
diff --git a/datapath/tunnel.c b/datapath/tunnel.c
index 326322336..2bf61597d 100644
--- a/datapath/tunnel.c
+++ b/datapath/tunnel.c
@@ -1027,27 +1027,6 @@ static struct rtable *find_route(struct vport *vport,
}
}
-static struct sk_buff *check_headroom(struct sk_buff *skb, int headroom)
-{
- if (skb_headroom(skb) < headroom || skb_header_cloned(skb)) {
- struct sk_buff *nskb = skb_realloc_headroom(skb, headroom + 16);
- if (unlikely(!nskb)) {
- kfree_skb(skb);
- return ERR_PTR(-ENOMEM);
- }
-
- set_skb_csum_bits(skb, nskb);
-
- if (skb->sk)
- skb_set_owner_w(nskb, skb->sk);
-
- kfree_skb(skb);
- return nskb;
- }
-
- return skb;
-}
-
static inline bool need_linearize(const struct sk_buff *skb)
{
int i;
@@ -1084,10 +1063,14 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb,
+ mutable->tunnel_hlen
+ (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);
- skb = check_headroom(skb, min_headroom);
- if (IS_ERR(skb)) {
- err = PTR_ERR(skb);
- goto error;
+ if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
+ int head_delta = SKB_DATA_ALIGN(min_headroom -
+ skb_headroom(skb) +
+ 16);
+ err = pskb_expand_head(skb, max_t(int, head_delta, 0),
+ 0, GFP_ATOMIC);
+ if (unlikely(err))
+ goto error_free;
}
if (skb_is_gso(skb)) {