diff options
-rw-r--r-- | include/linux/sysctl.h | 1 | ||||
-rw-r--r-- | include/net/tcp.h | 1 | ||||
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 8 | ||||
-rw-r--r-- | net/ipv4/tcp_cong.c | 31 |
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 | ||
443 | enum { | 444 | enum { |
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; | |||
230 | extern int sysctl_tcp_base_mss; | 230 | extern int sysctl_tcp_base_mss; |
231 | extern int sysctl_tcp_workaround_signed_windows; | 231 | extern int sysctl_tcp_workaround_signed_windows; |
232 | extern int sysctl_tcp_slow_start_after_idle; | 232 | extern int sysctl_tcp_slow_start_after_idle; |
233 | extern int sysctl_tcp_max_ssthresh; | ||
233 | 234 | ||
234 | extern atomic_t tcp_memory_allocated; | 235 | extern atomic_t tcp_memory_allocated; |
235 | extern atomic_t tcp_sockets_allocated; | 236 | extern 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 | ||
15 | int sysctl_tcp_max_ssthresh = 0; | ||
16 | |||
15 | static DEFINE_SPINLOCK(tcp_cong_list_lock); | 17 | static DEFINE_SPINLOCK(tcp_cong_list_lock); |
16 | static LIST_HEAD(tcp_cong_list); | 18 | static 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 | */ |
279 | void tcp_slow_start(struct tcp_sock *tp) | 282 | void 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 | } |
301 | EXPORT_SYMBOL_GPL(tcp_slow_start); | 314 | EXPORT_SYMBOL_GPL(tcp_slow_start); |
302 | 315 | ||