Commit Graph

356 Commits

Author SHA1 Message Date
Amaury Denoyelle
0e0969d6cf MINOR: mux-quic: release idle conns on process stopping
Implement the idle frontend connection cleanup for QUIC mux. Each
connection is registered on the mux_stopping_list. On process closing,
the mux is notified via a new function qc_wake. This function immediatly
release the connection if the parent proxy is stopped.

This allows to quickly close the process even if there is QUIC
connection stucked on timeout.
2022-02-01 15:42:32 +01:00
Amaury Denoyelle
1136e9243a MEDIUM: mux-quic: delay the closing with the timeout
Do not close immediatly the connection if there is no bidirectional
stream opened. Schedule instead the mux timeout when this condition is
verified. On the timer expiration, the mux/connection can be freed.
2022-02-01 15:19:35 +01:00
Amaury Denoyelle
aebe26f8ba MINOR: mux-quic: create a timeout task
This task will be used to schedule a timer when there is no activity on
the mux. The timeout is set via the "timeout client" from the
configuration file.

The timeout task process schedule the timeout only on specific
conditions. Currently, it's done if there is no opened bidirectional
stream.

For now this task is not used. This will be implemented in the following
commit.
2022-02-01 15:19:35 +01:00
Amaury Denoyelle
d975148776 MINOR: mux-quic: do not consider CONNECTION_CLOSE for the moment
Remove the condition on CONNECTION_CLOSE reception to close immediately
streams. It can cause some crash as the QUIC xprt layer still access the
qcs to send data and handle ACK.

The whole interface and buffering between QUIC xprt and mux must be
properly reorganized to better handle this case. Once this is done, it
may have some sense to free the qcs streams on CONNECTION_CLOSE
reception.
2022-02-01 15:19:35 +01:00
Amaury Denoyelle
ce1f30dac8 MINOR: mux-quic: properly initialize qcc flags
Set qcc.flags to 0 on qc_init.
2022-02-01 15:19:35 +01:00
Amaury Denoyelle
6a4aebfbfc MINOR: mux-quic: add comment
Explain the qc_release_detached_streams function purpose and interface.
Most notably the return code which is the count of released streams.
2022-02-01 10:56:43 +01:00
Frédéric Lécaille
82468ea98e MINOR: quic: Remove the packet number space TX MT_LIST
There is no need to use an MT_LIST to store frames to send from a packet
number space. This is a reminiscence for multi-threading support for the TX part.
2022-01-20 16:43:06 +01:00
Frédéric Lécaille
b80b20c6ff MINOR: quic: Do not wakeup the I/O handler before the mux is started
If we wakeup the I/O handler before the mux is started, it is possible
it has enough time to parse the ClientHello TLS message and update the
mux transport parameters, leading to a crash.
So, we initialize ->qcc quic_conn struct member at the very last time,
when the mux if fully initialized. The condition to wakeup the I/O handler
from lstnr_rcv_pkt() is: xprt context and mux both initialized.
Note that if the xprt context is initialized, it implies its tasklet is
initialized. So, we do not check anymore this latter condition.
2022-01-12 18:08:29 +01:00
Frédéric Lécaille
19cd46e6e5 MINOR: quic: Reset ->conn quic_conn struct member when calling qc_release()
There may be remaining locations where ->conn quic_conn struct member
is used. So let's reset this.
Add a trace to have an idead when this connection is released.
2022-01-11 16:12:31 +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
Frédéric Lécaille
677b99dca7 MINOR: quic: Add stream IDs to qcs_push_frame() traces
This is only for debug purpose.
2021-12-21 16:06:03 +01:00
Amaury Denoyelle
8a5b27a9b9 REORG: quic: move mux function outside of xprt
Move qcc_get_qcs() function from xprt_quic.c to mux_quic.c. This
function is used to retrieve the qcs instance from a qcc with a stream
id. This clearly belongs to the mux-quic layer.
2021-12-21 15:51:40 +01:00
Amaury Denoyelle
fdbf63e86e MINOR: mux-quic: fix trace on stream creation
Replace non-initialized qcs.by_id.key by the id to report the proper
stream ID on stream creation.
2021-12-17 09:55:01 +01:00
Amaury Denoyelle
f3b0ba7dc9 BUG/MINOR: mux-quic: properly initialize flow control
Initialize all flow control members on the qcc instance. Without this,
the value are undefined and it may be possible to have errors about
reached streams limit.
2021-12-08 15:26:16 +01:00
Amaury Denoyelle
5154e7a252 MINOR: quic: notify the mux on CONNECTION_CLOSE
The xprt layer is reponsible to notify the mux of a CONNECTION_CLOSE
reception. In this case the flag QC_CF_CC_RECV is positionned on the
qcc and the mux tasklet is waken up.

