MINOR: global: Use a dedicated bitfield to customize zero-copy fast-forwarding
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 4 Dec 2023 13:18:50 +0000 (14:18 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 4 Dec 2023 14:31:47 +0000 (15:31 +0100)
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
include/haproxy/global-t.h
src/cfgparse-global.c
src/haproxy.c
src/stconn.c

index 33e4ab6..670b2e8 100644 (file)
@@ -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 <number>
   Sets the number of events that may be processed at once by an asynchronous
index e302de4..bb39baf 100644 (file)
@@ -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)
 #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 */
index a80ac85..540dda7 100644 (file)
@@ -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;
index 3b5b171..e186325 100644 (file)
@@ -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') {
index 59b4acf..63dd9bf 100644 (file)
@@ -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