]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
13 months agoMINOR: sock: set conn->err_code in case of EPERM next
Valentine Krasnobaeva [Tue, 21 May 2024 17:24:37 +0000 (19:24 +0200)] 
MINOR: sock: set conn->err_code in case of EPERM

To improve the readability of sock_handle_system_err(), let's
set explicitly conn->err_code as CO_ER_SOCK_ERR in case of EPERM
(could be returned by setns syscall).

13 months agoBUG/MEDIUM: proto: fix fd leak in <proto>_connect_server
Valentine Krasnobaeva [Tue, 21 May 2024 17:24:31 +0000 (19:24 +0200)] 
BUG/MEDIUM: proto: fix fd leak in <proto>_connect_server

This fixes the fd leak, introduced in the commit d3fc982cd788
("MEDIUM: proto: make common fd checks in sock_create_server_socket").

Initially sock_create_server_socket() was designed to return only created
socket FD or -1. Its callers from upper protocol layers were required to test
the returned errno and were required then to apply different configuration
related checks to obtained positive sock_fd. A lot of this code was duplicated
among protocols implementations.

The new refactored version of sock_create_server_socket() gathers in one place
all duplicated checks, but in order to be complient with upper protocol
layers, it needs the 3rd parameter: 'stream_err', in which it sets the
Stream Error Flag for upper levels, if the obtained sock_fd has passed all
additional checks.

No backport needed since this was introduced in 3.0-dev10.

13 months agoDOC: configuration: add the supported crt-store options in crt-list
William Lallemand [Tue, 21 May 2024 16:12:14 +0000 (18:12 +0200)] 
DOC: configuration: add the supported crt-store options in crt-list

The crt-list supports some crt-store keywords. This patch list them in
the crt-list documentation.

13 months agoDOC: configuration: update the crt-list documentation
William Lallemand [Tue, 21 May 2024 15:49:58 +0000 (17:49 +0200)] 
DOC: configuration: update the crt-list documentation

Update the crt-list documentation with the supported keywords.

Also format it in a more clear way.

Must be backported to 2.8.

13 months agoMEDIUM: ssl: don't load file by discovering them in crt-store
William Lallemand [Tue, 21 May 2024 14:50:59 +0000 (16:50 +0200)] 
MEDIUM: ssl: don't load file by discovering them in crt-store

