Commit e326578a authored by Aananth V's avatar Aananth V Committed by David S. Miller

tcp: call tcp_try_undo_recovery when an RTOd TFO SYNACK is ACKed

For passive TCP Fast Open sockets that had SYN/ACK timeout and did not
send more data in SYN_RECV, upon receiving the final ACK in 3WHS, the
congestion state may awkwardly stay in CA_Loss mode unless the CA state
was undone due to TCP timestamp checks. However, if
tcp_rcv_synrecv_state_fastopen() decides not to undo, then we should
enter CA_Open, because at that point we have received an ACK covering
the retransmitted SYNACKs. Currently, the icsk_ca_state is only set to
CA_Open after we receive an ACK for a data-packet. This is because
tcp_ack does not call tcp_fastretrans_alert (and tcp_process_loss) if
!prior_packets

Note that tcp_process_loss() calls tcp_try_undo_recovery(), so having
tcp_rcv_synrecv_state_fastopen() decide that if we're in CA_Loss we
should call tcp_try_undo_recovery() is consistent with that, and
low risk.

Fixes: dad8cea7 ("tcp: fix TFO SYNACK undo to avoid double-timestamp-undo")
Signed-off-by: default avatarAananth V <aananthv@google.com>
Signed-off-by: default avatarNeal Cardwell <ncardwell@google.com>
Signed-off-by: default avatarYuchung Cheng <ycheng@google.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 50675d84
...@@ -6444,22 +6444,23 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, ...@@ -6444,22 +6444,23 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
static void tcp_rcv_synrecv_state_fastopen(struct sock *sk) static void tcp_rcv_synrecv_state_fastopen(struct sock *sk)
{ {
struct tcp_sock *tp = tcp_sk(sk);
struct request_sock *req; struct request_sock *req;
/* If we are still handling the SYNACK RTO, see if timestamp ECR allows /* If we are still handling the SYNACK RTO, see if timestamp ECR allows
* undo. If peer SACKs triggered fast recovery, we can't undo here. * undo. If peer SACKs triggered fast recovery, we can't undo here.
*/ */
if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss) if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss && !tp->packets_out)
tcp_try_undo_loss(sk, false); tcp_try_undo_recovery(sk);
/* Reset rtx states to prevent spurious retransmits_timed_out() */ /* Reset rtx states to prevent spurious retransmits_timed_out() */
tcp_sk(sk)->retrans_stamp = 0; tp->retrans_stamp = 0;
inet_csk(sk)->icsk_retransmits = 0; inet_csk(sk)->icsk_retransmits = 0;
/* Once we leave TCP_SYN_RECV or TCP_FIN_WAIT_1, /* Once we leave TCP_SYN_RECV or TCP_FIN_WAIT_1,
* we no longer need req so release it. * we no longer need req so release it.
*/ */
req = rcu_dereference_protected(tcp_sk(sk)->fastopen_rsk, req = rcu_dereference_protected(tp->fastopen_rsk,
lockdep_sock_is_held(sk)); lockdep_sock_is_held(sk));
reqsk_fastopen_remove(sk, req, false); reqsk_fastopen_remove(sk, req, false);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment