diff options
author | Eric Dumazet <dada1@cosmosbay.com> | 2007-02-09 18:44:52 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-02-11 02:20:29 -0500 |
commit | 95f30b336b944e3e418f825044b4793d9e9aac09 (patch) | |
tree | 4faf8cc7a061fdf7d85f94768ca1150f8580e700 /net | |
parent | 4768fbcbcfbbcacb785ae08eef33767a0b4fdcdd (diff) |
[UDP]: UDP can use sk_hash to speedup lookups
In a prior patch, I introduced a sk_hash field (__sk_common.skc_hash) to let
tcp lookups use one cache line per unmatched entry instead of two.
We can also use sk_hash to speedup UDP part as well. We store in sk_hash the
hnum value, and use sk->sk_hash (same cache line than 'next' pointer),
instead of inet->num (different cache line)
Note : We still have a false sharing problem for SMP machines, because
sock_hold(sock) dirties the cache line containing the 'next' pointer. Not
counting the udp_hash_lock rwlock. (did someone mentioned RCU ? :) )
Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/udp.c | 9 | ||||
-rw-r--r-- | net/ipv6/udp.c | 4 |
2 files changed, 7 insertions, 6 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 2a246de6a671..ce6c46034314 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -120,7 +120,7 @@ static inline int __udp_lib_lport_inuse(__u16 num, struct hlist_head udptable[]) | |||
120 | struct hlist_node *node; | 120 | struct hlist_node *node; |
121 | 121 | ||
122 | sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)]) | 122 | sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)]) |
123 | if (inet_sk(sk)->num == num) | 123 | if (sk->sk_hash == num) |
124 | return 1; | 124 | return 1; |
125 | return 0; | 125 | return 0; |
126 | } | 126 | } |
@@ -191,7 +191,7 @@ gotit: | |||
191 | head = &udptable[snum & (UDP_HTABLE_SIZE - 1)]; | 191 | head = &udptable[snum & (UDP_HTABLE_SIZE - 1)]; |
192 | 192 | ||
193 | sk_for_each(sk2, node, head) | 193 | sk_for_each(sk2, node, head) |
194 | if (inet_sk(sk2)->num == snum && | 194 | if (sk2->sk_hash == snum && |
195 | sk2 != sk && | 195 | sk2 != sk && |
196 | (!sk2->sk_reuse || !sk->sk_reuse) && | 196 | (!sk2->sk_reuse || !sk->sk_reuse) && |
197 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if | 197 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if |
@@ -200,6 +200,7 @@ gotit: | |||
200 | goto fail; | 200 | goto fail; |
201 | } | 201 | } |
202 | inet_sk(sk)->num = snum; | 202 | inet_sk(sk)->num = snum; |
203 | sk->sk_hash = snum; | ||
203 | if (sk_unhashed(sk)) { | 204 | if (sk_unhashed(sk)) { |
204 | head = &udptable[snum & (UDP_HTABLE_SIZE - 1)]; | 205 | head = &udptable[snum & (UDP_HTABLE_SIZE - 1)]; |
205 | sk_add_node(sk, head); | 206 | sk_add_node(sk, head); |
@@ -247,7 +248,7 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport, | |||
247 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { | 248 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { |
248 | struct inet_sock *inet = inet_sk(sk); | 249 | struct inet_sock *inet = inet_sk(sk); |
249 | 250 | ||
250 | if (inet->num == hnum && !ipv6_only_sock(sk)) { | 251 | if (sk->sk_hash == hnum && !ipv6_only_sock(sk)) { |
251 | int score = (sk->sk_family == PF_INET ? 1 : 0); | 252 | int score = (sk->sk_family == PF_INET ? 1 : 0); |
252 | if (inet->rcv_saddr) { | 253 | if (inet->rcv_saddr) { |
253 | if (inet->rcv_saddr != daddr) | 254 | if (inet->rcv_saddr != daddr) |
@@ -296,7 +297,7 @@ static inline struct sock *udp_v4_mcast_next(struct sock *sk, | |||
296 | sk_for_each_from(s, node) { | 297 | sk_for_each_from(s, node) { |
297 | struct inet_sock *inet = inet_sk(s); | 298 | struct inet_sock *inet = inet_sk(s); |
298 | 299 | ||
299 | if (inet->num != hnum || | 300 | if (s->sk_hash != hnum || |
300 | (inet->daddr && inet->daddr != rmt_addr) || | 301 | (inet->daddr && inet->daddr != rmt_addr) || |
301 | (inet->dport != rmt_port && inet->dport) || | 302 | (inet->dport != rmt_port && inet->dport) || |
302 | (inet->rcv_saddr && inet->rcv_saddr != loc_addr) || | 303 | (inet->rcv_saddr && inet->rcv_saddr != loc_addr) || |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index dbe2748db1e9..ccf2f4d196be 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -71,7 +71,7 @@ static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, | |||
71 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { | 71 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { |
72 | struct inet_sock *inet = inet_sk(sk); | 72 | struct inet_sock *inet = inet_sk(sk); |
73 | 73 | ||
74 | if (inet->num == hnum && sk->sk_family == PF_INET6) { | 74 | if (sk->sk_hash == hnum && sk->sk_family == PF_INET6) { |
75 | struct ipv6_pinfo *np = inet6_sk(sk); | 75 | struct ipv6_pinfo *np = inet6_sk(sk); |
76 | int score = 0; | 76 | int score = 0; |
77 | if (inet->dport) { | 77 | if (inet->dport) { |
@@ -309,7 +309,7 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, | |||
309 | sk_for_each_from(s, node) { | 309 | sk_for_each_from(s, node) { |
310 | struct inet_sock *inet = inet_sk(s); | 310 | struct inet_sock *inet = inet_sk(s); |
311 | 311 | ||
312 | if (inet->num == num && s->sk_family == PF_INET6) { | 312 | if (s->sk_hash == num && s->sk_family == PF_INET6) { |
313 | struct ipv6_pinfo *np = inet6_sk(s); | 313 | struct ipv6_pinfo *np = inet6_sk(s); |
314 | if (inet->dport) { | 314 | if (inet->dport) { |
315 | if (inet->dport != rmt_port) | 315 | if (inet->dport != rmt_port) |