8446 Commits

Author SHA1 Message Date
Frédéric Lécaille
301425b880 MEDIUM: quic: Compatible version negotiation implementation (draft-08)
At this time haproxy supported only incompatible version negotiation feature which
consists in sending a Version Negotiation packet after having received a long packet
without compatible value in its version field. This version value is the version
use to build the current packet. This patch does not modify this behavior.

This patch adds the support for compatible version negotiation feature which
allows endpoints to negotiate during the first flight or packets sent by the
client the QUIC version to use for the connection (or after the first flight).
This is done thanks to "version_information" parameter sent by both endpoints.
To be short, the client offers a list of supported versions by preference order.
The server (or haproxy listener) chooses the first version it also supported as
negotiated version.

This implementation has an impact on the tranport parameters handling (in both
direcetions). Indeed, the server must sent its version information, but only
after received and parsed the client transport parameters). So we cannot
encode these parameters at the same time we instantiated a new connection.

Add QUIC_TP_DRAFT_VERSION_INFORMATION(0xff73db) new transport parameter.
Add tp_version_information new C struct to handle this new parameter.
Implement quic_transport_param_enc_version_info() (resp.
quic_transport_param_dec_version_info()) to encode (resp. decode) this
parameter.
Add qc_conn_finalize() which encodes the transport parameters and configure
the TLS stack to send them.
Add ->negotiated_ictx quic_conn C struct new member to store the Initial
QUIC TLS context for the negotiated version. The Initial secrets derivation
is version dependent.
Rename ->version to ->original_version and add ->negotiated_version to
this C struct to reflect the QUIC-VN RFC denomination.
Modify most of the QUIC TLS API functions to pass a version as parameter.
Export the QUIC version definitions to be reused at least from quic_tp.c
(transport parameters.
Move the token check after the QUIC connection lookup. As this is the original
version which is sent into a Retry packet, and because this original version is
stored into the connection, we must check the token after having retreived this
connection.
Add packet version to traces.

See https://datatracker.ietf.org/doc/html/draft-ietf-quic-version-negotiation-08
for more information about this new feature.
2022-06-16 15:58:48 +02:00
Frédéric Lécaille
86845c5171 MEDIUM: quic: Add QUIC v2 draft support
This is becoming difficult to handle the QUIC TLS related definitions
which arrive with a QUIC version (draft or not). So, here we add
quic_version C struct which does not define only the QUIC version number,
but also the QUIC TLS definitions which depend on a QUIC version.
Modify consequently all the QUIC TLS API to reuse these definitions
through new quic_version C struct.
Implement quic_pkt_type() function which return a packet type (0 up to 3)
depending on the QUIC version number.
Stop harding the Retry packet first byte in send_retry(): this is not more
possible because the packet type field depends on the QUIC version.
Also modify quic_build_packet_long_header() for the same reason: the packet
type depends on the QUIC version.
Add a quic_version C struct member to quic_conn C struct.
Modify qc_lstnr_pkt_rcv() to set this member asap.
Remove the version member from quic_rx_packet C struct: a packet is attached
asap to a connection (or dropped) which is the unique object which should
store the QUIC version.
Modify qc_pkt_is_supported_version() to return a supported quic_version C
struct from a version number.
Add Initial salt for QUIC v2 draft (initial_salt_v2_draft).
2022-06-16 14:56:24 +02:00
Frédéric Lécaille
83bf9ca25a CLEANUP: quid: QUIC draft-28 no more supported
Remove this useless definition.
2022-06-16 14:56:24 +02:00
Frédéric Lécaille
fa94f77bc5 BUG/MINOR: quic: Wrong PTO calculation
Due to missing brackets around the ternary C operator, quic_pto() could return zero
at the first run, before the QUIC connection was completely initialized. This leaded
the idle timeout task to be executed before this initialization completion. Then
this connection could be immediately released.

This bug was revealed by the multi_packet_client_hello QUIC tracker test.

Must be backported to 2.6.
2022-06-16 14:56:24 +02:00
Frédéric Lécaille
3f96a0a4c1 MINOR: quic: Add several nonce and key definitions for Retry tag
The nonce and keys used to cipher the Retry tag depend on the QUIC version.
Add these definitions for 0xff00001d (draft-29) and v2 QUIC version. At least
draft-29 is useful for QUIC tracker tests with "quic-force-retry" enabled
on haproxy side.
Validated with -v 0xff00001d ngtcp2 option.
Could not validate the v2 nonce and key at this time because not supported.
2022-06-16 14:56:24 +02:00
Amaury Denoyelle
60ef19f137 BUG/MINOR: h3/qpack: deal with too many headers
ensures that we never insert too many entries in a headers input list.
On the decoding side, a new error QPACK_ERR_TOO_LARGE is reported in
this case.

This prevents crash if headers number on a H3 request or response is
superior to tune.http.maxhdr config value. Previously, a crash would
occur in QPACK decoding function.

Note that the process still crashes later with ABORT_NOW() because error
reporting on frame parsing is not implemented for now. It should be
treated with a RESET_STREAM frame in most cases.

This can be backported up to 2.6.
2022-06-15 15:05:08 +02:00
Amaury Denoyelle
53eef46b88 MINOR: qpack: reduce dependencies on other modules
Clean up QPACK decoder API by removing dependencies on ncbuf and
MUX-QUIC. This reduces includes statements. It will also help to
implement a standalone QPACK decoder.
2022-06-15 11:20:48 +02:00
Amaury Denoyelle
c5d31ed8be MINOR: qpack: add comments and remove a useless trace
Add comments on the decoding function to facilitate code analysis.

Also remove the qpack_debug_hexdump() which prints the whole left buffer
on each header parsing. With large HEADERS frame payload, QPACK traces
are complicated to debug with this statement.
2022-06-15 11:20:42 +02:00
Willy Tarreau
3ccb14d60d MINOR: thread: get rid of MAX_THREADS_MASK
This macro was used both for binding and for lookups. When binding tasks
or FDs, using all_threads_mask instead is better as it will later be per
group. For lookups, ~0UL always does the job. Thus in practice the macro
was already almost not used anymore since the rest of the code could run
fine with a constant of all ones there.
2022-06-14 11:18:40 +02:00
Willy Tarreau
1a85a958dd MINOR: tinfo: remove the global thread ID bit (tid_bit)
Each thread has its own local thread id and its own global thread id,
in addition to the masks corresponding to each. Once the global thread
ID can go beyond 64 it will not be possible to have a global thread Id
bit anymore, so better start to remove it and use only the local one
from the struct thread_info.
2022-06-14 10:44:38 +02:00
Willy Tarreau
680ed5f28b MINOR: task: move profiling bit to per-thread
Instead of having a global mask of all the profiled threads, let's have
one flag per thread in each thread's flags. They are never accessed more
than one at a time an are better located inside the threads' contexts for
both performance and scalability.
2022-06-14 10:38:03 +02:00
Amaury Denoyelle
b9e0640405 BUG/MEDIUM: mux-quic: fix flow control connection Tx level
The flow control enforced at connection level is incorrectly calculated.
There is a risk of exceeding the limit. In most cases, this results in a
segfault produced by a BUG_ON which is here to catch this kind of error.
If not compiled with DEBUG_STRICT, this should generate a connection
closed by the client due to the flow control overflow.

The problem is encountered when transfered payload is big enough to fill
the transport congestion window. In this case, some data are rejected by
the transport layer and kept by the MUX to be reemitted later. However,
these preserved data are not counted on the connection flow control when
resubmitted, which gradually amplify the gap between expected and real
consumed flow control.

To fix this, handle the flow-control at the connection level in the same
way as the stream level. A new field qcc.tx.offsets is incremented as
soon as data are transfered between stream TX buffers. The field
qcc.tx.sent_offsets is preserved to count bytes handled by the transport
layer and stop the MUX transfer if limit is reached.

As already stated, this bug can occur during transfers with enough
emitted data, over multiple streams. When using a single stream, the
flow control at the stream level hides it.

The BUG_ON crash is reproduced systematically with quiche client :
$ quiche-client --no-verify --http-version HTTP/3 -n 10000 https://127.0.0.1:20443/10K

This must be backported up to 2.6 when confirmed to work as expected.

This should fix github issue #1738.
2022-06-10 17:30:41 +02:00
Amaury Denoyelle
c715eb7898 BUG/MINOR: h3: fix frame type definition
Frame type has changed during HTTP/3 specification process. Adjust it to
reflect the latest RFC 9114 status.

Concretly, type for GOAWAY and MAX_PUSH_ID frames has been adjusted.
The impact of this bug is limited as currently these frames are not
handled by haproxy and are ignored.

This can be backported up to 2.6.
2022-06-09 14:34:43 +02:00
Willy Tarreau
7d318ed8cc BUILD: compiler: implement unreachable for older compilers too
Benoit Dolez reported that gcc-4.4 emits several "may be used
uninitialized" warnings around places where there are BUG_ON()
or ABORT_NOW(). The reason is that __builtin_unreachable() was
introduced in gcc-4.5 thus older ones do not know that the code
after such statements is not reachable.

This patch solves the problem by deplacing the statement with
an infinite loop on older versions. The compiler knows that the
code following it cannot be reached, and this is quite cheap
(2 to 4 bytes depending on architectures). It even reduces the
code size a little bit as the compiler doesn't have to optimize
for branches that do not exist.

This may be backported to older versions.
2022-06-08 12:17:22 +02:00
Amaury Denoyelle
1f21ebdd76 MINOR: mux-quic/h3: adjust demuxing function return values
Clean the API used by decode_qcs() and transcoder internal functions.
Parsing functions now returns a ssize_t which represents the number of
consumed bytes or a negative error code. The total consumed bytes is
returned via decode_qcs().

The API is now unified and cleaner. The MUX can thus simply use the
return value of decode_qcs() instead of substracting the data bytes in
the buffer before and after the call. Transcoders functions are not
anymore obliged to remove consumed bytes from the buffer which was not
obvious.
2022-06-07 18:15:47 +02:00
Amaury Denoyelle
62eef85961 MINOR: mux-quic: simplify decode_qcs API
Slightly modify decode_qcs function used by transcoders. The MUX now
gives a buffer instance on which each transcoder is free to work on it.
At the return of the function, the MUX removes consume data from its own
buffer.

This reduces the number of invocation to qcs_consume at the end of a
full demuxing process. The API is also cleaner with the transcoders not
responsible of calling it with the risk of having the input buffer
freed if empty.
2022-06-07 18:15:47 +02:00
Amaury Denoyelle
c0156790e6 MINOR: h3: add h3c pointer into h3s instance
As a mirror to qcc/qcs types, add a h3c pointer into h3s struct. This
should help to clean up H3 code and avoid to use qcs.qcc.ctx to retrieve
the h3c instance.
2022-06-07 18:13:11 +02:00
Willy Tarreau
29698e39ed [RELEASE] Released version 2.7-dev0
Released version 2.7-dev0 with the following main changes :
    - MINOR: version: it's development again
2022-05-31 17:05:27 +02:00
Willy Tarreau
6391bb2de0 MINOR: version: it's development again
This essentially reverts b2c1e081f7f61d16697a6c6d8312062baf291eb6.
2022-05-31 17:04:45 +02:00
Willy Tarreau
b2c1e081f7 MINOR: version: mention that it's LTS now.
The version will be maintained up to around Q2 2027. Let's
also update the INSTALL file to mention this.
2022-05-31 16:53:13 +02:00
Willy Tarreau
91a87918c9 BUILD: quic: use inttypes.h instead of stdint.h
The usual build joke on uncommon systems (AIX this time, though some
versions of Solaris are known for missing it as well).
2022-05-30 16:37:17 +02:00
Willy Tarreau
771483da3e MINOR: htx: add an unchecked version of htx_get_head_blk()
htx_get_head_blk() is used at plenty of places, many of which are known
to be safe, but the function checks for the presence of a first block
and returns NULL if it doesn't exist. While it's properly used, it makes
compilers complain at -Os on stream.c and mux_fcgi.c because they probably
don't propagate variables far enough to see that there's no risk.

Let's add an unchecked version for these use cases.
2022-05-30 16:25:16 +02:00
Frédéric Lécaille
6f7607ef1f MINOR: h3: Add a statistics module for h3
Add ->inc_err_cnt new callback to qcc_app_ops struct which can
be called from xprt to increment the application level error code counters.
It take the application context as first parameter to be generic and support
new QUIC applications to come.
Add h3_stats.c module with counters for all the frame types and error codes.
2022-05-30 09:59:26 +02:00
Frédéric Lécaille
eb79145f01 MINOR: quic_stats: Add transport new counters (lost, stateless reset, drop)
Add new counters to count the number of dropped packet upon parsing error, lost
sent packets and the number of stateless reset packet sent.
Take the oppportunity of this patch to rename CONN_OPENINGS to QUIC_ST_HALF_OPEN_CONN
(total number of half open connections) and QUIC_ST_HDSHK_FAILS to QUIC_ST_HDSHK_FAIL.
2022-05-30 09:59:26 +02:00
Frédéric Lécaille
3ccea6d276 MINOIR: quic_stats: add QUIC connection errors counters
Add statistical counters for all the transport level connection errrors.
2022-05-30 09:59:26 +02:00
Frédéric Lécaille
aee675746c MINOR: quic: Clarifications about transport parameters value
This is becoming difficult to distinguish the default values for
transport parameters which come with the RFC from our implementation
default values when not set by configuration (tunable parameters).
Add a comment to distinguish them.
Prefix these default values by QUIC_TP_DFLT_ to distinguish them from
QUIC_DFLT_* value even if there are not numerous.
Furthermore ->max_udp_payload_size must be first initialized to
QUIC_TP_DFLT_MAX_UDP_PAYLOAD_SIZE especially for received value.
2022-05-30 09:59:26 +02:00
Frédéric Lécaille
2674098569 MINOR: quic: Tunable "initial_max_streams_bidi" transport parameter
Add tunable "tune.quic.frontend.max_streams_bidi" setting for QUIC frontends
to set the "initial_max_streams_bidi" transport parameter.
Add some documentation for this new setting.
2022-05-30 09:59:26 +02:00
Frédéric Lécaille
1d96d6e024 MINOR: quic: Tunable "max_idle_timeout" transport parameter
Add two tunable settings both for backends and frontends "max_idle_timeout"
QUIC transport parameter, "tune.quic.frontend.max-idle-timeout" and
"tune.quic.backend.max-idle-timeout" respectively.
cfg_parse_quic_time() has been implemented to parse a time value thanks
to parse_time_err(). It should be reused for any tunable time value to be
parsed.
Add the documentation for this tunable setting only for frontend.
2022-05-30 09:59:26 +02:00
Frédéric Lécaille
c7785b5c26 MINOR: quic: Transport parameters dump
Add quic_transport_params_dump() static inline function to do so for
a quic_transport_parameters struct as parameter.
We use the trace API do dump these transport parameters both
after they have been initialized (RX/local) or received (TX/remote).
2022-05-30 09:59:26 +02:00
Frédéric Lécaille
748ece68b8 MINOR: quic: QUIC transport parameters split.
Make the transport parameters be standlone as much as possible as
it consists only in encoding/decoding data into/from buffers.
Reduce the size of xprt_quic.h. Unfortunalety, I think we will
have to continue to include <xprt_quic-t.h> to use the trace API
into this module.
2022-05-30 09:59:26 +02:00
Frédéric Lécaille
57ac3faed7 CLEANUP: quic: No more used handshake output buffer
->obuf quic_conn struct member is no more used.
2022-05-30 09:59:26 +02:00
Frédéric Lécaille
56f61b663b CLEANUP: quic: Useless QUIC_CONN_TX_BUF_SZ definition
This define is not more used.
2022-05-30 09:59:26 +02:00
Willy Tarreau
da59c895b9 CLEANUP: stconn: remove the new unneeded SE_FL_APP_MASK
The only two places where it was used was to carefully preserve the
SE_FL_WILL_CONSUME flag (since others are irrelevant there and the
previous RXBLK* flags moved to the stconn). Now that the flag is
cleared by default there's no need to re-created a fresh new one
when replacing the descriptor, so we can eliminate that remaining
trick.
2022-05-27 19:33:35 +02:00
Willy Tarreau
e4ebe261b1 MINOR: stconn: turn SE_FL_WILL_CONSUME to SE_FL_WONT_CONSUME
This flag was the only remaining one that was inverted as a blocking
condition, requiring special handling to preset it on sedesc allocation.
Let's flip it in its definition and accessors.
2022-05-27 19:33:35 +02:00
Willy Tarreau
d7b7e0df9a CLEANUP: mux-quic: rename the "endp" field to "sd"
The stream endpoint descriptor that was named "endp" is now called "sd"
both in the qcs struct and in the few functions using this.
2022-05-27 19:33:35 +02:00
Willy Tarreau
e68bc6178a CLEANUP: stconn: replace a few remaining occurrences of CS in comments or traces
A few "CS" desginating stconns were still present in code comments and
stream traces. This addresses them.
2022-05-27 19:33:35 +02:00
Willy Tarreau
1d2c79a53c CLEANUP: obj_type: rename OBJ_TYPE_CS to OBJ_TYPE_SC
Let's apply the new name to the type as well.
2022-05-27 19:33:35 +02:00
Willy Tarreau
df1a2fc234 CLEANUP: stream: rename stream_upgrade_from_cs() to stream_upgrade_from_sc()
It upgrades the protocol on a stream connector, let's update the name.
2022-05-27 19:33:35 +02:00
Willy Tarreau
c12b321661 CLEANUP: applet: rename appctx_cs() to appctx_sc()
It returns a stream connector, not a conn_stream anymore, so let's
fix its name.
2022-05-27 19:33:35 +02:00
Willy Tarreau
caff631bc0 CLEANUP: stats: rename all occurrences of stconn "cs" to "sc"
Function arguments and local variables called "cs" were renamed to "sc"
to avoid future confusion. Both the core functions and the ones in the
resolvers files were updated.
2022-05-27 19:33:35 +02:00
Willy Tarreau
b49672d21f CLEANUP: stream: rename all occurrences of stconn "cs" to "sc"
Function arguments and local variables called "cs" were renamed to "sc"
to avoid future confusion. The HTTP analyser and the backend functions
were all updated after being reviewed. Function stream_update_both_cs()
was renamed to stream_update_both_sc()
2022-05-27 19:33:35 +02:00
Willy Tarreau
3215e731b6 CLEANUP: quic/h3: rename all occurrences of stconn "cs" to "sc"
Function arguments and local variables called "cs" were renamed to "sc"
to avoid future confusion. The "nb_cs" stream-connector counter was
renamed to "nb_sc" and qc_attach_cs() was renamed to qc_attach_sc().
2022-05-27 19:33:35 +02:00
Willy Tarreau
0adb281fb0 CLEANUP: stconn: rename all occurrences of stconn "cs" to "sc"
Function arguments and local variables called "cs" were renamed to "sc"
to avoid future confusion. The change is huge (~580 lines), so extreme
care was given not to change anything else.
2022-05-27 19:33:35 +02:00
Willy Tarreau
61f5675cb4 CLEANUP: connection: rename all occurrences of stconn "cs" to "sc"
Function arguments and local variables called "cs" were renamed to "sc"
to avoid future confusion.
2022-05-27 19:33:35 +02:00
Willy Tarreau
bde14ad499 CLEANUP: check: rename all occurrences of stconn "cs" to "sc"
The check struct had a "cs" field renamed to "sc", which also required
a tiny update to a few functions using it to distinguish a check from
a stream (log.c, payload.c, ssl_sample.c, tcp_sample.c, tcpcheck.c,
connection.c).

Function arguments and local variables called "cs" were renamed to "sc".
The presence of one "cs=" in the debugging traces was also turned to
"sc=" for consistency.
2022-05-27 19:33:35 +02:00
Willy Tarreau
d137353ae3 CLEANUP: muxes: rename "get_first_cs" to "get_first_sc"
This is renamed both in the mux_ops descriptor and the mux functions
themselves to accommodate the new type name.
2022-05-27 19:33:35 +02:00
Willy Tarreau
cb086c6de1 REORG: stconn: rename conn_stream.{c,h} to stconn.{c,h}
There's no more reason for keepin the code and definitions in conn_stream,
let's move all that to stconn. The alphabetical ordering of include files
was adjusted.
2022-05-27 19:33:35 +02:00
Willy Tarreau
5edca2f0e1 REORG: rename cs_utils.h to sc_strm.h
This file contains all the stream-connector functions that are specific
to application layers of type stream. So let's name it accordingly so
that it's easier to figure what's located there.

The alphabetical ordering of include files was preserved.
2022-05-27 19:33:35 +02:00
Willy Tarreau
74568cf023 CLEANUP: stconn: rename final state manipulation functions from cs_* to sc_*
This applies the following renaming. It's a bit large but pretty
mechanical:

cs_state -> sc_state  (enum)

cs_alloc_ibuf() -> sc_alloc_ibuf()
cs_is_conn_error() -> sc_is_conn_error()
cs_opposite() -> sc_opposite()
cs_report_error() -> sc_report_error()
cs_set_state() -> sc_set_state()
cs_state_bit() -> sc_state_bit()
cs_state_in() -> sc_state_in()
cs_state_str() -> sc_state_str()
2022-05-27 19:33:35 +02:00
Willy Tarreau
f61dd19284 CLEANUP: stconn: rename cs_{shut,chk}* to sc_*
This applies the following renaming:

cs_shutr() -> sc_shutr()
cs_shutw() -> sc_shutw()
cs_chk_rcv() -> sc_chk_rcv()
cs_chk_snd() -> sc_chk_snd()
cs_must_kill_conn() -> sc_must_kill_conn()
2022-05-27 19:33:35 +02:00