aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
authorYuchung Cheng <ycheng@google.com>2018-05-16 19:40:17 -0400
committerDavid S. Miller <davem@davemloft.net>2018-05-17 15:41:29 -0400
commit56f8c5d78f5746f48abf6d1f0bc2945dc59277ee (patch)
treec543d69724d87f1128c00ce80843727902515fdf /net/ipv4/tcp_input.c
parentb8fef65a8a76c2f887c56bf8e9684ff04e8d3b9f (diff)
tcp: don't mark recently sent packets lost on RTO
An RTO event indicates the head has not been acked for a long time after its last (re)transmission. But the other packets are not necessarily lost if they have been only sent recently (for example due to application limit). This patch would prohibit marking packets sent within an RTT to be lost on RTO event, using similar logic in TCP RACK detection. Normally the head (SND.UNA) would be marked lost since RTO should fire strictly after the head was sent. An exception is when the most recent RACK RTT measurement is larger than the (previous) RTO. To address this exception the head is always marked lost. Congestion control interaction: since we may not mark every packet lost, the congestion window may be more than 1 (inflight plus 1). But only one packet will be retransmitted after RTO, since tcp_retransmit_timer() calls tcp_retransmit_skb(...,segs=1). The connection still performs slow start from one packet (with Cubic congestion control). This commit was tested in an A/B test with Google web servers, and showed a reduction of 2% in (spurious) retransmits post timeout (SlowStartRetrans), and correspondingly reduced DSACKs (DSACKIgnoredOld) by 7%. Signed-off-by: Yuchung Cheng <ycheng@google.com> Signed-off-by: Neal Cardwell <ncardwell@google.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Soheil Hassas Yeganeh <soheil@google.com> Reviewed-by: Priyaranjan Jha <priyarjha@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.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ba8a8e3464aa..0bf032839548 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1929,11 +1929,11 @@ static bool tcp_is_rack(const struct sock *sk)
1929static void tcp_timeout_mark_lost(struct sock *sk) 1929static void tcp_timeout_mark_lost(struct sock *sk)
1930{ 1930{
1931 struct tcp_sock *tp = tcp_sk(sk); 1931 struct tcp_sock *tp = tcp_sk(sk);
1932 struct sk_buff *skb; 1932 struct sk_buff *skb, *head;
1933 bool is_reneg; /* is receiver reneging on SACKs? */ 1933 bool is_reneg; /* is receiver reneging on SACKs? */
1934 1934
1935 skb = tcp_rtx_queue_head(sk); 1935 head = tcp_rtx_queue_head(sk);
1936 is_reneg = skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED); 1936 is_reneg = head && (TCP_SKB_CB(head)->sacked & TCPCB_SACKED_ACKED);
1937 if (is_reneg) { 1937 if (is_reneg) {
1938 NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSACKRENEGING); 1938 NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSACKRENEGING);
1939 tp->sacked_out = 0; 1939 tp->sacked_out = 0;
@@ -1943,9 +1943,13 @@ static void tcp_timeout_mark_lost(struct sock *sk)
1943 tcp_reset_reno_sack(tp); 1943 tcp_reset_reno_sack(tp);
1944 } 1944 }
1945 1945
1946 skb = head;
1946 skb_rbtree_walk_from(skb) { 1947 skb_rbtree_walk_from(skb) {
1947 if (is_reneg) 1948 if (is_reneg)
1948 TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; 1949 TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED;
1950 else if (tcp_is_rack(sk) && skb != head &&
1951 tcp_rack_skb_timeout(tp, skb, 0) > 0)
1952 continue; /* Don't mark recently sent ones lost yet */
1949 tcp_mark_skb_lost(sk, skb); 1953 tcp_mark_skb_lost(sk, skb);
1950 } 1954 }
1951 tcp_verify_left_out(tp); 1955 tcp_verify_left_out(tp);
@@ -1972,7 +1976,7 @@ void tcp_enter_loss(struct sock *sk)
1972 tcp_ca_event(sk, CA_EVENT_LOSS); 1976 tcp_ca_event(sk, CA_EVENT_LOSS);
1973 tcp_init_undo(tp); 1977 tcp_init_undo(tp);
1974 } 1978 }
1975 tp->snd_cwnd = 1; 1979 tp->snd_cwnd = tcp_packets_in_flight(tp) + 1;
1976 tp->snd_cwnd_cnt = 0; 1980 tp->snd_cwnd_cnt = 0;
1977 tp->snd_cwnd_stamp = tcp_jiffies32; 1981 tp->snd_cwnd_stamp = tcp_jiffies32;
1978 1982