aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/skbuff.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2009-01-04 19:13:40 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-04 19:13:40 -0500
commit5d38a079ce3971f932bbdc0dc5b887806fabd5dc (patch)
tree79d948098add1f6c52ecd42c151ce6b6fa1dbc5a /net/core/skbuff.c
parentb530256d2e0f1a75fab31f9821129fff1bb49faa (diff)
gro: Add page frag support
This patch allows GRO to merge page frags (skb_shinfo(skb)->frags) in one skb, rather than using the less efficient frag_list. It also adds a new interface, napi_gro_frags to allow drivers to inject page frags directly into the stack without allocating an skb. This is intended to be the GRO equivalent for LRO's lro_receive_frags interface. The existing GSO interface can already handle page frags with or without an appended frag_list so nothing needs to be changed there. The merging itself is rather simple. We store any new frag entries after the last existing entry, without checking whether the first new entry can be merged with the last existing entry. Making this check would actually be easy but since no existing driver can produce contiguous frags anyway it would just be mental masturbation. If the total number of entries would exceed the capacity of a single skb, we simply resort to using frag_list as we do now. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r--net/core/skbuff.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3aafb10325b8..5110b359c758 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2594,6 +2594,17 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
2594 2594
2595 if (skb_shinfo(p)->frag_list) 2595 if (skb_shinfo(p)->frag_list)
2596 goto merge; 2596 goto merge;
2597 else if (!skb_headlen(p) && !skb_headlen(skb) &&
2598 skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags <
2599 MAX_SKB_FRAGS) {
2600 memcpy(skb_shinfo(p)->frags + skb_shinfo(p)->nr_frags,
2601 skb_shinfo(skb)->frags,
2602 skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t));
2603
2604 skb_shinfo(p)->nr_frags += skb_shinfo(skb)->nr_frags;
2605 NAPI_GRO_CB(skb)->free = 1;
2606 goto done;
2607 }
2597 2608
2598 headroom = skb_headroom(p); 2609 headroom = skb_headroom(p);
2599 nskb = netdev_alloc_skb(p->dev, headroom); 2610 nskb = netdev_alloc_skb(p->dev, headroom);
@@ -2628,11 +2639,12 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
2628 p = nskb; 2639 p = nskb;
2629 2640
2630merge: 2641merge:
2631 NAPI_GRO_CB(p)->count++;
2632 p->prev->next = skb; 2642 p->prev->next = skb;
2633 p->prev = skb; 2643 p->prev = skb;
2634 skb_header_release(skb); 2644 skb_header_release(skb);
2635 2645
2646done:
2647 NAPI_GRO_CB(p)->count++;
2636 p->data_len += skb->len; 2648 p->data_len += skb->len;
2637 p->truesize += skb->len; 2649 p->truesize += skb->len;
2638 p->len += skb->len; 2650 p->len += skb->len;