Commit Graph

16591 Commits

Author SHA1 Message Date
Willy Tarreau
e90dde1edf BUILD: vars: avoid overlapping field initialization
Compiling vars.c with gcc 4.2 shows that we're initializing some local
structs field members in a not really portable way:

src/vars.c: In function 'vars_parse_cli_set_var':
src/vars.c:1195: warning: initialized field overwritten
src/vars.c:1195: warning: (near initialization for 'px.conf.args')
src/vars.c:1195: warning: initialized field overwritten
src/vars.c:1195: warning: (near initialization for 'px.conf')
src/vars.c:1201: warning: initialized field overwritten
src/vars.c:1201: warning: (near initialization for 'rule.conf')

It's totally harmless anyway, but better clean this up.
2022-01-28 19:04:02 +01:00
Willy Tarreau
95d3eaff36 BUILD: checks: fix inlining issue on set_srv_agent_[addr,port}
These functions are declared as external functions in check.h and
as inline functions in check.c. Let's move them as static inline in
check.h. This appeared in 2.4 with the following commits:

  4858fb2e1 ("MEDIUM: check: align agentaddr and agentport behaviour")
  1c921cd74 ("BUG/MINOR: check: consitent way to set agentaddr")

While harmless (it only triggers build warnings with some gcc 4.x),
it should probably be backported where the paches above are present
to keep the code consistent.
2022-01-28 19:04:02 +01:00
Willy Tarreau
a65b4933ba BUILD: cpuset: do not use const on the source of CPU_AND/CPU_ASSIGN
The man page indicates that CPU_AND() and CPU_ASSIGN() take a variable,
not a const on the source, even though it doesn't make much sense. But
with older libcs, this triggers a build warning:

  src/cpuset.c: In function 'ha_cpuset_and':
  src/cpuset.c:53: warning: initialization discards qualifiers from pointer target type
  src/cpuset.c: In function 'ha_cpuset_assign':
  src/cpuset.c:101: warning: initialization discards qualifiers from pointer target type

Better stick stricter to the documented API as this is really harmless
here. There's no need to backport it (unless build issues are reported,
which is quite unlikely).
2022-01-28 19:04:02 +01:00
Willy Tarreau
8da23393a1 BUILD: atomic: make the old HA_ATOMIC_LOAD() support const pointers
We have an implementation of atomic ops for older versions of gcc that
do not provide the __builtin_* API (< 4.4). Recent changes to the pools
broke that in pool_releasable() by having a load from a const pointer,
which doesn't work there due to a temporary local variable that is
declared then assigned. Let's make use of a compount statement to assign
it a value when declaring it.

There's no need to backport this.
2022-01-28 19:04:02 +01:00
Willy Tarreau
e08acaed19 BUG/MEDIUM: mworker: close unused transferred FDs on load failure
When the master process is reloaded on a new config, it will try to
connect to the previous process' socket to retrieve all known
listening FDs to be reused by the new listeners. If listeners were
removed, their unused FDs are simply closed.

However there's a catch. In case a socket fails to bind, the master
will cancel its startup and swithc to wait mode for a new operation
to happen. In this case it didn't close the possibly remaining FDs
that were left unused.

It is very hard to hit this case, but it can happen during a
troubleshooting session with fat fingers. For example, let's say
a config runs like this:

   frontend ftp
        bind 1.2.3.4:20000-29999

The admin wants to extend the port range down to 10000-29999 and
by mistake ends up with:

   frontend ftp
        bind 1.2.3.41:20000-29999

Upon restart the bind will fail if the address is not present, and the
master will then switch to wait mode without releasing the previous FDs
for 1.2.3.4:20000-29999 since they're now apparently unused. Then once
the admin fixes the config and does:

   frontend ftp
        bind 1.2.3.4:10000-29999

The service will start, but will bind new sockets, half of them
overlapping with the previous ones that were not properly closed. This
may result in a startup error (if SO_REUSEPORT is not enabled or not
available), in a FD number exhaustion (if the error is repeated many
times), or in connections being randomly accepted by the process if
they sometimes land on the old FD that nobody listens on.

This patch will need to be backported as far as 1.8, and depends on
previous patch:

   MINOR: sock: move the unused socket cleaning code into its own function

Note that before 2.3 most of the code was located inside haproxy.c, so
the patch above should probably relocate the function there instead of
sock.c.
2022-01-28 19:04:02 +01:00
Willy Tarreau
b510116fd2 MINOR: sock: move the unused socket cleaning code into its own function
The startup code used to scan the list of unused sockets retrieved from
an older process, and to close them one by one. This also required that
the knowledge of the internal storage of these temporary sockets was
known from outside sock.c and that the code was copy-pasted at every
call place.

