]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: protocol: move the global reuseport flag to the protocols
authorWilly Tarreau <w@1wt.eu>
Sat, 22 Apr 2023 13:09:07 +0000 (15:09 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 23 Apr 2023 07:46:15 +0000 (09:46 +0200)
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.

include/haproxy/global-t.h
include/haproxy/protocol-t.h
src/cfgcond.c
src/cfgparse-global.c
src/haproxy.c
src/proto_quic.c
src/proto_tcp.c
src/proto_udp.c
src/sock_inet.c

index af7f26cfb1a02a67180bfe57f52668e93246c8ca..3a7b53b73074b706f474ed499d88fd5713a4c34b 100644 (file)
@@ -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)
index aa8aa662c448f866367c7bbf86bf92582e0216f7..eec65fed4266e1519ce9f852bf782fab2597e528 100644 (file)
@@ -64,6 +64,9 @@ enum proto_type {
 #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.
  */
index 89036ada3faf6b4a8acca5941511e3c5c4a87972..117cf6c2891ebfc8e92d0edcdcb029447dae6057 100644 (file)
@@ -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 @@ static int cfg_eval_cond_enabled(const char *str)
        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)
index e46672e15961c22c7dd8d4f517be98d84f87f4c1..76d1769043c935d23c1260b99bc90b4f400a0ab3 100644 (file)
@@ -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 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
        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))
index 53061131995445241b5fe0a8d072f02c4a904ae5..b1574abfd680c55fb49ef8e5d88589543e73cf2b 100644 (file)
@@ -1589,9 +1589,6 @@ static void init_args(int argc, char **argv)
 #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 @@ static void init_args(int argc, char **argv)
 #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;
index 76583298e43d0a8217b73f594d68d3290c27c9d7..22776cd83c38dae29ae9740cf664dcce444aaf14 100644 (file)
@@ -105,6 +105,9 @@ struct protocol proto_quic4 = {
        .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 @@ struct protocol proto_quic6 = {
        .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);
index 2e5c36a51e8992ceefb6ebf1127e173f552a13b2..45ce27f11e01724fbcfb95e9d39ab319efe543c0 100644 (file)
@@ -88,6 +88,9 @@ struct protocol proto_tcpv4 = {
        .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 @@ struct protocol proto_tcpv6 = {
        .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);
index 1fd92c7ce793bd952880a4b3e16a3324e4c2d797..54f87d0ca079999375e276c02aa00dbd222a9a1a 100644 (file)
@@ -74,6 +74,9 @@ struct protocol proto_udp4 = {
        .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 @@ struct protocol proto_udp6 = {
        .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);
index d225a9dc94fdd0dc3f597875710f3842affbbae5..028ffaa6809b10dfe570a4d7e85074f5553f8a39 100644 (file)
@@ -376,7 +376,7 @@ int sock_inet_bind_receiver(struct receiver *rx, char **errmsg)
        /* 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 @@ int sock_inet_bind_receiver(struct receiver *rx, char **errmsg)
        /* 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