From: Amaury Denoyelle Date: Wed, 1 Feb 2023 08:28:32 +0000 (+0100) Subject: MINOR: quic: mark quic-conn as jobs on socket allocation X-Git-Tag: v2.8-dev5~160 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fb375574f947143e185225558c274ac00a3f8cb4;p=thirdparty%2Fhaproxy.git MINOR: quic: mark quic-conn as jobs on socket allocation 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. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index a778c4788b..e769350f86 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -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 diff --git a/doc/management.txt b/doc/management.txt index a56a9d5ea0..7586affe34 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -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 * : 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 ------------------------------ diff --git a/src/quic_conn.c b/src/quic_conn.c index 9661cc6fdc..8dd2b4846f 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -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 on socket allocation failure. */ qc_alloc_fd(qc, local_addr, peer_addr); }