No functional changes. Signed-off-by: Ilpo Järvinen <ilpo.jarvi...@helsinki.fi> --- net/ipv4/tcp_input.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 1a33752..e20f9ad 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2211,6 +2211,19 @@ static void tcp_update_scoreboard(struct sock *sk, int fast_rexmit) } } +/* False fast retransmits may occur when SACK is not in use under certain + * conditions (RFC6582). The sender MUST hold old state until something + * *above* high_seq is ACKed to prevent triggering such false fast + * retransmits. SACK TCP is safe. + */ +static bool tcp_false_fast_retrans_possible(const struct sock *sk, + const u32 snd_una) +{ + const struct tcp_sock *tp = tcp_sk(sk); + + return ((snd_una == tp->high_seq) && tcp_is_reno(tp)); +} + static bool tcp_tsopt_ecr_before(const struct tcp_sock *tp, u32 when) { return tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr && @@ -2350,10 +2363,10 @@ static bool tcp_try_undo_recovery(struct sock *sk) } else if (tp->rack.reo_wnd_persist) { tp->rack.reo_wnd_persist--; } - if (tp->snd_una == tp->high_seq && tcp_is_reno(tp)) { - /* Hold old state until something *above* high_seq - * is ACKed. For Reno it is MUST to prevent false - * fast retransmits (RFC2582). SACK TCP is safe. */ + if (tcp_false_fast_retrans_possible(sk, tp->snd_una)) { + /* Hold old state until something *above* high_seq is ACKed + * if false fast retransmit is possible. + */ if (!tcp_any_retrans_done(sk)) tp->retrans_stamp = 0; return true; -- 2.7.4