diff --git a/include/haproxy/xprt_qstrm.h b/include/haproxy/xprt_qstrm.h index 182a72c3e..536ba1abd 100644 --- a/include/haproxy/xprt_qstrm.h +++ b/include/haproxy/xprt_qstrm.h @@ -4,4 +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); + #endif /* _HAPROXY_XPRT_QSTRM_H */ diff --git a/src/mux_quic.c b/src/mux_quic.c index 234dfe1c0..15302f5fa 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -3784,6 +3784,8 @@ 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; b_alloc(&qcc->tx.qstrm_buf, DB_MUX_TX); if (!b_size(&qcc->tx.qstrm_buf)) { @@ -3797,6 +3799,11 @@ static int qmux_init(struct connection *conn, struct proxy *prx, 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_xfer(&qcc->rx.qstrm_buf, xprt_buf, b_data(xprt_buf)); } if (conn_is_back(conn)) { @@ -3857,8 +3864,14 @@ static int qmux_init(struct connection *conn, struct proxy *prx, qcc_reset_idle_start(qcc); LIST_INIT(&qcc->opening_list); - if (conn_is_quic(conn)) + if (conn_is_quic(conn)) { HA_ATOMIC_STORE(&conn->handle.qc->qcc, qcc); + } + else { + /* Wakeup MUX immediately if data copied from XPRT layer. */ + if (unlikely(b_data(&qcc->rx.qstrm_buf))) + tasklet_wakeup(qcc->wait_event.tasklet); + } /* Register conn as app_ops may use it. */ qcc->conn = conn; diff --git a/src/xprt_qstrm.c b/src/xprt_qstrm.c index 7b44cd26c..a51222a70 100644 --- a/src/xprt_qstrm.c +++ b/src/xprt_qstrm.c @@ -37,6 +37,13 @@ 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) +{ + struct xprt_qstrm_ctx *ctx = context; + return &ctx->rxbuf; +} + int conn_recv_qstrm(struct connection *conn, struct xprt_qstrm_ctx *ctx, int flag) { struct quic_frame frm;