14616 Commits

Author SHA1 Message Date
Frédéric Lécaille
a56054e438 MINOR: quic: Probe several packet number space upon timer expiration
When the loss detection timer expires, we SHOULD include new data in
our probing packets (RFC 9002 par 6.2.4. Sending Probe Packets).
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
db6a4727cf MINOR: quic: Probe Initial packet number space more often
Especially when the PTO expires for Handshake packet number space and when
Initial packets are still flying (for QUIC servers).
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
3bb457c4ba MINOR: quic: Speeding up Handshake Completion
According to RFC 9002 par. 6.2.3. when receving duplicate Initial CRYPTO
data a server may a packet containing non unacknowledged before the PTO
expiry.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
63556772cc MINOR: quic: qc_prep_pkts() code moving
Move the switch default case code out of the switch to improve the readibily.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
5732062cd2 MINOR: quic: Useless test in qc_prep_pkts()
These tests were there to initiate PTO probing but they are not correct.
Furthermore they may break the PTO probing process and lead to useless packet
building.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
dd51da599e MINOR: quic: Wrong packet number space trace in qc_prep_pkts()
It was always the first packet number space information which was dumped.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
466e9da145 MINOR: quic: Remove nb_pto_dgrams quic_conn struct member
For now on we rely on tx->pto_probe pktns struct member to inform
the packet building function we want to probe.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
22576a2e55 MINOR: quic: Wrong ack_delay compution before calling quic_loss_srtt_update()
RFC 9002 5.3. Estimating smoothed_rtt and rttvar:
MUST use the lesser of the acknowledgment delay and the peer's max_ack_delay
after the handshake is confirmed.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
dc90c07715 MINOR: quic: Wrong loss time computation in qc_packet_loss_lookup()
This part as been modified by the RFC since our first implementation.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
22cfd83890 MINOR: quic: Add trace about in flight bytes by packet number space
This parameter is useful to diagnose packet loss detection issues.
2022-01-04 17:30:00 +01:00
Frédéric Lécaille
fde2a98dd1 MINOR: quic: Wrong traces after rework
TRACE_*() macros must take a quic_conn struct as first argument.
2022-01-04 17:30:00 +01:00
Christopher Faulet
7bf46bb9a9 BUG/MEDIUM: http-ana: Preserve response's FLT_END analyser on L7 retry
When a filter is attached on a stream, the FLT_END analyser must not be
removed from the response channel on L7 retry. It is especially important
because CF_FLT_ANALYZE flag is still set. This means the synchronization
between the two sides when the filter ends can be blocked. Depending on the
timing, this can freeze the stream infinitely or lead to a spinning loop.

Note that the synchronization between the two sides at the end of the
analysis was introduced because the stream was reused in HTTP between two
transactions. But, since the HTX was introduced, a new stream is created for
each transaction. So it is probably possible to remove this step for 2.2 and
higher.

This patch must be backported as far as 2.0.
2022-01-04 10:56:04 +01:00
David Carlier
ae5c42f4d0 BUILD/MINOR: tools: solaris build fix on dladdr.
dladdr takes a mutable address on this platform.
2022-01-03 14:43:51 +01:00
Ilya Shipitsin
5e87bcf870 CLEANUP: assorted typo fixes in the code and comments This is 29th iteration of typo fixes 2022-01-03 14:40:58 +01:00
Willy Tarreau
1513c5479a MEDIUM: pools: release cached objects in batches
With this patch pool_evict_last_items builds clusters of up to
CONFIG_HAP_POOL_CLUSTER_SIZE entries so that accesses to the shared
pools are reduced by CONFIG_HAP_POOL_CLUSTER_SIZE and the inter-
thread contention is reduced by as much..
2022-01-02 19:35:26 +01:00
Willy Tarreau
43937e920f MEDIUM: pools: start to batch eviction from local caches
Since previous patch we can forcefully evict multiple objects from the
local cache, even when evicting basd on the LRU entries. Let's define
a compile-time configurable setting to batch releasing of objects. For
now we set this value to 8 items per round.

This is marked medium because eviction from the LRU will slightly change
in order to group the last items that are freed within a single cache
instead of accurately scanning only the oldest ones exactly in their
order of appearance. But this is required in order to evolve towards
batched removals.
2022-01-02 19:35:26 +01:00
Willy Tarreau
a0b5831eed MEDIUM: pools: centralize cache eviction in a common function
We currently have two functions to evict cold objects from local caches:
pool_evict_from_local_cache() to evict from a single cache, and
pool_evict_from_local_caches() to evict oldest objects from all caches.

