Commit graph

27253 commits

Author SHA1 Message Date
Frederic Lecaille
efc5ed1bf2 to be merged into haload sources commit:
Some checks failed
Contrib / admin/halog/ (push) Has been cancelled
Contrib / dev/flags/ (push) Has been cancelled
Contrib / dev/haring/ (push) Has been cancelled
Contrib / dev/hpack/ (push) Has been cancelled
Contrib / dev/poll/ (push) Has been cancelled
VTest / Generate Build Matrix (push) Has been cancelled
Windows / Windows, gcc, all features (push) Has been cancelled
VTest / (push) Has been cancelled
get rid of an intermediary task (hld_io_cb) between the muxes and the haload
stream task handler (hld_strm_task()).
2026-05-22 15:59:11 +02:00
Frederic Lecaille
7e877b8349 TO CHECK: make hq-interop support hlstream (streams for haload) 2026-05-22 14:21:04 +02:00
Frederic Lecaille
28893f43bc cleanup 2026-05-22 14:21:04 +02:00
Frederic Lecaille
4daa158974 to be merged: implement -e option 2026-05-22 14:21:04 +02:00
Frederic Lecaille
2459ae5917 to be merged: do not count stream in error as done for arg_rconn counter
also rename this counter from ->tot_done ->tot_rconn_done
2026-05-22 14:21:04 +02:00
Frederic Lecaille
244a4c2c31 to be merged into prev commit 2026-05-22 14:21:04 +02:00
Frederic Lecaille
db6ff84d84 to be merged: support again h2c after recent haproxy changes
-- server "proto h2c" could not be used anymore
h2c is not an ALPN identifier, this is a protocol
2026-05-22 14:21:04 +02:00
Frederic Lecaille
7c0c5f5618 to be merged: add BUG_ON()s and fix several multiple urls related issues 2026-05-22 14:21:04 +02:00
Frederic Lecaille
27614e16d5 to be merged: arg_mreqs in relation with max-concurrent streams (h2 and h3) 2026-05-22 14:21:04 +02:00
Frederic Lecaille
adb57b52b5 to be merged: adaptions to recent connection+mux API changes
Especially to select the muxes.
2026-05-22 14:21:04 +02:00
Frederic Lecaille
3223502ce7 to be merged: add quic URL scheme 2026-05-22 14:21:04 +02:00
Frederic Lecaille
6063841e26 to be merged: fix a http_add_header() api change 2026-05-22 14:21:04 +02:00
Frederic Lecaille
09c91eb59a to be merged: add --tls-ciphers --tls-ciphersuites --tls-curves opts
also improve the server options parsing (several options for the same
--server opt), reuse this for the newly added tls opts
2026-05-22 14:21:04 +02:00
Frederic Lecaille
5c48e9bc89 to be merged: add --default 2026-05-22 14:21:04 +02:00
Frederic Lecaille
c74b114ed8 to be merged: replace -G by --global 2026-05-22 14:21:04 +02:00
Frederic Lecaille
1409eff884 to be merged: replace -S by --server 2026-05-22 14:21:04 +02:00
Frederic Lecaille
fd3f99e348 WIP: haload sources 2026-05-22 11:07:11 +02:00
Frederic Lecaille
f39f8842ec MINOR: haload: add haload build target
This patch introduces the haload target to the Makefile. It defines
the HALOAD_OBJS list, which includes the standard objects along with
the specific haload_init.o, haload.o, and hbuf.o files.

The build process follows the same pattern as the haterm tool,
allowing haload to be compiled as a standalone binary.
2026-05-22 11:07:11 +02:00
Frederic Lecaille
873681bc17 MINOR: server: export functions used during server initialization
Export _srv_parse_kw() and srv_postinit() so they can be called from
haload (to come), which needs to configure servers using HAProxy's configuration
parser keywords.
2026-05-22 11:07:11 +02:00
Frederic Lecaille
4302d02cb5 MINOR: stconn: export sc_new()
This patch exports sc_new() by removing its static storage class and
adding its prototype to include/haproxy/stconn.h.

This is required to allow external modules, such as the upcoming haload
benchmarking tool, to allocate and initialize new stream connectors
from a stream endpoint descriptor (sedesc).
2026-05-22 11:07:11 +02:00
Frederic Lecaille
afca62e663 MINOR: stconn: add sc_hastream() and __sc_hastream() helpers
This patch introduces the sc_hastream() and __sc_hastream() inline
helpers to retrieve a haload stream context (struct hastream) from
a stream connector.

