[MINOR] tcp: add support for dynamic MSS setting

By passing a negative value to the "mss" argument of "bind" lines, it
becomes possible to subtract this value to the MSS advertised by the
client, which results in segments smaller than advertised. The effect
is useful with some TCP stacks which ACK less often when segments are
not full, because they only ACK every other full segment as suggested
by RFC1122.

NOTE: currently this has no effect on Linux kernel 2.6, a kernel patch
is still required to change the MSS of established connections.
This commit is contained in:
Willy Tarreau 2010-12-24 15:26:39 +01:00
parent df5b38fac1
commit 48a7e72c5d
4 changed files with 25 additions and 7 deletions

View File

@ -1463,9 +1463,14 @@ bind /<path> [, ...] [ group <user> | gid <gid> ]
connections passing through a VPN. Note that this relies on a
kernel feature which is theorically supported under Linux but
was buggy in all versions prior to 2.6.28. It may or may not
work on other operating systems. The commonly advertised
value on Ethernet networks is 1460 = 1500(MTU) - 40(IP+TCP).
This parameter is only compatible with TCP sockets.
work on other operating systems. It may also not change the
advertised value but change the effective size of outgoing
segments. The commonly advertised value on Ethernet networks
is 1460 = 1500(MTU) - 40(IP+TCP). If this value is positive,
it will be used as the advertised MSS. If it is negative, it
will indicate by how much to reduce the incoming connection's
advertised MSS for outgoing segments. This parameter is only
compatible with TCP sockets.
<id> is a persistent value for socket ID. Must be positive and
unique in the proxy. An unused value will automatically be

View File

@ -1683,9 +1683,9 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
goto out;
}
mss = str2uic(args[cur_arg + 1]);
if (mss < 1 || mss > 65535) {
Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
mss = atoi(args[cur_arg + 1]);
if (!mss || abs(mss) > 65535) {
Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;

View File

@ -20,6 +20,8 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <netinet/tcp.h>
#include <common/compat.h>
#include <common/config.h>
#include <common/debug.h>
@ -100,6 +102,17 @@ int frontend_accept(struct session *s)
if (s->fe->options & PR_O_TCP_NOLING)
setsockopt(cfd, SOL_SOCKET, SO_LINGER,
(struct linger *) &nolinger, sizeof(struct linger));
#if defined(TCP_MAXSEG)
if (s->listener->maxseg < 0) {
/* we just want to reduce the current MSS by that value */
int mss;
int mss_len = sizeof(mss);
if (getsockopt(cfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &mss_len) == 0) {
mss += s->listener->maxseg; /* remember, it's < 0 */
setsockopt(cfd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss));
}
}
#endif
}
if (global.tune.client_sndbuf)

View File

@ -509,7 +509,7 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
}
#endif
#if defined(TCP_MAXSEG)
if (listener->maxseg) {
if (listener->maxseg > 0) {
if (setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG,
&listener->maxseg, sizeof(listener->maxseg)) == -1) {
msg = "cannot set MSS";