]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux_quic: use dynamic conn buffers for QMux
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 23 Apr 2026 12:41:34 +0000 (14:41 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 24 Apr 2026 07:33:04 +0000 (09:33 +0200)
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
src/mux_quic_qstrm.c

index e82569f075d06baa9ae104227a99c9f5dc4e58d5..d2a1e6e3aec99f58cb1e64681f4d2ca1ea31717e 100644 (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);
                }
index cf56c23fae8fe18748cd3c59713319f126ce5009..339a2f15fbd255ab7458603fc5125b8fafcc8deb 100644 (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;
 }