MINOR: mux_quic/xprt_qstrm: simplify Rx buffer transfer

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.
This commit is contained in:
Amaury Denoyelle 2026-04-23 15:36:08 +02:00
parent b8e65423f3
commit 64b7ef7971
3 changed files with 16 additions and 25 deletions

View 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 */

View 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)) {

View 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);