These functions allow the stconn layer to safely access haload-specific
stream data when the application type is OBJ_TYPE_HXLOAD.
2026-05-22 11:07:11 +02:00
Frederic Lecaille
4d08c3692b MINOR: obj_type: add OBJ_TYPE_HXLOAD for haload stream objects
This patch introduces the OBJ_TYPE_HXLOAD object type to represent
haload stream objects (struct hastream).

It also adds the associated inline helper functions objt_hastream()
and __objt_hastream() to allow safe casting and retrieval of
hastream contexts from a generic object pointer, following the
standard container_of pattern.
2026-05-22 11:07:11 +02:00
Frederic Lecaille
ab64822a47 MINOR: hldstream: add definition of hldstream struct objects
haload is a client-side HTTP benchmarking tool designed to manage
concurrent HTTP streams.

This patch defines the hldstream C structure, which serves as the
core object to represent a haload HTTP stream for all the HTTP protocol.
It will be used by the upcoming haload module to handle specialized
stream contexts.
2026-05-22 11:07:11 +02:00
Frederic Lecaille
a524b0cfdc MINOR: trace: add definitions for haload streams
haload is the successor to the h1load HTTP benchmarking tool.

This patch adds haload stream definitions as arguments for the TRACE API.
These will be used by the upcoming haload module, which will handle
hldstream struct objects instead of regular stream structs.
2026-05-22 11:07:11 +02:00
Frederic Lecaille
ed632ee5d0 MINOR: init: add HTTP client-only mode
Introduce the new <client_mode> global variable to define the operating mode
of haproxy. This variable can be set to 1 to allow haproxy to start without
any listeners.

During the initialization cycle, setting this flag ensures that the lack of
configured listeners is no longer treated as a fatal error. This allows
programs based on haproxy source code to initialize the stack and use its
features even without a frontend.
2026-05-22 11:07:11 +02:00
Frederic Lecaille
597cbaa9fd MINOR: hbuf: add a very lightweight hbuf API
Add a new lightweight hbuf API to buffer formatted strings, similar to the
existing buffer API (struct buffer). This is required by haterm to build
its configuration in memory (fileless mode).

Update haterm to use this new API.

Note: hstream_str_buf_append() has been renamed to hbuf_str_append().
2026-05-22 11:07:11 +02:00
Frederic Lecaille
d291a99be7 DO NOT MERGE: fairer scheduling for less nice tasks
This ensures high priority for the <mtask> task, which must display statistics
every second without being delayed by other tasks.
2026-05-22 11:07:11 +02:00
Frederic Lecaille
407c768ca0 DO NOT MERGE: add timestamps to stderr sink 2026-05-22 11:07:11 +02:00
Frederic Lecaille
e104b85919 BUG/MINOR: quic: Fix memory leak in quic_deallocate_dghdlrs()
When deallocating the QUIC datagram handlers, the per-thread buffer
allocated inside quic_dghdlrs[i].buf.buffer was missing a free().
This led to a memory leak on exit or reload.

Fix this by freeing each thread buffer before releasing the main
quic_dghdlrs array.
2026-05-22 11:07:11 +02:00
Frederic Lecaille
ca5dbc2a9f BUG/MEDIUM: quic: handle ECONNREFUSED on RX side
Unlike the detection performed during sendto() for an unreachable peer,
ECONNREFUSED was not handled when received via recvmsg() as an ICMP
"host unreachable" message.

This patch tracks ECONNREFUSED errors on the receive path.

Note that this detection is entirely dependent on the remote host effectively
sending an ICMP "host unreachable" message and on the absence of any network
filtering (e.g., firewalls) that would drop such ICMP packets. Without
receiving this ICMP signal, the connection state cannot be updated through
this mechanism.

At a higher level, similar to how this error is handled on sendto(),
the connection is now terminated as soon as possible by calling
qc_kill_conn(). This triggers a call to qc_notify_err(). When the mux
does not exist, it attempts to create one via conn_create_mux(). While
the latter systematically fails if the connection is flagged with
CO_FL_ERROR, it has the useful side effect of waking the stconn stream
attached to the connection during a session opening without a mux
(e.g., for H3).

This issue was caught by haload (upcoming tool).

Must be backported as far as 2.6 because it impacts both the QUIC
frontends and backends.
2026-05-20 15:51:10 +02:00
Amaury Denoyelle
47a61eb86d BUG/MINOR: mux_quic: do not exceed stream.max-concurrent on backend side
Some checks are pending
Contrib / admin/halog/ (push) Waiting to run
Contrib / dev/flags/ (push) Waiting to run
Contrib / dev/haring/ (push) Waiting to run
Contrib / dev/hpack/ (push) Waiting to run
Contrib / dev/poll/ (push) Waiting to run
VTest / Generate Build Matrix (push) Waiting to run
VTest / (push) Blocked by required conditions
Windows / Windows, gcc, all features (push) Waiting to run
Fix usage of stream.max-concurrent QUIC setting on the backend side.
Contrary to frontend connections, this limit must be enforced by QUIC
MUX directly. This is necessary as the peer may allow a larger number of
concurrent streams via its flow control.

