16131 Commits

Author SHA1 Message Date
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
e9c4cc13fc MINOR: mux-quic: retry send opportunistically for remaining frames
This commit should fix the possible transfer interruption caused by the
previous commit. The MUX always retry to send frames if there is
remaining data after a send call on the transport layer. This is useful
if the transport layer is not blocked on the sending path.

In the future, the transport layer should retry by itself the send
operation if no blocking condition exists. The MUX layer will always
subscribe to retry later if remaining frames are reported which indicate
a blocking on the transport layer.
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
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
Frédéric Lécaille
edc81469a8 MINOR: quic: Make qc_build_frms() build ack-eliciting frames from a list
We want to be able to build ack-eliciting frames to be embedded into QUIC packets
from a prebuilt list of ack-eliciting frames. This will be helpful for the mux
which would like to send STREAM frames asap after having builts its own prebuilt
list.
To do so, we only add a parameter as struct list to this function to handle
such a prebuilt list.
2022-03-04 17:00:12 +01:00
Frédéric Lécaille
28c7ea3725 MINOR: quic: Send short packet from a frame list
We want to be able to send ack-elicting packets from a list of ack-eliciting
frames. So, this patch adds such a paramaters to the function responsible of
building 1RTT packets. The entry point function is qc_send_app_pkts() which
is used with the underlying packet number space TX frame list as parameter.
2022-03-04 17:00:12 +01:00
Frédéric Lécaille
1c5968b275 MINOR: quic: qc_prep_app_pkts() implementation
We want to get rid of the code used during the handshake step. qc_prep_app_pkts()
aim is to build short packets which are also datagrams.
Make quic_conn_app_io_cb() call this new function to prepare short packets.
2022-03-04 17:00:12 +01:00
Amaury Denoyelle
1455113e93 CLEANUP: quic: complete ABORT_NOW with a TODO comment
Add a TODO comment to not forget to properly implement error returned by
qcs_push_frame.
2022-03-04 16:56:51 +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
f9eba78fb8 BUG/MEDIUM: pools: fix ha_free() on area in the process of being freed
Commit e81248c0c ("BUG/MINOR: pool: always align pool_heads to 64 bytes")
added a free of the allocated pool in pool_destroy() using ha_free(), but
it added a subtle bug by which once the pool is released, setting its
address to NULL inside the structure itself cannot work because the area
has just been freed.

This will need to be backported wherever the patch above is backported.
2022-03-03 18:42:49 +01:00
Amaury Denoyelle
2d0f873cd8 BUG/MINOR: quic: fix segfault on CC if mux uninitialized
A segfault happens when receiving a CONNECTION_CLOSE during handshake.
This is because the mux is not initialized at this stage but the
transport layer dereferences it.

Fix this by ensuring that the MUX is initialized before. Thanks to Willy
for his help on this one. Welcome in the QUIC-men team !
2022-03-03 18:09:37 +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
William Lallemand
10a37360c8 BUG/MEDIUM: httpclient/lua: infinite appctx loop with POST
When POSTing a request with a payload, and reusing the same httpclient
lua instance, one could encounter a spinning of the httpclient appctx.

Indeed the sent counter is not reset between 2 POSTs and the condition
for sending the EOM flag is never met.

Must fixed issue #1593.

To be backported in 2.5.
2022-03-02 16:32:47 +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
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
9355d50f73 CLEANUP: quic: Indentation fix in qc_prep_pkts()
Non-invasive modification.
2022-03-01 16:22:35 +01:00
Frédéric Lécaille
7d845f15fd CLEANUP: quic: Useless tests in qc_try_rm_hp()
There is no need to test <qel>. Furthermore the packet type has already checked
by the caller.
2022-03-01 16:22:35 +01:00
Frédéric Lécaille
51c9065f66 MINOR: quic: Drop the packets of discarded packet number spaces
This is required since this previous commit:
   "MINOR: quic: Post handshake I/O callback switching"
If not, such packets remain endlessly in the RX buffer and cannot be parsed
by the new I/O callback used after the handshake has been confirmed.
2022-03-01 16:22:35 +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
Christopher Faulet
10c9c74cd1 CLEANUP: stream: Remove useless tests on conn-stream in stream_dump()
Since the recent refactoring on the conn-streams, a stream has always a
defined frontend and backend conn-streams. Thus, in stream_dump(), there is
no reason to still test if these conn-streams are defined.

In addition, still in stream_dump(), get the stream-interfaces using the
conn-streams and not the opposite.

This patch should fix issue #1589 and #1590.
2022-03-01 15:22:05 +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
Amaury Denoyelle
f77e3435a9 MINOR: quic: handle partially received buffered stream frame
Adjust the function to handle buffered STREAM frames. If the offset of
the frame was already fully received, discard the frame. If only
partially received, compute the difference and copy only the newly
offset.

