From b8e65423f3c9521158821cd13b269842a39ba0aa Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Thu, 23 Apr 2026 14:41:34 +0200 Subject: [PATCH] MINOR: mux_quic: use dynamic conn buffers for QMux Allocate and release as needed the QCC buffers used for QMux protocol. This should reduce the memory consumption of QMux. This is performed both for send and receive buffers. Along with this, always free these buffers in qcc_release() to prevent a memory leak. --- src/mux_quic.c | 22 +++++++++++----------- src/mux_quic_qstrm.c | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/mux_quic.c b/src/mux_quic.c index e82569f07..d2a1e6e3a 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -3525,6 +3525,12 @@ static void qcc_release(struct qcc *qcc) } TRACE_PROTO("application layer released", QMUX_EV_QCC_END, conn); + if (conn && !conn_is_quic(conn)) { + b_free(&qcc->rx.qstrm_buf); + b_free(&qcc->tx.qstrm_buf); + offer_buffers(NULL, 2); + } + pool_free(pool_head_qcc, qcc); if (conn) { @@ -3844,22 +3850,16 @@ static int qmux_init(struct connection *conn, struct proxy *prx, struct buffer *xprt_buf; qcc->tx.qstrm_buf = BUF_NULL; - b_alloc(&qcc->tx.qstrm_buf, DB_MUX_TX); - if (!b_size(&qcc->tx.qstrm_buf)) { - TRACE_ERROR("tx qstrm buf alloc failure", QMUX_EV_QCC_NEW); - goto err; - } - qcc->rx.qstrm_buf = BUF_NULL; - b_alloc(&qcc->rx.qstrm_buf, DB_MUX_RX); - if (!b_size(&qcc->rx.qstrm_buf)) { - TRACE_ERROR("rx qstrm buf alloc failure", QMUX_EV_QCC_NEW); - goto err; - } /* Retrieve data if xprt read too much */ xprt_buf = xprt_qstrm_rxbuf(conn->xprt_ctx); if (unlikely(b_data(xprt_buf))) { + b_alloc(&qcc->rx.qstrm_buf, DB_MUX_RX); + if (!b_size(&qcc->rx.qstrm_buf)) { + TRACE_ERROR("rx qstrm buf alloc failure", QMUX_EV_QCC_NEW); + goto err; + } b_xfer(&qcc->rx.qstrm_buf, xprt_buf, b_data(xprt_buf)); qcc->rx.rlen = xprt_qstrm_rxrlen(conn->xprt_ctx); } diff --git a/src/mux_quic_qstrm.c b/src/mux_quic_qstrm.c index cf56c23fa..339a2f15f 100644 --- a/src/mux_quic_qstrm.c +++ b/src/mux_quic_qstrm.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -105,6 +106,13 @@ int qcc_qstrm_recv(struct qcc *qcc) TRACE_ENTER(QMUX_EV_QCC_RECV, qcc->conn); + if (!b_size(buf)) { + if (!b_alloc(buf, DB_MUX_RX)) { + TRACE_ERROR("rx qstrm buf alloc failure", QMUX_EV_QCC_RECV); + goto err; + } + } + do { recv: /* Wrapping is not supported for QMux reception. */ @@ -165,6 +173,11 @@ int qcc_qstrm_recv(struct qcc *qcc) &qcc->wait_event); } + if (!b_data(buf)) { + b_free(buf); + offer_buffers(NULL, 1); + } + TRACE_LEAVE(QMUX_EV_QCC_RECV, qcc->conn); return total; @@ -252,6 +265,11 @@ int qcc_qstrm_send_frames(struct qcc *qcc, struct list *frms) TRACE_ENTER(QMUX_EV_QCC_SEND, qcc->conn); + if (!b_alloc(buf, DB_MUX_TX)) { + TRACE_ERROR("tx qstrm buf alloc failure", QMUX_EV_QCC_SEND); + goto out; + } + /* Record size field length */ lensz = quic_int_getsize(quic_int_cap_length(b_size(buf))); @@ -319,6 +337,7 @@ int qcc_qstrm_send_frames(struct qcc *qcc, struct list *frms) /* TODO */ BUG_ON(sent != b_data(buf)); + b_del(buf, sent); if (frm->type >= QUIC_FT_STREAM_8 && frm->type <= QUIC_FT_STREAM_F) qstrm_ctrl_send(frm->stream.stream, frm->stream.len); @@ -343,6 +362,11 @@ int qcc_qstrm_send_frames(struct qcc *qcc, struct list *frms) ret = 0; } + if (!b_data(buf)) { + b_free(buf); + offer_buffers(NULL, 1); + } + TRACE_LEAVE(QMUX_EV_QCC_SEND, qcc->conn); return ret; }