gre: Improve headroom calculation to reducing copying.
authorJesse Gross <jesse@nicira.com>
Fri, 11 Jun 2010 22:10:35 +0000 (15:10 -0700)
committerJesse Gross <jesse@nicira.com>
Fri, 11 Jun 2010 22:54:44 +0000 (15:54 -0700)
The first change is use skb_header_cloned() instead of (skb_cloned()
 && skb_clone_writable()).  While these are effectively the same
checks, skb_clone_writable() does not exist until 2.6.23 and relies
on information not available in earlier kernels and therefore the
compat version always returns false.  Since GRE only adds data to
the front of the packet and this is on the transmit path (meaning
there is no important data in the SKB head) it is safe to use
skb_header_cloned().  This avoids a copy for locally generated
TCP packets on the affected kernels.

The second change is to always allocate 64 bytes of headroom when
a copy needs to be made.  There is no cost to allocating extra
space once we have decided to make a copy and can avoid another
copy later if we need to add a VLAN tag.

datapath/vport-gre.c

index cd0f3e8dce46c1936cd0dd8a87f19deb7b2fcadc..98e0abc3b7d494793a47a0a5d43328c590fb3fbc 100644 (file)
@@ -557,9 +557,8 @@ send_frag_needed(struct vport *vport, const struct mutable_config *mutable,
 static struct sk_buff *
 check_headroom(struct sk_buff *skb, int headroom)
 {
-       if (skb_headroom(skb) < headroom ||
-           (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
-               struct sk_buff *nskb = skb_realloc_headroom(skb, headroom);
+       if (skb_headroom(skb) < headroom || skb_header_cloned(skb)) {
+               struct sk_buff *nskb = skb_realloc_headroom(skb, max(headroom, 64));
                if (!nskb) {
                        kfree_skb(skb);
                        return ERR_PTR(-ENOMEM);