7321 Commits

Author SHA1 Message Date
David Carlier
6709538068 BUILD: fix recent build breakage of freebsd caused by kFreeBSD build fix
Supporting kFreebsd previously led to FreeBSD (< 14) build breakage:

 In file included from src/cpuset.c:5:
 In file included from include/haproxy/cpuset.h:4:
 include/haproxy/cpuset-t.h:46:2: error: unknown type name 'cpu_set_t'; did you mean 'cpuset_t'?
         CPUSET_REPR cpuset;
         ^~~~~~~~~~~
         cpuset_t
 include/haproxy/cpuset-t.h:21:22: note: expanded from macro 'CPUSET_REPR'
 # define CPUSET_REPR cpu_set_t
                      ^
2022-03-08 16:03:28 +01:00
Frédéric Lécaille
5bcfd33063 BUG/MAJOR: quic: Wrong quic_max_available_room() returned value
Around limits for QUIC integer encoding, this functions could return
wrong values which lead to qc_build_frms() to prepare wrong CRYPTO (less chances)
or STREAM frames (more chances). qc_do_build_pkt() could build wrong packets
with bad CRYPTO/STREAM frames which could not be decoded by the peer.
In such a case ngtcp2 closes the connection with an ENCRYPTION_ERROR error
in a transport CONNECTION_CLOSE frame.
2022-03-04 17:47:32 +01:00
Frédéric Lécaille
4fe7d8a5b2 MINOR: quic: Add quic_max_int_by_size() function
This function returns the maximum integer which may be encoded with a number of
bytes passed as parameter. Useful to precisely compute the number of bytes which
may used to fulfill a buffer with lengths as QUIC enteger encoded prefixes for the
number of following bytes.
2022-03-04 17:47:32 +01:00
Frédéric Lécaille
9777ead2ed CLEANUP: quic: Remove window redundant variable from NewReno algorithm state struct
We use the window variable which is stored in the path struct.
2022-03-04 17:47:32 +01:00
Frédéric Lécaille
0e7c9a7143 MINOR: quic: More precise window update calculation
When in congestion avoidance state and when acknowledging an <acked> number bytes
we must increase the congestion window by at most one datagram (<path->mtu>)
by congestion window. So thanks to this patch we apply a ratio to the current
number of acked bytes : <acked> * <path->mtu> / <cwnd>.
So, when <cwnd> bytes are acked we precisely increment <cwnd> by <path->mtu>.
Furthermore we take into an account the number of remaining acknowledged bytes
each time we increment the window by <acked> storing their values in the algorithm
struct state (->remain_acked) so that it might be take into an account at the
next ACK event.
2022-03-04 17:47:32 +01:00
Frédéric Lécaille
abdf4a1533 BUG/MINOR: quic: Confusion betwen "in_flight" and "prep_in_flight" in quic_path_prep_data()
This function returns the remaining number of bytes which can be sent on the
network before fulfilling the congestion window. There is a counter for
the number of prepared data and another one for the really in flight number
of bytes (in_flight). These variable have been mixed up.
2022-03-04 17:47:32 +01:00
Frédéric Lécaille
5f6783094d CLEANUP: quic: Remove useless definitions from quic_cc_event struct
Since the persistent congestion detection is done out of the congestion
controllers, there is no need to pass them information through quic_cc_event struct.
We remove its useless members. Also remove qc_cc_loss_event() which is no more used.
2022-03-04 17:47:32 +01:00
Frédéric Lécaille
a5ee0ae6a2 MINOR: quic: Persistent congestion detection outside of controllers
We establish the persistent congestion out of any congestion controller
to improve the algorithms genericity. This path characteristic detection may
be implemented regarless of the underlying congestion control algorithm.

Send congestion (loss) event using directly quic_cc_event(), so without
qc_cc_loss_event() wrapper function around quic_cc_event().

Take the opportunity of this patch to shorten "newest_time_sent" member field
of quic_cc_event to "time_sent".
2022-03-04 17:47:32 +01:00
Frédéric Lécaille
83bfca6c71 MINOR: quic: Add a "slow start" callback to congestion controller
We want to be able to make the congestion controllers re-enter the slow
start state outside of the congestion controllers themselves. So,
we add a callback ->slow_start() to do so.
Define this callback for NewReno algorithm.
2022-03-04 17:47:32 +01:00
David Carlier
43a568575f BUILD: fix kFreeBSD build.
kFreeBSD needs to be treated as a distinct target from FreeBSD
since the underlying system libc is the GNU one. Thus, relying
only on __GLIBC__ no longer suffice.

- freebsd-glibc new target, key difference is including crypt.h
  and linking to libdl like linux.
