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.
This commit is contained in:
Amaury Denoyelle 2023-02-01 09:28:32 +01:00
parent b3aa07c78e
commit fb375574f9
3 changed files with 17 additions and 7 deletions

View 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

View 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
------------------------------

View 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);
}