This patch moves this into sock.c under the name
sock_drop_unused_old_sockets(), and removes the xfer_sock_list
definition from sock.h since the rest of the code doesn't need to know
this.

This cleanup is minimal and preliminary to a future fix that will need
to be backported to all versions featuring FD transfers over the CLI.
2022-01-28 19:04:02 +01:00
Christopher Faulet
dd0b144c3a BUG/MINOR: sink: Use the right field in appctx context in release callback
In the release callback, ctx.peers was used instead of ctx.sft. Concretly,
it is not an issue because the appctx context is an union and these both
fields are structures with a unique pointer. But it will be a problem if
that changes.

This patch must be backported as far as 2.2.
2022-01-28 17:56:18 +01:00
Christopher Faulet
c2b7fa891c DEV: flags: Add missing flags
The flags dev tool was not updated since a while. Support for several flags
was missing. It is up to date now.
2022-01-28 17:56:18 +01:00
Christopher Faulet
0a82cf4c16 BUG/MEDIUM: resolvers: Really ignore trailing dot in domain names
When a string is converted to a domain name label, the trailing dot must be
ignored. In resolv_str_to_dn_label(), there is a test to do so. However, the
trailing dot is not really ignored. The character itself is not copied but
the string index is still moved to the next char. Thus, this trailing dot is
counted in the length of the last encoded part of the domain name. Worst,
because the copy is skipped, a garbage character is included in the domain
name.

This patch should fix the issue #1528. It must be backported as far as 2.0.
2022-01-28 17:56:18 +01:00
Amaury Denoyelle
0442efd214 MINOR: quic: refactor quic CID association with threads
Do not use an extra DCID parameter on new_quic_cid to be able to
associated a new generated CID to a thread ID. Simply do the computation
inside the function. The API is cleaner this way.

This also has the effects to improve the apparent randomness of CIDs.
With the previous version the first byte of all CIDs are identical for a
connection which could lead to privacy issue. This version may not be
totally perfect on this aspect but it improves the situation.
2022-01-28 16:29:27 +01:00
Frédéric Lécaille
df1c7c78c1 MINOR: quic: Iterate over all received datagrams
Make the listener datagram handler iterate over all received datagrams
2022-01-28 16:08:07 +01:00
Frédéric Lécaille
1712b1df59 MINOR: quic: Wrong RX buffer tail handling when no more contiguous data
The producer must know where is the tailing hole in the RX buffer
when it purges it from consumed datagram. This is done allocating
a fake datagram with the remaining number of bytes which cannot be produced
at the tail of the RX buffer as length.
2022-01-28 16:08:07 +01:00
Frédéric Lécaille
dc36404c36 MINOR: quic: Drop Initial packets with wrong ODCID
According to the RFC 9000, the client ODCID must have a minimal length of 8 bytes.
2022-01-28 16:08:07 +01:00
David Carlier
629cbdf5cc MEDIUM: da: update module to handle schedule mode.
The DeviceAtlas addon can optionally interacts with the new service
 without change of configuration in the HAProxy part.
Note that however it requires the DeviceAtlas Identification C API
2.4.0 minimum from this point.

Signed-off-by: David Carlier <dcarlier@deviceatlas.com>
2022-01-28 07:29:01 +01:00
David Carlier
b81483cf2d MEDIUM: da: update doc and build for new scheduler mode service.
Mentions of the new database update runtime mode and update of
the legit module and the dummy part too.
Note the DeviceAtlas C API version 2.4.0 minimum required
alongside with libCURL, libzip and libgz.
2022-01-28 07:28:53 +01:00
David Carlier
e9cff619c1 MEDIUM: da: new optional data file download scheduler service.
New specialized service to daily handle the update of download file without
interruption of service and to be preemptively started before HAProxy.
It consists on a standalone utility which shared a memory block with
the DeviceAtlas module which handles the JSON data file update on
a daily basis.