First, QUIC TP initial max bidi streams value is now set to 0. This is
fine as only the HTTP/3 client is expected to open bidirectional
streams.

The most important changes is performed in qcm_avail_streams(). The
value first depends on the peer flow control. Now, it is further reduced
if necessary to not exceed the configured BE stream.max-concurrent.

Note that this new behavior may further increases current limitation on
QUIC BE reuse when a QCS instance is kept while its upper stream layer
is detached. In this case there is a risk that the connection is not
reinserted in the correct server pool, as an idle or avail one.

This is a breaking change as BE stream.max-concurrent keyword setting
meaning is changed in effect. However, this does not necessitate extra
warnings as the previous usage was in effect useless. Furthermore, QUIC
on the backend side is still considered as experimental.

This can be backported up to 3.3.
2026-05-20 14:42:03 +02:00
Amaury Denoyelle
b7c607e207 DOC: fix typo on QUIC stream.max-concurrent reference
Add a missing "fe" prefix for the QUIC keyword reference in
tune.streams-elasticity documentation.
2026-05-20 13:40:53 +02:00
Olivier Houchard
05e65489cb BUG/MEDIUM: servers: Don't forget to set srv_hash when needed
Commit 8aa854ab26a7daa613a17548f1fe1d0adb8cf61b made it so we'd store
the hash corresponding to the server parameters, so that we could detect
if we're still talking to the same server, and not use those parameters
if not.
However, when updating those parameters, we forgot to store the new
hash, which would result in the new parameters never be used, and
breakling 0RTT.
Fix that by properly update the hash when needed.
This should be backported when 8aa854ab26a7daa613a17548f1fe1d0adb8cf61b
is backported.
2026-05-20 12:32:19 +02:00
Willy Tarreau
b9acb4415f MEDIUM: startup: warn when chroot is not set for root
We're still regularly seeing insecure configs where chroot is missing.
Now that we have "chroot auto", there's no excuse for not knowing where
to chroot, so let's detect that we're starting as root, detect that the
process is allowed to chroot (i.e. no capability issue, or some hardened
containers), and if no chroot is set, let's emit a warning explaining how
to silence it, i.e. either "chroot auto" or "chroot /".

Most likely we'll start using "chroot auto" by default in 3.5 if no
usability issue is reported.
2026-05-20 11:51:45 +02:00
Willy Tarreau
3c35e7f137 MINOR: startup: do not execute chroot() when "/"
We'll recommend to use "chroot /" to explicitly disable chroot, however
there might be configurations where it would cause problems to just issue
the syscall (typically some hardened containers), so let's make sure that
"chroot /" is a nop in this case.
2026-05-20 11:46:43 +02:00
Willy Tarreau
d142c7f421 BUILD: traces: add USE_TRACE allowing to disable traces
This reduces the total code size by 6-10% and speeds up the build a
bit. It can be further reduced by disabling the trace decoding code
inside certain subsystems like muxes. But at least like this it will
help users on small systems to reduce the footprint when not needed
by explicitly passing USE_TRACE=0 (they remain enabled by default).
2026-05-20 11:46:43 +02:00
Willy Tarreau
8dd31dcd07 BUILD: traces: set a few __maybe_unused on vars used only for traces
Certain variables are used only for traces in mux, ssl and quic
essentially, and disabling traces emits warnings, so let's mark
them appropriately.
2026-05-20 11:46:43 +02:00
Amaury Denoyelle
f521581922 BUG/MINOR: prevent conn leak in case of xprt_qmux init failure
In case of XPRT_QMUX init failure on the frontend side, the connection
must immediately be released. This is not the case on the backend side
as a stream can supervize the connection lifetime.

This patch performs the connection free via conn_complete_session(). As
conn is flagged with CO_FL_ERROR, this will automatically fail and
invoke session_kill_embryonic(), which ensures the session and its
connection are both freed as wanted in this case.

