aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
authorYuchung Cheng <ycheng@google.com>2019-04-29 18:46:14 -0400
committerDavid S. Miller <davem@davemloft.net>2019-05-01 11:47:54 -0400
commit7c1f08154c4e34d10be41156375ce2b8ab591b0f (patch)
treef4fddf34b3b093d57867395e64dc450969dfc8ac /net/ipv4/tcp_input.c
parentbc9f38c8328e10c22cb2016d6131ea36141c8d11 (diff)
tcp: undo initial congestion window on false SYN timeout
Linux implements RFC6298 and use an initial congestion window of 1 upon establishing the connection if the SYN packet is retransmitted 2 or more times. In cellular networks SYN timeouts are often spurious if the wireless radio was dormant or idle. Also some network path is longer than the default SYN timeout. Having a minimal cwnd on both cases are detrimental to TCP startup performance. This patch extends TCP undo feature (RFC3522 aka TCP Eifel) to detect spurious SYN timeout via TCP timestamps. Since tp->retrans_stamp records the initial SYN timestamp instead of first retransmission, we have to implement a different undo code additionally. The detection also must happen before tcp_ack() as retrans_stamp is reset when SYN is acknowledged. Note this patch covers both active regular and fast open. Signed-off-by: Yuchung Cheng <ycheng@google.com> Signed-off-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r--net/ipv4/tcp_input.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index e2cbfc3ffa3f..695f840acc14 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5748,6 +5748,21 @@ static void smc_check_reset_syn(struct tcp_sock *tp)
5748#endif 5748#endif
5749} 5749}
5750 5750
5751static void tcp_try_undo_spurious_syn(struct sock *sk)
5752{
5753 struct tcp_sock *tp = tcp_sk(sk);
5754 u32 syn_stamp;
5755
5756 /* undo_marker is set when SYN or SYNACK times out. The timeout is
5757 * spurious if the ACK's timestamp option echo value matches the
5758 * original SYN timestamp.
5759 */
5760 syn_stamp = tp->retrans_stamp;
5761 if (tp->undo_marker && syn_stamp && tp->rx_opt.saw_tstamp &&
5762 syn_stamp == tp->rx_opt.rcv_tsecr)
5763 tp->undo_marker = 0;
5764}
5765
5751static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, 5766static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
5752 const struct tcphdr *th) 5767 const struct tcphdr *th)
5753{ 5768{
@@ -5815,6 +5830,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
5815 tcp_ecn_rcv_synack(tp, th); 5830 tcp_ecn_rcv_synack(tp, th);
5816 5831
5817 tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); 5832 tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
5833 tcp_try_undo_spurious_syn(sk);
5818 tcp_ack(sk, skb, FLAG_SLOWPATH); 5834 tcp_ack(sk, skb, FLAG_SLOWPATH);
5819 5835
5820 /* Ok.. it's good. Set up sequence numbers and 5836 /* Ok.. it's good. Set up sequence numbers and