aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2013-02-02 00:23:16 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-03 16:00:25 -0500
commit973ec449bb4f2b8c514bacbcb4d9506fc31c8ce3 (patch)
tree29d7b5de18aeff078f265f75a2a94be22254b851 /net
parent59fa534874e6779082275d12d950e26c67c86498 (diff)
tcp: fix an infinite loop in tcp_slow_start()
Since commit 9dc274151a548 (tcp: fix ABC in tcp_slow_start()), a nul snd_cwnd triggers an infinite loop in tcp_slow_start() Avoid this infinite loop and log a one time error for further analysis. FRTO code is suspected to cause this bug. Reported-by: Pasi Kärkkäinen <pasik@iki.fi> Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Neal Cardwell <ncardwell@google.com> Cc: Yuchung Cheng <ycheng@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/tcp_cong.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 291f2ed7cc31..cdf2e707bb10 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -310,6 +310,12 @@ void tcp_slow_start(struct tcp_sock *tp)
310{ 310{
311 int cnt; /* increase in packets */ 311 int cnt; /* increase in packets */
312 unsigned int delta = 0; 312 unsigned int delta = 0;
313 u32 snd_cwnd = tp->snd_cwnd;
314
315 if (unlikely(!snd_cwnd)) {
316 pr_err_once("snd_cwnd is nul, please report this bug.\n");
317 snd_cwnd = 1U;
318 }
313 319
314 /* RFC3465: ABC Slow start 320 /* RFC3465: ABC Slow start
315 * Increase only after a full MSS of bytes is acked 321 * Increase only after a full MSS of bytes is acked
@@ -324,7 +330,7 @@ void tcp_slow_start(struct tcp_sock *tp)
324 if (sysctl_tcp_max_ssthresh > 0 && tp->snd_cwnd > sysctl_tcp_max_ssthresh) 330 if (sysctl_tcp_max_ssthresh > 0 && tp->snd_cwnd > sysctl_tcp_max_ssthresh)
325 cnt = sysctl_tcp_max_ssthresh >> 1; /* limited slow start */ 331 cnt = sysctl_tcp_max_ssthresh >> 1; /* limited slow start */
326 else 332 else
327 cnt = tp->snd_cwnd; /* exponential increase */ 333 cnt = snd_cwnd; /* exponential increase */
328 334
329 /* RFC3465: ABC 335 /* RFC3465: ABC
330 * We MAY increase by 2 if discovered delayed ack 336 * We MAY increase by 2 if discovered delayed ack
@@ -334,11 +340,11 @@ void tcp_slow_start(struct tcp_sock *tp)
334 tp->bytes_acked = 0; 340 tp->bytes_acked = 0;
335 341
336 tp->snd_cwnd_cnt += cnt; 342 tp->snd_cwnd_cnt += cnt;
337 while (tp->snd_cwnd_cnt >= tp->snd_cwnd) { 343 while (tp->snd_cwnd_cnt >= snd_cwnd) {
338 tp->snd_cwnd_cnt -= tp->snd_cwnd; 344 tp->snd_cwnd_cnt -= snd_cwnd;
339 delta++; 345 delta++;
340 } 346 }
341 tp->snd_cwnd = min(tp->snd_cwnd + delta, tp->snd_cwnd_clamp); 347 tp->snd_cwnd = min(snd_cwnd + delta, tp->snd_cwnd_clamp);
342} 348}
343EXPORT_SYMBOL_GPL(tcp_slow_start); 349EXPORT_SYMBOL_GPL(tcp_slow_start);
344 350