MINOR: protocol: move the global reuseport flag to the protocols
Some protocol support SO_REUSEPORT and others not. Some have such a
limitation in the kernel, and others in haproxy itself (e.g. sock_unix
cannot support multiple bindings since each one will unbind the previous
one). Also it's really protocol-dependent and not just family-dependent
because on Linux for some time it was supported for TCP and not UDP.
Let's move the definition to the protocols instead. Now it's preset in
tcp/udp/quic when SO_REUSEPORT is defined, and is otherwise left unset.
The enabled() config condition test validates IPv4 (generally sufficient),
and -dR / noreuseport all protocols at once.
diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h
index af7f26c..3a7b53b 100644
--- a/include/haproxy/global-t.h
+++ b/include/haproxy/global-t.h
@@ -58,7 +58,7 @@
/* platform-specific options */
#define GTUNE_USE_SPLICE (1<<4)
#define GTUNE_USE_GAI (1<<5)
-#define GTUNE_USE_REUSEPORT (1<<6)
+/* unused: (1<<6) */
#define GTUNE_RESOLVE_DONTFAIL (1<<7)
#define GTUNE_SOCKET_TRANSFER (1<<8)
diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h
index aa8aa66..eec65fe 100644
--- a/include/haproxy/protocol-t.h
+++ b/include/haproxy/protocol-t.h
@@ -64,6 +64,9 @@
#define CONNECT_DELACK_ALWAYS 0x00000004 /* Use a delayed ACK */
#define CONNECT_CAN_USE_TFO 0x00000008 /* We can use TFO for this connection */
+/* Flags for protocol->flags */
+#define PROTO_F_REUSEPORT_SUPPORTED 0x00000001 /* SO_REUSEPORT is supported */
+
/* protocol families define standard functions acting on a given address family
* for a socket implementation, such as AF_INET/PF_INET for example.
*/
diff --git a/src/cfgcond.c b/src/cfgcond.c
index 89036ad..117cf6c 100644
--- a/src/cfgcond.c
+++ b/src/cfgcond.c
@@ -14,6 +14,7 @@
#include <haproxy/arg.h>
#include <haproxy/cfgcond.h>
#include <haproxy/global.h>
+#include <haproxy/proto_tcp.h>
#include <haproxy/tools.h>
/* supported condition predicates */
@@ -195,7 +196,7 @@
else if (strcmp(str, "GETADDRINFO") == 0)
return !!(global.tune.options & GTUNE_USE_GAI);
else if (strcmp(str, "REUSEPORT") == 0)
- return !!(global.tune.options & GTUNE_USE_REUSEPORT);
+ return !!(proto_tcpv4.flags & PROTO_F_REUSEPORT_SUPPORTED);
else if (strcmp(str, "FAST-FORWARD") == 0)
return !!(global.tune.options & GTUNE_USE_FAST_FWD);
else if (strcmp(str, "SERVER-SSL-VERIFY-NONE") == 0)
diff --git a/src/cfgparse-global.c b/src/cfgparse-global.c
index e46672e..76d1769 100644
--- a/src/cfgparse-global.c
+++ b/src/cfgparse-global.c
@@ -20,6 +20,7 @@
#include <haproxy/global.h>
#include <haproxy/log.h>
#include <haproxy/peers.h>
+#include <haproxy/protocol.h>
#include <haproxy/tools.h>
/* some keywords that are still being parsed using strcmp() and are not
@@ -171,7 +172,7 @@
else if (strcmp(args[0], "noreuseport") == 0) {
if (alertif_too_many_args(0, file, linenum, args, &err_code))
goto out;
- global.tune.options &= ~GTUNE_USE_REUSEPORT;
+ protocol_clrf_all(PROTO_F_REUSEPORT_SUPPORTED);
}
else if (strcmp(args[0], "quiet") == 0) {
if (alertif_too_many_args(0, file, linenum, args, &err_code))
diff --git a/src/haproxy.c b/src/haproxy.c
index 5306113..b1574ab 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -1589,9 +1589,6 @@
#if defined(USE_GETADDRINFO)
global.tune.options |= GTUNE_USE_GAI;
#endif
-#if defined(SO_REUSEPORT)
- global.tune.options |= GTUNE_USE_REUSEPORT;
-#endif
#ifdef USE_THREAD
global.tune.options |= GTUNE_IDLE_POOL_SHARED;
#endif
@@ -1650,7 +1647,7 @@
#endif
#if defined(SO_REUSEPORT)
else if (*flag == 'd' && flag[1] == 'R')
- global.tune.options &= ~GTUNE_USE_REUSEPORT;
+ protocol_clrf_all(PROTO_F_REUSEPORT_SUPPORTED);
#endif
else if (*flag == 'd' && flag[1] == 'F')
global.tune.options &= ~GTUNE_USE_FAST_FWD;
diff --git a/src/proto_quic.c b/src/proto_quic.c
index 7658329..22776cd 100644
--- a/src/proto_quic.c
+++ b/src/proto_quic.c
@@ -105,6 +105,9 @@
.default_iocb = quic_lstnr_sock_fd_iocb,
.receivers = LIST_HEAD_INIT(proto_quic4.receivers),
.nb_receivers = 0,
+#ifdef SO_REUSEPORT
+ .flags = PROTO_F_REUSEPORT_SUPPORTED,
+#endif
};
INITCALL1(STG_REGISTER, protocol_register, &proto_quic4);
@@ -146,6 +149,9 @@
.default_iocb = quic_lstnr_sock_fd_iocb,
.receivers = LIST_HEAD_INIT(proto_quic6.receivers),
.nb_receivers = 0,
+#ifdef SO_REUSEPORT
+ .flags = PROTO_F_REUSEPORT_SUPPORTED,
+#endif
};
INITCALL1(STG_REGISTER, protocol_register, &proto_quic6);
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 2e5c36a..45ce27f 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -88,6 +88,9 @@
.default_iocb = sock_accept_iocb,
.receivers = LIST_HEAD_INIT(proto_tcpv4.receivers),
.nb_receivers = 0,
+#ifdef SO_REUSEPORT
+ .flags = PROTO_F_REUSEPORT_SUPPORTED,
+#endif
};
INITCALL1(STG_REGISTER, protocol_register, &proto_tcpv4);
@@ -131,6 +134,9 @@
.default_iocb = sock_accept_iocb,
.receivers = LIST_HEAD_INIT(proto_tcpv6.receivers),
.nb_receivers = 0,
+#ifdef SO_REUSEPORT
+ .flags = PROTO_F_REUSEPORT_SUPPORTED,
+#endif
};
INITCALL1(STG_REGISTER, protocol_register, &proto_tcpv6);
diff --git a/src/proto_udp.c b/src/proto_udp.c
index 1fd92c7..54f87d0 100644
--- a/src/proto_udp.c
+++ b/src/proto_udp.c
@@ -74,6 +74,9 @@
.rx_unbind = sock_unbind,
.receivers = LIST_HEAD_INIT(proto_udp4.receivers),
.nb_receivers = 0,
+#ifdef SO_REUSEPORT
+ .flags = PROTO_F_REUSEPORT_SUPPORTED,
+#endif
};
INITCALL1(STG_REGISTER, protocol_register, &proto_udp4);
@@ -108,6 +111,9 @@
.rx_unbind = sock_unbind,
.receivers = LIST_HEAD_INIT(proto_udp6.receivers),
.nb_receivers = 0,
+#ifdef SO_REUSEPORT
+ .flags = PROTO_F_REUSEPORT_SUPPORTED,
+#endif
};
INITCALL1(STG_REGISTER, protocol_register, &proto_udp6);
diff --git a/src/sock_inet.c b/src/sock_inet.c
index d225a9d..028ffaa 100644
--- a/src/sock_inet.c
+++ b/src/sock_inet.c
@@ -376,7 +376,7 @@
/* OpenBSD and Linux 3.9 support this. As it's present in old libc versions of
* Linux, it might return an error that we will silently ignore.
*/
- if (!ext && (global.tune.options & GTUNE_USE_REUSEPORT))
+ if (!ext && (rx->proto->flags & PROTO_F_REUSEPORT_SUPPORTED))
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
#endif
@@ -384,7 +384,7 @@
/* FreeBSD 12 and above use this to load-balance incoming connections.
* This is limited to 256 listeners per group however.
*/
- if (!ext && (global.tune.options & GTUNE_USE_REUSEPORT))
+ if (!ext && (rx->proto->flags & PROTO_F_REUSEPORT_SUPPORTED))
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT_LB, &one, sizeof(one));
#endif