OSDN Git Service

tcp: undo cwnd on Fast Open spurious SYNACK retransmit
authorYuchung Cheng <ycheng@google.com>
Mon, 29 Apr 2019 22:46:18 +0000 (15:46 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 1 May 2019 15:47:54 +0000 (11:47 -0400)
This patch makes passive Fast Open reverts the cwnd to default
initial cwnd (10 packets) if the SYNACK timeout is spurious.

Passive Fast Open uses a full socket during handshake so it can
use the existing undo logic to detect spurious retransmission
by recording the first SYNACK timeout in key state variable
retrans_stamp. Upon receiving the ACK of the SYNACK, if the socket
has sent some data before the timeout, the spurious timeout
is detected by tcp_try_undo_recovery() in tcp_process_loss()
in tcp_ack().

But if the socket has not send any data yet, tcp_ack() does not
execute the undo code since no data is acknowledged. The fix is to
check such case explicitly after tcp_ack() during the ACK processing
in SYN_RECV state. In addition this is checked in FIN_WAIT_1 state
in case the server closes the socket before handshake completes.

Signed-off-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/tcp_input.c

index 53b4c5a..3a40584 100644 (file)
@@ -6089,6 +6089,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
                 * so release it.
                 */
                if (req) {
+                       tcp_try_undo_loss(sk, false);
                        inet_csk(sk)->icsk_retransmits = 0;
                        reqsk_fastopen_remove(sk, req, false);
                        /* Re-arm the timer because data may have been sent out.
@@ -6143,6 +6144,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
                 * our SYNACK so stop the SYNACK timer.
                 */
                if (req) {
+                       tcp_try_undo_loss(sk, false);
+                       inet_csk(sk)->icsk_retransmits = 0;
                        /* We no longer need the request sock. */
                        reqsk_fastopen_remove(sk, req, false);
                        tcp_rearm_rto(sk);