aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/sysctl_net_ipv4.c9
-rw-r--r--net/ipv4/tcp_output.c23
2 files changed, 25 insertions, 7 deletions
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index ebf2e0b363c4..6b6c3adfcf00 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -680,7 +680,14 @@ ctl_table ipv4_table[] = {
680 .mode = 0644, 680 .mode = 0644,
681 .proc_handler = &proc_dointvec, 681 .proc_handler = &proc_dointvec,
682 }, 682 },
683 683 {
684 .ctl_name = NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS,
685 .procname = "tcp_workaround_signed_windows",
686 .data = &sysctl_tcp_workaround_signed_windows,
687 .maxlen = sizeof(int),
688 .mode = 0644,
689 .proc_handler = &proc_dointvec
690 },
684 { .ctl_name = 0 } 691 { .ctl_name = 0 }
685}; 692};
686 693
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 518e568b53f3..9d79546d384e 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -45,6 +45,11 @@
45/* People can turn this off for buggy TCP's found in printers etc. */ 45/* People can turn this off for buggy TCP's found in printers etc. */
46int sysctl_tcp_retrans_collapse = 1; 46int sysctl_tcp_retrans_collapse = 1;
47 47
48/* People can turn this on to work with those rare, broken TCPs that
49 * interpret the window field as a signed quantity.
50 */
51int sysctl_tcp_workaround_signed_windows = 0;
52
48/* This limits the percentage of the congestion window which we 53/* This limits the percentage of the congestion window which we
49 * will allow a single TSO frame to consume. Building TSO frames 54 * will allow a single TSO frame to consume. Building TSO frames
50 * which are too large can cause TCP streams to be bursty. 55 * which are too large can cause TCP streams to be bursty.
@@ -177,12 +182,18 @@ void tcp_select_initial_window(int __space, __u32 mss,
177 space = (space / mss) * mss; 182 space = (space / mss) * mss;
178 183
179 /* NOTE: offering an initial window larger than 32767 184 /* NOTE: offering an initial window larger than 32767
180 * will break some buggy TCP stacks. We try to be nice. 185 * will break some buggy TCP stacks. If the admin tells us
181 * If we are not window scaling, then this truncates 186 * it is likely we could be speaking with such a buggy stack
182 * our initial window offering to 32k. There should also 187 * we will truncate our initial window offering to 32K-1
183 * be a sysctl option to stop being nice. 188 * unless the remote has sent us a window scaling option,
189 * which we interpret as a sign the remote TCP is not
190 * misinterpreting the window field as a signed quantity.
184 */ 191 */
185 (*rcv_wnd) = min(space, MAX_TCP_WINDOW); 192 if (sysctl_tcp_workaround_signed_windows)
193 (*rcv_wnd) = min(space, MAX_TCP_WINDOW);
194 else
195 (*rcv_wnd) = space;
196
186 (*rcv_wscale) = 0; 197 (*rcv_wscale) = 0;
187 if (wscale_ok) { 198 if (wscale_ok) {
188 /* Set window scaling on max possible window 199 /* Set window scaling on max possible window
@@ -241,7 +252,7 @@ static u16 tcp_select_window(struct sock *sk)
241 /* Make sure we do not exceed the maximum possible 252 /* Make sure we do not exceed the maximum possible
242 * scaled window. 253 * scaled window.
243 */ 254 */
244 if (!tp->rx_opt.rcv_wscale) 255 if (!tp->rx_opt.rcv_wscale && sysctl_tcp_workaround_signed_windows)
245 new_win = min(new_win, MAX_TCP_WINDOW); 256 new_win = min(new_win, MAX_TCP_WINDOW);
246 else 257 else
247 new_win = min(new_win, (65535U << tp->rx_opt.rcv_wscale)); 258 new_win = min(new_win, (65535U << tp->rx_opt.rcv_wscale));