diff options
-rw-r--r-- | net/ipv4/tcp_input.c | 30 |
1 files changed, 12 insertions, 18 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index cd8ea972dc65..8d480542aa07 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1909,6 +1909,7 @@ void tcp_enter_loss(struct sock *sk) | |||
1909 | struct tcp_sock *tp = tcp_sk(sk); | 1909 | struct tcp_sock *tp = tcp_sk(sk); |
1910 | struct net *net = sock_net(sk); | 1910 | struct net *net = sock_net(sk); |
1911 | struct sk_buff *skb; | 1911 | struct sk_buff *skb; |
1912 | bool new_recovery = icsk->icsk_ca_state < TCP_CA_Recovery; | ||
1912 | bool is_reneg; /* is receiver reneging on SACKs? */ | 1913 | bool is_reneg; /* is receiver reneging on SACKs? */ |
1913 | bool mark_lost; | 1914 | bool mark_lost; |
1914 | 1915 | ||
@@ -1967,15 +1968,12 @@ void tcp_enter_loss(struct sock *sk) | |||
1967 | tp->high_seq = tp->snd_nxt; | 1968 | tp->high_seq = tp->snd_nxt; |
1968 | tcp_ecn_queue_cwr(tp); | 1969 | tcp_ecn_queue_cwr(tp); |
1969 | 1970 | ||
1970 | /* F-RTO RFC5682 sec 3.1 step 1 mandates to disable F-RTO | 1971 | /* F-RTO RFC5682 sec 3.1 step 1: retransmit SND.UNA if no previous |
1971 | * if a previous recovery is underway, otherwise it may incorrectly | 1972 | * loss recovery is underway except recurring timeout(s) on |
1972 | * call a timeout spurious if some previously retransmitted packets | 1973 | * the same SND.UNA (sec 3.2). Disable F-RTO on path MTU probing |
1973 | * are s/acked (sec 3.2). We do not apply that retriction since | ||
1974 | * retransmitted skbs are permanently tagged with TCPCB_EVER_RETRANS | ||
1975 | * so FLAG_ORIG_SACK_ACKED is always correct. But we do disable F-RTO | ||
1976 | * on PTMU discovery to avoid sending new data. | ||
1977 | */ | 1974 | */ |
1978 | tp->frto = net->ipv4.sysctl_tcp_frto && | 1975 | tp->frto = net->ipv4.sysctl_tcp_frto && |
1976 | (new_recovery || icsk->icsk_retransmits) && | ||
1979 | !inet_csk(sk)->icsk_mtup.probe_size; | 1977 | !inet_csk(sk)->icsk_mtup.probe_size; |
1980 | } | 1978 | } |
1981 | 1979 | ||
@@ -2628,18 +2626,14 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack, | |||
2628 | tcp_try_undo_loss(sk, false)) | 2626 | tcp_try_undo_loss(sk, false)) |
2629 | return; | 2627 | return; |
2630 | 2628 | ||
2631 | /* The ACK (s)acks some never-retransmitted data meaning not all | ||
2632 | * the data packets before the timeout were lost. Therefore we | ||
2633 | * undo the congestion window and state. This is essentially | ||
2634 | * the operation in F-RTO (RFC5682 section 3.1 step 3.b). Since | ||
2635 | * a retransmitted skb is permantly marked, we can apply such an | ||
2636 | * operation even if F-RTO was not used. | ||
2637 | */ | ||
2638 | if ((flag & FLAG_ORIG_SACK_ACKED) && | ||
2639 | tcp_try_undo_loss(sk, tp->undo_marker)) | ||
2640 | return; | ||
2641 | |||
2642 | if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */ | 2629 | if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */ |
2630 | /* Step 3.b. A timeout is spurious if not all data are | ||
2631 | * lost, i.e., never-retransmitted data are (s)acked. | ||
2632 | */ | ||
2633 | if ((flag & FLAG_ORIG_SACK_ACKED) && | ||
2634 | tcp_try_undo_loss(sk, true)) | ||
2635 | return; | ||
2636 | |||
2643 | if (after(tp->snd_nxt, tp->high_seq)) { | 2637 | if (after(tp->snd_nxt, tp->high_seq)) { |
2644 | if (flag & FLAG_DATA_SACKED || is_dupack) | 2638 | if (flag & FLAG_DATA_SACKED || is_dupack) |
2645 | tp->frto = 0; /* Step 3.a. loss was real */ | 2639 | tp->frto = 0; /* Step 3.a. loss was real */ |