]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
22 months agoBUG/MEDIUM: stconn: Update stream expiration date on blocked sends
Christopher Faulet [Mon, 28 Aug 2023 15:42:24 +0000 (17:42 +0200)] 
BUG/MEDIUM: stconn: Update stream expiration date on blocked sends

When outgoing data are blocked, we must update the stream expiration date
and requeue the task. It is important to be sure to properly handle write
timeout, expecially if the stream cannot expire on reads. This bug was
introduced when handling of channel's timeouts was refactored to be managed
by the stream-connectors.

It is an issue if there is no server timeout and the client does not consume
the response (or the opposite but it is less common). It is also possible to
trigger the same scenario with applets on server side because, most of time,
there is no server timeout.

This patch must be backported to 2.8.

22 months agoDEBUG: applet: Properly report opposite SC expiration dates in traces
Christopher Faulet [Tue, 29 Aug 2023 08:55:15 +0000 (10:55 +0200)] 
DEBUG: applet: Properly report opposite SC expiration dates in traces

The wrong label was used in trace to report expiration dates of the opposite
SC. "sc" was used instead of "sco".

This patch should be backported to 2.8.

22 months agoMINOR: checks: also consider the thread's queue for rebalancing
Willy Tarreau [Thu, 31 Aug 2023 15:51:00 +0000 (17:51 +0200)] 
MINOR: checks: also consider the thread's queue for rebalancing

Let's also check for other threads when the current one is queueing,
let's not wait for the load to be high. Now this totally eliminates
differences between threads.

22 months agoMEDIUM: checks: implement a queue in order to limit concurrent checks
Willy Tarreau [Thu, 31 Aug 2023 14:54:22 +0000 (16:54 +0200)] 
MEDIUM: checks: implement a queue in order to limit concurrent checks

The progressive adoption of OpenSSL 3 and its abysmal handshake
performance has started to reveal situations where it simply isn't
possible anymore to succesfully run health checks on many servers,
because between the moment all the checks are started and the moment
the handshake finally completes, the timeout has expired!

This also has consequences on production traffic which gets
significantly delayed as well, all that for lots of checks. While it's
possible to increase the check delays, it doesn't solve everything as
checks still take a huge amount of time to converge in such conditions.

Here we take a different approach by permitting to enforce the maximum
concurrent checks per thread limitation and implementing an ordered
queue. Thanks to this, if a thread about to start a check has reached
its limit, it will add the check at the end of a queue and it will be
processed once another check is finished. This proves to be extremely
efficient, with all checks completing in a reasonable amount of time
and not being disturbed by the rest of the traffic from other checks.
They're just cycling slower, but at the speed the machine can handle.

One must understand however that if some complex checks perform multiple
exchanges, they will take a check slot for all the required duration.
This is why the limit is not enforced by default.

Tests on SSL show that a limit of 5-50 checks per thread on local
servers gives excellent results already, so that could be a good starting
point.

22 months agoMEDIUM: checks: search more aggressively for another thread on overload
Willy Tarreau [Wed, 23 Aug 2023 09:39:00 +0000 (11:39 +0200)] 
MEDIUM: checks: search more aggressively for another thread on overload

When the current check is overloaded (more running checks than the
configured limit), we'll try more aggressively to find another thread.
Instead of just opportunistically looking for one half as loaded, now if
the current thread has more than 1% more active checks than another one,
or has more than a configured limit of concurrent running checks, it will
search for a more suitable thread among 3 other random ones in order to
migrate the check there. The number of migrations remains very low (~1%)
and the checks load very fair across all threads (~1% as well). The new
parameter is called tune.max-checks-per-thread.

22 months agoMINOR: check: also consider the random other thread's active checks
Willy Tarreau [Wed, 23 Aug 2023 09:25:25 +0000 (11:25 +0200)] 
MINOR: check: also consider the random other thread's active checks

When checking if it's worth transferring a sleeping thread to another
random thread, let's also check if that random other thread has less
checks than the current one, which is another reason for transferring
the load there.

This commit adds a function "check_thread_cmp_load()" to compare two
threads' loads in order to simplify the decision taking.

The minimum active check count before starting to consider rebalancing
the load was now raised from 2 to 3, because tests show that at 15k
concurrent checks, at 2, 50% are evaluated for rebalancing and 30%
are rebalanced, while at 3, this is cut in half.

22 months agoMINOR: checks: maintain counters of active checks per thread
Willy Tarreau [Thu, 17 Aug 2023 14:25:28 +0000 (16:25 +0200)] 
MINOR: checks: maintain counters of active checks per thread

Let's keep two check counters per thread:
  - one for "active" checks, i.e. checks that are no more sleeping
    and are assigned to the thread. These include sleeping and
    running checks ;

  - one for "running" checks, i.e. those which are currently
    executing on the thread.

By doing so, we'll be able to spread the health checks load a bit better
and refrain from sending too many at once per thread. The counters are
atomic since a migration increments the target thread's active counter.
These numbers are reported in "show activity", which allows to check
per thread and globally how many checks are currently pending and running
on the system.

Ideally, we should only consider checks in the process of establishing
a connection since that's really the expensive part (particularly with
OpenSSL 3.0). But the inner layers are really not suitable to doing
this. However knowing the number of active checks is already a good
enough hint.

22 months agoMINOR: check/activity: collect some per-thread check activity stats
Willy Tarreau [Thu, 31 Aug 2023 14:06:10 +0000 (16:06 +0200)] 
MINOR: check/activity: collect some per-thread check activity stats

We now count the number of times a check was started on each thread
and the number of times a check was adopted. This helps understand
better what is observed regarding checks.

22 months agoMINOR: check: remember when we migrate a check
Willy Tarreau [Wed, 23 Aug 2023 09:58:24 +0000 (11:58 +0200)] 
MINOR: check: remember when we migrate a check

The goal here is to explicitly mark that a check was migrated so that
we don't do it again. This will allow us to perform other actions on
the target thread while still knowing that we don't want to be migrated
again. The new READY bit combine with SLEEPING to form 4 possible states:

 SLP  RDY   State      Description
  0    0    -          (reserved)
  0    1    RUNNING    Check is bound to current thread and running
  1    0    SLEEPING   Check is sleeping, not bound to a thread
  1    1    MIGRATING  Check is migrating to another thread

Thus we set READY upon migration, and check for it before migrating, this
is sufficient to prevent a second migration. To make things a bit clearer,
the SLEEPING bit was switched with FASTINTER so that SLEEPING and READY are
adjacent.

22 months agoMINOR: checks: pin the check to its thread upon wakeup
Willy Tarreau [Fri, 1 Sep 2023 05:27:56 +0000 (07:27 +0200)] 
MINOR: checks: pin the check to its thread upon wakeup

When a check leaves the sleeping state, we must pin it to the thread that
is processing it. It's normally always the case after the first execution,
but initial checks that start assigned to any thread (-1) could be assigned
much later, causing problems with planned changes involving queuing. Thus
better do it early, so that all threads start properly pinned.

22 months agoMINOR: checks: start the checks in sleeping state
Willy Tarreau [Thu, 17 Aug 2023 14:09:05 +0000 (16:09 +0200)] 
MINOR: checks: start the checks in sleeping state

