Commit Graph

16997 Commits

Author SHA1 Message Date
Frédéric Lécaille
728b30d750 CLEANUP: quic: Comments fix for qc_prep_(app)pkts() functions
Fix the comments for these two functions about their returned values.
2022-03-11 11:37:31 +01:00
Frédéric Lécaille
d5066dd9dd BUG/MEDIUM: quic: qc_prep_app_pkts() retries on qc_build_pkt() failures
The "stop_build" label aim is to try to reuse the TX buffer when there is not
enough contiguous room to build a packet. It was defined but not used!
2022-03-11 11:37:31 +01:00
Frédéric Lécaille
530601cd84 MEDIUM: quic: Implement the idle timeout feature
The aim of the idle timeout is to silently closed the connection after a period
of inactivity depending on the "max_idle_timeout" transport parameters advertised
by the endpoints. We add a new task to implement this timer. Its expiry is
updated each time we received an ack-eliciting packet, and each time we send
an ack-eliciting packet if no other such packet was sent since we received
the last ack-eliciting packet. Such conditions may be implemented thanks
to QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ new flag.
2022-03-11 11:37:30 +01:00
Frédéric Lécaille
c7a69e2aa5 MINOR: quic: Add a function to compute the current PTO
There was not such a function at this time. This is needed to implement the idle
timeout feature.
2022-03-11 11:37:30 +01:00
Frédéric Lécaille
676b849d37 BUG/MINOR: quic: Missing check when setting the anti-amplification limit as reached
Ensure the peer address is not validated before setting the anti-amplication
limit as reached.
2022-03-11 11:37:30 +01:00
Frédéric Lécaille
12c169aaf0 BUG/MINOR: quic: ACK_REQUIRED and ACK_RECEIVED flag collision
This packet number space flags were defined with the same value because
defined at different places in the file. Assemble them at the same location
with different values.

