mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-22 14:21:25 +02:00
[MINOR] tcp: add support for the defer_accept bind option
This can ensure that data is readily available on a socket when we accept it, but a bug in the kernel ignores the timeout so the socket can remain pending as long as the client does not talk. Use with care.
This commit is contained in:
parent
f2d2b1d128
commit
cb6cd43725
@ -1132,6 +1132,7 @@ bind [<address>]:<port> [, ...] mss <maxseg>
|
||||
bind [<address>]:<port> [, ...] transparent
|
||||
bind [<address>]:<port> [, ...] id <id>
|
||||
bind [<address>]:<port> [, ...] name <name>
|
||||
bind [<address>]:<port> [, ...] defer_accept
|
||||
Define one or several listening addresses and/or ports in a frontend.
|
||||
May be used in sections : defaults | frontend | listen | backend
|
||||
no | yes | yes | no
|
||||
@ -1182,6 +1183,20 @@ bind [<address>]:<port> [, ...] name <name>
|
||||
the specified port. This keyword is available only when
|
||||
HAProxy is built with USE_LINUX_TPROXY=1.
|
||||
|
||||
defer_accept is an optional keyword which is supported only on certain
|
||||
Linux kernels. It states that a connection will only be
|
||||
accepted once some data arrive on it, or at worst after the
|
||||
first retransmit. This should be used only on protocols for
|
||||
which the client talks first (eg: HTTP). It can slightly
|
||||
improve performance by ensuring that most of the request is
|
||||
already available when the connection is accepted. On the
|
||||
other hand, it will not be able to detect connections which
|
||||
don't talk. It is important to note that this option is
|
||||
broken in all kernels up to 2.6.31, as the connection is
|
||||
never accepted until the client talks. This can cause issues
|
||||
with front firewalls which would see an established
|
||||
connection while the proxy will only see it in SYN_RECV.
|
||||
|
||||
It is possible to specify a list of address:port combinations delimited by
|
||||
commas. The frontend will then listen on all of these addresses. There is no
|
||||
fixed limit to the number of addresses and ports which can be listened on in
|
||||
|
@ -71,6 +71,7 @@
|
||||
#define LI_O_NOLINGER 0x0001 /* disable linger on this socket */
|
||||
#define LI_O_FOREIGN 0x0002 /* permit listening on foreing addresses */
|
||||
#define LI_O_NOQUICKACK 0x0004 /* disable quick ack of immediate data (linux) */
|
||||
#define LI_O_DEF_ACCEPT 0x0008 /* wait up to 1 second for data before accepting */
|
||||
|
||||
/* The listener will be directly referenced by the fdtab[] which holds its
|
||||
* socket. The listener provides the protocol-specific accept() function to
|
||||
|
@ -1143,6 +1143,24 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
||||
goto out;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
|
||||
#ifdef TCP_DEFER_ACCEPT
|
||||
struct listener *l;
|
||||
|
||||
for (l = curproxy->listen; l != last_listen; l = l->next)
|
||||
l->options |= LI_O_DEF_ACCEPT;
|
||||
|
||||
cur_arg ++;
|
||||
continue;
|
||||
#else
|
||||
Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
|
||||
file, linenum, args[0], args[cur_arg]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
|
||||
#ifdef CONFIG_HAP_LINUX_TPROXY
|
||||
struct listener *l;
|
||||
@ -1212,7 +1230,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
||||
continue;
|
||||
}
|
||||
|
||||
Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'name', 'id', 'mss' and 'interface' options.\n",
|
||||
Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
|
||||
file, linenum, args[0]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
|
@ -519,6 +519,16 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
|
||||
err |= ERR_WARN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(TCP_DEFER_ACCEPT)
|
||||
if (listener->options & LI_O_DEF_ACCEPT) {
|
||||
/* defer accept by up to one second */
|
||||
int accept_delay = 1;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &accept_delay, sizeof(accept_delay)) == -1) {
|
||||
msg = "cannot enable DEFER_ACCEPT";
|
||||
err |= ERR_WARN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (bind(fd, (struct sockaddr *)&listener->addr, listener->proto->sock_addrlen) == -1) {
|
||||
err |= ERR_RETRYABLE | ERR_ALERT;
|
||||
|
Loading…
x
Reference in New Issue
Block a user