From: Olivier Houchard Date: Wed, 13 Aug 2025 13:39:46 +0000 (+0000) Subject: MEDIUM: mux_h1/mux_pt: Use XPRT_CAN_SPLICE to decide if we should splice X-Git-Tag: v3.3-dev7~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=075e75380235e2898989cfa50d80a402323d8125;p=thirdparty%2Fhaproxy.git MEDIUM: mux_h1/mux_pt: Use XPRT_CAN_SPLICE to decide if we should splice In both mux_h1 and mux_pt, use the new XPRT_CAN_SPLICE capability to decide if we should attempt to use splicing or not. If we receive XPRT_CONN_CAN_MAYBE_SPLICE, add a new flag on the connection, CO_FL_WANT_SPLICING, to let the xprt know that we'd love to be able to do splicing, so that it may get ready for that. This should have no effect right now, and is required work for adding kTLS support. --- diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 35b7eaf34..ab0231642 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -144,8 +144,7 @@ enum { */ CO_FL_WAIT_ROOM = 0x00000800, /* data sink is full */ - /* These flags are used to report whether the from/to addresses are set or not */ - /* unused: 0x00001000 */ + CO_FL_WANT_SPLICING = 0x00001000, /* we wish to use splicing on the connection when possible */ /* unused: 0x00002000 */ CO_FL_EARLY_SSL_HS = 0x00004000, /* We have early data pending, don't start SSL handshake yet */ diff --git a/src/mux_h1.c b/src/mux_h1.c index 204964613..a8a6efa93 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -4856,16 +4856,35 @@ static size_t h1_nego_ff(struct stconn *sc, struct buffer *input, size_t count, * supported to mix data. */ if (!b_data(input) && !b_data(&h1c->obuf) && (flags & NEGO_FF_FL_MAY_SPLICE)) { + int can_splice = XPRT_CONN_CAN_NOT_SPLICE; #if defined(USE_LINUX_SPLICE) - if (h1c->conn->xprt->snd_pipe && (h1s->sd->iobuf.pipe || (pipes_used < global.maxpipes && (h1s->sd->iobuf.pipe = get_pipe())))) { + + if (h1c->conn->xprt->snd_pipe && + h1c->conn->xprt->get_capability && + h1c->conn->xprt->get_capability(h1c->conn, h1c->conn->xprt_ctx, XPRT_CAN_SPLICE, &can_splice) == 0 && + can_splice == XPRT_CONN_CAN_SPLICE && + (h1s->sd->iobuf.pipe || (pipes_used < global.maxpipes && (h1s->sd->iobuf.pipe = get_pipe())))) { h1s->sd->iobuf.offset = 0; h1s->sd->iobuf.data = 0; ret = count; goto out; } #endif - h1s->sd->iobuf.flags |= IOBUF_FL_NO_SPLICING; - TRACE_DEVEL("Unable to allocate pipe for splicing, fallback to buffer", H1_EV_STRM_SEND, h1c->conn, h1s); + /* + * If can_splice is XPRT_CONN_COULD_SPLICE, it means + * that it can not splice right now, but it may at a later + * time, so don't disable it completely, just do not attempt + * to splice right now. If we got that, then no pipe has + * been allowed, so we should not try to splice. + * Set CO_FL_WANT_SPLICING to let the upper layers know that + * we would love to be able to use splicing if possible. + */ + if (can_splice == XPRT_CONN_COULD_SPLICE) { + h1c->conn->flags |= CO_FL_WANT_SPLICING; + } else { + h1s->sd->iobuf.flags |= IOBUF_FL_NO_SPLICING; + TRACE_DEVEL("Unable to allocate pipe for splicing, fallback to buffer", H1_EV_STRM_SEND, h1c->conn, h1s); + } } no_splicing: @@ -5048,8 +5067,16 @@ static int h1_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags) count = h1m->curr_len; } - if (h1c->conn->xprt->rcv_pipe && !!(flags & CO_RFL_MAY_SPLICE) && !(sdo->iobuf.flags & IOBUF_FL_NO_SPLICING)) - nego_flags |= NEGO_FF_FL_MAY_SPLICE; + if (h1c->conn->xprt->rcv_pipe && !!(flags & CO_RFL_MAY_SPLICE) && !(sdo->iobuf.flags & IOBUF_FL_NO_SPLICING)) { + int can_splice = XPRT_CONN_CAN_NOT_SPLICE; + + if (h1c->conn->xprt->get_capability && + h1c->conn->xprt->get_capability(h1c->conn, h1c->conn->xprt_ctx, XPRT_CAN_SPLICE, &can_splice) == 0 && + can_splice == XPRT_CONN_CAN_SPLICE) + nego_flags |= NEGO_FF_FL_MAY_SPLICE; + else if (can_splice == XPRT_CONN_COULD_SPLICE) + h1c->conn->flags |= CO_FL_WANT_SPLICING; + } try = se_nego_ff(sdo, &h1c->ibuf, count, nego_flags); if (b_room(&h1c->ibuf) && (h1c->flags & H1C_F_IN_FULL)) { diff --git a/src/mux_pt.c b/src/mux_pt.c index 5a26a153e..0b4c9ce78 100644 --- a/src/mux_pt.c +++ b/src/mux_pt.c @@ -592,16 +592,33 @@ static size_t mux_pt_nego_ff(struct stconn *sc, struct buffer *input, size_t cou * supported to mix data. */ if (!b_data(input) && (flags & NEGO_FF_FL_MAY_SPLICE)) { - if (conn->xprt->snd_pipe && (ctx->sd->iobuf.pipe || (pipes_used < global.maxpipes && (ctx->sd->iobuf.pipe = get_pipe())))) { + int can_splice = XPRT_CONN_CAN_NOT_SPLICE; + + if (conn->xprt->snd_pipe && conn->xprt->get_capability && + conn->xprt->get_capability(conn, conn->xprt_ctx, XPRT_CAN_SPLICE, &can_splice) == 0 && + can_splice == XPRT_CONN_CAN_SPLICE && + (ctx->sd->iobuf.pipe || (pipes_used < global.maxpipes && (ctx->sd->iobuf.pipe = get_pipe())))) { ctx->sd->iobuf.offset = 0; ctx->sd->iobuf.data = 0; ret = count; goto out; } - ctx->sd->iobuf.flags |= IOBUF_FL_NO_SPLICING; - TRACE_DEVEL("Unable to allocate pipe for splicing, fallback to buffer", PT_EV_TX_DATA, conn, sc); + /* + * If can_splice is XPRT_CONN_COULD, it means + * that it can not splice right now, but it may at a later + * time, so don't disable it completely, just do not attempt + * to splice right now. If we got that, then no pipe has + * been allowed, so we should not try to splice. + * Set CO_FL_WANT_SPLICING to let the upper layers know that + * we would love to be able to use splicing if possible. + */ + if (can_splice == XPRT_CONN_COULD_SPLICE) { + conn->flags |= CO_FL_WANT_SPLICING; + } else { + ctx->sd->iobuf.flags |= IOBUF_FL_NO_SPLICING; + TRACE_DEVEL("Unable to allocate pipe for splicing, fallback to buffer", PT_EV_TX_DATA, conn, sc); + } } - /* No buffer case */ out: @@ -664,8 +681,17 @@ static int mux_pt_fastfwd(struct stconn *sc, unsigned int count, unsigned int fl goto out; } - if (conn->xprt->rcv_pipe && !!(flags & CO_RFL_MAY_SPLICE) && !(sdo->iobuf.flags & IOBUF_FL_NO_SPLICING)) - nego_flags |= NEGO_FF_FL_MAY_SPLICE; + if (conn->xprt->rcv_pipe && !!(flags & CO_RFL_MAY_SPLICE) && !(sdo->iobuf.flags & IOBUF_FL_NO_SPLICING)) { + int can_splice = XPRT_CONN_CAN_NOT_SPLICE; + + if (conn->xprt->get_capability && + conn->xprt->get_capability(conn, conn->xprt_ctx, XPRT_CAN_SPLICE, &can_splice) == 0 && + can_splice == XPRT_CONN_CAN_SPLICE) + nego_flags |= NEGO_FF_FL_MAY_SPLICE; + else if (can_splice == XPRT_CONN_COULD_SPLICE) + conn->flags |= CO_FL_WANT_SPLICING; + } + try = se_nego_ff(sdo, &BUF_NULL, count, nego_flags); if (sdo->iobuf.flags & IOBUF_FL_NO_FF) {