aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2008-02-03 07:06:04 -0500
committerDavid S. Miller <davem@davemloft.net>2008-02-03 07:28:52 -0500
commitab1e0a13d70299e792fd0527cefd070c1405fa5b (patch)
treed470e7b94b0e33ea59b12713366f1bee0b94f78c /net/ipv4
parent9dc7f30e3bac329998a2a9bb814bd0abc7cb58e2 (diff)
[SOCK] proto: Add hashinfo member to struct proto
This way we can remove TCP and DCCP specific versions of sk->sk_prot->get_port: both v4 and v6 use inet_csk_get_port sk->sk_prot->hash: inet_hash is directly used, only v6 need a specific version to deal with mapped sockets sk->sk_prot->unhash: both v4 and v6 use inet_hash directly struct inet_connection_sock_af_ops also gets a new member, bind_conflict, so that inet_csk_get_port can find the per family routine. Now only the lookup routines receive as a parameter a struct inet_hashtable. With this we further reuse code, reducing the difference among INET transport protocols. Eventually work has to be done on UDP and SCTP to make them share this infrastructure and get as a bonus inet_diag interfaces so that iproute can be used with these protocols. net-2.6/net/ipv4/inet_hashtables.c: struct proto | +8 struct inet_connection_sock_af_ops | +8 2 structs changed __inet_hash_nolisten | +18 __inet_hash | -210 inet_put_port | +8 inet_bind_bucket_create | +1 __inet_hash_connect | -8 5 functions changed, 27 bytes added, 218 bytes removed, diff: -191 net-2.6/net/core/sock.c: proto_seq_show | +3 1 function changed, 3 bytes added, diff: +3 net-2.6/net/ipv4/inet_connection_sock.c: inet_csk_get_port | +15 1 function changed, 15 bytes added, diff: +15 net-2.6/net/ipv4/tcp.c: tcp_set_state | -7 1 function changed, 7 bytes removed, diff: -7 net-2.6/net/ipv4/tcp_ipv4.c: tcp_v4_get_port | -31 tcp_v4_hash | -48 tcp_v4_destroy_sock | -7 tcp_v4_syn_recv_sock | -2 tcp_unhash | -179 5 functions changed, 267 bytes removed, diff: -267 net-2.6/net/ipv6/inet6_hashtables.c: __inet6_hash | +8 1 function changed, 8 bytes added, diff: +8 net-2.6/net/ipv4/inet_hashtables.c: inet_unhash | +190 inet_hash | +242 2 functions changed, 432 bytes added, diff: +432 vmlinux: 16 functions changed, 485 bytes added, 492 bytes removed, diff: -7 /home/acme/git/net-2.6/net/ipv6/tcp_ipv6.c: tcp_v6_get_port | -31 tcp_v6_hash | -7 tcp_v6_syn_recv_sock | -9 3 functions changed, 47 bytes removed, diff: -47 /home/acme/git/net-2.6/net/dccp/proto.c: dccp_destroy_sock | -7 dccp_unhash | -179 dccp_hash | -49 dccp_set_state | -7 dccp_done | +1 5 functions changed, 1 bytes added, 242 bytes removed, diff: -241 /home/acme/git/net-2.6/net/dccp/ipv4.c: dccp_v4_get_port | -31 dccp_v4_request_recv_sock | -2 2 functions changed, 33 bytes removed, diff: -33 /home/acme/git/net-2.6/net/dccp/ipv6.c: dccp_v6_get_port | -31 dccp_v6_hash | -7 dccp_v6_request_recv_sock | +5 3 functions changed, 5 bytes added, 38 bytes removed, diff: -33 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/inet_connection_sock.c8
-rw-r--r--net/ipv4/inet_hashtables.c58
-rw-r--r--net/ipv4/tcp.c2
-rw-r--r--net/ipv4/tcp_ipv4.c31
4 files changed, 60 insertions, 39 deletions
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index de5a41de191a..b189278c7bc1 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -78,11 +78,9 @@ EXPORT_SYMBOL_GPL(inet_csk_bind_conflict);
78/* Obtain a reference to a local port for the given sock, 78/* Obtain a reference to a local port for the given sock,
79 * if snum is zero it means select any available local port. 79 * if snum is zero it means select any available local port.
80 */ 80 */
81int inet_csk_get_port(struct inet_hashinfo *hashinfo, 81int inet_csk_get_port(struct sock *sk, unsigned short snum)
82 struct sock *sk, unsigned short snum,
83 int (*bind_conflict)(const struct sock *sk,
84 const struct inet_bind_bucket *tb))
85{ 82{
83 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
86 struct inet_bind_hashbucket *head; 84 struct inet_bind_hashbucket *head;
87 struct hlist_node *node; 85 struct hlist_node *node;
88 struct inet_bind_bucket *tb; 86 struct inet_bind_bucket *tb;
@@ -142,7 +140,7 @@ tb_found:
142 goto success; 140 goto success;
143 } else { 141 } else {
144 ret = 1; 142 ret = 1;
145 if (bind_conflict(sk, tb)) 143 if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb))
146 goto fail_unlock; 144 goto fail_unlock;
147 } 145 }
148 } 146 }
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 48d45008f749..90f422c9447b 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -66,8 +66,9 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
66/* 66/*
67 * Get rid of any references to a local port held by the given sock. 67 * Get rid of any references to a local port held by the given sock.
68 */ 68 */
69static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk) 69static void __inet_put_port(struct sock *sk)
70{ 70{
71 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
71 const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size); 72 const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size);
72 struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash]; 73 struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
73 struct inet_bind_bucket *tb; 74 struct inet_bind_bucket *tb;
@@ -81,10 +82,10 @@ static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
81 spin_unlock(&head->lock); 82 spin_unlock(&head->lock);
82} 83}
83 84
84void inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk) 85void inet_put_port(struct sock *sk)
85{ 86{
86 local_bh_disable(); 87 local_bh_disable();
87 __inet_put_port(hashinfo, sk); 88 __inet_put_port(sk);
88 local_bh_enable(); 89 local_bh_enable();
89} 90}
90 91
@@ -317,8 +318,9 @@ static inline u32 inet_sk_port_offset(const struct sock *sk)
317 inet->dport); 318 inet->dport);
318} 319}
319 320
320void __inet_hash_nolisten(struct inet_hashinfo *hashinfo, struct sock *sk) 321void __inet_hash_nolisten(struct sock *sk)
321{ 322{
323 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
322 struct hlist_head *list; 324 struct hlist_head *list;
323 rwlock_t *lock; 325 rwlock_t *lock;
324 struct inet_ehash_bucket *head; 326 struct inet_ehash_bucket *head;
@@ -337,13 +339,14 @@ void __inet_hash_nolisten(struct inet_hashinfo *hashinfo, struct sock *sk)
337} 339}
338EXPORT_SYMBOL_GPL(__inet_hash_nolisten); 340EXPORT_SYMBOL_GPL(__inet_hash_nolisten);
339 341
340void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk) 342static void __inet_hash(struct sock *sk)
341{ 343{
344 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
342 struct hlist_head *list; 345 struct hlist_head *list;
343 rwlock_t *lock; 346 rwlock_t *lock;
344 347
345 if (sk->sk_state != TCP_LISTEN) { 348 if (sk->sk_state != TCP_LISTEN) {
346 __inet_hash_nolisten(hashinfo, sk); 349 __inet_hash_nolisten(sk);
347 return; 350 return;
348 } 351 }
349 352
@@ -357,13 +360,48 @@ void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk)
357 write_unlock(lock); 360 write_unlock(lock);
358 wake_up(&hashinfo->lhash_wait); 361 wake_up(&hashinfo->lhash_wait);
359} 362}
360EXPORT_SYMBOL_GPL(__inet_hash); 363
364void inet_hash(struct sock *sk)
365{
366 if (sk->sk_state != TCP_CLOSE) {
367 local_bh_disable();
368 __inet_hash(sk);
369 local_bh_enable();
370 }
371}
372EXPORT_SYMBOL_GPL(inet_hash);
373
374void inet_unhash(struct sock *sk)
375{
376 rwlock_t *lock;
377 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
378
379 if (sk_unhashed(sk))
380 goto out;
381
382 if (sk->sk_state == TCP_LISTEN) {
383 local_bh_disable();
384 inet_listen_wlock(hashinfo);
385 lock = &hashinfo->lhash_lock;
386 } else {
387 lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
388 write_lock_bh(lock);
389 }
390
391 if (__sk_del_node_init(sk))
392 sock_prot_inuse_add(sk->sk_prot, -1);
393 write_unlock_bh(lock);
394out:
395 if (sk->sk_state == TCP_LISTEN)
396 wake_up(&hashinfo->lhash_wait);
397}
398EXPORT_SYMBOL_GPL(inet_unhash);
361 399
362int __inet_hash_connect(struct inet_timewait_death_row *death_row, 400int __inet_hash_connect(struct inet_timewait_death_row *death_row,
363 struct sock *sk, 401 struct sock *sk,
364 int (*check_established)(struct inet_timewait_death_row *, 402 int (*check_established)(struct inet_timewait_death_row *,
365 struct sock *, __u16, struct inet_timewait_sock **), 403 struct sock *, __u16, struct inet_timewait_sock **),
366 void (*hash)(struct inet_hashinfo *, struct sock *)) 404 void (*hash)(struct sock *sk))
367{ 405{
368 struct inet_hashinfo *hinfo = death_row->hashinfo; 406 struct inet_hashinfo *hinfo = death_row->hashinfo;
369 const unsigned short snum = inet_sk(sk)->num; 407 const unsigned short snum = inet_sk(sk)->num;
@@ -427,7 +465,7 @@ ok:
427 inet_bind_hash(sk, tb, port); 465 inet_bind_hash(sk, tb, port);
428 if (sk_unhashed(sk)) { 466 if (sk_unhashed(sk)) {
429 inet_sk(sk)->sport = htons(port); 467 inet_sk(sk)->sport = htons(port);
430 hash(hinfo, sk); 468 hash(sk);
431 } 469 }
432 spin_unlock(&head->lock); 470 spin_unlock(&head->lock);
433 471
@@ -444,7 +482,7 @@ ok:
444 tb = inet_csk(sk)->icsk_bind_hash; 482 tb = inet_csk(sk)->icsk_bind_hash;
445 spin_lock_bh(&head->lock); 483 spin_lock_bh(&head->lock);
446 if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { 484 if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
447 hash(hinfo, sk); 485 hash(sk);
448 spin_unlock_bh(&head->lock); 486 spin_unlock_bh(&head->lock);
449 return 0; 487 return 0;
450 } else { 488 } else {
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index a0d373bd9065..071e83a894ad 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1669,7 +1669,7 @@ void tcp_set_state(struct sock *sk, int state)
1669 sk->sk_prot->unhash(sk); 1669 sk->sk_prot->unhash(sk);
1670 if (inet_csk(sk)->icsk_bind_hash && 1670 if (inet_csk(sk)->icsk_bind_hash &&
1671 !(sk->sk_userlocks & SOCK_BINDPORT_LOCK)) 1671 !(sk->sk_userlocks & SOCK_BINDPORT_LOCK))
1672 inet_put_port(&tcp_hashinfo, sk); 1672 inet_put_port(sk);
1673 /* fall through */ 1673 /* fall through */
1674 default: 1674 default:
1675 if (oldstate==TCP_ESTABLISHED) 1675 if (oldstate==TCP_ESTABLISHED)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 77c1939a2b0d..63414ea427c5 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -108,22 +108,6 @@ struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
108 .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait), 108 .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait),
109}; 109};
110 110
111static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
112{
113 return inet_csk_get_port(&tcp_hashinfo, sk, snum,
114 inet_csk_bind_conflict);
115}
116
117static void tcp_v4_hash(struct sock *sk)
118{
119 inet_hash(&tcp_hashinfo, sk);
120}
121
122void tcp_unhash(struct sock *sk)
123{
124 inet_unhash(&tcp_hashinfo, sk);
125}
126
127static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb) 111static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb)
128{ 112{
129 return secure_tcp_sequence_number(ip_hdr(skb)->daddr, 113 return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
@@ -1478,8 +1462,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1478 } 1462 }
1479#endif 1463#endif
1480 1464
1481 __inet_hash_nolisten(&tcp_hashinfo, newsk); 1465 __inet_hash_nolisten(newsk);
1482 __inet_inherit_port(&tcp_hashinfo, sk, newsk); 1466 __inet_inherit_port(sk, newsk);
1483 1467
1484 return newsk; 1468 return newsk;
1485 1469
@@ -1827,6 +1811,7 @@ struct inet_connection_sock_af_ops ipv4_specific = {
1827 .getsockopt = ip_getsockopt, 1811 .getsockopt = ip_getsockopt,
1828 .addr2sockaddr = inet_csk_addr2sockaddr, 1812 .addr2sockaddr = inet_csk_addr2sockaddr,
1829 .sockaddr_len = sizeof(struct sockaddr_in), 1813 .sockaddr_len = sizeof(struct sockaddr_in),
1814 .bind_conflict = inet_csk_bind_conflict,
1830#ifdef CONFIG_COMPAT 1815#ifdef CONFIG_COMPAT
1831 .compat_setsockopt = compat_ip_setsockopt, 1816 .compat_setsockopt = compat_ip_setsockopt,
1832 .compat_getsockopt = compat_ip_getsockopt, 1817 .compat_getsockopt = compat_ip_getsockopt,
@@ -1926,7 +1911,7 @@ int tcp_v4_destroy_sock(struct sock *sk)
1926 1911
1927 /* Clean up a referenced TCP bind bucket. */ 1912 /* Clean up a referenced TCP bind bucket. */
1928 if (inet_csk(sk)->icsk_bind_hash) 1913 if (inet_csk(sk)->icsk_bind_hash)
1929 inet_put_port(&tcp_hashinfo, sk); 1914 inet_put_port(sk);
1930 1915
1931 /* 1916 /*
1932 * If sendmsg cached page exists, toss it. 1917 * If sendmsg cached page exists, toss it.
@@ -2435,9 +2420,9 @@ struct proto tcp_prot = {
2435 .getsockopt = tcp_getsockopt, 2420 .getsockopt = tcp_getsockopt,
2436 .recvmsg = tcp_recvmsg, 2421 .recvmsg = tcp_recvmsg,
2437 .backlog_rcv = tcp_v4_do_rcv, 2422 .backlog_rcv = tcp_v4_do_rcv,
2438 .hash = tcp_v4_hash, 2423 .hash = inet_hash,
2439 .unhash = tcp_unhash, 2424 .unhash = inet_unhash,
2440 .get_port = tcp_v4_get_port, 2425 .get_port = inet_csk_get_port,
2441 .enter_memory_pressure = tcp_enter_memory_pressure, 2426 .enter_memory_pressure = tcp_enter_memory_pressure,
2442 .sockets_allocated = &tcp_sockets_allocated, 2427 .sockets_allocated = &tcp_sockets_allocated,
2443 .orphan_count = &tcp_orphan_count, 2428 .orphan_count = &tcp_orphan_count,
@@ -2450,6 +2435,7 @@ struct proto tcp_prot = {
2450 .obj_size = sizeof(struct tcp_sock), 2435 .obj_size = sizeof(struct tcp_sock),
2451 .twsk_prot = &tcp_timewait_sock_ops, 2436 .twsk_prot = &tcp_timewait_sock_ops,
2452 .rsk_prot = &tcp_request_sock_ops, 2437 .rsk_prot = &tcp_request_sock_ops,
2438 .hashinfo = &tcp_hashinfo,
2453#ifdef CONFIG_COMPAT 2439#ifdef CONFIG_COMPAT
2454 .compat_setsockopt = compat_tcp_setsockopt, 2440 .compat_setsockopt = compat_tcp_setsockopt,
2455 .compat_getsockopt = compat_tcp_getsockopt, 2441 .compat_getsockopt = compat_tcp_getsockopt,
@@ -2467,7 +2453,6 @@ void __init tcp_v4_init(struct net_proto_family *ops)
2467EXPORT_SYMBOL(ipv4_specific); 2453EXPORT_SYMBOL(ipv4_specific);
2468EXPORT_SYMBOL(tcp_hashinfo); 2454EXPORT_SYMBOL(tcp_hashinfo);
2469EXPORT_SYMBOL(tcp_prot); 2455EXPORT_SYMBOL(tcp_prot);
2470EXPORT_SYMBOL(tcp_unhash);
2471EXPORT_SYMBOL(tcp_v4_conn_request); 2456EXPORT_SYMBOL(tcp_v4_conn_request);
2472EXPORT_SYMBOL(tcp_v4_connect); 2457EXPORT_SYMBOL(tcp_v4_connect);
2473EXPORT_SYMBOL(tcp_v4_do_rcv); 2458EXPORT_SYMBOL(tcp_v4_do_rcv);