Signed-off-by: David Carlier <dcarlier@deviceatlas.com>
2022-01-28 07:23:07 +01:00
Frédéric Lécaille
74904a4792 MINOR: quic: Make usage of by datagram handler trees
The CID trees are no more attached to the listener receiver but to the
underlying datagram handlers (one by thread) which run always on the same thread.
So, any operation on these trees do not require any locking.
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
9ea9463d47 MINOR: quic: Attach all the CIDs to the same connection
We copy the first octet of the original destination connection ID to any CID for
the connection calling new_quic_cid(). So this patch modifies only this function
to take a dcid as passed parameter.
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
320744b53d MINOR: quic: Do not reset a full RX buffer
As the RX buffer is not consumed by the sock i/o handler as soon as a datagram
is produced, when full an RX buffer must not be reset. The remaining room is
consumed without modifying it. The consumer has a represention of its contents:
a list of datagrams.
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
37ae505c21 MINOR: quic: Do not consume the RX buffer on QUIC sock i/o handler side
Rename quic_lstnr_dgram_read() to quic_lstnr_dgram_dispatch() to reflect its new role.
After calling this latter, the sock i/o handler must consume the buffer only if
the datagram it received is detected as wrong by quic_lstnr_dgram_dispatch().
The datagram handler task mark the datagram as consumed atomically setting ->buf
to NULL value. The sock i/o handler is responsible of flushing its RX buffer
before using it. It also keeps a datagram among the consumed ones so that
to pass it to quic_lstnr_dgram_dispatch() and prevent it from allocating a new one.
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
794d068d8f MINOR: proto_quic: Wrong allocations for TX rings and RX bufs
As mentionned in the comment, the tx_qrings and rxbufs members of
receiver struct must be pointers to pointers!
Modify the functions responsible of their allocations consequently.
Note that this code could work because sizeof rxbuf and sizeof tx_qrings
are greater than the size of pointer!
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
d152309423 CLEANUP: quic: Remove useless definition
The quic_dgram_ctx struct has been replaced by quic_dgram struct.
There is no need to keek a typedef for a pointer to function since we
converted the UDP datagram parser (quic_dgram_read()) into a task.
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
25bc8875d7 MINOR: quic: Convert quic_dgram_read() into a task
quic_dgram_read() parses all the QUIC packets from a UDP datagram. It is the best
candidate to be converted into a task, because is processing data unit is the UDP
datagram received by the QUIC sock i/o handler. If correct, this datagram is
added to the context of a task, quic_lstnr_dghdlr(), a conversion of quic_dgram_read()
into a task. This task pop a datagram from an mt_list and passes it among to
the packet handler (quic_lstnr_pkt_rcv()).
Modify the quic_dgram struct to play the role of the old quic_dgram_ctx struct when
passed to quic_lstnr_pkt_rcv().
Modify the datagram handlers allocation to set their tasks to quic_lstnr_dghdlr().
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
220894a5d6 MINOR: quic: Pass CID as a buffer to quic_get_cid_tid()
Very minor modification so that this function might be used for a context
without CID (at datagram level).
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
69dd5e6a0b MINOR: proto_quic: Allocate datagram handlers
Add quic_dghdlr new struct do define datagram handler tasks, one by thread.
Allocate them and attach them to the listener receiver part calling
quic_alloc_dghdlrs_listener() newly implemented function.
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
3d4bfe708a MINOR: quic: Allocate QUIC datagrams from sock I/O handler
Add quic_dgram new structure to store information about datagrams received
by the sock I/O handler (quic_sock_fd_iocb) and its associated pool.
Implement quic_get_dgram_dcid() to retrieve the datagram DCID which must
be the same for all the packets in the datagram.
Modify quic_lstnr_dgram_read() called by the sock I/O handler to allocate
a quic_dgram each time a correct datagram is found and add it to the sock I/O
handler rxbuf dgram list.
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
53898bba81 MINOR: quic: Add a list to QUIC sock I/O handler RX buffer
This list will be used to store datagrams in the rxbuf struct used
by the quic_sock_fd_iocb() QUIC sock I/O handler with one rxbuf by thread.
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
ce521e4f15 MINOR: quic: Add new defintion about DCIDs offsets
Define the offsets of the DCIDs from the beginning of a QUIC packets.
Note that they must always be present. As QUIC servers, QUIC haproxy listeners
always use a CID, source CID on the haproxy side, which is a destination ID on the
peer side.
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
9cc64e2dba MINOR: quic: Remove the QUIC haproxy server packet parser
This function is no more used anymore, broken and uses code shared with the
listener packet parser. This is becoming anoying to continue to modify
it without testing each time we modify the code it shares with the
listener packet parser.
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
3d55462654 MINOR: quic: Get rid of a struct buffer in quic_lstnr_dgram_read()
This is to be sure xprt functions do not manipulate the buffer struct
passed as parameter to quic_lstnr_dgram_read() from low level datagram
I/O callback in quic_sock.c (quic_sock_fd_iocb()).
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
055ee6c14b MINOR: quic: Comment fix about the token found in Initial packets
Mention that the token is sent only by servers in both server and listener
packet parsers.
Remove a "TO DO" section in listener packet parser because there is nothing
more to do in this function about the token
2022-01-27 16:37:55 +01:00
Frédéric Lécaille
4852101fd2 MINOR: quic: No DCID length for datagram context
This quic_dgram_ctx struct member is used to denote if we are parsing a new
datagram (null value), or a coalesced packet into the current datagram (non null
value). But it was never set.
2022-01-27 16:37:55 +01:00
Willy Tarreau
97ea9c49f1 BUG/MEDIUM: fd: always align fdtab[] to 64 bytes
There's a risk that fdtab is not 64-byte aligned. The first effect is that
it may cause false sharing between cache lines resulting in contention
when adjacent FDs are used by different threads. The second is related
to what is explained in commit "BUG/MAJOR: compiler: relax alignment
constraints on certain structures", i.e. that modern compilers might
make use of aligned vector operations to zero some entries, and would
crash. We do not use any memset() or so on fdtab, so the risk is almost
inexistent, but that's not a reason for violating some valid assumptions.

