]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: haterm: Add support for splicing and option to disable it
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 2 Apr 2026 19:47:12 +0000 (21:47 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 3 Apr 2026 08:46:15 +0000 (10:46 +0200)
The support for the splicing was added and enabled by default, if
supported. The command line option '-dS' was also added to disable the
feature.

When the splicing can be used and the front multiplexer agrees to proceed,
tee() is used to "copy" data from the master pipe to the client pipe.

src/haterm.c
src/haterm_init.c

index e66c41f23ee0fe27931476919ad36718dad0c229..f7ef4ddbe5ee49bcaa73837a13de0e3c5e3a5d89 100644 (file)
@@ -48,7 +48,8 @@ const char *HTTP_HELP =
         "                     E.g. /?K=1\n"
         " - /?t=<time>        wait <time> milliseconds before responding.\n"
         "                     E.g. /?t=500\n"
-        " - /?k=<enable>      Enable transfer encoding chunked with only one chunk if >0.\n"
+        " - /?k=<enable>      Enable transfer encoding chunked with only one chunk if >0 (disable fast-forward and splicing).\n"
+        " - /?S=<enable>      Disable use of splice() to send data if <1.\n"
         " - /?R=<enable>      Enable sending random data if >0.\n"
         "\n"
         "Note that those arguments may be cumulated on one line separated by a set of\n"
@@ -324,6 +325,10 @@ static int hstream_ff_snd(struct connection *conn, struct hstream *hs)
        }
 
        nego_flags |= NEGO_FF_FL_EXACT_SIZE;
+#if defined(USE_LINUX_SPLICE)
+       if ((global.tune.options & GTUNE_USE_SPLICE) && !(sd->iobuf.flags & IOBUF_FL_NO_SPLICING))
+               nego_flags |= NEGO_FF_FL_MAY_SPLICE;
+#endif
        len = se_nego_ff(sd, &BUF_NULL, hs->to_write, nego_flags);
        if (sd->iobuf.flags & IOBUF_FL_NO_FF) {
                TRACE_DEVEL("Fast-forwarding not supported by endpoint, disable it", HS_EV_HSTRM_RESP, hs);
@@ -334,10 +339,25 @@ static int hstream_ff_snd(struct connection *conn, struct hstream *hs)
                goto out;
        }
 
+#if defined(USE_LINUX_SPLICE)
+       if (sd->iobuf.pipe) {
+               if (len > master_pipesize)
+                       len = master_pipesize;
+               ret = tee(master_pipe->cons, sd->iobuf.pipe->prod, len, SPLICE_F_NONBLOCK);
+               if (ret > 0) {
+                       sd->iobuf.pipe->data += ret;
+                       hs->to_write -= ret;
+               }
+               if (!hs->to_write)
+                       sd->iobuf.flags |= IOBUF_FL_EOI;
+               goto done;
+       }
+#endif
        hs->to_write -= hstream_add_ff_data(hs, sd, len);
        if (!hs->to_write)
                sd->iobuf.flags |= IOBUF_FL_EOI;
 
+  done:
        if (se_done_ff(sd) != 0 || !(sd->iobuf.flags & (IOBUF_FL_FF_BLOCKED|IOBUF_FL_FF_WANT_ROOM))) {
                /* Something was forwarding or the consumer states it is not
                 * blocked anyore, don't reclaim more room */
index 797e636d27037c168879f9a4960c3bb8f722e248..06752c4ca2072b75b5e1072608689cc2f818ce93 100644 (file)
@@ -26,6 +26,7 @@ static void haterm_usage(char *name)
                "        -c <curves> : ECSDA curves (ex: \"P-256\", \"P-384\"...)\n"
                "        -v : shows version\n"
                "        -d : enable the traces for all http protocols\n"
+               "        -dS : disables splice() usage even when available\n"
                "        -dZ : disable zero-copy forwarding\n"
                "        --" QUIC_BIND_LONG_OPT " <opts> : append options to QUIC \"bind\" lines\n"
                "        --" TCP_BIND_LONG_OPT " <opts> : append options to TCP \"bind\" lines\n"
@@ -40,6 +41,9 @@ static void haterm_usage(char *name)
 static const char *haterm_cfg_dflt_str =
         "defaults\n"
             "\tmode haterm\n"
+#if defined(USE_LINUX_SPLICE)
+           "\toption splice-response\n"
+#endif
             "\ttimeout client 25s\n";
 
 #define HATERM_CFG_CRT_STORE_STR_FMT \
@@ -247,6 +251,11 @@ void haproxy_init_args(int argc, char **argv)
                                else
                                        haterm_usage(progname);
                        }
+#if defined(USE_LINUX_SPLICE)
+                       else if (*opt == 'd' && *(opt+1) == 'S') {
+                               global.tune.options &= ~GTUNE_USE_SPLICE;
+                       }
+#endif
                        else if (*opt == 'd' && *(opt+1) == 'Z') {
                                global.tune.no_zero_copy_fwd |= NO_ZERO_COPY_FWD;
                        }