Skip to content

Commit 89fe18e

Browse files
yuchungchengdavem330
authored andcommitted
tcp: extend F-RTO to catch more spurious timeouts
Current F-RTO reverts cwnd reset whenever a never-retransmitted packet was (s)acked. The timeout can be declared spurious because the packets acknoledged with this ACK was transmitted before the timeout, so clearly not all the packets are lost to reset the cwnd. This nice detection does not really depend F-RTO internals. This patch applies the detection universally. On Google servers this change detected 20% more spurious timeouts. Suggested-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: Yuchung Cheng <ycheng@google.com> Signed-off-by: Neal Cardwell <ncardwell@google.com> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent a0370b3 commit 89fe18e

File tree

1 file changed

+19
-14
lines changed

1 file changed

+19
-14
lines changed

net/ipv4/tcp_input.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,7 +1939,6 @@ void tcp_enter_loss(struct sock *sk)
19391939
struct tcp_sock *tp = tcp_sk(sk);
19401940
struct net *net = sock_net(sk);
19411941
struct sk_buff *skb;
1942-
bool new_recovery = icsk->icsk_ca_state < TCP_CA_Recovery;
19431942
bool is_reneg; /* is receiver reneging on SACKs? */
19441943
bool mark_lost;
19451944

@@ -2000,13 +1999,15 @@ void tcp_enter_loss(struct sock *sk)
20001999
tp->high_seq = tp->snd_nxt;
20012000
tcp_ecn_queue_cwr(tp);
20022001

2003-
/* F-RTO RFC5682 sec 3.1 step 1: retransmit SND.UNA if no previous
2004-
* loss recovery is underway except recurring timeout(s) on
2005-
* the same SND.UNA (sec 3.2). Disable F-RTO on path MTU probing
2002+
/* F-RTO RFC5682 sec 3.1 step 1 mandates to disable F-RTO
2003+
* if a previous recovery is underway, otherwise it may incorrectly
2004+
* call a timeout spurious if some previously retransmitted packets
2005+
* are s/acked (sec 3.2). We do not apply that retriction since
2006+
* retransmitted skbs are permanently tagged with TCPCB_EVER_RETRANS
2007+
* so FLAG_ORIG_SACK_ACKED is always correct. But we do disable F-RTO
2008+
* on PTMU discovery to avoid sending new data.
20062009
*/
2007-
tp->frto = sysctl_tcp_frto &&
2008-
(new_recovery || icsk->icsk_retransmits) &&
2009-
!inet_csk(sk)->icsk_mtup.probe_size;
2010+
tp->frto = sysctl_tcp_frto && !inet_csk(sk)->icsk_mtup.probe_size;
20102011
}
20112012

20122013
/* If ACK arrived pointing to a remembered SACK, it means that our
@@ -2740,14 +2741,18 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack,
27402741
tcp_try_undo_loss(sk, false))
27412742
return;
27422743

2743-
if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */
2744-
/* Step 3.b. A timeout is spurious if not all data are
2745-
* lost, i.e., never-retransmitted data are (s)acked.
2746-
*/
2747-
if ((flag & FLAG_ORIG_SACK_ACKED) &&
2748-
tcp_try_undo_loss(sk, true))
2749-
return;
2744+
/* The ACK (s)acks some never-retransmitted data meaning not all
2745+
* the data packets before the timeout were lost. Therefore we
2746+
* undo the congestion window and state. This is essentially
2747+
* the operation in F-RTO (RFC5682 section 3.1 step 3.b). Since
2748+
* a retransmitted skb is permantly marked, we can apply such an
2749+
* operation even if F-RTO was not used.
2750+
*/
2751+
if ((flag & FLAG_ORIG_SACK_ACKED) &&
2752+
tcp_try_undo_loss(sk, tp->undo_marker))
2753+
return;
27502754

2755+
if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */
27512756
if (after(tp->snd_nxt, tp->high_seq)) {
27522757
if (flag & FLAG_DATA_SACKED || is_dupack)
27532758
tp->frto = 0; /* Step 3.a. loss was real */

0 commit comments

Comments
 (0)