The new function pool_evict_last_items() focuses on scanning oldest
objects from a pool and releasing a predefined number of them, either
to the shared pool or to the system. For now they're evicted one at a
time, but the next step will consist in creating clusters.
2022-01-02 19:35:26 +01:00
Willy Tarreau
337410c5a4 MINOR: pools: pass the objects count to pool_put_to_shared_cache()
This is in order to let the caller build the cluster of items to be
released. For now single items are released hence the count is always
1.
2022-01-02 19:35:26 +01:00
Willy Tarreau
148160b027 MINOR: pools: prepare pool_item to support chained clusters
In order to support batched allocations and releases, we'll need to
prepare chains of items linked together and that can be atomically
attached and detached at once. For this we implement a "down" pointer
in each pool_item that points to the other items belonging to the same
group. For now it's always NULL though freeing functions already check
them when trying to release everything.
2022-01-02 19:35:26 +01:00
Willy Tarreau
361e31e3fe MEDIUM: pool: compute the number of evictable entries once per pool
In pool_evict_from_local_cache() we used to check for room left in the
pool for each and every object. Now we compute the value before entering
the loop and keep into a local list what has to be released, and call
the OS-specific functions for the other ones.

It should already save some cycles since it's not needed anymore to
recheck for the pool's filling status. But the main expected benefit
comes from the ability to pre-construct a list of all releasable
objects, that will later help with grouping them.
2022-01-02 19:35:26 +01:00
Willy Tarreau
c16ed3b090 MINOR: pool: introduce pool_item to represent shared pool items
In order to support batch allocation from/to shared pools, we'll have to
support a specific representation for pool objects. The new pool_item
structure will be used for this. For now it only contains a "next"
pointer that matches exactly the current storage model. The few functions
that deal with the shared pool entries were adapted to use the new type.
There is no functionality difference at this point.
2022-01-02 19:35:26 +01:00
Willy Tarreau
b46674a283 MINOR: pool: check for pool's fullness outside of pool_put_to_shared_cache()
Instead of letting pool_put_to_shared_cache() pass the object to the
underlying OS layer when there's no more room, let's have the caller
check if the pool is full and either call pool_put_to_shared_cache()
or call pool_free_nocache().

Doing this sensibly simplifies the code as this function now only has
to deal with a pool and an item and only for cases where there are
local caches and shared caches. As the code was simplified and the
calls more isolated, the function was moved to pool.c.

Note that it's only called from pool_evict_from_local_cache{,s}() and
that a part of its logic might very well move there when dealing with
batches.
2022-01-02 19:35:26 +01:00
Willy Tarreau
afe2c4a1fc MINOR: pool: allocate from the shared cache through the local caches
One of the thread scaling challenges nowadays for the pools is the
contention on the shared caches. There's never any situation where we
have a shared cache and no local cache anymore, so we can technically
afford to transfer objects from the shared cache to the local cache
before returning them to the user via the regular path. This adds a
little bit more work per object per miss, but will permit batch
processing later.

This patch simply moves pool_get_from_shared_cache() to pool.c under
the new name pool_refill_local_from_shared(), and this function does
not return anything but it places the allocated object at the head of
the local cache.
2022-01-02 19:27:57 +01:00
Willy Tarreau
8c4927098e CLEANUP: pools: get rid of the POOL_LINK macro
The POOL_LINK macro is now only used for debugging, and it still requires
ifdefs around, which needlessly complicates the code. Let's replace it
and the calling code with a new pair of macros: POOL_DEBUG_SET_MARK()
and POOL_DEBUG_CHECK_MARK(), that respectively store and check the pool
pointer in the extra location at the end of the pool. This removes 4
pairs of ifdefs in the middle of the code.
2022-01-02 12:44:19 +01:00
Willy Tarreau
799f6143ca CLEANUP: pools: do not use the extra pointer to link shared elements
This practice relying on POOL_LINK() dates from the era where there were
no pool caches, but given that the structures are a bit more complex now
and that pool caches do not make use of this feature, it is totally
useless since released elements have already been overwritten, and yet
it complicates the architecture and prevents from making simplifications
and optimizations. Let's just get rid of this feature. The pointer to
the origin pool is preserved though, as it helps detect incorrect frees
and serves as a canary for overflows.
2022-01-02 12:44:19 +01:00
Willy Tarreau
d5ec100661 MINOR: pools: always evict oldest objects first in pool_evict_from_local_cache()
For an unknown reason, despite the comment stating that we were evicting
oldest objects first from the local caches, due to the use of LIST_NEXT,
the newest were evicted, since pool_put_to_cache() uses LIST_INSERT().