This patch addresses this by allocating 64 extra bytes and aligning the
structure manually (this is an extremely cheap solution for this specific
case). The original address is stored in a new variable "fdtab_addr" and
is the one that gets freed. This remains extremely simple and should be
easily backportable. A dedicated aligned allocator later would help, of
course.

This needs to be backported as far as 2.2. No issue related to this was
reported yet, but it could very well happen as compilers evolve. In
addition this should preserve high performance across restarts (i.e.
no more dependency on allocator's alignment).
2022-01-27 16:28:10 +01:00
Willy Tarreau
ecc473b529 BUG/MAJOR: compiler: relax alignment constraints on certain structures
In github bug #1517, Mike Lothian reported instant crashes on startup
on RHEL8 + gcc-11 that appeared with 2.4 when allocating a proxy.

The analysis brought us down to the THREAD_ALIGN() entries that were
placed inside the "server" struct to avoid false sharing of cache lines.
It turns out that some modern gcc make use of aligned vector operations
to manipulate some fields (e.g. memset() etc) and that these structures
allocated using malloc() are not necessarily aligned, hence the crash.

The compiler is allowed to do that because the structure claims to be
aligned. The problem is in fact that the alignment propagates to other
structures that embed it. While most of these structures are used as
statically allocated variables, some are dynamic and cannot use that.
A deeper analysis showed that struct server does this, propagates to
struct proxy, which propagates to struct spoe_config, all of which
are allocated using malloc/calloc.

A better approach would consist in usins posix_memalign(), but this one
is not available everywhere and will either need to be reimplemented
less efficiently (by always wasting 64 bytes before the area), or a
few functions will have to be specifically written to deal with the
few structures that are dynamically allocated.

But the deeper problem that remains is that it is difficult to track
structure alignment, as there's no available warning to check this.
For the long term we'll probably have to create a macro such as
"struct_malloc()" etc which takes a type and enforces an alignment
based on the one of this type. This also means propagating that to
pools as well, and it's not a tiny task.

For now, let's get rid of the forced alignment in struct server, and
replace it with extra padding. By punching 63-byte holes, we can keep
areas on separate cache lines. Doing so moderately increases the size
of the "server" structure (~+6%) but that's the best short-term option
and it's easily backportable.

This will have to be backported as far as 2.4.

Thanks to Mike for the detailed report.
2022-01-27 16:28:10 +01:00
Willy Tarreau
8e92738ffd DEBUG: lru: use a xorshift generator in the testing code
The standalone testing code used to rely on rand(), but switching to a
xorshift generator speeds up the test by 7% which is important to
accurately measure the real impact of the LRU code itself.
2022-01-27 16:28:10 +01:00
Willy Tarreau
bf9c07fd91 BUILD/DEBUG: lru: update the standalone code to support the revision
The standalone testing code didn't implement the revision and didn't
build anymore, let's fix that.
2022-01-27 16:28:10 +01:00
William Lallemand
08cb945a9b CLEANUP: mworker: simplify mworker_free_child()
Remove useless checks and simplify the function.
2022-01-27 15:33:40 +01:00
Amaury Denoyelle
cfa2d5648f MAJOR: quic: implement accept queue
Do not proceed to direct accept when creating a new quic_conn. Wait for
the QUIC handshake to succeeds to insert the quic_conn in the accept
queue. A tasklet is then woken up to call listener_accept to accept the
quic_conn.

The most important effect is that the connection/mux layers are not
instantiated at the same time as the quic_conn. This forces to delay
some process to be sure that the mux is allocated :
* initialization of mux transport parameters
* installation of the app-ops

Also, the mux instance is not checked now to wake up the quic_conn
tasklet. This is safe because the xprt-quic code is now ready to handle
the absence of the connection/mux layers.

Note that this commit has a deep impact as it changes significantly the
lower QUIC architecture. Most notably, it breaks the 0-RTT feature.
2022-01-26 16:13:54 +01:00
Amaury Denoyelle
f68b2cb816 MINOR: listener: define per-thr struct
Create a new structure li_per_thread. This is uses as an array in the
listener structure, with an entry allocated per thread. The new function
li_init_per_thr is responsible of the allocation.

For now, li_per_thread contains fields only useful for QUIC listeners.
As such, it is only allocated for QUIC listeners.
2022-01-26 16:13:54 +01:00
Amaury Denoyelle
2ce99fe4bf MINOR: quic: create accept queue for QUIC connections
Create a new type quic_accept_queue to handle QUIC connections accept.
A queue will be allocated for each thread. It contains a list of
listeners which contains at least one quic_conn ready to be accepted and
the tasklet to run listener_accept for these listeners.
2022-01-26 16:13:51 +01:00
Amaury Denoyelle
b59b88950a MINOR: quic: define QUIC flag on listener
Mark QUIC listeners with the flag LI_F_QUIC_LISTENER. It is set by the
proto-quic layer on the add listener callback. This allows to override
more clearly the accept callback on quic_session_accept.
2022-01-26 15:25:45 +01:00
Amaury Denoyelle
31ea9177ac MINOR: listener: add flags field
Define a new field in listener structure named flags.

For the moment, no flag is defined. This will be notably useful to
differentiate QUIC listeners with the implementation of a QUIC conn
accept queue.
2022-01-26 15:25:45 +01:00
Amaury Denoyelle
cbe090d42f MINOR: quic: remove wait handshake/L6 flags on init connection
The connection is allocated after finishing the QUIC handshake. Remove
handshake/L6 flags when initializing the connection as handshake is
finished with success at this stage.
2022-01-26 15:25:45 +01:00
Amaury Denoyelle
9fa15e5413 MINOR: quic: do not manage connection in xprt snd_buf
Remove usage of connection in quic_conn_from_buf. As connection and
quic_conn are decorrelated, it is not logical to check connection flags
when using sendto.

This require to store the L4 peer address in quic_conn to be able to use
sendto.

This change is required to delay allocation of connection.
2022-01-26 15:25:38 +01:00
Amaury Denoyelle
683b5fc7b8 MEDIUM: quic: flag listener for local accept
QUIC connections are distributed accross threads by xprt-quic according
to their CIDs. As such disable the thread selection in listener_accept
for QUIC listeners.

This prevents connection from migrating to another threads after its
allocation which can results in unexpected side-effects.
2022-01-26 11:59:12 +01:00
Amaury Denoyelle
7f7713d6ef MINOR: receiver: define a flag for local accept
This flag is named RX_F_LOCAL_ACCEPT. It will be activated for special
receivers where connection balancing to threads is already handle
outside of listener_accept, such as with QUIC listeners.
2022-01-26 11:22:20 +01:00
Amaury Denoyelle
4b40f19f92 MINOR: quic: refactor app-ops initialization
Add a new function in mux-quic to install app-ops. For now this
functions is called during the ALPN negotiation of the QUIC handshake.

This change will be useful when the connection accept queue will be
implemented. It will be thus required to delay the app-ops
initialization because the mux won't be allocated anymore during the
QUIC handshake.
2022-01-26 10:59:33 +01:00
Amaury Denoyelle
0b1f93127f MINOR: quic: handle app data according to mux/connection layer status
Define a new enum to represent the status of the mux/connection layer
above a quic_conn. This is important to know if it's possible to handle
application data, or if it should be buffered or dropped.
2022-01-26 10:57:17 +01:00
Amaury Denoyelle
8ae28077b9 MINOR: quic: refactor header protection removal
Adjust the function to check if header protection can be removed. It can
now be used both for a single packet in qc_lstnr_pkt_rcv and in the
quic_conn handler to handle buffered packets for a specific encryption
level.
2022-01-26 10:51:16 +01:00
Willy Tarreau
f70fdde591 BUILD: pools: fix build error on DEBUG_POOL_TRACING
When squashing commit add43fa43 ("DEBUG: pools: add new build option
DEBUG_POOL_TRACING") I managed to break the build and to fail to detect
it even after the rebase and a full rebuild :-(
2022-01-25 15:59:18 +01:00