diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2009-05-26 14:50:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-27 06:25:55 -0400 |
commit | 78a478d0efd9e86e5345b436e130497b4e5846e8 (patch) | |
tree | 273e7565811add8216267f5893335bdb7928a6b7 /net/core | |
parent | 42da6994ca6d20ad1d4e30255dee98047db454e7 (diff) |
gro: Inline skb_gro_header and cache frag0 virtual address
The function skb_gro_header is called four times per packet which
quickly adds up at 10Gb/s. This patch inlines it to allow better
optimisations.
Some architectures perform multiplication for page_address, which
is done by each skb_gro_header invocation. This patch caches that
value in skb->cb to avoid the unnecessary multiplications.
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.c | 27 |
1 files changed, 12 insertions, 15 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 5eb3e48ab31d..bdb1a738193d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2390,21 +2390,6 @@ void napi_gro_flush(struct napi_struct *napi) | |||
2390 | } | 2390 | } |
2391 | EXPORT_SYMBOL(napi_gro_flush); | 2391 | EXPORT_SYMBOL(napi_gro_flush); |
2392 | 2392 | ||
2393 | void *skb_gro_header(struct sk_buff *skb, unsigned int hlen) | ||
2394 | { | ||
2395 | unsigned int offset = skb_gro_offset(skb); | ||
2396 | |||
2397 | hlen += offset; | ||
2398 | if (unlikely(skb_headlen(skb) || | ||
2399 | skb_shinfo(skb)->frags[0].size < hlen || | ||
2400 | PageHighMem(skb_shinfo(skb)->frags[0].page))) | ||
2401 | return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL; | ||
2402 | |||
2403 | return page_address(skb_shinfo(skb)->frags[0].page) + | ||
2404 | skb_shinfo(skb)->frags[0].page_offset + offset; | ||
2405 | } | ||
2406 | EXPORT_SYMBOL(skb_gro_header); | ||
2407 | |||
2408 | int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | 2393 | int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) |
2409 | { | 2394 | { |
2410 | struct sk_buff **pp = NULL; | 2395 | struct sk_buff **pp = NULL; |
@@ -2520,6 +2505,18 @@ int napi_skb_finish(int ret, struct sk_buff *skb) | |||
2520 | } | 2505 | } |
2521 | EXPORT_SYMBOL(napi_skb_finish); | 2506 | EXPORT_SYMBOL(napi_skb_finish); |
2522 | 2507 | ||
2508 | void skb_gro_reset_offset(struct sk_buff *skb) | ||
2509 | { | ||
2510 | NAPI_GRO_CB(skb)->data_offset = 0; | ||
2511 | NAPI_GRO_CB(skb)->frag0 = NULL; | ||
2512 | |||
2513 | if (!skb_headlen(skb) && !PageHighMem(skb_shinfo(skb)->frags[0].page)) | ||
2514 | NAPI_GRO_CB(skb)->frag0 = | ||
2515 | page_address(skb_shinfo(skb)->frags[0].page) + | ||
2516 | skb_shinfo(skb)->frags[0].page_offset; | ||
2517 | } | ||
2518 | EXPORT_SYMBOL(skb_gro_reset_offset); | ||
2519 | |||
2523 | int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | 2520 | int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) |
2524 | { | 2521 | { |
2525 | skb_gro_reset_offset(skb); | 2522 | skb_gro_reset_offset(skb); |