This bug could unvalidate the peer address after it was validated
during the handshake leading to the anti-amplication limit to be
enabled again after having been disabled. The situation could not
be unblocked (deadlock).
2022-03-11 11:37:30 +01:00
Frédéric Lécaille
f293b69521 MEDIUM: quic: Remove the QUIC connection reference counter
There is no need to use such a reference counter anymore since the QUIC
connections are always handled by the same thread.
quic_conn_drop() is removed. Its code is merged into quic_conn_release().
2022-03-11 11:37:30 +01:00
Frédéric Lécaille
66d37fa051 MINOR: quic: Add max_idle_timeout advertisement handling
When we store the remote transport parameters, we compute the maximum idle
timeout for the connection which is the minimum of the two advertised
max_idle_timeout transport parameter values if both have non-null values, or the
maximum if one of the value is set and non-null.
2022-03-11 11:37:30 +01:00
Willy Tarreau
d2985f3cec BUG/MINOR: session: fix theoretical risk of memleak in session_accept_fd()
Andrew Suffield reported in issue #1596 that we've had a bug in
session_accept_fd() since 2.4 with commit 1b3c931bf ("MEDIUM:
connections: Introduce a new XPRT method, start().") where an error
label is wrong and may cause the leak of the freshly allocated session
in case conn_xprt_start() returns < 0.

The code was checked there and the only two transport layers available
at this point are raw_sock and ssl_sock. The former doesn't provide a
->start() method hence conn_xprt_start() will always return zero. The
second does provide such a function, but it may only return <0 if the
underlying transport (raw_sock) has such a method and fails, which is
thus not the case.

So fortunately it is not possible to trigger this leak.

The patch above also touched the accept code in quic_sock() which was
mostly a plain copy of the session code, but there the move didn't
have this impact, and since then it was simplified and the next change
moved it to its final destination with the proper error label.

This should be backported as far as 2.4 as a long-term safety measure
(e.g. if in the future we have a reason for making conn_xprt_start()
to start failing), but will not have any positive nor negative effect
in the short term.
2022-03-11 07:25:11 +01:00
Willy Tarreau
0657b93385 MINOR: stream: add "last_rule_file" and "last_rule_line" samples
These two sample fetch methods report respectively the file name and the
line number where was located the last rule that was final. This is aimed
at being used on log-format lines to help admins figure what rule in the
configuration gave a final verdict, and help understand the condition
that led to the action.

For example, it's now possible to log the last matched rule by adding
this to the log-format:

  ... lr=%[last_rule_file]:%[last_rule_line]

A regtest is provided to test various combinations of final rules, some
even on top of each other from different rulesets.
2022-03-10 11:51:34 +01:00
Willy Tarreau
c6dae869ca MINOR: rules: record the last http/tcp rule that gave a final verdict
When a tcp-{request,response} content or http-request/http-response
rule delivers a final verdict (deny, accept, redirect etc), the last
evaluated one will now be recorded in the stream. The purpose is to
permit to log the last one that performed a final action. For now
the log is not produced.
2022-03-10 11:51:34 +01:00
Willy Tarreau
3ec1461b03 DOC: sample fetch methods: move distcc_* to the right locations
The distcc* sample fetch methods were surprisingly located within the
"internal state" section, while they in fact depend on L6 contents.
This can be backported to all versions where they appear.
2022-03-10 11:51:34 +01:00
Christopher Faulet
fbff854250 BUG/MAJOR: mux-pt: Always destroy the backend connection on detach
In TCP, when a conn-stream is detached from a backend connection, the
connection must be always closed. It was only performed if an error or a
shutdown occurred or if there was no connection owner. But it is a problem,
because, since the 2.3, backend connections are always owned by a
session. This way it is possible to have idle connections attached to a
session instead of a server. But there is no idle connections in TCP. In
addition, when a session owns a connection it is responsible to close it
when it is released. But it only works for idle connections. And it only
works if the session is released.

Thus there is the place for bugs here. And indeed, a connection leak may
occur if a connection retry is performed because of a timeout. In this case,
the underlying connection is still alive and is waiting to be fully
established. Thus, when the conn-stream is detached from the connection, the
connection is not closed. Because the PT multiplexer is quite simple, there
is no timeout at this stage. We depend on the kenerl to be notified and
finally close the connection. With an unreachable server, orphan backend
connections may be accumulated for a while. It may be perceived as a leak.

Because there is no reason to keep such backend connections, we just close
it now. Frontend connections are still closed by the session or when an
error or a shutdown occurs.

This patch should fix the issue #1522. It must be backported as far as
2.0. Note that the 2.2 and 2.0 are not affected by this bug because there is
no owner for backend TCP connections. But it is probably a good idea to
backport the patch on these versions to avoid any future bugs.
2022-03-09 15:56:00 +01:00
Tim Duesterhus
a6a3279188 CLEANUP: fcgi: Use istadv() in fcgi_strm_send_params
Found manually, while creating the previous commits to turn `struct proxy`
members into ists.

There is an existing Coccinelle rule to replace this pattern by `istadv()` in
`ist.cocci`:

    @@
    struct ist i;
    expression e;
    @@

    - i.ptr += e;
    - i.len -= e;
    + i = istadv(i, e);

But apparently it is not smart enough to match ists that are stored in another
struct. It would be useful to make the existing rule more generic, so that it
might catch similar cases in the future.
2022-03-09 07:51:27 +01:00
Tim Duesterhus
98f05f6a38 CLEANUP: fcgi: Replace memcpy() on ist by istcat()
This is a little cleaner, because the length of the resulting string does not
need to be calculated manually.
2022-03-09 07:51:27 +01:00
Tim Duesterhus
b4b03779d0 MEDIUM: proxy: Store server_id_hdr_name as a struct ist
The server_id_hdr_name is already processed as an ist in various locations lets
also just store it as such.

see 0643b0e7e ("MINOR: proxy: Make `header_unique_id` a `struct ist`") for a
very similar past commit.
2022-03-09 07:51:27 +01:00
Tim Duesterhus
e502c3e793 MINOR: proxy: Store orgto_hdr_name as a struct ist
The orgto_hdr_name is already processed as an ist in `http_process_request`,
lets also just store it as such.

see 0643b0e7e ("MINOR: proxy: Make `header_unique_id` a `struct ist`") for a
very similar past commit.
2022-03-09 07:51:27 +01:00
Tim Duesterhus
b50ab8489e MINOR: proxy: Store fwdfor_hdr_name as a struct ist
The fwdfor_hdr_name is already processed as an ist in `http_process_request`,
lets also just store it as such.

see 0643b0e7e ("MINOR: proxy: Make `header_unique_id` a `struct ist`") for a
very similar past commit.
2022-03-09 07:51:27 +01:00
Tim Duesterhus
4b1fcaaee3 MINOR: proxy: Store monitor_uri as a struct ist
The monitor_uri is already processed as an ist in `http_wait_for_request`, lets
also just store it as such.

see 0643b0e7e ("MINOR: proxy: Make `header_unique_id` a `struct ist`") for a
very similar past commit.
2022-03-09 07:51:27 +01:00
Christopher Faulet
5ce1299c64 DEBUG: stream: Fix stream trace message to print response buffer state
Channels buffer state is displayed in the strem trace messages. However,
because of a typo, the request buffer was used instead of the response one.

This patch should be backported as far as 2.2.
2022-03-08 18:31:44 +01:00
Christopher Faulet
5001913033 DEBUG: stream: Add the missing descriptions for stream trace events
The description for STRM_EV_FLT_ANA and STRM_EV_FLT_ERR was missing.

This patch should be backported as far as 2.2.
2022-03-08 18:31:44 +01:00
Christopher Faulet
e8cefacfa9 BUG/MEDIUM: mcli: Properly handle errors and timeouts during reponse processing
The response analyzer of the master CLI only handles read errors. So if
there is a write error, the session remains stuck because some outgoing data
are blocked in the channel and the response analyzer waits everything to be
sent. Because the maxconn is set to 10 for the master CLI, it may be
unresponsive if this happens to many times.

Now read and write errors, timeouts and client aborts are handled.

This patch should solve the issue #1512. It must be backported as far as
2.0.
2022-03-08 18:31:44 +01:00
Christopher Faulet
8b1eed16d0 DEBUG: cache: Update underlying buffer when loading HTX message in cache applet
In the I/O handler of the cache applet, we must update the underlying buffer
when the HTX message is loaded, using htx_from_buf() function instead of
htxbuf(). It is important because the applet will update the message by
adding new HTX blocks. This way, the state of the underlying buffer remains
consistant with the state of the HTX message.

It is especially important if HAProxy is compiled with "DEBUG_STRICT=2"
mode. Without this patch, channel_add_input() call crashed if the channel
was empty at the begining of the I/O handler.

Note that it is more a build/debug issue than a bug. But this patch may
prevent future bugs. For now it is safe because htx_to_buf() function is
systematically called, updating accordingly the underlying buffer.

This patch may be backported as far as 2.0.
2022-03-08 18:29:20 +01:00
Christopher Faulet
e9382e0afe BUG/MEDIUM: stream: Use the front analyzers for new listener-less streams
For now, for a stream, request analyzers are set at 2 stages. The first one
is when the stream is created. The session's listener analyzers, if any, are
set on the request channel. In addition, some HTTP analyzers are set for HTX
streams (AN_REQ_WAIT_HTTP and AN_REQ_HTTP_PROCESS_FE). The second one is
when the backend is set on the stream. At the stage, request analyzers are
updated using the backend settings.

It is an issue for client applets because there is no listener attached to
the stream. In addtion, it may have no specific/dedicated backend. Thus,
several request analyzers are missing. Among others, the HTTP analyzers for
HTTP applets. The HTTP client is the only one affected for now.

To fix the bug, when a stream is created without a listener, we use the
frontend to set the request analyzers. Note that there is no issue with the
response channel because its analyzers are set when the server connection is
established.

This patch may be backported to all stable versions. Because only the HTTP
client is affected, it must at least be backported to 2.5. It is related to
the issue #1593.
2022-03-08 18:27:47 +01:00
Christopher Faulet
bef64b23b7 BUG/MINOR: promex: Set conn-stream/channel EOI flags at the end of request
This bug is the same than for the HTTP client. See "BUG/MINOR: httpclient:
Set conn-stream/channel EOI flags at the end of request" for details.

This patch must be backported as far as 2.0. But only CF_EOI must be set
because applets are not attached to a conn-stream on older versions.
2022-03-08 18:24:16 +01:00
Christopher Faulet
dbf1e88e87 BUG/MINOR: cache: Set conn-stream/channel EOI flags at the end of request
This bug is the same than for the HTTP client. See "BUG/MINOR: httpclient:
Set conn-stream/channel EOI flags at the end of request" for details.

Note that because a filter is always attached to the stream when the cache
is used, there is no issue because there is no direct forwarding in this
case. Thus the stream analyzers are able to see the HTX_FL_EOM flag on the
HTX messge.

This patch must be backported as far as 2.0. But only CF_EOI must be set
because applets are not attached to a conn-stream on older versions.
2022-03-08 18:24:16 +01:00
Christopher Faulet
3fa5d19d14 BUG/MINOR: stats: Set conn-stream/channel EOI flags at the end of request
This bug is the same than for the HTTP client. See "BUG/MINOR: httpclient:
Set conn-stream/channel EOI flags at the end of request" for details.

This patch must be backported as far as 2.0. But only CF_EOI must be set
because applets are not attached to a conn-stream on older versions.
2022-03-08 18:24:16 +01:00
Christopher Faulet
d8d2708cfe BUG/MINOR: hlua: Set conn-stream/channel EOI flags at the end of request
This bug is the same than for the HTTP client. See "BUG/MINOR: httpclient:
Set conn-stream/channel EOI flags at the end of request" for details.

This patch must be backported as far as 2.0. But only CF_EOI must be set
because applets are not attached to a conn-stream on older versions.
2022-03-08 18:24:16 +01:00
Christopher Faulet
3d4332419c BUG/MINOR: httpclient: Set conn-stream/channel EOI flags at the end of request
In HTX, HTX_FL_EOM flag is added on the message to notifiy the end of the
message was received. In addition, the producer must set CS_FL_EOI flag on
the conn-stream. If it is a mux, the stream-interface is responsible to set
CF_EOI flag on the input channel. But, for now, if the producer is an
applet, in addition to the conn-stream flag, it must also set the channel
one.

These flags are used to notify the stream that the message is finished and
no more data are expected. It is especially important when the message
itself it directly forwarded from one side to the other. Because in this
case, the stream has no way to see the HTX_FL_EOM flag on the
message. Otherwise, the stream will detect a client or a server abort,
depending on the side.

For the HTTP client, it is not really easy to diagnose this error because
there is also another bug hiding this one. All HTTP request analyzers are
not set on the input channel. This will be fixed by another patch.

This patch must be backported to 2.5. It is related to the issue #1593.
2022-03-08 16:33:56 +01:00
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
Marno Krahmer
a690b73fba MINOR: stats: Add dark mode support for socket rows
In commit e9ed63e548 dark mode support was added to the stats page. The
initial commit does not include  dark mode color overwrites for the
.socket CSS class. This commit colors socket rows the same way as
backends that acre active but do not have a health check defined.

This fixes an issue where reading information from socket lines became
really hard in dark mode due to suboptimal coloring of the cell
background and the font in it.
2022-03-08 14:47:23 +01:00
Amaury Denoyelle
20f89cac95 BUG/MEDIUM: quic: do not drop packet on duplicate stream/decoding error
Change the return value to success in qc_handle_bidi_strm_frm for two
specific cases :
* if STREAM frame is an already received offset
* if application decoding failed

This ensures that the packet is not dropped and properly acknowledged.
Previous to this fix, the return code was set to error which prevented
the ACK to be generated.

The impact of the bug might be noticeable in environment with packet
loss and retransmission. Due to haproxy not generating ACK for packets
containing STREAM frames with already received offset, the client will
probably retransmit them again, which will worsen the network
transmission.
2022-03-08 14:36:32 +01:00
William Lallemand
b0dfd099c5 BUG/MINOR: cli: shows correct mode in "show sess"
The "show sess" cli command only handles "http" or "tcp" as a fallback
mode, replace this by a call to proxy_mode_str() to show all the modes.

Could be backported in every maintained versions.
2022-03-08 12:21:36 +01:00
William Lallemand
06715af9e5 BUG/MINOR: add missing modes in proxy_mode_str()
Add the missing PR_MODE_SYSLOG and PR_MODE_PEERS in proxy_mode_str().

Could be backported in every maintained versions.
2022-03-08 12:21:36 +01:00
Willy Tarreau
c4e56dc58c MINOR: pools: add a new global option "no-memory-trimming"
Some users with very large numbers of connections have been facing
extremely long malloc_trim() calls on reload that managed to trigger
the watchdog! That's a bit counter-productive. It's even possible
that some implementations are not perfectly reliable or that their
trimming time grows quadratically with the memory used. Instead of
constantly trying to work around these issues, let's offer an option
to disable this mechanism, since nobody had been complaining in the
past, and this was only meant to be an improvement.

This should be backported to 2.4 where trimming on reload started to
appear.
2022-03-08 10:45:03 +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
Frédéric Lécaille
ba9db40b07 CLEANUP: quic: Remove QUIC path manipulations out of the congestion controller
QUIC connection path in flight bytes is a variable which should not be manipulated
by the congestion controller. This latter aim is to compute the congestion window.
So, we pass it as less as parameters as possible to do so.
2022-03-04 17:47:32 +01:00
Frédéric Lécaille
4d3d36b670 BUG/MINOR: quic: Missing recovery start timer reset
The recovery start time must be reset after a persistent congestion has been
detected.
2022-03-04 17:47:32 +01:00
Frédéric Lécaille
05e30ee7d5 MINOR: quic: Retry on qc_build_pkt() failures
This is done going to stop_build label when qc_build_pkt() fails
because of a lack of buffer room (returns -1).
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
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