ngompa / rpms / haproxy

Forked from rpms/haproxy 4 years ago
Clone

Blame SOURCES/haproxy-tcp-user-timeout.patch

5cd88c
From a8d1818959a7a2351d94e077b60e84b0b35ec231 Mon Sep 17 00:00:00 2001
5cd88c
From: Willy Tarreau <w@1wt.eu>
5cd88c
Date: Wed, 4 Feb 2015 00:45:58 +0100
5cd88c
Subject: [PATCH] MEDIUM: tcp: implement tcp-ut bind option to set
5cd88c
 TCP_USER_TIMEOUT
5cd88c
5cd88c
On Linux since 2.6.37, it's possible to set the socket timeout for
5cd88c
pending outgoing data, with an accuracy of 1 millisecond. This is
5cd88c
pretty handy to deal with dead connections to clients and or servers.
5cd88c
5cd88c
For now we only implement it on the frontend side (bind line) so
5cd88c
that when a client disappears from the net, we're able to quickly
5cd88c
get rid of its connection and possibly release a server connection.
5cd88c
This can be useful with long-lived connections where an application
5cd88c
level timeout is not suited because long pauses are expected (remote
5cd88c
terminals, connection pools, etc).
5cd88c
5cd88c
Thanks to Thijs Houtenbos and John Eckersberg for the suggestion.
5cd88c
---
5cd88c
 doc/configuration.txt    | 13 +++++++++++++
5cd88c
 include/types/listener.h |  1 +
5cd88c
 src/proto_tcp.c          | 42 +++++++++++++++++++++++++++++++++++++++++-
5cd88c
 3 files changed, 55 insertions(+), 1 deletion(-)
5cd88c
5cd88c
diff --git a/doc/configuration.txt b/doc/configuration.txt
5cd88c
index 6714afb..e131e99 100644
5cd88c
--- a/doc/configuration.txt
5cd88c
+++ b/doc/configuration.txt
5cd88c
@@ -8652,6 +8652,19 @@ strict-sni
5cd88c
   a certificate. The default certificate is not used.
5cd88c
   See the "crt" option for more information.
5cd88c
 
5cd88c
+tcp-ut <delay>
5cd88c
+  Sets the TCP User Timeout for all incoming connections instanciated from this
5cd88c
+  listening socket. This option is available on Linux since version 2.6.37. It
5cd88c
+  allows haproxy to configure a timeout for sockets which contain data not
5cd88c
+  receiving an acknoledgement for the configured delay. This is especially
5cd88c
+  useful on long-lived connections experiencing long idle periods such as
5cd88c
+  remote terminals or database connection pools, where the client and server
5cd88c
+  timeouts must remain high to allow a long period of idle, but where it is
5cd88c
+  important to detect that the client has disappeared in order to release all
5cd88c
+  resources associated with its connection (and the server's session). The
5cd88c
+  argument is a delay expressed in milliseconds by default. This only works
5cd88c
+  for regular TCP connections, and is ignored for other protocols.
5cd88c
+
5cd88c
 tfo
5cd88c
   Is an optional keyword which is supported only on Linux kernels >= 3.7. It
5cd88c
   enables TCP Fast Open on the listening socket, which means that clients which
5cd88c
diff --git a/include/types/listener.h b/include/types/listener.h
5cd88c
index 83b63af..2d71df6 100644
5cd88c
--- a/include/types/listener.h
5cd88c
+++ b/include/types/listener.h
5cd88c
@@ -175,6 +175,7 @@ struct listener {
5cd88c
 	struct list wait_queue;		/* link element to make the listener wait for something (LI_LIMITED)  */
5cd88c
 	unsigned int analysers;		/* bitmap of required protocol analysers */
5cd88c
 	int maxseg;			/* for TCP, advertised MSS */
5cd88c
+	int tcp_ut;                     /* for TCP, user timeout */
5cd88c
 	char *interface;		/* interface name or NULL */
5cd88c
 
5cd88c
 	struct list by_fe;              /* chaining in frontend's list of listeners */
5cd88c
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
5cd88c
index cfa62f7..e98a9fb 100644
5cd88c
--- a/src/proto_tcp.c
5cd88c
+++ b/src/proto_tcp.c
5cd88c
@@ -838,6 +838,15 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
5cd88c
 		}
5cd88c
 	}