Some tests on 16 threads show that evicting oldest objects instead can
improve performance by 0.5-1% especially when using shared pools.
2022-01-02 12:40:14 +01:00
William Lallemand
e69563fd8e BUG/MEDIUM: ssl: free the ckch instance linked to a server
This patch unlinks and frees the ckch instance linked to a server during
the free of this server.

This could have locked certificates in a "Used" state when removing
servers dynamically from the CLI. And could provoke a segfault once we
try to dynamically update the certificate after that.

This must be backported as far as 2.4.
2021-12-30 16:56:52 +01:00
William Lallemand
231610ad9c BUG/MINOR: ssl: free the fields in srv->ssl_ctx
A lot of free are missing in ssl_sock_free_srv_ctx(), this could result
in memory leaking when removing dynamically a server via the CLI.

This must be backported in every branches, by removing the fields that
does not exist in the previous branches.
2021-12-30 13:43:04 +01:00
William Lallemand
2c776f1c30 BUG/MEDIUM: ssl: initialize correctly ssl w/ default-server
This bug was introduced by d817dc73 ("MEDIUM: ssl: Load client
certificates in a ckch for backend servers") in which the creation of
the SSL_CTX for a server was moved to the configuration parser when
using a "crt" keyword instead of being done in ssl_sock_prepare_srv_ctx().

The patch 0498fa40 ("BUG/MINOR: ssl: Default-server configuration ignored by
server") made it worse by setting the same SSL_CTX for every servers
using a default-server. Resulting in any SSL option on a server applied
to every server in its backend.

This patch fixes the issue by reintroducing a string which store the
path of certificate inside the server structure, and loading the
certificate in ssl_sock_prepare_srv_ctx() again.

This is a quick fix to backport, a cleaner way can be achieve by always
creating the SSL_CTX in ssl_sock_prepare_srv_ctx() and splitting
properly the ssl_sock_load_srv_cert() function.

This patch fixes issue #1488.

Must be backported as far as 2.4.
2021-12-29 14:42:16 +01:00
Willy Tarreau
654726db5a MINOR: debug: add support for -dL to dump library names at boot
This is a second help to dump loaded library names late at boot, once
external code has already been initialized. The purpose is to provide
a format that makes it easy to pass to "tar" to produce an archive
containing the executable and the list of dependencies. For example
if haproxy is started as "haproxy -f foo.cfg", a config check only
will suffice to quit before starting, "-q" will be used to disable
undesired output messages, and -dL will be use to dump libraries.
This will result in such a command to trivially produce a tarball
of loaded libraries:

   ./haproxy -q -c -dL -f foo.cfg | tar -T - -hzcf archive.tgz
2021-12-28 17:07:13 +01:00
Willy Tarreau
6ab7b21a11 MINOR: debug: add ability to dump loaded shared libraries
Many times core dumps reported by users who experience trouble are
difficult to exploit due to missing system libraries. Sometimes,
having just a list of loaded libraries and their respective addresses
can already provide some hints about some problems.

This patch makes a step in that direction by adding a new "show libs"
command that will try to enumerate the list of object files that are
loaded in memory, relying on the dynamic linker for this. It may also
be used to detect that some foreign code embarks other undesired libs
(e.g. some external Lua modules).

At the moment it's only supported on glibc when USE_DL is set, but it's
implemented in a way that ought to make it reasonably easy to be extended
to other platforms.
2021-12-28 16:59:00 +01:00
Willy Tarreau
b4ff6f4ae9 BUG/MEDIUM: peers: properly skip conn_cur from incoming messages
The approach used for skipping conn_cur in commit db2ab8218 ("MEDIUM:
stick-table: never learn the "conn_cur" value from peers") was wrong,
it only works with simple tables but as soon as frequency counters or
arrays are exchanged after conn_cur, the stream is desynchronized and
incorrect values are read. This is because the fields have a variable
length depending on their types and cannot simply be skipped by a
"continue" statement.

Let's change the approach to make sure we continue to completely parse
these local-only fields, and only drop the value at the moment we're
about to store them, since this is exactly the intent.

A simpler approach could consist in having two sets of stktable_data_ptr()
functions, one for retrieval and one for storage, and to make the store
function return a NULL pointer for local types. For now this doesn't
seem worth the trouble.

This fixes github issue #1497. Thanks to @brenc for the reproducer.

This must be backported to 2.5.
2021-12-24 13:48:39 +01:00
Willy Tarreau
266d540549 BUG/MEDIUM: backend: fix possible sockaddr leak on redispatch
A subtle change of target address allocation was introduced with commit
68cf3959b ("MINOR: backend: rewrite alloc of stream target address") in
2.4. Prior to this patch, a target address was allocated by function
assign_server_address() only if none was previously allocated. After
the change, the allocation became unconditional. Most of the time it
makes no difference, except when we pass multiple times through
connect_server() with SF_ADDR_SET cleared.

The most obvious fix would be to avoid allocating that address there
when already set, but the root cause is that since introduction of
dynamically allocated addresses, the SF_ADDR_SET flag lies. It can
be cleared during redispatch or during a queue redistribution without
the address being released.

This patch instead gives back all its correct meaning to SF_ADDR_SET
and guarantees that when not set no address is allocated, by freeing
that address at the few places the flag is cleared. The flag could
even be removed so that only the address is checked but that would
require to touch many areas for no benefit.

The easiest way to test it is to send requests to a proxy with l7
retries enabled, which forwards to a server returning 500:

  defaults
    mode http
    timeout client 1s
    timeout server 1s
    timeout connect 1s
    retry-on all-retryable-errors
    retries 1
    option redispatch

  listen proxy
    bind *:5000
    server app 0.0.0.0:5001

  frontend dummy-app
    bind :5001
    http-request return status 500

Issuing "show pools" on the CLI will show that pool "sockaddr" grows
as requests are redispatched, and remains stable with the fix. Even
"ps" will show that the process' RSS grows by ~160B per request.

This fix will need to be backported to 2.4. Note that before 2.5,
there's no strm->si[1].dst, strm->target_addr must be used instead.

This addresses github issue #1499. Special thanks to Daniil Leontiev
for providing a well-documented reproducer.
2021-12-24 11:50:01 +01:00
Amaury Denoyelle
9979d0d1ea BUG/MINOR: quic: fix potential use of uninit pointer
Properly initialized the ssl_sock_ctx pointer in qc_conn_init. This is
required to avoid to set an undefined pointer in qc.xprt_ctx if argument
*xprt_ctx is NULL.
2021-12-23 16:33:47 +01:00
Amaury Denoyelle
c6fab98f9b BUG/MINOR: quic: fix potential null dereference
This is not a real issue because found_in_dcid can not be set if qc is
NULL.
2021-12-23 16:32:19 +01:00
Amaury Denoyelle
76f47caacc MEDIUM: quic: implement refcount for quic_conn
Implement a refcount on quic_conn instance. By default, the refcount is
0. Two functions are implemented to manipulate it.
* qc_conn_take() which increments the refcount
* qc_conn_drop() which decrements it. If the refcount is 0 *BEFORE*
  the substraction, the instance is freed.

The refcount is incremented on retrieve_qc_conn_from_cid() or when
allocating a new quic_conn in qc_lstnr_pkt_rcv(). It is substracted most
notably by the xprt.close operation and at the end of
qc_lstnr_pkt_rcv(). The increments/decrements should be conducted under
the CID lock to guarantee thread-safety.
2021-12-23 16:06:07 +01:00
Amaury Denoyelle
0a29e13835 MINOR: quic: delete timer task on quic_close()
The timer task is attached to the connection-pinned thread. Only this
thread can delete it. With the future refcount implementation of
quic_conn, every thread can be responsible to remove the quic_conn via
quic_conn_free(). Thus, the timer task deletion is moved from the
calling function quic_close().
2021-12-23 16:06:07 +01:00
Amaury Denoyelle
e81fed9a54 MINOR: quic: replace usage of ssl_sock_ctx by quic_conn
Big refactoring on xprt-quic. A lot of functions were using the
ssl_sock_ctx as argument to only access the related quic_conn. All these
arguments are replaced by a quic_conn parameter.

As a convention, the quic_conn instance is always the first parameter of
these functions.

This commit is part of the rearchitecture of xprt-quic layers and the
separation between xprt and connection instances.
2021-12-23 16:06:06 +01:00
Amaury Denoyelle
741eacca47 MINOR: quic: remove unnecessary if in qc_pkt_may_rm_hp()
Remove the shortcut to use the INITIAL encryption level when removing
header protection on first connection packet.

This change is useful for the following change which removes
ssl_sock_ctx in argument lists in favor of the quic_conn instance.
2021-12-23 16:02:24 +01:00
Amaury Denoyelle
7ca7c84fb8 MINOR: quic: store ssl_sock_ctx reference into quic_conn
Add a pointer in quic_conn to its related ssl_sock_ctx. This change is
required to avoid to use the connection instance to access it.

This commit is part of the rearchitecture of xprt-quic layers and the
separation between xprt and connection instances. It will be notably
useful when the connection allocation will be delayed.
2021-12-23 15:51:00 +01:00
Amaury Denoyelle
a83729e9e6 MINOR: quic: remove unnecessary call to free_quic_conn_cids()
free_quic_conn_cids() was called in quic_build_post_handshake_frames()
if an error occured. However, the only error is an allocation failure of
the CID which does not required to call it.

This change is required for future refcount implementation. The CID lock
will be removed from the free_quic_conn_cids() and to the caller.
2021-12-23 15:51:00 +01:00
Amaury Denoyelle
250ac42754 BUG/MINOR: quic: upgrade rdlock to wrlock for ODCID removal
When a quic_conn is found in the DCID tree, it can be removed from the
first ODCID tree. However, this operation must absolutely be run under a
write-lock to avoid race condition. To avoid to use the lock too
frequently, node.leaf_p is checked. This value is set to NULL after
ebmb_delete.
2021-12-23 15:51:00 +01:00
Amaury Denoyelle
d6b166787c REORG: quic: remove qc_ prefix on functions which not used it directly
The qc_* prefix should be reserved to functions which used a specific
quic_conn instance and are expected to be pinned on the connection
thread.
2021-12-23 15:51:00 +01:00
Frédéric Lécaille
010e532e81 MINOR: quic: Add CONNECTION_CLOSE phrase to trace
Some applications may send some information about the reason why they decided
to close a connection. Add them to CONNECTION_CLOSE frame traces.
Take the opportunity of this patch to shorten some too long variable names
without any impact.
2021-12-23 15:48:25 +01:00
Frédéric Lécaille
1ede823d6b MINOR: quic: Add traces for RX frames (flow control related)
Add traces about important frame types to chunk_tx_frm_appendf()
and call this function for any type of frame when parsing a packet.
Move it to quic_frame.c
2021-12-23 15:48:25 +01:00
Willy Tarreau
77bfa66124 DEBUG: ssl: make sure we never change a servername on established connections
Since this case was already met previously with commit 655dec81b
("BUG/MINOR: backend: do not set sni on connection reuse"), let's make
sure that we don't change reused connection settings. This could be
generalized to most settings that are only in effect before the handshake
in fact (like set_alpn and a few other ones).
2021-12-23 15:44:06 +01:00
Willy Tarreau
0d93a81863 MINOR: pools: work around possibly slow malloc_trim() during gc
During 2.4-dev, support for malloc_trim() was implemented to ease
release of memory in a stopping process. This was found to be quite
effective and later backported to 2.3.7.

Then it was found that sometimes malloc_trim() could take a huge time
to complete it if was competing with other threads still allocating and
releasing memory, reason why it was decided in 2.5-dev to move
malloc_trim() under the thread isolation that was already in place in
the shared pool version of pool_gc() (this was commit 26ed1835).

However, other instances of pool_gc() that used to call malloc_trim()
were not updated since they were not using thread isolation. Currently
we have two other such instances, one for when there is absolutely no
pool and one for when there are only thread-local pools.

Christian Ruppert reported in GH issue #1490 that he's sometimes seeing
and old process die upon reload when upgrading from 2.3 to 2.4, and
that this happens inside malloc_trim(). The problem is that since
2.4-dev11 with commit 0bae07592 we detect modern libc that provide a
faster thread-aware allocator and do not maintain shared pools anymore.
As such we're using again the simpler pool_gc() implementations that do
not use thread isolation around the malloc_trim() call.

All this code was cleaned up recently and the call moved to a new
function trim_all_pools(). This patch implements explicit thread isolation
inside that function so that callers do not have to care about this
anymore. The thread isolation is conditional so that this doesn't affect
the one already in place in the larger version of pool_gc(). This way it
will solve the problem for all callers.

This patch must be backported as far as 2.3. It may possibly require
some adaptations. If trim_all_pools() is not present, copy-pasting the
tests in each version of pool_gc() will have the same effect.

Thanks to Christian for his detailed report and his testing.
2021-12-23 15:44:06 +01:00
Frédéric Lécaille
2c15a66b61 MINOR: quic: Drop asap Retry or Version Negotiation packets
These packet are only sent by servers. We drop them as soon as possible
when we are an haproxy listener.
2021-12-22 20:43:22 +01:00
Frédéric Lécaille
e7ff2b265a MINOR: quic: xprt traces fixes
Empty parameters are permitted with TRACE_*() macros. If removed, must
be replaced by NULL.
2021-12-22 20:43:22 +01:00
Frédéric Lécaille
10250b2e93 MINOR: quic: Handle the cases of overlapping STREAM frames
This is the same treatment for bidi and uni STREAM frames. This is a duplication
code which should me remove building a function for both these types of streams.
2021-12-22 20:43:22 +01:00