[MINOR] add support for the "backlog" parameter

Add the "backlog" parameter to frontends, to give hints to
the system about the approximate listen backlog desired size.

In order to protect against SYN flood attacks, one solution is
to increase the system's SYN backlog size. Depending on the
system, sometimes it is just tunable via a system parameter,
sometimes it is not adjustable at all, and sometimes the system
relies on hints given by the application at the time of the
listen() syscall. By default, HAProxy passes the frontend's
maxconn value to the listen() syscall. On systems which can
make use of this value, it can sometimes be useful to be able
to specify a different value, hence this backlog parameter.
This commit is contained in:
Willy Tarreau 2008-01-06 10:55:10 +01:00
parent c27debfe56
commit c73ce2b111
7 changed files with 66 additions and 4 deletions

View File

@ -4,7 +4,7 @@
----------------------
version 1.3.14.2
willy tarreau
2007/12/27
2008/01/05
This document covers the configuration language as implemented in the version
@ -502,6 +502,7 @@ keyword defaults frontend listen backend
----------------------+----------+----------+---------+---------
acl - X X X
appsession - - X X
backlog X X X -
balance X - X X
bind - X X -
block - X X X
@ -653,6 +654,31 @@ appsession <cookie> len <length> timeout <holdtime>
See also : "cookie", "capture cookie" and "balance".
backlog <conns>
Give hints to the system about the approximate listen backlog desired size
May be used in sections : defaults | frontend | listen | backend
yes | yes | yes | no
Arguments :
<conns> is the number of pending connections. Depending on the operating
system, it may represent the number of already acknowledged
connections, of non-acknowledged ones, or both.
In order to protect against SYN flood attacks, one solution is to increase
the system's SYN backlog size. Depending on the system, sometimes it is just
tunable via a system parameter, sometimes it is not adjustable at all, and
sometimes the system relies on hints given by the application at the time of
the listen() syscall. By default, HAProxy passes the frontend's maxconn value
to the listen() syscall. On systems which can make use of this value, it can
sometimes be useful to be able to specify a different value, hence this
backlog parameter.
On Linux 2.4, the parameter is ignored by the system. On Linux 2.6, it is
used as a hint and the system accepts up to the smallest greater power of
two, and never more than some limits (usually 32768).
See also : "maxconn" and the target operating system's tuning guide.
balance <algorithm> [ <arguments> ]
Define the load balancing algorithm to be used in a backend.
May be used in sections : defaults | frontend | listen | backend

View File

@ -78,6 +78,7 @@ struct listener {
struct protocol *proto; /* protocol this listener belongs to */
int nbconn; /* current number of connections on this listener */
int maxconn; /* maximum connections allowed on this listener */
unsigned int backlog; /* if set, listen backlog */
struct listener *next; /* next address for the same proxy, or NULL */
struct list proto_list; /* list in the protocol header */
int (*accept)(int fd); /* accept() function passed to fdtab[] */

View File

@ -228,6 +228,7 @@ struct proxy {
struct chunk errmsg[HTTP_ERR_SIZE]; /* default or customized error messages for known errors */
int uuid; /* universally unique proxy ID, used for SNMP */
int next_svid; /* next server-id, used for SNMP */
unsigned int backlog; /* force the frontend's listen backlog */
};
struct switching_rule {

View File

@ -614,6 +614,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
if (curproxy->cap & PR_CAP_FE) {
curproxy->maxconn = defproxy.maxconn;
curproxy->backlog = defproxy.backlog;
/* initialize error relocations */
for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
@ -1365,6 +1366,16 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
}
curproxy->maxconn = atol(args[1]);
}
else if (!strcmp(args[0], "backlog")) { /* backlog */
if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
return 0;
if (*(args[1]) == 0) {
Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
return -1;
}
curproxy->backlog = atol(args[1]);
}
else if (!strcmp(args[0], "fullconn")) { /* fullconn */
if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
return 0;
@ -2865,6 +2876,7 @@ int readcfgfile(const char *file)
if (curproxy->options & PR_O_TCP_NOLING)
listener->options |= LI_O_NOLINGER;
listener->maxconn = curproxy->maxconn;
listener->backlog = curproxy->backlog;
listener->timeout = &curproxy->timeout.client;
listener->accept = event_accept;
listener->private = curproxy;

View File

@ -160,7 +160,7 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
goto tcp_close_return;
}
if (listen(fd, listener->maxconn) == -1) {
if (listen(fd, listener->backlog ? listener->backlog : listener->maxconn) == -1) {
err |= ERR_RETRYABLE | ERR_ALERT;
msg = "cannot listen to socket";
goto tcp_close_return;

View File

@ -369,7 +369,7 @@ void pause_proxy(struct proxy *p)
struct listener *l;
for (l = p->listen; l != NULL; l = l->next) {
if (shutdown(l->fd, SHUT_WR) == 0 &&
listen(l->fd, p->maxconn) == 0 &&
listen(l->fd, p->backlog ? p->backlog : p->maxconn) == 0 &&
shutdown(l->fd, SHUT_RD) == 0) {
EV_FD_CLR(l->fd, DIR_RD);
if (p->state != PR_STERROR)
@ -435,7 +435,7 @@ void listen_proxies(void)
send_log(p, LOG_WARNING, "Enabling proxy %s.\n", p->id);
for (l = p->listen; l != NULL; l = l->next) {
if (listen(l->fd, p->maxconn) == 0) {
if (listen(l->fd, p->backlog ? p->backlog : p->maxconn) == 0) {
if (actconn < global.maxconn && p->feconn < p->maxconn) {
EV_FD_SET(l->fd, DIR_RD);
p->state = PR_STRUN;

22
tests/test-backlog.cfg Normal file
View File

@ -0,0 +1,22 @@
# This is a test configuration.
# It is used to check that the backlog queue works as expected.
global
maxconn 200
stats timeout 3s
frontend backlog_def
mode http
timeout client 15s
maxconn 100
bind :8000
option httpclose
frontend backlog_max
mode http
timeout client 15s
maxconn 100
backlog 100000
bind :8001
option httpclose