aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/linux/sysctl.h1
-rw-r--r--include/net/tcp.h1
-rw-r--r--net/ipv4/sysctl_net_ipv4.c8
-rw-r--r--net/ipv4/tcp_cong.c31
4 files changed, 32 insertions, 9 deletions
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 9a8970bf99a6..98e0fd241a25 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -438,6 +438,7 @@ enum
438 NET_CIPSOV4_RBM_STRICTVALID=121, 438 NET_CIPSOV4_RBM_STRICTVALID=121,
439 NET_TCP_AVAIL_CONG_CONTROL=122, 439 NET_TCP_AVAIL_CONG_CONTROL=122,
440 NET_TCP_ALLOWED_CONG_CONTROL=123, 440 NET_TCP_ALLOWED_CONG_CONTROL=123,
441 NET_TCP_MAX_SSTHRESH=124,
441}; 442};
442 443
443enum { 444enum {
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 7fd6b77519c3..6d09f5085f6a 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -230,6 +230,7 @@ extern int sysctl_tcp_mtu_probing;
230extern int sysctl_tcp_base_mss; 230extern int sysctl_tcp_base_mss;
231extern int sysctl_tcp_workaround_signed_windows; 231extern int sysctl_tcp_workaround_signed_windows;
232extern int sysctl_tcp_slow_start_after_idle; 232extern int sysctl_tcp_slow_start_after_idle;
233extern int sysctl_tcp_max_ssthresh;
233 234
234extern atomic_t tcp_memory_allocated; 235extern atomic_t tcp_memory_allocated;
235extern atomic_t tcp_sockets_allocated; 236extern atomic_t tcp_sockets_allocated;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 0aa304711a96..d68effe98e8d 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -803,6 +803,14 @@ ctl_table ipv4_table[] = {
803 .proc_handler = &proc_allowed_congestion_control, 803 .proc_handler = &proc_allowed_congestion_control,
804 .strategy = &strategy_allowed_congestion_control, 804 .strategy = &strategy_allowed_congestion_control,
805 }, 805 },
806 {
807 .ctl_name = NET_TCP_MAX_SSTHRESH,
808 .procname = "tcp_max_ssthresh",
809 .data = &sysctl_tcp_max_ssthresh,
810 .maxlen = sizeof(int),
811 .mode = 0644,
812 .proc_handler = &proc_dointvec,
813 },
806 { .ctl_name = 0 } 814 { .ctl_name = 0 }
807}; 815};
808 816
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