diff options
author | Neal Cardwell <ncardwell@google.com> | 2015-01-28 20:01:36 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-01-29 01:18:37 -0500 |
commit | 814d488c61260521b1b3cc97063700a5a6667c8f (patch) | |
tree | 676d16d97849f4b4727d365cd35e67e67d9a2c79 /net | |
parent | e73ebb0881ea5534ce606c1d71b4ac44db5c6930 (diff) |
tcp: fix the timid additive increase on stretch ACKs
tcp_cong_avoid_ai() was too timid (snd_cwnd increased too slowly) on
"stretch ACKs" -- cases where the receiver ACKed more than 1 packet in
a single ACK. For example, suppose w is 10 and we get a stretch ACK
for 20 packets, so acked is 20. We ought to increase snd_cwnd by 2
(since acked/w = 20/10 = 2), but instead we were only increasing cwnd
by 1. This patch fixes that behavior.
Reported-by: Eyal Perry <eyalpe@mellanox.com>
Signed-off-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/tcp_cong.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 6826017c12d1..faaee5338bea 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
@@ -304,16 +304,19 @@ u32 tcp_slow_start(struct tcp_sock *tp, u32 acked) | |||
304 | } | 304 | } |
305 | EXPORT_SYMBOL_GPL(tcp_slow_start); | 305 | EXPORT_SYMBOL_GPL(tcp_slow_start); |
306 | 306 | ||
307 | /* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd (or alternative w) */ | 307 | /* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd (or alternative w), |
308 | * for every packet that was ACKed. | ||
309 | */ | ||
308 | void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w, u32 acked) | 310 | void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w, u32 acked) |
309 | { | 311 | { |
312 | tp->snd_cwnd_cnt += acked; | ||
310 | if (tp->snd_cwnd_cnt >= w) { | 313 | if (tp->snd_cwnd_cnt >= w) { |
311 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) | 314 | u32 delta = tp->snd_cwnd_cnt / w; |
312 | tp->snd_cwnd++; | 315 | |
313 | tp->snd_cwnd_cnt = 0; | 316 | tp->snd_cwnd_cnt -= delta * w; |
314 | } else { | 317 | tp->snd_cwnd += delta; |
315 | tp->snd_cwnd_cnt += acked; | ||
316 | } | 318 | } |
319 | tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_cwnd_clamp); | ||
317 | } | 320 | } |
318 | EXPORT_SYMBOL_GPL(tcp_cong_avoid_ai); | 321 | EXPORT_SYMBOL_GPL(tcp_cong_avoid_ai); |
319 | 322 | ||