The CHK_ST_SLEEPING state was introduced by commit d114f4a68 ("MEDIUM:
checks: spread the checks load over random threads") to indicate that
a check was not currently bound to a thread and that it could easily
be migrated to any other thread. However it did not start the checks
in this state, meaning that they were not redispatchable on startup.

Sometimes under heavy load (e.g. when using SSL checks with OpenSSL 3.0)
the cost of setting up new connections is so high that some threads may
experience connection timeouts on startup. In this case it's better if
they can transfer their excess load to other idle threads. By just
marking the check as sleeping upon startup, we can do this and
significantly reduce the number of failed initial checks.

22 months agoBUG/MINOR: checks: do not queue/wake a bounced check
Willy Tarreau [Fri, 1 Sep 2023 05:41:46 +0000 (07:41 +0200)] 
BUG/MINOR: checks: do not queue/wake a bounced check

A small issue was introduced with commit d114f4a68 ("MEDIUM: checks:
spread the checks load over random threads"): when a check is bounced
to another thread, its expiration time is set to TICK_ETERNITY. This
makes it show as not expired upon first wakeup on the next thread,
thus being detected as "woke up too early" and being instantly
rescheduled. Only this after this next wakeup it will be properly
considered.

Several approaches were attempted to fix this. The best one seems to
consist in resetting t->expire and expired upon wakeup, and changing
the !expired test for !tick_is_expired() so that we don't trigger on
this case.

This needs to be backported to 2.7.

22 months agoMINOR: activity: report the current run queue size
Willy Tarreau [Thu, 31 Aug 2023 15:43:14 +0000 (17:43 +0200)] 
MINOR: activity: report the current run queue size

While troubleshooting the causes of load spikes, it appeared that the
length of individual run queues was missing, let's add it to "show
activity".

22 months agoMEDIUM: server/ssl: pick another thread's session when we have none yet
Willy Tarreau [Mon, 21 Aug 2023 10:12:12 +0000 (12:12 +0200)] 
MEDIUM: server/ssl: pick another thread's session when we have none yet

The per-thread SSL context in servers causes a burst of connection
renegotiations on startup, both for the forwarded traffic and for the
health checks. Health checks have been seen to continue to cause SSL
rekeying for several minutes after a restart on large thread-count
machines. The reason is that the context is exlusively per-thread
and that the more threads there are, the more likely it is for a new
connection to start on a thread that doesn't have such a context yet.

In order to improve this situation, this commit ensures that a thread
starting an SSL connection to a server without a session will first
look at the last session that was updated by another thread, and will
try to use it. In order to minimize the contention, we're using a read
lock here to protect the data, and the first-level index is an integer
containing the thread number, that is always valid and may always be
dereferenced. This way the session retrieval algorithm becomes quite
simple:

  - if the last thread index is valid, then try to use the same session
    under a read lock ;
  - if any error happens, then atomically nuke the index so that other
    threads don't use it and the next one to update a connection updates
    it again

And for the ssl_sess_new_srv_cb(), we have this:

  - update the entry under a write lock if the new session is valid,
    otherwise kill it if the session is not valid;
  - atomically update the index if it was 0 and the new one is valid,
    otherwise atomically nuke it if the session failed.

Note that even if only the pointer is destroyed, the element will be
re-allocated by the next thread during the sess_new_srv_sb().

Right now a session is picked even if the SNI doesn't match, because
we don't know the SNI yet during ssl_sock_init(), but that's essentially
a matter of API, since connect_server() figures the SNI very early, then
calls conn_prepare() which calls ssl_sock_init(). Thus in the future we
could easily imaging storing a number of SNI-based contexts instead of
storing contexts per thread.

It could be worth backporting this to one LTS version after some
observation, though this is not strictly necessary. the current commit
depends on the following ones:

  BUG/MINOR: ssl_sock: fix possible memory leak on OOM
  MINOR: ssl_sock: avoid iterating realloc(+1) on stored context
  DOC: ssl: add some comments about the non-obvious session allocation stuff
  CLEANUP: ssl: keep a pointer to the server in ssl_sock_init()
  MEDIUM: ssl_sock: always use the SSL's server name, not the one from the tid
  MEDIUM: server/ssl: place an rwlock in the per-thread ssl server session
  MINOR: server/ssl: maintain an index of the last known valid SSL session
  MINOR: server/ssl: clear the shared good session index on failure
  MEDIUM: server/ssl: pick another thread's session when we have none yet

22 months agoMINOR: server/ssl: clear the shared good session index on failure
Willy Tarreau [Mon, 21 Aug 2023 10:04:01 +0000 (12:04 +0200)] 
MINOR: server/ssl: clear the shared good session index on failure

If we fail to set the session using SSL_set_session(), we want to quickly
erase our index from the shared one so that any other thread with a valid
session replaces it.

22 months agoMINOR: server/ssl: maintain an index of the last known valid SSL session
Willy Tarreau [Mon, 21 Aug 2023 09:55:42 +0000 (11:55 +0200)] 
MINOR: server/ssl: maintain an index of the last known valid SSL session

When a thread creates a new session for a server, if none was known yet,
we assign the thread id (hence the reused_sess index) to a shared variable
so that other threads will later be able to find it when they don't have
one yet. For now we only set and clear the pointer upon session creation,
we do not yet pick it.

Note that we could have done it per thread-group, so as to avoid any
cross-thread exchanges, but it's anticipated that this is essentially
used during startup, at a moment where the cost of inter-thread contention
is very low compared to the ability to restart at full speed, which
explains why instead we store a single entry.

22 months agoMEDIUM: server/ssl: place an rwlock in the per-thread ssl server session
Willy Tarreau [Mon, 21 Aug 2023 06:41:49 +0000 (08:41 +0200)] 
MEDIUM: server/ssl: place an rwlock in the per-thread ssl server session

The goal will be to permit a thread to update its session while having
it shared with other threads. For now we only place the lock and arrange
the code around it so that this is quite light. For now only the owner
thread uses this lock so there is no contention.

Note that there is a subtlety in the openssl API regarding
i2s_SSL_SESSION() in that it fills the area pointed to by its argument
with a dump of the session and returns a size that's equal to the
previously allocated one. As such, it does modify the shared area even
if that's not obvious at first glance.

22 months agoMEDIUM: ssl_sock: always use the SSL's server name, not the one from the tid
Willy Tarreau [Wed, 30 Aug 2023 10:02:33 +0000 (12:02 +0200)] 
MEDIUM: ssl_sock: always use the SSL's server name, not the one from the tid

In ssl_sock_set_servername(), we're retrieving the current server name
from the current thread, hoping it will not have changed. This is a
bit dangerous as strictly speaking it's not easy to prove that no other
connection had to use one between the moment it was retrieved in
ssl_sock_init() and the moment it's being read here. In addition, this
forces us to maintain one session per thread while this is not the real
need, in practice we only need one session per SNI. And the current model
prevents us from sharing sessions between threads.

This had been done in 2.5 via commit e18d4e828 ("BUG/MEDIUM: ssl: backend
TLS resumption with sni and TLSv1.3"), but as analyzed with William, it
turns out that a saner approach consists in keeping the call to
SSL_get_servername() there and instead to always assign the SNI to the
current SSL context via SSL_set_tlsext_host_name() immediately when the
session is retreived. This way the session and SNI are consulted atomically
and the host name is only checked from the session and not from possibly
changing elements.

As a bonus the rdlock that was added by that commit could now be removed,
though it didn't cost much.

22 months agoCLEANUP: ssl: keep a pointer to the server in ssl_sock_init()
Willy Tarreau [Wed, 30 Aug 2023 10:00:29 +0000 (12:00 +0200)] 
CLEANUP: ssl: keep a pointer to the server in ssl_sock_init()

We're using about 6 times "__objt_server(conn->target)" there, it's not
quite easy to read, let's keep a pointer to the server.

22 months agoDOC: ssl: add some comments about the non-obvious session allocation stuff
Willy Tarreau [Mon, 21 Aug 2023 09:17:10 +0000 (11:17 +0200)] 
DOC: ssl: add some comments about the non-obvious session allocation stuff

The SSL session allocation/reuse part is far from being trivial, and
there are some necessary tricks such as allocating then immediately
freeing that are required by the API due to internal refcount. All of
this is particularly hard to grasp, even with the scarce man pages.

Let's document a little bit what's granted and expected along this path
to help the reader later.

22 months agoMINOR: ssl_sock: avoid iterating realloc(+1) on stored context
Willy Tarreau [Mon, 21 Aug 2023 06:12:12 +0000 (08:12 +0200)] 
MINOR: ssl_sock: avoid iterating realloc(+1) on stored context

The SSL context storage in servers is per-thread, and the contents are
allocated for a length that is determined from the session. It turns out
that placing some traces there revealed that the realloc() that is called
to grow the area can be called multiple times in a row even for just
health checks, to grow the area by just one or two bytes. Given that
malloc() allocates in multiples of 8 or 16 anyway, let's round the
allocated size up to the nearest multiple of 8 to avoid this unneeded
operation.

22 months agoMINOR: sample: Add common TLV types as constants for fc_pp_tlv
Alexander Stephan [Wed, 16 Aug 2023 14:32:13 +0000 (16:32 +0200)] 
MINOR: sample: Add common TLV types as constants for fc_pp_tlv

This patch adds common TLV types as specified in the PPv2 spec.
We will use the suffix of the type, e.g., PP2_TYPE_AUTHORITY becomes AUTHORITY.

22 months agoMINOR: sample: Refactor fc_pp_unique_id by wrapping the generic TLV fetch
Alexander Stephan [Wed, 16 Aug 2023 14:22:25 +0000 (16:22 +0200)] 
MINOR: sample: Refactor fc_pp_unique_id by wrapping the generic TLV fetch

The fetch logic is redundant and can be simplified by simply
calling the generic fetch with the correct TLV ID set as an
argument, similar to fc_pp_authority.

22 months agoMINOR: sample: Refactor fc_pp_authority by wrapping the generic TLV fetch
Alexander Stephan [Wed, 16 Aug 2023 14:18:33 +0000 (16:18 +0200)] 
MINOR: sample: Refactor fc_pp_authority by wrapping the generic TLV fetch

We already have a call that can retreive an TLV with any value.
Therefore, the fetch logic is redundant and can be simplified
by simply calling the generic fetch with the correct TLV ID
set as an argument.

22 months agoMEDIUM: sample: Add fetch for arbitrary TLVs
Alexander Stephan [Wed, 16 Aug 2023 13:53:51 +0000 (15:53 +0200)] 
MEDIUM: sample: Add fetch for arbitrary TLVs

Based on the new, generic allocation infrastructure, a new sample
fetch fc_pp_tlv is introduced. It is an abstraction for existing
PPv2 TLV sample fetches. It takes any valid TLV ID as argument and
returns the value as a string, similar to fc_pp_authority and
fc_pp_unique_id.

22 months agoMEDIUM: connection: Generic, list-based allocation and look-up of PPv2 TLVs
Alexander Stephan [Wed, 16 Aug 2023 13:35:04 +0000 (15:35 +0200)] 
MEDIUM: connection: Generic, list-based allocation and look-up of PPv2 TLVs

In order to be able to implement fetches in the future that allow
retrieval of any TLVs, a new generic data structure for TLVs is introduced.

Existing TLV fetches for PP2_TYPE_AUTHORITY and PP2_TYPE_UNIQUE_ID are
migrated to use this new data structure. TLV related pools are updated
to not rely on type, but only on size. Pools accomodate the TLV list
element with their associated value. For now, two pools for 128 B and
256 B values are introduced. More fine-grained solutions are possible
in the future, if necessary.

22 months agoCLEANUP/MINOR: connection: Improve consistency of PPv2 related constants
Alexander Stephan [Mon, 14 Aug 2023 19:10:11 +0000 (21:10 +0200)] 
CLEANUP/MINOR: connection: Improve consistency of PPv2 related constants

This patch improves readability by scoping HA proxy related PPv2 constants
with a 'HA" prefix. Besides, a new constant for the length of a CRC32C
TLV is introduced. The length is derived from the PPv2 spec, so 32 Bit.

22 months agoMEDIUM: capabilities: enable support for Linux capabilities
Willy Tarreau [Tue, 29 Aug 2023 08:24:26 +0000 (10:24 +0200)] 
MEDIUM: capabilities: enable support for Linux capabilities

For a while there has been the constraint of having to run as root for
transparent proxying, and we're starting to see some cases where QUIC is
not running in socket-per-connection mode due to the missing capability
that would be needed to bind a privileged port. It's not realistic to
ask all QUIC users on port 443 to run as root, so instead let's provide
a basic support for capabilities at least on linux. The ones currently
supported are cap_net_raw, cap_net_admin and cap_net_bind_service. The
mechanism was made OS-specific with a dedicated file because it really
is. It can be easily refined later for other OSes if needed.

A new keyword "setcaps" is added to the global section, to enumerate the
capabilities that must be kept when switching from root to non-root. This
is ignored in other situations though. HAProxy has to be built with
USE_LINUX_CAP=1 for this to be supported, which is enabled by default
for linux-glibc, linux-glibc-legacy and linux-musl.

A good way to test this is to start haproxy with such a config:

    global
        uid 1000
        setcap cap_net_bind_service

    frontend test
        mode http
        timeout client 3s
        bind quic4@:443 ssl crt rsa+dh2048.pem allow-0rtt

and run it under "sudo strace -e trace=bind,setuid", then connecting
there from an H3 client. The bind() syscall must succeed despite the
user id having been switched.

22 months agoDOC: config: mention uid dependency on the tune.quic.socket-owner option
Willy Tarreau [Tue, 29 Aug 2023 08:22:46 +0000 (10:22 +0200)] 
DOC: config: mention uid dependency on the tune.quic.socket-owner option

This option defaults to "connection" but is also dependent on the user
being allowed to bind the specified port. Since QUIC can easily run on
non-privileged ports, usually this is not a problem, but if bound to port
443 it will usually fail. Let's mention this.

22 months agoBUG/MINOR: stream: protect stream_dump() against incomplete streams
Willy Tarreau [Mon, 28 Aug 2023 15:05:22 +0000 (17:05 +0200)] 
BUG/MINOR: stream: protect stream_dump() against incomplete streams

If a stream is interrupted during its initialization by a panic signal
and tries to dump itself, it may cause a crash during the dump due to
scf and/or scb not being fully initialized. This may also happen while
releasing an endpoint to attach a new one. The effect is that instead
of dying on an abort, the process dies on a segv. This race is ultra-
rare but totally possible. E.g:

  #0  se_fl_test (test=1, se=0x0) at include/haproxy/stconn.h:98
  #1  sc_ep_test (test=1, sc=0x7ff8d5cbd560) at include/haproxy/stconn.h:148
  #2  sc_conn (sc=0x7ff8d5cbd560) at include/haproxy/stconn.h:223
  #3  stream_dump (buf=buf@entry=0x7ff9507e7678, s=0x7ff4c40c8800, pfx=pfx@entry=0x55996c558cb3 ' ' <repeats 13 times>, eol=eol@entry=10 '\n') at src/stream.c:2840
  #4  0x000055996c493b42 in ha_task_dump (buf=buf@entry=0x7ff9507e7678, task=<optimized out>, pfx=pfx@entry=0x55996c558cb3 ' ' <repeats 13 times>) at src/debug.c:328
  #5  0x000055996c493edb in ha_thread_dump_one (thr=thr@entry=18, from_signal=from_signal@entry=0) at src/debug.c:227
  #6  0x000055996c493ff1 in ha_thread_dump (buf=buf@entry=0x7ff9507e7678, thr=thr@entry=18) at src/debug.c:270
  #7  0x000055996c494257 in ha_panic () at src/debug.c:430
  #8  ha_panic () at src/debug.c:411
  (...)
  #23 0x000055996c341fe8 in ssl_sock_close (conn=<optimized out>, xprt_ctx=0x7ff8dcae3880) at src/ssl_sock.c:6699
  #24 0x000055996c397648 in conn_xprt_close (conn=0x7ff8c297b0c0) at include/haproxy/connection.h:148
  #25 conn_full_close (conn=0x7ff8c297b0c0) at include/haproxy/connection.h:192
  #26 h1_release (h1c=0x7ff8c297b3c0) at src/mux_h1.c:1074
  #27 0x000055996c39c9f0 in h1_detach (sd=<optimized out>) at src/mux_h1.c:3502
  #28 0x000055996c474de4 in sc_detach_endp (scp=scp@entry=0x7ff9507e3148) at src/stconn.c:375
  #29 0x000055996c4752a5 in sc_reset_endp (sc=<optimized out>, sc@entry=0x7ff8d5cbd560) at src/stconn.c:475

Note that this cannot happen on "show sess" since a stream never leaves
process_stream in such an uninitialized state, thus it's really only the
crash dump that may cause this.

It should be backported to 2.8.

22 months agoBUG/MINOR: ssl/cli: can't find ".crt" files when replacing a certificate
William Lallemand [Mon, 28 Aug 2023 15:12:14 +0000 (17:12 +0200)] 
BUG/MINOR: ssl/cli: can't find ".crt" files when replacing a certificate

Bug was introduced by commit 26654 ("MINOR: ssl: add "crt" in the
cert_exts array").

When looking for a .crt directly in the cert_exts array, the
ssl_sock_load_pem_into_ckch() function will be called with a argument
which does not have its ".crt" extensions anymore.

If "ssl-load-extra-del-ext" is used this is not a problem since we try
to add the ".crt" when doing the lookup in the tree.

However when using directly a ".crt" without this option it will failed
looking for the file in the tree.

The fix removes the "crt" entry from the array since it does not seem to
be really useful without a rework of all the lookups.

Should fix issue #2265

Must be backported as far as 2.6.

22 months agoBUILD: pools: import plock.h to build even without thread support
Willy Tarreau [Sat, 26 Aug 2023 15:22:32 +0000 (17:22 +0200)] 
BUILD: pools: import plock.h to build even without thread support

In 2.9-dev4, commit 544c2f2d9 ("MINOR: pools: use EBO to wait for
unlock during pool_flush()") broke the thread-less build by calling
pl_wait_new_long() without explicitly including plock.h which is
normally included by thread.h when threads are enabled.

22 months agoBUILD: import: guard plock.h against multiple inclusion
Willy Tarreau [Sat, 26 Aug 2023 15:27:24 +0000 (17:27 +0200)] 
BUILD: import: guard plock.h against multiple inclusion

Surprisingly there's no include guard in plock.h though there is one in
atomic-ops.h. Let's add one, or we cannot risk including the file multiple
times.

22 months agoBUG/MEDIUM: mux-h2: fix crash when checking for reverse connection after error
Willy Tarreau [Sat, 26 Aug 2023 15:05:19 +0000 (17:05 +0200)] 
BUG/MEDIUM: mux-h2: fix crash when checking for reverse connection after error

If the connection is closed in h2_release(), which is indicated by ret<0, we
must not dereference conn anymore. This was introduced in 2.9-dev4 by commit
5053e8914 ("MEDIUM: h2: prevent stream opening before connection reverse
completed") and detected after a few hours of runtime thanks to running with
pool integrity checks and caller enabled. No backport is needed.

22 months ago[RELEASE] Released version 2.9-dev4 v2.9-dev4
Willy Tarreau [Fri, 25 Aug 2023 15:57:22 +0000 (17:57 +0200)] 
[RELEASE] Released version 2.9-dev4

Released version 2.9-dev4 with the following main changes :
    - DEV: flags/show-sess-to-flags: properly decode fd.state
    - BUG/MINOR: stktable: allow sc-set-gpt(0) from tcp-request connection
    - BUG/MINOR: stktable: allow sc-add-gpc from tcp-request connection
    - DOC: typo: fix sc-set-gpt references
    - SCRIPTS: git-show-backports: automatic ref and base detection with -m
    - REGTESTS: Do not use REQUIRE_VERSION for HAProxy 2.5+ (3)
    - DOC: jwt: Add explicit list of supported algorithms
    - BUILD: Makefile: add the USE_QUIC option to make help
    - BUILD: Makefile: add USE_QUIC_OPENSSL_COMPAT to make help
    - BUILD: Makefile: realigned USE_* options in make help
    - DEV: makefile: fix POSIX compatibility for "range" target
    - IMPORT: plock: also support inlining the int code
    - IMPORT: plock: always expose the inline version of the lock wait function
    - IMPORT: lorw: support inlining the wait call
    - MINOR: threads: inline the wait function for pthread_rwlock emulation
    - MINOR: atomic: make sure to always relax after a failed CAS
    - MINOR: pools: use EBO to wait for unlock during pool_flush()
    - BUILD/IMPORT: fix compilation with PLOCK_DISABLE_EBO=1
    - MINOR: quic+openssl_compat: Do not start without "limited-quic"
    - MINOR: quic+openssl_compat: Emit an alert for "allow-0rtt" option
    - BUG/MINOR: quic: allow-0rtt warning must only be emitted with quic bind
    - BUG/MINOR: quic: ssl_quic_initial_ctx() uses error count not error code
    - MINOR: pattern: do not needlessly lookup the LRU cache for empty lists
    - IMPORT: xxhash: update xxHash to version 0.8.2
    - MINOR: proxy: simplify parsing 'backend/server'
    - MINOR: connection: centralize init/deinit of backend elements
    - MEDIUM: connection: implement passive reverse
    - MEDIUM: h2: reverse connection after SETTINGS reception
    - MINOR: server: define reverse-connect server
    - MINOR: backend: only allow reuse for reverse server
    - MINOR: tcp-act: parse 'tcp-request attach-srv' session rule
    - REGTESTS: provide a reverse-server test
    - MINOR: tcp-act: define optional arg name for attach-srv
    - MINOR: connection: use attach-srv name as SNI reuse parameter on reverse
    - REGTESTS: provide a reverse-server test with name argument
    - MINOR: proto: define dedicated protocol for active reverse connect
    - MINOR: connection: extend conn_reverse() for active reverse
    - MINOR: proto_reverse_connect: parse rev@ addresses for bind
    - MINOR: connection: prepare init code paths for active reverse
    - MEDIUM: proto_reverse_connect: bootstrap active reverse connection
    - MINOR: proto_reverse_connect: handle early error before reversal
    - MEDIUM: h2: implement active connection reversal
    - MEDIUM: h2: prevent stream opening before connection reverse completed
    - REGTESTS: write a full reverse regtest
    - BUG/MINOR: h2: fix reverse if no timeout defined
    - CI: fedora: fix "dnf" invocation syntax
    - BUG/MINOR: hlua_fcn: potentially unsafe stktable_data_ptr usage
    - DOC: lua: fix Sphinx warning from core.get_var()
    - DOC: lua: fix core.register_action typo
    - BUG/MINOR: ssl_sock: fix possible memory leak on OOM
    - MEDIUM: map/acl: Improve pat_ref_set() efficiency (for "set-map", "add-acl" action perfs)
    - MEDIUM: map/acl: Improve pat_ref_set_elt() efficiency (for "set-map", "add-acl"action perfs)
    - MEDIUM: map/acl: Accelerate several functions using pat_ref_elt struct ->head list
    - MEDIUM: map/acl: Replace map/acl spin lock by a read/write lock.
    - DOC: map/acl: Remove the comments about map/acl performance issue
    - DOC: Explanation of be_name and be_id fetches
    - MINOR: connection: simplify removal of idle conns from their trees
    - MINOR: server: move idle tree insert in a dedicated function
    - MAJOR: connection: purge idle conn by last usage

22 months agoMAJOR: connection: purge idle conn by last usage
Amaury Denoyelle [Mon, 21 Aug 2023 16:32:29 +0000 (18:32 +0200)] 
MAJOR: connection: purge idle conn by last usage

Backend idle connections are purged on a recurring occurence during the
process lifetime. An estimated number of needed connections is
calculated and the excess is removed periodically.

Before this patch, purge was done directly using the idle then the safe
connection tree of a server instance. This has a major drawback to take
no account of a specific ordre and it may removed functional connections
while leaving ones which will fail on the next reuse.

The problem can be worse when using criteria to differentiate idle
connections such as the SSL SNI. In this case, purge may remove
connections with a high rate of reusing while leaving connections with
criteria never matched once, thus reducing drastically the reuse rate.

To improve this, introduce an alternative storage for idle connection
used in parallel of the idle/safe trees. Now, each connection inserted
in one of this tree is also inserted in the new list at
`srv_per_thread.idle_conn_list`. This guarantees that recently used
connection is present at the end of the list.

During the purge, use this list instead of idle/safe trees. Remove first
connection in front of the list which were not reused recently. This
will ensure that connection that are frequently reused are not purged
and should increase the reuse rate, particularily if distinct idle
connection criterias are in used.

22 months agoMINOR: server: move idle tree insert in a dedicated function
Amaury Denoyelle [Fri, 25 Aug 2023 13:48:39 +0000 (15:48 +0200)] 
MINOR: server: move idle tree insert in a dedicated function

Define a new function _srv_add_idle(). This is a simple wrapper to
insert a connection in the server idle tree. This is reserved for simple
usage and require to idle_conns lock. In most cases,
srv_add_to_idle_list() should be used.

This patch does not have any functional change. However, it will help
with the next patch as idle connection will be always inserted in a list
as secondary storage along with idle/safe trees.

22 months agoMINOR: connection: simplify removal of idle conns from their trees
Amaury Denoyelle [Mon, 21 Aug 2023 12:24:17 +0000 (14:24 +0200)] 
MINOR: connection: simplify removal of idle conns from their trees

Small change of API for conn_delete_from_tree(). Now the connection
instance is taken as argument instead of its inner node.

No functional change introduced with this commit. This simplifies
slightly invocation of conn_delete_from_tree(). The most useful changes
is that this function will be extended in the next patch to be able to
remove the connection from its new idle list at the same time as in its
idle tree.

22 months agoDOC: Explanation of be_name and be_id fetches
Sébastien Gross [Wed, 23 Aug 2023 09:49:11 +0000 (05:49 -0400)] 
DOC: Explanation of be_name and be_id fetches

The be_name and be_id fetches contain data related to the current
backend and can be used in frontend responses. Yet, in cases where
no backend is used due to a local response or backend selection
failure, these fetches retain details of the current frontend.

This patch enhances the clarity of the values provided by these
fetches.

Signed-off-by: Sébastien Gross <sgross@haproxy.com>
22 months agoDOC: map/acl: Remove the comments about map/acl performance issue
Frédéric Lécaille [Thu, 24 Aug 2023 14:02:03 +0000 (16:02 +0200)] 
DOC: map/acl: Remove the comments about map/acl performance issue

These commits have improved the performances of "set-map", "add-acl"
http rule actions:

   MINOR: map/acl: Improve pat_ref_set_elt() efficiency (for "set-map", "add-acl" actions perfs)
   MINOR: map/acl: Improve pat_ref_set() efficiency (for "set-map", "add-acl" action perfs)

22 months agoMEDIUM: map/acl: Replace map/acl spin lock by a read/write lock.
Frédéric Lécaille [Mon, 21 Aug 2023 16:44:24 +0000 (18:44 +0200)] 
MEDIUM: map/acl: Replace map/acl spin lock by a read/write lock.

Replace ->lock type of pat_ref struct by HA_RWLOCK_T.
Replace all calls to HA_SPIN_LOCK() (resp. HA_SPIN_UNLOCK()) by HA_RWLOCK_WRLOCK()
(resp. HA_RWLOCK_WRUNLOCK()) when a write access is required.
There is only one read access which is needed. This is in the "show map" command
callback, cli_io_handler_map_lookup() where a HA_SPIN_LOCK() call is replaced
by HA_RWLOCK_RDLOCK() (resp. HA_SPIN_UNLOCK() by HA_RWLOCK_RDUNLOCK).
Replace HA_SPIN_INIT() calls by HA_RWLOCK_INIT() calls.

22 months agoMEDIUM: map/acl: Accelerate several functions using pat_ref_elt struct ->head list
Frédéric Lécaille [Tue, 22 Aug 2023 16:32:13 +0000 (18:32 +0200)] 
MEDIUM: map/acl: Accelerate several functions using pat_ref_elt struct ->head list

Replace as much as possible list_for_each*() around ->head list, member of
pat_ref_elt struct by use of its ->ebpt_root member which is an ebtree.

22 months agoMEDIUM: map/acl: Improve pat_ref_set_elt() efficiency (for "set-map", "add-acl"action...
Frédéric Lécaille [Wed, 23 Aug 2023 13:58:26 +0000 (15:58 +0200)] 
MEDIUM: map/acl: Improve pat_ref_set_elt() efficiency (for "set-map", "add-acl"action perfs)

Store a pointer to the expression (struct pattern_expr) into the data structure
used to chain/store the map element references (struct pat_ref_elt) , e.g. the
struct pattern_tree when stored into an ebtree or struct pattern_list when
chained to a list.

Modify pat_ref_set_elt() to stop inspecting all the expressions attached to a map
and to look for the <elt> element passed as parameter to retrieve the sample data
to be parsed. Indeed, thanks to the pointer added above to each pattern tree nodes
or list elements, they all can be inspected directly from the <elt> passed as
parameter and its ->tree_head and ->list_head member: the pattern tree nodes are
stored into elt->tree_head, and the pattern list elements are chained to
elt->list_head list. This inspection was also the job of pattern_find_smp() which
is no more useful. This patch removes the code of this function.

22 months agoMEDIUM: map/acl: Improve pat_ref_set() efficiency (for "set-map", "add-acl" action...
Frédéric Lécaille [Tue, 22 Aug 2023 14:52:47 +0000 (16:52 +0200)] 
MEDIUM: map/acl: Improve pat_ref_set() efficiency (for "set-map", "add-acl" action perfs)

Organize reference to pattern element of map (struct pat_ref_elt) into an ebtree:
  - add an eb_root member to the map (pat_ref struct) and an ebpt_node to its
    element (pat_ref_elt struct),
  - modify the code to insert these nodes into their ebtrees each time they are
    allocated. This is done in pat_ref_append().

Note that ->head member (struct list) of map (struct pat_ref) is not removed
could have been removed. This is not the case because still necessary to dump
the map contents from the CLI in the order the map elememnts have been inserted.

This patch also modifies http_action_set_map() which is the callback at least
used by "set-map" action. The pat_ref_elt element returned by pat_ref_find_elt()
is no more ignored, but reused if not NULL by pat_ref_set() as first element to
lookup from. This latter is also modified to use the ebtree attached to the map
in place of the ->head list attached to each map element (pat_ref_elt struct).

Also modify pat_ref_find_elt() to makes it use ->eb_root map ebtree added to the
map by this patch in place of inspecting all the elements with a strcmp() call.

22 months agoBUG/MINOR: ssl_sock: fix possible memory leak on OOM
Willy Tarreau [Mon, 21 Aug 2023 06:45:35 +0000 (08:45 +0200)] 
BUG/MINOR: ssl_sock: fix possible memory leak on OOM

That's the classical realloc() issue: if it returns NULL, the old area
is not freed but we erase the pointer. It was brought by commit e18d4e828
("BUG/MEDIUM: ssl: backend TLS resumption with sni and TLSv1.3"), and
should be backported where this commit was backported.

22 months agoDOC: lua: fix core.register_action typo
Aurelien DARRAGON [Wed, 23 Aug 2023 15:38:42 +0000 (17:38 +0200)] 
DOC: lua: fix core.register_action typo

"converter" was used in place of "action" as a result of a copy-paste
error probably.

Also, rephrasing the "actions" keyword explanation to prevent confusion
between action name (which is the name of new action about to be created)
and action facilities where we want to expose the new action.

This could be backported to every stable versions.

22 months agoDOC: lua: fix Sphinx warning from core.get_var()
Aurelien DARRAGON [Wed, 23 Aug 2023 15:47:10 +0000 (17:47 +0200)] 
DOC: lua: fix Sphinx warning from core.get_var()

Since f034139bc0 ("MINOR: lua: Allow reading "proc." scoped vars from
LUA core."), a new Sphinx warning is emitted when generating the lua doc:

  "WARNING: Field list ends without a blank line; unexpected unindent."

This is due to a missing space after the line break continuation, sphinx
parser is very restrictive unfortunately!

Suppressing the warning and fixing the html output at the same time by
adding the missing space.

22 months agoBUG/MINOR: hlua_fcn: potentially unsafe stktable_data_ptr usage
Aurelien DARRAGON [Tue, 22 Aug 2023 09:03:06 +0000 (11:03 +0200)] 
BUG/MINOR: hlua_fcn: potentially unsafe stktable_data_ptr usage

As reported by Coverity in GH #2253, stktable_data_ptr() usage in
hlua_stktable_dump() func is potentially unsafe because
stktable_data_ptr() may return NULL and the returned value is
dereferenced as-is without precautions.

In practise, this should not happen because some error checking was
already performed prior to calling stktable_data_ptr(). But since we're
using the safe stktable_data_ptr() function, all the error checking is
already done within the function, thus all we need to do is check ptr
against NULL instead to protect against NULL dereferences.

This should be backported in every stable versions.

22 months agoCI: fedora: fix "dnf" invocation syntax
Ilya Shipitsin [Fri, 25 Aug 2023 06:20:24 +0000 (08:20 +0200)] 
CI: fedora: fix "dnf" invocation syntax

In 39e205302e8afb68d954e17944fad5f8c1587287 I erroneously used
"dnf git" instead of "dnf install"

22 months agoBUG/MINOR: h2: fix reverse if no timeout defined
Amaury Denoyelle [Thu, 24 Aug 2023 15:32:50 +0000 (17:32 +0200)] 
BUG/MINOR: h2: fix reverse if no timeout defined

h2c.task is not allocated in h2_init() if timeout client/server is not
defined depending on the connection side. This caused crash on
connection reverse due to systematic requeuing of h2c.task in
h2_conn_reverse().

To fix this, check h2c.task in h2_conn_reverse(). If old timeout was
undefined but new one is, h2c.task must be allocated as it was not in
h2_init(). On the opposite situation, if old timeout was defined and new
one is not, h2c.task is freed. In this case, or if neither timeout are
defined, skip the task requeuing.

This bug is easily reproduced by using reverse bind or server with
undefined timeout client/server depending on the connection reverse
direction.

This bug has been introduced by reverse connect support.
No need to backport it.

22 months agoREGTESTS: write a full reverse regtest
Amaury Denoyelle [Mon, 14 Aug 2023 09:10:06 +0000 (11:10 +0200)] 
REGTESTS: write a full reverse regtest

This test instantiates two haproxy instances :
* first one uses a reverse server with two bind pub and priv
* second one uses a reverse bind to initiate connection to priv endpoint

On startup, only first haproxy instance is up. A client send a request
to pub endpoint and should receive a HTTP 503 as no connection are
available on the reverse server.

Second haproxy instance is started. A delay of 3 seconds is inserted to
wait for the connection between the two LBs. Then a client retry the
request and this time should receive a HTTP 200 reusing the bootstrapped
connection.

22 months agoMEDIUM: h2: prevent stream opening before connection reverse completed
Amaury Denoyelle [Mon, 14 Aug 2023 14:38:23 +0000 (16:38 +0200)] 
MEDIUM: h2: prevent stream opening before connection reverse completed

HTTP/2 demux must be handled with care for active reverse connection.
Until accept has been completed, it should be forbidden to handle
HEADERS frame as session is not yet ready to handle streams.

To implement this, use the flag H2_CF_DEM_TOOMANY which blocks demux
process. This flag is automatically set just after conn_reverse()
invocation. The flag is removed on rev_accept_conn() callback via a new
H2 ctl enum. H2 tasklet is woken up to restart demux process.

As a side-effect, reporting in H2 mux may be blocked as demux functions
are used to convert error status at the connection level with
CO_FL_ERROR. To ensure error is reported for a reverse connection, check
h2c_is_dead() specifically for this case in h2_wake(). This change also
has its own side-effect : h2c_is_dead() conditions have been adjusted to
always exclude !h2c->conn->owner condition which is always true for
reverse connection or else H2 mux may kill them unexpectedly.

22 months agoMEDIUM: h2: implement active connection reversal
Amaury Denoyelle [Mon, 7 Aug 2023 12:55:32 +0000 (14:55 +0200)] 
MEDIUM: h2: implement active connection reversal

Implement active reverse on h2_conn_reverse().

Only minimal steps are done here : HTTP version session counters are
incremented on the listener instance. Also, the connection is inserted
in the mux_stopping_list to ensure it will be actively closed on process
shutdown/listener suspend.

22 months agoMINOR: proto_reverse_connect: handle early error before reversal
Amaury Denoyelle [Mon, 14 Aug 2023 08:52:50 +0000 (10:52 +0200)] 
MINOR: proto_reverse_connect: handle early error before reversal

An error can occured on a reverse connection before accept is completed.
In this case, no parent session can be notified. Instead, wake up the
receiver task on conn_create_mux().

As a counterpart to this, receiver task is extended to match CO_FL_ERROR
flag on pending connection. In this case, the onnection is freed. The
task is then requeued with a 1 second delay to start a new reverse
connection attempt.

22 months agoMEDIUM: proto_reverse_connect: bootstrap active reverse connection
Amaury Denoyelle [Wed, 23 Aug 2023 15:16:07 +0000 (17:16 +0200)] 
MEDIUM: proto_reverse_connect: bootstrap active reverse connection

Implement active reverse connection initialization. This is done through
a new task stored in the receiver structure. This task is instantiated
via bind callback and first woken up via enable callback.

Task handler is separated into two halves. On the first step, a new
connection is allocated and stored in <pend_conn> member of the
receiver. This new client connection will proceed to connect using the
server instance referenced in the bind_conf.

When connect has successfully been executed and HTTP/2 connection is
ready for exchange after SETTINGS, reverse_connect task is woken up. As
<pend_conn> is still set, the second halve is executed which only
execute listener_accept(). This will in turn execute accept_conn
callback which is defined to return the pending connection.

The task is automatically requeued inside accept_conn callback if bind
maxconn is not yet reached. This allows to specify how many connection
should be opened. Each connection is instantiated and reversed serially
one by one until maxconn is reached.

conn_free() has been modified to handle failure if a reverse connection
fails before being accepted. In this case, no session exists to notify
about the failure. Instead, reverse_connect task is requeud with a 1
second delay, giving time to fix a possible network issue. This will
allow to attempt a new connection reverse.

Note that for the moment connection rebinding after accept is disabled
for simplicity. Extra operations are required to migrate an existing
connection and its stack to a new thread which will be implemented
later.

22 months agoMINOR: connection: prepare init code paths for active reverse
Amaury Denoyelle [Wed, 23 Aug 2023 16:02:51 +0000 (18:02 +0200)] 
MINOR: connection: prepare init code paths for active reverse

When an active reverse connection is initialized, it has no stream-conn
attached to it contrary to other backend connections. This forces to add
extra check on stream existence in conn_create_mux() and h2_init().

There is also extra checks required for session_accept_fd() after
reverse and accept is done. This is because contrary to other frontend
connections, reversed connections have already initialized their mux and
transport layers. This forces us to skip the majority of
session_accept_fd() initialization part.

Finally, if session_accept_fd() is interrupted due to an early error, a
reverse connection cannot be freed directly or else mux will remain
alone. Instead, the mux destroy callback is used to free all connection
elements properly.

22 months agoMINOR: proto_reverse_connect: parse rev@ addresses for bind
Amaury Denoyelle [Mon, 7 Aug 2023 15:56:36 +0000 (17:56 +0200)] 
MINOR: proto_reverse_connect: parse rev@ addresses for bind

Implement parsing for "rev@" addresses on bind line. On config parsing,
server name is stored on the bind_conf.

Several new callbacks are defined on reverse_connect protocol to
complete parsing. listen callback is used to retrieve the server
instance from the bind_conf server name. If found, the server instance
is stored on the receiver. Checks are implemented to ensure HTTP/2
protocol only is used by the server.

22 months agoMINOR: connection: extend conn_reverse() for active reverse
Amaury Denoyelle [Mon, 7 Aug 2023 12:46:24 +0000 (14:46 +0200)] 
MINOR: connection: extend conn_reverse() for active reverse

Implement active reverse support inside conn_reverse(). This is used to
transfer the connection from the backend to the frontend side.

A new flag is defined CO_FL_REVERSED which is set just after this
transition. This will be used to identify connections which were
reversed but not yet accepted.

22 months agoMINOR: proto: define dedicated protocol for active reverse connect
Amaury Denoyelle [Tue, 1 Aug 2023 15:27:06 +0000 (17:27 +0200)] 
MINOR: proto: define dedicated protocol for active reverse connect

A new protocol named "reverse_connect" is created. This will be used to
instantiate connections that are opened by a reverse bind.

For the moment, only a minimal set of callbacks are defined with no real
work. This will be extended along the next patches.

22 months agoREGTESTS: provide a reverse-server test with name argument
Amaury Denoyelle [Tue, 22 Aug 2023 15:01:57 +0000 (17:01 +0200)] 
REGTESTS: provide a reverse-server test with name argument

This regtest is similar to the previous one, except the optional name
argument is specified.

An extra haproxy instance is used as a gateway for clear/TLS as vtest
does not support TLS natively.

A first request is done by specifying a name which does not match the
idle connection SNI. This must result in a HTTP 503. Then the correct
name is used which must result in a 200.

22 months agoMINOR: connection: use attach-srv name as SNI reuse parameter on reverse
Amaury Denoyelle [Tue, 22 Aug 2023 14:58:55 +0000 (16:58 +0200)] 
MINOR: connection: use attach-srv name as SNI reuse parameter on reverse

On connection passive reverse from frontend to backend, its hash node is
calculated to be able to select it from the idle server pool. If
attach-srv rule defined an associated name, reuse it as the value for
SNI prehash.

This change allows a client to select a reverse connection by its name
by configuring its server line with a SNI to permit this.

22 months agoMINOR: tcp-act: define optional arg name for attach-srv
Amaury Denoyelle [Mon, 31 Jul 2023 14:21:00 +0000 (16:21 +0200)] 
MINOR: tcp-act: define optional arg name for attach-srv

Add an optional argument 'name' for attach-srv rule. This contains an
expression which will be used as an identifier inside the server idle
pool after reversal. To match this connection for a future transfer
through the server, the SNI server parameter must match this name. If no
name is defined, match will only occur with an empty SNI value.

For the moment, only the parsing step is implemented. An extra check is
added to ensure that the reverse server uses SSL with a SNI. Indeed, if
name is defined but server does not uses a SNI, connections will never
be selected on reused after reversal due to a hash mismatch.

22 months agoREGTESTS: provide a reverse-server test
Amaury Denoyelle [Thu, 27 Jul 2023 16:43:30 +0000 (18:43 +0200)] 
REGTESTS: provide a reverse-server test

Test support for reverse server. This can be test without the opposite
haproxy reversal support though a combination of VTC clients used to
emit HTTP/2 responses after connection.

This test ensures that first we get a 503 when connecting on a reverse
server with no idle connection. Then a dummy VTC client is connected to
act as as server. It is then expected that the same request is achieved
with a 200 this time.

22 months agoMINOR: tcp-act: parse 'tcp-request attach-srv' session rule
Amaury Denoyelle [Tue, 25 Jul 2023 13:59:30 +0000 (15:59 +0200)] 
MINOR: tcp-act: parse 'tcp-request attach-srv' session rule

Create a new tcp-request session rule 'attach-srv'.

The parsing handler is used to extract the server targetted with the
notation 'backend/server'. The server instance is stored in the act_rule
instance under the new union variant 'attach_srv'.

Extra checks are implemented in parsing to ensure attach-srv is only
used for proxy in HTTP mode and with listeners/server with no explicit
protocol reference or HTTP/2 only.

The action handler itself is really simple. It assigns the stored server
instance to the 'reverse' member of the connection instance. It will be
used in a future patch to implement passive reverse-connect.

22 months agoMINOR: backend: only allow reuse for reverse server
Amaury Denoyelle [Fri, 18 Aug 2023 14:02:35 +0000 (16:02 +0200)] 
MINOR: backend: only allow reuse for reverse server

A reverse server relies solely on its pool of idle connection to
transfer requests which will be populated through a new tcp-request rule
'attach-srv'.

Several changes are required on connect_server() to implement this.
First, reuse mode is forced to always for this type of server. Then, if
no idle connection is found, the request will be aborted. This results
with a 503 HTTP error code, similarly to when no server is available.

22 months agoMINOR: server: define reverse-connect server
Amaury Denoyelle [Tue, 25 Jul 2023 13:16:55 +0000 (15:16 +0200)] 
MINOR: server: define reverse-connect server

Implement reverse-connect server. This server type cannot instantiate
its own connection on transfer. Instead, it can only reuse connection
from its idle pool. These connections will be populated using the future
'tcp-request session attach-srv' rule.

A reverse-connect has no address. Instead, it uses a new custom server
notation with '@' character prefix. For the moment, only '@reverse' is
defined. An extra check is implemented to ensure server is used in a
HTTP proxy.

22 months agoMEDIUM: h2: reverse connection after SETTINGS reception
Amaury Denoyelle [Thu, 27 Jul 2023 13:58:08 +0000 (15:58 +0200)] 
MEDIUM: h2: reverse connection after SETTINGS reception

Reverse connection after SETTINGS reception if it was set as reversable.
This operation is done in a new function h2_conn_reverse(). It regroups
common changes which are needed for both reversal direction :
H2_CF_IS_BACK is set or unset and timeouts are inverted.

For the moment, only passive reverse is fully implemented. Once done,
the connection instance is directly inserted in its targetted server
pool. It can then be used immediately for future transfers using this
server.

22 months agoMEDIUM: connection: implement passive reverse
Amaury Denoyelle [Thu, 27 Jul 2023 13:56:34 +0000 (15:56 +0200)] 
MEDIUM: connection: implement passive reverse

Define a new method conn_reverse(). This method is used to reverse a
connection from frontend to backend or vice-versa depending on its
initial status.

For the moment, passive reverse only is implemented. This covers the
transition from frontend to backend side. The connection is detached
from its owner session which can then be freed. Then the connection is
linked to the server instance.

only for passive connection on
frontend to transfer them on the backend side. This requires to free the
connection session after detaching it from.

22 months agoMINOR: connection: centralize init/deinit of backend elements
Amaury Denoyelle [Thu, 27 Jul 2023 13:30:07 +0000 (15:30 +0200)] 
MINOR: connection: centralize init/deinit of backend elements

A connection contains extra elements which are only used for the backend
side. Regroup their allocation and deallocation in two new functions
named conn_backend_init() and conn_backend_deinit().

No functional change is introduced with this commit. The new functions
are reused in place of manual alloc/dealloc in conn_new() / conn_free().
This patch will be useful for reverse connect support with connection
conversion from backend to frontend side and vice-versa.

22 months agoMINOR: proxy: simplify parsing 'backend/server'
Amaury Denoyelle [Mon, 7 Aug 2023 14:24:24 +0000 (16:24 +0200)] 
MINOR: proxy: simplify parsing 'backend/server'

Several CLI handlers use a server argument specified with the format
'<backend>/<server>'. The parsing of this arguement is done in two
steps, first splitting the string with '/' delimiter and then use
get_backend_server() to retrieve the server instance.

Refactor this code sections with the following changes :
* splitting is reimplented using ist API
* get_backend_server() is removed. Instead use the already existing
  proxy_be_by_name() then server_find_by_name() which contains
  duplicated code with the now removed function.

No functional change occurs with this commit. However, it will be useful
to add new configuration options reusing the same '<backend>/<server>'
for reverse connect.

22 months agoIMPORT: xxhash: update xxHash to version 0.8.2
Willy Tarreau [Thu, 24 Aug 2023 10:01:06 +0000 (12:01 +0200)] 
IMPORT: xxhash: update xxHash to version 0.8.2

Peter Varkoly reported a build issue on ppc64le in xxhash.h. Our version
(0.8.1) was the last one 9 months ago, and since then this specific issue
was addressed in 0.8.2, so let's apply the maintenance update.

This should be backported to 2.8 and 2.7.

22 months agoMINOR: pattern: do not needlessly lookup the LRU cache for empty lists
Willy Tarreau [Tue, 22 Aug 2023 05:22:05 +0000 (07:22 +0200)] 
MINOR: pattern: do not needlessly lookup the LRU cache for empty lists

If a pattern list is empty, there's no way we can find its elements in
the pattern cache, so let's avoid this expensive lookup. This can happen
for ACLs or maps loaded from files that may optionally be empty for
example. Doing so improves the request rate by roughly 10% for a single
such match for only 8 threads. That's normal because the LRU cache
pre-creates an entry that is about to be committed for the case the list
lookup succeeds after a miss, so we bypass all this.

22 months agoBUG/MINOR: quic: ssl_quic_initial_ctx() uses error count not error code
William Lallemand [Mon, 21 Aug 2023 13:22:57 +0000 (15:22 +0200)] 
BUG/MINOR: quic: ssl_quic_initial_ctx() uses error count not error code

ssl_quic_initial_ctx() is supposed to use error count and not errror
code.

Bug was introduced by 557706b3 ("MINOR: quic: Initialize TLS contexts
for QUIC openssl wrapper").

No backport needed.

22 months agoBUG/MINOR: quic: allow-0rtt warning must only be emitted with quic bind
William Lallemand [Mon, 21 Aug 2023 11:51:56 +0000 (13:51 +0200)] 
BUG/MINOR: quic: allow-0rtt warning must only be emitted with quic bind

When built with USE_QUIC_OPENSSL_COMPAT, a warning is emitted when using
allow-0rtt. However this warning is emitted for every allow-0rtt
keywords on the bind line which is confusing, it must only be done in
case the bind is a quic one. Also this does not handle the case where
the allow-0rtt keyword is in the crt-list.

This patch moves the warning to ssl_quic_initial_ctx() in order to emit
the warning in every useful cases.

22 months agoMINOR: quic+openssl_compat: Emit an alert for "allow-0rtt" option
Frédéric Lécaille [Thu, 17 Aug 2023 08:53:34 +0000 (10:53 +0200)] 
MINOR: quic+openssl_compat: Emit an alert for "allow-0rtt" option

QUIC 0-RTT is not supported when haproxy is linked against an TLS stack with
limited QUIC support (OpenSSL).

Modify the "allow-0rtt" option callback to make it emit a warning if set on
a QUIC listener "bind" line.

22 months agoMINOR: quic+openssl_compat: Do not start without "limited-quic"
Frédéric Lécaille [Thu, 17 Aug 2023 08:15:09 +0000 (10:15 +0200)] 
MINOR: quic+openssl_compat: Do not start without "limited-quic"

Add a check for limited-quic in check_config_validity() when compiled
with USE_QUIC_OPENSSL_COMPAT so that we prevent a config from starting
accidentally with limited QUIC support. If a QUIC listener is found
when using the compatibility mode and limited-quic is not set, an error
message is reported explaining that the SSL library is not compatible
and proposing the user to enable limited-quic if that's what they want,
and the startup fails.

This partially reverts commit 7c730803d ("MINOR: quic: Warning for
OpenSSL wrapper QUIC bindings without "limited-quic"") since a warning
was not sufficient.

22 months agoBUILD/IMPORT: fix compilation with PLOCK_DISABLE_EBO=1
Amaury Denoyelle [Thu, 17 Aug 2023 09:04:42 +0000 (11:04 +0200)] 
BUILD/IMPORT: fix compilation with PLOCK_DISABLE_EBO=1

Compilation is broken due to missing __pl_wait_unlock_long() definition
when building with PLOCK_DISABLE_EBO=1. This has been introduced since
the following commit which activates the inlining version of
pl_wait_unlock_long() :
  commit 071d689a514dac522ac3654f53bc22214b5716d0
  MINOR: threads: inline the wait function for pthread_rwlock emulation

Add an extra check on PLOCK_DISABLE_EBO before choosing the inline or
default version of pl_wait_unlock_long() to fix this.

22 months agoMINOR: pools: use EBO to wait for unlock during pool_flush()
Willy Tarreau [Thu, 17 Aug 2023 07:04:35 +0000 (09:04 +0200)] 
MINOR: pools: use EBO to wait for unlock during pool_flush()

pool_flush() could become a source of contention on the pool's free list
if there are many competing thread using that pool. Let's make sure we
use EBO and not just a simple CPU relaxation there, to avoid disturbing
them.

22 months agoMINOR: atomic: make sure to always relax after a failed CAS
Willy Tarreau [Thu, 17 Aug 2023 06:59:15 +0000 (08:59 +0200)] 
MINOR: atomic: make sure to always relax after a failed CAS

There were a few places left where we forgot to call __ha_cpu_relax()
after a failed CAS, in the HA_ATOMIC_UPDATE_{MIN,MAX} macros, and in
a few sync_* API macros (the same as above plus HA_ATOMIC_CAS and
HA_ATOMIC_XCHG). Let's add them now.

This could have been a cause of contention, particularly with
process_stream() calling stream_update_time_stats() which uses 8 of them
in a call (4 for the server, 4 for the proxy). This may be a possible
explanation for the high CPU consumption reported in GH issue #2251.

This should be backported at least to 2.6 as it's harmless.

22 months agoMINOR: threads: inline the wait function for pthread_rwlock emulation
Willy Tarreau [Wed, 16 Aug 2023 20:51:37 +0000 (22:51 +0200)] 
MINOR: threads: inline the wait function for pthread_rwlock emulation

When using pthread_rwlock emulation, contention is reported on
pl_wait_unlock_long(). This is really not convenient to analyse what is
happening. Now plock supports inlining the wait call for just the lorw
functions by enabling PLOCK_LORW_INLINE_WAIT. Let's do this so that now
the wait time will be precisely reported as either pthread_rwlock_rdlock()
or pthread_rwlock_wrlock() depending on the contended function, but no
more on pl_wait_unlock_long(), which will still be reported for all
other locks.

22 months agoIMPORT: lorw: support inlining the wait call
Willy Tarreau [Wed, 16 Aug 2023 20:40:05 +0000 (22:40 +0200)] 
IMPORT: lorw: support inlining the wait call

Now when PLOCK_LORW_INLINE_WAIT is defined, the pl_wait_unlock_long()
calls in pl_lorw_rdlock() and pl_lorw_wrlock() will be inlined so that
all the CPU time is accounted for in the calling function.

This is plock upstream commit c993f81d581732a6eb8fe3033f21970420d21e5e.

22 months agoIMPORT: plock: always expose the inline version of the lock wait function
Willy Tarreau [Wed, 16 Aug 2023 20:29:45 +0000 (22:29 +0200)] 
IMPORT: plock: always expose the inline version of the lock wait function

Doing so will allow to expose the time spent in certain highly
contended functions, which can be desirable for more accurate CPU
profiling. For example this could be done in locking functions that
are already not inlined so that they are the ones being reported as
those consuming the CPU instead of just pl_wait_unlock_long().

This is plock upstream commit 7505c2e2c8c4aa0ab8f52a2288e1334ae6412be4.

22 months agoIMPORT: plock: also support inlining the int code
Willy Tarreau [Wed, 16 Aug 2023 20:25:34 +0000 (22:25 +0200)] 
IMPORT: plock: also support inlining the int code

Commit 9db830b ("plock: support inlining exponential backoff code")
added an option to support inlining of the wait code for longs but
forgot to do it for ints. Let's do it now.

This is plock upstream commit b1f9f0d252fa40577d11cfb2bc0a809d6960a297.

22 months agoDEV: makefile: fix POSIX compatibility for "range" target
Aurelien DARRAGON [Wed, 16 Aug 2023 16:16:16 +0000 (18:16 +0200)] 
DEV: makefile: fix POSIX compatibility for "range" target

make "range" which was introduced with 06d34d4 ("DEV: makefile: add a
new "range" target to iteratively build all commits") does not work with
POSIX shells (namely: bourne shell), and will fail with this kind of
errors:

   |/bin/sh: 6: Syntax error: "(" unexpected (expecting ")")
   |make: *** [Makefile:1226: range] Error 2

This is because arrays and arithmetic expressions which are used for the
"range" target are not supported by sh (unlike bash and other "modern"
interpreters).

However the make "all" target already complies with POSIX, so in this
commit we try to make "range" target POSIX compliant to ensure that the
makefile works as expected on systems where make uses /bin/sh as default
intepreter and where /bin/sh points to POSIX shell.

22 months agoBUILD: Makefile: realigned USE_* options in make help
William Lallemand [Wed, 16 Aug 2023 22:03:01 +0000 (00:03 +0200)] 
BUILD: Makefile: realigned USE_* options in make help

Realigned the USE_* options of `make help` because of the length of
USE_QUIC_OPENSSL_COMPAT.

No backport needed.

22 months agoBUILD: Makefile: add USE_QUIC_OPENSSL_COMPAT to make help
William Lallemand [Wed, 16 Aug 2023 22:01:27 +0000 (00:01 +0200)] 
BUILD: Makefile: add USE_QUIC_OPENSSL_COMPAT to make help

Add the missing USE_QUIC_OPENSSL_COMPAT option to `make help`.

No backport needed.

22 months agoBUILD: Makefile: add the USE_QUIC option to make help
William Lallemand [Wed, 16 Aug 2023 21:41:15 +0000 (23:41 +0200)] 
BUILD: Makefile: add the USE_QUIC option to make help

Add the missing "USE_QUIC" option to `make help`.

Must be backported as far as 2.4.

22 months agoDOC: jwt: Add explicit list of supported algorithms
Remi Tricot-Le Breton [Thu, 10 Aug 2023 14:11:27 +0000 (16:11 +0200)] 
DOC: jwt: Add explicit list of supported algorithms

Add explicit list of algorithms supported by the jwt_verify converter.

22 months agoREGTESTS: Do not use REQUIRE_VERSION for HAProxy 2.5+ (3)
Tim Duesterhus [Mon, 7 Aug 2023 13:46:23 +0000 (15:46 +0200)] 
REGTESTS: Do not use REQUIRE_VERSION for HAProxy 2.5+ (3)

Introduced in:

424981cde REGTEST: add ifnone-forwardfor test
b015b3eb1 REGTEST: add RFC7239 forwarded header tests

see also:

fbbbc33df REGTESTS: Do not use REQUIRE_VERSION for HAProxy 2.5+

22 months agoSCRIPTS: git-show-backports: automatic ref and base detection with -m
Willy Tarreau [Mon, 14 Aug 2023 11:03:46 +0000 (13:03 +0200)] 
SCRIPTS: git-show-backports: automatic ref and base detection with -m

When running with -m (check for missing backports) we often have to fill
lots of information that can be determined automatically the vast majority
of the time:
  - restart point (last cherry-picked ID from one of the last commits)
  - current branch (HEAD)
  - reference branch (the one that contains most of the last commits)

These elements are not that hard to determine, so let's make sure we
can fall back to them when running in missing mode.

The reference branch is guessed by looking at the upstream branch that
most frequently contains some of the last 10 commits. It can be inaccurate
if multiple branches exist with these commits, or when upstream changes
due to a non-LTS branch disappearing in the middle of the series, in which
case passing "-r" will help. But most of the time it works OK. It also gives
precedence to local branches over remote ones for such choices. A test in
2.4 at commit 793a4b520 correctly shows 2.6/master as the upstream despite
2.5 having been used for the early ones of the tag.

For the restart point, we assume that the most recent commit that was
backported serves as a reference (and not the most recently backported
commit). This means that the usual case where an old commit was found
to be missing will not fool the analysis. Commits are inspected from
2 commits before the last tag, and reordered from the parent's tree
to see which one is the last one.

With this, it's sufficient to issue "git-show-backports -q -m" to get
the list of backports from the upstream branch, restarting from the
last backported one.

22 months agoDOC: typo: fix sc-set-gpt references
Johannes Naab [Thu, 10 Aug 2023 12:10:37 +0000 (14:10 +0200)] 
DOC: typo: fix sc-set-gpt references

Only sc-inc-gpc and sc-set-gpt do exist. The mix-up sc-inc-gpt crept in
in 71d189219 (DOC: config: Rework and uniformize how TCP/HTTP rules are
documented, 2021-10-14) and got copied in a92480462 (MINOR: http-rules:
Add missing actions in http-after-response ruleset, 2023-01-05).

22 months agoBUG/MINOR: stktable: allow sc-add-gpc from tcp-request connection
Aurelien DARRAGON [Wed, 9 Aug 2023 15:39:29 +0000 (17:39 +0200)] 
BUG/MINOR: stktable: allow sc-add-gpc from tcp-request connection

Following the previous commit's logic, we enable the use of sc-add-gpc
from tcp-request connection since it was probably forgotten in the first
place for sc-set-gpt0, and since sc-add-gpc was inspired from it, it also
lacks its.

As sc-add-gpc was implemented in 5a72d03a58 ("MINOR: stick-table: implement
the sc-add-gpc() action"), this should only be backported to 2.8

22 months agoBUG/MINOR: stktable: allow sc-set-gpt(0) from tcp-request connection
Aurelien DARRAGON [Wed, 9 Aug 2023 15:23:32 +0000 (17:23 +0200)] 
BUG/MINOR: stktable: allow sc-set-gpt(0) from tcp-request connection

Both the documentation and original developer intents seem to suggest
that sc-set-gpt/sc-set-gpt0 actions should be available from
tcp-request connection.

Yet because it was probably forgotten when expr support was added to
sc-set-gpt0 in 0d7712dff0 ("MINOR: stick-table: allow sc-set-gpt0 to
set value from an expression") it doesn't work and will report this
kind of errors:
 "internal error, unexpected rule->from=0, please report this bug!"

Fixing the code to comply with the documentation and the expected
behavior.

This must be backported to every stable versions.

[for < 2.5, as only sc-set-gpt0 existed back then, the patch must be
manually applied to skip irrelevant parts]

22 months agoDEV: flags/show-sess-to-flags: properly decode fd.state
Willy Tarreau [Mon, 14 Aug 2023 06:47:43 +0000 (08:47 +0200)] 
DEV: flags/show-sess-to-flags: properly decode fd.state

fd.state is reported without the "0x" prefix in show sess, let's support
this during decoding.

This may be backported to all versions supporting this utility.

23 months ago[RELEASE] Released version 2.9-dev3 v2.9-dev3
Willy Tarreau [Sat, 12 Aug 2023 17:59:27 +0000 (19:59 +0200)] 
[RELEASE] Released version 2.9-dev3

Released version 2.9-dev3 with the following main changes :
    - BUG/MINOR: ssl: OCSP callback only registered for first SSL_CTX
    - BUG/MEDIUM: h3: Properly report a C-L header was found to the HTX start-line
    - MINOR: sample: add pid sample
    - MINOR: sample: implement act_conn sample fetch
    - MINOR: sample: accept_date / request_date return %Ts / %tr timestamp values
    - MEDIUM: sample: implement us and ms variant of utime and ltime
    - BUG/MINOR: sample: check alloc_trash_chunk() in conv_time_common()
    - DOC: configuration: describe Td in Timing events
    - MINOR: sample: implement the T* timer tags from the log-format as fetches
    - DOC: configuration: add sample fetches for timing events
    - BUG/MINOR: quic: Possible crash when acknowledging Initial v2 packets
    - MINOR: quic: Export QUIC traces code from quic_conn.c
    - MINOR: quic: Export QUIC CLI code from quic_conn.c
    - MINOR: quic: Move TLS related code to quic_tls.c
    - MINOR: quic: Add new "QUIC over SSL" C module.
    - MINOR: quic: Add a new quic_ack.c C module for QUIC acknowledgements
    - CLEANUP: quic: Defined but no more used function (quic_get_tls_enc_levels())
    - MINOR: quic: Split QUIC connection code into three parts
    - CLEANUP: quic: quic_conn struct cleanup
    - MINOR: quic; Move the QUIC frame pool to its proper location
    - BUG/MINOR: chunk: fix chunk_appendf() to not write a zero if buffer is full
    - BUG/MEDIUM: h3: Be sure to handle fin bit on the last DATA frame
    - DOC: configuration: rework the custom log format table
    - BUG/MINOR: quic+openssl_compat: Non initialized TLS encryption levels
    - CLEANUP: acl: remove cache_idx from acl struct
    - REORG: cfgparse: extract curproxy as a global variable
    - MINOR: acl: add acl() sample fetch
    - BUILD: cfgparse: keep a single "curproxy"
    - BUG/MEDIUM: bwlim: Reset analyse expiration date when then channel analyse ends
    - MEDIUM: stream: Reset response analyse expiration date if there is no analyzer
    - BUG/MINOR: htx/mux-h1: Properly handle bodyless responses when splicing is used
    - BUG/MEDIUM: quic: consume contig space on requeue datagram
    - BUG/MINOR: http-client: Don't forget to commit changes on HTX message
    - CLEANUP: stconn: Move comment about sedesc fields on the field line
    - REGTESTS: http: Create a dedicated script to test spliced bodyless responses
    - REGTESTS: Test SPLICE feature is enabled to execute script about splicing
    - BUG/MINOR: quic: reappend rxbuf buffer on fake dgram alloc error
    - BUILD: quic: fix wrong potential NULL dereference
    - MINOR: h3: abort request if not completed before full response
    - BUG/MAJOR: http-ana: Get a fresh trash buffer for each header value replacement
    - CLEANUP: quic: Remove quic_path_room().
    - MINOR: quic: Amplification limit handling sanitization.
    - MINOR: quic: Move some counters from [rt]x quic_conn anonymous struct
    - MEDIUM: quic: Send CONNECTION_CLOSE packets from a dedicated buffer.
    - MINOR: quic: Use a pool for the connection ID tree.
    - MEDIUM: quic: Allow the quic_conn memory to be asap released.
    - MINOR: quic: Release asap quic_conn memory (application level)
    - MINOR: quic: Release asap quic_conn memory from ->close() xprt callback.
    - MINOR: quic: Warning for OpenSSL wrapper QUIC bindings without "limited-quic"
    - REORG: http: move has_forbidden_char() from h2.c to http.h
    - BUG/MAJOR: h3: reject header values containing invalid chars
    - MINOR: mux-h2/traces: also suggest invalid header upon parsing error
    - MINOR: ist: add new function ist_find_range() to find a character range
    - MINOR: http: add new function http_path_has_forbidden_char()
    - MINOR: h2: pass accept-invalid-http-request down the request parser
    - REGTESTS: http-rules: add accept-invalid-http-request for normalize-uri tests
    - BUG/MINOR: h1: do not accept '#' as part of the URI component
    - BUG/MINOR: h2: reject more chars from the :path pseudo header
    - BUG/MINOR: h3: reject more chars from the :path pseudo header
    - REGTESTS: http-rules: verify that we block '#' by default for normalize-uri
    - DOC: clarify the handling of URL fragments in requests
    - BUG/MAJOR: http: reject any empty content-length header value
    - BUG/MINOR: http: skip leading zeroes in content-length values
    - BUG/MEDIUM: mux-h1: fix incorrect state checking in h1_process_mux()
    - BUG/MEDIUM: mux-h1: do not forget EOH even when no header is sent
    - BUILD: mux-h1: shut a build warning on clang from previous commit
    - DEV: makefile: add a new "range" target to iteratively build all commits
    - CI: do not use "groupinstall" for Fedora Rawhide builds
    - CI: get rid of travis-ci wrapper for Coverity scan
    - BUG/MINOR: quic: mux started when releasing quic_conn
    - BUG/MINOR: quic: Possible crash in quic_cc_conn_io_cb() traces.
    - MINOR: quic: Add a trace for QUIC conn fd ready for receive
    - BUG/MINOR: quic: Possible crash when issuing "show fd/sess" CLI commands
    - BUG/MINOR: quic: Missing tasklet (quic_cc_conn_io_cb) memory release (leak)
    - BUG/MEDIUM: quic: fix tasklet_wakeup loop on connection closing
    - BUG/MINOR: hlua: fix invalid use of lua_pop on error paths
    - MINOR: hlua: add hlua_stream_ctx_prepare helper function
    - BUG/MEDIUM: hlua: streams don't support mixing lua-load with lua-load-per-thread
    - MAJOR: threads/plock: update the embedded library again
    - MINOR: stick-table: move the task_queue() call outside of the lock
    - MINOR: stick-table: move the task_wakeup() call outside of the lock
    - MEDIUM: stick-table: change the ref_cnt atomically
    - MINOR: stick-table: better organize the struct stktable
    - MEDIUM: peers: update ->commitupdate out of the lock using a CAS
    - MEDIUM: peers: drop then re-acquire the wrlock in peer_send_teachmsgs()
    - MEDIUM: peers: only read-lock peer_send_teachmsgs()
    - MEDIUM: stick-table: use a distinct lock for the updates tree
    - MEDIUM: stick-table: touch updates under an upgradable read lock
    - MEDIUM: peers: drop the stick-table lock before entering peer_send_teachmsgs()
    - MINOR: stick-table: move the update lock into its own cache line
    - CLEANUP: stick-table: slightly reorder the stktable struct
    - BUILD: defaults: use __WORDSIZE not LONGBITS for MAX_THREADS_PER_GROUP
    - MINOR: tools: make ptr_hash() support 0-bit outputs
    - MINOR: tools: improve ptr hash distribution on 64 bits
    - OPTIM: tools: improve hash distribution using a better prime seed
    - OPTIM: pools: use exponential back-off on shared pool allocation/release
    - OPTIM: pools: make pool_get_from_os() / pool_put_to_os() not update ->allocated
    - MINOR: pools: introduce the use of multiple buckets
    - MEDIUM: pools: spread the allocated counter over a few buckets
    - MEDIUM: pools: move the used counter over a few buckets
    - MEDIUM: pools: move the needed_avg counter over a few buckets
    - MINOR: pools: move the failed allocation counter over a few buckets
    - MAJOR: pools: move the shared pool's free_list over multiple buckets
    - MINOR: pools: make pool_evict_last_items() use pool_put_to_os_no_dec()
    - BUILD: pools: fix build error on clang with inline vs forceinline

23 months agoBUILD: pools: fix build error on clang with inline vs forceinline
Willy Tarreau [Sat, 12 Aug 2023 17:58:17 +0000 (19:58 +0200)] 
BUILD: pools: fix build error on clang with inline vs forceinline

clang is more picky than gcc regarding duplicate "inline". The functions
declared with "forceinline" don't need to have "inline" since it's already
in the macro.

23 months agoMINOR: pools: make pool_evict_last_items() use pool_put_to_os_no_dec()
Willy Tarreau [Sat, 12 Aug 2023 10:34:09 +0000 (12:34 +0200)] 
MINOR: pools: make pool_evict_last_items() use pool_put_to_os_no_dec()

The bucket is already known, no need to calculate it again. Let's just
include the lower level functions.

23 months agoMAJOR: pools: move the shared pool's free_list over multiple buckets
Willy Tarreau [Mon, 24 Jul 2023 15:02:22 +0000 (17:02 +0200)] 
MAJOR: pools: move the shared pool's free_list over multiple buckets

This aims at further reducing the contention on the free_list when using
global pools. The free_list pointer now appears for each bucket, and both
the alloc and the release code skip to a next bucket when ending on a
contended entry. The default entry used for allocations and releases
depend on the thread ID so that locality is preserved as much as possible
under low contention.

It would be nice to improve the situation to make sure that releases to
the shared pools doesn't consider the first entry's pointer but only an
argument that would be passed and that would correspond to the bucket in
the thread's cache. This would reduce computations and make sure that the
shared cache only contains items whose pointers match the same bucket.
This was not yet done. One possibility could be to keep the same splitting
in the local cache.

With this change, an h2load test with 5 * 160 conns & 40 streams on 80
threads that was limited to 368k RPS with the shared cache jumped to
3.5M RPS for 8 buckets, 4M RPS for 16 buckets, 4.7M RPS for 32 buckets
and 5.5M RPS for 64 buckets.

23 months agoMINOR: pools: move the failed allocation counter over a few buckets
Willy Tarreau [Mon, 24 Jul 2023 14:38:09 +0000 (16:38 +0200)] 
MINOR: pools: move the failed allocation counter over a few buckets

The failed allocation counter cannot depend on a pointer, but since it's
a perpetually increasing counter and not a gauge, we don't care where
it's incremented. Thus instead we're hashing on the TID. There's no
contention there anyway, but it's better not to waste the room in
the pool's heads and to move that with the other counters.

23 months agoMEDIUM: pools: move the needed_avg counter over a few buckets
Willy Tarreau [Mon, 24 Jul 2023 14:18:25 +0000 (16:18 +0200)] 
MEDIUM: pools: move the needed_avg counter over a few buckets

That's the same principle as for ->allocated and ->used. Here we return
the summ of the raw values, so the result still needs to be fed to
swrate_avg(). It also means that we now use the local ->used instead
of the global one for the calculations and do not need to call pool_used()
anymore on fast paths. The number of samples should likely be divided by
the number of buckets, but that's not done yet (better observe first).

A function pool_needed_avg() was added to report aggregated values for
the "show pools" command.

With this change, an h2load made of 5 * 160 conn * 40 streams on 80
threads raised from 1.5M RPS to 6.7M RPS.