Commit 7b0eb22b authored by Ilpo Järvinen's avatar Ilpo Järvinen Committed by David S. Miller

[TCP] FRTO: Use Disorder state during operation instead of Open

Retransmission counter assumptions are to be changed. Forcing
reason to do this exist: Using sysctl in check would be racy
as soon as FRTO starts to ignore some ACKs (doing that in the
following patches). Userspace may disable it at any moment
giving nice oops if timing is right. frto_counter would be
inaccessible from userspace, but with SACK enhanced FRTO
retrans_out can include other than head, and possibly leaving
it non-zero after spurious RTO, boom again.

Luckily, solution seems rather simple: never go directly to Open
state but use Disorder instead. This does not really change much,
since TCP could anyway change its state to Disorder during FRTO
using path tcp_fastretrans_alert -> tcp_try_to_open (e.g., when
a SACK block makes ACK dubious). Besides, Disorder seems to be
the state where TCP should be if not recovering (in Recovery or
Loss state) while having some retransmissions in-flight (see
tcp_try_to_open), which is exactly what happens with FRTO.
Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7487c48c
...@@ -1286,7 +1286,8 @@ void tcp_enter_frto(struct sock *sk) ...@@ -1286,7 +1286,8 @@ void tcp_enter_frto(struct sock *sk)
} }
tcp_sync_left_out(tp); tcp_sync_left_out(tp);
tcp_set_ca_state(sk, TCP_CA_Open); tcp_set_ca_state(sk, TCP_CA_Disorder);
tp->high_seq = tp->snd_nxt;
tp->frto_highmark = tp->snd_nxt; tp->frto_highmark = tp->snd_nxt;
tp->frto_counter = 1; tp->frto_counter = 1;
} }
...@@ -2014,8 +2015,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, ...@@ -2014,8 +2015,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
/* E. Check state exit conditions. State can be terminated /* E. Check state exit conditions. State can be terminated
* when high_seq is ACKed. */ * when high_seq is ACKed. */
if (icsk->icsk_ca_state == TCP_CA_Open) { if (icsk->icsk_ca_state == TCP_CA_Open) {
if (!sysctl_tcp_frto) BUG_TRAP(tp->retrans_out == 0);
BUG_TRAP(tp->retrans_out == 0);
tp->retrans_stamp = 0; tp->retrans_stamp = 0;
} else if (!before(tp->snd_una, tp->high_seq)) { } else if (!before(tp->snd_una, tp->high_seq)) {
switch (icsk->icsk_ca_state) { switch (icsk->icsk_ca_state) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment