Re: [PATCH] Add support to tcp socket linger tweaking

From: Willy Tarreau <w#1wt.eu>
Date: Sat, 29 Sep 2007 10:33:54 +0200


Hi Alex!

On Tue, Sep 25, 2007 at 03:42:18PM +0200, Alexandre Cassen wrote:
> Hello,
>
> The following patch will give the ability to tweak socket linger mode.
> You can use this option with "option linger" inside fronted or backend
> configuration declaration.

There is something which puzzles me, because I'm not used to play with linger. Does the lingering apply after the last data segment has been ACKed or could it cause some data retransmits to be lost ? If the former, then yes it's wise to shorten the timeout, but if the later, maybe we should be able to tweak the value ? In all cases, I think it could be useful in the health-checking code too.

BTW, if the option does not require any tweaking, maybe we should call it "nolinger" since its goal is precisely to disable lingering. I'm holding the patch so that we can discuss the feature a bit before merging it.

Also, I don't know if you have noticed, but there are quite a number of syscalls performed upon each accept(). A lot of setsockopt(), and now possibly the setsockopt(nolinger). I never found any way to make a socket inherit from the listen socket's options. Would you happen to know a trick to do this ? Otherwise, maybe we should slightly patch the kernel to provide this feature (eg: SO_INHERIT_OPTIONS), which haproxy would check during the listen so that it knows it has nothing to do to prepare the socket after an accept().

> regards,
> Alexandre

Thanks,
Willy

> Index: include/types/global.h
> ===================================================================
> --- include/types/global.h (révision 1)
> +++ include/types/global.h (révision 2)
> @@ -73,6 +73,7 @@
> extern char trash[BUFSIZE];
> extern const int zero;
> extern const int one;
> +extern const struct linger nolinger;
> extern int stopping; /* non zero means stopping in progress */
>
> #endif /* _TYPES_GLOBAL_H */
> Index: include/types/backend.h
> ===================================================================
> --- include/types/backend.h (révision 1)
> +++ include/types/backend.h (révision 2)
> @@ -60,6 +60,7 @@
> #define PR_O_BALANCE_UH 0x10000000 /* balance on URI hash */
> #define PR_O_BALANCE (PR_O_BALANCE_RR | PR_O_BALANCE_SH | PR_O_BALANCE_UH)
> #define PR_O_SMTP_CHK 0x20000000 /* use SMTP EHLO check for server health - pvandijk#vision6.com.au */
> +#define PR_O_TCP_LINGER 0x40000000 /* linger handling client connection */
>
>
> #endif /* _TYPES_BACKEND_H */
> Index: src/client.c
> ===================================================================
> --- src/client.c (révision 1)
> +++ src/client.c (révision 2)
> @@ -165,6 +165,9 @@
> if (p->options & PR_O_TCP_CLI_KA)
> setsockopt(cfd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one));
>
> + if (p->options & PR_O_TCP_LINGER)
> + setsockopt(cfd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
> +
> t->wq = NULL;
> t->qlist.p = NULL;
> t->state = TASK_IDLE;
> Index: src/proxy.c
> ===================================================================
> --- src/proxy.c (révision 1)
> +++ src/proxy.c (révision 2)
> @@ -26,6 +26,7 @@
> #include <types/polling.h>
>
> #include <proto/client.h>
> +#include <proto/backend.h>
> #include <proto/fd.h>
> #include <proto/log.h>
> #include <proto/proxy.h>
> @@ -113,6 +114,9 @@
> Alert("cannot do so_reuseaddr for proxy %s. Continuing.\n",
> curproxy->id);
> }
> +
> + if (curproxy->options & PR_O_TCP_LINGER)
> + setsockopt(fd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
>
> #ifdef SO_REUSEPORT
> /* OpenBSD supports this. As it's present in old libc versions of Linux,
> Index: src/backend.c
> ===================================================================
> --- src/backend.c (révision 1)
> +++ src/backend.c (révision 2)
> @@ -408,6 +408,9 @@
> if (s->be->options & PR_O_TCP_SRV_KA)
> setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one));
>
> + if (s->be->options & PR_O_TCP_LINGER)
> + setsockopt(fd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
> +
> /* allow specific binding :
> * - server-specific at first
> * - proxy-specific next
> Index: src/cfgparse.c
> ===================================================================
> --- src/cfgparse.c (révision 1)
> +++ src/cfgparse.c (révision 2)
> @@ -92,6 +92,7 @@
> { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
> { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
> { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
> + { "linger", PR_O_TCP_LINGER, PR_CAP_FE | PR_CAP_BE, 0 },
> { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
> { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
> { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
> Index: src/haproxy.c
> ===================================================================
> --- src/haproxy.c (révision 1)
> +++ src/haproxy.c (révision 2)
> @@ -135,6 +135,7 @@
>
> const int zero = 0;
> const int one = 1;
> +const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
>
> /*
> * Syslog facilities and levels. Conforming to RFC3164.
Received on 2007/09/29 10:33

This archive was generated by hypermail 2.2.0 : 2007/11/04 19:21 CET