Commit Graph

34 Commits

Author SHA1 Message Date
Frédéric Lécaille
439c464250 MINOR: quic: EINTR error ignored
This should fix Coverity CID 375050 in GH #1536 where EINTR errno was ignored due
to wrong do...while() loop usage.
2022-02-14 15:20:54 +01:00
Amaury Denoyelle
58a7704d54 MINOR: quic: take out xprt snd_buf operation
Rename quic_conn_to_buf to qc_snd_buf and remove it from xprt ops. This
is done to reflect the true usage of this function which is only a
wrapper around sendto but cannot be called by the upper layer.

qc_snd_buf is moved in quic-sock because to mark its link with
quic_sock_fd_iocb which is the recvfrom counterpart.
2022-02-09 15:57:46 +01:00
Frédéric Lécaille
f6f7520b9b MINOR: quic: Wrong datagram buffer passed to quic_lstnr_dgram_dispatch()
The same datagram could be passed to quic_lstnr_dgram_dispatch() before
being consumed by qc_lstnr_pkt_rcv() leading to a wrong decryption for the packet
number decryption, then a decryption error for the data. This was due to
a wrong datagram buffer passed to quic_lstnr_dgram_dispatch(). The datagram data
which must be passed to quic_lstnr_dgram_dispatch() are the same as the one
passed to recvfrom().
2022-02-02 18:24:21 +01:00
Frédéric Lécaille
91f083a365 MINOR: quic: Do not try to accept a connection more than one time
We add a new flag to mark a connection as already enqueued for acception.
This is useful for 0-RTT session where a connection is first enqueued for
acception as soon as 0-RTT RX secrets could be derived. Then as for any other
connection, we could accept one more time this connection after handshake
completion which lead to very bad side effects.

Thank you to Amaury for this nice patch.
2022-01-31 16:40:23 +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
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
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
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
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
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
57af069571 MINOR: quic: set listener accept cb on parsing
Define a special accept cb for QUIC listeners to quic_session_accept().
This operation is conducted during the proto.add callback when creating
listeners.

A special care is now taken care when setting the standard callback
session_accept_fd() to not overwrite if already defined by the proto
layer.
2022-01-24 10:30:49 +01:00
Amaury Denoyelle
4d29504c58 MINOR: quic: add missing include in quic_sock
Add quic_sock.h include in corresponding source file quic_sock.c.
2022-01-24 10:30:49 +01:00
Amaury Denoyelle
ee72a43321 BUILD: quic: fix potential NULL dereference on xprt_quic
A warning is triggered by gcc9 on this code path, which is the compiler
version used by ubuntu20.04 on the github CI.

This is linked to github issue #1445.
2021-11-19 15:55:19 +01:00
Frédéric Lécaille
d169efe52b MINOR: quic_sock: missing CO_FL_ADDR_TO_SET flag
When allocating destination addresses for QUIC connections we did not set
this flag which denotes these addresses have been set. This had as side
effect to prevent the H3 request results from being returned to the QUIC clients.

Note that this bug was revealed by this commit:
  "MEDIUM: backend: Rely on addresses at stream level to init server connection"

Thanks to Christopher for having found the real cause of this issue.
2021-11-19 14:37:35 +01:00
Frédéric Lécaille
c4becf5424 MINOR: quic: Fix potential null pointer dereference
Fix compilation warnings about non initialized pointers.