- cpu affinity available but the api is still the FreeBSD's.
- enabling auxiliary data access only for Linux.

Patch based on preliminary work done by @bigon.

closes #1555
2022-03-04 17:19:12 +01:00
Amaury Denoyelle
c055e30176 MEDIUM: mux-quic: implement MAX_STREAMS emission for bidir streams
Implement the locally flow-control streams limit for opened
bidirectional streams. Add a counter which is used to count the total
number of closed streams. If this number is big enough, emit a
MAX_STREAMS frame to increase the limit of remotely opened bidirectional
streams.

This is the first commit to implement QUIC flow-control. A series of
patches should follow to complete this.

This is required to be able to handle more than 100 client requests.
This should help to validate the Multiplexing interop test.
2022-03-04 17:00:12 +01:00
Amaury Denoyelle
2c71fe58f0 MEDIUM: mux-quic: use direct send transport API for STREAMs
Modify the STREAM emission in qc_send. Use the new transport function
qc_send_app_pkts to directly send the list of constructed frames. This
allows to remove the tasklet wakeup on the quic_conn and should reduce
the latency.

If not all frames are send after the transport call, subscribe the MUX
on the lower layer to be able to retry. Currently there is a bug because
the transport layer does not retry to send frames in excess after a
successful sendto. This might cause the transfer to be interrupted.
2022-03-04 17:00:12 +01:00
Amaury Denoyelle
414df7684a MINOR: mux-quic: define new unions for flow-control fields
Define two new unions in the qcc structure named 'lfctl' and 'rfctl'.
For the moment they are empty. They will be completed to store the
initial and current level for flow-control on the local and remote side.
2022-03-04 17:00:12 +01:00
Amaury Denoyelle
0dc40f06d1 MINOR: mux-quic: complete functions to detect stream type
Improve the functions used to detect the stream characteristics :
uni/bidirectional and local/remote initiated.

Most notably, these functions are now designed to work transparently for
a MUX in the frontend or backend side. For this, we use the connection
to determine the current MUX side. This will be useful if QUIC is
implemented on the server side.
2022-03-04 17:00:12 +01:00
Amaury Denoyelle
749cb647b1 MINOR: mux-quic: refactor transport parameters init
Since QUIC accept handling has been improved, the MUX is initialized
after the handshake completion. Thus its safe to access transport
parameters in qc_init via the quic_conn.

Remove quic_mux_transport_params_update which was called by the
transport for the MUX. This improves the architecture by removing a
direct call from the transport to the MUX.

The deleted function body is not transfered to qc_init because this part
will change heavily in the near future when implementing the
flow-control.
2022-03-04 17:00:12 +01:00
Frédéric Lécaille
c2f561ce1e MINOR: quic: Export qc_send_app_pkts()
This is at least to make this function be callable by the mux.
2022-03-04 17:00:12 +01:00
Willy Tarreau
3dfb7da04b CLEANUP: tree-wide: remove a few rare non-ASCII chars
As reported by Tim in issue #1428, our sources are clean, there are
just a few files with a few rare non-ASCII chars for the paragraph
symbol, a few typos, or in Fred's name. Given that Fred already uses
the non-accentuated form at other places like on the public list,
let's uniformize all this and make sure the code displays equally
everywhere.
2022-03-04 08:58:32 +01:00
Willy Tarreau
e81248c0c8 BUG/MINOR: pool: always align pool_heads to 64 bytes
This is the pool equivalent of commit 97ea9c49f ("BUG/MEDIUM: fd: always
align fdtab[] to 64 bytes"). After a careful code review, it happens that
the pool heads are the other structures allocated with malloc/calloc that
claim to be aligned to a size larger than what the allocator can offer.
While no issue was reported on them, no memset() is performed and no type
is large, this is a problem waiting to happen, so better fix it. In
addition, it's relatively easy to do by storing the allocation address
inside the pool_head itself and use it at free() time. Finally, threads
might benefit from the fact that the caches will really be aligned and
that there will be no false sharing.

This should be backported to all versions where it applies easily.
2022-03-02 18:22:08 +01:00
Willy Tarreau
06e66c84fc DEBUG: reduce the footprint of BUG_ON() calls
Many inline functions involve some BUG_ON() calls and because of the
partial complexity of the functions, they're not inlined anymore (e.g.
co_data()). The reason is that the expression instantiates the message,
its size, sometimes a counter, then the atomic OR to taint the process,
and the back trace. That can be a lot for an inline function and most
of it is always the same.

