diff options
author | Rick Jones <rick.jones2@hp.com> | 2006-03-21 01:40:29 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-21 01:40:29 -0500 |
commit | 15d99e02babae8bc20b836917ace07d93e318149 (patch) | |
tree | 6a8941a3ef45f831161730aeee4a2fcc18cca78a /net/ipv4 | |
parent | c1b1bce8527c2c3cac7e2520ca54b7c04281033e (diff) |
[TCP]: sysctl to allow TCP window > 32767 sans wscale
Back in the dark ages, we had to be conservative and only allow 15-bit
window fields if the window scale option was not negotiated. Some
ancient stacks used a signed 16-bit quantity for the window field of
the TCP header and would get confused.
Those days are long gone, so we can use the full 16-bits by default
now.
There is a sysctl added so that we can still interact with such old
stacks
Signed-off-by: Rick Jones <rick.jones2@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 9 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 23 |
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. */ |
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)); |