This partially address #1445 github issue.
2021-11-08 11:31:12 +01:00
Frédéric Lécaille
324ecdafbb MINOR: quic: Enhance the listener RX buffering part
Add a buffer per QUIC connection. At this time the listener which receives
the UDP datagram is responsible of identifying the underlying QUIC connection
and must copy the QUIC packets to its buffer.
->pkt_list member has been added to quic_conn struct to enlist the packets
in the order they have been copied to the connection buffer so that to be
able to consume this buffer when the packets are freed. This list is locked
thanks to a R/W lock to protect it from concurent accesses.
quic_rx_packet struct does not use a static buffer anymore to store the QUIC
packets contents.
2021-11-05 15:20:04 +01: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
Frédéric Lécaille
b9c06fbe52 MINOR: quic_sock: Do not flag QUIC connections as being set
This is to let conn_get_src() or conn_get_src() set the source
or destination addresses for the connection.
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
01ab6618fe MINOR: quic: Move conn_prepare() to ->accept_conn() callback
The xprt context must be initialized before receiving further packets from
the I/O dgram handler.
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
c28aba2a8d MINOR: quic: Replace the RX list of packet by a thread safety one.
This list is shared between the I/O dgram handler and the task responsible
for processing the QUIC packets.
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
3d77fa754d MINOR: quic: QUIC conn initialization from I/O handler
Move the QUIC conn (struct quic_conn) initialization from quic_sock_accept_conn()
to qc_lstnr_pkt_rcv() as this is done for the server part.
Move the timer initialization to ->start xprt callback to ensure the connection
context is done : it is initialized by the ->accept callback which may be run
by another thread than the one for the I/O handler which also run ->start.
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
ecb5872012 MINOR: quic: Initialize the session before starting the xprt.
We must ensure the session and the mux are initialized before starting the xprt.
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
e8139f3b37 BUG/MINOR: quic: Wrong ->accept() error handling
Really signal the caller that ->accept() has failed if the session could not
be initialized because conn_complete_session() has failed. This is the case
if the mux could not be initialized too.
When it fails an ->accept() must returns -1 in case of resource shortage.
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
27faba7240 MINOR: quic_sock: Finalize the QUIC connections.
Add a call to conn_connection_complete() so that to install the mux any
QUIC connection.
2021-09-23 15:27:25 +02:00
Frédéric Lécaille
5aa4143d6c MINOR: quic: Move transport parmaters to anynomous struct.
We move ->params transport parameters to ->rx.params. They are the
transport parameters which will be sent to the peer, and used for
the endpoint flow control. So, they will be used to received packets
from the peer (RX part).
Also move ->rx_tps transport parameters to ->tx.params. They are the
transport parameter which are sent by the peer, and used to respect
its flow control limits. So, they will be used when sending packets
to the peer (TX part).
2021-09-23 15:27:25 +02:00
Tim Duesterhus
16554245e2 CLEANUP: Apply bug_on.cocci
The changes look safe to me, even if `DEBUG_STRICT` is not enabled.
2021-09-17 17:22:05 +02:00
Willy Tarreau
2b71810cb3 CLEANUP: lists/tree-wide: rename some list operations to avoid some confusion
The current "ADD" vs "ADDQ" is confusing because when thinking in terms
of appending at the end of a list, "ADD" naturally comes to mind, but
here it does the opposite, it inserts. Several times already it's been
incorrectly used where ADDQ was expected, the latest of which was a
fortunate accident explained in 6fa922562 ("CLEANUP: stream: explain
why we queue the stream at the head of the server list").

Let's use more explicit (but slightly longer) names now:

   LIST_ADD        ->       LIST_INSERT
   LIST_ADDQ       ->       LIST_APPEND
   LIST_ADDED      ->       LIST_INLIST
   LIST_DEL        ->       LIST_DELETE

The same is true for MT_LISTs, including their "TRY" variant.
LIST_DEL_INIT keeps its short name to encourage to use it instead of the
lazier LIST_DELETE which is often less safe.

The change is large (~674 non-comment entries) but is mechanical enough
to remain safe. No permutation was performed, so any out-of-tree code
can easily map older names to new ones.

The list doc was updated.
2021-04-21 09:20:17 +02:00
Willy Tarreau
f509065191 MEDIUM: fd: merge fdtab[].ev and state for FD_EV_* and FD_POLL_* into state
For a long time we've had fdtab[].ev and fdtab[].state which contain two
arbitrary sets of information, one is mostly the configuration plus some
shutdown reports and the other one is the latest polling status report
which also contains some sticky error and shutdown reports.

These ones used to be stored into distinct chars, complicating certain
operations and not even allowing to clearly see concurrent accesses (e.g.
fd_delete_orphan() would set the state to zero while fd_insert() would
only set the event to zero).

This patch creates a single uint with the two sets in it, still delimited
at the byte level for better readability. The original FD_EV_* values
remained at the lowest bit levels as they are also known by their bit
value. The next step will consist in merging the remaining bits into it.

The whole bits are now cleared both in fd_insert() and _fd_delete_orphan()
because after a complete check, it is certain that in both cases these
functions are the only ones touching these areas. Indeed, for
_fd_delete_orphan(), the thread_mask has already been zeroed before a
poller can call fd_update_event() which would touch the state, so it
is certain that _fd_delete_orphan() is alone. Regarding fd_insert(),
only one thread will get an FD at any moment, and it as this FD has
already been released by _fd_delete_orphan() by definition it is certain
that previous users have definitely stopped touching it.

Strictly speaking there's no need for clearing the state again in
fd_insert() but it's cheap and will remove some doubts during some
troubleshooting sessions.
2021-04-07 18:04:39 +02:00
Olivier Houchard
26c51097d8 MEDIUM: quic: Fix build.
Put the ) at the right place.

This should fix github issue #1190.
2021-03-19 20:09:22 +01:00
Olivier Houchard
7ab6d8bdf3 MEDIUM: quic: Fix build.
Spell conn_xprt_start() correctly.

This should fix github issue #1189.
2021-03-19 19:48:53 +01:00
Olivier Houchard
1b3c931bff MEDIUM: connections: Introduce a new XPRT method, start().
Introduce a new XPRT method, start(). The init() method will now only
initialize whatever is needed for the XPRT to run, but any action the XPRT
has to do before being ready, such as handshakes, will be done in the new
start() method. That way, we will be sure the full stack of xprt will be
initialized before attempting to do anything.
The init() call is also moved to conn_prepare(). There's no longer any reason
to wait for the ctrl to be ready, any action will be deferred until start(),
anyway. This means conn_xprt_init() is no longer needed.
2021-03-19 15:33:04 +01:00
Frdric Lcaille
026a7921a5 MINOR: quic: QUIC socket management finalization.
Implement ->accept_conn() callback for QUIC listener sockets.
Note that this patch also implements quic_session_accept() function
which is similar to session_accept_fd() without calling conn_complete_session()
at this time because we do not have any real QUIC mux.
2020-12-23 11:57:26 +01:00
Frdric Lcaille
70da889d57 MINOR: quic: Redefine control layer callbacks which are QUIC specific.
We add src/quic_sock.c QUIC specific socket management functions as callbacks
for the control layer: ->accept_conn, ->default_iocb and ->rx_listening.
accept_conn() will have to be defined. The default I/O handler only recvfrom()
the datagrams received. Furthermore, ->rx_listening callback always returns 1 at
this time but should returns 0 when reloading the processus.
2020-12-23 11:57:26 +01:00