One of the notable effect of the QC_CF_CC_RECV is that each qcs will be
released even if they have remaining data in their send buffers.
2021-12-08 15:26:16 +01:00
Amaury Denoyelle
2873a31c81 MINOR: mux-quic: do not release qcs if there is remaining data to send
A qcs is not freed if there is remaining data in its buffer. In this
case, the flag QC_SF_DETACH is positionned.

The qcc io handler is responsible to remove the qcs if the QC_SF_DETACH
is set and their buffers are empty.
2021-12-08 15:26:16 +01:00
Amaury Denoyelle
fecfa0d822 MINOR: mux-quic: remove uneeded code to check fin on TX
Remove a wrong comparaison with the same buffer on both sides. In any
cases, the FIN is properly set by qcs_push_frame only when the payload
has been totally emptied.
2021-12-07 17:11:22 +01:00
Amaury Denoyelle
84ea8dcbc4 MEDIUM: mux-quic: handle when sending buffer is full
Handle the case when the app layer sending buffer is full. A new flag
QC_SF_BLK_MROOM is set in this case and the transfer is interrupted. It
is expected that then the conn-stream layer will subscribe to SEND.

The MROOM flag is reset each time the muxer transfer data from the app
layer to its own buffer. If the app layer has been subscribed on SEND it
is woken up.
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
e257d9e8ec MEDIUM: mux-quic: wake up xprt on data transferred
On qc_send, data are transferred for each stream from their qcs.buf to
the qcs.xprt_buf. Wake up the xprt to warn about new data available for
transmission.
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
a2c58a7c8d MEDIUM: mux-quic: subscribe on xprt if remaining data after send
The streams data are transferred from the qcs.buf to the qcs.xprt_buf
during qc_send. If the xprt_buf is not empty and not all data can be
transferred, subscribe the connection on the xprt for sending.

The mux will be woken up by the xprt when the xprt_buf will be cleared.
This happens on ACK reception.
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
a3f222dc1e MINOR: mux-quic: implement subscribe on stream
Implement the subscription in the mux on the qcs instance.

Subscribe is now used by the h3 layer when receiving an incomplete frame
on the H3 control stream. It is also used when attaching the remote
uni-directional streams on the h3 layer.

In the qc_send, the mux wakes up the qcs for each new transfer executed.
This is done via the method qcs_notify_send().

The xprt wakes up the qcs when receiving data on unidirectional streams.
This is done via the method qcs_notify_recv().
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
c2025c1ec6 MEDIUM: quic: detect the stream FIN
Set the QC_SF_FIN_STREAM on the app layers (h3 / hq-interop) when
reaching the HTX EOM. This is used to warn the mux layer to set the FIN
on the QUIC stream.
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
916f0ac1e7 MEDIUM: mux-quic: implement release mux operation
Implement qc_release. This function is called by the upper layer on
connection close. For the moment, this only happens on client timeout.

This functions is used the free a qcs instance. If all bidirectional
streams are freed, the qcc instance and the connection are purged.
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
deed777766 MAJOR: mux-quic: implement a simplified mux version
Re-implement the QUIC mux. It will reuse the mechanics from the previous
mux without all untested/unsupported features. This should ease the
maintenance.

Note that a lot of features are broken for the moment. They will be
re-implemented on the following commits to have a clean commit history.
2021-12-07 15:44:45 +01:00
Amaury Denoyelle
e2288c3087 MEDIUM: xprt-quic: finalize app layer initialization after ALPN nego
The app layer is initialized after the handshake completion by the XPRT
stack. Call the finalize operation just after that.

Remove the erroneous call to finalize by the mux in the TPs callback as
the app layer is not yet initialized at this stage.

This should fix the missing H3 settings currently not emitted by
haproxy.
2021-12-07 15:37:53 +01:00
Amaury Denoyelle
71e588c8a7 MEDIUM: quic: inspect ALPN to install app_ops
Remove the hardcoded initialization of h3 layer on mux init. Now the
ALPN is looked just after the SSL handshake. The app layer is then
installed if the ALPN negotiation returned a supported protocol.

This required to add a get_alpn on the ssl_quic layer which is just a
call to ssl_sock_get_alpn() from ssl_sock. This is mandatory to be able
to use conn_get_alpn().
2021-11-18 10:50:58 +01:00
Amaury Denoyelle
abbe91e5e8 MINOR: quic: redirect app_ops snd_buf through mux
This change is required to be able to use multiple app_ops layer on top
of QUIC. The stream-interface will now call the mux snd_buf which is
just a proxy to the app_ops snd_buf function.

The architecture may be simplified in the structure to install the
app_ops on the stream_interface and avoid the detour via the mux layer
on the sending path.
2021-11-18 10:50:58 +01:00
Amaury Denoyelle
7bb54f9906 MINOR: mux-quic: fix gcc11 warning
Fix minor warnings about an unused variable.

