diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2009-05-26 18:50:27 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-27 03:26:01 -0700 |
commit | 7489594cb249aeb178287c9a43a9e4f366044259 (patch) | |
tree | 3989b000550aa061d6cd222a83c12c62c1cc0182 | |
parent | 30a3ae30c775e2723f86ef70746ad3cb4404a4c9 (diff) | |
download | linux-3.10-7489594cb249aeb178287c9a43a9e4f366044259.tar.gz linux-3.10-7489594cb249aeb178287c9a43a9e4f366044259.tar.bz2 linux-3.10-7489594cb249aeb178287c9a43a9e4f366044259.zip |
gro: Optimise length comparison in skb_gro_header
By caching frag0_len, we can avoid checking both frag0 and the
length separately in skb_gro_header. This helps as skb_gro_header
is called four times per packet which amounts to a few million
times at 10Gb/s.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/netdevice.h | 7 | ||||
-rw-r--r-- | net/core/dev.c | 5 |
2 files changed, 9 insertions, 3 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index d1afc3b6485..2e44a049be0 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1011,6 +1011,9 @@ struct napi_gro_cb { /* Virtual address of skb_shinfo(skb)->frags[0].page + offset. */ void *frag0; + /* Length of frag0. */ + unsigned int frag0_len; + /* This indicates where we are processing relative to skb->data. */ int data_offset; @@ -1134,9 +1137,9 @@ static inline void *skb_gro_header(struct sk_buff *skb, unsigned int hlen) unsigned int offset = skb_gro_offset(skb); hlen += offset; - if (!NAPI_GRO_CB(skb)->frag0 || - unlikely(skb_shinfo(skb)->frags[0].size < hlen)) { + if (NAPI_GRO_CB(skb)->frag0_len < hlen) { NAPI_GRO_CB(skb)->frag0 = NULL; + NAPI_GRO_CB(skb)->frag0_len = 0; return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL; } diff --git a/net/core/dev.c b/net/core/dev.c index f9d90c56b6f..b1722a2d1fb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2509,12 +2509,15 @@ void skb_gro_reset_offset(struct sk_buff *skb) { NAPI_GRO_CB(skb)->data_offset = 0; NAPI_GRO_CB(skb)->frag0 = NULL; + NAPI_GRO_CB(skb)->frag0_len = 0; if (skb->mac_header == skb->tail && - !PageHighMem(skb_shinfo(skb)->frags[0].page)) + !PageHighMem(skb_shinfo(skb)->frags[0].page)) { NAPI_GRO_CB(skb)->frag0 = page_address(skb_shinfo(skb)->frags[0].page) + skb_shinfo(skb)->frags[0].page_offset; + NAPI_GRO_CB(skb)->frag0_len = skb_shinfo(skb)->frags[0].size; + } } EXPORT_SYMBOL(skb_gro_reset_offset); |