This commit modifies this by delegating the common parts to a dedicated
function "complain()" that takes care of updating the counter if needed,
writing the message and measuring its length, and tainting the process.
This way the caller only has to check a condition, pass a pointer to the
preset message, and the info about the type (bug or warn) for the tainting,
then decide whether to dump or crash. Note that this part could also be
moved to the function but resulted in complain() always being at the top
of the stack, which didn't seem like an improvement.

Thanks to these changes, the BUG_ON() calls do not result in uninlining
functions anymore and the overall code size was reduced by 60 to 120 kB
depending on the build options.
2022-03-02 16:00:42 +01:00
Willy Tarreau
a631b86523 BUILD: tcpcheck: do not declare tcp_check_keywords_register() inline
This one is referenced in initcalls by its pointer, it makes no sense
to declare it inline. At best it causes function duplication, at worst
it doesn't build on older compilers.
2022-03-02 14:54:44 +01:00
Willy Tarreau
4de2cda104 BUILD: trace: do not declare trace_registre_source() inline
This one is referenced in initcalls by its pointer, it makes no sense
to declare it inline. At best it causes function duplication, at worst
it doesn't build on older compilers.
2022-03-02 14:53:00 +01:00
Willy Tarreau
368479c3fc BUILD: http_rules: do not declare http_*_keywords_registre() inline
The 3 functions http_{req,res,after_res}_keywords_register() are
referenced in initcalls by their pointer, it makes no sense to declare
them inline. At best it causes function duplication, at worst it doesn't
build on older compilers.
2022-03-02 14:50:38 +01:00
Willy Tarreau
d318e4e022 BUILD: connection: do not declare register_mux_proto() inline
This one is referenced in initcalls by its pointer, it makes no sense
to declare it inline. At best it causes function duplication, at worst
it doesn't build on older compilers.
2022-03-02 14:46:45 +01:00
Willy Tarreau
e4149cdbc6 BUILD: conn_stream: avoid null-deref warnings on gcc 6
gcc 6 continues its saga with excessive reports of null-deref warnings.
This time it was in the IS_HTX_CS() macro. Let's use __cs_conn() after
cs_conn() was checked.
2022-03-02 14:39:39 +01:00
Frédéric Lécaille
bd24208673 MINOR: quic: Assemble QUIC TLS flags at the same level
Do not distinguish the direction (TX/RX) when settings TLS secrets flags.
There is not such a distinction in the RFC 9001.
Assemble them at the same level: at the upper context level.
2022-03-01 16:34:03 +01:00
Frédéric Lécaille
00e2400fa6 MINOR: quic: Post handshake I/O callback switching
Implement a simple task quic_conn_app_io_cb() to be used after the handshakes
have completed.
2022-03-01 16:22:35 +01:00
Frédéric Lécaille
5757b4a50e MINOR: quic: Ensure PTO timer is not set in the past
Wakeup asap the timer task when setting its timer in the past.
Take also the opportunity of this patch to make simplify quic_pto_pktns():
calling tick_first() is useless here to compare <lpto> with <tmp_pto>.
2022-03-01 16:22:35 +01:00
Julien Thomas
59e6bcdcea BUILD: ssl: another build warning on LIBRESSL_VERSION_NUMBER
We had several warnings when building haproxy 2.5.4 with
old openssl 1.0.1e. This version of openssl is the latest
available in EOL centos 6.

  include/haproxy/openssl-compat.h:157:51: \
  warning: "LIBRESSL_VERSION_NUMBER" is not defined

This patch fixed the build. It changes the #if condition,
as done in other similar parts of openssl-compat.h.
2022-03-01 15:49:30 +01:00
Amaury Denoyelle
0e3010b1bb MEDIUM: quic: rearchitecture Rx path for bidirectional STREAM frames
Reorganize the Rx path for STREAM frames on bidirectional streams. A new
function qcc_recv is implemented on the MUX. It will handle the STREAM
frames copy and offset calculation from transport to MUX.

Another function named qcc_decode_qcs from the MUX can be called by
transport each time new STREAM data has been copied.

The architecture is now cleaner with the MUX layer in charge of parsing
the STREAM frames offsets. This is required to be able to implement the
flow-control on the MUX layer.

Note that as a convenience, a STREAM frame is not partially copied to
the MUX buffer. This simplify the implementation for the moment but it
may change in the future to optimize the STREAM frames handling.

For the moment, only bidirectional streams benefit from this change. In
the future, it may be extended to unidirectional streams to unify the
STREAM frames processing.
2022-03-01 11:07:27 +01:00
Amaury Denoyelle
3c4303998f BUG/MINOR: quic: support FIN on Rx-buffered STREAM frames
FIN flag on a STREAM frame was not detected if the frame was previously
buffered on qcs.rx.frms before being handled.

