aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-11-30 04:49:27 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-30 15:02:56 -0500
commitce43b03e8889475817d427b1f3724c7e294b76eb (patch)
tree0cd6679992bd810371620fcab52c24ce39a89aa8 /net
parentb02a80674ea3905926c1a942426008d732c47339 (diff)
net: move inet_dport/inet_num in sock_common
commit 68835aba4d9b (net: optimize INET input path further) moved some fields used for tcp/udp sockets lookup in the first cache line of struct sock_common. This patch moves inet_dport/inet_num as well, filling a 32bit hole on 64 bit arches and reducing number of cache line misses in lookups. Also change INET_MATCH()/INET_TW_MATCH() to perform the ports match before addresses match, as this check is more discriminant. Remove the hash check from MATCH() macros because we dont need to re validate the hash value after taking a refcount on socket, and use likely/unlikely compiler hints, as the sk_hash/hash check makes the following conditional tests 100% predicted by cpu. Introduce skc_addrpair/skc_portpair pair values to better document the alignment requirements of the port/addr pairs used in the various MATCH() macros, and remove some casts. The namespace check can also be done at last. This slightly improves TCP/UDP lookup times. IP/TCP early demux needs inet->rx_dst_ifindex and TCP needs inet->min_ttl, lets group them together in same cache line. With help from Ben Hutchings & Joe Perches. Idea of this patch came after Ling Ma proposal to move skc_hash to the beginning of struct sock_common, and should allow him to submit a final version of his patch. My tests show an improvement doing so. Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Ben Hutchings <bhutchings@solarflare.com> Cc: Joe Perches <joe@perches.com> Cc: Ling Ma <ling.ma.program@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/inet_hashtables.c36
-rw-r--r--net/ipv6/inet6_hashtables.c27
2 files changed, 42 insertions, 21 deletions
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 7880af970208..fa3ae8148710 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -237,12 +237,14 @@ struct sock *__inet_lookup_established(struct net *net,
237 rcu_read_lock(); 237 rcu_read_lock();
238begin: 238begin:
239 sk_nulls_for_each_rcu(sk, node, &head->chain) { 239 sk_nulls_for_each_rcu(sk, node, &head->chain) {
240 if (INET_MATCH(sk, net, hash, acookie, 240 if (sk->sk_hash != hash)
241 saddr, daddr, ports, dif)) { 241 continue;
242 if (likely(INET_MATCH(sk, net, acookie,
243 saddr, daddr, ports, dif))) {
242 if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt))) 244 if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt)))
243 goto begintw; 245 goto begintw;
244 if (unlikely(!INET_MATCH(sk, net, hash, acookie, 246 if (unlikely(!INET_MATCH(sk, net, acookie,
245 saddr, daddr, ports, dif))) { 247 saddr, daddr, ports, dif))) {
246 sock_put(sk); 248 sock_put(sk);
247 goto begin; 249 goto begin;
248 } 250 }
@@ -260,14 +262,18 @@ begin:
260begintw: 262begintw:
261 /* Must check for a TIME_WAIT'er before going to listener hash. */ 263 /* Must check for a TIME_WAIT'er before going to listener hash. */
262 sk_nulls_for_each_rcu(sk, node, &head->twchain) { 264 sk_nulls_for_each_rcu(sk, node, &head->twchain) {
263 if (INET_TW_MATCH(sk, net, hash, acookie, 265 if (sk->sk_hash != hash)
264 saddr, daddr, ports, dif)) { 266 continue;
267 if (likely(INET_TW_MATCH(sk, net, acookie,
268 saddr, daddr, ports,
269 dif))) {
265 if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt))) { 270 if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt))) {
266 sk = NULL; 271 sk = NULL;
267 goto out; 272 goto out;
268 } 273 }
269 if (unlikely(!INET_TW_MATCH(sk, net, hash, acookie, 274 if (unlikely(!INET_TW_MATCH(sk, net, acookie,
270 saddr, daddr, ports, dif))) { 275 saddr, daddr, ports,
276 dif))) {
271 sock_put(sk); 277 sock_put(sk);
272 goto begintw; 278 goto begintw;
273 } 279 }
@@ -314,10 +320,12 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
314 320
315 /* Check TIME-WAIT sockets first. */ 321 /* Check TIME-WAIT sockets first. */
316 sk_nulls_for_each(sk2, node, &head->twchain) { 322 sk_nulls_for_each(sk2, node, &head->twchain) {
317 tw = inet_twsk(sk2); 323 if (sk2->sk_hash != hash)
324 continue;
318 325
319 if (INET_TW_MATCH(sk2, net, hash, acookie, 326 if (likely(INET_TW_MATCH(sk2, net, acookie,
320 saddr, daddr, ports, dif)) { 327 saddr, daddr, ports, dif))) {
328 tw = inet_twsk(sk2);
321 if (twsk_unique(sk, sk2, twp)) 329 if (twsk_unique(sk, sk2, twp))
322 goto unique; 330 goto unique;
323 else 331 else
@@ -328,8 +336,10 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
328 336
329 /* And established part... */ 337 /* And established part... */
330 sk_nulls_for_each(sk2, node, &head->chain) { 338 sk_nulls_for_each(sk2, node, &head->chain) {
331 if (INET_MATCH(sk2, net, hash, acookie, 339 if (sk2->sk_hash != hash)
332 saddr, daddr, ports, dif)) 340 continue;
341 if (likely(INET_MATCH(sk2, net, acookie,
342 saddr, daddr, ports, dif)))
333 goto not_unique; 343 goto not_unique;
334 } 344 }
335 345
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 73f1a00a96af..dea17fd28e50 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -87,11 +87,13 @@ struct sock *__inet6_lookup_established(struct net *net,
87 rcu_read_lock(); 87 rcu_read_lock();
88begin: 88begin:
89 sk_nulls_for_each_rcu(sk, node, &head->chain) { 89 sk_nulls_for_each_rcu(sk, node, &head->chain) {
90 /* For IPV6 do the cheaper port and family tests first. */ 90 if (sk->sk_hash != hash)
91 if (INET6_MATCH(sk, net, hash, saddr, daddr, ports, dif)) { 91 continue;
92 if (likely(INET6_MATCH(sk, net, saddr, daddr, ports, dif))) {
92 if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt))) 93 if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt)))
93 goto begintw; 94 goto begintw;
94 if (!INET6_MATCH(sk, net, hash, saddr, daddr, ports, dif)) { 95 if (unlikely(!INET6_MATCH(sk, net, saddr, daddr,
96 ports, dif))) {
95 sock_put(sk); 97 sock_put(sk);
96 goto begin; 98 goto begin;
97 } 99 }
@@ -104,12 +106,16 @@ begin:
104begintw: 106begintw:
105 /* Must check for a TIME_WAIT'er before going to listener hash. */ 107 /* Must check for a TIME_WAIT'er before going to listener hash. */
106 sk_nulls_for_each_rcu(sk, node, &head->twchain) { 108 sk_nulls_for_each_rcu(sk, node, &head->twchain) {
107 if (INET6_TW_MATCH(sk, net, hash, saddr, daddr, ports, dif)) { 109 if (sk->sk_hash != hash)
110 continue;
111 if (likely(INET6_TW_MATCH(sk, net, saddr, daddr,
112 ports, dif))) {
108 if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt))) { 113 if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt))) {
109 sk = NULL; 114 sk = NULL;
110 goto out; 115 goto out;
111 } 116 }
112 if (!INET6_TW_MATCH(sk, net, hash, saddr, daddr, ports, dif)) { 117 if (unlikely(!INET6_TW_MATCH(sk, net, saddr, daddr,
118 ports, dif))) {
113 sock_put(sk); 119 sock_put(sk);
114 goto begintw; 120 goto begintw;
115 } 121 }
@@ -236,9 +242,12 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
236 242
237 /* Check TIME-WAIT sockets first. */ 243 /* Check TIME-WAIT sockets first. */
238 sk_nulls_for_each(sk2, node, &head->twchain) { 244 sk_nulls_for_each(sk2, node, &head->twchain) {
239 tw = inet_twsk(sk2); 245 if (sk2->sk_hash != hash)
246 continue;
240 247
241 if (INET6_TW_MATCH(sk2, net, hash, saddr, daddr, ports, dif)) { 248 if (likely(INET6_TW_MATCH(sk2, net, saddr, daddr,
249 ports, dif))) {
250 tw = inet_twsk(sk2);
242 if (twsk_unique(sk, sk2, twp)) 251 if (twsk_unique(sk, sk2, twp))
243 goto unique; 252 goto unique;
244 else 253 else
@@ -249,7 +258,9 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
249 258
250 /* And established part... */ 259 /* And established part... */
251 sk_nulls_for_each(sk2, node, &head->chain) { 260 sk_nulls_for_each(sk2, node, &head->chain) {
252 if (INET6_MATCH(sk2, net, hash, saddr, daddr, ports, dif)) 261 if (sk2->sk_hash != hash)
262 continue;
263 if (likely(INET6_MATCH(sk2, net, saddr, daddr, ports, dif)))
253 goto not_unique; 264 goto not_unique;
254 } 265 }
255 266