5cd88c
 #endif
5cd88c
+#if defined(TCP_USER_TIMEOUT)
5cd88c
+	if (listener->tcp_ut) {
5cd88c
+		if (setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT,
5cd88c
+			       &listener->tcp_ut, sizeof(listener->tcp_ut)) == -1) {
5cd88c
+			msg = "cannot set TCP User Timeout";
5cd88c
+			err |= ERR_WARN;
5cd88c
+		}
5cd88c
+	}
5cd88c
+#endif
5cd88c
 #if defined(TCP_DEFER_ACCEPT)
5cd88c
 	if (listener->options & LI_O_DEF_ACCEPT) {
5cd88c
 		/* defer accept by up to one second */
5cd88c
@@ -1986,8 +1995,36 @@ static int bind_parse_mss(char **args, int cur_arg, struct proxy *px, struct bin
5cd88c
 }
5cd88c
 #endif
5cd88c
 
5cd88c
+#ifdef TCP_USER_TIMEOUT
5cd88c
+/* parse the "tcp-ut" bind keyword */
5cd88c
+static int bind_parse_tcp_ut(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
5cd88c
+{
5cd88c
+	const char *ptr = NULL;
5cd88c
+	struct listener *l;
5cd88c
+	unsigned int timeout;
5cd88c
+
5cd88c
+	if (!*args[cur_arg + 1]) {
5cd88c
+		memprintf(err, "'%s' : missing TCP User Timeout value", args[cur_arg]);
5cd88c
+		return ERR_ALERT | ERR_FATAL;
5cd88c
+	}
5cd88c
+
5cd88c
+	ptr = parse_time_err(args[cur_arg + 1], &timeout, TIME_UNIT_MS);
5cd88c
+	if (ptr) {
5cd88c
+		memprintf(err, "'%s' : expects a positive delay in milliseconds", args[cur_arg]);
5cd88c
+		return ERR_ALERT | ERR_FATAL;
5cd88c
+	}
5cd88c
+
5cd88c
+	list_for_each_entry(l, &conf->listeners, by_bind) {
5cd88c
+		if (l->addr.ss_family == AF_INET || l->addr.ss_family == AF_INET6)
5cd88c
+			l->tcp_ut = timeout;
5cd88c
+	}
5cd88c
+
5cd88c
+	return 0;
5cd88c
+}
5cd88c
+#endif
5cd88c
+
5cd88c
 #ifdef SO_BINDTODEVICE
5cd88c
-/* parse the "mss" bind keyword */
5cd88c
+/* parse the "interface" bind keyword */
5cd88c
 static int bind_parse_interface(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
5cd88c
 {
5cd88c
 	struct listener *l;
5cd88c
@@ -2056,6 +2093,9 @@ static struct bind_kw_list bind_kws = { "TCP", { }, {
5cd88c
 #ifdef TCP_MAXSEG
5cd88c
 	{ "mss",           bind_parse_mss,          1 }, /* set MSS of listening socket */
5cd88c
 #endif
5cd88c
+#ifdef TCP_USER_TIMEOUT
5cd88c
+	{ "tcp-ut",        bind_parse_tcp_ut,       1 }, /* set User Timeout on listening socket */
5cd88c
+#endif
5cd88c
 #ifdef TCP_FASTOPEN
5cd88c
 	{ "tfo",           bind_parse_tfo,          0 }, /* enable TCP_FASTOPEN of listening socket */
5cd88c
 #endif
5cd88c
-- 
5cd88c
1.9.3
5cd88c