From 7732323cf3df151d9b546f17278e1e4698fe6f63 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Mon, 4 Dec 2023 14:18:50 +0100 Subject: [PATCH] MINOR: global: Use a dedicated bitfield to customize zero-copy fast-forwarding Zero-copy fast-forwading feature is a quite new and is a bit sensitive. There is an option to disable it globally. However, all protocols have not the same maturity. For instance, for the PT multiplexer, there is nothing really new. The zero-copy fast-forwading is only another name for the kernel splicing. However, for the QUIC/H3, it is pretty new, not really optimized and it will evolved. And soon, the support will be added for the cache applet. In this context, it is usefull to be able to enable/disable zero-copy fast-forwading per-protocol and applet. And when it is applicable, on sends or receives separately. So, instead of having one flag to disable it globally, there is now a dedicated bitfield, global.tune.no_zero_copy_fwd. --- doc/configuration.txt | 8 ++++---- include/haproxy/global-t.h | 15 ++++++++++++++- src/cfgparse-global.c | 2 +- src/haproxy.c | 6 ++++-- src/stconn.c | 2 +- 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 33e4ab63bf..670b2e80e9 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -2916,10 +2916,10 @@ tune.disable-fast-forward [ EXPERIMENTAL ] directive. tune.disable-zero-copy-forwarding - Disables the zero-copy forwarding of data. It is a mechanism to optimize the - data fast-forwarding by avoiding to use the channel's buffer. Thanks to this - directive, it is possible to disable this optimization. Note it also disable - any kernel tcp splicing. + Globally disables the zero-copy forwarding of data. It is a mechanism to + optimize the data fast-forwarding by avoiding to use the channel's buffer. + Thanks to this directive, it is possible to disable this optimization. Note + it also disable any kernel tcp splicing. tune.events.max-events-at-once Sets the number of events that may be processed at once by an asynchronous diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h index e302de45df..bb39baffce 100644 --- a/include/haproxy/global-t.h +++ b/include/haproxy/global-t.h @@ -66,7 +66,7 @@ #define GTUNE_USE_SYSTEMD (1<<10) #define GTUNE_BUSY_POLLING (1<<11) -#define GTUNE_USE_ZERO_COPY_FWD (1<<12) +/* (1<<12) unused */ #define GTUNE_SET_DUMPABLE (1<<13) #define GTUNE_USE_EVPORTS (1<<14) #define GTUNE_STRICT_LIMITS (1<<15) @@ -85,6 +85,18 @@ #define GTUNE_LISTENER_MQ_OPT (1<<28) #define GTUNE_LISTENER_MQ_ANY (GTUNE_LISTENER_MQ_FAIR | GTUNE_LISTENER_MQ_OPT) +#define NO_ZERO_COPY_FWD 0x0001 /* Globally disable zero-copy FF */ +#define NO_ZERO_COPY_FWD_PT 0x0002 /* disable zero-copy FF for PT (recv & send are disabled automatically) */ +#define NO_ZERO_COPY_FWD_H1_RCV 0x0004 /* disable zero-copy FF for H1 on received */ +#define NO_ZERO_COPY_FWD_H1_SND 0x0008 /* disable zero-copy FF for H1 on send */ +#define NO_ZERO_COPY_FWD_H2_RCV 0x0010 /* disable zero-copy FF for H2 on received */ +#define NO_ZERO_COPY_FWD_H2_SND 0x0020 /* disable zero-copy FF for H2 on send */ +#define NO_ZERO_COPY_FWD_QUIC_RCV 0x0040 /* disable zero-copy FF for QUIC on received */ +#define NO_ZERO_COPY_FWD_QUIC_SND 0x0080 /* disable zero-copy FF for QUIC on send */ +#define NO_ZERO_COPY_FWD_FCGI_RCV 0x0100 /* disable zero-copy FF for FCGI on received */ +#define NO_ZERO_COPY_FWD_FCGI_SND 0x0200 /* disable zero-copy FF for FCGI on send */ + + extern int cluster_secret_isset; /* non zero means a cluster secret was initialized */ /* SSL server verify mode */ @@ -173,6 +185,7 @@ struct global { int pool_high_count; /* max number of opened fd before we start killing idle connections when creating new connections */ size_t pool_cache_size; /* per-thread cache size per pool (defaults to CONFIG_HAP_POOL_CACHE_SIZE) */ unsigned short idle_timer; /* how long before an empty buffer is considered idle (ms) */ + unsigned short no_zero_copy_fwd; /* Flags to disable zero-copy fast-forwarding (global & per-protocols) */ int nb_stk_ctr; /* number of stick counters, defaults to MAX_SESS_STKCTR */ int default_shards; /* default shards for listeners, or -1 (by-thread) or -2 (by-group) */ uint max_checks_per_thread; /* if >0, no more than this concurrent checks per thread */ diff --git a/src/cfgparse-global.c b/src/cfgparse-global.c index a80ac854f6..540dda79b0 100644 --- a/src/cfgparse-global.c +++ b/src/cfgparse-global.c @@ -520,7 +520,7 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm) else if (strcmp(args[0], "tune.disable-zero-copy-forwarding") == 0) { if (alertif_too_many_args(0, file, linenum, args, &err_code)) goto out; - global.tune.options &= ~GTUNE_USE_ZERO_COPY_FWD; + global.tune.no_zero_copy_fwd |= NO_ZERO_COPY_FWD; } else if (strcmp(args[0], "cluster-secret") == 0) { blk_SHA_CTX sha1_ctx; diff --git a/src/haproxy.c b/src/haproxy.c index 3b5b1719b2..e186325542 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -1599,7 +1599,9 @@ static void init_args(int argc, char **argv) global.tune.options |= GTUNE_STRICT_LIMITS; global.tune.options |= GTUNE_USE_FAST_FWD; /* Use fast-forward by default */ - global.tune.options |= GTUNE_USE_ZERO_COPY_FWD; /* Use zero-copy forwarding by default */ + + /* Use zero-copy forwarding by default */ + global.tune.no_zero_copy_fwd = 0; /* keep a copy of original arguments for the master process */ old_argv = copy_argv(argc, argv); @@ -1656,7 +1658,7 @@ static void init_args(int argc, char **argv) else if (*flag == 'd' && flag[1] == 'V') global.ssl_server_verify = SSL_SERVER_VERIFY_NONE; else if (*flag == 'd' && flag[1] == 'Z') - global.tune.options &= ~GTUNE_USE_ZERO_COPY_FWD; + global.tune.no_zero_copy_fwd |= NO_ZERO_COPY_FWD; else if (*flag == 'V') arg_mode |= MODE_VERBOSE; else if (*flag == 'd' && flag[1] == 'C') { diff --git a/src/stconn.c b/src/stconn.c index 59b4acf10a..63dd9bf1f3 100644 --- a/src/stconn.c +++ b/src/stconn.c @@ -1276,7 +1276,7 @@ int sc_conn_recv(struct stconn *sc) /* First, let's see if we may fast-forward data from a side to the other * one without using the channel buffer. */ - if ((global.tune.options & GTUNE_USE_ZERO_COPY_FWD) && + if (!(global.tune.no_zero_copy_fwd & NO_ZERO_COPY_FWD) && sc_ep_test(sc, SE_FL_MAY_FASTFWD) && ic->to_forward) { if (channel_data(ic)) { /* We're embarrassed, there are already data pending in