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 /include/linux/netdevice.h | |
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 'include/linux/netdevice.h')
-rw-r--r-- | include/linux/netdevice.h | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 586b71f0358c..61890ed0bcf2 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -1008,6 +1008,9 @@ void netif_napi_add(struct net_device *dev, struct napi_struct *napi, | |||
1008 | void netif_napi_del(struct napi_struct *napi); | 1008 | void netif_napi_del(struct napi_struct *napi); |
1009 | 1009 | ||
1010 | struct napi_gro_cb { | 1010 | struct napi_gro_cb { |
1011 | /* Virtual address of skb_shinfo(skb)->frags[0].page + offset. */ | ||
1012 | void *frag0; | ||
1013 | |||
1011 | /* This indicates where we are processing relative to skb->data. */ | 1014 | /* This indicates where we are processing relative to skb->data. */ |
1012 | int data_offset; | 1015 | int data_offset; |
1013 | 1016 | ||
@@ -1107,9 +1110,9 @@ extern int dev_restart(struct net_device *dev); | |||
1107 | #ifdef CONFIG_NETPOLL_TRAP | 1110 | #ifdef CONFIG_NETPOLL_TRAP |
1108 | extern int netpoll_trap(void); | 1111 | extern int netpoll_trap(void); |
1109 | #endif | 1112 | #endif |
1110 | extern void *skb_gro_header(struct sk_buff *skb, unsigned int hlen); | ||
1111 | extern int skb_gro_receive(struct sk_buff **head, | 1113 | extern int skb_gro_receive(struct sk_buff **head, |
1112 | struct sk_buff *skb); | 1114 | struct sk_buff *skb); |
1115 | extern void skb_gro_reset_offset(struct sk_buff *skb); | ||
1113 | 1116 | ||
1114 | static inline unsigned int skb_gro_offset(const struct sk_buff *skb) | 1117 | static inline unsigned int skb_gro_offset(const struct sk_buff *skb) |
1115 | { | 1118 | { |
@@ -1126,23 +1129,28 @@ static inline void skb_gro_pull(struct sk_buff *skb, unsigned int len) | |||
1126 | NAPI_GRO_CB(skb)->data_offset += len; | 1129 | NAPI_GRO_CB(skb)->data_offset += len; |
1127 | } | 1130 | } |
1128 | 1131 | ||
1129 | static inline void skb_gro_reset_offset(struct sk_buff *skb) | 1132 | static inline void *skb_gro_header(struct sk_buff *skb, unsigned int hlen) |
1130 | { | 1133 | { |
1131 | NAPI_GRO_CB(skb)->data_offset = 0; | 1134 | unsigned int offset = skb_gro_offset(skb); |
1135 | |||
1136 | hlen += offset; | ||
1137 | if (!NAPI_GRO_CB(skb)->frag0 || | ||
1138 | unlikely(skb_shinfo(skb)->frags[0].size + skb_headlen(skb) < hlen)) | ||
1139 | return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL; | ||
1140 | |||
1141 | return NAPI_GRO_CB(skb)->frag0 + offset; | ||
1132 | } | 1142 | } |
1133 | 1143 | ||
1134 | static inline void *skb_gro_mac_header(struct sk_buff *skb) | 1144 | static inline void *skb_gro_mac_header(struct sk_buff *skb) |
1135 | { | 1145 | { |
1136 | return skb_headlen(skb) ? skb_mac_header(skb) : | 1146 | return skb_headlen(skb) ? skb_mac_header(skb) : |
1137 | page_address(skb_shinfo(skb)->frags[0].page) + | 1147 | NAPI_GRO_CB(skb)->frag0; |
1138 | skb_shinfo(skb)->frags[0].page_offset; | ||
1139 | } | 1148 | } |
1140 | 1149 | ||
1141 | static inline void *skb_gro_network_header(struct sk_buff *skb) | 1150 | static inline void *skb_gro_network_header(struct sk_buff *skb) |
1142 | { | 1151 | { |
1143 | return skb_headlen(skb) ? skb_network_header(skb) : | 1152 | return skb_headlen(skb) ? skb_network_header(skb) : |
1144 | page_address(skb_shinfo(skb)->frags[0].page) + | 1153 | NAPI_GRO_CB(skb)->frag0 + skb_network_offset(skb); |
1145 | skb_shinfo(skb)->frags[0].page_offset + skb_network_offset(skb); | ||
1146 | } | 1154 | } |
1147 | 1155 | ||
1148 | static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, | 1156 | static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, |