Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 15d99e02 authored by Rick Jones's avatar Rick Jones Committed by David S. Miller
Browse files

[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: default avatarRick Jones <rick.jones2@hp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c1b1bce8
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -355,6 +355,13 @@ somaxconn - INTEGER
	Defaults to 128.  See also tcp_max_syn_backlog for additional tuning
	for TCP sockets.

tcp_workaround_signed_windows - BOOLEAN
	If set, assume no receipt of a window scaling option means the
	remote TCP is broken and treats the window as a signed quantity.
	If unset, assume the remote TCP is not broken even if we do
	not receive a window scaling option from them.
	Default: 0

IP Variables:

ip_local_port_range - 2 INTEGERS
+1 −0
Original line number Diff line number Diff line
@@ -402,6 +402,7 @@ enum
	NET_IPV4_IPFRAG_MAX_DIST=112,
 	NET_TCP_MTU_PROBING=113,
	NET_TCP_BASE_MSS=114,
	NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS=115,
};

enum {
+1 −0
Original line number Diff line number Diff line
@@ -224,6 +224,7 @@ extern int sysctl_tcp_tso_win_divisor;
extern int sysctl_tcp_abc;
extern int sysctl_tcp_mtu_probing;
extern int sysctl_tcp_base_mss;
extern int sysctl_tcp_workaround_signed_windows;

extern atomic_t tcp_memory_allocated;
extern atomic_t tcp_sockets_allocated;
+8 −1
Original line number Diff line number Diff line
@@ -680,7 +680,14 @@ ctl_table ipv4_table[] = {
		.mode		= 0644,
		.proc_handler	= &proc_dointvec,
	},

        {
		.ctl_name	= NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS,
		.procname	= "tcp_workaround_signed_windows",
		.data		= &sysctl_tcp_workaround_signed_windows,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= &proc_dointvec
	},
	{ .ctl_name = 0 }
};

+17 −6
Original line number Diff line number Diff line
@@ -45,6 +45,11 @@
/* People can turn this off for buggy TCP's found in printers etc. */
int sysctl_tcp_retrans_collapse = 1;

/* People can turn this on to  work with those rare, broken TCPs that
 * interpret the window field as a signed quantity.
 */
int sysctl_tcp_workaround_signed_windows = 0;

/* This limits the percentage of the congestion window which we
 * will allow a single TSO frame to consume.  Building TSO frames
 * which are too large can cause TCP streams to be bursty.
@@ -177,12 +182,18 @@ void tcp_select_initial_window(int __space, __u32 mss,
		space = (space / mss) * mss;

	/* NOTE: offering an initial window larger than 32767
	 * will break some buggy TCP stacks. We try to be nice.
	 * If we are not window scaling, then this truncates
	 * our initial window offering to 32k. There should also
	 * be a sysctl option to stop being nice.
	 */
	 * will break some buggy TCP stacks. If the admin tells us
	 * it is likely we could be speaking with such a buggy stack
	 * we will truncate our initial window offering to 32K-1
	 * unless the remote has sent us a window scaling option,
	 * which we interpret as a sign the remote TCP is not
	 * misinterpreting the window field as a signed quantity.
	 */
	if (sysctl_tcp_workaround_signed_windows)
		(*rcv_wnd) = min(space, MAX_TCP_WINDOW);
	else
		(*rcv_wnd) = space;

	(*rcv_wscale) = 0;
	if (wscale_ok) {
		/* Set window scaling on max possible window
@@ -241,7 +252,7 @@ static u16 tcp_select_window(struct sock *sk)
	/* Make sure we do not exceed the maximum possible
	 * scaled window.
	 */
	if (!tp->rx_opt.rcv_wscale)
	if (!tp->rx_opt.rcv_wscale && sysctl_tcp_workaround_signed_windows)
		new_win = min(new_win, MAX_TCP_WINDOW);
	else
		new_win = min(new_win, (65535U << tp->rx_opt.rcv_wscale));