To fix this, copy the fin field from the quic_stream instance to
quic_rx_strm_frm. This is required to properly notify the FIN flag on
qc_treat_rx_strm_frms for the MUX layer.

Without this fix, the request channel might be left opened after the
last STREAM frame reception if there is out-of-order frames on the Rx
path.
2022-03-01 11:07:06 +01:00
Amaury Denoyelle
3bf06093dc MINOR: mux-quic: define flag for last received frame
This flag is set when the STREAM frame with FIN set has been received on
a qcs instance. For now, this is only used as a BUG_ON guard to prevent
against multiple frames with FIN set. It will also be useful when
reorganize the RX path and move some of its code in the mux.
2022-03-01 10:52:31 +01:00
Willy Tarreau
5a001a0e4d BUILD: debug: fix build warning on older compilers around DEBUG_STRICT_ACTION
The new macro was introduced with commit 86bcc5308 ("DEBUG: implement 4
levels of choices between warn and crash.") but some older compilers can
complain that we test the value when the macro is not defined despite
having already been checked in a previous #if directive. Let's just
repeat the test for the definition.
2022-02-28 17:59:28 +01:00
Christopher Faulet
8bc1759f60 DEBUG: stream-int: Fix BUG_ON used to test appctx in si_applet_ops callbacks
693b23bb1 ("MEDIUM: tree-wide: Use unsafe conn-stream API when it is
relevant") introduced a regression in DEBUG_STRICT mode because some BUG_ON
conditions were inverted. It should ok now.

In addition, ALREADY_CHECKED macro was removed from appctx_wakeup() function
because it is useless now.
2022-02-28 17:29:11 +01:00
Christopher Faulet
9936dc6577 REORG: stream-int: Uninline si_sync_recv() and make si_cs_recv() private
This way si_*_recv() and si_*_sned() API are defined the same
way. si_sync_snd/si_sync_recv are both exported and defined in the C
file. And si_cs_send/si_cs_recv are private and only used by
stream-interface internals.
2022-02-28 17:16:47 +01:00
Christopher Faulet
693b23bb10 MEDIUM: tree-wide: Use unsafe conn-stream API when it is relevant
The unsafe conn-stream API (__cs_*) is now used when we are sure the good
endpoint or application is attached to the conn-stream. This avoids compiler
warnings about possible null derefs. It also simplify the code and clear up
any ambiguity about manipulated entities.
2022-02-28 17:13:36 +01:00
Christopher Faulet
e645d88c6b MINOR: conn-stream: Improve API to have safe/unsafe accessors
Depending on the context, we know the endpoint or the application attached
to the conn_stream is defined and we know its type. However, having
accessors testing the endpoint or the application may lead the compiler to
report possible null derefs here and there. The alternative is to add
useless tests or use ALREAD_CHECKED/DISGUISE macros. It is tedious and
inelegant.

So now, similarily to the ob API, the safe API, testing
endpoint/application, relies on an unsafe one (same name prefixed with
'__'). This way, any caller may use the unsafe API when it is relevant.

In addition, there is no reason to test the conn-stream itself. It is the
caller responsibility to be sure there is a conn-stream to get its endpoint
or its application. And most of type, we are sure to have a conn-stream.
2022-02-28 17:13:36 +01:00
Willy Tarreau
68ae291cd2 DEBUG: channel: add consistency checks using BUG_ON_HOT() in some key functions
A few functions such as c_adv(), c_rew(), co_set_data() or co_skip() got a
BUG_ON_HOT() to make sure they're not used to push more data than available
in the buffer. Note that with HTX the margin can be high and will less easily
trigger, but the goal is to detect a misuse early enough.

co_data() should never be called with a wrong c->output. At least it never
happens in regtests, but we're adding a CHECK_IF_HOT() there to avoid crashing
but report it if it ever happened when the hot path checks are enabled.
2022-02-28 16:59:17 +01:00
Willy Tarreau
84240044f0 MINOR: channel: don't use co_set_data() to decrement output
The use of co_set_data() should be strictly limited to setting the amount
of existing data to be transmitted. It ought not be used to decrement the
output after the data have left the buffer, because doing so involves
performing incorrect calculations using co_data() that still comprises
data that are not in the buffer anymore. Let's use c_rew() for this, which
is made exactly for this purpose, i.e. decrement c->output by as much as
requested. This is cleaner, faster, and will permit stricter checks.
2022-02-28 16:51:23 +01:00
Willy Tarreau
8873b85bd9 DEBUG: buf: add BUG_ON_HOT() to most buffer management functions
A number of tests are now performed in low-level buffer management
functions to verify that we're not appending data to a full buffer
for example, or that the buffer passed in argument is consistent in
that its data don't outweigh its size. The few functions that already
involve memcpy() or memmove() instead got a BUG_ON() that will always
be enabled, since the overhead remains minimalist.
2022-02-28 16:14:02 +01:00
Willy Tarreau
a8f4b34bb7 DEBUG: buf: replace some sensitive BUG_ON() with BUG_ON_HOT()
The buffer ring management functions br_* were all stuffed with BUG_ON()
statements that never triggered and that are on some fast paths (e.g. in
mux_h2). Let's turn them to BUG_ON_HOT() instead.
2022-02-28 16:10:00 +01:00
Willy Tarreau
7bd7954535 DEBUG: add two new macros to enable debugging in hot paths
Two new BUG_ON variants, BUG_ON_HOT() and CHECK_IF_HOT() are introduced
to debug hot paths (such as low-level API functions). These ones must
not be enabled by default as they would significantly affect performance
but they may be enabled by setting DEBUG_STRICT to a value above 1. In
this case, DEBUG_STRICT_ACTION is mostly respected with a small change,
which is that the no_crash variant of BUG_ON() isn't turned to a regular
warning but to a one-time warning so as not to spam with warnings in a
hot path. It is for this reason that there is no WARN_ON_HOT().
2022-02-28 15:32:24 +01:00
Willy Tarreau
86bcc53084 DEBUG: implement 4 levels of choices between warn and crash.
We used to have DEBUG_STRICT_NOCRASH to disable crashes on BUG_ON().
Now we have other levels (WARN_ON(), CHECK_IF()) so we need something
finer-grained.

This patch introduces DEBUG_STRICT_ACTION which takes an integer value.
0 disables crashes and is the equivalent of DEBUG_STRICT_NOCRASH. 1 is
the default and only enables crashes on BUG_ON(). 2 also enables crashes
on WARN_ON(), and 3 also enables warnings on CHECK_IF(), and is suited
to developers and CI.
2022-02-28 15:00:55 +01:00
Willy Tarreau
ef16578822 DEBUG: improve BUG_ON output message accuracy
Now we'll explicitly mention if the test was a bug/warn/check, and
"FATAL" is only displayed when the process crashes. The non-crashing
BUG_ON() also suggests to report to developers.
2022-02-28 15:00:03 +01:00
Willy Tarreau
6d3f1e322e DEBUG: rename WARN_ON_ONCE() to CHECK_IF()
The only reason for warning once is to check if a condition really
happens. Let's use a term that better translates the intent, that's
important when reading the code.
2022-02-28 11:51:23 +01:00
Amaury Denoyelle
642ab06313 MINOR: quic: adjust buffer handling for STREAM transmission
Simplify the data manipulation of STREAM frames on TX. Only stream data
and len field are used to generate a valid STREAM frames from the
buffer. Do not use the offset field, which required that a single buffer
instance should be shared for every frames on a single stream.
2022-02-25 15:06:17 +01:00
Willy Tarreau
897c861aea DEBUG: report BUG_ON() and WARN_ON() in the tainted flags
It can be useful to know from the "tainted" variable whether any
WARN_ON() or BUG_ON() triggered. Both were now added.
2022-02-25 11:55:47 +01:00
Willy Tarreau
4e0a8b1224 DEBUG: add a new WARN_ON_ONCE() macro
This one will maintain a static counter per call place and will only
emit the warning on the first call. It may be used to invite users to
report an unexpected event without spamming them with messages.
2022-02-25 11:55:47 +01:00
Willy Tarreau
a79db30c63 DEBUG: make the _BUG_ON() macro return the condition
By doing so it now becomes an expression and will allow for example
to use WARN_ON() in tests, for example:

    if (WARN_ON(cond))
       return NULL;
2022-02-25 11:55:47 +01:00
Willy Tarreau
305cfbde43 DBEUG: add a new WARN_ON() macro
This is the same as BUG_ON() except that it never crashes and only emits
a warning and a backtrace, inviting users to report the problem. This will
be usable for non-fatal issues that should not happen and need to be fixed.
This way the BUG_ON() when using DEBUG_STRICT_NOCRASH is effectively an
equivalent of WARN_ON().
2022-02-25 11:55:47 +01:00
Willy Tarreau
f19aab88d5 DEBUG: mark ABORT_NOW() as unreachable
The purpose is to make the program die at this point, so let's help the
compiler optimise the code (especially in sensitive areas) by telling it
that ABORT_NOW() does not return. This reduces the overall code size by
~0.5%.
2022-02-25 11:55:47 +01:00