No need to backport.
2026-05-20 11:13:56 +02:00
Olivier Houchard
de3f245df0 BUG/MEDIUM: servers: Store the connection hash with the parameter cache
When we store the negociated server parameters, such as the ALPN, also
store the calculated hash with the connection. If it is different, as
can happen because the IP address is different because set-dst was used,
we certainly do not want to reuse the information in the cache,
otherwise we could end up using the wrong ALPN and mux.
That means we already have to calculate the hash in connect_server()
now, while before we would not do it for Websockets, if we could not do
connection reuse, as that's all the hash was used for.

This should fix Github issue #3386

This should be backported as far as 3.2.
2026-05-20 10:29:22 +02:00
Amaury Denoyelle
e139dd90e3 MAJOR: mux_quic: support stream elasticity during connection lifetime
Some checks are pending
Contrib / admin/halog/ (push) Waiting to run
Contrib / dev/flags/ (push) Waiting to run
Contrib / dev/haring/ (push) Waiting to run
Contrib / dev/hpack/ (push) Waiting to run
Contrib / dev/poll/ (push) Waiting to run
VTest / Generate Build Matrix (push) Waiting to run
VTest / (push) Blocked by required conditions
Windows / Windows, gcc, all features (push) Waiting to run
qcc_release_remote_stream() is called each time a remote stream is
closed. Flow control accounting is updated and when necessary, a
MAX_STREAMS_BIDI frame is prepared to allow the peer to initiate new
streams.

This patch extends stream elasticity features with the QUIC bidirection
stream flow control mechanism. The announced value can now be possibly
reduced depending on conn_calc_max_streams().

The first step is to decrement closed streams from the global committed
extra streams total. This must be performed conn_calc_max_streams() to
ensure the calculation will be valid.

Then, there is two cases depending on conn_calc_max_streams() result. If
the value is less than the peer still remaining stream window, nothing
more is performed. If the opposite case, flow control must be increased
and a MAX_STREAMS_BIDI frame is prepared, with the value adjusted to not
exceed the stream elasticity limit. Global extra streams total is then
finally incremented.

This calcul also ensures that when all streams are closed, global extra
streams accounting operations are decremented by 1, as a connection
always has access to one stream which is excluded from the global total.

Note that if stream elasticity is not active, flow control increases
principle is unchanged and remains statically performed.

This patch is labelled as major as it complexifies bidirectional stream
flow control mechanisme. This is a sensitive operation as there is a
risk of connection freeze if flow control updates are inadvertently
skipped.
2026-05-20 09:52:50 +02:00
Amaury Denoyelle
89f3975acc MINOR: mux_quic: define ms_bidi_rel QCC member
Add a new QCC member <ms_bidi_rel>. This represents the number of
concurrent streams advertised similarly to ms_bidi, but as a relative
value.

This patch does not introduce any functional change. For now,
<ms_bidi_rel> will be equal to <ms_bidi_init>. However, with the
implementation of stream elasticity and dynamic adjustment for
concurrent max-streams-bidi, the former will be required to keep the
last advertised value.
2026-05-20 09:52:50 +02:00
Amaury Denoyelle
d21ec4c707 MINOR: quic: use stream elasticity value for initial advertisement
When stream elasticity is active, the maximum number of concurrent bidi
streams advertised via transport parameters is now reduced depending on
the connection load. This is implemented via conn_calc_max_streams()
which returns the value to use.

This is not applied on listeners with enabled 0-RTT. Indeed, for such
connections, clients are expected to reuse the previously seen transport
parameters. The server on the other hand must not decrease several
values on the newly advertised params, in particular for the maximum
number of concurrent bidi streams. The simplest way to prevent 0-RTT
failure is to not mix stream elasticity with it.

Note that the 0-RTT limitation is only applied for the initial value :
during the connection lifetime, stream elasticity can still be used by
the MUX to dynamically reduce the stream window. This will be
implemented in a future patch.
2026-05-20 09:52:50 +02:00
Amaury Denoyelle
e4adba6e64 MINOR: mux_quic: implement basic committed_extra_streams accounting
Account QUIC frontend connections into committed_extra_streams when
stream elasticity setting is active. This is performed in QCC init and
release functions.

This patch has no impact on QUIC subsystem for now. Connections will
still allow a static number of concurrent streams based on
tune.quic.fe.stream.max-concurrent. However, this has a direct
repercussion on H2 subsystem, as a higher count of QUIC connections will
reduce the concurrent streams allowed there.
2026-05-20 09:52:50 +02:00
Amaury Denoyelle
33c8270903 OPTIM: h2: do not update committed streams if elasticity disabled
When streams-elasticity is enabled in the configuration, H2 mux is
responsible to update the global committed_extra_streams value.

Adjust these operations to ensure they are skipped if streams-elasticity
is disabled, which is the current default. This prevents unnecessary
atomic operations in this case.

