ngompa / rpms / haproxy

Forked from rpms/haproxy 4 years ago
Clone

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

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