MEDIUM: haterm: Add support for splicing and option to disable it

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.
This commit is contained in:
Christopher Faulet 2026-04-02 21:47:12 +02:00
parent 70a7f8dce0
commit f349d0b113
2 changed files with 30 additions and 1 deletions

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

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