]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: mux_h1/mux_pt: Use XPRT_CAN_SPLICE to decide if we should splice
authorOlivier Houchard <ohouchard@haproxy.com>
Wed, 13 Aug 2025 13:39:46 +0000 (13:39 +0000)
committerOlivier Houchard <cognet@ci0.org>
Wed, 20 Aug 2025 16:33:10 +0000 (18:33 +0200)
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.

include/haproxy/connection-t.h
src/mux_h1.c
src/mux_pt.c

index 35b7eaf3461ea510669bd04f4ce2f7df7b1f2e0a..ab0231642e53c06e3df1e905807b845d63bb5d45 100644 (file)
@@ -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 */
index 204964613007d9f2fd49dae6439e4c1950802698..a8a6efa93c189a8b6fa2c18a7ff4f94a3de89f37 100644 (file)
@@ -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)) {
index 5a26a153e98ccfaf6325782b7a82866d275a4173..0b4c9ce78cdd092a9e83a0fab1ebc658ef086554 100644 (file)
@@ -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) {