aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_cong.c
diff options
context:
space:
mode:
authorJohn Heffner <jheffner@psc.edu>2007-03-25 22:21:45 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:23:19 -0400
commit886236c1247ab5e2ad9c73f6e9a652e3ae3c8b07 (patch)
treef0ab2d6f6b6c98c6042be100db752c2d492669ae /net/ipv4/tcp_cong.c
parent5ef814753eb810d900fbd77af7c87f6d04f0e551 (diff)
[TCP]: Add RFC3742 Limited Slow-Start, controlled by variable sysctl_tcp_max_ssthresh.
Signed-off-by: John Heffner <jheffner@psc.edu> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_cong.c')
-rw-r--r--net/ipv4/tcp_cong.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 34ae3f13483a..ccd88407e0cd 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -12,6 +12,8 @@
12#include <linux/list.h> 12#include <linux/list.h>
13#include <net/tcp.h> 13#include <net/tcp.h>
14 14
15int sysctl_tcp_max_ssthresh = 0;
16
15static DEFINE_SPINLOCK(tcp_cong_list_lock); 17static DEFINE_SPINLOCK(tcp_cong_list_lock);
16static LIST_HEAD(tcp_cong_list); 18static LIST_HEAD(tcp_cong_list);
17 19
@@ -274,10 +276,13 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
274 276
275 277
276/* 278/*
277 * Linear increase during slow start 279 * Slow start (exponential increase) with
280 * RFC3742 Limited Slow Start (fast linear increase) support.
278 */ 281 */
279void tcp_slow_start(struct tcp_sock *tp) 282void tcp_slow_start(struct tcp_sock *tp)
280{ 283{
284 int cnt = 0;
285
281 if (sysctl_tcp_abc) { 286 if (sysctl_tcp_abc) {
282 /* RFC3465: Slow Start 287 /* RFC3465: Slow Start
283 * TCP sender SHOULD increase cwnd by the number of 288 * TCP sender SHOULD increase cwnd by the number of
@@ -286,17 +291,25 @@ void tcp_slow_start(struct tcp_sock *tp)
286 */ 291 */
287 if (tp->bytes_acked < tp->mss_cache) 292 if (tp->bytes_acked < tp->mss_cache)
288 return; 293 return;
289
290 /* We MAY increase by 2 if discovered delayed ack */
291 if (sysctl_tcp_abc > 1 && tp->bytes_acked >= 2*tp->mss_cache) {
292 if (tp->snd_cwnd < tp->snd_cwnd_clamp)
293 tp->snd_cwnd++;
294 }
295 } 294 }
295
296 if (sysctl_tcp_max_ssthresh > 0 &&
297 tp->snd_cwnd > sysctl_tcp_max_ssthresh)
298 cnt += sysctl_tcp_max_ssthresh>>1;
299 else
300 cnt += tp->snd_cwnd;
301
302 /* RFC3465: We MAY increase by 2 if discovered delayed ack */
303 if (sysctl_tcp_abc > 1 && tp->bytes_acked >= 2*tp->mss_cache)
304 cnt <<= 1;
296 tp->bytes_acked = 0; 305 tp->bytes_acked = 0;
297 306
298 if (tp->snd_cwnd < tp->snd_cwnd_clamp) 307 tp->snd_cwnd_cnt += cnt;
299 tp->snd_cwnd++; 308 while (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
309 tp->snd_cwnd_cnt -= tp->snd_cwnd;
310 if (tp->snd_cwnd < tp->snd_cwnd_clamp)
311 tp->snd_cwnd++;
312 }
300} 313}
301EXPORT_SYMBOL_GPL(tcp_slow_start); 314EXPORT_SYMBOL_GPL(tcp_slow_start);
302 315