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>
This commit is contained in:

committed by
David S. Miller

parent
1046716368
commit
8336886f78
@@ -190,6 +190,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
|
||||
ireq = inet_rsk(req);
|
||||
ireq6 = inet6_rsk(req);
|
||||
treq = tcp_rsk(req);
|
||||
treq->listener = NULL;
|
||||
|
||||
if (security_inet_conn_request(sk, skb, req))
|
||||
goto out_free;
|
||||
|
@@ -475,7 +475,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst,
|
||||
if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL)
|
||||
goto done;
|
||||
|
||||
skb = tcp_make_synack(sk, dst, req, rvp);
|
||||
skb = tcp_make_synack(sk, dst, req, rvp, NULL);
|
||||
|
||||
if (skb) {
|
||||
__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)
|
||||
&ipv6_hdr(skb)->saddr,
|
||||
&ipv6_hdr(skb)->daddr, inet6_iif(skb));
|
||||
if (req)
|
||||
return tcp_check_req(sk, skb, req, prev);
|
||||
return tcp_check_req(sk, skb, req, prev, false);
|
||||
|
||||
nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo,
|
||||
&ipv6_hdr(skb)->saddr, th->source,
|
||||
@@ -1179,6 +1179,7 @@ have_isn:
|
||||
want_cookie)
|
||||
goto drop_and_free;
|
||||
|
||||
tcp_rsk(req)->listener = NULL;
|
||||
inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
|
||||
return 0;
|
||||
|
||||
|
Reference in New Issue
Block a user