This addresses in part github issue #1445.
2021-11-08 08:59:30 +01:00
Amaury Denoyelle
493bb1db10 MINOR: quic: handle CONNECTION_CLOSE frame
On receiving CONNECTION_CLOSE frame, the mux is flagged for immediate
connection close. A stream is closed even if there is data not ACKed
left if CONNECTION_CLOSE has been received.
2021-10-13 16:38:56 +02:00
Amaury Denoyelle
1e308ffc79 MINOR: mux: remove last occurences of qcc ring buffer
The mux tx buffers have been rewritten with buffers attached to qcs
instances. qc_buf_available and qc_get_buf functions are updated to
manipulates qcs. All occurences of the unused qcc ring buffer are
removed to ease the code maintenance.
2021-10-13 16:38:56 +02:00
Amaury Denoyelle
cae0791942 MEDIUM: mux-quic: defer stream shut if remaining tx data
Defer the shutting of a qcs if there is still data in its tx buffers. In
this case, the conn_stream is closed but the qcs is kept with a new flag
QC_SF_DETACH.

On ACK reception, the xprt wake up the shut_tl tasklet if the stream is
flagged with QC_SF_DETACH. This tasklet is responsible to free the qcs
and possibly the qcc when all bidirectional streams are removed.
2021-10-13 16:38:56 +02:00
Amaury Denoyelle
ac8ee25659 MINOR: mux-quic: implement standard method to detect if qcc is dead
For the moment, a quic connection is considered dead if it has no
bidirectional streams left on it. This test is implemented via
qcc_is_dead function. It can be reused to properly close the connection
when needed.
2021-10-13 16:38:56 +02:00
Amaury Denoyelle
4fc8b1cb17 CLEANUP: h3: remove dead code
Remove unused function. This will simplify code maintenance.
2021-10-13 16:38:56 +02:00
Amaury Denoyelle
a543eb1f6f MEDIUM: h3: properly manage tx buffers for large data
Properly handle tx buffers management in h3 data sending. If there is
not enough contiguous space, the buffer is first realigned. If this is
not enough, the stream is flagged with QC_SF_BLK_MROOM waiting for the
buffer to be emptied.

If a frame on a stream is successfully pushed for sending, the stream is
called if it was flagged with QC_SF_BLK_MROOM.
2021-10-13 16:38:56 +02:00
Amaury Denoyelle
d3d97c6ae7 MEDIUM: mux-quic: rationalize tx buffers between qcc/qcs
Remove the tx mux ring buffers in qcs, which should be in the qcc. For
the moment, use a simple architecture with 2 simple tx buffers in the
qcs.

The first buffer is used by the h3 layer to prepare the data. The mux
send operation transfer these into the 2nd buffer named xprt_buf. This
buffer is only freed when an ACK has been received.

This architecture is functional but not optimal for two reasons :
- it won't limit the buffer usage by connection
- each transfer on a new stream requires an allocation
2021-10-13 16:38:56 +02:00
Willy Tarreau
b4e34766a3 REORG: thread/sched: move the last dynamic thread_info to thread_ctx
The last 3 fields were 3 list heads that are per-thread, and which are:
  - the pool's LRU head
  - the buffer_wq
  - the streams list head

Moving them into thread_ctx completes the removal of dynamic elements
from the struct thread_info. Now all these dynamic elements are packed
together at a single place for a thread.
2021-10-08 17:22:26 +02:00
Amaury Denoyelle
eb01f597eb BUG/MINOR: quic: fix includes for compilation
Fix missing includes in quic code following the general recent include
reorganization. This fixes the compilation error with QUIC enabled.
2021-10-08 15:59:02 +02:00
Amaury Denoyelle
769e9ffd94 CLEANUP: mux-quic: remove unused code
Remove unused code in mux-quic. This is mostly code related to the
backend side. This code is untested for the moment, its removal will
simplify the code maintenance.
2021-10-08 15:48:00 +02:00
Amaury Denoyelle
d595f108db MINOR: mux-quic: release connection if no more bidir streams
Use the count of bidirectional streams to call qc_release in qc_detach.
We cannot inspect the by_id tree because uni-streams are never removed
from it. This allows the connection to be properly freed.
2021-10-07 17:35:25 +02:00
Amaury Denoyelle
139814a67a BUG/MEDIUM: mux-quic: reinsert all streams in by_id tree
It is required that all qcs streams are in the by_id tree for the xprt
to function correctly. Without this, some ACKs are not properly emitted
by xprt.