In commit 55e9e9591 ("MEDIUM: ssl: temporarily load files by detecting
their presence in crt-store"), ssl_sock_load_pem_into_ckch() was
replaced by ssl_sock_load_files_into_ckch() in the crt-store loading.

But the side effect was that we always try to autodetect, and this is
not what we want. This patch reverse this, and add specific code in the
crt-list loading, so we could autodetect in crt-list like it was done
before, but still try to load files when a crt-store filename keyword is
specified.

Example:

These crt-list lines won't autodetect files:

    foobar.crt [key foobar.key issuer foobar.issuer ocsp-update on] *.foo.bar
    foobar.crt [key foobar.key] *.foo.bar

These crt-list lines will autodect files:

    foobar.pem [ocsp-update on] *.foo.bar
    foobar.pem

13 months agoDEBUG: fd: add name hint for large memory areas
Aurelien DARRAGON [Tue, 21 May 2024 12:30:32 +0000 (14:30 +0200)] 
DEBUG: fd: add name hint for large memory areas

Thanks to ("MINOR: tools: add vma_set_name() helper"), set a name hint
for large arrays created by fd api (fdtab arrays and so on) so that
that they can be easily identified in /proc/<pid>/maps.

Depending on malloc() implementation, such memory areas will normally be
merged on the heap under MMAP_THRESHOLD (128 kB by default) and will
have a dedicated memory area once the threshold is exceeded. As such, when
large enough, they will appear like this in /proc/<pid>/maps:

7b8e83200000-7b8e84201000 rw-p 00000000 00:00 0                          [anon:fd:fdinfo]
7b8e84400000-7b8e85401000 rw-p 00000000 00:00 0                          [anon:fd:polled_mask]
7b8e85600000-7b8e89601000 rw-p 00000000 00:00 0                          [anon:fd:fdtab_addr]
7b8e90a00000-7b8e90e01000 rw-p 00000000 00:00 0                          [anon:fd:fd_updt]

13 months agoDEBUG: errors: add name hint for startup-logs memory area
Aurelien DARRAGON [Tue, 21 May 2024 08:49:55 +0000 (10:49 +0200)] 
DEBUG: errors: add name hint for startup-logs memory area

Thanks to ("MINOR: tools: add vma_set_name() helper"), set a name hint
for startup-logs ring's memory area created using mmap() so it can be
easily indentified in /proc/<pid>/maps.

7b8e91cce000-7b8e91cde000 rw-s 00000000 00:19 46                         [anon_shmem:errors:startup_logs]

13 months agoDEBUG: pollers: add name hint for large memory areas used by pollers
Aurelien DARRAGON [Tue, 21 May 2024 08:21:24 +0000 (10:21 +0200)] 
DEBUG: pollers: add name hint for large memory areas used by pollers

Thanks to ("MINOR: tools: add vma_set_name() helper"), set a name hint
for large memory areas allocated by pollers upon init so that they can
be easily indentified in /proc/<pid>/maps.

For now, only linux-compatible pollers are considered since vma_set_name()
requires a recent linux kernel (>= 5.17).

Depending on malloc() implementation, such memory areas will normally be
merged on the heap under MMAP_THRESHOLD (128 kB by default) and will
have a dedicated memory area once the threshold is exceeded. As such, when
large enough, they will appear like this in /proc/<pid>/maps:

7ec6b2d40000-7ec6b2d61000 rw-p 00000000 00:00 0                          [anon:ev_poll:fd_evts_wr]
7ec6b2d61000-7ec6b2d82000 rw-p 00000000 00:00 0                          [anon:ev_poll:fd_evts_rd]

13 months agoDEBUG: sink: add name hint for memory area used by memory-backed sinks
Aurelien DARRAGON [Mon, 20 May 2024 13:16:10 +0000 (15:16 +0200)] 
DEBUG: sink: add name hint for memory area used by memory-backed sinks

Thanks to ("MINOR: tools: add vma_set_name() helper"), set a name hint
for user created memory-backed sinks (ring sections without backing-file)
so that they can be easily indentified in /proc/<pid>/maps.

Depending on malloc() implementation, such memory areas will normally be
merged on the heap under MMAP_THRESHOLD (128 kB by default) and will
have a dedicated memory area once the threshold is exceeded. As such, when
large enough, they will appear like this in /proc/<pid>/maps:

7b8e8ac00000-7b8e8bf13000 rw-p 00000000 00:00 0                          [anon:ring:myring]

13 months agoDEBUG: shctx: name shared memory using vma_set_name()
Aurelien DARRAGON [Mon, 20 May 2024 12:11:31 +0000 (14:11 +0200)] 
DEBUG: shctx: name shared memory using vma_set_name()

In 98d22f212 ("MEDIUM: shctx: Naming shared memory context"), David
implemented prctl/PR_SET_VMA support to give a name to shctx maps when
supported. Maps were named after "HAProxy $name". It turns out that it
is not relevant to include "HAProxy" in the map name, given that we're
already looking at maps for a given PID (and here it's HAProxy's pid).

Instead, let's name shctx maps by making use of the new vma_set_name()
helper introduced by previous commit. Resulting maps will be named
"shctx:$name", e.g.: "shctx:globalCache", they will appear like this in
/proc/<pid>/maps:

7ec6aab0f000-7ec6ac000000 rw-s 00000000 00:01 405                        [anon_shmem:shctx:custom_name]

13 months agoDEBUG: tools: add vma_set_name() helper
Aurelien DARRAGON [Thu, 16 May 2024 10:08:56 +0000 (12:08 +0200)] 
DEBUG: tools: add vma_set_name() helper

Following David Carlier's work in 98d22f21 ("MEDIUM: shctx: Naming shared
memory context"), let's provide an helper function to set a name hint on
a virtual memory area (ie: anonymous map created using mmap(), or memory
area returned by malloc()).

Naming will only occur if available, and naming errors will be ignored.
The function takes mandatory <type> and <name> parameterss to build the
map name as follow: "type:name". When looking at /proc/<pid>/maps, vma
named using this helper function will show up this way (provided that
the kernel has prtcl support for PR_SET_VMA_ANON_NAME):

example, using mmap + MAP_SHARED|MAP_ANONYMOUS:
  7364c4fff000-736508000000 rw-s 00000000 00:01 3540  [anon_shmem:type:name]
Another example, using mmap + MAP_PRIVATE|MAP_ANONYMOUS or using
glibc/malloc() above MMAP_THRESHOLD:
  7364c4fff000-736508000000 rw-s 00000000 00:01 3540  [anon:type:name]

13 months agoDOC: configuration: rework the crt-store load documentation
William Lallemand [Tue, 21 May 2024 09:51:56 +0000 (11:51 +0200)] 
DOC: configuration: rework the crt-store load documentation

The load keyword from the documentation has its own section to be
readable (like the server or bind options section).

The ocsp-update keyword was move from the bind section to the crt-list
load one.

13 months agoBUG/MINOR: ring: free ring's allocated area not ring's usable area when using maps
Aurelien DARRAGON [Tue, 21 May 2024 09:13:46 +0000 (11:13 +0200)] 
BUG/MINOR: ring: free ring's allocated area not ring's usable area when using maps

Since 40d1c84bf0 ("BUG/MAJOR: ring: free the ring storage not the ring
itself when using maps"), munmap() call for startup_logs's ring and
file-backed rings fails to work (EINVAL) and causes memory leaks during
process cleanup.

munmap() fails because it is called with the ring's usable area pointer
which is an offset from the underlying original memory block allocated
using mmap(). Indeed, ring_area() helper function was misused because
it didn't explicitly mention that the returned address corresponds to
the usable storage's area, not the allocated one.

To fix the issue, we add an explicit ring_allocated_area() helper to
return the allocated area for the ring, just like we already have
ring_allocated_size() for the allocated size, and we properly use both
the allocated size and allocated area to manipulate them using munmap()
and msync().

No backport needed.

13 months agoMINOR: ssl: check parameter in ckch_conf_cmp()
William Lallemand [Tue, 21 May 2024 09:01:59 +0000 (11:01 +0200)] 
MINOR: ssl: check parameter in ckch_conf_cmp()

Check prev and new parameters in ckch_conf_cmp() so we don't dereference
a NULL ptr. There is no risk since it's not used with a NULL ptr yet.

Also remove the check that are done later, and do it at the beginning of
the function.

Should fix issue #2572.

13 months agoCLEANUP: ssl/cli: remove unused code in dump_crtlist_conf
William Lallemand [Tue, 21 May 2024 08:58:09 +0000 (10:58 +0200)] 
CLEANUP: ssl/cli: remove unused code in dump_crtlist_conf

This code was never used because space is never define before:

    if (space) chunk_appendf(buf, " ");

Should fix issue #2571.

13 months ago[RELEASE] Released version 3.0-dev12 v3.0-dev12
Willy Tarreau [Sat, 18 May 2024 14:51:23 +0000 (16:51 +0200)] 
[RELEASE] Released version 3.0-dev12

Released version 3.0-dev12 with the following main changes :
    - CI: drop asan.log umbrella completely
    - BUG/MINOR: log: fix leak in add_sample_to_logformat_list() error path
    - BUG/MINOR: log: smp_rgs array issues with inherited global log directives
    - MINOR: rhttp: Don't require SSL when attach-srv name parsing
    - REGTESTS: ssl: be more verbose with ocsp_compat_check.vtc
    - DOC: Update UUID references to RFC 9562
    - MINOR: hlua: add hlua_nb_instruction getter
    - MEDIUM: hlua: take nbthread into account in hlua_get_nb_instruction()
    - BUG/MEDIUM: server: clear purgeable conns before server deletion
    - BUG/MINOR: mux-quic: fix error code on shutdown for non HTTP/3
    - BUG/MINOR: qpack: fix error code reported on QPACK decoding failure
    - BUG/MEDIUM: htx: mark htx_sl as packed since it may be realigned
    - BUG/MEDIUM: stick-tables: properly mark stktable_data as packed
    - SCRIPTS: run-regtests: fix a few occurrences of extended regexes
    - BUG/MINOR: ssl_sock: fix xprt_set_used() to properly clear the TASK_F_USR1 bit
    - MINOR: dynbuf: provide a b_dequeue() variant for multi-thread
    - BUG/MEDIUM: muxes: enforce buf_wait check in takeover()
    - BUG/MINOR: h1: Check authority for non-CONNECT methods only if a scheme is found
    - BUG/MEDIUM: h1: Reject CONNECT request if the target has a scheme
    - BUG/MAJOR: h1: Be stricter on request target validation during message parsing
    - MINOR: qpack: prepare error renaming
    - MINOR: h3/qpack: adjust naming for errors
    - MINOR: h3: adjust error reporting on sending
    - MINOR: h3: adjust error reporting on receive
    - MINOR: mux-quic: support glitches
    - MINOR: h3: report glitch on RFC violation
    - BUILD: stick-tables: better mark the stktable_data as 32-bit aligned
    - MINOR: ssl: rename tune.ssl.ocsp-update.mode in ocsp-update.mode
    - REGTESTS: update the ocsp-update tests
    - BUILD: stats: remove non portable getline() usage
    - MEDIUM: ssl: add ocsp-update.mindelay and ocsp-update.maxdelay
    - BUILD: log: get rid of non-portable strnlen() func
    - BUG/MEDIUM: fd: prevent memory waste in fdtab array
    - CLEANUP: compat: make the MIN/MAX macros more reliable
    - Revert: MEDIUM: evports: permit to report multiple events at once"
    - BUG/MINOR: stats: Don't state the 303 redirect response is chunked
    - MINOR: mux-h1: Add a flag to ignore the request payload
    - REORG: mux-h1: Group H1S_F_BODYLESS_* flags
    - CLEANUP: mux-h1: Remove unused H1S_F_ERROR_MASK mask value
    - MEDIUM: mux-h1: Support C-L/T-E header suppressions when sending messages
    - MINOR: ssl: ckch_store_new_load_files_conf() loads filenames from ckch_conf
    - MEDIUM: ssl/crtlist: loading crt-store keywords from a crt-list
    - CLEANUP: ssl/ocsp: remove the deprecated parsing code for "ocsp-update"
    - MINOR: ssl: pass ckch_store instead of ckch_data to ssl_sock_load_ocsp()
    - MEDIUM: ssl: ckch_conf_parse() uses -1/0/1 for off/default/on
    - MINOR: ssl: handle PARSE_TYPE_INT and PARSE_TYPE_ONOFF in ckch_store_load_files()
    - MINOR: ssl/ocsp: use 'ocsp-update' in crt-store
    - MINOR: ssl: ckch_conf_clean() utility function for ckch_conf
    - MEDIUM: ssl: add ocsp-update.disable global option
    - MEDIUM: ssl/cli: handle crt-store keywords in crt-list over the CLI
    - MINOR: ssl: ckch_conf_cmp() compare multiple ckch_conf structures
    - MEDIUM: ssl: temporarily load files by detecting their presence in crt-store
    - REGTESTS: ocsp-update: change the reg-test to support the new crt-store mode
    - DOC: capabilities: fix chapter header rendering

13 months agoDOC: capabilities: fix chapter header rendering
Valentine Krasnobaeva [Fri, 17 May 2024 13:38:02 +0000 (15:38 +0200)] 
DOC: capabilities: fix chapter header rendering

The header of a new management guide chapter, "13.1. Linux capabilities
support", is not rendered in HTML format in a proper way, because of missing
dots at the end of this chapter's number.

13 months agoREGTESTS: ocsp-update: change the reg-test to support the new crt-store mode
William Lallemand [Tue, 7 May 2024 07:55:02 +0000 (09:55 +0200)] 
REGTESTS: ocsp-update: change the reg-test to support the new crt-store mode

Update the ocsp-update tests for the recent changes:

- Incompatibilities check string changed to match the crt-store one
- The "good configurations" are not good anymore because the
  ckch_conf_cmp() does not compare anymore with a global value.

13 months agoMEDIUM: ssl: temporarily load files by detecting their presence in crt-store
William Lallemand [Tue, 7 May 2024 07:40:17 +0000 (09:40 +0200)] 
MEDIUM: ssl: temporarily load files by detecting their presence in crt-store

crt-store is maint to be stricter than your common crt argument on a
bind line, and is supposed to be a declarative format.

However, since the 'ocsp-update' was migrated from ssl_conf to
ckch_conf, the .issuer file is not autodetected anymore when adding a
ocsp-update keyword in a crt-list file, which breaks retro-compatibility.

This patch is a quick fix that will disappear once we are able to be
strict on a crt-store and autodetect on a crt-list.

13 months agoMINOR: ssl: ckch_conf_cmp() compare multiple ckch_conf structures
William Lallemand [Thu, 2 May 2024 15:46:06 +0000 (17:46 +0200)] 
MINOR: ssl: ckch_conf_cmp() compare multiple ckch_conf structures

The ckch_conf_cmp() function allow to compare multiple ckch_conf
structures in order to check that multiple usage of the same crt in the
configuration uses the same ckch_conf definition.

A crt-list allows to use "crt-store" keywords that defines a ckch_store,
that can lead to inconsistencies when a crt is called multiple time with
different parameters.

This function compare and dump a list of differences in the err variable
to be output as error.

The variant ckch_conf_cmp_empty() compares the ckch_conf structure to an
empty one, which is useful for bind lines, that are not able to have
crt-store keywords.

These functions are used when a crt-store is already inialized and we
need to verify if the parameters are compatible.

ckch_conf_cmp() handles multiple cases:

- When the previous ckch_conf was declared with CKCH_CONF_SET_EMPTY, we
  can't define any new keyword in the next initialisation
- When the previous ckch_conf was declared with keywords in a crtlist
  (CKCH_CONF_SET_CRTLIST), the next initialisation must have the exact
  same keywords.
- When the previous ckch_conf was declared in a "crt-store"
  (CKCH_CONF_SET_CRTSTORE), the next initialisaton could use no keyword
  at all or the exact same keywords.

13 months agoMEDIUM: ssl/cli: handle crt-store keywords in crt-list over the CLI
William Lallemand [Tue, 7 May 2024 07:20:06 +0000 (09:20 +0200)] 
MEDIUM: ssl/cli: handle crt-store keywords in crt-list over the CLI

This patch adds crt-store keywords from the crt-list on the CLI.

- keywords from crt-store can be used over the CLI when inserting
  certificate in a crt-list
- keywords from crt-store are dumped when showing a crt-list content
  over the CLI

The ckch_conf_kws.func function pointer needed a new "cli" parameter, in
order to differenciate loading that come from the CLI or from the
startup, as they don't behave the same. For example it must not try to
load a file on the filesystem when loading a crt-list line from the CLI.

dump_crtlist_sslconf() was renamed in dump_crtlist_conf() and takes a
new ckch_conf parameter in order to dump relevant crt-store keywords.

13 months agoMEDIUM: ssl: add ocsp-update.disable global option
William Lallemand [Thu, 2 May 2024 12:22:24 +0000 (14:22 +0200)] 
MEDIUM: ssl: add ocsp-update.disable global option

This option allow to disable completely the ocsp-update.

To achieve this, the ocsp-update.mode global keyword don't rely anymore
on SSL_SOCK_OCSP_UPDATE_OFF during parsing to call
ssl_create_ocsp_update_task().

Instead, we will inherit the SSL_SOCK_OCSP_UPDATE_* value from
ocsp-update.mode for each certificate which does not specify its own
mode.

To disable completely the ocsp without editing all crt entries,
ocsp-update.disable is used instead of "ocsp-update.mode" which is now
only used as the default value for crt.

13 months agoMINOR: ssl: ckch_conf_clean() utility function for ckch_conf
William Lallemand [Thu, 2 May 2024 18:50:59 +0000 (20:50 +0200)] 
MINOR: ssl: ckch_conf_clean() utility function for ckch_conf

- ckch_conf_clean() to free() the content of a ckch_conf structure,
  mostly the string that were strdup()

13 months agoMINOR: ssl/ocsp: use 'ocsp-update' in crt-store
William Lallemand [Tue, 30 Apr 2024 19:55:45 +0000 (21:55 +0200)] 
MINOR: ssl/ocsp: use 'ocsp-update' in crt-store

Use the ocsp-update keyword in the crt-store section. This is not used
as an exception in the crtlist code anymore.

This patch introduces the "ocsp_update_mode" variable in the ckch_conf
structure.

The SSL_SOCK_OCSP_UPDATE_* enum was changed to a define to match the
ckch_conf on/off parser so we can have off to -1.

13 months agoMINOR: ssl: handle PARSE_TYPE_INT and PARSE_TYPE_ONOFF in ckch_store_load_files()
William Lallemand [Tue, 30 Apr 2024 17:20:21 +0000 (19:20 +0200)] 
MINOR: ssl: handle PARSE_TYPE_INT and PARSE_TYPE_ONOFF in ckch_store_load_files()

The callback used by ckch_store_load_files() only works with
PARSE_TYPE_STR.

This allows to use a callback which will use a integer type for PARSE_TYPE_INT
and PARSE_TYPE_ONOFF.

This require to change the type of the callback to void * to pass either
a char * or a int depending of the parsing type.

The ssl_sock_load_* functions were encapsuled in ckch_conf_load_*
function just to match the type.

This will allow to handle crt-store keywords that are ONOFF or INT
types.

13 months agoMEDIUM: ssl: ckch_conf_parse() uses -1/0/1 for off/default/on
William Lallemand [Tue, 30 Apr 2024 19:38:16 +0000 (21:38 +0200)] 
MEDIUM: ssl: ckch_conf_parse() uses -1/0/1 for off/default/on

ckch_conf_parse() now set -1 for a off value and 1 for a on value.
This allow to detect when a value is the default since the struct are memset
to 0.

13 months agoMINOR: ssl: pass ckch_store instead of ckch_data to ssl_sock_load_ocsp()
William Lallemand [Tue, 30 Apr 2024 19:31:05 +0000 (21:31 +0200)] 
MINOR: ssl: pass ckch_store instead of ckch_data to ssl_sock_load_ocsp()

ssl_sock_put_ckch_into_ctx() and ssl_sock_load_ocsp() need to take a
ckch_store in argument. Indeed the ocsp_update_mode is not stored
anymore in ckch_data, but in ckch_conf which is part of the ckch_store.

This is a minor change, but the function definition had to change.

13 months agoCLEANUP: ssl/ocsp: remove the deprecated parsing code for "ocsp-update"
William Lallemand [Tue, 30 Apr 2024 17:29:24 +0000 (19:29 +0200)] 
CLEANUP: ssl/ocsp: remove the deprecated parsing code for "ocsp-update"

Remove the "ocsp-update" keyword handling from the crt-list.

The code was made as an exception everywhere so we could activate the
ocsp-update for an individual certificate.

The feature will still exists but will be parsed as a "crt-store"
keyword which will still be usable in a "crt-list". This will appear in
future commits.

This commit also disable the reg-tests for now.

13 months agoMEDIUM: ssl/crtlist: loading crt-store keywords from a crt-list
William Lallemand [Wed, 10 Apr 2024 15:21:50 +0000 (17:21 +0200)] 
MEDIUM: ssl/crtlist: loading crt-store keywords from a crt-list

This patch allows the usage of "crt-store" keywords from a "crt-list".

The crtstore_parse_load() function was splitted into 2 functions, so the
keywords parsing is done in ckch_conf_parse().

With this patch, crt are loaded with ckch_store_new_load_files_conf() or
ckch_store_new_load_files_path() depending on weither or not there is a
"crt-store" keyword.

More checks need to be done on "crt" bind keywords to ensure that
keywords are compatible.

This patch does not introduce the feature on the CLI.

13 months agoMINOR: ssl: ckch_store_new_load_files_conf() loads filenames from ckch_conf
William Lallemand [Thu, 11 Apr 2024 16:33:35 +0000 (18:33 +0200)] 
MINOR: ssl: ckch_store_new_load_files_conf() loads filenames from ckch_conf

ckch_store_new_load_files_conf() is the equivalent of
new_ckch_store_load_files_path() but instead of trying to find the files
using a base filename, it will load them from a list of files.

13 months agoMEDIUM: mux-h1: Support C-L/T-E header suppressions when sending messages
Christopher Faulet [Thu, 16 May 2024 15:37:13 +0000 (17:37 +0200)] 
MEDIUM: mux-h1: Support C-L/T-E header suppressions when sending messages

During the 2.9 dev cycle, to be able to support zero-copy data forwarding, a
change on the H1 mux was performed to ignore the headers modifications about
payload representation (Content-Length and Transfer-Encoding headers).

It appears there are some use-cases where it could be handy to change values
of these headers or just remove them. For instance, we can imagine to remove
these headers on a server response to force the old HTTP/1.0 close mode
behavior. So thaks to this patch, the rules are relaxed. It is now possible
to remove these headers. When this happens, the following rules are applied:

 * If "Content-Length" header is removed but a "Transfer-Encoding: chunked"
   header is found, no special processing is performed. The message remains
   chunked. However the close mode is not forced.

 * If "Transfer-Encoding" header is removed but a "Content-Length" header is
   found, no special processing is performed. The payload length must comply
   to the specified content length.

 * If one of them is removed and the other one is not found, a response is
   switch the close mode and a "Content-Length: 0" header is forced on a
   request.

With these rules, we fit the best to the user expectations.

This patch depends on the following commit:

  * MINOR: mux-h1: Add a flag to ignore the request payload

This patch should fix the issue #2536. It should be backported it to 2.9
with the commit above.

13 months agoCLEANUP: mux-h1: Remove unused H1S_F_ERROR_MASK mask value
Christopher Faulet [Thu, 16 May 2024 15:29:16 +0000 (17:29 +0200)] 
CLEANUP: mux-h1: Remove unused H1S_F_ERROR_MASK mask value

This mask value is unused, so we can safely remove it. It is a chance
because its value was wrong. But there is no bug here, even in stable
versions, because it is no longer used in all versions.

13 months agoREORG: mux-h1: Group H1S_F_BODYLESS_* flags
Christopher Faulet [Thu, 16 May 2024 15:27:43 +0000 (17:27 +0200)] 
REORG: mux-h1: Group H1S_F_BODYLESS_* flags

To ease reading of H1S flags, H1S_F_BODYLESS_REQ and H1S_F_BODYLESS_RESP
flags are grouped.

13 months agoMINOR: mux-h1: Add a flag to ignore the request payload
Christopher Faulet [Thu, 16 May 2024 15:11:50 +0000 (17:11 +0200)] 
MINOR: mux-h1: Add a flag to ignore the request payload

There was a flag to skip the response payload on output, if any, by stating
it is bodyless. It is used for responses to HEAD requests or for 204/304
responses. This allow rewrites during analysis. For instance a HEAD request
can be rewrite to a GET request for any reason (ie, a server not supporting
HEAD requests). In this case, the server will send a response with a
payload. On frontend side, the payload will be skipped and a valid response
(without payload) will be sent to the client.

With this patch we introduce the corresponding flag for the request. It will
be used to skip the request payload. In addition, when payload must be
skipped for a request or a response, The zero-copy data forwarding is now
disabled.

13 months agoBUG/MINOR: stats: Don't state the 303 redirect response is chunked
Christopher Faulet [Fri, 17 May 2024 13:42:46 +0000 (15:42 +0200)] 
BUG/MINOR: stats: Don't state the 303 redirect response is chunked

Start-line flags for 303-See-Other response returned by the stats applet are
not properly set. Indeed, the reponse has a "content-length" header but both
HTX_SL_F_CHNK and HTX_SL_F_CLEN flags are set. Because of this bug, the
reponse is considered as chunked. So, let's remove HTX_SL_F_CHNK flag.

And also add HTX_SL_F_BODYLESS flag because there is no payload
("content-length" header is always set to 0).

This patch must be backported to all stable versions. On the 2.8 and lower
versions, the commit d0b04920d1 ("BUG/MINOR: htpp-ana/stats: Specify that
HTX redirect messages have a C-L header") must be backported first.

13 months agoRevert: MEDIUM: evports: permit to report multiple events at once"
Willy Tarreau [Fri, 17 May 2024 13:53:40 +0000 (15:53 +0200)] 
Revert: MEDIUM: evports: permit to report multiple events at once"

Tests have shown that switching nevlist to global.tune.maxpollevents
is totally unreliable when using evports, and that events seem to be
missed. A good reproducer seems to be QUIC. There are not enough
users of Solaris to warrant spending more time trying to get down to
this, and even the few that remain are by definition not interested
in performance, so let's just revert the commit that tried to lift the
value: e6662bf706 ("MEDIUM: evports: permit to report multiple events
at once").

No backport is needed.

13 months agoCLEANUP: compat: make the MIN/MAX macros more reliable
Willy Tarreau [Fri, 17 May 2024 13:25:26 +0000 (15:25 +0200)] 
CLEANUP: compat: make the MIN/MAX macros more reliable

After every release we say that MIN/MAX should be changed to be an
expression that only evaluates each operand once, and before every
version we forget to change it and we recheck that the code doesn't
misuse them. Let's fix them now.

13 months agoBUG/MEDIUM: fd: prevent memory waste in fdtab array
Aurelien DARRAGON [Fri, 17 May 2024 08:54:54 +0000 (10:54 +0200)] 
BUG/MEDIUM: fd: prevent memory waste in fdtab array

In 97ea9c49f1 ("BUG/MEDIUM: fd: always align fdtab[] to 64 bytes"), the
patch doesn't do what the message says. The intent was only to align the
base fdtab addr on 64 bytes so that all fdtab entries are aligned and thus
don't share the same cache line. For that, fdtab pointer is adjusted from
fdtab_addr (unaligned) address after it is allocated. Thus, all we need
is an extra 64 bytes in the fdtab_addr array for the aligment. Because
we use calloc() to perform the allocation, a dumb mistake was made: the
'+64' was added on <size> calloc argument, which means EACH fdtab entry
is allocated with 64 extra bytes.

Given that a single fdtab entry is 64 bytes, since 97ea9c49f1 each fdtab
entry now takes 128 bytes! We doubled fdtab memory consumption.

To give you an idea, on my laptop, when looking at memory consumption
using 'ps -p `pidof haproxy` -o size' right after starting haproxy
process with default settings (no maxsock enforced):

before 97ea9c49f1:
  -> 118440 (KB, ~= 118MB)

after 97ea9c49f1:
  -> 183976 (KB, ~= 184MB)

To fix this, use calloc with 1 <nmemb> and manually provide the size with
<size> as we would do if we used malloc(). With this patch, we're back to
pre-97ea9c49f1 for fdtab  memory consumption (with 64 extra bytes the
whole array, which is insignificant).

It should be backported to all stable versions.

13 months agoBUILD: log: get rid of non-portable strnlen() func
Aurelien DARRAGON [Fri, 17 May 2024 08:24:33 +0000 (10:24 +0200)] 
BUILD: log: get rid of non-portable strnlen() func

In c614fd3b9 ("MINOR: log: add +cbor encoding option"), I wrongly used
strnlen() without noticing that the function is not portable (requires
_POSIX_C_SOURCE >= 2008) and that it was the first occurrence in the
entire project. In fact it is not a hard requirement since it's a pretty
simple function. Thus to restore build compatibility with minimal/older
build systems, let's actually get rid of it and use an equivalent portable
code where needed (we cannot simply rely on strlen() because the string
might not be NULL terminated, we must take upstream len into account).

No backport needed (unless c614fd3b9 gets backported)

13 months agoMEDIUM: ssl: add ocsp-update.mindelay and ocsp-update.maxdelay
William Lallemand [Tue, 30 Apr 2024 20:57:03 +0000 (22:57 +0200)] 
MEDIUM: ssl: add ocsp-update.mindelay and ocsp-update.maxdelay

This patch deprecates tune.ssl.ocsp-update.* in favor of
"ocsp-update.*".

Since the ocsp-update is not really a tunable of the SSL connections.

13 months agoBUILD: stats: remove non portable getline() usage
Amaury Denoyelle [Fri, 17 May 2024 12:50:12 +0000 (14:50 +0200)] 
BUILD: stats: remove non portable getline() usage

getline() was used to read stats-file. However, this function is not
portable and may cause build issue on some systems. Replace it by
standard fgets().

No need to backport.

13 months agoREGTESTS: update the ocsp-update tests
William Lallemand [Tue, 7 May 2024 07:55:02 +0000 (09:55 +0200)] 
REGTESTS: update the ocsp-update tests

Update the ocsp-update tests for the recent changes:

- "tune.ssl.ocsp-update.mode" was renamed iin "ocsp-update.mode"

13 months agoMINOR: ssl: rename tune.ssl.ocsp-update.mode in ocsp-update.mode
William Lallemand [Tue, 30 Apr 2024 20:31:47 +0000 (22:31 +0200)] 
MINOR: ssl: rename tune.ssl.ocsp-update.mode in ocsp-update.mode

Since the ocsp-update is not strictly a tuning of the SSL stack, but a
feature of its own, lets rename the option.

The option was also missing from the index.

13 months agoBUILD: stick-tables: better mark the stktable_data as 32-bit aligned
Willy Tarreau [Fri, 17 May 2024 06:38:00 +0000 (08:38 +0200)] 
BUILD: stick-tables: better mark the stktable_data as 32-bit aligned

Aurélien reported that clang's build was broken by the recent fix
845fb846c7 ("BUG/MEDIUM: stick-tables: properly mark stktable_data
as packed"), because it now wants to use a helper for some atomic
ops (to increment std_t_uint). While this makes no sense to do
something that slow on modern architectures like x86 and arm64 which
are fine with unaligned accesses, we actually we can simply mark the
struct as aligned to its smallest element which is 32-bit (but still
packed). With this, it was verified that it is enough for clang to
see that its 32-bit operations will always be aligned, while making
64-bit operations safe on 64-bit platforms that do not support unaligned
accesses.

This should be backported wherever the patch above is backported.

13 months agoMINOR: h3: report glitch on RFC violation
Amaury Denoyelle [Mon, 13 May 2024 15:45:38 +0000 (17:45 +0200)] 
MINOR: h3: report glitch on RFC violation

Increment glitch connection counter on every HTTP/3 or QPACK errors
which is a violation of the specification. This could be useful to get
rid early of bogus clients.

13 months agoMINOR: mux-quic: support glitches
Amaury Denoyelle [Mon, 13 May 2024 07:05:27 +0000 (09:05 +0200)] 
MINOR: mux-quic: support glitches

Implement basic support for glitches on QUIC multiplexer. This is mostly
identical too glitches for HTTP/2.

A new configuration option named tune.quic.frontend.glitches-threshold
is defined to limit the number of glitches on a connection before
closing it.

Glitches counter is incremented via qcc_report_glitch(). A new
qcc_app_ops callback <report_susp> is defined. On threshold reaching, it
allows to set an application error code to close the connection. For
HTTP/3, value H3_EXCESSIVE_LOAD is returned. If not defined, default
code INTERNAL_ERROR is used.

For the moment, no glitch are reported for QUIC or HTTP/3 usage. This
will be added in future patches as needed.

13 months agoMINOR: h3: adjust error reporting on receive
Amaury Denoyelle [Mon, 13 May 2024 15:44:54 +0000 (17:44 +0200)] 
MINOR: h3: adjust error reporting on receive

This commit is the second step to simplify HTTP/3 error management. This
times it deals with receive side on h3_rcv_buf().

Various internal HTTP/3 to HTX conversion functions does not set
H3_INTERNAL_ERROR on h3c err anymore. Only standard error code are set.
For every errors, both internal and protocol ones, a negative value is
returned. This ensure that h3_rcv_buf() looping is interrupted. This
function will then set H3_INTERNAL_ERROR only if no standard error is
registered via h3c or h3s.

Along the previous commit, this should better reflect internal errors
from protocol ones caused by a faulty client.

13 months agoMINOR: h3: adjust error reporting on sending
Amaury Denoyelle [Mon, 13 May 2024 15:27:26 +0000 (17:27 +0200)] 
MINOR: h3: adjust error reporting on sending

It's currently difficult to differentiate HTTP/3 standard protocol
violation from internal issues which use solely H3_INTERNAL_ERROR code.
This patch aims is the first step to simplify this. The objective is to
reduce H3_INTERNAL_ERROR. <err> field of h3c should be reserved
exclusively to other values.

Simplify error management in sending via h3_snd_buf(). Sending side is
straightforward as only internal errors can be encountered. Do not
manually set h3c.err to H3_INTERNAL_ERROR in HTX to HTTP/3 various
conversion function. Instead, just return a negative value which is
enough to break h3_snd_buf() loop. H3_INTERNAL_ERROR is thus positionned
on a single location in this function for all sending operations.

13 months agoMINOR: h3/qpack: adjust naming for errors
Amaury Denoyelle [Fri, 10 May 2024 16:12:15 +0000 (18:12 +0200)] 
MINOR: h3/qpack: adjust naming for errors

Rename enum values used for HTTP/3 and QPACK RFC defined codes. First
uses a prefix H3_ERR_* which serves as identifier between them. Also
separate QPACK values in a new dedicated enum qpack_err. This is deemed
cleaner.

13 months agoMINOR: qpack: prepare error renaming
Amaury Denoyelle [Fri, 10 May 2024 16:17:41 +0000 (18:17 +0200)] 
MINOR: qpack: prepare error renaming

There is two distinct enums both related to QPACK error management. The
first one is dedicated to RFC defined code. The other one is a set of
internal values returned by qpack_decode_fs(). There has been issues
discovered recently due to the confusion between them.

Rename internal values with the prefix QPACK_RET_*. The older name
QPACK_ERR_* will be used in a future commit for the first enum.

13 months agoBUG/MAJOR: h1: Be stricter on request target validation during message parsing
Christopher Faulet [Wed, 15 May 2024 14:53:50 +0000 (16:53 +0200)] 
BUG/MAJOR: h1: Be stricter on request target validation during message parsing

As stated in issue #2565, checks on the request target during H1 message
parsing are not good enough. Invalid paths, not starting by a slash are in
fact parsed as authorities. The same error is repeated at the sample fetch
level. This last point is annoying because routing rules may be fooled. It
is also an issue when the URI or the Host header are updated.

Because the error is repeated at different places, it must be fixed. We
cannot be lax by arguing it is the server's job to accept or reject invalid
request targets. With this patch, we strengthen the checks performed on the
request target during H1 parsing. Idea is to reject invalid requests at this
step to be sure it is safe to manipulate the path or the authority at other
places.

So now, the asterisk-form is only allowed for OPTIONS and OTHER methods.
This last point was added to not reject the H2 preface. In addition, we take
care to have only one asterisk and nothing more. For the CONNECT method, we
take care to have a valid authority-form. All other form are rejected. The
authority-form is now only supported for CONNECT method. No specific check
is performed on the origin-form (except for the CONNECT method). For the
absolute-form, we take care to have a scheme and a valid authority.

These checks are not perfect but should be good enough to properly identify
each part of the request target for a relative small cost. But, it is a
breaking change. Some requests are now be rejected while they was not on
older versions. However, nowadays, it is most probably not an issue.  If it
turns out it's really an issue for legitimate use-cases, an option would be
to supports these kinds of requests when the "accept-invalid-http-request"
option is set, with the consequence of seeing some sample fetches having an
unexpected behavior.

This patch should fix the issue #2665. It MUST NOT be backported. First
because it is a breaking change. And then because by avoiding backporting
it, it remains possible to relax the parsing with the
"accept-invalid-http-request" option.

13 months agoBUG/MEDIUM: h1: Reject CONNECT request if the target has a scheme
Christopher Faulet [Tue, 14 May 2024 13:06:48 +0000 (15:06 +0200)] 
BUG/MEDIUM: h1: Reject CONNECT request if the target has a scheme

The target of a CONNECT request must not have scheme. However, this was not
checked during the message parsing. It is now rejected.

This patch may be backported as far as 2.4.

13 months agoBUG/MINOR: h1: Check authority for non-CONNECT methods only if a scheme is found
Christopher Faulet [Tue, 14 May 2024 09:42:21 +0000 (11:42 +0200)] 
BUG/MINOR: h1: Check authority for non-CONNECT methods only if a scheme is found

When a non-CONNECT H1 request is parsed, the authority is compared to the
host header value, to validate that they are the same. However there is an
issue here when a relative path is used (not begining with a '/'). In this
case, the path is considered as the authority and will be erroneously
compared to the host header value. It is observable with this kind of
request:

  GET admin HTTP/1.1
  Host: www.mysite.com

In this case "admin" is parsed as an authority while it is in fact a path.
At this step, it is not a big deal because it just happens on the very first
checks on the message during the parsing. However, the same happens when the
authority is updated. This will be fixed in another commit

Note this kind of request is invalid because the path does not start with a
'/'. But, till now, HAProxy does not reject it.

This patch is related to issue #2565. It must be backported as far as 2.4.

13 months agoBUG/MEDIUM: muxes: enforce buf_wait check in takeover()
Willy Tarreau [Tue, 14 May 2024 17:26:44 +0000 (19:26 +0200)] 
BUG/MEDIUM: muxes: enforce buf_wait check in takeover()

The ->takeover() is quite tricky. It didn't take care of the possibility
that the original thread's connection handler had been woken up to handle
an event (e.g. read0), failed to get a buffer, registered against its own
thread's buffer_wait queue and left the connection in an idle state.

A new thread could then come by, perform a takeover(), and when a buffer
was available, the new thread's tasklet would be woken up by the old one
via *_buf_available(), causing all sort of problems. These problems are
easy to reproduce, by running with shared backend connections and few
buffers (tune.buffers.limit=20, 8 threads, 500 connections, transfer
64kB objects and wait 2-5s for a crash to appear).

A first estimated solution consisted in removing the connection from the
idle list but it turns out that it would be worse for the delete stuff
(the connection no longer appearing as idle, making it impossible to find
it in order to close it). Also, idle counts wouldn't match anymore the
list's state, and the special case of private connections could be
difficult to handle as the connection could be forcefully re-added to the
idle list after allocation despite being private.

After multiple attempts to address the problem in various ways, it appears
that the only reliable solution for now (without starting to turn many
lists to mt_lists) is to have the takeover() function handle the buf_wait
detection or unregistration itself:

  - when doing a regular takeover aiming at finding an idle connection
    for a new request, connections that are blocked in a buffer_wait
    queue are quite rare and not interesting at all (since not immediately
    usable), so skipping them is sufficient. For this we detect that the
    desired connection belongs to a buffer_wait list by checking its
    buf_wait.list element. Note that this check is *not* thread-safe! The
    LIST_DEL_INIT() is performed by __offer_buffers() after the callback
    was called. But this is sufficient as it is now because the only way
    for the element to be seen as not in a list is after the element was
    last touched by __offer_buffers(), so the situation for this connection
    will not change in a different way later.

  - when doing a server delete, we're running under thread isolation.
    The connection might get taken over to be killed. The only trick is
    that private connections not belonging to any idle list may also
    experience this, and in this case even the idle_conns lock will not
    offer any protection against anything. But since we're run under
    thread isolation, we're certain not to compete with the other thread,
    so it's safe to directly unregister the connection from its owner
    thread. Normally this is already handled by conn_release() in
    cli_parse_delete_server(), which calls mux->destroy(), but this would
    actually update the current thread's queue instead of the origin
    thread's, thus we do need to perform an explicit dequeue before
    completing the takeover.

With this, the problem now looks solved for HTTP/1, HTTP/2 and FCGI,
though extensive tests were essentially run on HTTP/1 and HTTP/2.

While the problem has been there for a very long time, there should be
no reason to backport it since buffer_wait didn't practically work
before 3.0-dev and the process used to freeze hard very quickly before
we'd even have a chance to meet that race.

13 months agoMINOR: dynbuf: provide a b_dequeue() variant for multi-thread
Willy Tarreau [Tue, 14 May 2024 17:19:23 +0000 (19:19 +0200)] 
MINOR: dynbuf: provide a b_dequeue() variant for multi-thread

In order to forcefully unregister a buffer waiter during an inter-thread
takeover under isolation, we'll need to that the function works without
th_ctx but the target thread's ctx instead. Let's implement this by
passing the target thread as an argument. Now b_dequeue() simply calls
this one with tid. It's OK it's not on that critical a path, especially
since the list has been checked for existence before performing the call.

13 months agoBUG/MINOR: ssl_sock: fix xprt_set_used() to properly clear the TASK_F_USR1 bit
Willy Tarreau [Tue, 14 May 2024 16:54:20 +0000 (18:54 +0200)] 
BUG/MINOR: ssl_sock: fix xprt_set_used() to properly clear the TASK_F_USR1 bit

In 2.4-dev8 with commit 5c7086f6b0 ("MEDIUM: connection: protect idle
conn lists with locks"), the idle conns list started to be protected
using the lock for takeover, and the SSL layer used to always take
that lock. Later in 2.4-dev11, with commit 4149168255 ("MEDIUM: ssl:
implement xprt_set_used and xprt_set_idle to relax context checks"), we
decided to relax this lock using TASK_F_USR1 just as is done in muxes.

However the xprt_set_used() call, that's supposed to clear the flag,
visibly suffered from a copy-paste and kept the OR operation instead of
the AND, resulting in the flag never being released, so that SSL on the
backend continues to take the lock on each and every I/O access even when
the connection is not idle.

The effect is only a reduced performance. This could be backported, but
given the non-zero risk of triggering another bug somewhere, it would
be prudent to wait for this fix to be sufficiently tested in new
versions first.

13 months agoSCRIPTS: run-regtests: fix a few occurrences of extended regexes
Willy Tarreau [Wed, 15 May 2024 17:33:45 +0000 (19:33 +0200)] 
SCRIPTS: run-regtests: fix a few occurrences of extended regexes

Running run-regtests on OpenBSD failed to identify haproxy version and
the various build options because the backslash is not recognized in
grep expressions. One must only use -E for the extended regexes and
not use the slash.

13 months agoBUG/MEDIUM: stick-tables: properly mark stktable_data as packed
Willy Tarreau [Wed, 15 May 2024 14:22:23 +0000 (16:22 +0200)] 
BUG/MEDIUM: stick-tables: properly mark stktable_data as packed

The stktable_data union is made of types of varying sizes, and depending
on which types are stored in a table, some offsets might not necessarily
be aligned. This results in a bus error for certain regtests (e.g.
lb-services) on MIPS64. This bug may impact MIPS64, SPARC64, armv7 when
accessing a 64-bit counter (e.g. bytes) and depending on how the compiler
emitted the operation, and cause a trap that's emulated by the OS on RISCV
(heavy cost). x86_64 and armv8 are not affected at all.

Let's properly mark the struct with __attribute__((packed)) so that the
compiler emits the suitable unaligned-compatible instructions when
accessing the fields.

This should be backported to all versions where it applies.

13 months agoBUG/MEDIUM: htx: mark htx_sl as packed since it may be realigned
Willy Tarreau [Wed, 15 May 2024 16:23:18 +0000 (18:23 +0200)] 
BUG/MEDIUM: htx: mark htx_sl as packed since it may be realigned

A test on MIPS64 revealed that the following reg tests would all
fail at the same place in htx_replace_stline() when updating
parts of the request line:
  reg-tests/cache/if-modified-since.vtc
  reg-tests/http-rules/h1or2_to_h1c.vtc
  reg-tests/http-rules/http_after_response.vtc
  reg-tests/http-rules/normalize_uri.vtc
  reg-tests/http-rules/path_and_pathq.vtc

While the status line is normally aligned since it's the first block
of the HTX, it may become unaligned once replaced. The problem is, it
is a structure which contains some u16 and u32, and dereferencing them
on machines not natively supporting unaligned accesses makes them crash
or handle crap. Typically, MIPS/MIPS64/SPARC will crash, ARMv5 will
either crash or (more likely) return swapped values and do crap, and
RISCV will trap and turn to slow emulation.

We can assign the htx_sl struct the packed attribute, but then this
also causes the ints to fill the 2-bytes gap before them, always causing
unaligned accesses for this part on such machines. The patch does a bit
better, by explicitly filling this two-bytes hole, and packing the
struct.

This should be backported to all versions.

13 months agoBUG/MINOR: qpack: fix error code reported on QPACK decoding failure
Amaury Denoyelle [Mon, 13 May 2024 14:01:08 +0000 (16:01 +0200)] 
BUG/MINOR: qpack: fix error code reported on QPACK decoding failure

qpack_decode_fs() is used to decode QPACK field section on HTTP/3
headers parsing. Its return value is incoherent as it returns either
QPACK_DECOMPRESSION_FAILED defined in RFC 9204 or any other internal
values defined in qpack-dec.h. On failure, such return code is reused by
HTTP/3 layer to be reported via a CONNECTION_CLOSE frame. This is
incorrect if an internal error values was reported as it is not defined
by any specification.

Fir return values of qpack_decode_fs() in two ways. Firstly, fix invalid
usages of QPACK_DECOMPRESSION_FAILED when decoded content is too large
for the correct internal error QPACK_ERR_TOO_LARGE.

Secondly, adjust qpack_decode_fs() API to only returns internal code
values. A new internal enum QPACK_ERR_DECOMP is defined to replace
QPACK_DECOMPRESSION_FAILED. Caller is responsible to convert it to a
suitable error value. For other internal values, H3_INTERNAL_ERROR is
used. This is done through a set of convert functions.

This should be backported up to 2.6. Note that trailers are not
supported in 2.6 so chunk related to h3_trailers_to_htx() can be safely
skipped.

13 months agoBUG/MINOR: mux-quic: fix error code on shutdown for non HTTP/3
Amaury Denoyelle [Mon, 13 May 2024 07:02:47 +0000 (09:02 +0200)] 
BUG/MINOR: mux-quic: fix error code on shutdown for non HTTP/3

qcc_shutdown() is called whenever the connection must be closed. If
application protocol defined its owned shutdown callback, it is invoked
to use the correct error code. Else transport error code NO_ERROR is
used.

A bug occurs in the latter case as NO_ERROR is used with quic_err_app()
which is reserved for application errro codes. This will trigger the
emission of a CONNECTION_CLOSE of type 0x1d (Application) instead of
0x1c (Transport).

This bug is considered minor as it does not impact QUIC with HTTP/3. It
may only be visible when using experimental HTTP/0.9 protocol.

This should be backported up to 2.6. For 2.6, patch must be completed
rewritten due to code differences. Here is the change to apply :

  diff --git a/src/mux_quic.c b/src/mux_quic.c
  index 26fb70ddf..c48f82e27 100644
  --- a/src/mux_quic.c
  +++ b/src/mux_quic.c
  @@ -1918,7 +1918,9 @@ static void qc_release(struct qcc *qcc)
                          qc_send(qcc);
                  }
                  else {
  -                       qcc_emit_cc_app(qcc, QC_ERR_NO_ERROR, 0);
  +                       /* Duplicate from qcc_emit_cc_app() for Transport error code. */
  +                       if (!(qcc->conn->handle.qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE))
  +                               qcc->conn->handle.qc->err = quic_err_transport(QC_ERR_NO_ERROR);
                  }
          }

13 months agoBUG/MEDIUM: server: clear purgeable conns before server deletion
Amaury Denoyelle [Wed, 15 May 2024 12:28:21 +0000 (14:28 +0200)] 
BUG/MEDIUM: server: clear purgeable conns before server deletion

Since the following commit, idle connections are cleared before a server
is deleted. This is better than blocking server deletion due to inactive
connections :

  6e0afb2e274952663957121ea33cb6bae574fc2e
  MEDIUM: server: close idle conn on server deletion

A BUG_ON() has been added to ensure that server idle conn counter is nul
after these connections are removed. However, Willy managed to trigger
it easily by repeatedly and randomly delete servers accross a
single-thread haproxy using a server-template with 1000 instances. In
parallel, a h1load client is executed to generate traffic.

This BUG_ON() reflected that it some connections referencing the server
targetted for deletion remained, even though idle server list is empty.
In fact, this is caused by connections scheduled for purging. These
connections are moved from idle server list to a global toremove_list
while still being accounted by the server.

A first approach could be to decrement server idle counter while moving
connection to the purge list. However, this is functionnaly incorrect as
these purgeable connections still reference the server and it could
cause a crash if cleared after it.

The correct fix for this issue is simply to remove every purgeable
connections before a server is deleted. This is implemented by this
patch by extending cli_parse_delete_server(). It could be enough to only
remove connections targetted the deleted server, but as these
connections will be purged anyway it is justified to clear the whole
list.

This must not be backported, unless the above mentionned patch is.

13 months agoMEDIUM: hlua: take nbthread into account in hlua_get_nb_instruction()
Aurelien DARRAGON [Wed, 15 May 2024 08:02:27 +0000 (10:02 +0200)] 
MEDIUM: hlua: take nbthread into account in hlua_get_nb_instruction()

Based on Willy's idea (from 3.0-dev6 announcement message): in this patch
we try to reduce the max latency that can be caused by running lua scripts
with default settings.

Indeed, by default, hlua engine is allowed to process up to 10k
instructions per batch. While this value was found to be the optimal one
for a single thread, it turns out that keeping a thread busy for 10k lua
instructions could increase thread contention. This is especially true
when the script is loaded with 'lua-load', because in that case the
current thread owns the main lua lock and prevent other threads from
making any progress if they're also waiting on the main lock.

Thanks to Thierry Fournier's work, we know that performance-wise we can
reach optimal performance by sticking between 500 and 10k instructions
per batch. Given that, when the script is loaded using 'lua-load', if no
"tune.lua.forced-yield" was set by the user, we automatically divide the
default value (10K) by the number of threads haproxy can use to reduce
thread contention (given that all threads could compete for the main lua
lock), however we make sure not to return a value below 500, because
Thierry's work showed that this would come with a significant performance
loss.

The historical behavior may still be enforced by setting
"tune.lua.forced-yield" to 10000 in the global config section.

13 months agoMINOR: hlua: add hlua_nb_instruction getter
Aurelien DARRAGON [Wed, 15 May 2024 08:19:46 +0000 (10:19 +0200)] 
MINOR: hlua: add hlua_nb_instruction getter

No functional behavior change, but this will ease the work of dynamically
computing hlua_nb_instruction value depending on various inputs.

13 months agoDOC: Update UUID references to RFC 9562
Tim Duesterhus [Sun, 12 May 2024 15:08:34 +0000 (17:08 +0200)] 
DOC: Update UUID references to RFC 9562

When support for UUIDv7 was added in commit
aab6477b67415c4cc260bba5df359fa2e6f49733
the specification still was a draft.

It has since been published as RFC 9562.

This patch updates all UUID references from the obsoleted RFC 4122 and the
draft for RFC 9562 to the published RFC 9562.

13 months agoREGTESTS: ssl: be more verbose with ocsp_compat_check.vtc
William Lallemand [Tue, 7 May 2024 12:06:45 +0000 (14:06 +0200)] 
REGTESTS: ssl: be more verbose with ocsp_compat_check.vtc

the ocsp_compat_check.vtc reg-test is difficult to debug given than the
haproxy output is piped in `grep -q`.

This patch helps by showing the haproxy output as well as the return
code.

13 months agoMINOR: rhttp: Don't require SSL when attach-srv name parsing
William Manley [Wed, 8 May 2024 10:43:11 +0000 (11:43 +0100)] 
MINOR: rhttp: Don't require SSL when attach-srv name parsing

An attach-srv config line usually looks like this:
    tcp-request session attach-srv be/srv name ssl_c_s_dn(CN)

while a rhttp server line usually looks like this:
    server srv rhttp@ sni req.hdr(host)

The server sni argument is used as a key for looking up connection in
the connection pool. The attach-srv name argument is used as a key for
inserting connections into the pool. For it to work correctly they must
match. There was a check that either both the attach-srv and server
provide that key or neither does.

It also checked that SSL and SNI was activated on the server. However,
thanks to current connect_server() implementation, it appears that SNI
is usable even without SSL to identify a connection in the pool. Thus,
it can be diverted from its original intent in reverse HTTP case to
serve even without SSL activated. For example, this could be useful to
use `fc_pp_unique_id` as a name expression (DISCLAIMER: note that for
now PROXY protocol is not compatible with rhttp).

Error is still reported if either SNI or name is used without the other.
This patch adjust the message to a more helpful one.

Arguably it would be easier to understand if instead of using `name` and
`sni` for `attach-srv` and `server` rules it used the same term in both
places - like "conn-pool-key" or something. That would make it clear
that the two must match.

13 months agoBUG/MINOR: log: smp_rgs array issues with inherited global log directives
Aurelien DARRAGON [Tue, 14 May 2024 08:22:19 +0000 (10:22 +0200)] 
BUG/MINOR: log: smp_rgs array issues with inherited global log directives

When a log directive is defined in the global section, each time we use
"log global" in a proxy section, the global log directives are duplicated
for the current proxy. This works by creating a new proxy logger struct
and duplicating every members for each global one.

However, smp_rgs logger member is a special pointer member that is
allocated when "range" is used on a log directive. Currently, we simply
copy the array pointer (from the global one), instead of creating our own
copy. Because of that, range log sampling may not work properly in some
situations prior to 3f1284560 ("MINOR: log: remove the unused curr_idx in
struct smp_log_range") when used in global log directives, for instance:

  global
    log 127.0.0.1:5114 format raw sample 1-2,3:4 local0 info # should receive 75% of all proxy logs
    log 127.0.0.1:5115 format raw sample 4:4 local0 info     # should receive 25% of all proxy logs

  listen proxy1
    log global

  listen proxy2
    log global

May not work as expected, because curr_idx was stored within smp_rgs array
member prior to 3f1284560, and due to this bug, it happens to be shared
between every log directive inherited from a "global" one. The result is
that curr_idx counter will not behave properly because the index will be
increased globally instead of per-log directive, and it could even suffer
from concurrent thread accesses under load since we don't own the global
log directive's lock when manipulating it.

Another issue that was revealed because of this bug is that the smp_rgs
array allocated during config parsing is never freed in free_logger(),
resulting in small memory leak during clean exit.

To fix these issues all at once, let's properly duplicate smp_rgs logger
struct member in dup_logger() like we already do for other special members
so that every log directive have its own sms_rgs copy, and then
systematically free it in free_logger().

While this bug affects all stable versions (including 2.4), it's probably
best to not backport this beyond 2.6 because of 211ea252d
("BUG/MINOR: logs: fix logsrv leaks on clean exit") prerequisite that
first appears in 2.6.

[ada: for versions prior to 2.9, 969e212
 ("MINOR: log: add dup_logsrv() helper function") and 76acde91
 ("BUG/MINOR: log: keep the ref in dup_logger()") must be backported
 first.
 Note: Some ctx adjustments should be performed because 'logger' struct
 used to be named 'logsrv' in the past and 2.9 introduced logger target
 struct member. Thus it's probably easier to manually apply 76acde91 and
 the current bugfix by hand directly on top of 969e212.
]

13 months agoBUG/MINOR: log: fix leak in add_sample_to_logformat_list() error path
Aurelien DARRAGON [Mon, 13 May 2024 14:24:10 +0000 (16:24 +0200)] 
BUG/MINOR: log: fix leak in add_sample_to_logformat_list() error path

If add_sample_to_logformat_list() fails to allocate new logformat_node,
then we directly jump to error_free label to cleanup the node using
free_logformat_node() before returning an error.

However if the node failed to allocate, then the sample expression that
was allocated just before (not yet assigned) isn't released
(free_logformat_node() is a no-op when NULL is provided). Thus if expr
wasn't assigned to the node during early failure, then it must be manually
released.

This bug was introduced by 2462e5bcc ("BUG/MINOR: log: fix potential
lf->name memory leak") which wasn't marked for backports. It only
affects 3.0.

13 months agoCI: drop asan.log umbrella completely
Ilia Shipitsin [Thu, 9 May 2024 20:19:18 +0000 (22:19 +0200)] 
CI: drop asan.log umbrella completely

asan.log redirection appeared to work poorly, let's cease that practice
for good.

ML: https://www.mail-archive.com/haproxy@formilux.org/msg44844.html

13 months ago[RELEASE] Released version 3.0-dev11 v3.0-dev11
Willy Tarreau [Fri, 10 May 2024 15:39:19 +0000 (17:39 +0200)] 
[RELEASE] Released version 3.0-dev11

Released version 3.0-dev11 with the following main changes :
    - BUILD: clock: improve check for pthread_getcpuclockid()
    - CI: add Illumos scheduled workflow
    - CI: netbsd: limit scheduled workflow to parent repo only
    - OPTIM: log: resolve logformat options during postparsing
    - BUG/MINOR: haproxy: only tid 0 must not sleep if got signal
    - REGTEST: add tests for acl() sample fetch
    - BUG/MINOR: acl: support built-in ACLs with acl() sample
    - BUG/MINOR: cfgparse: use curproxy global var from config post validation
    - MEDIUM: stconn/muxes: Add an abort reason for SE shutdowns on muxes
    - MINOR: mux-h2: Set the SE abort reason when a RST_STREAM frame is received
    - MEDIUM: mux-h2: Forward h2 client cancellations to h2 servers
    - MINOR: mux-quic: Set tha SE abort reason when a STOP_SENDING frame is received
    - MINOR: stconn: Add samples to retrieve about stream aborts
    - MINOR: mux-quic: Add .ctl callback function to get info about a mux connection
    - MINOR: muxes: Add ctl commands to get info on streams for a connection
    - MINOR: connection: Add samples to retrieve info on streams for a connection
    - BUG/MEDIUM: log/ring: broken syslog octet counting
    - BUG/MEDIUM: mux-quic: fix crash on STOP_SENDING received without SD
    - DOC: lua: fix filters.txt file location
    - MINOR: dynbuf: pass a criticality argument to b_alloc()
    - MINOR: dynbuf: add functions to help queue/requeue buffer_wait fields
    - MINOR: dynbuf: use the b_queue()/b_requeue() functions everywhere
    - MEDIUM: dynbuf: make the buffer_wq an array of list heads
    - CLEANUP: tinfo: better align fields in thread_ctx
    - MINOR: dynbuf: provide a b_dequeue() function to detach a bw from the queue
    - MEDIUM: dynbuf: generalize the use of b_dequeue() to detach buffer_wait
    - MEDIUM: dynbuf/stream: re-enable queueing upon failed buffer allocation
    - MEDIUM: dynbuf/stream: do not allocate the buffers in the callback
    - MEDIUM: applet: make appctx_buf_available() only wake the applet up, not allocate
    - MINOR: applet: set the blocking flag in the buffer allocation function
    - MINOR: applet: adjust the allocation criticity based on the requested buffer
    - MINOR: dynbuf/mux-h1: use different criticalities for buffer allocations
    - MEDIUM: dynbuf/mux-h1: do not allocate the buffers in the callback
    - MEDIUM: dynbuf: refrain from offering a buffer if more critical ones are waiting
    - MINOR: stconn: report that a buffer allocation succeeded
    - MINOR: stream: report that a buffer allocation succeeded
    - MINOR: applet: report about buffer allocation success
    - MINOR: mux-h1: report that a buffer allocation succeeded
    - MEDIUM: stream: allocate without queuing when retrying
    - MEDIUM: channel: allocate without queuing when retrying
    - MEDIUM: mux-h1: allocate without queuing when retrying
    - MEDIUM: dynbuf: implement emergency buffers
    - MEDIUM: dynbuf: use emergency buffers upon failed memory allocations

13 months agoMEDIUM: dynbuf: use emergency buffers upon failed memory allocations
Willy Tarreau [Mon, 29 Apr 2024 06:36:09 +0000 (08:36 +0200)] 
MEDIUM: dynbuf: use emergency buffers upon failed memory allocations

Now, if a pool_alloc() fails for a buffer and if conditions are met
based on the queue number, we'll try to get an emergency buffer.

Thanks to this the situation is way more stable now. With only 4 reserve
buffers and 1 buffer it's possible to reliably serve 500 concurrent end-
to-end H1 connections and consult stats in parallel in loops showing the
growing number of buf_wait events in "show activity" without facing an
instant stall like in the past. Lower values still cause quick stalls
though.

It's also apparent that some subsystems do not seem to detach from the
buffer_wait lists when leaving. For example several crashes in the H1
part showed list elements still present after a free(), so maybe some
operations performed inside h1_release() after the b_dequeue() call
can sometimes result in a new allocation. Same for streams, where
the dequeue is done relatively early.

13 months agoMEDIUM: dynbuf: implement emergency buffers
Willy Tarreau [Fri, 26 Apr 2024 14:40:32 +0000 (16:40 +0200)] 
MEDIUM: dynbuf: implement emergency buffers

The buffer reserve set by tune.buffers.reserve has long been unused, and
in order to deal gracefully with failed memory allocations we'll need to
resort to a few emergency buffers that are pre-allocated per thread.

These buffers are only for emergency use, so every time their count is
below the configured number a b_free() will refill them. For this reason
their count can remain pretty low. We changed the default number from 2
to 4 per thread, and the minimum value is now zero (e.g. for low-memory
systems). The tune.buffers.limit setting has always been a problem when
trying to deal with the reserve but now we could simplify it by simply
pushing the limit (if set) to match the reserve. That was already done in
the past with a static value, but now with threads it was a bit trickier,
which is why the per-thread allocators increment the limit on the fly
before allocating their own buffers. This also means that the configured
limit is saner and now corresponds to the regular buffers that can be
allocated on top of emergency buffers.

At the moment these emergency buffers are not used upon allocation
failure. The only reason is to ease bisecting later if needed, since
this commit only has to deal with resource management.

13 months agoMEDIUM: mux-h1: allocate without queuing when retrying
Willy Tarreau [Tue, 7 May 2024 15:36:13 +0000 (17:36 +0200)] 
MEDIUM: mux-h1: allocate without queuing when retrying

Now when trying to allocate a buffer, we can check if we've been notified
of availability via the callback, in which case we should not consult the
queue, or if we're doing a first allocation and check the queue. At this
point it still doesn't change much since the stream still doesn't make use
of it but some progress is expected.

13 months agoMEDIUM: channel: allocate without queuing when retrying
Willy Tarreau [Tue, 7 May 2024 15:52:11 +0000 (17:52 +0200)] 
MEDIUM: channel: allocate without queuing when retrying

Now when trying to allocate a channel buffer, we can check if we've been
notified of availability via the producer stream connector callback, in
which case we should not consult the queue, or if we're doing a first
allocation and check the queue.

13 months agoMEDIUM: stream: allocate without queuing when retrying
Willy Tarreau [Tue, 7 May 2024 15:54:03 +0000 (17:54 +0200)] 
MEDIUM: stream: allocate without queuing when retrying

Now when trying to allocate the work buffer, we can check if we've been
notified of availability via the buf_wait callback, in which case we
should not consult the queue, or if we're doing a first allocation and
check the queue.

13 months agoMINOR: mux-h1: report that a buffer allocation succeeded
Willy Tarreau [Tue, 7 May 2024 15:31:32 +0000 (17:31 +0200)] 
MINOR: mux-h1: report that a buffer allocation succeeded

When the buffer allocation callback is notified of a buffer availability,
it will now set a MAYALLOC flag in addition to clearing the ALLOC one, for
each of the 3 levels where we may fail an allocation. The flag will be
cleared upon a successful allocation. This will soon be used to decide to
re-allocate without waiting again in the queue. For now it has no effect.

There's just a trick, we need to clear the various *_ALLOC flags before
testing h1_recv_allowed() otherwise it will return false!

13 months agoMINOR: applet: report about buffer allocation success
Willy Tarreau [Tue, 7 May 2024 17:22:08 +0000 (19:22 +0200)] 
MINOR: applet: report about buffer allocation success

When appctx_buf_available() is called, it now sets APPCTX_FL_IN_MAYALLOC
or APPCTX_FL_OUT_MAYALLOC depending on the reportedly permitted buffer
allocation, and these flags are cleared when the said buffers are
allocated. For now they're not used for anything else.

13 months agoMINOR: stream: report that a buffer allocation succeeded
Willy Tarreau [Tue, 7 May 2024 15:45:31 +0000 (17:45 +0200)] 
MINOR: stream: report that a buffer allocation succeeded

When the buffer allocation callback is notified of a buffer availability,
it will now set a MAYALLOC flag on the stream so that the stream knows it
is allowed to bypass the queue checks. For now this is not used.

13 months agoMINOR: stconn: report that a buffer allocation succeeded
Willy Tarreau [Tue, 7 May 2024 15:11:14 +0000 (17:11 +0200)] 
MINOR: stconn: report that a buffer allocation succeeded

We used to have two states for the channel's input buffer used by the SC,
NEED_BUFF or not, flipped by sc_need_buff() and sc_have_buff(). We want to
have a 3rd state, indicating that we've just got a desired buffer. Let's
add an HAVE_BUFF flag that is set by sc_have_buff() and that is cleared by
sc_used_buff(). This way by looking at HAVE_BUFF we know that we're coming
back from the allocation callback and that the offered buffer has not yet
been used.

13 months agoMEDIUM: dynbuf: refrain from offering a buffer if more critical ones are waiting
Willy Tarreau [Wed, 24 Apr 2024 16:14:06 +0000 (18:14 +0200)] 
MEDIUM: dynbuf: refrain from offering a buffer if more critical ones are waiting

Now b_alloc() will check the queues at the same and higher criticality
levels before allocating a buffer, and will refrain from allocating one
if these are not empty. The purpose is to put some priorities in the
allocation order so that most critical allocators are offered a chance
to complete.

However in order to permit a freshly dequeued task to allocate again while
siblings are still in the queue, there is a special DB_F_NOQUEUE flag to
pass to b_alloc() that will take care of this special situation.

13 months agoMEDIUM: dynbuf/mux-h1: do not allocate the buffers in the callback
Willy Tarreau [Mon, 29 Apr 2024 07:20:17 +0000 (09:20 +0200)] 
MEDIUM: dynbuf/mux-h1: do not allocate the buffers in the callback

One of the problematic designs with the buffer_wait mechanism is that
the callbacks pre-allocate the buffers and stay in the run queue for
a while, resulting in all of the few buffers being assigned to waiting
tasks instead of being all available to one task that needs them all at
once.

Here we simply stop doing this, the callback clears the waiting flags
and wakes the task up so that it has a chance of still finding some
buffers.

13 months agoMINOR: dynbuf/mux-h1: use different criticalities for buffer allocations
Willy Tarreau [Mon, 29 Apr 2024 07:21:34 +0000 (09:21 +0200)] 
MINOR: dynbuf/mux-h1: use different criticalities for buffer allocations

While it could certainly still be improved, this first approach consists
in assigning buffers like this in the H1 mux:
  - h1c->obuf : DB_MUX_TX
  - h1c->ibuf : DB_MUX_RX
  - h1s->rxbuf: DB_SE_RX

That's done via 3 distinct functions for better code clarity, and it
also allowed to move the missing buffer flags assignment there.

Among possible improvements would be to take into consideration the
state of the parser (i.e. no data yet vs data, or headers vs payload)
so that even server beginning of response or pure payload can be lowered
in priority.

13 months agoMINOR: applet: adjust the allocation criticity based on the requested buffer
Willy Tarreau [Tue, 7 May 2024 18:09:04 +0000 (20:09 +0200)] 
MINOR: applet: adjust the allocation criticity based on the requested buffer

When we want to allocate an in buffer, it's in order to pass data to
the applet, that will consume it, so it must be seen as the same as
a send() from the higher level, i.e. MUX_TX. And for the outbuf, it's
a stream endpoint returning data, i.e. DB_SE_RX.

13 months agoMINOR: applet: set the blocking flag in the buffer allocation function
Willy Tarreau [Tue, 7 May 2024 17:16:20 +0000 (19:16 +0200)] 
MINOR: applet: set the blocking flag in the buffer allocation function

Instead of having each caller of appctx_get_buf() think about setting
the blocking flag, better have the function do it, since it's already
handling the queue anyway. This way we're sure that both are consistent.

13 months agoMEDIUM: applet: make appctx_buf_available() only wake the applet up, not allocate
Willy Tarreau [Tue, 30 Apr 2024 06:59:07 +0000 (08:59 +0200)] 
MEDIUM: applet: make appctx_buf_available() only wake the applet up, not allocate

Now we don't want bufwait handlers to preallocate the resources they
were expecting since it contributes to the shortage. Let's just wake
the applet up and that's all.

13 months agoMEDIUM: dynbuf/stream: do not allocate the buffers in the callback
Willy Tarreau [Mon, 29 Apr 2024 06:52:40 +0000 (08:52 +0200)] 
MEDIUM: dynbuf/stream: do not allocate the buffers in the callback

One of the problematic designs with the buffer_wait mechanism is that
the callbacks pre-allocate the buffers and stay in the run queue for
a while, resulting in all of the few buffers being assigned to waiting
tasks instead of being all available to one task that needs them all at
once.

Here we simply stop doing this, the callback clears the waiting flags
and wakes the task up so that it has a chance of still finding some
buffers.

13 months agoMEDIUM: dynbuf/stream: re-enable queueing upon failed buffer allocation
Willy Tarreau [Mon, 29 Apr 2024 06:52:40 +0000 (08:52 +0200)] 
MEDIUM: dynbuf/stream: re-enable queueing upon failed buffer allocation

The errors were not working fine anyway since we know that upon low memory
condition everything freezes. However we have a chance to do better now,
so let's start by re-enabling queueing when allocations fail.

13 months agoMEDIUM: dynbuf: generalize the use of b_dequeue() to detach buffer_wait
Willy Tarreau [Wed, 24 Apr 2024 16:44:03 +0000 (18:44 +0200)] 
MEDIUM: dynbuf: generalize the use of b_dequeue() to detach buffer_wait

Now thanks to this the bufq_map field is expected to remain accurate.

13 months agoMINOR: dynbuf: provide a b_dequeue() function to detach a bw from the queue
Willy Tarreau [Wed, 24 Apr 2024 16:31:14 +0000 (18:31 +0200)] 
MINOR: dynbuf: provide a b_dequeue() function to detach a bw from the queue

Now that we need to keep the bitmap in sync with the list heads, we don't
want tasks to leave just doing a LIST_DEL_INIT() without updating the map.
Let's provide a b_dequeue() function for that purpose. The function detects
when it's going to remove the last element and figures the queue number
based on the pointer since it points to the root. It's not used yet.

13 months agoCLEANUP: tinfo: better align fields in thread_ctx
Willy Tarreau [Tue, 30 Apr 2024 13:22:46 +0000 (15:22 +0200)] 
CLEANUP: tinfo: better align fields in thread_ctx

The introduction of buffer_wq[] in thread_ctx pushed a few fields around
and the cache line alignment is less satisfying. And more importantly, even
before this, all the lists in the local parts were 8-aligned, with the first
one split across two cache lines.

We can do better:
  - sched_profile_entry is not atomic at all, the data it points to is
    atomic so it doesn't need to be in the atomic-only region, and it can
    fill the 8-hole before the lists
  - the align(2*void) that was only before tasklets[] moves before all
    lists (and it's a nop for now)

This now makes the lists and buffer_wq[] start on a cache line boundary,
leaves 48 bytes after the lists before the atomic-only cache line, and
leaves a full cache line at the end for 128-alignment. This way we still
have plenty of room in both parts with better aligned fields.

13 months agoMEDIUM: dynbuf: make the buffer_wq an array of list heads
Willy Tarreau [Mon, 22 Apr 2024 16:39:06 +0000 (18:39 +0200)] 
MEDIUM: dynbuf: make the buffer_wq an array of list heads

Let's turn the buffer_wq into an array of 4 list heads. These are chosen
by criticality. The DB_CRIT_TO_QUEUE() macro maps each criticality level
into one of these 4 queues. The goal here clearly is to make it possible
to wake up the most critical queues in priority in order to let some tasks
finish their job and release buffers that others can use.

In order to avoid having to look up all queues, a bit map indicates which
queues are in use, which also allows to avoid looping in the most common
case where queues are empty..

13 months agoMINOR: dynbuf: use the b_queue()/b_requeue() functions everywhere
Willy Tarreau [Wed, 24 Apr 2024 15:02:23 +0000 (17:02 +0200)] 
MINOR: dynbuf: use the b_queue()/b_requeue() functions everywhere

The code places that were used to manipulate the buffer_wq manually
now just call b_queue() or b_requeue(). This will simplify the multiple
list management later.

13 months agoMINOR: dynbuf: add functions to help queue/requeue buffer_wait fields
Willy Tarreau [Tue, 23 Apr 2024 17:00:22 +0000 (19:00 +0200)] 
MINOR: dynbuf: add functions to help queue/requeue buffer_wait fields

When failing an allocation we always do the same dance, add the
buffer_wait struct to a list if it's not, and return. Let's just add
dedicated functions to centralize this, this will be useful to implement
a bit more complex logic.

For now they're not used.

13 months agoMINOR: dynbuf: pass a criticality argument to b_alloc()
Willy Tarreau [Tue, 16 Apr 2024 06:55:20 +0000 (08:55 +0200)] 
MINOR: dynbuf: pass a criticality argument to b_alloc()

The goal is to indicate how critical the allocation is, between the
least one (growing an existing buffer ring) and the topmost one (boot
time allocation for the life of the process).

The 3 tcp-based muxes (h1, h2, fcgi) use a common allocation function
to try to allocate otherwise subscribe. There's currently no distinction
of direction nor part that tries to allocate, and this should be revisited
to improve this situation, particularly when we consider that mux-h2 can
reduce its Tx allocations if needed.

For now, 4 main levels are planned, to translate how the data travels
inside haproxy from a producer to a consumer:
  - MUX_RX:   buffer used to receive data from the OS
  - SE_RX:    buffer used to place a transformation of the RX data for
              a mux, or to produce a response for an applet
  - CHANNEL:  the channel buffer for sync recv
  - MUX_TX:   buffer used to transfer data from the channel to the outside,
              generally a mux but there can be a few specificities (e.g.
              http client's response buffer passed to the application,
              which also gets a transformation of the channel data).

The other levels are a bit different in that they don't strictly need to
allocate for the first two ones, or they're permanent for the last one
(used by compression).

13 months agoDOC: lua: fix filters.txt file location
Aurelien DARRAGON [Fri, 10 May 2024 07:31:47 +0000 (09:31 +0200)] 
DOC: lua: fix filters.txt file location

At the beginning of the filter class section, we encourage the user to
check out filters.txt file to get to know how the filters API works
within haproxy.

However the file location is incorrect. The proper directory to look for
the file is: doc/internals/api.

It should be backported up to 2.5.

13 months agoBUG/MEDIUM: mux-quic: fix crash on STOP_SENDING received without SD
Amaury Denoyelle [Fri, 10 May 2024 08:42:07 +0000 (10:42 +0200)] 
BUG/MEDIUM: mux-quic: fix crash on STOP_SENDING received without SD

Abort reason code received on STOP_SENDING is notified to upper layer
since the following commit :
  367ce1ebf3e4cead319a9f01581037c9f0280e77
  MINOR: mux-quic: Set tha SE abort reason when a STOP_SENDING frame is received

However, this causes a crash when a STOP_SENDING is received on a QCS
instance without any stream instantiated. Fix this by checking first if
qcs->sd is not NULL before setting abort code.

This bug can easily be reproduced by emitting a STOP_SENDING as first
frame of a stream.

This should fix github issue #2563.

This does not need to be backported.

14 months agoBUG/MEDIUM: log/ring: broken syslog octet counting
Aurelien DARRAGON [Tue, 7 May 2024 14:46:35 +0000 (16:46 +0200)] 
BUG/MEDIUM: log/ring: broken syslog octet counting

As reported by Tristan in GH #2561, syslog messages sent over rings are
malformed since commit 01aa0a05 ("MEDIUM: ring: change the ring reader
to use the new vector-based API now").

Indeed, take a look at the following log message produced prior to
01aa0a05:

  181 <134>1 2024-05-07T09:45:21.543263+02:00 - haproxy 113700 - - 127.0.0.1:56136 [07/May/2024:09:45:21.491] front front/s1 0/0/21/30/51 404 369 - - ---- 1/1/0/0/0 0/0   "GET / HTTP/1.1"

Starting with 01aa0a05, here's the equivalent log message:

  <134>1 2024-05-07T09:45:21.543263+02:00 - haproxy 112729 - - 127.0.0.1:56136 [07/May/2024:09:45:21.491] front front/s1 0/0/66/39/105 404 369 - - ---- 1/1/0/0/0 0/0   "GET / HTTP/1.1"-fwr

-> Message is missing octet counting header, and garbage bytes are found
at the end of the payload.

This bug is caused by a small mistake in syslog_applet_append_event():
when the function was refactored to use vector API instead of buffer
API, we used 'trash.area' as starting pointer to write the event instead
of 'trash.area + trash.data', causing existing octet counting prefix
(already written in trash) to be overwritten and trash.data to be
wrongly incremented.

No backport needed (01aa0a05 was introduced during 3.0 development)

14 months agoMINOR: connection: Add samples to retrieve info on streams for a connection
Christopher Faulet [Tue, 30 Apr 2024 15:52:04 +0000 (17:52 +0200)] 
MINOR: connection: Add samples to retrieve info on streams for a connection

Thanks to the previous fix, it is now possible to get the number of opened
streams for a connection and the negociated limit. Here, corresponding
sample feches are added, in fc_ and bc_ scopes.

On frontend side, the limit of streams is imposed by HAProxy. But on the
backend side, the limit is defined by the server. it may be useful for
debugging purpose because it may explain slow-downs on some processing.

14 months agoMINOR: muxes: Add ctl commands to get info on streams for a connection
Christopher Faulet [Tue, 30 Apr 2024 14:18:07 +0000 (16:18 +0200)] 
MINOR: muxes: Add ctl commands to get info on streams for a connection

There are 2 new ctl commands that may be used to retrieve the current number
of streams openned for a connection and its limit (the maximum number of
streams a mux connection supports).

For the PT and H1 muxes, the limit is always 1 and the current number of
streams is 0 for idle connections, otherwise 1 is returned.

For the H2 and the FCGI muxes, info are already available in the mux
connection.

For the QUIC mux, the limit is also directly available. It is the maximum
initial sub-ID of bidirectional stream allowed for the connection. For the
current number of streams, it is the number of SC attached on the connection
and the number of not already attached streams present in the "opening_list"
list.