[INET]: Generalise tcp_tw_bucket, aka TIME_WAIT sockets

This paves the way to generalise the rest of the sock ID lookup
routines and saves some bytes in TCPv4 TIME_WAIT sockets on distro
kernels (where IPv6 is always built as a module):

[root@qemu ~]# grep tw_sock /proc/slabinfo
tw_sock_TCPv6  0  0  128  31  1
tw_sock_TCP    0  0   96  41  1
[root@qemu ~]#

Now if a protocol wants to use the TIME_WAIT generic infrastructure it
only has to set the sk_prot->twsk_obj_size field with the size of its
inet_timewait_sock derived sock and proto_register will create
sk_prot->twsk_slab, for now its only for INET sockets, but we can
introduce timewait_sock later if some non INET transport protocolo
wants to use this stuff.

Next changesets will take advantage of this new infrastructure to
generalise even more TCP code.

[acme@toy net-2.6.14]$ grep built-in /tmp/before.size /tmp/after.size
/tmp/before.size: 188646   11764    5068  205478   322a6 net/ipv4/built-in.o
/tmp/after.size:  188144   11764    5068  204976   320b0 net/ipv4/built-in.o
[acme@toy net-2.6.14]$

Tested with both IPv4 & IPv6 (::1 (localhost) & ::ffff:172.20.0.1
(qemu host)).

Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Arnaldo Carvalho de Melo 2005-08-09 20:09:30 -07:00 committed by David S. Miller
parent 33b6223190
commit 8feaf0c0a5
13 changed files with 484 additions and 391 deletions

View file

@ -81,7 +81,7 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
r->id.tcpdiag_cookie[1] = (u32)(((unsigned long)sk >> 31) >> 1);
if (r->tcpdiag_state == TCP_TIME_WAIT) {
struct tcp_tw_bucket *tw = (struct tcp_tw_bucket*)sk;
const struct inet_timewait_sock *tw = inet_twsk(sk);
long tmo = tw->tw_ttd - jiffies;
if (tmo < 0)
tmo = 0;
@ -99,10 +99,12 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
r->tcpdiag_inode = 0;
#ifdef CONFIG_IP_TCPDIAG_IPV6
if (r->tcpdiag_family == AF_INET6) {
const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk);
ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src,
&tw->tw_v6_rcv_saddr);
&tcp6tw->tw_v6_rcv_saddr);
ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst,
&tw->tw_v6_daddr);
&tcp6tw->tw_v6_daddr);
}
#endif
nlh->nlmsg_len = skb->tail - b;
@ -239,7 +241,7 @@ static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh)
out:
if (sk) {
if (sk->sk_state == TCP_TIME_WAIT)
tcp_tw_put((struct tcp_tw_bucket*)sk);
inet_twsk_put((struct inet_timewait_sock *)sk);
else
sock_put(sk);
}