MEDIUM: haterm: Prepare support for splicing by initializing a master pipe

Now the zero-copy data forwarding is supported, we will add the splicing
support. To do so, we first create a master pipe with vmsplice() during
haterm startup. It is only performed if the splicing is supported. And its
size can be configured by setting "tune.pipesize" global parameter.

This master pipe will be used to fill the pipe with the client.
This commit is contained in:
Christopher Faulet 2026-04-02 21:31:53 +02:00
parent ecf36f2ca8
commit 70a7f8dce0
2 changed files with 64 additions and 0 deletions

View File

@ -1,3 +1,6 @@
#define _GNU_SOURCE
#include <fcntl.h>
#include <haproxy/buf.h>
#include <haproxy/cfgparse.h>
#include <haproxy/chunk.h>
@ -6,6 +9,7 @@
#include <haproxy/http_htx.h>
#include <haproxy/http.h>
#include <haproxy/istbuf.h>
#include <haproxy/pipe.h>
#include <haproxy/pool.h>
#include <haproxy/proxy-t.h>
#include <haproxy/sc_strm.h>
@ -62,6 +66,11 @@ static char common_chunk_resp[RESPSIZE];
static char *random_resp;
static int random_resp_len = RESPSIZE;
#if defined(USE_LINUX_SPLICE)
struct pipe *master_pipe = NULL;
size_t master_pipesize = 0;
#endif
static size_t hstream_add_ff_data(struct hstream *hs, struct sedesc *sd, unsigned long long len);
static size_t hstream_add_htx_data(struct hstream *hs, struct htx *htx, unsigned long long len);
@ -1158,4 +1167,55 @@ static int hstream_build_responses(void)
return 1;
}
#if defined(USE_LINUX_SPLICE)
static void hstream_init_splicing(void)
{
if (!(global.tune.options & GTUNE_USE_SPLICE))
return;
if (!global.tune.pipesize)
global.tune.pipesize = 65536 * 5 / 4;
master_pipe = get_pipe();
if (master_pipe) {
struct iovec v = { .iov_base = common_response,
.iov_len = sizeof(common_response) };
int total, ret;
total = ret = 0;
do {
ret = vmsplice(master_pipe->prod, &v, 1, SPLICE_F_NONBLOCK);
if (ret > 0)
total += ret;
} while (ret > 0 && total < global.tune.pipesize);
master_pipesize = total;
if (master_pipesize < global.tune.pipesize) {
if (master_pipesize < 60*1024) {
/* Older kernels were limited to around 60-61 kB */
ha_warning("Failed to vmsplice response buffer after %lu bytes, splicing disabled\n", master_pipesize);
global.tune.options &= ~GTUNE_USE_SPLICE;
put_pipe(master_pipe);
master_pipe = NULL;
}
else
ha_warning("Splicing is limited to %lu bytes (too old kernel)\n", master_pipesize);
}
}
else {
ha_warning("Unable to allocate master pipe for splicing, splicing disabled\n");
global.tune.options &= ~GTUNE_USE_SPLICE;
}
}
static void hstream_deinit(void)
{
if (master_pipe)
put_pipe(master_pipe);
}
REGISTER_POST_DEINIT(hstream_deinit);
INITCALL0(STG_INIT_2, hstream_init_splicing);
#endif
REGISTER_POST_CHECK(hstream_build_responses);

View File

@ -186,6 +186,10 @@ void haproxy_init_args(int argc, char **argv)
/* save the arguments */
sargc = argc; sargv = argv;
#if defined(USE_LINUX_SPLICE)
global.tune.options |= GTUNE_USE_SPLICE;
#endif
/* THIS PART MUST NOT MODIFY THE ARGUMENTS */
/* Parse the arguments which must be reused to build the conf. */
while (argc > 0) {