aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_ipv4.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@mandriva.com>2005-12-14 02:25:19 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-01-03 16:10:54 -0500
commit6d6ee43e0b8b8d4847627fd43739b98ec2b9404f (patch)
treea2a66381d2351610c81362bf218e743f6ccf56ef /net/ipv4/tcp_ipv4.c
parentfc44b9805324c0ad2733ea2feea9935cc056709d (diff)
[TWSK]: Introduce struct timewait_sock_ops
So that we can share several timewait sockets related functions and make the timewait mini sockets infrastructure closer to the request mini sockets one. Next changesets will take advantage of this, moving more code out of TCP and DCCP v4 and v6 to common infrastructure. Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r--net/ipv4/tcp_ipv4.c71
1 files changed, 42 insertions, 29 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 0b5ab04d3c5a..6728772a943a 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -69,6 +69,7 @@
69#include <net/transp_v6.h> 69#include <net/transp_v6.h>
70#include <net/ipv6.h> 70#include <net/ipv6.h>
71#include <net/inet_common.h> 71#include <net/inet_common.h>
72#include <net/timewait_sock.h>
72#include <net/xfrm.h> 73#include <net/xfrm.h>
73 74
74#include <linux/inet.h> 75#include <linux/inet.h>
@@ -118,6 +119,39 @@ static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
118 skb->h.th->source); 119 skb->h.th->source);
119} 120}
120 121
122int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
123{
124 const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw);
125 struct tcp_sock *tp = tcp_sk(sk);
126
127 /* With PAWS, it is safe from the viewpoint
128 of data integrity. Even without PAWS it is safe provided sequence
129 spaces do not overlap i.e. at data rates <= 80Mbit/sec.
130
131 Actually, the idea is close to VJ's one, only timestamp cache is
132 held not per host, but per port pair and TW bucket is used as state
133 holder.
134
135 If TW bucket has been already destroyed we fall back to VJ's scheme
136 and use initial timestamp retrieved from peer table.
137 */
138 if (tcptw->tw_ts_recent_stamp &&
139 (twp == NULL || (sysctl_tcp_tw_reuse &&
140 xtime.tv_sec - tcptw->tw_ts_recent_stamp > 1))) {
141 tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
142 if (tp->write_seq == 0)
143 tp->write_seq = 1;
144 tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
145 tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
146 sock_hold(sktw);
147 return 1;
148 }
149
150 return 0;
151}
152
153EXPORT_SYMBOL_GPL(tcp_twsk_unique);
154
121/* called with local bh disabled */ 155/* called with local bh disabled */
122static int __tcp_v4_check_established(struct sock *sk, __u16 lport, 156static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
123 struct inet_timewait_sock **twp) 157 struct inet_timewait_sock **twp)
@@ -142,35 +176,9 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
142 tw = inet_twsk(sk2); 176 tw = inet_twsk(sk2);
143 177
144 if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) { 178 if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) {
145 const struct tcp_timewait_sock *tcptw = tcp_twsk(sk2); 179 if (twsk_unique(sk, sk2, twp))
146 struct tcp_sock *tp = tcp_sk(sk);
147
148 /* With PAWS, it is safe from the viewpoint
149 of data integrity. Even without PAWS it
150 is safe provided sequence spaces do not
151 overlap i.e. at data rates <= 80Mbit/sec.
152
153 Actually, the idea is close to VJ's one,
154 only timestamp cache is held not per host,
155 but per port pair and TW bucket is used
156 as state holder.
157
158 If TW bucket has been already destroyed we
159 fall back to VJ's scheme and use initial
160 timestamp retrieved from peer table.
161 */
162 if (tcptw->tw_ts_recent_stamp &&
163 (!twp || (sysctl_tcp_tw_reuse &&
164 xtime.tv_sec -
165 tcptw->tw_ts_recent_stamp > 1))) {
166 tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
167 if (tp->write_seq == 0)
168 tp->write_seq = 1;
169 tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
170 tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
171 sock_hold(sk2);
172 goto unique; 180 goto unique;
173 } else 181 else
174 goto not_unique; 182 goto not_unique;
175 } 183 }
176 } 184 }
@@ -869,6 +877,11 @@ struct request_sock_ops tcp_request_sock_ops = {
869 .send_reset = tcp_v4_send_reset, 877 .send_reset = tcp_v4_send_reset,
870}; 878};
871 879
880static struct timewait_sock_ops tcp_timewait_sock_ops = {
881 .twsk_obj_size = sizeof(struct tcp_timewait_sock),
882 .twsk_unique = tcp_twsk_unique,
883};
884
872int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) 885int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
873{ 886{
874 struct inet_request_sock *ireq; 887 struct inet_request_sock *ireq;
@@ -1979,7 +1992,7 @@ struct proto tcp_prot = {
1979 .sysctl_rmem = sysctl_tcp_rmem, 1992 .sysctl_rmem = sysctl_tcp_rmem,
1980 .max_header = MAX_TCP_HEADER, 1993 .max_header = MAX_TCP_HEADER,
1981 .obj_size = sizeof(struct tcp_sock), 1994 .obj_size = sizeof(struct tcp_sock),
1982 .twsk_obj_size = sizeof(struct tcp_timewait_sock), 1995 .twsk_prot = &tcp_timewait_sock_ops,
1983 .rsk_prot = &tcp_request_sock_ops, 1996 .rsk_prot = &tcp_request_sock_ops,
1984}; 1997};
1985 1998