udp: bind() optimisation
Subsystems (3)
PATCH 1/1 udp: bind() optimisation
UDP bind() can be O(N^2) in some pathological cases.
Thanks to secondary hash tables, we can make it O(N)
Signed-off-by Eric Dumazet <[email protected]>
--- include/linux/udp.h | 6 +++ include/net/udp.h | 3 + net/ipv4/udp.c | 73 +++++++++++++++++++++++++++++++++++++----- net/ipv6/udp.c | 14 ++++---- 4 files changed, 80 insertions(+), 16 deletions(-)
include/linux/udp.h +6 -0
@@ -88,6 +88,12 @@ static inline struct udp_sock *udp_sk(const struct sock *sk) return (struct udp_sock *)sk; } +#define udp_portaddr_for_each_entry (__sk, node, list) \ + hlist_nulls_for_each_entry(__sk, node, list, __sk_common.skc_portaddr_node) + +#define udp_portaddr_for_each_entry_rcu (__sk, node, list) \ + hlist_nulls_for_each_entry_rcu(__sk, node, list, __sk_common.skc_portaddr_node) +#define IS_UDPLITE (__sk) (udp_sk(__sk)->pcflag)#endif
include/net/udp.h +2 -1
@@ -158,7 +158,8 @@ static inline void udp_lib_close(struct sock *sk, long timeout) }extern int udp_lib_get_port (struct sock *sk,unsigned short snum, -int (*)(const struct sock *,const struct sock *)); +int (*)(const struct sock *,const struct sock *), +unsigned int hash2_nulladdr);/* net/ipv4/udp.c */ extern int udp_get_port(struct sock *sk, unsigned short snum,
net/ipv4/udp.c +65 -8
107 lines not on this page · raw message
net/ipv6/udp.c +7 -7
@@ -100,12 +100,14 @@ static unsigned int udp6_portaddr_hash(struct net *net,int udp_v6_get_port (struct sock *sk,unsigned short snum) { +unsigned int hash2_nulladdr = +udp6_portaddr_hash (sock_net (sk), &in6addr_any, snum); +unsigned int hash2_partial = +udp6_portaddr_hash (sock_net (sk), &inet6_sk (sk)->rcv_saddr,0 ); +/* precompute partial secondary hash */ -udp_sk (sk)->udp_portaddr_hash = -udp6_portaddr_hash (sock_net (sk), - &inet6_sk (sk)->rcv_saddr, -0 ); -return udp_lib_get_port (sk, snum, ipv6_rcv_saddr_equal); +udp_sk (sk)->udp_portaddr_hash = hash2_partial; +return udp_lib_get_port (sk, snum, ipv6_rcv_saddr_equal, hash2_nulladdr); } static inline int compute_score(struct sock *sk, struct net *net,
@@ -181,8 +183,6 @@ static inline int compute_score2(struct sock *sk, struct net *net,return score; } -#define udp_portaddr_for_each_entry_rcu (__sk, node, list) \ - hlist_nulls_for_each_entry_rcu(__sk, node, list, __sk_common.skc_portaddr_node)/* called with read_rcu_lock() */ static struct sock *udp6_lib_lookup2(struct net *net,
From: Eric Dumazet <[email protected]>
Date: Mon, 09 Nov 2009 16:26:33 +0100
Quoted 5 lines
UDP
bind()can be O(N^2) in some pathological cases.Thanks to secondary hash tables, we can make it O(N)
Signed-off-by Eric Dumazet <[email protected]>
Applied to net-next-2.6