aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/tcp_input.c29
-rw-r--r--net/ipv4/tcp_timer.c4
2 files changed, 20 insertions, 13 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 7832d941dbcd..6a2984507755 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1904,16 +1904,17 @@ void tcp_clear_retrans(struct tcp_sock *tp)
1904 tp->sacked_out = 0; 1904 tp->sacked_out = 0;
1905} 1905}
1906 1906
1907/* Enter Loss state. If "how" is not zero, forget all SACK information 1907/* Enter Loss state. If we detect SACK reneging, forget all SACK information
1908 * and reset tags completely, otherwise preserve SACKs. If receiver 1908 * and reset tags completely, otherwise preserve SACKs. If receiver
1909 * dropped its ofo queue, we will know this due to reneging detection. 1909 * dropped its ofo queue, we will know this due to reneging detection.
1910 */ 1910 */
1911void tcp_enter_loss(struct sock *sk, int how) 1911void tcp_enter_loss(struct sock *sk)
1912{ 1912{
1913 const struct inet_connection_sock *icsk = inet_csk(sk); 1913 const struct inet_connection_sock *icsk = inet_csk(sk);
1914 struct tcp_sock *tp = tcp_sk(sk); 1914 struct tcp_sock *tp = tcp_sk(sk);
1915 struct sk_buff *skb; 1915 struct sk_buff *skb;
1916 bool new_recovery = false; 1916 bool new_recovery = false;
1917 bool is_reneg; /* is receiver reneging on SACKs? */
1917 1918
1918 /* Reduce ssthresh if it has not yet been made inside this window. */ 1919 /* Reduce ssthresh if it has not yet been made inside this window. */
1919 if (icsk->icsk_ca_state <= TCP_CA_Disorder || 1920 if (icsk->icsk_ca_state <= TCP_CA_Disorder ||
@@ -1934,7 +1935,11 @@ void tcp_enter_loss(struct sock *sk, int how)
1934 tcp_reset_reno_sack(tp); 1935 tcp_reset_reno_sack(tp);
1935 1936
1936 tp->undo_marker = tp->snd_una; 1937 tp->undo_marker = tp->snd_una;
1937 if (how) { 1938
1939 skb = tcp_write_queue_head(sk);
1940 is_reneg = skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED);
1941 if (is_reneg) {
1942 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSACKRENEGING);
1938 tp->sacked_out = 0; 1943 tp->sacked_out = 0;
1939 tp->fackets_out = 0; 1944 tp->fackets_out = 0;
1940 } 1945 }
@@ -1948,7 +1953,7 @@ void tcp_enter_loss(struct sock *sk, int how)
1948 tp->undo_marker = 0; 1953 tp->undo_marker = 0;
1949 1954
1950 TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED; 1955 TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED;
1951 if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || how) { 1956 if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || is_reneg) {
1952 TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; 1957 TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED;
1953 TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; 1958 TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
1954 tp->lost_out += tcp_skb_pcount(skb); 1959 tp->lost_out += tcp_skb_pcount(skb);
@@ -1981,19 +1986,21 @@ void tcp_enter_loss(struct sock *sk, int how)
1981 * remembered SACKs do not reflect real state of receiver i.e. 1986 * remembered SACKs do not reflect real state of receiver i.e.
1982 * receiver _host_ is heavily congested (or buggy). 1987 * receiver _host_ is heavily congested (or buggy).
1983 * 1988 *
1984 * Do processing similar to RTO timeout. 1989 * To avoid big spurious retransmission bursts due to transient SACK
1990 * scoreboard oddities that look like reneging, we give the receiver a
1991 * little time (max(RTT/2, 10ms)) to send us some more ACKs that will
1992 * restore sanity to the SACK scoreboard. If the apparent reneging
1993 * persists until this RTO then we'll clear the SACK scoreboard.
1985 */ 1994 */
1986static bool tcp_check_sack_reneging(struct sock *sk, int flag) 1995static bool tcp_check_sack_reneging(struct sock *sk, int flag)
1987{ 1996{
1988 if (flag & FLAG_SACK_RENEGING) { 1997 if (flag & FLAG_SACK_RENEGING) {
1989 struct inet_connection_sock *icsk = inet_csk(sk); 1998 struct tcp_sock *tp = tcp_sk(sk);
1990 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSACKRENEGING); 1999 unsigned long delay = max(usecs_to_jiffies(tp->srtt_us >> 4),
2000 msecs_to_jiffies(10));
1991 2001
1992 tcp_enter_loss(sk, 1);
1993 icsk->icsk_retransmits++;
1994 tcp_retransmit_skb(sk, tcp_write_queue_head(sk));
1995 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, 2002 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
1996 icsk->icsk_rto, TCP_RTO_MAX); 2003 delay, TCP_RTO_MAX);
1997 return true; 2004 return true;
1998 } 2005 }
1999 return false; 2006 return false;
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 286227abed10..df90cd1ce37f 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -391,7 +391,7 @@ void tcp_retransmit_timer(struct sock *sk)
391 tcp_write_err(sk); 391 tcp_write_err(sk);
392 goto out; 392 goto out;
393 } 393 }
394 tcp_enter_loss(sk, 0); 394 tcp_enter_loss(sk);
395 tcp_retransmit_skb(sk, tcp_write_queue_head(sk)); 395 tcp_retransmit_skb(sk, tcp_write_queue_head(sk));
396 __sk_dst_reset(sk); 396 __sk_dst_reset(sk);
397 goto out_reset_timer; 397 goto out_reset_timer;
@@ -422,7 +422,7 @@ void tcp_retransmit_timer(struct sock *sk)
422 NET_INC_STATS_BH(sock_net(sk), mib_idx); 422 NET_INC_STATS_BH(sock_net(sk), mib_idx);
423 } 423 }
424 424
425 tcp_enter_loss(sk, 0); 425 tcp_enter_loss(sk);
426 426
427 if (tcp_retransmit_skb(sk, tcp_write_queue_head(sk)) > 0) { 427 if (tcp_retransmit_skb(sk, tcp_write_queue_head(sk)) > 0) {
428 /* Retransmission failed because of local congestion, 428 /* Retransmission failed because of local congestion,