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.h68
1 files changed, 39 insertions, 29 deletions
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 646b6ea7fe26..07840baa9341 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -40,7 +40,7 @@
40struct inet_ehash_bucket { 40struct inet_ehash_bucket {
41 rwlock_t lock; 41 rwlock_t lock;
42 struct hlist_head chain; 42 struct hlist_head chain;
43} __attribute__((__aligned__(8))); 43};
44 44
45/* There are a few simple rules, which allow for local port reuse by 45/* There are a few simple rules, which allow for local port reuse by
46 * an application. In essence: 46 * an application. In essence:
@@ -108,7 +108,7 @@ struct inet_hashinfo {
108 struct inet_bind_hashbucket *bhash; 108 struct inet_bind_hashbucket *bhash;
109 109
110 int bhash_size; 110 int bhash_size;
111 int ehash_size; 111 unsigned int ehash_size;
112 112
113 /* All sockets in TCP_LISTEN state will be in here. This is the only 113 /* All sockets in TCP_LISTEN state will be in here. This is the only
114 * table where wildcard'd TCP sockets can exist. Hash function here 114 * table where wildcard'd TCP sockets can exist. Hash function here
@@ -125,22 +125,19 @@ struct inet_hashinfo {
125 rwlock_t lhash_lock ____cacheline_aligned; 125 rwlock_t lhash_lock ____cacheline_aligned;
126 atomic_t lhash_users; 126 atomic_t lhash_users;
127 wait_queue_head_t lhash_wait; 127 wait_queue_head_t lhash_wait;
128 spinlock_t portalloc_lock;
129 kmem_cache_t *bind_bucket_cachep; 128 kmem_cache_t *bind_bucket_cachep;
130 int port_rover;
131}; 129};
132 130
133static inline int inet_ehashfn(const __u32 laddr, const __u16 lport, 131static inline unsigned int inet_ehashfn(const __u32 laddr, const __u16 lport,
134 const __u32 faddr, const __u16 fport, 132 const __u32 faddr, const __u16 fport)
135 const int ehash_size)
136{ 133{
137 int h = (laddr ^ lport) ^ (faddr ^ fport); 134 unsigned int h = (laddr ^ lport) ^ (faddr ^ fport);
138 h ^= h >> 16; 135 h ^= h >> 16;
139 h ^= h >> 8; 136 h ^= h >> 8;
140 return h & (ehash_size - 1); 137 return h;
141} 138}
142 139
143static inline int inet_sk_ehashfn(const struct sock *sk, const int ehash_size) 140static inline int inet_sk_ehashfn(const struct sock *sk)
144{ 141{
145 const struct inet_sock *inet = inet_sk(sk); 142 const struct inet_sock *inet = inet_sk(sk);
146 const __u32 laddr = inet->rcv_saddr; 143 const __u32 laddr = inet->rcv_saddr;
@@ -148,7 +145,14 @@ static inline int inet_sk_ehashfn(const struct sock *sk, const int ehash_size)
148 const __u32 faddr = inet->daddr; 145 const __u32 faddr = inet->daddr;
149 const __u16 fport = inet->dport; 146 const __u16 fport = inet->dport;
150 147
151 return inet_ehashfn(laddr, lport, faddr, fport, ehash_size); 148 return inet_ehashfn(laddr, lport, faddr, fport);
149}
150
151static inline struct inet_ehash_bucket *inet_ehash_bucket(
152 struct inet_hashinfo *hashinfo,
153 unsigned int hash)
154{
155 return &hashinfo->ehash[hash & (hashinfo->ehash_size - 1)];
152} 156}
153 157
154extern struct inet_bind_bucket * 158extern struct inet_bind_bucket *
@@ -235,9 +239,11 @@ static inline void __inet_hash(struct inet_hashinfo *hashinfo,
235 lock = &hashinfo->lhash_lock; 239 lock = &hashinfo->lhash_lock;
236 inet_listen_wlock(hashinfo); 240 inet_listen_wlock(hashinfo);
237 } else { 241 } else {
238 sk->sk_hashent = inet_sk_ehashfn(sk, hashinfo->ehash_size); 242 struct inet_ehash_bucket *head;
239 list = &hashinfo->ehash[sk->sk_hashent].chain; 243 sk->sk_hash = inet_sk_ehashfn(sk);
240 lock = &hashinfo->ehash[sk->sk_hashent].lock; 244 head = inet_ehash_bucket(hashinfo, sk->sk_hash);
245 list = &head->chain;
246 lock = &head->lock;
241 write_lock(lock); 247 write_lock(lock);
242 } 248 }
243 __sk_add_node(sk, list); 249 __sk_add_node(sk, list);
@@ -268,9 +274,8 @@ static inline void inet_unhash(struct inet_hashinfo *hashinfo, struct sock *sk)
268 inet_listen_wlock(hashinfo); 274 inet_listen_wlock(hashinfo);
269 lock = &hashinfo->lhash_lock; 275 lock = &hashinfo->lhash_lock;
270 } else { 276 } else {
271 struct inet_ehash_bucket *head = &hashinfo->ehash[sk->sk_hashent]; 277 lock = &inet_ehash_bucket(hashinfo, sk->sk_hash)->lock;
272 lock = &head->lock; 278 write_lock_bh(lock);
273 write_lock_bh(&head->lock);
274 } 279 }
275 280
276 if (__sk_del_node_init(sk)) 281 if (__sk_del_node_init(sk))
@@ -337,23 +342,27 @@ sherry_cache:
337#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ 342#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
338 const __u64 __name = (((__u64)(__daddr)) << 32) | ((__u64)(__saddr)); 343 const __u64 __name = (((__u64)(__daddr)) << 32) | ((__u64)(__saddr));
339#endif /* __BIG_ENDIAN */ 344#endif /* __BIG_ENDIAN */
340#define INET_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\ 345#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
341 (((*((__u64 *)&(inet_sk(__sk)->daddr))) == (__cookie)) && \ 346 (((__sk)->sk_hash == (__hash)) && \
347 ((*((__u64 *)&(inet_sk(__sk)->daddr))) == (__cookie)) && \
342 ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \ 348 ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \
343 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) 349 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
344#define INET_TW_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\ 350#define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
345 (((*((__u64 *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \ 351 (((__sk)->sk_hash == (__hash)) && \
352 ((*((__u64 *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \
346 ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ 353 ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \
347 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) 354 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
348#else /* 32-bit arch */ 355#else /* 32-bit arch */
349#define INET_ADDR_COOKIE(__name, __saddr, __daddr) 356#define INET_ADDR_COOKIE(__name, __saddr, __daddr)
350#define INET_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif) \ 357#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif) \
351 ((inet_sk(__sk)->daddr == (__saddr)) && \ 358 (((__sk)->sk_hash == (__hash)) && \
359 (inet_sk(__sk)->daddr == (__saddr)) && \
352 (inet_sk(__sk)->rcv_saddr == (__daddr)) && \ 360 (inet_sk(__sk)->rcv_saddr == (__daddr)) && \
353 ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \ 361 ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \
354 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) 362 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
355#define INET_TW_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif) \ 363#define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif) \
356 ((inet_twsk(__sk)->tw_daddr == (__saddr)) && \ 364 (((__sk)->sk_hash == (__hash)) && \
365 (inet_twsk(__sk)->tw_daddr == (__saddr)) && \
357 (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \ 366 (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \
358 ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ 367 ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \
359 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) 368 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
@@ -378,18 +387,19 @@ static inline struct sock *
378 /* Optimize here for direct hit, only listening connections can 387 /* Optimize here for direct hit, only listening connections can
379 * have wildcards anyways. 388 * have wildcards anyways.
380 */ 389 */
381 const int hash = inet_ehashfn(daddr, hnum, saddr, sport, hashinfo->ehash_size); 390 unsigned int hash = inet_ehashfn(daddr, hnum, saddr, sport);
382 struct inet_ehash_bucket *head = &hashinfo->ehash[hash]; 391 struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
383 392
393 prefetch(head->chain.first);
384 read_lock(&head->lock); 394 read_lock(&head->lock);
385 sk_for_each(sk, node, &head->chain) { 395 sk_for_each(sk, node, &head->chain) {
386 if (INET_MATCH(sk, acookie, saddr, daddr, ports, dif)) 396 if (INET_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
387 goto hit; /* You sunk my battleship! */ 397 goto hit; /* You sunk my battleship! */
388 } 398 }
389 399
390 /* Must check for a TIME_WAIT'er before going to listener hash. */ 400 /* Must check for a TIME_WAIT'er before going to listener hash. */
391 sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) { 401 sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
392 if (INET_TW_MATCH(sk, acookie, saddr, daddr, ports, dif)) 402 if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
393 goto hit; 403 goto hit;
394 } 404 }
395 sk = NULL; 405 sk = NULL;