Before this change, a buffered frame representing a fully or partially
received offset caused the loop to be interrupted. The frame was
preserved, thus preventing frames with greater offset to be handled.

This may fix some occurences of stalled transfer on the request channel
if there is out-of-order STREAM frames on the Rx path.
2022-03-01 10:52:31 +01:00
Amaury Denoyelle
2d2d030522 MINOR: quic: simplify copy of STREAM frames to RX buffer
qc_strm_cpy can be simplified by simply using b_putblk which already
handle wrapping of the destination buffer. The function is kept to
update the frame length and offset fields.
2022-03-01 10:52:31 +01:00
Amaury Denoyelle
850695ab1f CLEANUP: adjust indentation in bidir STREAM handling function
Fix indentation in qc_handle_bidi_strm_frm in if condition.
2022-03-01 10:52:31 +01:00
Tim Duesterhus
cc8348fbc1 MINOR: queue: Replace if() + abort() with BUG_ON()
see 5cd4bbd7a ("BUG/MAJOR: threads/queue: Fix thread-safety issues on the queues management")
2022-03-01 10:14:56 +01:00
Tim Duesterhus
17e6b737d7 MINOR: connection: Transform safety check in PROXYv2 parsing into BUG_ON()
With BUG_ON() being enabled by default it is more useful to use a BUG_ON()
instead of an effectively never-taken if, as any incorrect assumptions will
become much more visible.

see 488ee7fb6 ("BUG/MAJOR: proxy_protocol: Properly validate TLV lengths")
2022-02-28 17:59:28 +01:00
Tim Duesterhus
f09af57df5 CLEANUP: connection: Indicate unreachability to the compiler in conn_recv_proxy
Transform the unreachability comment into a call to `my_unreachable()` to allow
the compiler from benefitting from it.

see d1b15b6e9 ("MINOR: proxy_protocol: Ingest PP2_TYPE_UNIQUE_ID on incoming connections")
see 615f81eb5 ("MINOR: connection: Use a `struct ist` to store proxy_authority")
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
234a10aa9b BUG/MEDIUM: htx: Fix a possible null derefs in htx_xfer_blks()
In htx_xfer_blks() function, when headers or trailers are partially
transferred, we rollback the copy by removing copied blocks. Internally, all
blocks between <dstref> and <dstblk> are removed. But if the transfer was
stopped because we failed to reserve a block, the variable <dstblk> is
NULL. Thus, we must not try to remove it. It is unexpected to call
htx_remove_blk() in this case.

htx_remove_blk() was updated to test <blk> variable inside the existing
BUG_ON(). The block must be defined.

For now, this bug may only be encountered when H2 trailers are copied. On H2
headers, the destination buffer is empty. Thus a swap is performed.

This patch should fix the issue #1578. It must be backported as far as 2.4.
2022-02-28 17:16:55 +01:00
Christopher Faulet
4ab8438362 BUG/MEDIUM: mux-fcgi: Don't rely on SI src/dst addresses for FCGI health-checks
When an HTTP health-check is performed in FCGI, we must not rely on the SI
source and destination addresses to set default parameters
(REMOTE_ADDR/REMOTE_PORT and SERVER_NAME/SERVER_PORT) because the backend
conn-stream is not attached to a stream but to a healt-check. Thus, there is
no stream-interface. In addition, there is no client connection because it
is an "internal" session.

Thus, for now, in this case, there is only the server connection that can be
used. So src/dst addresses are retrieved from the server connection when the
CS application is a health-check.

This patch should solve issue #1572. It must be backported to 2.5. Note than
the CS api has changed. Thus, on HAProxy 2.5, we should test the session's
origin instead:

    const struct sockaddr_storage *src = (cs_check(fstrm->cs) ? ...);
    const struct sockaddr_storage *dst = (cs_check(fstrm->cs) ? ...);
2022-02-28 17:16:55 +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
494162381e CLEANUP: stream-int: Make si_cs_send() function static
This function was not exported and is only used in stream_interface.c. So
make it static.
2022-02-28 17:13:36 +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
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
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
7b4c9d6e8c MINOR: quic: add a TODO for a memleak frame on ACK consume
The quic_frame instance containing the quic_stream must be freed when
the corresponding ACK has been received. However when implementing this
on qcs_try_to_consume, some data transfers are interrupted and cannot
complete (DC test from interop test suite).
2022-02-25 15:06:17 +01:00
Amaury Denoyelle
0c7679dd86 MINOR: quic: liberate the TX stream buffer after ACK processing
The sending buffer of each stream is cleared when processing ACKs
corresponding to STREAM emitted frames. If the buffer is empty, free it
and offer it as with other dynamic buffers usage.

This should reduce memory consumption as before an opened stream
confiscate a buffer during its whole lifetime even if there is no more
data to transmit.
2022-02-25 15:06:17 +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
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
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