diff options
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r-- | net/ipv4/tcp_output.c | 23 |
1 files changed, 17 insertions, 6 deletions
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. */ |
46 | int sysctl_tcp_retrans_collapse = 1; | 46 | int 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 | */ | ||
51 | int 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)); |