]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
3 months agoBUG/MINOR: dns: add tempo between 2 connection attempts for dns servers
Aurelien DARRAGON [Tue, 29 Apr 2025 18:13:00 +0000 (20:13 +0200)] 
BUG/MINOR: dns: add tempo between 2 connection attempts for dns servers

As reported by Lukas Tribus on the mailing list [1], trying to connect to
a nameserver with invalid network settings causes haproxy to retry a new
connection attempt immediately which eventually causes unexpected CPU usage
on the thread responsible for the applet (namely 100% on one CPU will be
observed).

This can be reproduced with the test config below:

 resolvers default
  nameserver ns1 tcp4@8.8.8.8:53 source 192.168.99.99
 listen listen
  mode http
  bind :8080
  server s1 www.google.com resolvers default init-addr none

To fix this the issue, we add a temporisation of one second between a new
connection attempt is retried. We do this in dns_session_create() when we
know that the applet was created in the release callback (when previous
query attempt was unsuccessful), which means initial connection is not
affected.

[1]: https://www.mail-archive.com/haproxy@formilux.org/msg45665.html

This should fix GH #2909 and may be backported to all stable versions.
This patch depends on ("MINOR: applet: add appctx_schedule() macro")

3 months agoMINOR: applet: add appctx_schedule() macro
Aurelien DARRAGON [Mon, 28 Apr 2025 16:03:36 +0000 (18:03 +0200)] 
MINOR: applet: add appctx_schedule() macro

Just like task_schedule() but for applets to wakeup an applet at a
specific time, leverages _task_schedule() internally

3 months agoBUG/MINOR: acme: remove references to virt@acme
William Lallemand [Tue, 29 Apr 2025 14:35:35 +0000 (16:35 +0200)] 
BUG/MINOR: acme: remove references to virt@acme

"virt@acme" was the default map used during development, now this must
be configured in the acme section or it won't try to use any map.

This patch removes the references to virt@acme in the comments and the
code.

3 months agoMEDIUM: acme: use a map to store tokens and thumbprints
William Lallemand [Tue, 29 Apr 2025 14:08:31 +0000 (16:08 +0200)] 
MEDIUM: acme: use a map to store tokens and thumbprints

The stateless mode which was documented previously in the ACME example
is not convenient for all use cases.

First, when HAProxy generates the account key itself, you wouldn't be
able to put the thumbprint in the configuration, so you will have to get
the thumbprint and then reload.
Second, in the case you are using multiple account key, there are
multiple thumbprint, and it's not easy to know which one you want to use
when responding to the challenger.

This patch allows to configure a map in the acme section, which will be
filled by the acme task with the token corresponding to the challenge,
as the key, and the thumbprint as the value. This way it's easy to reply
the right thumbprint.

Example:
    http-request return status 200 content-type text/plain lf-string "%[path,field(-1,/)].%[path,field(-1,/),map(virt@acme)]\n" if { path_beg '/.well-known/acme-challenge/' }

3 months agoMEDIUM: quic: limit global Tx memory
Amaury Denoyelle [Tue, 29 Apr 2025 09:39:42 +0000 (11:39 +0200)] 
MEDIUM: quic: limit global Tx memory

Define a new settings tune.quic.frontend.max-tot-window. It contains a
size argument which can be used to set a limit on the sum of all QUIC
connections congestion window. This is applied both on
quic_cc_path_set() and quic_cc_path_inc().

Note that this limitation cannot reduce a congestion window more than
the minimal limit which is set to 2 datagrams.

3 months agoMINOR: quic: account for global congestion window
Amaury Denoyelle [Mon, 28 Apr 2025 06:52:43 +0000 (08:52 +0200)] 
MINOR: quic: account for global congestion window

Use the newly defined cshared type to account for the sum of congestion
window of every QUIC connection. This value is stored in global counter
quic_mem_global defined in proto_quic module.

3 months agoMINOR: thread: define cshared type
Amaury Denoyelle [Fri, 25 Apr 2025 09:37:07 +0000 (11:37 +0200)] 
MINOR: thread: define cshared type

Define a new type "struct cshared". This can be used as a tool to
manipulate a global counter with thread-safety ensured. Each thread
would declare its thread-local cshared type, which would point to a
global counter.

Each thread can then add/substract value to their owned thread-local
cshared instance via cshared_add(). If the difference exceed a
configured limit, either positively or negatively, the global counter is
updated and thread-local instance is reset to 0. Each thread can safely
read the global counter value using cshared_read().

3 months agoBUG/MINOR: quic: ensure cwnd limits are always enforced
Amaury Denoyelle [Mon, 20 Jan 2025 15:24:21 +0000 (16:24 +0100)] 
BUG/MINOR: quic: ensure cwnd limits are always enforced

Congestion window is limit by a minimal and maximum values which can
never be exceeded. Min value is hardcoded to 2 datagrams as recommended
by the specification. Max value is specified via haproxy configuration.

These values must be respected each time the congestion window size is
adjusted. However, in some rare occasions, limit were not always
enforced. Fix this by implementing wrappers to set or increment the
congestion window. These functions ensure limits are always applied
after the operation.

Additionnally, wrappers also ensure that if window reached a new maximum
value, it is saved in <cwnd_last_max> field.

This should be backported up to 2.6, after a brief period of
observation.

3 months agoMINOR: quic: refactor BBR API
Amaury Denoyelle [Mon, 28 Apr 2025 07:22:37 +0000 (09:22 +0200)] 
MINOR: quic: refactor BBR API

Write minor adjustments to QUIC BBR functions. The objective is to
centralize every modification of path cwnd field.

No functional change. This patch will be useful to simplify
implementation of global QUIC Tx memory usage limitation.

3 months agoMINOR: quic: rename min/max fields for congestion window algo
Amaury Denoyelle [Thu, 23 Jan 2025 09:47:57 +0000 (10:47 +0100)] 
MINOR: quic: rename min/max fields for congestion window algo

There was some possible confusion between fields related to congestion
window size min and max limit which cannot be exceeded, and the maximum
value previously reached by the window.

Fix this by adopting a new naming scheme. Enforced limit are now renamed
<limit_max>/<limit_min>, while the previously reached max value is
renamed <cwnd_last_max>.

This should be backported up to 3.1.

3 months agoBUG/MINOR: acme: creating an account should not end the task
William Lallemand [Tue, 29 Apr 2025 12:09:46 +0000 (14:09 +0200)] 
BUG/MINOR: acme: creating an account should not end the task

The account creation was mistakenly ending the task instead of being
wakeup for the NewOrder state, it was preventing the creation of the
certificate, however the account was correctly created.

To fix this, only the jump to the end label need to be remove, the
standard leaving codepath of the function will allow to be wakeup.

No backport needed.

3 months agoMINOR: tcp: add support for setting TCP_NOTSENT_LOWAT on both sides
Willy Tarreau [Tue, 29 Apr 2025 09:43:46 +0000 (11:43 +0200)] 
MINOR: tcp: add support for setting TCP_NOTSENT_LOWAT on both sides

TCP_NOTSENT_LOWAT is very convenient as it indicates when to report
EAGAIN on the sending side. It takes a margin on top of the estimated
window, meaning that it's no longer needed to store too many data in
socket buffers. Instead there's just enough to fill the send window
and a little bit of margin to cover the scheduling time to restart
sending. Experiments on a 100ms network have shown a 10-fold reduction
in the memory used by socket buffers by just setting this value to
tune.bufsize, without noticing any performance degradation. Theoretically
the responsiveness on multiplexed protocols such as H2 should also be
improved.

3 months agoBUG/MINOR: mux-h2: fix the offset of the pattern for the ping frame
Willy Tarreau [Tue, 29 Apr 2025 10:05:08 +0000 (12:05 +0200)] 
BUG/MINOR: mux-h2: fix the offset of the pattern for the ping frame

