diff options
author | Jerry Chu <hkchu@google.com> | 2012-08-31 08:29:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-08-31 20:02:19 -0400 |
commit | 8336886f786fdacbc19b719c1f7ea91eb70706d4 (patch) | |
tree | c1fa912f7583ce0ffcb5ae673802da4a7dfb3b19 /net/ipv6 | |
parent | 1046716368979dee857a2b8a91c4a8833f21b9cb (diff) |
tcp: TCP Fast Open Server - support TFO listeners
This patch builds on top of the previous patch to add the support
for TFO listeners. This includes -
1. allocating, properly initializing, and managing the per listener
fastopen_queue structure when TFO is enabled
2. changes to the inet_csk_accept code to support TFO. E.g., the
request_sock can no longer be freed upon accept(), not until 3WHS
finishes
3. allowing a TCP_SYN_RECV socket to properly poll() and sendmsg()
if it's a TFO socket
4. properly closing a TFO listener, and a TFO socket before 3WHS
finishes
5. supporting TCP_FASTOPEN socket option
6. modifying tcp_check_req() to use to check a TFO socket as well
as request_sock
7. supporting TCP's TFO cookie option
8. adding a new SYN-ACK retransmit handler to use the timer directly
off the TFO socket rather than the listener socket. Note that TFO
server side will not retransmit anything other than SYN-ACK until
the 3WHS is completed.
The patch also contains an important function
"reqsk_fastopen_remove()" to manage the somewhat complex relation
between a listener, its request_sock, and the corresponding child
socket. See the comment above the function for the detail.
Signed-off-by: H.K. Jerry Chu <hkchu@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/syncookies.c | 1 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 5 |
2 files changed, 4 insertions, 2 deletions
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index bb46061c813a..182ab9a85d6c 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -190,6 +190,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
190 | ireq = inet_rsk(req); | 190 | ireq = inet_rsk(req); |
191 | ireq6 = inet6_rsk(req); | 191 | ireq6 = inet6_rsk(req); |
192 | treq = tcp_rsk(req); | 192 | treq = tcp_rsk(req); |
193 | treq->listener = NULL; | ||
193 | 194 | ||
194 | if (security_inet_conn_request(sk, skb, req)) | 195 | if (security_inet_conn_request(sk, skb, req)) |
195 | goto out_free; | 196 | goto out_free; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index f99b81d53cca..09078b9bc6f6 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -475,7 +475,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, | |||
475 | if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL) | 475 | if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL) |
476 | goto done; | 476 | goto done; |
477 | 477 | ||
478 | skb = tcp_make_synack(sk, dst, req, rvp); | 478 | skb = tcp_make_synack(sk, dst, req, rvp, NULL); |
479 | 479 | ||
480 | if (skb) { | 480 | if (skb) { |
481 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); | 481 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); |
@@ -987,7 +987,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
987 | &ipv6_hdr(skb)->saddr, | 987 | &ipv6_hdr(skb)->saddr, |
988 | &ipv6_hdr(skb)->daddr, inet6_iif(skb)); | 988 | &ipv6_hdr(skb)->daddr, inet6_iif(skb)); |
989 | if (req) | 989 | if (req) |
990 | return tcp_check_req(sk, skb, req, prev); | 990 | return tcp_check_req(sk, skb, req, prev, false); |
991 | 991 | ||
992 | nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo, | 992 | nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo, |
993 | &ipv6_hdr(skb)->saddr, th->source, | 993 | &ipv6_hdr(skb)->saddr, th->source, |
@@ -1179,6 +1179,7 @@ have_isn: | |||
1179 | want_cookie) | 1179 | want_cookie) |
1180 | goto drop_and_free; | 1180 | goto drop_and_free; |
1181 | 1181 | ||
1182 | tcp_rsk(req)->listener = NULL; | ||
1182 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | 1183 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); |
1183 | return 0; | 1184 | return 0; |
1184 | 1185 | ||