aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ipv6.h32
-rw-r--r--include/net/inet_hashtables.h48
-rw-r--r--include/net/inet_sock.h8
-rw-r--r--include/net/inet_timewait_sock.h7
-rw-r--r--include/net/sock.h25
-rw-r--r--net/ipv4/inet_hashtables.c36
-rw-r--r--net/ipv6/inet6_hashtables.c27
7 files changed, 115 insertions, 68 deletions
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 5e11905a4f01..12729e966dc9 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -364,20 +364,22 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk)
364#define inet_v6_ipv6only(__sk) 0 364#define inet_v6_ipv6only(__sk) 0
365#endif /* IS_ENABLED(CONFIG_IPV6) */ 365#endif /* IS_ENABLED(CONFIG_IPV6) */
366 366
367#define INET6_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif)\ 367#define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif) \
368 (((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net) && \ 368 ((inet_sk(__sk)->inet_portpair == (__ports)) && \
369 ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) && \ 369 ((__sk)->sk_family == AF_INET6) && \
370 ((__sk)->sk_family == AF_INET6) && \ 370 ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr)) && \
371 ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr)) && \ 371 ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \
372 ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \ 372 (!(__sk)->sk_bound_dev_if || \
373 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) 373 ((__sk)->sk_bound_dev_if == (__dif))) && \
374 374 net_eq(sock_net(__sk), (__net)))
375#define INET6_TW_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif) \ 375
376 (((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net) && \ 376#define INET6_TW_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif) \
377 (*((__portpair *)&(inet_twsk(__sk)->tw_dport)) == (__ports)) && \ 377 ((inet_twsk(__sk)->tw_portpair == (__ports)) && \
378 ((__sk)->sk_family == PF_INET6) && \ 378 ((__sk)->sk_family == AF_INET6) && \
379 (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_daddr, (__saddr))) && \ 379 ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_daddr, (__saddr)) && \
380 (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_rcv_saddr, (__daddr))) && \ 380 ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_rcv_saddr, (__daddr)) && \
381 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) 381 (!(__sk)->sk_bound_dev_if || \
382 ((__sk)->sk_bound_dev_if == (__dif))) && \
383 net_eq(sock_net(__sk), (__net)))
382 384
383#endif /* _IPV6_H */ 385#endif /* _IPV6_H */
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 54be0287eb98..d1de4fbd45c2 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -299,30 +299,34 @@ typedef __u64 __bitwise __addrpair;
299 (((__force __u64)(__be32)(__daddr)) << 32) | \ 299 (((__force __u64)(__be32)(__daddr)) << 32) | \
300 ((__force __u64)(__be32)(__saddr))); 300 ((__force __u64)(__be32)(__saddr)));
301#endif /* __BIG_ENDIAN */ 301#endif /* __BIG_ENDIAN */
302#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ 302#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
303 (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \ 303 ((inet_sk(__sk)->inet_portpair == (__ports)) && \
304 ((*((__addrpair *)&(inet_sk(__sk)->inet_daddr))) == (__cookie)) && \ 304 (inet_sk(__sk)->inet_addrpair == (__cookie)) && \
305 ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) && \ 305 (!(__sk)->sk_bound_dev_if || \
306 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) 306 ((__sk)->sk_bound_dev_if == (__dif))) && \
307#define INET_TW_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ 307 net_eq(sock_net(__sk), (__net)))
308 (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \ 308#define INET_TW_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif)\
309 ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \ 309 ((inet_twsk(__sk)->tw_portpair == (__ports)) && \
310 ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ 310 (inet_twsk(__sk)->tw_addrpair == (__cookie)) && \
311 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) 311 (!(__sk)->sk_bound_dev_if || \
312 ((__sk)->sk_bound_dev_if == (__dif))) && \
313 net_eq(sock_net(__sk), (__net)))
312#else /* 32-bit arch */ 314#else /* 32-bit arch */
313#define INET_ADDR_COOKIE(__name, __saddr, __daddr) 315#define INET_ADDR_COOKIE(__name, __saddr, __daddr)
314#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif) \ 316#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
315 (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \ 317 ((inet_sk(__sk)->inet_portpair == (__ports)) && \
316 (inet_sk(__sk)->inet_daddr == (__saddr)) && \ 318 (inet_sk(__sk)->inet_daddr == (__saddr)) && \
317 (inet_sk(__sk)->inet_rcv_saddr == (__daddr)) && \ 319 (inet_sk(__sk)->inet_rcv_saddr == (__daddr)) && \
318 ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) && \ 320 (!(__sk)->sk_bound_dev_if || \
319 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) 321 ((__sk)->sk_bound_dev_if == (__dif))) && \
320#define INET_TW_MATCH(__sk, __net, __hash,__cookie, __saddr, __daddr, __ports, __dif) \ 322 net_eq(sock_net(__sk), (__net)))
321 (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \ 323#define INET_TW_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
322 (inet_twsk(__sk)->tw_daddr == (__saddr)) && \ 324 ((inet_twsk(__sk)->tw_portpair == (__ports)) && \
323 (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \ 325 (inet_twsk(__sk)->tw_daddr == (__saddr)) && \
324 ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ 326 (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \
325 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) 327 (!(__sk)->sk_bound_dev_if || \
328 ((__sk)->sk_bound_dev_if == (__dif))) && \
329 net_eq(sock_net(__sk), (__net)))
326#endif /* 64-bit arch */ 330#endif /* 64-bit arch */
327 331
328/* 332/*
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 256c1ed2d69a..a4196cbc84ec 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -144,9 +144,11 @@ struct inet_sock {
144 /* Socket demultiplex comparisons on incoming packets. */ 144 /* Socket demultiplex comparisons on incoming packets. */
145#define inet_daddr sk.__sk_common.skc_daddr 145#define inet_daddr sk.__sk_common.skc_daddr
146#define inet_rcv_saddr sk.__sk_common.skc_rcv_saddr 146#define inet_rcv_saddr sk.__sk_common.skc_rcv_saddr
147#define inet_addrpair sk.__sk_common.skc_addrpair
148#define inet_dport sk.__sk_common.skc_dport
149#define inet_num sk.__sk_common.skc_num
150#define inet_portpair sk.__sk_common.skc_portpair
147 151
148 __be16 inet_dport;
149 __u16 inet_num;
150 __be32 inet_saddr; 152 __be32 inet_saddr;
151 __s16 uc_ttl; 153 __s16 uc_ttl;
152 __u16 cmsg_flags; 154 __u16 cmsg_flags;
@@ -154,6 +156,7 @@ struct inet_sock {
154 __u16 inet_id; 156 __u16 inet_id;
155 157
156 struct ip_options_rcu __rcu *inet_opt; 158 struct ip_options_rcu __rcu *inet_opt;
159 int rx_dst_ifindex;
157 __u8 tos; 160 __u8 tos;
158 __u8 min_ttl; 161 __u8 min_ttl;
159 __u8 mc_ttl; 162 __u8 mc_ttl;
@@ -170,7 +173,6 @@ struct inet_sock {
170 int uc_index; 173 int uc_index;
171 int mc_index; 174 int mc_index;
172 __be32 mc_addr; 175 __be32 mc_addr;
173 int rx_dst_ifindex;
174 struct ip_mc_socklist __rcu *mc_list; 176 struct ip_mc_socklist __rcu *mc_list;
175 struct inet_cork_full cork; 177 struct inet_cork_full cork;
176}; 178};
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index ba52c830a7a5..7d658d577368 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -112,6 +112,11 @@ struct inet_timewait_sock {
112#define tw_net __tw_common.skc_net 112#define tw_net __tw_common.skc_net
113#define tw_daddr __tw_common.skc_daddr 113#define tw_daddr __tw_common.skc_daddr
114#define tw_rcv_saddr __tw_common.skc_rcv_saddr 114#define tw_rcv_saddr __tw_common.skc_rcv_saddr
115#define tw_addrpair __tw_common.skc_addrpair
116#define tw_dport __tw_common.skc_dport
117#define tw_num __tw_common.skc_num
118#define tw_portpair __tw_common.skc_portpair
119
115 int tw_timeout; 120 int tw_timeout;
116 volatile unsigned char tw_substate; 121 volatile unsigned char tw_substate;
117 unsigned char tw_rcv_wscale; 122 unsigned char tw_rcv_wscale;
@@ -119,8 +124,6 @@ struct inet_timewait_sock {
119 /* Socket demultiplex comparisons on incoming packets. */ 124 /* Socket demultiplex comparisons on incoming packets. */
120 /* these three are in inet_sock */ 125 /* these three are in inet_sock */
121 __be16 tw_sport; 126 __be16 tw_sport;
122 __be16 tw_dport;
123 __u16 tw_num;
124 kmemcheck_bitfield_begin(flags); 127 kmemcheck_bitfield_begin(flags);
125 /* And these are ours. */ 128 /* And these are ours. */
126 unsigned int tw_ipv6only : 1, 129 unsigned int tw_ipv6only : 1,
diff --git a/include/net/sock.h b/include/net/sock.h
index c945fba4f543..c4132c1b63a8 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -132,6 +132,8 @@ struct net;
132 * @skc_rcv_saddr: Bound local IPv4 addr 132 * @skc_rcv_saddr: Bound local IPv4 addr
133 * @skc_hash: hash value used with various protocol lookup tables 133 * @skc_hash: hash value used with various protocol lookup tables
134 * @skc_u16hashes: two u16 hash values used by UDP lookup tables 134 * @skc_u16hashes: two u16 hash values used by UDP lookup tables
135 * @skc_dport: placeholder for inet_dport/tw_dport
136 * @skc_num: placeholder for inet_num/tw_num
135 * @skc_family: network address family 137 * @skc_family: network address family
136 * @skc_state: Connection state 138 * @skc_state: Connection state
137 * @skc_reuse: %SO_REUSEADDR setting 139 * @skc_reuse: %SO_REUSEADDR setting
@@ -149,16 +151,29 @@ struct net;
149 * for struct sock and struct inet_timewait_sock. 151 * for struct sock and struct inet_timewait_sock.
150 */ 152 */
151struct sock_common { 153struct sock_common {
152 /* skc_daddr and skc_rcv_saddr must be grouped : 154 /* skc_daddr and skc_rcv_saddr must be grouped on a 8 bytes aligned
153 * cf INET_MATCH() and INET_TW_MATCH() 155 * address on 64bit arches : cf INET_MATCH() and INET_TW_MATCH()
154 */ 156 */
155 __be32 skc_daddr; 157 union {
156 __be32 skc_rcv_saddr; 158 unsigned long skc_addrpair;
157 159 struct {
160 __be32 skc_daddr;
161 __be32 skc_rcv_saddr;
162 };
163 };
158 union { 164 union {
159 unsigned int skc_hash; 165 unsigned int skc_hash;
160 __u16 skc_u16hashes[2]; 166 __u16 skc_u16hashes[2];
161 }; 167 };
168 /* skc_dport && skc_num must be grouped as well */
169 union {
170 u32 skc_portpair;
171 struct {
172 __be16 skc_dport;
173 __u16 skc_num;
174 };
175 };
176
162 unsigned short skc_family; 177 unsigned short skc_family;
163 volatile unsigned char skc_state; 178 volatile unsigned char skc_state;
164 unsigned char skc_reuse; 179 unsigned char skc_reuse;
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