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; |