Note that this change breaks the free of the connection because the
condition eb_is_empty in qc_detach is always true. This will be fixed in
a following patch.
2021-10-07 17:35:25 +02:00
Willy Tarreau
beeabf5314 MINOR: task: provide 3 task_new_* wrappers to simplify the API
We'll need to improve the API to pass other arguments in the future, so
let's start to adapt better to the current use cases. task_new() is used:
  - 18 times as task_new(tid_bit)
  - 18 times as task_new(MAX_THREADS_MASK)
  - 2 times with a single bit (in a loop)
  - 1 in the debug code that uses a mask

This patch provides 3 new functions to achieve this:
  - task_new_here()     to create a task on the calling thread
  - task_new_anywhere() to create a task to be run anywhere
  - task_new_on()       to create a task to run on a specific thread

The change is trivial and will allow us to later concentrate the
required adaptations to these 3 functions only. It's still possible
to call task_new() if needed but a comment was added to encourage the
use of the new ones instead. The debug code was not changed and still
uses it.
2021-10-01 18:36:29 +02:00
Amaury Denoyelle
cde911231e MINOR: quic: fix qcc subs initialization 2021-09-23 15:27:25 +02:00
Amaury Denoyelle
cd28b27581 MEDIUM: quic: implement mux release/conn free 2021-09-23 15:27:25 +02:00
Frédéric Lécaille
8526f14acd MINOR: quic: Wake up the xprt from mux
We wake up the xprt as soon as STREAM frames have been pushed to
the TX mux buffer (->tx.buf).
We also make the mux subscribe() to the xprt layer if some data
remain in its ring buffer after having try to transfer them to the
xprt layer (TX mux buffer for the stream full).
Also do not consider a buffer in the ring if not allocated (see b_size(buf))
condition in the for(;;) loop.
Make a call to qc_process_mux() if possible when entering qc_send() to
fill the mux with data from streams in the send or flow control lists.
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
1d40240f25 MINOR: quic: Implement qc_process_mux()
At this time, we only add calls to qc_resume_each_sending_qcs()
which handle the flow control and send lists.
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
d2ba0967b7 MINOR: quic: Stream FIN bit fix in qcs_push_frame()
The FIN of a STREAM frame to be built must be set if there is no more
at all data in the ring buffer.
Do not do anything if there is nothing to transfer the ->tx.buf mux
buffer via b_force_xfer() (without zero copy)
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
153194f47a MINOR: mux_quic: Export the mux related flags
These flags should be available from the xprt which must be able to
wake up the mux when blocked.
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
578a7898f2 MINOR: mux_quic: move qc_process() code to qc_send()
qc_process is supposed to be run for each I/O handler event, not
only for "send" events.
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
785d3bdedc MINOR: quic: Make use of buffer structs to handle STREAM frames
The STREAM data to send coming from the upper layer must be stored until
having being acked by the peer. To do so, we store them in buffer structs,
one by stream (see qcs.tx.buf). Each time a STREAM is built by quic_push_frame(),
its offset must match the offset of the first byte added to the buffer (modulo
the size of the buffer) by the frame. As they are not always acknowledged in
order, they may be stored in eb_trees ordered by their offset to be sure
to sequentially delete the STREAM data from their buffer, in the order they
have been added to it.
2021-09-23 15:27:25 +02:00
Amaury Denoyelle
42bb8aac65 MINOR: h3/mux: detect fin on last h3 frame of the stream 2021-09-23 15:27:25 +02:00
Amaury Denoyelle
26dfd90eb0 MINOR: h3: define snd_buf callback and divert mux ops 2021-09-23 15:27:25 +02:00
Amaury Denoyelle
7b1d3d6d3d MINOR: mux-quic: send SETTINGS on uni stream 2021-09-23 15:27:25 +02:00
Amaury Denoyelle
f52151d83e MEDIUM: mux-quic: implement ring buffer on stream tx 2021-09-23 15:27:25 +02:00
Frédéric Lécaille
0ad0458a56 MINOR: quic: Replace quic_tx_frm struct by quic_frame struct
These structures are similar. quic_tx_frm was there to try to reduce the
size of such objects which embed a union for all the QUIC frames.
Furtheremore this patch fixes the issue where quic_tx_frm objects were freed
from the pool for quic_frame.
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
01abc4612b MINOR: quic: Unitialized mux context upon Client Hello message receipt.
If we let the connection packet handler task (quic_conn_io_cb) process the first
client Initial packet which contain the TLS Client Hello message before the mux
context is initialized, quic_mux_transport_params_update() makes haproxy crash.
->start xprt callback already wakes up this task and is called after all the
connection contexts are initialized. So, this patch do not wakes up quic_conn_io_cb()
if the mux context is not initialized (this was already the case for the connection
context (conn_ctx)).
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
dfbae766b2 MINOR: mux_quic: Add QUIC mux layer.
This file has been derived from mux_h2.c removing all h2 parts. At
QUIC mux layer, there must not be any reference to http. This will be the
responsability of the application layer (h3) to open streams handled by the mux.
2021-09-23 15:27:25 +02:00