aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2009-04-16 05:02:07 -0400
committerDavid S. Miller <davem@davemloft.net>2009-04-16 05:02:07 -0400
commit76620aafd66f0004829764940c5466144969cffc (patch)
tree38041e6938121b5611546c582cd23f289db047b0 /net/core
parent861ab44059350e5cab350238606cf8814abab93b (diff)
gro: New frags interface to avoid copying shinfo
It turns out that copying a 16-byte area at ~800k times a second can be really expensive :) This patch redesigns the frags GRO interface to avoid copying that area twice. The two disciples of the frags interface have been converted. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c81
1 files changed, 36 insertions, 45 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 91d792d17e09..619fa141b8f5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2519,16 +2519,10 @@ void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb)
2519} 2519}
2520EXPORT_SYMBOL(napi_reuse_skb); 2520EXPORT_SYMBOL(napi_reuse_skb);
2521 2521
2522struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, 2522struct sk_buff *napi_get_frags(struct napi_struct *napi)
2523 struct napi_gro_fraginfo *info)
2524{ 2523{
2525 struct net_device *dev = napi->dev; 2524 struct net_device *dev = napi->dev;
2526 struct sk_buff *skb = napi->skb; 2525 struct sk_buff *skb = napi->skb;
2527 struct ethhdr *eth;
2528 skb_frag_t *frag;
2529 int i;
2530
2531 napi->skb = NULL;
2532 2526
2533 if (!skb) { 2527 if (!skb) {
2534 skb = netdev_alloc_skb(dev, GRO_MAX_HEAD + NET_IP_ALIGN); 2528 skb = netdev_alloc_skb(dev, GRO_MAX_HEAD + NET_IP_ALIGN);
@@ -2536,47 +2530,14 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi,
2536 goto out; 2530 goto out;
2537 2531
2538 skb_reserve(skb, NET_IP_ALIGN); 2532 skb_reserve(skb, NET_IP_ALIGN);
2539 }
2540
2541 BUG_ON(info->nr_frags > MAX_SKB_FRAGS);
2542 frag = &info->frags[info->nr_frags - 1];
2543 2533
2544 for (i = skb_shinfo(skb)->nr_frags; i < info->nr_frags; i++) { 2534 napi->skb = skb;
2545 skb_fill_page_desc(skb, i, frag->page, frag->page_offset,
2546 frag->size);
2547 frag++;
2548 } 2535 }
2549 skb_shinfo(skb)->nr_frags = info->nr_frags;
2550
2551 skb->data_len = info->len;
2552 skb->len += info->len;
2553 skb->truesize += info->len;
2554
2555 skb_reset_mac_header(skb);
2556 skb_gro_reset_offset(skb);
2557
2558 eth = skb_gro_header(skb, sizeof(*eth));
2559 if (!eth) {
2560 napi_reuse_skb(napi, skb);
2561 skb = NULL;
2562 goto out;
2563 }
2564
2565 skb_gro_pull(skb, sizeof(*eth));
2566
2567 /*
2568 * This works because the only protocols we care about don't require
2569 * special handling. We'll fix it up properly at the end.
2570 */
2571 skb->protocol = eth->h_proto;
2572
2573 skb->ip_summed = info->ip_summed;
2574 skb->csum = info->csum;
2575 2536
2576out: 2537out:
2577 return skb; 2538 return skb;
2578} 2539}
2579EXPORT_SYMBOL(napi_fraginfo_skb); 2540EXPORT_SYMBOL(napi_get_frags);
2580 2541
2581int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret) 2542int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret)
2582{ 2543{
@@ -2606,9 +2567,39 @@ int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret)
2606} 2567}
2607EXPORT_SYMBOL(napi_frags_finish); 2568EXPORT_SYMBOL(napi_frags_finish);
2608 2569
2609int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info) 2570struct sk_buff *napi_frags_skb(struct napi_struct *napi)
2571{
2572 struct sk_buff *skb = napi->skb;
2573 struct ethhdr *eth;
2574
2575 napi->skb = NULL;
2576
2577 skb_reset_mac_header(skb);
2578 skb_gro_reset_offset(skb);
2579
2580 eth = skb_gro_header(skb, sizeof(*eth));
2581 if (!eth) {
2582 napi_reuse_skb(napi, skb);
2583 skb = NULL;
2584 goto out;
2585 }
2586
2587 skb_gro_pull(skb, sizeof(*eth));
2588
2589 /*
2590 * This works because the only protocols we care about don't require
2591 * special handling. We'll fix it up properly at the end.
2592 */
2593 skb->protocol = eth->h_proto;
2594
2595out:
2596 return skb;
2597}
2598EXPORT_SYMBOL(napi_frags_skb);
2599
2600int napi_gro_frags(struct napi_struct *napi)
2610{ 2601{
2611 struct sk_buff *skb = napi_fraginfo_skb(napi, info); 2602 struct sk_buff *skb = napi_frags_skb(napi);
2612 2603
2613 if (!skb) 2604 if (!skb)
2614 return NET_RX_DROP; 2605 return NET_RX_DROP;
@@ -2712,7 +2703,7 @@ void netif_napi_del(struct napi_struct *napi)
2712 struct sk_buff *skb, *next; 2703 struct sk_buff *skb, *next;
2713 2704
2714 list_del_init(&napi->dev_list); 2705 list_del_init(&napi->dev_list);
2715 kfree_skb(napi->skb); 2706 napi_free_frags(napi);
2716 2707
2717 for (skb = napi->gro_list; skb; skb = next) { 2708 for (skb = napi->gro_list; skb; skb = next) {
2718 next = skb->next; 2709 next = skb->next;