]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: startup detect for quic-conn owned socket support
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 21 Nov 2022 09:04:14 +0000 (10:04 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 2 Dec 2022 13:45:43 +0000 (14:45 +0100)
To be able to use individual sockets for QUIC connections, we rely on
the OS network stack which must support UDP sockets binding on the same
local address.

Add a detection code for this feature executed on startup. When the
first QUIC listener socket is binded, a test socket is created and
binded on the same address. If the bind call fails, we consider that
it's impossible to use individual socket for QUIC connections.

A new global option GTUNE_QUIC_SOCK_PER_CONN is defined. If startup
detect fails, this value is resetted from global options. For the
moment, there is no code to activate the option : this will be in a
follow-up patch with the introduction of a new configuration option.

This change is part of quic-conn owned socket implementation.
It may be backported to 2.7 after a period of observation.

include/haproxy/global-t.h
src/proto_quic.c

index 0cdb361aeab6c7897facb2d8efa1b07417292c8d..2e9b61b24e54302fcb2d251146707622343fee9d 100644 (file)
@@ -78,6 +78,7 @@
 #define GTUNE_DISABLE_H2_WEBSOCKET (1<<21)
 #define GTUNE_DISABLE_ACTIVE_CLOSE (1<<22)
 #define GTUNE_QUICK_EXIT         (1<<23)
+#define GTUNE_QUIC_SOCK_PER_CONN (1<<24)
 
 /* SSL server verify mode */
 enum {
index 7267b67e7d198bd5f8106a40eb864a15b2e68ef8..003e510b64ac44cfba18686fa7b7feff49c2055c 100644 (file)
@@ -570,6 +570,40 @@ static int quic_alloc_rxbufs_listener(struct listener *l)
        return 0;
 }
 
+/* Check if platform supports the required feature set for quic-conn owned
+ * socket. <l> listener must already be binded; a dummy socket will be opened
+ * on the same address as one of the support test.
+ *
+ * Returns true if platform is deemed compatible else false.
+ */
+static int quic_test_sock_per_conn_support(struct listener *l)
+{
+       const struct receiver *rx = &l->rx;
+       int ret = 1, fdtest;
+
+       /* Check if platform support multiple UDP sockets bind on the same
+        * local address. Create a dummy socket and bind it on the same address
+        * as <l> listener. If bind system call fails, deactivate socket per
+        * connection. All other errors are not taken into account.
+        */
+       if (ret) {
+               fdtest = socket(rx->proto->fam->sock_domain,
+                               rx->proto->sock_type, rx->proto->sock_prot);
+               if (fdtest > 0) {
+                       if (setsockopt(fdtest, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) &&
+                           bind(fdtest, (struct sockaddr *)&rx->addr, rx->proto->fam->sock_addrlen) < 0) {
+                               ha_alert("Your platform does not seem to support multiple UDP sockets binded on the same address. "
+                                        "QUIC connections will use listener socket.\n");
+                               ret = 0;
+                       }
+
+                       close(fdtest);
+               }
+       }
+
+       return ret;
+}
+
 /* This function tries to bind a QUIC4/6 listener. It may return a warning or
  * an error message in <errmsg> if the message is at most <errlen> bytes long
  * (including '\0'). Note that <errmsg> may be NULL if <errlen> is also zero.
@@ -626,6 +660,11 @@ static int quic_bind_listener(struct listener *listener, char *errmsg, int errle
                goto udp_return;
        }
 
+       if (global.tune.options & GTUNE_QUIC_SOCK_PER_CONN) {
+               if (!quic_test_sock_per_conn_support(listener))
+                       global.tune.options &= ~GTUNE_QUIC_SOCK_PER_CONN;
+       }
+
        listener_set_state(listener, LI_LISTEN);
 
  udp_return: