tcp: add a sysctl to config the tcp_default_init_rwnd
authorJP Abgrall <jpa@google.com>
Sat, 8 Feb 2014 02:40:10 +0000 (18:40 -0800)
committerJP Abgrall <jpa@google.com>
Sat, 8 Feb 2014 02:40:10 +0000 (18:40 -0800)
The default initial rwnd is hardcoded to 10.

Now we allow it to be controlled via
  /proc/sys/net/ipv4/tcp_default_init_rwnd
which limits the values from 3 to 100

This is somewhat needed because ipv6 routes are
autoconfigured by the kernel.

See "An Argument for Increasing TCP's Initial Congestion Window"
in https://developers.google.com/speed/articles/tcp_initcwnd_paper.pdf

Change-Id: I386b2a9d62de0ebe05c1ebe1b4bd91b314af5c54
Signed-off-by: JP Abgrall <jpa@google.com>
Conflicts:
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_input.c

include/net/tcp.h
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c

index 1ed71a993d6576038cf4d52277c0008965eb84ce..cfb55e14b25b5117e6ce959faf3e0a5ee2fae97f 100644 (file)
@@ -287,6 +287,7 @@ extern int sysctl_tcp_thin_dupack;
 extern int sysctl_tcp_early_retrans;
 extern int sysctl_tcp_limit_output_bytes;
 extern int sysctl_tcp_challenge_ack_limit;
+extern int sysctl_tcp_default_init_rwnd;
 
 extern atomic_long_t tcp_memory_allocated;
 extern struct percpu_counter tcp_sockets_allocated;
index fa2f63fc453b936b1660b79146b67edf17ae687a..f9bb5d7488e0d3d8599efecb5db1b9386cbb25f9 100644 (file)
@@ -135,6 +135,21 @@ static int ipv4_ping_group_range(ctl_table *table, int write,
        return ret;
 }
 
+/* Validate changes from /proc interface. */
+static int proc_tcp_default_init_rwnd(ctl_table *ctl, int write,
+                                     void __user *buffer,
+                                     size_t *lenp, loff_t *ppos)
+{
+       int old_value = *(int *)ctl->data;
+       int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+       int new_value = *(int *)ctl->data;
+
+       if (write && ret == 0 && (new_value < 3 || new_value > 100))
+               *(int *)ctl->data = old_value;
+
+       return ret;
+}
+
 static int proc_tcp_congestion_control(ctl_table *ctl, int write,
                                       void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -732,7 +747,7 @@ static struct ctl_table ipv4_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec
        },
-        {
+       {
                .procname       = "tcp_thin_dupack",
                .data           = &sysctl_tcp_thin_dupack,
                .maxlen         = sizeof(int),
@@ -748,6 +763,13 @@ static struct ctl_table ipv4_table[] = {
                .extra1         = &zero,
                .extra2         = &four,
        },
+       {
+               .procname       = "tcp_default_init_rwnd",
+               .data           = &sysctl_tcp_default_init_rwnd,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_tcp_default_init_rwnd
+       },
        {
                .procname       = "udp_mem",
                .data           = &sysctl_udp_mem,
index 9c6225780bd5aafdb175a762d45c704e82416582..4189682d9ade37c7dffb075328d22e77a1598a29 100644 (file)
@@ -98,6 +98,7 @@ int sysctl_tcp_thin_dupack __read_mostly;
 
 int sysctl_tcp_moderate_rcvbuf __read_mostly = 1;
 int sysctl_tcp_early_retrans __read_mostly = 3;
+int sysctl_tcp_default_init_rwnd __read_mostly = TCP_DEFAULT_INIT_RCVWND;
 
 #define FLAG_DATA              0x01 /* Incoming frame contained data.          */
 #define FLAG_WIN_UPDATE                0x02 /* Incoming ACK was a window update.       */
@@ -351,14 +352,14 @@ static void tcp_grow_window(struct sock *sk, const struct sk_buff *skb)
 static void tcp_fixup_rcvbuf(struct sock *sk)
 {
        u32 mss = tcp_sk(sk)->advmss;
-       u32 icwnd = TCP_DEFAULT_INIT_RCVWND;
+       u32 icwnd = sysctl_tcp_default_init_rwnd;
        int rcvmem;
 
        /* Limit to 10 segments if mss <= 1460,
         * or 14600/mss segments, with a minimum of two segments.
         */
        if (mss > 1460)
-               icwnd = max_t(u32, (1460 * TCP_DEFAULT_INIT_RCVWND) / mss, 2);
+               icwnd = max_t(u32, (1460 * icwnd) / mss, 2);
 
        rcvmem = SKB_TRUESIZE(mss + MAX_TCP_HEADER);
        while (tcp_win_from_space(rcvmem) < mss)
index ec335fabd5cc12daba8addf5de86adc90abbd561..084eac6a43b95442955087f35ffe3f0228ecfb3c 100644 (file)
@@ -231,14 +231,13 @@ void tcp_select_initial_window(int __space, __u32 mss,
        }
 
        /* Set initial window to a value enough for senders starting with
-        * initial congestion window of TCP_DEFAULT_INIT_RCVWND. Place
+        * initial congestion window of sysctl_tcp_default_init_rwnd. Place
         * a limit on the initial window when mss is larger than 1460.
         */
        if (mss > (1 << *rcv_wscale)) {
-               int init_cwnd = TCP_DEFAULT_INIT_RCVWND;
+               int init_cwnd = sysctl_tcp_default_init_rwnd;
                if (mss > 1460)
-                       init_cwnd =
-                       max_t(u32, (1460 * TCP_DEFAULT_INIT_RCVWND) / mss, 2);
+                       init_cwnd = max_t(u32, (1460 * init_cwnd) / mss, 2);
                /* when initializing use the value from init_rcv_wnd
                 * rather than the default from above
                 */