From: Frederic Lecaille Date: Tue, 24 Jun 2025 08:55:22 +0000 (+0200) Subject: MINOR: quic-be: add a "CC connection" backend TX buffer pool X-Git-Tag: v3.3-dev2~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9cb2acd2f274c08eaa87b61c59684ffb79768bfe;p=thirdparty%2Fhaproxy.git MINOR: quic-be: add a "CC connection" backend TX buffer pool A QUIC client must be able to close a connection sending Initial packets. But QUIC client Initial packets must always be at least 1200 bytes long. To reduce the memory use of TX buffers of a connection when in "closing" state, a pool was dedicated for this purpose but with a too much reduced TX buffer size (QUIC_MAX_CC_BUFSIZE). This patch adds a "closing state connection" TX buffer pool with the same role for QUIC backends. --- diff --git a/include/haproxy/quic_tx-t.h b/include/haproxy/quic_tx-t.h index 19ad777ed..fde45221c 100644 --- a/include/haproxy/quic_tx-t.h +++ b/include/haproxy/quic_tx-t.h @@ -4,6 +4,7 @@ #define QUIC_MIN_CC_PKTSIZE 128 #define QUIC_DGRAM_HEADLEN (sizeof(uint16_t) + sizeof(void *)) #define QUIC_MAX_CC_BUFSIZE (2 * (QUIC_MIN_CC_PKTSIZE + QUIC_DGRAM_HEADLEN)) +#define QUIC_BE_MAX_CC_BUFSIZE MAX(QUIC_INITIAL_IPV6_MTU, QUIC_INITIAL_IPV4_MTU) /* Sendmsg input buffer cannot be bigger than 65535 bytes. This comes from UDP * header which uses a 2-bytes length field. QUIC datagrams are limited to 1252 @@ -21,6 +22,7 @@ extern struct pool_head *pool_head_quic_tx_packet; extern struct pool_head *pool_head_quic_cc_buf; +extern struct pool_head *pool_head_quic_be_cc_buf; /* Flag a sent packet as being an ack-eliciting packet. */ #define QUIC_FL_TX_PACKET_ACK_ELICITING (1UL << 0) diff --git a/src/quic_conn.c b/src/quic_conn.c index 4cbfa2c53..600d2893c 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -650,7 +650,12 @@ static void quic_release_cc_conn(struct quic_conn_closed *cc_qc) free_quic_conn_cids(qc); pool_free(pool_head_quic_cids, cc_qc->cids); cc_qc->cids = NULL; - pool_free(pool_head_quic_cc_buf, cc_qc->cc_buf_area); + if (objt_listener(cc_qc->target)) { + pool_free(pool_head_quic_cc_buf, cc_qc->cc_buf_area); + } + else { + pool_free(pool_head_quic_be_cc_buf, cc_qc->cc_buf_area); + } cc_qc->cc_buf_area = NULL; /* free the SSL sock context */ pool_free(pool_head_quic_conn_closed, cc_qc); diff --git a/src/quic_tx.c b/src/quic_tx.c index 611788b15..01b53b60e 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -33,6 +33,7 @@ DECLARE_POOL(pool_head_quic_tx_packet, "quic_tx_packet", sizeof(struct quic_tx_packet)); DECLARE_POOL(pool_head_quic_cc_buf, "quic_cc_buf", QUIC_MAX_CC_BUFSIZE); +DECLARE_POOL(pool_head_quic_be_cc_buf, "quic_be_cc_buf", QUIC_BE_MAX_CC_BUFSIZE); static struct quic_tx_packet *qc_build_pkt(unsigned char **pos, const unsigned char *buf_end, struct quic_enc_level *qel, struct quic_tls_ctx *ctx, @@ -129,16 +130,28 @@ struct buffer *qc_get_txb(struct quic_conn *qc) struct buffer *buf; if (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE) { + struct pool_head *ph; + size_t psz; + + if (objt_listener(qc->target)) { + ph = pool_head_quic_cc_buf; + psz = QUIC_MAX_CC_BUFSIZE; + } + else { + ph = pool_head_quic_be_cc_buf; + psz = QUIC_BE_MAX_CC_BUFSIZE; + } + TRACE_PROTO("Immediate close required", QUIC_EV_CONN_PHPKTS, qc); buf = &qc->tx.cc_buf; if (b_is_null(buf)) { - qc->tx.cc_buf_area = pool_alloc(pool_head_quic_cc_buf); + qc->tx.cc_buf_area = pool_alloc(ph); if (!qc->tx.cc_buf_area) goto err; } /* In every case, initialize ->tx.cc_buf */ - qc->tx.cc_buf = b_make(qc->tx.cc_buf_area, QUIC_MAX_CC_BUFSIZE, 0, 0); + qc->tx.cc_buf = b_make(qc->tx.cc_buf_area, psz, 0, 0); } else { buf = qc_txb_alloc(qc);