From d6646dddccb1aae08f60717b5b6743c513c37299 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Wed, 26 Apr 2023 17:15:37 +0200 Subject: [PATCH] MINOR: quic: finalize affinity change as soon as possible During accept, a quic-conn is rebind to a new thread. This process is done in two times : * first on the original thread via qc_set_tid_affinity() * then on the newly assigned thread via qc_finalize_affinity_rebind() Most quic_conn operations (I/O tasklet, task and quic_conn FD socket read) are reactivated ony after the second step. However, there is a possibility that datagrams are handled before it via quic_dgram_parse() when using listener sockets. This does not seem to cause any issue but this may cause unexpected behavior in the future. To simplify this, qc_finalize_affinity_rebind() will be called both by qc_xprt_start() and quic_dgram_parse(). Only one invocation will be performed thanks to the new flag QUIC_FL_CONN_AFFINITY_CHANGED. This should be backported up to 2.7. --- include/haproxy/quic_conn-t.h | 1 + src/quic_conn.c | 8 ++++++++ src/xprt_quic.c | 3 ++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/haproxy/quic_conn-t.h b/include/haproxy/quic_conn-t.h index 113cc61bb..9bd911914 100644 --- a/include/haproxy/quic_conn-t.h +++ b/include/haproxy/quic_conn-t.h @@ -628,6 +628,7 @@ enum qc_mux_state { #define QUIC_FL_CONN_RETRANS_NEEDED (1U << 7) #define QUIC_FL_CONN_RETRANS_OLD_DATA (1U << 8) /* retransmission in progress for probing with already sent data */ #define QUIC_FL_CONN_TLS_ALERT (1U << 9) +#define QUIC_FL_CONN_AFFINITY_CHANGED (1U << 10) /* qc_finalize_affinity_rebind() must be called to finalize affinity rebind */ /* gap here */ #define QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED (1U << 11) /* The half-open connection counter was decremented */ #define QUIC_FL_CONN_HANDSHAKE_SPEED_UP (1U << 12) /* Handshake speeding up was done */ diff --git a/src/quic_conn.c b/src/quic_conn.c index d76802238..254ce58d5 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -8277,6 +8277,9 @@ int quic_dgram_parse(struct quic_dgram *dgram, struct quic_conn *from_qc, dgram->qc = qc; } + if (qc->flags & QUIC_FL_CONN_AFFINITY_CHANGED) + qc_finalize_affinity_rebind(qc); + if (qc_rx_check_closing(qc, pkt)) { /* Skip the entire datagram. */ pkt->len = end - pos; @@ -8541,6 +8544,7 @@ int qc_set_tid_affinity(struct quic_conn *qc, uint new_tid, struct listener *new /* Rebinding is considered done when CID points to the new thread. No * access should be done to quic-conn instance after it. */ + qc->flags |= QUIC_FL_CONN_AFFINITY_CHANGED; HA_ATOMIC_STORE(&conn_id->tid, new_tid); qc = NULL; @@ -8561,6 +8565,10 @@ void qc_finalize_affinity_rebind(struct quic_conn *qc) { TRACE_ENTER(QUIC_EV_CONN_SET_AFFINITY, qc); + /* This function must not be called twice after an affinity rebind. */ + BUG_ON(!(qc->flags & QUIC_FL_CONN_AFFINITY_CHANGED)); + qc->flags &= ~QUIC_FL_CONN_AFFINITY_CHANGED; + /* Reactivate FD polling if connection socket is active. */ qc_want_recv(qc); diff --git a/src/xprt_quic.c b/src/xprt_quic.c index be9b09c89..c3b9c6a73 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -132,7 +132,8 @@ static int qc_xprt_start(struct connection *conn, void *ctx) qc = conn->handle.qc; TRACE_ENTER(QUIC_EV_CONN_NEW, qc); - qc_finalize_affinity_rebind(qc); + if (qc->flags & QUIC_FL_CONN_AFFINITY_CHANGED) + qc_finalize_affinity_rebind(qc); /* mux-quic can now be considered ready. */ qc->mux_state = QC_MUX_READY;