aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/neighbour.h
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-08-06 22:19:56 -0400
committerDavid S. Miller <davem@davemloft.net>2012-08-07 19:24:55 -0400
commit425f09ab7d1c9da6ca4137dd639cb6fe3f8a88f3 (patch)
tree49c586d8025f671a8e47415f4364bfb818534569 /include/net/neighbour.h
parente07b94f1352723994d8b588ac5ed8af91bcc9fb6 (diff)
net: output path optimizations
1) Avoid dirtying neighbour's confirmed field. TCP workloads hits this cache line for each incoming ACK. Lets write n->confirmed only if there is a jiffie change. 2) Optimize neigh_hh_output() for the common Ethernet case, were hh_len is less than 16 bytes. Replace the memcpy() call by two inlined 64bit load/stores on x86_64. Bench results using udpflood test, with -C option (MSG_CONFIRM flag added to sendto(), to reproduce the n->confirmed dirtying on UDP) 24 threads doing 1.000.000 UDP sendto() on dummy device, 4 runs. before : 2.247s, 2.235s, 2.247s, 2.318s after : 1.884s, 1.905s, 1.891s, 1.895s Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/neighbour.h')
-rw-r--r--include/net/neighbour.h14
1 files changed, 9 insertions, 5 deletions
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 344d8988842a..0dab173e27da 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -334,18 +334,22 @@ static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb)
334} 334}
335#endif 335#endif
336 336
337static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb) 337static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb)
338{ 338{
339 unsigned int seq; 339 unsigned int seq;
340 int hh_len; 340 int hh_len;
341 341
342 do { 342 do {
343 int hh_alen;
344
345 seq = read_seqbegin(&hh->hh_lock); 343 seq = read_seqbegin(&hh->hh_lock);
346 hh_len = hh->hh_len; 344 hh_len = hh->hh_len;
347 hh_alen = HH_DATA_ALIGN(hh_len); 345 if (likely(hh_len <= HH_DATA_MOD)) {
348 memcpy(skb->data - hh_alen, hh->hh_data, hh_alen); 346 /* this is inlined by gcc */
347 memcpy(skb->data - HH_DATA_MOD, hh->hh_data, HH_DATA_MOD);
348 } else {
349 int hh_alen = HH_DATA_ALIGN(hh_len);
350
351 memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
352 }
349 } while (read_seqretry(&hh->hh_lock, seq)); 353 } while (read_seqretry(&hh->hh_lock, seq));
350 354
351 skb_push(skb, hh_len); 355 skb_push(skb, hh_len);