diff options
author | Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | 2005-08-09 23:09:46 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:42:18 -0400 |
commit | e48c414ee61f4ac8d5cff2973e66a7cbc8a93aa5 (patch) | |
tree | c4656efe48b75adf5742514c3e4286007f20bdca /include/net | |
parent | 8feaf0c0a5488b3d898a9c207eb6678f44ba3f26 (diff) |
[INET]: Generalise the TCP sock ID lookup routines
And also some TIME_WAIT functions.
[acme@toy net-2.6.14]$ grep built-in /tmp/before.size /tmp/after.size
/tmp/before.size: 282955 13122 9312 305389 4a8ed net/ipv4/built-in.o
/tmp/after.size: 281566 13122 9312 304000 4a380 net/ipv4/built-in.o
[acme@toy net-2.6.14]$
I kept them still inlined, will uninline at some point to see what
would be the performance difference.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net')
-rw-r--r-- | include/net/inet_hashtables.h | 77 | ||||
-rw-r--r-- | include/net/inet_timewait_sock.h | 9 | ||||
-rw-r--r-- | include/net/sock.h | 12 |
3 files changed, 87 insertions, 11 deletions
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index c38c637e0734..b5c0d64ea741 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <net/tcp_states.h> | 30 | #include <net/tcp_states.h> |
31 | 31 | ||
32 | #include <asm/atomic.h> | 32 | #include <asm/atomic.h> |
33 | #include <asm/byteorder.h> | ||
33 | 34 | ||
34 | /* This is for all connections with a full identity, no wildcards. | 35 | /* This is for all connections with a full identity, no wildcards. |
35 | * New scheme, half the table is for TIME_WAIT, the other half is | 36 | * New scheme, half the table is for TIME_WAIT, the other half is |
@@ -285,13 +286,13 @@ extern struct sock *__inet_lookup_listener(const struct hlist_head *head, | |||
285 | const int dif); | 286 | const int dif); |
286 | 287 | ||
287 | /* Optimize the common listener case. */ | 288 | /* Optimize the common listener case. */ |
288 | static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo, | 289 | static inline struct sock * |
289 | const u32 daddr, | 290 | inet_lookup_listener(struct inet_hashinfo *hashinfo, |
290 | const unsigned short hnum, | 291 | const u32 daddr, |
291 | const int dif) | 292 | const unsigned short hnum, const int dif) |
292 | { | 293 | { |
293 | struct sock *sk = NULL; | 294 | struct sock *sk = NULL; |
294 | struct hlist_head *head; | 295 | const struct hlist_head *head; |
295 | 296 | ||
296 | read_lock(&hashinfo->lhash_lock); | 297 | read_lock(&hashinfo->lhash_lock); |
297 | head = &hashinfo->listening_hash[inet_lhashfn(hnum)]; | 298 | head = &hashinfo->listening_hash[inet_lhashfn(hnum)]; |
@@ -351,4 +352,70 @@ sherry_cache: | |||
351 | ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ | 352 | ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ |
352 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) | 353 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) |
353 | #endif /* 64-bit arch */ | 354 | #endif /* 64-bit arch */ |
355 | |||
356 | /* | ||
357 | * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so we need | ||
358 | * not check it for lookups anymore, thanks Alexey. -DaveM | ||
359 | * | ||
360 | * Local BH must be disabled here. | ||
361 | */ | ||
362 | static inline struct sock * | ||
363 | __inet_lookup_established(struct inet_hashinfo *hashinfo, | ||
364 | const u32 saddr, const u16 sport, | ||
365 | const u32 daddr, const u16 hnum, | ||
366 | const int dif) | ||
367 | { | ||
368 | INET_ADDR_COOKIE(acookie, saddr, daddr) | ||
369 | const __u32 ports = INET_COMBINED_PORTS(sport, hnum); | ||
370 | struct sock *sk; | ||
371 | const struct hlist_node *node; | ||
372 | /* Optimize here for direct hit, only listening connections can | ||
373 | * have wildcards anyways. | ||
374 | */ | ||
375 | const int hash = inet_ehashfn(daddr, hnum, saddr, sport, hashinfo->ehash_size); | ||
376 | struct inet_ehash_bucket *head = &hashinfo->ehash[hash]; | ||
377 | |||
378 | read_lock(&head->lock); | ||
379 | sk_for_each(sk, node, &head->chain) { | ||
380 | if (INET_MATCH(sk, acookie, saddr, daddr, ports, dif)) | ||
381 | goto hit; /* You sunk my battleship! */ | ||
382 | } | ||
383 | |||
384 | /* Must check for a TIME_WAIT'er before going to listener hash. */ | ||
385 | sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) { | ||
386 | if (INET_TW_MATCH(sk, acookie, saddr, daddr, ports, dif)) | ||
387 | goto hit; | ||
388 | } | ||
389 | sk = NULL; | ||
390 | out: | ||
391 | read_unlock(&head->lock); | ||
392 | return sk; | ||
393 | hit: | ||
394 | sock_hold(sk); | ||
395 | goto out; | ||
396 | } | ||
397 | |||
398 | static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo, | ||
399 | const u32 saddr, const u16 sport, | ||
400 | const u32 daddr, const u16 hnum, | ||
401 | const int dif) | ||
402 | { | ||
403 | struct sock *sk = __inet_lookup_established(hashinfo, saddr, sport, daddr, | ||
404 | hnum, dif); | ||
405 | return sk ? : inet_lookup_listener(hashinfo, daddr, hnum, dif); | ||
406 | } | ||
407 | |||
408 | static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo, | ||
409 | const u32 saddr, const u16 sport, | ||
410 | const u32 daddr, const u16 dport, | ||
411 | const int dif) | ||
412 | { | ||
413 | struct sock *sk; | ||
414 | |||
415 | local_bh_disable(); | ||
416 | sk = __inet_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif); | ||
417 | local_bh_enable(); | ||
418 | |||
419 | return sk; | ||
420 | } | ||
354 | #endif /* _INET_HASHTABLES_H */ | 421 | #endif /* _INET_HASHTABLES_H */ |
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index ce117048f2fd..020f28058fd4 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/config.h> | 18 | #include <linux/config.h> |
19 | 19 | ||
20 | #include <linux/ip.h> | ||
20 | #include <linux/list.h> | 21 | #include <linux/list.h> |
21 | #include <linux/types.h> | 22 | #include <linux/types.h> |
22 | 23 | ||
@@ -32,6 +33,7 @@ | |||
32 | #endif | 33 | #endif |
33 | 34 | ||
34 | struct inet_bind_bucket; | 35 | struct inet_bind_bucket; |
36 | struct inet_hashinfo; | ||
35 | 37 | ||
36 | /* | 38 | /* |
37 | * This is a TIME_WAIT sock. It works around the memory consumption | 39 | * This is a TIME_WAIT sock. It works around the memory consumption |
@@ -139,4 +141,11 @@ static inline void inet_twsk_put(struct inet_timewait_sock *tw) | |||
139 | kmem_cache_free(tw->tw_prot->twsk_slab, tw); | 141 | kmem_cache_free(tw->tw_prot->twsk_slab, tw); |
140 | } | 142 | } |
141 | } | 143 | } |
144 | |||
145 | extern void __inet_twsk_kill(struct inet_timewait_sock *tw, | ||
146 | struct inet_hashinfo *hashinfo); | ||
147 | |||
148 | extern void __inet_twsk_hashdance(struct inet_timewait_sock *tw, | ||
149 | struct sock *sk, | ||
150 | struct inet_hashinfo *hashinfo); | ||
142 | #endif /* _INET_TIMEWAIT_SOCK_ */ | 151 | #endif /* _INET_TIMEWAIT_SOCK_ */ |
diff --git a/include/net/sock.h b/include/net/sock.h index c902c57bf2b7..bdae0a5eadf5 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -255,28 +255,28 @@ struct sock { | |||
255 | /* | 255 | /* |
256 | * Hashed lists helper routines | 256 | * Hashed lists helper routines |
257 | */ | 257 | */ |
258 | static inline struct sock *__sk_head(struct hlist_head *head) | 258 | static inline struct sock *__sk_head(const struct hlist_head *head) |
259 | { | 259 | { |
260 | return hlist_entry(head->first, struct sock, sk_node); | 260 | return hlist_entry(head->first, struct sock, sk_node); |
261 | } | 261 | } |
262 | 262 | ||
263 | static inline struct sock *sk_head(struct hlist_head *head) | 263 | static inline struct sock *sk_head(const struct hlist_head *head) |
264 | { | 264 | { |
265 | return hlist_empty(head) ? NULL : __sk_head(head); | 265 | return hlist_empty(head) ? NULL : __sk_head(head); |
266 | } | 266 | } |
267 | 267 | ||
268 | static inline struct sock *sk_next(struct sock *sk) | 268 | static inline struct sock *sk_next(const struct sock *sk) |
269 | { | 269 | { |
270 | return sk->sk_node.next ? | 270 | return sk->sk_node.next ? |
271 | hlist_entry(sk->sk_node.next, struct sock, sk_node) : NULL; | 271 | hlist_entry(sk->sk_node.next, struct sock, sk_node) : NULL; |
272 | } | 272 | } |
273 | 273 | ||
274 | static inline int sk_unhashed(struct sock *sk) | 274 | static inline int sk_unhashed(const struct sock *sk) |
275 | { | 275 | { |
276 | return hlist_unhashed(&sk->sk_node); | 276 | return hlist_unhashed(&sk->sk_node); |
277 | } | 277 | } |
278 | 278 | ||
279 | static inline int sk_hashed(struct sock *sk) | 279 | static inline int sk_hashed(const struct sock *sk) |
280 | { | 280 | { |
281 | return sk->sk_node.pprev != NULL; | 281 | return sk->sk_node.pprev != NULL; |
282 | } | 282 | } |
@@ -494,7 +494,7 @@ extern int sk_wait_data(struct sock *sk, long *timeo); | |||
494 | struct request_sock_ops; | 494 | struct request_sock_ops; |
495 | 495 | ||
496 | /* Here is the right place to enable sock refcounting debugging */ | 496 | /* Here is the right place to enable sock refcounting debugging */ |
497 | #define SOCK_REFCNT_DEBUG | 497 | //#define SOCK_REFCNT_DEBUG |
498 | 498 | ||
499 | /* Networking protocol blocks we attach to sockets. | 499 | /* Networking protocol blocks we attach to sockets. |
500 | * socket layer -> transport layer interface | 500 | * socket layer -> transport layer interface |