aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/inet_hashtables.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/inet_hashtables.h')
-rw-r--r--include/net/inet_hashtables.h96
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
274extern struct sock *__inet_lookup_listener(const struct hlist_head *head, 274extern 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. */ 279static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo,
280static 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) {
301sherry_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*/
294typedef __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)
304typedef __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 */
357static inline struct sock * 348static 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
385static 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
394static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo, 395static 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
404static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo, 406static 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;