Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tcp: fix undo after RTO for CUBIC

This patch fixes CUBIC so that cwnd reductions made during RTOs can be
undone (just as they already can be undone when using the default/Reno
behavior).

When undoing cwnd reductions, BIC-derived congestion control modules
were restoring the cwnd from last_max_cwnd. There were two problems
with using last_max_cwnd to restore a cwnd during undo:

(a) last_max_cwnd was set to 0 on state transitions into TCP_CA_Loss
(by calling the module's reset() functions), so cwnd reductions from
RTOs could not be undone.

(b) when fast_covergence is enabled (which it is by default)
last_max_cwnd does not actually hold the value of snd_cwnd before the
loss; instead, it holds a scaled-down version of snd_cwnd.

This patch makes the following changes:

(1) upon undo, revert snd_cwnd to ca->loss_cwnd, which is already, as
the existing comment notes, the "congestion window at last loss"

(2) stop forgetting ca->loss_cwnd on TCP_CA_Loss events

(3) use ca->last_max_cwnd to check if we're in slow start

Signed-off-by: Neal Cardwell <ncardwell@google.com>
Acked-by: Stephen Hemminger <shemminger@vyatta.com>
Acked-by: Sangtae Ha <sangtae.ha@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Neal Cardwell and committed by
David S. Miller
5a45f008 fc16dcd8

+6 -4
+6 -4
net/ipv4/tcp_cubic.c
··· 107 107 { 108 108 ca->cnt = 0; 109 109 ca->last_max_cwnd = 0; 110 - ca->loss_cwnd = 0; 111 110 ca->last_cwnd = 0; 112 111 ca->last_time = 0; 113 112 ca->bic_origin_point = 0; ··· 141 142 142 143 static void bictcp_init(struct sock *sk) 143 144 { 144 - bictcp_reset(inet_csk_ca(sk)); 145 + struct bictcp *ca = inet_csk_ca(sk); 146 + 147 + bictcp_reset(ca); 148 + ca->loss_cwnd = 0; 145 149 146 150 if (hystart) 147 151 bictcp_hystart_reset(sk); ··· 277 275 * The initial growth of cubic function may be too conservative 278 276 * when the available bandwidth is still unknown. 279 277 */ 280 - if (ca->loss_cwnd == 0 && ca->cnt > 20) 278 + if (ca->last_max_cwnd == 0 && ca->cnt > 20) 281 279 ca->cnt = 20; /* increase cwnd 5% per RTT */ 282 280 283 281 /* TCP Friendly */ ··· 344 342 { 345 343 struct bictcp *ca = inet_csk_ca(sk); 346 344 347 - return max(tcp_sk(sk)->snd_cwnd, ca->last_max_cwnd); 345 + return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd); 348 346 } 349 347 350 348 static void bictcp_state(struct sock *sk, u8 new_state)