diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2009-02-08 13:00:37 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-08 23:22:18 -0500 |
commit | aa4b9f533ed5a22952e038b9fac2447ccc682124 (patch) | |
tree | 91722b13a63dcd0e49695388e633cfa91b856b80 /net/core | |
parent | 4ae5544f9a33e4ae306e337f96951eb3ff2df6d9 (diff) |
gro: Optimise Ethernet header comparison
This patch optimises the Ethernet header comparison to use 2-byte
and 4-byte xors instead of memcmp. In order to facilitate this,
the actual comparison is now carried out by the callers of the
shared dev_gro_receive function.
This has a significant impact when receiving 1500B packets through
10GbE.
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 | 23 |
1 files changed, 2 insertions, 21 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index ae0b66936abe..1e27a67df242 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -215,13 +215,6 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex) | |||
215 | return &net->dev_index_head[ifindex & ((1 << NETDEV_HASHBITS) - 1)]; | 215 | return &net->dev_index_head[ifindex & ((1 << NETDEV_HASHBITS) - 1)]; |
216 | } | 216 | } |
217 | 217 | ||
218 | static inline void *skb_gro_mac_header(struct sk_buff *skb) | ||
219 | { | ||
220 | return skb_mac_header(skb) < skb->data ? skb_mac_header(skb) : | ||
221 | page_address(skb_shinfo(skb)->frags[0].page) + | ||
222 | skb_shinfo(skb)->frags[0].page_offset; | ||
223 | } | ||
224 | |||
225 | /* Device list insertion */ | 218 | /* Device list insertion */ |
226 | static int list_netdevice(struct net_device *dev) | 219 | static int list_netdevice(struct net_device *dev) |
227 | { | 220 | { |
@@ -2415,29 +2408,16 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | |||
2415 | 2408 | ||
2416 | rcu_read_lock(); | 2409 | rcu_read_lock(); |
2417 | list_for_each_entry_rcu(ptype, head, list) { | 2410 | list_for_each_entry_rcu(ptype, head, list) { |
2418 | struct sk_buff *p; | ||
2419 | void *mac; | ||
2420 | |||
2421 | if (ptype->type != type || ptype->dev || !ptype->gro_receive) | 2411 | if (ptype->type != type || ptype->dev || !ptype->gro_receive) |
2422 | continue; | 2412 | continue; |
2423 | 2413 | ||
2424 | skb_set_network_header(skb, skb_gro_offset(skb)); | 2414 | skb_set_network_header(skb, skb_gro_offset(skb)); |
2425 | mac = skb_gro_mac_header(skb); | ||
2426 | mac_len = skb->network_header - skb->mac_header; | 2415 | mac_len = skb->network_header - skb->mac_header; |
2427 | skb->mac_len = mac_len; | 2416 | skb->mac_len = mac_len; |
2428 | NAPI_GRO_CB(skb)->same_flow = 0; | 2417 | NAPI_GRO_CB(skb)->same_flow = 0; |
2429 | NAPI_GRO_CB(skb)->flush = 0; | 2418 | NAPI_GRO_CB(skb)->flush = 0; |
2430 | NAPI_GRO_CB(skb)->free = 0; | 2419 | NAPI_GRO_CB(skb)->free = 0; |
2431 | 2420 | ||
2432 | for (p = napi->gro_list; p; p = p->next) { | ||
2433 | if (!NAPI_GRO_CB(p)->same_flow) | ||
2434 | continue; | ||
2435 | |||
2436 | if (p->mac_len != mac_len || | ||
2437 | memcmp(skb_mac_header(p), mac, mac_len)) | ||
2438 | NAPI_GRO_CB(p)->same_flow = 0; | ||
2439 | } | ||
2440 | |||
2441 | pp = ptype->gro_receive(&napi->gro_list, skb); | 2421 | pp = ptype->gro_receive(&napi->gro_list, skb); |
2442 | break; | 2422 | break; |
2443 | } | 2423 | } |
@@ -2492,7 +2472,8 @@ static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | |||
2492 | struct sk_buff *p; | 2472 | struct sk_buff *p; |
2493 | 2473 | ||
2494 | for (p = napi->gro_list; p; p = p->next) { | 2474 | for (p = napi->gro_list; p; p = p->next) { |
2495 | NAPI_GRO_CB(p)->same_flow = 1; | 2475 | NAPI_GRO_CB(p)->same_flow = !compare_ether_header( |
2476 | skb_mac_header(p), skb_gro_mac_header(skb)); | ||
2496 | NAPI_GRO_CB(p)->flush = 0; | 2477 | NAPI_GRO_CB(p)->flush = 0; |
2497 | } | 2478 | } |
2498 | 2479 | ||