diff options
Diffstat (limited to 'net/ipv4')
| -rw-r--r-- | net/ipv4/inet_timewait_sock.c | 5 | ||||
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 71 |
2 files changed, 45 insertions, 31 deletions
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index a010e9a68811..417f126c749e 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c | |||
| @@ -90,8 +90,9 @@ EXPORT_SYMBOL_GPL(__inet_twsk_hashdance); | |||
| 90 | 90 | ||
| 91 | struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int state) | 91 | struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int state) |
| 92 | { | 92 | { |
| 93 | struct inet_timewait_sock *tw = kmem_cache_alloc(sk->sk_prot_creator->twsk_slab, | 93 | struct inet_timewait_sock *tw = |
| 94 | SLAB_ATOMIC); | 94 | kmem_cache_alloc(sk->sk_prot_creator->twsk_prot->twsk_slab, |
| 95 | SLAB_ATOMIC); | ||
| 95 | if (tw != NULL) { | 96 | if (tw != NULL) { |
| 96 | const struct inet_sock *inet = inet_sk(sk); | 97 | const struct inet_sock *inet = inet_sk(sk); |
| 97 | 98 | ||
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 | ||
| 122 | int 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 | |||
| 153 | EXPORT_SYMBOL_GPL(tcp_twsk_unique); | ||
| 154 | |||
| 121 | /* called with local bh disabled */ | 155 | /* called with local bh disabled */ |
| 122 | static int __tcp_v4_check_established(struct sock *sk, __u16 lport, | 156 | static 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 | ||
| 880 | static 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 | |||
| 872 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | 885 | int 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 | ||
