diff options
Diffstat (limited to 'net/ipv4/tcp_cong.c')
-rw-r--r-- | net/ipv4/tcp_cong.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 27ead0dd16bc..8670e68e2ce6 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
@@ -291,26 +291,32 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) | |||
291 | * ABC caps N to 2. Slow start exits when cwnd grows over ssthresh and | 291 | * ABC caps N to 2. Slow start exits when cwnd grows over ssthresh and |
292 | * returns the leftover acks to adjust cwnd in congestion avoidance mode. | 292 | * returns the leftover acks to adjust cwnd in congestion avoidance mode. |
293 | */ | 293 | */ |
294 | void tcp_slow_start(struct tcp_sock *tp, u32 acked) | 294 | u32 tcp_slow_start(struct tcp_sock *tp, u32 acked) |
295 | { | 295 | { |
296 | u32 cwnd = tp->snd_cwnd + acked; | 296 | u32 cwnd = tp->snd_cwnd + acked; |
297 | 297 | ||
298 | if (cwnd > tp->snd_ssthresh) | 298 | if (cwnd > tp->snd_ssthresh) |
299 | cwnd = tp->snd_ssthresh + 1; | 299 | cwnd = tp->snd_ssthresh + 1; |
300 | acked -= cwnd - tp->snd_cwnd; | ||
300 | tp->snd_cwnd = min(cwnd, tp->snd_cwnd_clamp); | 301 | tp->snd_cwnd = min(cwnd, tp->snd_cwnd_clamp); |
302 | |||
303 | return acked; | ||
301 | } | 304 | } |
302 | EXPORT_SYMBOL_GPL(tcp_slow_start); | 305 | EXPORT_SYMBOL_GPL(tcp_slow_start); |
303 | 306 | ||
304 | /* 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), |
305 | void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w) | 308 | * for every packet that was ACKed. |
309 | */ | ||
310 | void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w, u32 acked) | ||
306 | { | 311 | { |
312 | tp->snd_cwnd_cnt += acked; | ||
307 | if (tp->snd_cwnd_cnt >= w) { | 313 | if (tp->snd_cwnd_cnt >= w) { |
308 | if (tp->snd_cwnd < tp->snd_cwnd_clamp) | 314 | u32 delta = tp->snd_cwnd_cnt / w; |
309 | tp->snd_cwnd++; | 315 | |
310 | tp->snd_cwnd_cnt = 0; | 316 | tp->snd_cwnd_cnt -= delta * w; |
311 | } else { | 317 | tp->snd_cwnd += delta; |
312 | tp->snd_cwnd_cnt++; | ||
313 | } | 318 | } |
319 | tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_cwnd_clamp); | ||
314 | } | 320 | } |
315 | EXPORT_SYMBOL_GPL(tcp_cong_avoid_ai); | 321 | EXPORT_SYMBOL_GPL(tcp_cong_avoid_ai); |
316 | 322 | ||
@@ -329,11 +335,13 @@ void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
329 | return; | 335 | return; |
330 | 336 | ||
331 | /* In "safe" area, increase. */ | 337 | /* In "safe" area, increase. */ |
332 | if (tp->snd_cwnd <= tp->snd_ssthresh) | 338 | if (tp->snd_cwnd <= tp->snd_ssthresh) { |
333 | tcp_slow_start(tp, acked); | 339 | acked = tcp_slow_start(tp, acked); |
340 | if (!acked) | ||
341 | return; | ||
342 | } | ||
334 | /* In dangerous area, increase slowly. */ | 343 | /* In dangerous area, increase slowly. */ |
335 | else | 344 | tcp_cong_avoid_ai(tp, tp->snd_cwnd, acked); |
336 | tcp_cong_avoid_ai(tp, tp->snd_cwnd); | ||
337 | } | 345 | } |
338 | EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid); | 346 | EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid); |
339 | 347 | ||