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 | |
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>
-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 | ||||
-rw-r--r-- | net/ipv4/Makefile | 1 | ||||
-rw-r--r-- | net/ipv4/inet_hashtables.c | 2 | ||||
-rw-r--r-- | net/ipv4/inet_timewait_sock.c | 83 | ||||
-rw-r--r-- | net/ipv4/tcp_diag.c | 8 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 83 | ||||
-rw-r--r-- | net/ipv4/tcp_minisocks.c | 78 |
9 files changed, 188 insertions, 165 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 |
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 2d8d30e83eb0..6650d18e400f 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | obj-y := route.o inetpeer.o protocol.o \ | 5 | obj-y := route.o inetpeer.o protocol.o \ |
6 | ip_input.o ip_fragment.o ip_forward.o ip_options.o \ | 6 | ip_input.o ip_fragment.o ip_forward.o ip_options.o \ |
7 | ip_output.o ip_sockglue.o inet_hashtables.o \ | 7 | ip_output.o ip_sockglue.o inet_hashtables.o \ |
8 | inet_timewait_sock.o \ | ||
8 | tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \ | 9 | tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \ |
9 | tcp_minisocks.o tcp_cong.o \ | 10 | tcp_minisocks.o tcp_cong.o \ |
10 | datagram.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \ | 11 | datagram.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \ |
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 88fcba05b7d6..d94e962958a4 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
@@ -162,3 +162,5 @@ struct sock *__inet_lookup_listener(const struct hlist_head *head, const u32 dad | |||
162 | } | 162 | } |
163 | return result; | 163 | return result; |
164 | } | 164 | } |
165 | |||
166 | EXPORT_SYMBOL_GPL(__inet_lookup_listener); | ||
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c new file mode 100644 index 000000000000..d38d160faeb7 --- /dev/null +++ b/net/ipv4/inet_timewait_sock.c | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * INET An implementation of the TCP/IP protocol suite for the LINUX | ||
3 | * operating system. INET is implemented using the BSD Socket | ||
4 | * interface as the means of communication with the user level. | ||
5 | * | ||
6 | * Generic TIME_WAIT sockets functions | ||
7 | * | ||
8 | * From code orinally in TCP | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | |||
13 | #include <net/inet_hashtables.h> | ||
14 | #include <net/inet_timewait_sock.h> | ||
15 | |||
16 | /* Must be called with locally disabled BHs. */ | ||
17 | void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashinfo) | ||
18 | { | ||
19 | struct inet_bind_hashbucket *bhead; | ||
20 | struct inet_bind_bucket *tb; | ||
21 | /* Unlink from established hashes. */ | ||
22 | struct inet_ehash_bucket *ehead = &hashinfo->ehash[tw->tw_hashent]; | ||
23 | |||
24 | write_lock(&ehead->lock); | ||
25 | if (hlist_unhashed(&tw->tw_node)) { | ||
26 | write_unlock(&ehead->lock); | ||
27 | return; | ||
28 | } | ||
29 | __hlist_del(&tw->tw_node); | ||
30 | sk_node_init(&tw->tw_node); | ||
31 | write_unlock(&ehead->lock); | ||
32 | |||
33 | /* Disassociate with bind bucket. */ | ||
34 | bhead = &hashinfo->bhash[inet_bhashfn(tw->tw_num, hashinfo->bhash_size)]; | ||
35 | spin_lock(&bhead->lock); | ||
36 | tb = tw->tw_tb; | ||
37 | __hlist_del(&tw->tw_bind_node); | ||
38 | tw->tw_tb = NULL; | ||
39 | inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb); | ||
40 | spin_unlock(&bhead->lock); | ||
41 | #ifdef SOCK_REFCNT_DEBUG | ||
42 | if (atomic_read(&tw->tw_refcnt) != 1) { | ||
43 | printk(KERN_DEBUG "%s timewait_sock %p refcnt=%d\n", | ||
44 | tw->tw_prot->name, tw, atomic_read(&tw->tw_refcnt)); | ||
45 | } | ||
46 | #endif | ||
47 | inet_twsk_put(tw); | ||
48 | } | ||
49 | |||
50 | /* | ||
51 | * Enter the time wait state. This is called with locally disabled BH. | ||
52 | * Essentially we whip up a timewait bucket, copy the relevant info into it | ||
53 | * from the SK, and mess with hash chains and list linkage. | ||
54 | */ | ||
55 | void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, | ||
56 | struct inet_hashinfo *hashinfo) | ||
57 | { | ||
58 | const struct inet_sock *inet = inet_sk(sk); | ||
59 | struct inet_ehash_bucket *ehead = &hashinfo->ehash[sk->sk_hashent]; | ||
60 | struct inet_bind_hashbucket *bhead; | ||
61 | /* Step 1: Put TW into bind hash. Original socket stays there too. | ||
62 | Note, that any socket with inet->num != 0 MUST be bound in | ||
63 | binding cache, even if it is closed. | ||
64 | */ | ||
65 | bhead = &hashinfo->bhash[inet_bhashfn(inet->num, hashinfo->bhash_size)]; | ||
66 | spin_lock(&bhead->lock); | ||
67 | tw->tw_tb = inet->bind_hash; | ||
68 | BUG_TRAP(inet->bind_hash); | ||
69 | inet_twsk_add_bind_node(tw, &tw->tw_tb->owners); | ||
70 | spin_unlock(&bhead->lock); | ||
71 | |||
72 | write_lock(&ehead->lock); | ||
73 | |||
74 | /* Step 2: Remove SK from established hash. */ | ||
75 | if (__sk_del_node_init(sk)) | ||
76 | sock_prot_dec_use(sk->sk_prot); | ||
77 | |||
78 | /* Step 3: Hash TW into TIMEWAIT half of established hash table. */ | ||
79 | inet_twsk_add_node(tw, &(ehead + hashinfo->ehash_size)->chain); | ||
80 | atomic_inc(&tw->tw_refcnt); | ||
81 | |||
82 | write_unlock(&ehead->lock); | ||
83 | } | ||
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c index 6f2d6f2276b9..60c6a797cc50 100644 --- a/net/ipv4/tcp_diag.c +++ b/net/ipv4/tcp_diag.c | |||
@@ -174,8 +174,6 @@ nlmsg_failure: | |||
174 | return -1; | 174 | return -1; |
175 | } | 175 | } |
176 | 176 | ||
177 | extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, | ||
178 | int dif); | ||
179 | #ifdef CONFIG_IP_TCPDIAG_IPV6 | 177 | #ifdef CONFIG_IP_TCPDIAG_IPV6 |
180 | extern struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport, | 178 | extern struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport, |
181 | struct in6_addr *daddr, u16 dport, | 179 | struct in6_addr *daddr, u16 dport, |
@@ -197,9 +195,9 @@ static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) | |||
197 | struct sk_buff *rep; | 195 | struct sk_buff *rep; |
198 | 196 | ||
199 | if (req->tcpdiag_family == AF_INET) { | 197 | if (req->tcpdiag_family == AF_INET) { |
200 | sk = tcp_v4_lookup(req->id.tcpdiag_dst[0], req->id.tcpdiag_dport, | 198 | sk = inet_lookup(&tcp_hashinfo, req->id.tcpdiag_dst[0], |
201 | req->id.tcpdiag_src[0], req->id.tcpdiag_sport, | 199 | req->id.tcpdiag_dport, req->id.tcpdiag_src[0], |
202 | req->id.tcpdiag_if); | 200 | req->id.tcpdiag_sport, req->id.tcpdiag_if); |
203 | } | 201 | } |
204 | #ifdef CONFIG_IP_TCPDIAG_IPV6 | 202 | #ifdef CONFIG_IP_TCPDIAG_IPV6 |
205 | else if (req->tcpdiag_family == AF_INET6) { | 203 | else if (req->tcpdiag_family == AF_INET6) { |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ce423e48ebe0..e7e91e60ac74 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -238,71 +238,6 @@ void tcp_unhash(struct sock *sk) | |||
238 | inet_unhash(&tcp_hashinfo, sk); | 238 | inet_unhash(&tcp_hashinfo, sk); |
239 | } | 239 | } |
240 | 240 | ||
241 | /* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so | ||
242 | * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM | ||
243 | * | ||
244 | * Local BH must be disabled here. | ||
245 | */ | ||
246 | |||
247 | static inline struct sock *__tcp_v4_lookup_established(const u32 saddr, | ||
248 | const u16 sport, | ||
249 | const u32 daddr, | ||
250 | const u16 hnum, | ||
251 | const int dif) | ||
252 | { | ||
253 | struct inet_ehash_bucket *head; | ||
254 | INET_ADDR_COOKIE(acookie, saddr, daddr) | ||
255 | const __u32 ports = INET_COMBINED_PORTS(sport, hnum); | ||
256 | struct sock *sk; | ||
257 | const struct hlist_node *node; | ||
258 | /* Optimize here for direct hit, only listening connections can | ||
259 | * have wildcards anyways. | ||
260 | */ | ||
261 | const int hash = inet_ehashfn(daddr, hnum, saddr, sport, tcp_hashinfo.ehash_size); | ||
262 | head = &tcp_hashinfo.ehash[hash]; | ||
263 | read_lock(&head->lock); | ||
264 | sk_for_each(sk, node, &head->chain) { | ||
265 | if (INET_MATCH(sk, acookie, saddr, daddr, ports, dif)) | ||
266 | goto hit; /* You sunk my battleship! */ | ||
267 | } | ||
268 | |||
269 | /* Must check for a TIME_WAIT'er before going to listener hash. */ | ||
270 | sk_for_each(sk, node, &(head + tcp_hashinfo.ehash_size)->chain) { | ||
271 | if (INET_TW_MATCH(sk, acookie, saddr, daddr, ports, dif)) | ||
272 | goto hit; | ||
273 | } | ||
274 | sk = NULL; | ||
275 | out: | ||
276 | read_unlock(&head->lock); | ||
277 | return sk; | ||
278 | hit: | ||
279 | sock_hold(sk); | ||
280 | goto out; | ||
281 | } | ||
282 | |||
283 | static inline struct sock *__tcp_v4_lookup(u32 saddr, u16 sport, | ||
284 | u32 daddr, u16 hnum, int dif) | ||
285 | { | ||
286 | struct sock *sk = __tcp_v4_lookup_established(saddr, sport, | ||
287 | daddr, hnum, dif); | ||
288 | |||
289 | return sk ? : inet_lookup_listener(&tcp_hashinfo, daddr, hnum, dif); | ||
290 | } | ||
291 | |||
292 | inline struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, | ||
293 | u16 dport, int dif) | ||
294 | { | ||
295 | struct sock *sk; | ||
296 | |||
297 | local_bh_disable(); | ||
298 | sk = __tcp_v4_lookup(saddr, sport, daddr, ntohs(dport), dif); | ||
299 | local_bh_enable(); | ||
300 | |||
301 | return sk; | ||
302 | } | ||
303 | |||
304 | EXPORT_SYMBOL_GPL(tcp_v4_lookup); | ||
305 | |||
306 | static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb) | 241 | static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb) |
307 | { | 242 | { |
308 | return secure_tcp_sequence_number(skb->nh.iph->daddr, | 243 | return secure_tcp_sequence_number(skb->nh.iph->daddr, |
@@ -751,8 +686,8 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) | |||
751 | return; | 686 | return; |
752 | } | 687 | } |
753 | 688 | ||
754 | sk = tcp_v4_lookup(iph->daddr, th->dest, iph->saddr, | 689 | sk = inet_lookup(&tcp_hashinfo, iph->daddr, th->dest, iph->saddr, |
755 | th->source, tcp_v4_iif(skb)); | 690 | th->source, tcp_v4_iif(skb)); |
756 | if (!sk) { | 691 | if (!sk) { |
757 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); | 692 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); |
758 | return; | 693 | return; |
@@ -1359,11 +1294,9 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
1359 | if (req) | 1294 | if (req) |
1360 | return tcp_check_req(sk, skb, req, prev); | 1295 | return tcp_check_req(sk, skb, req, prev); |
1361 | 1296 | ||
1362 | nsk = __tcp_v4_lookup_established(skb->nh.iph->saddr, | 1297 | nsk = __inet_lookup_established(&tcp_hashinfo, skb->nh.iph->saddr, |
1363 | th->source, | 1298 | th->source, skb->nh.iph->daddr, |
1364 | skb->nh.iph->daddr, | 1299 | ntohs(th->dest), tcp_v4_iif(skb)); |
1365 | ntohs(th->dest), | ||
1366 | tcp_v4_iif(skb)); | ||
1367 | 1300 | ||
1368 | if (nsk) { | 1301 | if (nsk) { |
1369 | if (nsk->sk_state != TCP_TIME_WAIT) { | 1302 | if (nsk->sk_state != TCP_TIME_WAIT) { |
@@ -1505,9 +1438,9 @@ int tcp_v4_rcv(struct sk_buff *skb) | |||
1505 | TCP_SKB_CB(skb)->flags = skb->nh.iph->tos; | 1438 | TCP_SKB_CB(skb)->flags = skb->nh.iph->tos; |
1506 | TCP_SKB_CB(skb)->sacked = 0; | 1439 | TCP_SKB_CB(skb)->sacked = 0; |
1507 | 1440 | ||
1508 | sk = __tcp_v4_lookup(skb->nh.iph->saddr, th->source, | 1441 | sk = __inet_lookup(&tcp_hashinfo, skb->nh.iph->saddr, th->source, |
1509 | skb->nh.iph->daddr, ntohs(th->dest), | 1442 | skb->nh.iph->daddr, ntohs(th->dest), |
1510 | tcp_v4_iif(skb)); | 1443 | tcp_v4_iif(skb)); |
1511 | 1444 | ||
1512 | if (!sk) | 1445 | if (!sk) |
1513 | goto no_tcp_socket; | 1446 | goto no_tcp_socket; |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 5b5a49335fbb..4112f7a6d108 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -56,42 +56,6 @@ static __inline__ int tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win) | |||
56 | 56 | ||
57 | int tcp_tw_count; | 57 | int tcp_tw_count; |
58 | 58 | ||
59 | |||
60 | /* Must be called with locally disabled BHs. */ | ||
61 | static void tcp_timewait_kill(struct inet_timewait_sock *tw) | ||
62 | { | ||
63 | struct inet_bind_hashbucket *bhead; | ||
64 | struct inet_bind_bucket *tb; | ||
65 | /* Unlink from established hashes. */ | ||
66 | struct inet_ehash_bucket *ehead = &tcp_hashinfo.ehash[tw->tw_hashent]; | ||
67 | |||
68 | write_lock(&ehead->lock); | ||
69 | if (hlist_unhashed(&tw->tw_node)) { | ||
70 | write_unlock(&ehead->lock); | ||
71 | return; | ||
72 | } | ||
73 | __hlist_del(&tw->tw_node); | ||
74 | sk_node_init(&tw->tw_node); | ||
75 | write_unlock(&ehead->lock); | ||
76 | |||
77 | /* Disassociate with bind bucket. */ | ||
78 | bhead = &tcp_hashinfo.bhash[inet_bhashfn(tw->tw_num, tcp_hashinfo.bhash_size)]; | ||
79 | spin_lock(&bhead->lock); | ||
80 | tb = tw->tw_tb; | ||
81 | __hlist_del(&tw->tw_bind_node); | ||
82 | tw->tw_tb = NULL; | ||
83 | inet_bind_bucket_destroy(tcp_hashinfo.bind_bucket_cachep, tb); | ||
84 | spin_unlock(&bhead->lock); | ||
85 | |||
86 | #ifdef SOCK_REFCNT_DEBUG | ||
87 | if (atomic_read(&tw->tw_refcnt) != 1) { | ||
88 | printk(KERN_DEBUG "%s timewait_sock %p refcnt=%d\n", | ||
89 | tw->tw_prot->name, tw, atomic_read(&tw->tw_refcnt)); | ||
90 | } | ||
91 | #endif | ||
92 | inet_twsk_put(tw); | ||
93 | } | ||
94 | |||
95 | /* | 59 | /* |
96 | * * Main purpose of TIME-WAIT state is to close connection gracefully, | 60 | * * Main purpose of TIME-WAIT state is to close connection gracefully, |
97 | * when one of ends sits in LAST-ACK or CLOSING retransmitting FIN | 61 | * when one of ends sits in LAST-ACK or CLOSING retransmitting FIN |
@@ -290,40 +254,6 @@ kill: | |||
290 | return TCP_TW_SUCCESS; | 254 | return TCP_TW_SUCCESS; |
291 | } | 255 | } |
292 | 256 | ||
293 | /* Enter the time wait state. This is called with locally disabled BH. | ||
294 | * Essentially we whip up a timewait bucket, copy the | ||
295 | * relevant info into it from the SK, and mess with hash chains | ||
296 | * and list linkage. | ||
297 | */ | ||
298 | static void __tcp_tw_hashdance(struct sock *sk, struct inet_timewait_sock *tw) | ||
299 | { | ||
300 | const struct inet_sock *inet = inet_sk(sk); | ||
301 | struct inet_ehash_bucket *ehead = &tcp_hashinfo.ehash[sk->sk_hashent]; | ||
302 | struct inet_bind_hashbucket *bhead; | ||
303 | /* Step 1: Put TW into bind hash. Original socket stays there too. | ||
304 | Note, that any socket with inet->num != 0 MUST be bound in | ||
305 | binding cache, even if it is closed. | ||
306 | */ | ||
307 | bhead = &tcp_hashinfo.bhash[inet_bhashfn(inet->num, tcp_hashinfo.bhash_size)]; | ||
308 | spin_lock(&bhead->lock); | ||
309 | tw->tw_tb = inet->bind_hash; | ||
310 | BUG_TRAP(inet->bind_hash); | ||
311 | inet_twsk_add_bind_node(tw, &tw->tw_tb->owners); | ||
312 | spin_unlock(&bhead->lock); | ||
313 | |||
314 | write_lock(&ehead->lock); | ||
315 | |||
316 | /* Step 2: Remove SK from established hash. */ | ||
317 | if (__sk_del_node_init(sk)) | ||
318 | sock_prot_dec_use(sk->sk_prot); | ||
319 | |||
320 | /* Step 3: Hash TW into TIMEWAIT half of established hash table. */ | ||
321 | inet_twsk_add_node(tw, &(ehead + tcp_hashinfo.ehash_size)->chain); | ||
322 | atomic_inc(&tw->tw_refcnt); | ||
323 | |||
324 | write_unlock(&ehead->lock); | ||
325 | } | ||
326 | |||
327 | /* | 257 | /* |
328 | * Move a socket to time-wait or dead fin-wait-2 state. | 258 | * Move a socket to time-wait or dead fin-wait-2 state. |
329 | */ | 259 | */ |
@@ -381,7 +311,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) | |||
381 | tw->tw_ipv6only = 0; | 311 | tw->tw_ipv6only = 0; |
382 | #endif | 312 | #endif |
383 | /* Linkage updates. */ | 313 | /* Linkage updates. */ |
384 | __tcp_tw_hashdance(sk, tw); | 314 | __inet_twsk_hashdance(tw, sk, &tcp_hashinfo); |
385 | 315 | ||
386 | /* Get the TIME_WAIT timeout firing. */ | 316 | /* Get the TIME_WAIT timeout firing. */ |
387 | if (timeo < rto) | 317 | if (timeo < rto) |
@@ -448,7 +378,7 @@ rescan: | |||
448 | inet_twsk_for_each_inmate(tw, node, &tcp_tw_death_row[slot]) { | 378 | inet_twsk_for_each_inmate(tw, node, &tcp_tw_death_row[slot]) { |
449 | __inet_twsk_del_dead_node(tw); | 379 | __inet_twsk_del_dead_node(tw); |
450 | spin_unlock(&tw_death_lock); | 380 | spin_unlock(&tw_death_lock); |
451 | tcp_timewait_kill(tw); | 381 | __inet_twsk_kill(tw, &tcp_hashinfo); |
452 | inet_twsk_put(tw); | 382 | inet_twsk_put(tw); |
453 | killed++; | 383 | killed++; |
454 | spin_lock(&tw_death_lock); | 384 | spin_lock(&tw_death_lock); |
@@ -544,7 +474,7 @@ void tcp_tw_deschedule(struct inet_timewait_sock *tw) | |||
544 | del_timer(&tcp_tw_timer); | 474 | del_timer(&tcp_tw_timer); |
545 | } | 475 | } |
546 | spin_unlock(&tw_death_lock); | 476 | spin_unlock(&tw_death_lock); |
547 | tcp_timewait_kill(tw); | 477 | __inet_twsk_kill(tw, &tcp_hashinfo); |
548 | } | 478 | } |
549 | 479 | ||
550 | /* Short-time timewait calendar */ | 480 | /* Short-time timewait calendar */ |
@@ -653,7 +583,7 @@ void tcp_twcal_tick(unsigned long dummy) | |||
653 | inet_twsk_for_each_inmate_safe(tw, node, safe, | 583 | inet_twsk_for_each_inmate_safe(tw, node, safe, |
654 | &tcp_twcal_row[slot]) { | 584 | &tcp_twcal_row[slot]) { |
655 | __inet_twsk_del_dead_node(tw); | 585 | __inet_twsk_del_dead_node(tw); |
656 | tcp_timewait_kill(tw); | 586 | __inet_twsk_kill(tw, &tcp_hashinfo); |
657 | inet_twsk_put(tw); | 587 | inet_twsk_put(tw); |
658 | killed++; | 588 | killed++; |
659 | } | 589 | } |