diff options
Diffstat (limited to 'include/net/inet_hashtables.h')
-rw-r--r-- | include/net/inet_hashtables.h | 96 |
1 files changed, 49 insertions, 47 deletions
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 98e0bb3014fe..a9eb2eaf094e 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h | |||
@@ -271,66 +271,57 @@ static inline int inet_iif(const struct sk_buff *skb) | |||
271 | return ((struct rtable *)skb->dst)->rt_iif; | 271 | return ((struct rtable *)skb->dst)->rt_iif; |
272 | } | 272 | } |
273 | 273 | ||
274 | extern struct sock *__inet_lookup_listener(const struct hlist_head *head, | 274 | extern struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo, |
275 | const u32 daddr, | 275 | const __be32 daddr, |
276 | const unsigned short hnum, | 276 | const unsigned short hnum, |
277 | const int dif); | 277 | const int dif); |
278 | 278 | ||
279 | /* Optimize the common listener case. */ | 279 | static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo, |
280 | static inline struct sock * | 280 | __be32 daddr, __be16 dport, int dif) |
281 | inet_lookup_listener(struct inet_hashinfo *hashinfo, | ||
282 | const u32 daddr, | ||
283 | const unsigned short hnum, const int dif) | ||
284 | { | 281 | { |
285 | struct sock *sk = NULL; | 282 | return __inet_lookup_listener(hashinfo, daddr, ntohs(dport), dif); |
286 | const struct hlist_head *head; | ||
287 | |||
288 | read_lock(&hashinfo->lhash_lock); | ||
289 | head = &hashinfo->listening_hash[inet_lhashfn(hnum)]; | ||
290 | if (!hlist_empty(head)) { | ||
291 | const struct inet_sock *inet = inet_sk((sk = __sk_head(head))); | ||
292 | |||
293 | if (inet->num == hnum && !sk->sk_node.next && | ||
294 | (!inet->rcv_saddr || inet->rcv_saddr == daddr) && | ||
295 | (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) && | ||
296 | !sk->sk_bound_dev_if) | ||
297 | goto sherry_cache; | ||
298 | sk = __inet_lookup_listener(head, daddr, hnum, dif); | ||
299 | } | ||
300 | if (sk) { | ||
301 | sherry_cache: | ||
302 | sock_hold(sk); | ||
303 | } | ||
304 | read_unlock(&hashinfo->lhash_lock); | ||
305 | return sk; | ||
306 | } | 283 | } |
307 | 284 | ||
308 | /* Socket demux engine toys. */ | 285 | /* Socket demux engine toys. */ |
286 | /* What happens here is ugly; there's a pair of adjacent fields in | ||
287 | struct inet_sock; __be16 dport followed by __u16 num. We want to | ||
288 | search by pair, so we combine the keys into a single 32bit value | ||
289 | and compare with 32bit value read from &...->dport. Let's at least | ||
290 | make sure that it's not mixed with anything else... | ||
291 | On 64bit targets we combine comparisons with pair of adjacent __be32 | ||
292 | fields in the same way. | ||
293 | */ | ||
294 | typedef __u32 __bitwise __portpair; | ||
309 | #ifdef __BIG_ENDIAN | 295 | #ifdef __BIG_ENDIAN |
310 | #define INET_COMBINED_PORTS(__sport, __dport) \ | 296 | #define INET_COMBINED_PORTS(__sport, __dport) \ |
311 | (((__u32)(__sport) << 16) | (__u32)(__dport)) | 297 | ((__force __portpair)(((__force __u32)(__be16)(__sport) << 16) | (__u32)(__dport))) |
312 | #else /* __LITTLE_ENDIAN */ | 298 | #else /* __LITTLE_ENDIAN */ |
313 | #define INET_COMBINED_PORTS(__sport, __dport) \ | 299 | #define INET_COMBINED_PORTS(__sport, __dport) \ |
314 | (((__u32)(__dport) << 16) | (__u32)(__sport)) | 300 | ((__force __portpair)(((__u32)(__dport) << 16) | (__force __u32)(__be16)(__sport))) |
315 | #endif | 301 | #endif |
316 | 302 | ||
317 | #if (BITS_PER_LONG == 64) | 303 | #if (BITS_PER_LONG == 64) |
304 | typedef __u64 __bitwise __addrpair; | ||
318 | #ifdef __BIG_ENDIAN | 305 | #ifdef __BIG_ENDIAN |
319 | #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ | 306 | #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ |
320 | const __u64 __name = (((__u64)(__saddr)) << 32) | ((__u64)(__daddr)); | 307 | const __addrpair __name = (__force __addrpair) ( \ |
308 | (((__force __u64)(__be32)(__saddr)) << 32) | \ | ||
309 | ((__force __u64)(__be32)(__daddr))); | ||
321 | #else /* __LITTLE_ENDIAN */ | 310 | #else /* __LITTLE_ENDIAN */ |
322 | #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ | 311 | #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ |
323 | const __u64 __name = (((__u64)(__daddr)) << 32) | ((__u64)(__saddr)); | 312 | const __addrpair __name = (__force __addrpair) ( \ |
313 | (((__force __u64)(__be32)(__daddr)) << 32) | \ | ||
314 | ((__force __u64)(__be32)(__saddr))); | ||
324 | #endif /* __BIG_ENDIAN */ | 315 | #endif /* __BIG_ENDIAN */ |
325 | #define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ | 316 | #define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ |
326 | (((__sk)->sk_hash == (__hash)) && \ | 317 | (((__sk)->sk_hash == (__hash)) && \ |
327 | ((*((__u64 *)&(inet_sk(__sk)->daddr))) == (__cookie)) && \ | 318 | ((*((__addrpair *)&(inet_sk(__sk)->daddr))) == (__cookie)) && \ |
328 | ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \ | 319 | ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports)) && \ |
329 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) | 320 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) |
330 | #define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ | 321 | #define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ |
331 | (((__sk)->sk_hash == (__hash)) && \ | 322 | (((__sk)->sk_hash == (__hash)) && \ |
332 | ((*((__u64 *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \ | 323 | ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \ |
333 | ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ | 324 | ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ |
334 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) | 325 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) |
335 | #else /* 32-bit arch */ | 326 | #else /* 32-bit arch */ |
336 | #define INET_ADDR_COOKIE(__name, __saddr, __daddr) | 327 | #define INET_ADDR_COOKIE(__name, __saddr, __daddr) |
@@ -338,13 +329,13 @@ sherry_cache: | |||
338 | (((__sk)->sk_hash == (__hash)) && \ | 329 | (((__sk)->sk_hash == (__hash)) && \ |
339 | (inet_sk(__sk)->daddr == (__saddr)) && \ | 330 | (inet_sk(__sk)->daddr == (__saddr)) && \ |
340 | (inet_sk(__sk)->rcv_saddr == (__daddr)) && \ | 331 | (inet_sk(__sk)->rcv_saddr == (__daddr)) && \ |
341 | ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \ | 332 | ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports)) && \ |
342 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) | 333 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) |
343 | #define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif) \ | 334 | #define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif) \ |
344 | (((__sk)->sk_hash == (__hash)) && \ | 335 | (((__sk)->sk_hash == (__hash)) && \ |
345 | (inet_twsk(__sk)->tw_daddr == (__saddr)) && \ | 336 | (inet_twsk(__sk)->tw_daddr == (__saddr)) && \ |
346 | (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \ | 337 | (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \ |
347 | ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ | 338 | ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ |
348 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) | 339 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) |
349 | #endif /* 64-bit arch */ | 340 | #endif /* 64-bit arch */ |
350 | 341 | ||
@@ -356,12 +347,12 @@ sherry_cache: | |||
356 | */ | 347 | */ |
357 | static inline struct sock * | 348 | static inline struct sock * |
358 | __inet_lookup_established(struct inet_hashinfo *hashinfo, | 349 | __inet_lookup_established(struct inet_hashinfo *hashinfo, |
359 | const u32 saddr, const u16 sport, | 350 | const __be32 saddr, const __be16 sport, |
360 | const u32 daddr, const u16 hnum, | 351 | const __be32 daddr, const u16 hnum, |
361 | const int dif) | 352 | const int dif) |
362 | { | 353 | { |
363 | INET_ADDR_COOKIE(acookie, saddr, daddr) | 354 | INET_ADDR_COOKIE(acookie, saddr, daddr) |
364 | const __u32 ports = INET_COMBINED_PORTS(sport, hnum); | 355 | const __portpair ports = INET_COMBINED_PORTS(sport, hnum); |
365 | struct sock *sk; | 356 | struct sock *sk; |
366 | const struct hlist_node *node; | 357 | const struct hlist_node *node; |
367 | /* Optimize here for direct hit, only listening connections can | 358 | /* Optimize here for direct hit, only listening connections can |
@@ -391,25 +382,36 @@ hit: | |||
391 | goto out; | 382 | goto out; |
392 | } | 383 | } |
393 | 384 | ||
385 | static inline struct sock * | ||
386 | inet_lookup_established(struct inet_hashinfo *hashinfo, | ||
387 | const __be32 saddr, const __be16 sport, | ||
388 | const __be32 daddr, const __be16 dport, | ||
389 | const int dif) | ||
390 | { | ||
391 | return __inet_lookup_established(hashinfo, saddr, sport, daddr, | ||
392 | ntohs(dport), dif); | ||
393 | } | ||
394 | |||
394 | static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo, | 395 | static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo, |
395 | const u32 saddr, const u16 sport, | 396 | const __be32 saddr, const __be16 sport, |
396 | const u32 daddr, const u16 hnum, | 397 | const __be32 daddr, const __be16 dport, |
397 | const int dif) | 398 | const int dif) |
398 | { | 399 | { |
400 | u16 hnum = ntohs(dport); | ||
399 | struct sock *sk = __inet_lookup_established(hashinfo, saddr, sport, daddr, | 401 | struct sock *sk = __inet_lookup_established(hashinfo, saddr, sport, daddr, |
400 | hnum, dif); | 402 | hnum, dif); |
401 | return sk ? : inet_lookup_listener(hashinfo, daddr, hnum, dif); | 403 | return sk ? : __inet_lookup_listener(hashinfo, daddr, hnum, dif); |
402 | } | 404 | } |
403 | 405 | ||
404 | static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo, | 406 | static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo, |
405 | const u32 saddr, const u16 sport, | 407 | const __be32 saddr, const __be16 sport, |
406 | const u32 daddr, const u16 dport, | 408 | const __be32 daddr, const __be16 dport, |
407 | const int dif) | 409 | const int dif) |
408 | { | 410 | { |
409 | struct sock *sk; | 411 | struct sock *sk; |
410 | 412 | ||
411 | local_bh_disable(); | 413 | local_bh_disable(); |
412 | sk = __inet_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif); | 414 | sk = __inet_lookup(hashinfo, saddr, sport, daddr, dport, dif); |
413 | local_bh_enable(); | 415 | local_bh_enable(); |
414 | 416 | ||
415 | return sk; | 417 | return sk; |