aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorNeal Cardwell <ncardwell@google.com>2014-08-14 16:13:07 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-14 17:38:55 -0400
commit0c9ab09223fe9922baeb22546c9a90d774a4bde6 (patch)
treed94a2e28f5f1c32fa56ad41655722fd06e64c953 /net
parenta26552afe89438eefbe097512b3187f2c7e929fd (diff)
tcp: fix ssthresh and undo for consecutive short FRTO episodes
Fix TCP FRTO logic so that it always notices when snd_una advances, indicating that any RTO after that point will be a new and distinct loss episode. Previously there was a very specific sequence that could cause FRTO to fail to notice a new loss episode had started: (1) RTO timer fires, enter FRTO and retransmit packet 1 in write queue (2) receiver ACKs packet 1 (3) FRTO sends 2 more packets (4) RTO timer fires again (should start a new loss episode) The problem was in step (3) above, where tcp_process_loss() returned early (in the spot marked "Step 2.b"), so that it never got to the logic to clear icsk_retransmits. Thus icsk_retransmits stayed non-zero. Thus in step (4) tcp_enter_loss() would see the non-zero icsk_retransmits, decide that this RTO is not a new episode, and decide not to cut ssthresh and remember the current cwnd and ssthresh for undo. There were two main consequences to the bug that we have observed. First, ssthresh was not decreased in step (4). Second, when there was a series of such FRTO (1-4) sequences that happened to be followed by an FRTO undo, we would restore the cwnd and ssthresh from before the entire series started (instead of the cwnd and ssthresh from before the most recent RTO). This could result in cwnd and ssthresh being restored to values much bigger than the proper values. Signed-off-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: Yuchung Cheng <ycheng@google.com> Fixes: e33099f96d99c ("tcp: implement RFC5682 F-RTO") Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/tcp_input.c8
1 files changed, 3 insertions, 5 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 4f6cfbc57775..a906e0200ff2 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2687,7 +2687,6 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack)
2687 */ 2687 */
2688static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) 2688static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack)
2689{ 2689{
2690 struct inet_connection_sock *icsk = inet_csk(sk);
2691 struct tcp_sock *tp = tcp_sk(sk); 2690 struct tcp_sock *tp = tcp_sk(sk);
2692 bool recovered = !before(tp->snd_una, tp->high_seq); 2691 bool recovered = !before(tp->snd_una, tp->high_seq);
2693 2692
@@ -2713,12 +2712,9 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack)
2713 2712
2714 if (recovered) { 2713 if (recovered) {
2715 /* F-RTO RFC5682 sec 3.1 step 2.a and 1st part of step 3.a */ 2714 /* F-RTO RFC5682 sec 3.1 step 2.a and 1st part of step 3.a */
2716 icsk->icsk_retransmits = 0;
2717 tcp_try_undo_recovery(sk); 2715 tcp_try_undo_recovery(sk);
2718 return; 2716 return;
2719 } 2717 }
2720 if (flag & FLAG_DATA_ACKED)
2721 icsk->icsk_retransmits = 0;
2722 if (tcp_is_reno(tp)) { 2718 if (tcp_is_reno(tp)) {
2723 /* A Reno DUPACK means new data in F-RTO step 2.b above are 2719 /* A Reno DUPACK means new data in F-RTO step 2.b above are
2724 * delivered. Lower inflight to clock out (re)tranmissions. 2720 * delivered. Lower inflight to clock out (re)tranmissions.
@@ -3405,8 +3401,10 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
3405 icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) 3401 icsk->icsk_pending == ICSK_TIME_LOSS_PROBE)
3406 tcp_rearm_rto(sk); 3402 tcp_rearm_rto(sk);
3407 3403
3408 if (after(ack, prior_snd_una)) 3404 if (after(ack, prior_snd_una)) {
3409 flag |= FLAG_SND_UNA_ADVANCED; 3405 flag |= FLAG_SND_UNA_ADVANCED;
3406 icsk->icsk_retransmits = 0;
3407 }
3410 3408
3411 prior_fackets = tp->fackets_out; 3409 prior_fackets = tp->fackets_out;
3412 3410