aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2009-05-26 14:50:27 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-27 06:26:01 -0400
commit7489594cb249aeb178287c9a43a9e4f366044259 (patch)
tree3989b000550aa061d6cd222a83c12c62c1cc0182
parent30a3ae30c775e2723f86ef70746ad3cb4404a4c9 (diff)
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.h7
-rw-r--r--net/core/dev.c5
2 files changed, 9 insertions, 3 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d1afc3b64854..2e44a049be0f 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1011,6 +1011,9 @@ struct napi_gro_cb {
1011 /* Virtual address of skb_shinfo(skb)->frags[0].page + offset. */ 1011 /* Virtual address of skb_shinfo(skb)->frags[0].page + offset. */
1012 void *frag0; 1012 void *frag0;
1013 1013
1014 /* Length of frag0. */
1015 unsigned int frag0_len;
1016
1014 /* This indicates where we are processing relative to skb->data. */ 1017 /* This indicates where we are processing relative to skb->data. */
1015 int data_offset; 1018 int data_offset;
1016 1019
@@ -1134,9 +1137,9 @@ static inline void *skb_gro_header(struct sk_buff *skb, unsigned int hlen)
1134 unsigned int offset = skb_gro_offset(skb); 1137 unsigned int offset = skb_gro_offset(skb);
1135 1138
1136 hlen += offset; 1139 hlen += offset;
1137 if (!NAPI_GRO_CB(skb)->frag0 || 1140 if (NAPI_GRO_CB(skb)->frag0_len < hlen) {
1138 unlikely(skb_shinfo(skb)->frags[0].size < hlen)) {
1139 NAPI_GRO_CB(skb)->frag0 = NULL; 1141 NAPI_GRO_CB(skb)->frag0 = NULL;
1142 NAPI_GRO_CB(skb)->frag0_len = 0;
1140 return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL; 1143 return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL;
1141 } 1144 }
1142 1145
diff --git a/net/core/dev.c b/net/core/dev.c
index f9d90c56b6f0..b1722a2d1fbe 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2509,12 +2509,15 @@ void skb_gro_reset_offset(struct sk_buff *skb)
2509{ 2509{
2510 NAPI_GRO_CB(skb)->data_offset = 0; 2510 NAPI_GRO_CB(skb)->data_offset = 0;
2511 NAPI_GRO_CB(skb)->frag0 = NULL; 2511 NAPI_GRO_CB(skb)->frag0 = NULL;
2512 NAPI_GRO_CB(skb)->frag0_len = 0;
2512 2513
2513 if (skb->mac_header == skb->tail && 2514 if (skb->mac_header == skb->tail &&
2514 !PageHighMem(skb_shinfo(skb)->frags[0].page)) 2515 !PageHighMem(skb_shinfo(skb)->frags[0].page)) {
2515 NAPI_GRO_CB(skb)->frag0 = 2516 NAPI_GRO_CB(skb)->frag0 =
2516 page_address(skb_shinfo(skb)->frags[0].page) + 2517 page_address(skb_shinfo(skb)->frags[0].page) +
2517 skb_shinfo(skb)->frags[0].page_offset; 2518 skb_shinfo(skb)->frags[0].page_offset;
2519 NAPI_GRO_CB(skb)->frag0_len = skb_shinfo(skb)->frags[0].size;
2520 }
2518} 2521}
2519EXPORT_SYMBOL(skb_gro_reset_offset); 2522EXPORT_SYMBOL(skb_gro_reset_offset);
2520 2523