]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: mark quic-conn as jobs on socket allocation
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 1 Feb 2023 08:28:32 +0000 (09:28 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 20 Feb 2023 10:20:18 +0000 (11:20 +0100)
To prevent data loss for QUIC connections, haproxy global variable jobs
is incremented each time a quic-conn socket is allocated. This allows
the QUIC connection to terminate all its transfer operation during proxy
soft-stop. Without this patch, the process will be terminated without
waiting for QUIC connections.

Note that this is done in qc_alloc_fd(). This means only QUIC connection
with their owned socket will properly support soft-stop. In the other
case, the connection will be interrupted abruptly as before. Similarly,
jobs decrement is conducted in qc_release_fd().

This should be backported up to 2.7.

doc/configuration.txt
doc/management.txt
src/quic_conn.c

index a778c4788b0ef5fe5fe7efc349c4395de87d86e5..e769350f86267a15c2e94aba694456c4f93f8d8e 100644 (file)
@@ -3159,9 +3159,11 @@ tune.quic.socket-owner { listener | connection }
 
   When default "connection" value is set, a dedicated socket will be allocated
   by every QUIC connections. This option is the preferred one to achieve the
-  best performance with a large QUIC traffic. However, this relies on some
-  advanced features from the UDP network stack. If your platform is deemed not
-  compatible, haproxy will automatically switch to "listener" mode on startup.
+  best performance with a large QUIC traffic. This is also the only way to
+  ensure soft-stop is conducted properly without data loss for QUIC
+  connections. However, this relies on some advanced features from the UDP
+  network stack. If your platform is deemed not compatible, haproxy will
+  automatically switch to "listener" mode on startup.
 
   The "listener" value indicates that QUIC transfers will occur on the shared
   listener socket. This option can be a good compromise for small traffic as it
index a56a9d5ea0d899bb4f2f141f5f710a1842da4afe..7586affe345afd5f1e1d0a1c463000c76f380e13 100644 (file)
@@ -434,7 +434,7 @@ list of options is :
     is a list of pids to signal (one per argument). The list ends on any
     option starting with a "-". It is not a problem if the list of pids is
     empty, so that it can be built on the fly based on the result of a command
-    like "pidof" or "pgrep". QUIC connections will be aborted.
+    like "pidof" or "pgrep".
 
   -st <pid>* : send the "terminate" signal (SIGTERM) to older processes after
     boot completion to terminate them immediately without finishing what they
@@ -670,9 +670,6 @@ don't have enough load to trigger the race conditions. And for most high traffic
 users, the failure rate is still fairly within the noise margin provided that at
 least SO_REUSEPORT is properly supported on their systems.
 
-QUIC limitations: soft-stop is not supported. In case of reload, QUIC connections
-will not be preserved.
-
 5. File-descriptor limitations
 ------------------------------
 
index 9661cc6fdc43e298c028eb70947cac1a5cbe8da3..8dd2b4846f95a1ed75c2a689b843b4da384a83c8 100644 (file)
@@ -5022,6 +5022,12 @@ static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
            is_addr(local_addr)) {
                TRACE_USER("Allocate a socket for QUIC connection", QUIC_EV_CONN_INIT, qc);
                qc_alloc_fd(qc, local_addr, peer_addr);
+
+               /* haproxy soft-stop is supported only for QUIC connections
+                * with their owned socket.
+                */
+               if (qc_test_fd(qc))
+                       _HA_ATOMIC_INC(&jobs);
        }
 
        /* insert the allocated CID in the receiver datagram handler tree */
@@ -5144,6 +5150,9 @@ void quic_conn_release(struct quic_conn *qc)
        /* We must not free the quic-conn if the MUX is still allocated. */
        BUG_ON(qc->mux_state == QC_MUX_READY);
 
+       if (qc_test_fd(qc))
+               _HA_ATOMIC_DEC(&jobs);
+
        /* Close quic-conn socket fd. */
        qc_release_fd(qc, 0);
 
@@ -5235,6 +5244,7 @@ void quic_conn_release(struct quic_conn *qc)
 
        pool_free(pool_head_quic_conn_rxbuf, qc->rx.buf.area);
        pool_free(pool_head_quic_conn, qc);
+
        TRACE_PROTO("QUIC conn. freed", QUIC_EV_CONN_FREED, qc);
 
        TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
@@ -6537,6 +6547,7 @@ static int qc_handle_conn_migration(struct quic_conn *qc,
                /* TODO try to reuse socket instead of closing it and opening a new one. */
                TRACE_STATE("Connection migration detected, allocate a new connection socket", QUIC_EV_CONN_LPKT, qc);
                qc_release_fd(qc, 1);
+               /* TODO need to adjust <jobs> on socket allocation failure. */
                qc_alloc_fd(qc, local_addr, peer_addr);
        }