]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux_quic/xprt_qstrm: simplify Rx buffer transfer
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 23 Apr 2026 13:36:08 +0000 (15:36 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 24 Apr 2026 07:33:04 +0000 (09:33 +0200)
When xprt_qstrm layer is completed, MUX layer is started. Rx buffer from
the XPRT layer is transferred to the MUX so that it can handle any extra
data following the transport parameters first frame.

Since previous commit, QCC Rx buffer is dynamically allocated only when
needed. However, qmux_init() must still allocate it when there is data
to be transferred from the XPRT layer. As a result, code has been over
extended to continue to support this case.

This patch simplifies xprt_qstrm API for the Rx buffer transfer. Buffer
content and remaining record length can now be retrieved via the single
function xprt_qstrm_xfer_rxbuf(). If the buffer is empty, nothing is
performed and XPRT layer will release it. If not empty, MUX will take
ownership of the buffer from the XPRT layer.

include/haproxy/xprt_qstrm.h
src/mux_quic.c
src/xprt_qstrm.c

index 5a992f21f25ba011e7fea37df2fdde59fb8804f8..f8af655b874b645faf40c1a0fee71dd12ac0811d 100644 (file)
@@ -4,7 +4,6 @@
 const struct quic_transport_params *xprt_qstrm_lparams(const void *context);
 const struct quic_transport_params *xprt_qstrm_rparams(const void *context);
 
-struct buffer *xprt_qstrm_rxbuf(const void *context);
-size_t xprt_qstrm_rxrlen(const void *context);
+size_t xprt_qstrm_xfer_rxbuf(const void *context, struct buffer *out);
 
 #endif /* _HAPROXY_XPRT_QSTRM_H */
index d2a1e6e3aec99f58cb1e64681f4d2ca1ea31717e..127ff048b263f257633f4bef57e3272d1e9219bc 100644 (file)
@@ -3847,25 +3847,13 @@ static int qmux_init(struct connection *conn, struct proxy *prx,
        }
 
        if (!conn_is_quic(conn)) {
-               struct buffer *xprt_buf;
-
                qcc->tx.qstrm_buf = BUF_NULL;
                qcc->rx.qstrm_buf = BUF_NULL;
 
-               /* 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);
-               }
-               else {
-                       qcc->rx.rlen = 0;
-               }
+               /* Rx buffer is transfered from xprt layer - necessary if too many data where read */
+               qcc->rx.rlen = xprt_qstrm_xfer_rxbuf(conn->xprt_ctx, &qcc->rx.qstrm_buf);
+               /* Cannot have a non empty record with an empty buffer. */
+               BUG_ON(qcc->rx.rlen && !b_data(&qcc->rx.qstrm_buf));
        }
 
        if (conn_is_back(conn)) {
index 6dcac7725912cf67fe5511dcaf6ed356cf17f8ad..a03f455a84a5b18a0fa535a9c89754d681abd7f9 100644 (file)
@@ -39,16 +39,16 @@ const struct quic_transport_params *xprt_qstrm_rparams(const void *context)
        return &ctx->rparams;
 }
 
-/* Returns RX buffer as mutable to allow zero-copy by the caller. */
-struct buffer *xprt_qstrm_rxbuf(void *context)
+/* Transfer Rx buffer into <out>. */
+size_t xprt_qstrm_xfer_rxbuf(void *context, struct buffer *out)
 {
        struct xprt_qstrm_ctx *ctx = context;
-       return &ctx->rxbuf;
-}
 
-size_t xprt_qstrm_rxrlen(const void *context)
-{
-       const struct xprt_qstrm_ctx *ctx = context;
+       if (b_data(&ctx->rxbuf)) {
+               *out = ctx->rxbuf;
+               ctx->rxbuf = BUF_NULL;
+       }
+
        return ctx->rxrlen;
 }
 
@@ -221,6 +221,10 @@ struct task *xprt_qstrm_io_cb(struct task *t, void *context, unsigned int state)
                conn->xprt_ctx = ctx->ctx_lower;
                conn->xprt = ctx->ops_lower;
 
+               /* MUX layer is responsible to retrieve any remaining data in
+                * the Rx buffer prior to reset it.
+                */
+               BUG_ON(b_data(&ctx->rxbuf));
                b_free(&ctx->rxbuf);
                b_free(&ctx->txbuf);