The ping frame's pattern must be written at offset 9 (frame header
length), not 8. This was added in 3.2 with commit 4dcfe098a6 ("MINOR:
mux-h2: prepare to support PING emission"), so no backport is needed.

3 months agoBUG/MINOR: acme: does not try to unlock after a failed trylock
William Lallemand [Tue, 29 Apr 2025 09:29:52 +0000 (11:29 +0200)] 
BUG/MINOR: acme: does not try to unlock after a failed trylock

Return after a failed trylock in acme_update_certificate() instead of
jumping to the error label which does an unlock.

3 months agoDOC: configuration: add quic4 to the ssl-f-use example
William Lallemand [Tue, 29 Apr 2025 08:50:39 +0000 (10:50 +0200)] 
DOC: configuration: add quic4 to the ssl-f-use example

The ssl-f-use keyword is very useful in the case of multiple SSL bind
lines. Add a quic4 bind line in the example to show that.

3 months agoCLEANUP: acme: remove old TODO for account key
William Lallemand [Tue, 29 Apr 2025 07:59:32 +0000 (09:59 +0200)] 
CLEANUP: acme: remove old TODO for account key

Remove old TODO comments about the account key.

3 months agoDOC: configuration: acme account key are auto generated
William Lallemand [Tue, 29 Apr 2025 07:27:45 +0000 (09:27 +0200)] 
DOC: configuration: acme account key are auto generated

Explain that account key are auto generated when they do not exist.

3 months agoMEDIUM: mcli: replicate the current mode when enterin the worker process
Willy Tarreau [Mon, 28 Apr 2025 17:09:02 +0000 (19:09 +0200)] 
MEDIUM: mcli: replicate the current mode when enterin the worker process

While humans can find it convenient to enter the worker process in prompt
mode, for external tools it will not be convenient to have to systematically
disable it. A better approach is to replicate the master socket's mode
there, since it has already been configured to suit the user: interactive,
prompt and timed modes are automatically passed to the worker process.
This makes the using the worker commands more natural from the master
process, without having to systematically adapt it for each new connection.

3 months agoMEDIUM: mcli: make the prompt mode configurable between i/p
Willy Tarreau [Mon, 28 Apr 2025 16:51:47 +0000 (18:51 +0200)] 
MEDIUM: mcli: make the prompt mode configurable between i/p

Support the same syntax in master mode as in worker mode in order to
configure the prompt. The only thing is that for now the master doesn't
have a non-interactive mode and it doesn't seem necessary to implement
it, so we only support the interactive and prompt modes. However the code
was written in a way that makes it easy to change this later if desired.

3 months agoMEDIUM: cli: make the prompt mode configurable between n/i/p
Willy Tarreau [Mon, 28 Apr 2025 16:36:57 +0000 (18:36 +0200)] 
MEDIUM: cli: make the prompt mode configurable between n/i/p

Now the prompt mode can more finely be configured between non-interactive
(default), interactive without prompt, and interactive with prompt. This
will ease the usage from automated tools which are not necessarily
interested in having to consume '> ' after each command nor displaying
"+" on payload lines. This can also be convenient when coming from the
master CLI to keep the same output format.

3 months agoMINOR: cli: split APPCTX_CLI_ST1_PROMPT into two distinct flags
Willy Tarreau [Mon, 28 Apr 2025 15:42:03 +0000 (17:42 +0200)] 
MINOR: cli: split APPCTX_CLI_ST1_PROMPT into two distinct flags

The CLI's "prompt" command toggles two distinct things:
  - displaying or hiding the prompt at the beginning of the line
  - single-command vs interactive mode

These are two independent concepts and the prompt mode doesn't
always cope well with tools that would like to upload data without
having to read the prompt on return. Also, the master command line
works in interactive mode by default with no prompt, which is not
consistent (and not convenient for tools). So let's start by splitting
the bit in two, and have a new APPCTX_CLI_ST1_INTER flag dedicated
to the interactive mode. For now the "prompt" command alone continues
to toggle the two at once.

3 months agoMINOR: compiler: add more macros to detect macro definitions
Willy Tarreau [Mon, 28 Apr 2025 06:56:56 +0000 (08:56 +0200)] 
MINOR: compiler: add more macros to detect macro definitions

We add __equals_0(NAME) which is only true if NAME is defined as zero,
and __def_as_empty(NAME) which is only true if NAME is defined as an
empty string.

3 months agoMEDIUM: acme: use 'crt-base' to load the account key
William Lallemand [Mon, 28 Apr 2025 15:52:28 +0000 (17:52 +0200)] 
MEDIUM: acme: use 'crt-base' to load the account key

Prefix the filename with the 'crt-base' before loading the account key,
in order to work like every other keypair in haproxy.

3 months agoMEDIUM: acme: generate the account file when not found
William Lallemand [Mon, 28 Apr 2025 15:40:26 +0000 (17:40 +0200)] 
MEDIUM: acme: generate the account file when not found

Generate the private key on the account file when the file does not
exists. This generate a private key of the type and parameters
configured in the acme section.

3 months agoMINOR: acme: failure when no directory is specified
William Lallemand [Mon, 28 Apr 2025 15:37:21 +0000 (17:37 +0200)] 
MINOR: acme: failure when no directory is specified

The "directory" parameter of the acme section is mandatory. This patch
exits with an alert when this parameter is not found.

3 months agoMINOR: acme: separate the code generating private keys
William Lallemand [Mon, 28 Apr 2025 14:27:45 +0000 (16:27 +0200)] 
MINOR: acme: separate the code generating private keys

acme_EVP_PKEY_gen() generates private keys of specified <keytype>,
<curves> and <bits>. Only RSA and EC are supported for now.

3 months agoBUG/MINOR: ssl/acme: free EVP_PKEY upon error
William Lallemand [Mon, 28 Apr 2025 14:33:48 +0000 (16:33 +0200)] 
BUG/MINOR: ssl/acme: free EVP_PKEY upon error

Free the EPV_PKEY upon error when the X509_REQ generation failed.

No backport needed.

3 months agoMEDIUM: thread: set DEBUG_THREAD to 1 by default
Willy Tarreau [Mon, 28 Apr 2025 13:57:26 +0000 (15:57 +0200)] 
MEDIUM: thread: set DEBUG_THREAD to 1 by default

Setting DEBUG_THREAD to 1 allows recording the lock history for each
thread. Tests have shown that (as predicted) the cost of updating a
single thread-local variable is not perceptible in the noise, especially
when compared to the cost of obtaining a lock. Since this can provide
useful value when debugging deadlocks, let's enable it by default when
threads are enabled.

3 months agoMINOR: threads/cli: display the lock history on "show threads"
Willy Tarreau [Mon, 28 Apr 2025 13:19:35 +0000 (15:19 +0200)] 
MINOR: threads/cli: display the lock history on "show threads"

This will display the lock labels and modes for each non-empty step
at the end of "show threads" when these are defined. This allows to
emit up to the last 8 locking operation for each thread on 64 bit
machines.

3 months agoMEDIUM: threads: keep history of taken locks with DEBUG_THREAD > 0
Willy Tarreau [Mon, 28 Apr 2025 07:42:58 +0000 (09:42 +0200)] 
MEDIUM: threads: keep history of taken locks with DEBUG_THREAD > 0

by only storing a word in each thread context, we can keep the history
of all taken/dropped locks by label. This is expected to be very cheap
and to permit to store up to 8 consecutive lock operations in 64 bits.
That should significantly help detect recursive locks as well as figure
what thread was likely to hinder another one waiting for a lock.

For now we only store the final state of the lock, we don't store the
attempt to get it. It's just a matter of space since we already need
4 ops (rd,sk,wr,un) which take 2 bits, leaving max 64 labels. We're
already around 45. We could also multiply by 5 and still keep 8 bits
total per lock, that would limit us to 51 locks max. It seems that
most of the time if we get a watchdog panic, anyway the victim thread
will be perfectly located so that we don't need a specific value for
this. Another benefit is that we perform a single memory write per
lock.

3 months agoMINOR: threads: turn the full lock debugging to DEBUG_THREAD=2
Willy Tarreau [Mon, 28 Apr 2025 07:05:02 +0000 (09:05 +0200)] 
MINOR: threads: turn the full lock debugging to DEBUG_THREAD=2

At level 1 it now does nothing. This is reserved for some subsequent
patches which will implement lighter debugging.

3 months agoMINOR: threads: prepare DEBUG_THREAD to receive more values
Willy Tarreau [Mon, 28 Apr 2025 07:00:00 +0000 (09:00 +0200)] 
MINOR: threads: prepare DEBUG_THREAD to receive more values

We now default the value to zero and make sure all tests properly take
care of values above zero. This is in preparation for supporting several
degrees of debugging.

3 months agoBUILD: leastconn: fix build warning when building without threads on old machines
Willy Tarreau [Mon, 28 Apr 2025 14:48:42 +0000 (16:48 +0200)] 
BUILD: leastconn: fix build warning when building without threads on old machines

Machines lacking CAS8B/DWCAS and emit a warning in lb_fwlc.c without
threads due to declaration ordering. Let's just move the variable
declaration into the block that uses it as a last variable. No
backport is needed.

3 months agoBUILD: acme: use my_strndup() instead of strndup()
Willy Tarreau [Mon, 28 Apr 2025 14:35:24 +0000 (16:35 +0200)] 
BUILD: acme: use my_strndup() instead of strndup()

Not all systems have strndup(), that's why we have our "my_strndup()",
so let's make use of it here. This fixes the build on Solaris 10. No
backport is needed.

3 months agoMINOR: promex: expose ST_I_PX_RATE (current_session_rate)
Aurelien DARRAGON [Mon, 28 Apr 2025 10:19:36 +0000 (12:19 +0200)] 
MINOR: promex: expose ST_I_PX_RATE (current_session_rate)

It has been requested to have the current_session_rate exposed at the
frontend level. For now only the per-process value was exposed
(ST_I_INF_SESS_RATE).

Thanks to the work done lately to merge promex and stat_cols_px[]
array, let's simply defined an .alt_name for the ST_I_PX_RATE metric in
order to have promex exposing it as current_session_rate for relevant
contexts.

3 months agoDOC: config: clarify log-forward "host" option
Aurelien DARRAGON [Mon, 28 Apr 2025 10:09:45 +0000 (12:09 +0200)] 
DOC: config: clarify log-forward "host" option

log-forward "host" option may be confusing because we often mention the
host field when talking about syslog RFC3164 or RFC5424 messages, but
neither rfc actually define "host" field. In fact, everywhere we used
"host field" we actually meant "hostname field" as documented in RFC5424.
This was a language abuse on our side.

In this patch we replace "host" with "hostname" where relevant in the
documentation to prevent confusion.

Thanks to Nick Ramirez for having reported the issue.

3 months agoDOC: config: fix ACME paragraph rendering issue
Aurelien DARRAGON [Mon, 28 Apr 2025 09:30:01 +0000 (11:30 +0200)] 
DOC: config: fix ACME paragraph rendering issue

Nick Ramirez reported that the ACME paragraph (3.13) caused a rendering
issue where simple text was rendered as a directive. This was caused
by the use of unescaped <name> which confuses dconv.

Let's escape <name> by putting quotes around it to prevent the rendering
issue.

No backport needed.

3 months agoMINOR: ssl/cli: add a '-t' option to 'show ssl sni'
William Lallemand [Mon, 28 Apr 2025 09:35:11 +0000 (11:35 +0200)] 
MINOR: ssl/cli: add a '-t' option to 'show ssl sni'

Add a -t option to 'show ssl sni', allowing to add an offset to the
current date so it would allow to check which certificates are expired
after a certain period of time.

3 months agoBUG/MAJOR: listeners: transfer connection accounting when switching listeners
Willy Tarreau [Fri, 25 Apr 2025 16:32:02 +0000 (18:32 +0200)] 
BUG/MAJOR: listeners: transfer connection accounting when switching listeners

Since we made it possible for a bind_conf to listen to multiple thread
groups with shards in 2.8 with commit 9d360604bd ("MEDIUM: listener:
rework thread assignment to consider all groups"), the per-listener
connection count was not properly transferred to the target listener
with the connection when switching to another thread group. This results
in one listener possibly reaching high values and another one possibly
reaching negative values. Usually it's not visible, unless a maxconn is
set on the bind_conf, in which case comparisons will quickly put an end
to the willingness to accept new connections.

This problem only happens when thread groups are enabled, and it seems
very hard to trigger it normally, it only impacts sockets having a single
shard, hence currently the CLI (or any conf with "bind ... shards 1"),
where it can be reproduced with a config having a very low "maxconn" on
the stats socket directive (here, 4), and issuing a few tens of
socat <<< "show activity" in parallel, or sending HTTP connections to a
single-shared listener. Very quickly, haproxy stops accepting connections
and eats CPU in the poller which tries to get its connections accepted.

A BUG_ON(l->nbconn<0) after HA_ATOMIC_DEC() in listener_release() also
helps spotting them better.

Many thanks to Christian Ruppert who once again provided a very accurate
report in GH #2951 with the required data permitting this analysis.

This fix must be backported to 2.8.

3 months agoBUG/MAJOR: tasklets: Make sure he tasklet can't run twice
Olivier Houchard [Fri, 25 Apr 2025 10:17:07 +0000 (12:17 +0200)] 
BUG/MAJOR: tasklets: Make sure he tasklet can't run twice

tasklets were originally designed to alway run on only one thread, so it
was not possible to have it run on 2 threads concurrently.
The API has been extended so that another thread may wake the tasklet,
the idea was still that we wanted to have it run on one thread only.
However, the way it's been done meant that unless a tasklet was bound to
a specific tid with tasklet_set_tid(), or we explicitely used
tasklet_wakeup_on() to specify the thread for the target to run on, it
would be scheduled to run on the current thread.
This is in fact a desirable feature. There is however a race condition
in which the tasklet would be scheduled on a thread, while it is running
on another. This could lead to the same tasklet to run on multiple
threads, which we do not want.
To fix this, just do what we already do for regular tasks, set the
"TASK_RUNNING" flag, and when it's time to execute the tasklet, wait
until that flag is gone.
Only one case has been found in the current code, where the tasklet
could run on different threads depending on who wakes it up, in the
leastconn load balancer, since commit
627280e15f03755b8f59f0191cd6d6bcad5afeb3.
It should not be a problem in practice, as the function called can be
called concurrently.
If a bug is eventually found in relation to this problem, and this patch
should be backported, the following patches should be backported too :
MEDIUM: quic: Make sure we return the tasklet from quic_accept_run
MEDIUM: quic: Make sure we return NULL in quic_conn_app_io_cb if needed
MEDIUM: quic: Make sure we return the tasklet from qcc_io_cb
MEDIUM: mux_fcgi: Make sure we return the tasklet from fcgi_deferred_shut
MEDIUM: listener: Make sure w ereturn the tasklet from accept_queue_process
MEDIUM: checks: Make sure we return the tasklet from srv_chk_io_cb

3 months agoMEDIUM: quic: Make sure we return the tasklet from quic_accept_run
Olivier Houchard [Fri, 25 Apr 2025 11:03:29 +0000 (13:03 +0200)] 
MEDIUM: quic: Make sure we return the tasklet from quic_accept_run

In quic_accept_run, return the tasklet to tell the scheduler the tasklet
is still alive, it is not yet needed, but will be soon.

3 months agoMEDIUM: quic: Make sure we return NULL in quic_conn_app_io_cb if needed
Olivier Houchard [Fri, 25 Apr 2025 11:02:47 +0000 (13:02 +0200)] 
MEDIUM: quic: Make sure we return NULL in quic_conn_app_io_cb if needed

In quic_conn_app_io_cb, make sure we return NULL if the tasklet has been
destroyed, so that the scheduler knows. It is not yet needed, but will
be soon.

3 months agoMEDIUM: quic: Make sure we return the tasklet from qcc_io_cb
Olivier Houchard [Fri, 25 Apr 2025 11:01:58 +0000 (13:01 +0200)] 
MEDIUM: quic: Make sure we return the tasklet from qcc_io_cb

In qcc_io_cb, return the tasklet to tell the scheduler the tasklet is
still alive, it is not yet needed, but will be soon.

3 months agoMEDIUM: mux_fcgi: Make sure we return the tasklet from fcgi_deferred_shut
Olivier Houchard [Fri, 25 Apr 2025 11:01:15 +0000 (13:01 +0200)] 
MEDIUM: mux_fcgi: Make sure we return the tasklet from fcgi_deferred_shut

In fcgi_deferred_shut, return the tasklet to tell the scheduler the
tasklet is still alive, it is not yet needed, but will be soon.

3 months agoMEDIUM: listener: Make sure w ereturn the tasklet from accept_queue_process
Olivier Houchard [Fri, 25 Apr 2025 11:00:34 +0000 (13:00 +0200)] 
MEDIUM: listener: Make sure w ereturn the tasklet from accept_queue_process

In accept_queue_process, return the tasklet to tell the scheduler the
tasklet is still alive, it is not yet needed, but will be soon.

3 months agoMEDIUM: checks: Make sure we return the tasklet from srv_chk_io_cb
Olivier Houchard [Fri, 25 Apr 2025 10:59:37 +0000 (12:59 +0200)] 
MEDIUM: checks: Make sure we return the tasklet from srv_chk_io_cb

In srv_chk_io_cb, return the tasklet to tell the scheduler the tasklet
is still alive, it is not yet needed, but will be soon.

3 months ago[RELEASE] Released version 3.2-dev12 v3.2-dev12
Willy Tarreau [Fri, 25 Apr 2025 08:19:03 +0000 (10:19 +0200)] 
[RELEASE] Released version 3.2-dev12

Released version 3.2-dev12 with the following main changes :
    - BUG/MINOR: quic: do not crash on CRYPTO ncbuf alloc failure
    - BUG/MINOR: proxy: always detach a proxy from the names tree on free()
    - CLEANUP: proxy: detach the name node in proxy_free_common() instead
    - CLEANUP: Slightly reorder some proxy option flags to free slots
    - MINOR: proxy: Add options to drop HTTP trailers during message forwarding
    - MINOR: h1-htx: Skip C-L and T-E headers for 1xx and 204 messages during parsing
    - MINOR: mux-h1: Keep custom "Content-Length: 0" header in 1xx and 204 messages
    - MINOR: hlua/h1: Use http_parse_cont_len_header() to parse content-length value
    - CLEANUP: h1: Remove now useless h1_parse_cont_len_header() function
    - BUG/MEDIUM: mux-spop: Respect the negociated max-frame-size value to send frames
    - MINOR: http-act: Add 'pause' action to temporarily suspend the message analysis
    - MINOR: acme/cli: add the 'acme renew' command to the help message
    - MINOR: httpclient: add an "https" log-format
    - MEDIUM: acme: use a customized proxy
    - MEDIUM: acme: rename "uri" into "directory"
    - MEDIUM: acme: rename "account" into "account-key"
    - MINOR: stick-table: use a separate lock label for updates
    - MINOR: h3: simplify h3_rcv_buf return path
    - BUG/MINOR: mux-quic: fix possible infinite loop during decoding
    - BUG/MINOR: mux-quic: do not decode if conn in error
    - BUG/MINOR: cli: Issue an error when too many args are passed for a command
    - MINOR: cli: Use a full prompt command for bidir connections with workers
    - MAJOR: cli: Refacor parsing and execution of pipelined commands
    - MINOR: cli: Rename some CLI applet states to reflect recent refactoring
    - CLEANUP: applet: Update st0/st1 comment in appctx structure
    - BUG/MINOR: hlua: Fix I/O handler of lua CLI commands to not rely on the SC
    - BUG/MINOR: ring: Fix I/O handler of "show event" command to not rely on the SC
    - MINOR: cli/applet: Move appctx fields only used by the CLI in a private context
    - MINOR: cache: Add a pointer on the cache in the cache applet context
    - MINOR: hlua: Use the applet name in error messages for lua services
    - MINOR: applet: Save the "use-service" rule in the stream to init a service applet
    - CLEANUP: applet: Remove unsued rule pointer in appctx structure
    - BUG/MINOR: master/cli: properly trim the '@@' process name in error messages
    - MEDIUM: resolvers: add global "dns-accept-family" directive
    - MINOR: resolvers: add command-line argument -4 to force IPv4-only DNS
    - MINOR: sock-inet: detect apparent IPv6 connectivity
    - MINOR: resolvers: add "dns-accept-family auto" to rely on detected IPv6
    - MEDIUM: acme: use Retry-After value for retries
    - MEDIUM: acme: reset the remaining retries
    - MEDIUM: acme: better error/retry management of the challenge checks
    - BUG/MEDIUM: cli: Handle applet shutdown when waiting for a command line
    - Revert "BUG/MINOR: master/cli: properly trim the '@@' process name in error messages"
    - BUG/MINOR: master/cli: only parse the '@@' prefix on complete lines
    - MINOR: resolvers: use the runtime IPv6 status instead of boot time one

3 months agoMINOR: resolvers: use the runtime IPv6 status instead of boot time one
Willy Tarreau [Fri, 25 Apr 2025 07:26:44 +0000 (09:26 +0200)] 
MINOR: resolvers: use the runtime IPv6 status instead of boot time one

On systems where the network is not reachable at boot time (certain HA
systems for example, or dynamically addressed test machines), we'll want
to be able to periodically revalidate the IPv6 reachability status. The
current code makes it complicated because it sets the config bits once
for all at boot time. This commit changes this so that the config bits
are not changed, but instead we rely on a static inline function that
relies on sock_inet6_seems_reachable for every test (really cheap). This
also removes the now unneeded resolvers late init code.

This variable for now is still set at boot time but this will ease the
transition later, as the resolvers code is now ready for this.

3 months agoBUG/MINOR: master/cli: only parse the '@@' prefix on complete lines
Willy Tarreau [Fri, 25 Apr 2025 06:40:57 +0000 (08:40 +0200)] 
BUG/MINOR: master/cli: only parse the '@@' prefix on complete lines

The new adhoc parser for the '@@' prefix forgot to require the presence
of the LF character marking the end of the line. This is the reason why
entering incomplete commands would display garbage, because the line was
expected to have its LF character replaced with a zero.

The problem is well illustrated by using socat in raw mode:

   socat /tmp/master.sock STDIO,raw,echo=0

then entering "@@1 show info" one character at a time would error just
after the second "@". The command must take care to report an incomplete
line and wait for more data in such a case.

3 months agoRevert "BUG/MINOR: master/cli: properly trim the '@@' process name in error messages"
Willy Tarreau [Fri, 25 Apr 2025 06:43:48 +0000 (08:43 +0200)] 
Revert "BUG/MINOR: master/cli: properly trim the '@@' process name in error messages"

This reverts commit 0e94339eaf1c8423132debb6b1b485d8bb1bb7da.

This patch was in fact fixing the symptom, not the cause. The root cause
of the problem is that the parser was processing an incomplete line when
looking for '@@'. When the LF is present, this problem does not exist
as it's properly replaced with a zero. This can be verified using socat
in raw mode:

  socat /tmp/master.sock STDIO,raw,echo=0

Then entering "@@1 show info" one character at a time will immediately
fail on "@@" without going further. A subsequent patch will fix this.
No backport is needed.

3 months agoBUG/MEDIUM: cli: Handle applet shutdown when waiting for a command line
Christopher Faulet [Thu, 24 Apr 2025 16:54:32 +0000 (18:54 +0200)] 
BUG/MEDIUM: cli: Handle applet shutdown when waiting for a command line

When the CLI applet was refactord in the commit 20ec1de21 ("MAJOR: cli:
Refacor parsing and execution of pipelined commands"), a regression was
introduced. The applet shutdown was not longer handled when the applet was
waiting for the next command line. It is especially visible when a client
timeout occurred because the client connexion is no longer closed.

To fix the issue, the test on the SE_FL_SHW flag was reintroduced in
CLI_ST_PARSE_CMDLINE state, but only is there is no pending input data.

It is a 3.2-specific issue. No backport needed.

3 months agoMEDIUM: acme: better error/retry management of the challenge checks
William Lallemand [Thu, 24 Apr 2025 17:58:56 +0000 (19:58 +0200)] 
MEDIUM: acme: better error/retry management of the challenge checks

When the ACME task is checking for the status of the challenge, it would
only succeed or retry upon failure.

However that's not the best way to do it, ACME objects contain an
"status" field which could have a final status or a in progress status,
so we need to be able to retry.

This patch adds an acme_ret enum which contains OK, RETRY and FAIL.

In the case of the CHKCHALLENGE, the ACME could return a "pending" or a
"processing" status, which basically need to be rechecked later with the
RETRY. However a "invalid" or "valid" status is final and will return
either a FAIL or a OK.

So instead of retrying in any case, the "invalid" status will ends the
task with an error.

3 months agoMEDIUM: acme: reset the remaining retries
William Lallemand [Thu, 24 Apr 2025 15:50:29 +0000 (17:50 +0200)] 
MEDIUM: acme: reset the remaining retries

When a request succeed, reset the remaining retries to the default
ACME_RETRY value (3 by default).

3 months agoMEDIUM: acme: use Retry-After value for retries
William Lallemand [Thu, 24 Apr 2025 15:31:51 +0000 (17:31 +0200)] 
MEDIUM: acme: use Retry-After value for retries

Parse the Retry-After header in response and store it in order to use
the value as the next delay for the next retry, fallback to 3s if the
value couldn't be parse or does not exist.

3 months agoMINOR: resolvers: add "dns-accept-family auto" to rely on detected IPv6
Willy Tarreau [Thu, 24 Apr 2025 15:18:06 +0000 (17:18 +0200)] 
MINOR: resolvers: add "dns-accept-family auto" to rely on detected IPv6

Instead of always having to force IPv4 or IPv6, let's now also offer
"auto" which will only enable IPv6 if the system has a default gateway
for it. This means that properly configured dual-stack systems will
default to "ipv4,ipv6" while those lacking a gateway will only use
"ipv4". Note that no real connectivity test is performed, so firewalled
systems may still get it wrong and might prefer to rely on a manual
"ipv4" assignment.

3 months agoMINOR: sock-inet: detect apparent IPv6 connectivity
Willy Tarreau [Thu, 24 Apr 2025 15:05:14 +0000 (17:05 +0200)] 
MINOR: sock-inet: detect apparent IPv6 connectivity

In order to ease dual-stack deployments, we could at least try to
check if ipv6 seems to be reachable. For this we're adding a test
based on a UDP connect (no traffic) on port 53 to the base of
public addresses (2001::) and see if the connect() is permitted,
indicating that the routing table knows how to reach it, or fails.
Based on this result we're setting a global variable that other
subsystems might use to preset their defaults.

3 months agoMINOR: resolvers: add command-line argument -4 to force IPv4-only DNS
Willy Tarreau [Thu, 24 Apr 2025 14:31:47 +0000 (16:31 +0200)] 
MINOR: resolvers: add command-line argument -4 to force IPv4-only DNS

In order to ease troubleshooting and testing, the new "-4" command line
argument enforces queries and processing of "A" DNS records only, i.e.
those representing IPv4 addresses. This can be useful when a host lack
end-to-end dual-stack connectivity. This overrides the global
"dns-accept-family" directive and is equivalent to value "ipv4".

3 months agoMEDIUM: resolvers: add global "dns-accept-family" directive
Willy Tarreau [Thu, 24 Apr 2025 14:29:11 +0000 (16:29 +0200)] 
MEDIUM: resolvers: add global "dns-accept-family" directive

By default, DNS resolvers accept both IPv4 and IPv6 addresses. This can be
influenced by the "resolve-prefer" keywords on server lines as well as the
family argument to the "do-resolve" action, but that is only a preference,
which does not block the other family from being used when it's alone. In
some environments where dual-stack is not usable, stumbling on an unreachable
IPv6-only DNS record can cause significant trouble as it will replace a
previous IPv4 one which would possibly have continued to work till next
request. The "dns-accept-family" global option permits to enforce usage of
only one (or both) address families. The argument is a comma-delimited list
of the following words:
  - "ipv4": query and accept IPv4 addresses ("A" records)
  - "ipv6": query and accept IPv6 addresses ("AAAA" records)

When a single family is used, no request will be sent to resolvers for the
other family, and any response for the othe family will be ignored. The
default value is "ipv4,ipv6", which effectively enables both families.

3 months agoBUG/MINOR: master/cli: properly trim the '@@' process name in error messages
Willy Tarreau [Thu, 24 Apr 2025 15:47:23 +0000 (17:47 +0200)] 
BUG/MINOR: master/cli: properly trim the '@@' process name in error messages

When '@@' alone is sent on the master CLI (no trailing LF), we get an
error that displays anything past these two characters in the buffer
since there's no room for a \0. Let's make sure to limit the length of
the process name in this case. No backport is needed since this was added
with 00c967fac4 ("MINOR: master/cli: support bidirectional communications
with workers").

3 months agoCLEANUP: applet: Remove unsued rule pointer in appctx structure
Christopher Faulet [Thu, 24 Apr 2025 14:19:11 +0000 (16:19 +0200)] 
CLEANUP: applet: Remove unsued rule pointer in appctx structure

Thanks to previous commits, the "rule" field in the appctx structure is no
longer used. So we can safely remove it.

3 months agoMINOR: applet: Save the "use-service" rule in the stream to init a service applet
Christopher Faulet [Thu, 24 Apr 2025 14:08:48 +0000 (16:08 +0200)] 
MINOR: applet: Save the "use-service" rule in the stream to init a service applet

When a service is initialized, the "use-service" rule that was executed is
now saved in the stream, using "current_rule" field, instead of saving it
into the applet context. It is safe to do so becaues this field is unused at
this stage. To avoid any issue, it is reset after the service
initialization. Doing so, it is no longer necessary to save it in the applet
context. It was the last usage of the rule pointer in the applet context.

The init functions for TCP and HTTP lua services were updated accordingly.

3 months agoMINOR: hlua: Use the applet name in error messages for lua services
Christopher Faulet [Thu, 24 Apr 2025 13:59:31 +0000 (15:59 +0200)] 
MINOR: hlua: Use the applet name in error messages for lua services

The lua function name was used in error messages of HTTP/TCP lua services
while the applet name can be used. Concretely, this will not change
anything, because when a lua service is regiestered, the lua function name
is used to name the applet. But it is easier, cleaner and more logicial
because it is really the applet name that should be displayed in these error
messages.

3 months agoMINOR: cache: Add a pointer on the cache in the cache applet context
Christopher Faulet [Thu, 24 Apr 2025 13:48:57 +0000 (15:48 +0200)] 
MINOR: cache: Add a pointer on the cache in the cache applet context

Thanks to this change, when a response is delivered from the cache, it is no
longer necessary to get the cache filter configuration from the http
"use-cache" rule saved in the appctx to get the currently used cache. It was
a bit complex to get an info that can be directly and naturally stored in
the cache applet context.

3 months agoMINOR: cli/applet: Move appctx fields only used by the CLI in a private context
Christopher Faulet [Thu, 24 Apr 2025 09:17:07 +0000 (11:17 +0200)] 
MINOR: cli/applet: Move appctx fields only used by the CLI in a private context

There are several fields in the appctx structure only used by the CLI. To
make things cleaner, all these fields are now placed in a dedicated context
inside the appctx structure. The final goal is to move it in the service
context and add an API for cli commands to get a command coontext inside the
cli context.

3 months agoBUG/MINOR: ring: Fix I/O handler of "show event" command to not rely on the SC
Christopher Faulet [Wed, 23 Apr 2025 14:38:25 +0000 (16:38 +0200)] 
BUG/MINOR: ring: Fix I/O handler of "show event" command to not rely on the SC

Thanks to the CLI refactoring ("MAJOR: cli: Refacor parsing and execution of
pipelined commands"), it is possible to fix "show event" I/O handle function
to no longer use the SC.

When the applet API was refactored to no longer manipulate the channels or
the stream-connectors, this part was missed. However, without the patch
above, it could not be fixed. It is now possible so let's do it.

This patch must not be backported becaues it depends on refactoring of the
CLI applet.

3 months agoBUG/MINOR: hlua: Fix I/O handler of lua CLI commands to not rely on the SC
Christopher Faulet [Wed, 23 Apr 2025 14:32:55 +0000 (16:32 +0200)] 
BUG/MINOR: hlua: Fix I/O handler of lua CLI commands to not rely on the SC

Thanks to the CLI refactoring ("MAJOR: cli: Refacor parsing and execution of
pipelined commands"), it is possible to fix the I/O handler function used by
lua CLI commands to no longer use the SC.

When the applet API was refactored to no longer manipulate the channels or
the stream-connectors, this part was missed. However, without the patch
above, it could not be fixed. It is now possible so let's do it.

This patch must not be backported becaues it depends on refactoring of the
CLI applet.

3 months agoCLEANUP: applet: Update st0/st1 comment in appctx structure
Christopher Faulet [Wed, 23 Apr 2025 14:30:50 +0000 (16:30 +0200)] 
CLEANUP: applet: Update st0/st1 comment in appctx structure

Today, these states are used by almost all applets. So update the comments
of these fields.

3 months agoMINOR: cli: Rename some CLI applet states to reflect recent refactoring
Christopher Faulet [Wed, 23 Apr 2025 14:27:45 +0000 (16:27 +0200)] 
MINOR: cli: Rename some CLI applet states to reflect recent refactoring

CLI_ST_GETREQ state was renamed into CLI_ST_PARSE_CMDLINE and CLI_ST_PARSEREQ
into CLI_ST_PROCESS_CMDLINE to reflect the real action performed in these
states.

3 months agoMAJOR: cli: Refacor parsing and execution of pipelined commands
Christopher Faulet [Wed, 23 Apr 2025 13:57:41 +0000 (15:57 +0200)] 
MAJOR: cli: Refacor parsing and execution of pipelined commands

Before this patch, when pipelined commands were received, each command was
parsed and then excuted before moving to the next command. Pending commands
were not copied in the input buffer of the applet. The major issue with this
way to handle commands is the impossibility to consume inputs from commands
with an I/O handler, like "show events" for instance. It was working thanks
to a "bug" if such commands were the last one on the command line. But it
was impossible to use them followed by another command. And this prevents us
to implement any streaming support for CLI commands.

So we decided to refactor the command line parsing to have something similar
to a basic shell. Now an entire line is parsed, including the payload,
before starting commands execution. The command line is copied in a
dedicated buffer. "appctx->chunk" buffer is used for this purpose. It was an
unsed field, so it is safe to use it here. Once the command line copied, the
commands found on this line are executed. Because the applet input buffer
was flushed, any input can be safely consumed by the CLI applet and is
available for the command I/O handler. Thanks to this change, "show event
-w" command can be followed by a command. And in theory, it should be
possible to implement commands supporting input data streaming. For
instance, the Tetris like lua applet can be used on the CLI now.

Note that the payload, if any, is part of the command line and must be fully
received before starting the commands processing. It means there is still
the limitation to a buffer, but not only for the payload but for the whole
command line. The payload is still necessarily at the end of the command
line and is passed as argument to the last command. Internally, the
"appctx->cli_payload" field was introduced to point on the payload in the
command line buffer.

This patch is quite huge but it cannot easily be splitted. It should not
introduced significant changes.

3 months agoMINOR: cli: Use a full prompt command for bidir connections with workers
Christopher Faulet [Thu, 24 Apr 2025 12:54:55 +0000 (14:54 +0200)] 
MINOR: cli: Use a full prompt command for bidir connections with workers

When a bidirection connection with no command is establisehd with a worker
(so "@@<pid>" alone), a "prompt" command is automatically added to display
the worker's prompt and enter in interactive mode in the worker context.
However, till now, an unfinished command line is sent, with a semicolon
instead of a newline at the end. It is not exactly a bug because this
works. But it is not really expected and could be a problem for future
changes.

So now, a full command line is sent: the "prompt" command finished by a
newline character.

3 months agoBUG/MINOR: cli: Issue an error when too many args are passed for a command
Christopher Faulet [Wed, 23 Apr 2025 13:29:00 +0000 (15:29 +0200)] 
BUG/MINOR: cli: Issue an error when too many args are passed for a command

When a command is parsed to split it in an array of arguments, by default,
at most 64 arguments are supported. But no warning was emitted when there
were too many arguments. Instead, the arguments above the limit were
silently ignored. It could be an issue for some commands, like "add server",
because there was no way to know some arguments were ignored.

Now an error is issued when too many arguments are passed and the command is
not executed.

This patch should be backported to all stable versions.

3 months agoBUG/MINOR: mux-quic: do not decode if conn in error
Amaury Denoyelle [Wed, 23 Apr 2025 15:06:22 +0000 (17:06 +0200)] 
BUG/MINOR: mux-quic: do not decode if conn in error

Add an early return to qcc_decode_qcs() if QCC instance is flagged on
error and connection is scheduled for immediate closure.

The main objective is to ensure to not trigger BUG_ON() from
qcc_set_error() : if a stream decoding has set the connection error, do
not try to process decoding on other streams as they may also encounter
an error. Thus, the connection is closed asap with the first encountered
error case.

This should be backported up to 2.6, after a period of observation.

3 months agoBUG/MINOR: mux-quic: fix possible infinite loop during decoding
Amaury Denoyelle [Wed, 23 Apr 2025 15:27:24 +0000 (17:27 +0200)] 
BUG/MINOR: mux-quic: fix possible infinite loop during decoding

With the support of multiple Rx buffers per QCS instance, stream
decoding in qcc_io_recv() has been reworked for the next haproxy
release. An issue appears in a double while loop : a break statement is
used in the inner loop, which is not sufficient as it should instead
exit from the outer one.

Fix this by replacing break with a goto statement.

No need to backport this.

3 months agoMINOR: h3: simplify h3_rcv_buf return path
Amaury Denoyelle [Wed, 23 Apr 2025 14:57:42 +0000 (16:57 +0200)] 
MINOR: h3: simplify h3_rcv_buf return path

Remove return statement in h3_rcv_buf() in case of stream/connection
error. Instead, reuse already existing label err. This simplifies the
code path. It also fixes the missing leave trace for these cases.

3 months agoMINOR: stick-table: use a separate lock label for updates
Willy Tarreau [Thu, 24 Apr 2025 12:01:13 +0000 (14:01 +0200)] 
MINOR: stick-table: use a separate lock label for updates

Too many locks were sharing STK_TABLE_LOCK making it hard to analyze.
Let's split the already heavily used update lock.

3 months agoMEDIUM: acme: rename "account" into "account-key"
William Lallemand [Thu, 24 Apr 2025 09:06:39 +0000 (11:06 +0200)] 
MEDIUM: acme: rename "account" into "account-key"

Rename the "account" option of the acme section into "account-key".

3 months agoMEDIUM: acme: rename "uri" into "directory"
William Lallemand [Thu, 24 Apr 2025 08:51:41 +0000 (10:51 +0200)] 
MEDIUM: acme: rename "uri" into "directory"

Rename the "uri" option of the acme section into "directory".

3 months agoMEDIUM: acme: use a customized proxy
William Lallemand [Wed, 23 Apr 2025 13:37:57 +0000 (15:37 +0200)] 
MEDIUM: acme: use a customized proxy

Use a customized proxy for the ACME client.

The proxy is initialized at the first acme section parsed.

The proxy uses the httpsclient log format as ACME CA use HTTPS.

3 months agoMINOR: httpclient: add an "https" log-format
William Lallemand [Wed, 23 Apr 2025 13:32:46 +0000 (15:32 +0200)] 
MINOR: httpclient: add an "https" log-format

Add an experimental "https" log-format for the httpclient, it is not
used by the httpclient by default, but could be define in a customized
proxy.

The string is basically a httpslog, with some of the fields replaced by
their backend equivalent or - when not available:

"%ci:%cp [%tr] %ft -/- %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r %[bc_err]/%[ssl_bc_err,hex]/-/-/%[ssl_bc_is_resumed] -/-/-"

3 months agoMINOR: acme/cli: add the 'acme renew' command to the help message
William Lallemand [Wed, 23 Apr 2025 11:59:27 +0000 (13:59 +0200)] 
MINOR: acme/cli: add the 'acme renew' command to the help message

Add the 'acme renew' command to the 'help' command of the CLI.

3 months agoMINOR: http-act: Add 'pause' action to temporarily suspend the message analysis
Christopher Faulet [Tue, 22 Apr 2025 14:08:50 +0000 (16:08 +0200)] 
MINOR: http-act: Add 'pause' action to temporarily suspend the message analysis

The 'pause' HTTP action can now be used to suspend for a moment the message
analysis. A timeout, expressed in milliseconds using a time-format
parameter, or an expression can be used. If an expression is used, errors
and invalid values are ignored.

Internally, the action will set the analysis expiration date on the
corresponding channel to the configured value and it will yield while it is
not expired.

The 'pause' action is available for 'http-request' and 'http-response'
rules.

3 months agoBUG/MEDIUM: mux-spop: Respect the negociated max-frame-size value to send frames
Christopher Faulet [Tue, 22 Apr 2025 13:27:12 +0000 (15:27 +0200)] 
BUG/MEDIUM: mux-spop: Respect the negociated max-frame-size value to send frames

When a SPOP connection is opened, the maximum size for frames is negociated.
This negociated size is properly used when a frame is received and if a too
big frame is detected, an error is triggered. However, the same was not
performed on the sending path. No check was performed on frames sent to the
agent. So it was possible to send frames bigger than the maximum size
supported by the the SPOE agent.

Now, the size of NOTIFY and DISCONNECT frames is checked before sending them
to the agent.

Thanks to Miroslav to have reported the issue.

This patch must be backported to 3.1.

3 months agoCLEANUP: h1: Remove now useless h1_parse_cont_len_header() function
Christopher Faulet [Tue, 15 Apr 2025 17:17:21 +0000 (19:17 +0200)] 
CLEANUP: h1: Remove now useless h1_parse_cont_len_header() function

Since the commit "MINOR: hlua/h1: Use http_parse_cont_len_header() to parse
content-length value", this function is no longer used. So it can be safely
removed.

3 months agoMINOR: hlua/h1: Use http_parse_cont_len_header() to parse content-length value
Christopher Faulet [Tue, 15 Apr 2025 17:14:31 +0000 (19:14 +0200)] 
MINOR: hlua/h1: Use http_parse_cont_len_header() to parse content-length value

Till now, h1_parse_cont_len_header() was used during the H1 message parsing and
by the lua HTTP applets to parse the content-length header value. But a more
generic function was added some years ago doing exactly the same operations. So
let's use it instead.

3 months agoMINOR: mux-h1: Keep custom "Content-Length: 0" header in 1xx and 204 messages
Christopher Faulet [Tue, 15 Apr 2025 17:04:42 +0000 (19:04 +0200)] 
MINOR: mux-h1: Keep custom "Content-Length: 0" header in 1xx and 204 messages

Thanks to the commit "MINOR: mux-h1: Don't remove custom "Content-Length: 0"
header in 1xx and 204 messages", we are now sure that 1xx and 204 responses
were sanitized during the parsing. So, if one of these headers are found in
such responses when sent to the client, it means it was added by hand, via a
"set-header" action for instance. In this context, we are able to make an
exception for the "Content-Length: 0" header, and only this one with this
value, to not break leagacy applications.

So now, a user can force the "Content-Length: 0" header to appear in 1xx and
204 responses by adding the right action in hist configuration.
"Transfer-Encoding" headers are still dropped as "Content-Length" headers
with another value than 0. Note, that in practice, only 101 and 204 are
concerned because other 1xx message are not subject to HTTP analysis.

This patch should fix the issue #2888. There is no reason to backport
it. But if we do so, the patch above must be backported too.

3 months agoMINOR: h1-htx: Skip C-L and T-E headers for 1xx and 204 messages during parsing
Christopher Faulet [Tue, 15 Apr 2025 16:56:18 +0000 (18:56 +0200)] 
MINOR: h1-htx: Skip C-L and T-E headers for 1xx and 204 messages during parsing

According to the RFC9110 and RFC9112, a server must not add 'Content-Length'
or 'Transfer-Encoding' headers into 1xx and 204 responses. So till now,
these headers were dropped from the response when it is sent to the client.

However, it seems more logical to remove it during the message parsing. In
addition to sanitize messages as early as possible, this will allow us to
apply some exception in some cases (This will be the subject of another
patch).

In this patch, 'Content-Length' and 'Transfer-Encoding' headers are removed
from 1xx and 204 responses during the parsing but the same is still
performed during the formatting stage.

3 months agoMINOR: proxy: Add options to drop HTTP trailers during message forwarding
Christopher Faulet [Tue, 15 Apr 2025 13:36:19 +0000 (15:36 +0200)] 
MINOR: proxy: Add options to drop HTTP trailers during message forwarding

In RFC9110, it is stated that trailers could be merged with the
headers. While it should be performed with a speicial care, it may be a
problem for some applications. To avoid any trouble with such applications,
two new options were added to drop trailers during the message forwarding.

On the backend, "http-drop-request-trailers" option can be enabled to drop
trailers from the requests before sending them to the server. And on the
frontend, "http-drop-response-trailers" option can be enabled to drop
trailers from the responses before sending them to the client. The options
can be defined in defaults sections and disabled with "no" keyword.

This patch should fix the issue #2930.

3 months agoCLEANUP: Slightly reorder some proxy option flags to free slots
Christopher Faulet [Tue, 15 Apr 2025 06:40:49 +0000 (08:40 +0200)] 
CLEANUP: Slightly reorder some proxy option flags to free slots

PR_O_TCPCHK_SSL and PR_O_CONTSTATS was shifted to free a slot. The idea is
to have 2 contiguous slots to be able to insert two new options.

3 months agoCLEANUP: proxy: detach the name node in proxy_free_common() instead
Willy Tarreau [Sat, 19 Apr 2025 08:21:19 +0000 (10:21 +0200)] 
CLEANUP: proxy: detach the name node in proxy_free_common() instead

This changes commit d2a9149f0 ("BUG/MINOR: proxy: always detach a proxy
from the names tree on free()") to be cleaner. AurĂ©lien spotted that
the free(p->id) was indeed already done in proxy_free_common(), which is
called before we delete the node. That's still a bit ugly and it only
works because ebpt_delete() does not dereference the key during the
operation. Better play safe and delete the entry before freeing it,
that's more future-proof.

3 months agoBUG/MINOR: proxy: always detach a proxy from the names tree on free()
Willy Tarreau [Fri, 18 Apr 2025 21:50:13 +0000 (23:50 +0200)] 
BUG/MINOR: proxy: always detach a proxy from the names tree on free()

Stephen Farrell reported in issue #2942 that recent haproxy versions
crash if there's no resolv.conf. A quick bisect with his reproducer
showed that it started with commit 4194f75 ("MEDIUM: tree-wide: avoid
manually initializing proxies") which reorders the proxies initialization
sequence a bit. The crash shows a corrupted tree, typically indicating a
use-after-free. With the help of ASAN it was possible to find that a
resolver proxy had been destroyed and freed before the name insertion
that causes the crash, very likely caused by the absence of the needed
resolv.conf:

    #0 0x7ffff72a82f7 in free (/usr/local/lib64/libasan.so.5+0x1062f7)
    #1 0x94c1fd in free_proxy src/proxy.c:436
    #2 0x9355d1 in resolvers_destroy src/resolvers.c:2604
    #3 0x93e899 in resolvers_create_default src/resolvers.c:3892
    #4 0xc6ed29 in httpclient_resolve_init src/http_client.c:1170
    #5 0xc6fbcf in httpclient_create_proxy src/http_client.c:1310
    #6 0x4ae9da in ssl_ocsp_update_precheck src/ssl_ocsp.c:1452
    #7 0xa1b03f in step_init_2 src/haproxy.c:2050

But free_proxy() doesn't delete the ebpt_node that carries the name,
which perfectly explains the situation. This patch simply deletes the
name node and Stephen confirmed that it fixed the problem for him as
well. Let's also free it since the key points to p->id which is never
freed either in this function!

No backport is needed since the patch above was first merged into
3.2-dev10.

3 months agoBUG/MINOR: quic: do not crash on CRYPTO ncbuf alloc failure
Amaury Denoyelle [Fri, 18 Apr 2025 16:02:48 +0000 (18:02 +0200)] 
BUG/MINOR: quic: do not crash on CRYPTO ncbuf alloc failure

To handle out-of-order received CRYPTO frames, a ncbuf instance is
allocated. This is done via the helper quic_get_ncbuf().

Buffer allocation was improperly checked. In case b_alloc() fails, it
crashes due to a BUG_ON(). Fix this by removing it. The function now
returns NULL on allocation failure, which is already properly handled in
its caller qc_handle_crypto_frm().

This should fix the last reported crash from github issue #2935.

This must be backported up to 2.6.

3 months ago[RELEASE] Released version 3.2-dev11 v3.2-dev11
Willy Tarreau [Fri, 18 Apr 2025 12:19:47 +0000 (14:19 +0200)] 
[RELEASE] Released version 3.2-dev11

Released version 3.2-dev11 with the following main changes :
    - CI: enable weekly QuicTLS build
    - DOC: management: slightly clarify the prefix role of the '@' command
    - DOC: management: add a paragraph about the limitations of the '@' prefix
    - MINOR: master/cli: support bidirectional communications with workers
    - MEDIUM: ssl/ckch: add filename and linenum argument to crt-store parsing
    - MINOR: acme: add the acme section in the configuration parser
    - MINOR: acme: add configuration for the crt-store
    - MINOR: acme: add private key configuration
    - MINOR: acme/cli: add the 'acme renew' command
    - MINOR: acme: the acme section is experimental
    - MINOR: acme: get the ACME directory
    - MINOR: acme: handle the nonce
    - MINOR: acme: check if the account exist
    - MINOR: acme: generate new account
    - MINOR: acme: newOrder request retrieve authorizations URLs
    - MINOR: acme: allow empty payload in acme_jws_payload()
    - MINOR: acme: get the challenges object from the Auth URL
    - MINOR: acme: send the request for challenge ready
    - MINOR: acme: implement a check on the challenge status
    - MINOR: acme: generate the CSR in a X509_REQ
    - MINOR: acme: finalize by sending the CSR
    - MINOR: acme: verify the order status once finalized
    - MINOR: acme: implement retrieval of the certificate
    - BUG/MINOR: acme: ckch_conf_acme_init() when no filename
    - MINOR: ssl/ckch: handle ckch_conf in ckchs_dup() and ckch_conf_clean()
    - MINOR: acme: copy the original ckch_store
    - MEDIUM: acme: replace the previous ckch instance with new ones
    - MINOR: acme: schedule retries with a timer
    - BUILD: acme: enable the ACME feature when JWS is present
    - BUG/MINOR: cpu-topo: check the correct variable for NULL after malloc()
    - BUG/MINOR: acme: key not restored upon error in acme_res_certificate()
    - BUG/MINOR: thread: protect thread_cpus_enabled_at_boot with USE_THREAD
    - MINOR: acme: default to 2048bits for RSA
    - DOC: acme: explain how to configure and run ACME
    - BUG/MINOR: debug: remove the trailing \n from BUG_ON() statements
    - DOC: config: add the missing "profiling.memory" to the global kw index
    - DOC: config: add the missing "force-cfg-parser-pause" to the global kw index
    - DEBUG: init: report invalid characters in debug description strings
    - DEBUG: rename DEBUG_GLITCHES to DEBUG_COUNTERS and enable it by default
    - DEBUG: counters: make COUNT_IF() only appear at DEBUG_COUNTERS>=1
    - DEBUG: counters: add the ability to enable/disable updating the COUNT_IF counters
    - MINOR: tools: let dump_addr_and_bytes() support dumping before the offset
    - MINOR: debug: in call traces, dump the 8 bytes before the return address, not after
    - MINOR: debug: detect call instructions and show the branch target in backtraces
    - BUG/MINOR: acme: fix possible NULL deref
    - CLEANUP: acme: stored value is overwritten before it can be used
    - BUILD: incompatible pointer type suspected with -DDEBUG_UNIT
    - BUG/MINOR: http-ana: Properly detect client abort when forwarding the response
    - BUG/MEDIUM: http-ana: Report 502 from req analyzer only during rsp forwarding
    - CI: fedora rawhide: enable unit tests
    - DOC: configuration: fix a typo in ACME documentation
    - MEDIUM: sink: add a new dpapi ring buffer
    - Revert "BUG/MINOR: acme: key not restored upon error in acme_res_certificate()"
    - BUG/MINOR: acme: key not restored upon error in acme_res_certificate() V2
    - BUG/MINOR: acme: fix the exponential backoff of retries
    - DOC: configuration: specify limitations of ACME for 3.2
    - MINOR: acme: emit logs instead of ha_notice
    - MINOR: acme: add a success message to the logs
    - BUG/MINOR: acme/cli: fix certificate name in error message
    - MINOR: acme: register the task in the ckch_store
    - MINOR: acme: free acme_ctx once the task is done
    - BUG/MEDIUM: h3: trim whitespaces when parsing headers value
    - BUG/MEDIUM: h3: trim whitespaces in header value prior to QPACK encoding
    - BUG/MINOR: h3: filter upgrade connection header
    - BUG/MINOR: h3: reject invalid :path in request
    - BUG/MINOR: h3: reject request URI with invalid characters
    - MEDIUM: h3: use absolute URI form with :authority
    - BUG/MEDIUM: hlua: fix hlua_applet_{http,tcp}_fct() yield regression (lost data)
    - BUG/MINOR: mux-h2: prevent past scheduling with idle connections
    - BUG/MINOR: rhttp: fix reconnect if timeout connect unset
    - BUG/MINOR: rhttp: ensure GOAWAY can be emitted after reversal
    - BUG/MINOR: mux-h2: do not apply timer on idle backend connection
    - MINOR: mux-h2: refactor idle timeout calculation
    - MINOR: mux-h2: prepare to support PING emission
    - MEDIUM: server/mux-h2: implement idle-ping on backend side
    - MEDIUM: listener/mux-h2: implement idle-ping on frontend side
    - MINOR: mux-h2: do not emit GOAWAY on idle ping expiration
    - MINOR: mux-h2: handle idle-ping on conn reverse
    - BUILD: makefile: enable backtrace by default on musl
    - BUG/MINOR: threads: set threads_idle and threads_harmless even with no threads
    - BUG/MINOR debug: fix !USE_THREAD_DUMP in ha_thread_dump_fill()
    - BUG/MINOR: wdt/debug: avoid signal re-entrance between debugger and watchdog
    - BUG/MINOR: debug: detect and prevent re-entrance in ha_thread_dump_fill()
    - MINOR: debug: do not statify a few debugging functions often used with wdt/dbg
    - MINOR: tools: also protect the library name resolution against concurrent accesses
    - MINOR: tools: protect dladdr() against reentrant calls from the debug handler
    - MINOR: debug: protect ha_dump_backtrace() against risks of re-entrance
    - MINOR: tinfo: keep a copy of the pointer to the thread dump buffer
    - MINOR: debug: always reset the dump pointer when done
    - MINOR: debug: remove unused case of thr!=tid in ha_thread_dump_one()
    - MINOR: pass a valid buffer pointer to ha_thread_dump_one()
    - MEDIUM: wdt: always make the faulty thread report its own warnings
    - MINOR: debug: make ha_stuck_warning() only work for the current thread
    - MINOR: debug: make ha_stuck_warning() print the whole message at once
    - CLEANUP: debug: no longer set nor use TH_FL_DUMPING_OTHERS
    - MINOR: sched: add a new function is_sched_alive() to report scheduler's health
    - MINOR: wdt: use is_sched_alive() instead of keeping a local ctxsw copy
    - MINOR: sample: add 4 new sample fetches for clienthello parsing
    - REGTEST: add new reg-test for the 4 new clienthello fetches
    - MINOR: servers: Move the per-thread server initialization earlier
    - MINOR: proxies: Initialize the per-thread structure earlier.
    - MINOR: servers: Provide a pointer to the server in srv_per_tgroup.
    - MINOR: lb_fwrr: Move the next weight out of fwrr_group.
    - MINOR: proxies: Add a per-thread group lbprm struct.
    - MEDIUM: lb_fwrr: Use one ebtree per thread group.
    - MEDIUM: lb_fwrr: Don't start all thread groups on the same server.
    - MINOR: proxies: Do stage2 initialization for sinks too

3 months agoMINOR: proxies: Do stage2 initialization for sinks too
Olivier Houchard [Thu, 17 Apr 2025 15:16:44 +0000 (17:16 +0200)] 
MINOR: proxies: Do stage2 initialization for sinks too

In check_config_validity(), we initialize the proxy in several stages.
We do so for the sink list for stage1, but not for stage2. It may not be
needed right now, but it may become needed in the future, so do it
anyway.

3 months agoMEDIUM: lb_fwrr: Don't start all thread groups on the same server.
Olivier Houchard [Thu, 17 Apr 2025 14:45:29 +0000 (16:45 +0200)] 
MEDIUM: lb_fwrr: Don't start all thread groups on the same server.

Now that all there is one tree per thread group, all thread groups will
start on the same server. To prevent that, just insert the servers in a
different order for each thread group.

3 months agoMEDIUM: lb_fwrr: Use one ebtree per thread group.
Olivier Houchard [Thu, 17 Apr 2025 14:31:44 +0000 (16:31 +0200)] 
MEDIUM: lb_fwrr: Use one ebtree per thread group.

When using the round-robin load balancer, the major source of contention
is the lbprm lock, that has to be held every time we pick a server.
To mitigate that, make it so there are one tree per thread-group, and
one lock per thread-group. That means we now have a lb_fwrr_per_tgrp
structure that will contain the two lb_fwrr_groups (active and backup) as well
as the lock to protect them in the per-thread lbprm struct, and all
fields in the struct server are now moved to the per-thread structure
too.
Those changes are mostly mechanical, and brings good performances
improvment, on a 64-cores AMD CPU, with 64 servers configured, we could
process about 620000 requests par second, and we now can process around
1400000 requests per second.

3 months agoMINOR: proxies: Add a per-thread group lbprm struct.
Olivier Houchard [Thu, 17 Apr 2025 14:10:48 +0000 (16:10 +0200)] 
MINOR: proxies: Add a per-thread group lbprm struct.

Add a new structure in the per-thread groups proxy structure, that will
contain whatever is per-thread group in lbprm.
It will be accessed as p->per_tgrp[tgid].lbprm.

3 months agoMINOR: lb_fwrr: Move the next weight out of fwrr_group.
Olivier Houchard [Thu, 17 Apr 2025 13:50:33 +0000 (15:50 +0200)] 
MINOR: lb_fwrr: Move the next weight out of fwrr_group.

Move the "next_weight" outside of fwrr_group, and inside struct lb_fwrr
directly, one for the active servers, one for the backup servers.
We will soon have one fwrr_group per thread group, but next_weight will
be global to all of them.

3 months agoMINOR: servers: Provide a pointer to the server in srv_per_tgroup.
Olivier Houchard [Thu, 17 Apr 2025 09:20:24 +0000 (11:20 +0200)] 
MINOR: servers: Provide a pointer to the server in srv_per_tgroup.

Add a pointer to the server into the struct srv_per_tgroup, so that if
we only have access to that srv_per_tgroup, we can come back to the
corresponding server.

3 months agoMINOR: proxies: Initialize the per-thread structure earlier.
Olivier Houchard [Thu, 17 Apr 2025 15:05:07 +0000 (17:05 +0200)] 
MINOR: proxies: Initialize the per-thread structure earlier.

Move the call to initialize the proxy's per-thread structure earlier
than currently done, so that they are usable when we're initializing the
load balancers.

3 months agoMINOR: servers: Move the per-thread server initialization earlier
Olivier Houchard [Thu, 17 Apr 2025 08:42:25 +0000 (10:42 +0200)] 
MINOR: servers: Move the per-thread server initialization earlier

Move the code responsible for calling per-thread server initialization
earlier than it was done, so that per-thread structures are available a
bit later, when we initialize load-balancing.