diff options
author | David Held <drheld@google.com> | 2014-07-15 23:28:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-17 02:29:52 -0400 |
commit | 2dc41cff7545d55c6294525c811594576f8e119c (patch) | |
tree | cab09b28d188606139b1b50b661f42da157c52ba /include/net | |
parent | 5cf3d46192fccf68b4a4759e4d7346e41c669a76 (diff) |
udp: Use hash2 for long hash1 chains in __udp*_lib_mcast_deliver.
Many multicast sources can have the same port which can result in a very
large list when hashing by port only. Hash by address and port instead
if this is the case. This makes multicast more similar to unicast.
On a 24-core machine receiving from 500 multicast sockets on the same
port, before this patch 80% of system CPU was used up by spin locking
and only ~25% of packets were successfully delivered.
With this patch, all packets are delivered and kernel overhead is ~8%
system CPU on spinlocks.
Signed-off-by: David Held <drheld@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net')
-rw-r--r-- | include/net/sock.h | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/include/net/sock.h b/include/net/sock.h index 29e48a6d1ded..28f734601b50 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -660,6 +660,20 @@ static inline void sk_add_bind_node(struct sock *sk, | |||
660 | #define sk_for_each_bound(__sk, list) \ | 660 | #define sk_for_each_bound(__sk, list) \ |
661 | hlist_for_each_entry(__sk, list, sk_bind_node) | 661 | hlist_for_each_entry(__sk, list, sk_bind_node) |
662 | 662 | ||
663 | /** | ||
664 | * sk_nulls_for_each_entry_offset - iterate over a list at a given struct offset | ||
665 | * @tpos: the type * to use as a loop cursor. | ||
666 | * @pos: the &struct hlist_node to use as a loop cursor. | ||
667 | * @head: the head for your list. | ||
668 | * @offset: offset of hlist_node within the struct. | ||
669 | * | ||
670 | */ | ||
671 | #define sk_nulls_for_each_entry_offset(tpos, pos, head, offset) \ | ||
672 | for (pos = (head)->first; \ | ||
673 | (!is_a_nulls(pos)) && \ | ||
674 | ({ tpos = (typeof(*tpos) *)((void *)pos - offset); 1;}); \ | ||
675 | pos = pos->next) | ||
676 | |||
663 | static inline struct user_namespace *sk_user_ns(struct sock *sk) | 677 | static inline struct user_namespace *sk_user_ns(struct sock *sk) |
664 | { | 678 | { |
665 | /* Careful only use this in a context where these parameters | 679 | /* Careful only use this in a context where these parameters |