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.
This commit is contained in:
Amaury Denoyelle 2026-04-23 14:41:34 +02:00
parent 265e893921
commit b8e65423f3
2 changed files with 35 additions and 11 deletions

View File

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

View File

@ -4,6 +4,7 @@
#include <haproxy/buf.h>
#include <haproxy/chunk.h>
#include <haproxy/connection.h>
#include <haproxy/dynbuf.h>
#include <haproxy/mux_quic.h>
#include <haproxy/mux_quic_priv.h>
#include <haproxy/proxy.h>
@ -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;
}