No need to backport unless streams-elasticity feature is picked in older
releases.
2026-05-20 09:52:50 +02:00
Amaury Denoyelle
ad3562fea1 MINOR: h2: explain committed_extra_streams dec on h2_init() error
h2_init() is now responsible to increment committed_extra_streams for
new frontend connections, in relation to the newly implemented
stream-elasticity feature. In case of an early error, a mirroring
decrement is executed on fail_stream label.

However, for now this error label can only be selected via BE conns. In
fact, it's not yet possible for h2_init() to fail after the extra
streams increment.

However, the decrement operation is kept to prevent any omissions in
case of future evolutions of h2_init() error path. To prevent reporting
of a possible dead code, add an extra comment which summarizes the
situation.
2026-05-20 09:52:50 +02:00
Maxime Henrion
641fe4f119 MEDIUM: startup: add automatic chroot feature
It is now possible to use "chroot auto" in the configuration. This lets
haproxy create an anonymous (cleaned up after the process terminates)
and read-only directory for chroot. This directory is created in /tmp;
we might want to support creating it in a different directory in the
future, either by respecting $TMPDIR or by allowing an optional
directory after the "auto" keyword.
2026-05-20 08:34:24 +02:00
Maxime Henrion
2d2980408f MINOR: startup: support unprivileged chroot if possible
Try to use unshare(CLONE_NEWUSER) if available so we can have a chroot
as an unprivileged user. This is a Linux-only mechanism.
2026-05-20 08:34:17 +02:00
Willy Tarreau
7004bb3b8c MINOR: backend: support hash-key guid for a stabler distribution
Some checks are pending
Contrib / admin/halog/ (push) Waiting to run
Contrib / dev/flags/ (push) Waiting to run
Contrib / dev/haring/ (push) Waiting to run
Contrib / dev/hpack/ (push) Waiting to run
Contrib / dev/poll/ (push) Waiting to run
VTest / Generate Build Matrix (push) Waiting to run
VTest / (push) Blocked by required conditions
Windows / Windows, gcc, all features (push) Waiting to run
When server fleets are constantly updated, using a stable distribution
across a bunch of load balancers can be convenient. The addr and port
already provide a bit of this but for situations were addresses might
differ between sites or change dynamically this does not work. The guid
is perfect for this because by definition it's supposed to designate a
single server and be unique. So when two servers anywhere have the same,
the tool that provisionned them promises that they are the same server.

So here we introduce "hash-key guid" which performs a 32-bit hash on
the GUID value. When no guid is provided, a fallback is performed on
ID, as is done for other keys.
2026-05-19 19:11:25 +02:00
Willy Tarreau
a59e6e5efd MINOR: server: support hash-key id32 for a cleaner distribution
The "id" hash-key scales the ID by a factor of 16 that tries to leave
room between the nodes on the 32-bit space to permit smooth weight
variations (e.g. during slowstart). However this does not deal well
with overlaps between server IDs. For example, assigning IDs that are
only multiples of 256 million to 16 servers yields traffic only on
one since in practice they all have the same 28 lower bits.

The new "id32" hash key bridges this gap by using the full 32-bit ID
of the server as the key. On the other hand, the user must be careful
not to switch the hash function to "none" when using incremental IDs
because in this case they might be very poorly distributed. But this
can be convenient for automated provisionning systems which assign
IDs themselves, as the full 32 bits are used now.
2026-05-19 19:11:25 +02:00
Willy Tarreau
cb5d98c495 BUG/MINOR: backend: fix balance hash calculation when using hash-type none
The "hash-type xxx none" is broken for keys that are not in type string
because the sample fetch call casts them to SMP_T_BIN, that tends to
preserve the original format (integers, IP addresses etc), but the
gen_hash() function in case of BE_LB_HFCN_NONE expects to read a string
representing a number, that it parses to retrieve the value, and just
fails on many binary types. For example, the following just always
returns key 0:

    balance hash rand()
    hash type consistent none

An ugly workaround is to make sure the expression returns a string, for
example this:

    balance hash rand(),concat()
    hash type consistent none

In order to fix most cases here, we force the conversion to type string
when using BE_LB_HFCN_NONE, but a better approach would require a larger
rework and split gen_hash() or change it to accept an integer as well,
so that the caller could cast to SMP_T_INT for BE_LB_HFCN_NONE and pass
the resulting number already parsed with the least information loss. In
this case even IPv4 addresses would be preserved.

The current approach at least addresses the initially envisioned use
cases, and the limitations have been added to the doc. This can be
backported to 3.0 though it's not really important.
2026-05-19 19:11:25 +02:00