17548 Commits

Author SHA1 Message Date
Christopher Faulet
08c8f8e20d MEDIUM: check: No longer shutdown the connection in .wake callback function
The connection is already closed by the health-check itself. Thus there is
now reason to duplicate this part in the .wake callback function. It is
enough to wake the health-check and wait.
2022-05-19 10:12:38 +02:00
Christopher Faulet
6d781f612a BUG/MINOR: check: Reinit the buffer wait list at the end of a check
The buffer wait list is used to deal with buffer allocation failure. But at
the end of health-check, it must be reinitialized. There is no reason to
reason to get a buffer between two health-check runs. And in fact, the
associated flags, CHK_ST_IN_ALLOC and CHK_ST_OUT_ALLOC, are already cleared
at the end of a health-check.

This patch must be backported as far as 2.2. On the 2.2, MT_LIST_ADDED and
MT_LIST_DEL must be used instead of LIST_INLIST and LIST_DEL_INIT.
2022-05-19 10:12:38 +02:00
Christopher Faulet
dfe32c7e15 BUG/MEDIUM: config: Reset outline buffer size on realloc error in readcfgfile()
When the line parsing failed because outline buffer must be reallocated, if
my_realloc2() call fails, the buffer size must be reset. Indeed, in this case
the current line is skipped, a fatal error is reported and we jump to the next
line. At this stage the outline buffer is NULL. If the buffer size is not reset,
the next call to parse_line() crashes because we try to write in the buffer. We
fail to detect the outline buffer is too small to copy any character.

To fix the issue, outlinesize variable must be set to 0 when outline allocation
failed.

This patch should fix the issue #1563. It must be backported as far as 2.2.
2022-05-19 10:12:38 +02:00
Amaury Denoyelle
8b87b15c22 MINOR: mux-quic: free RX buf if empty
Release the QCS RX buffer if emptied afer qcs_consume(). This improves
memory usage and avoids a QCS to keep an allocated buffer, particularly
when no data is received anymore. Buffer is automatically reallocated if
needed via qc_get_ncbuf().
2022-05-18 16:25:07 +02:00
Amaury Denoyelle
7313f5ee7e BUG/MINOR: mux-quic: support nul buffer with qc_free_ncbuf()
qc_free_ncbuf() may now be used with a NCBUF_NULL buffer as parameter.
This is useful when using this function on a QCS with no allocated
buffer. This case was not reproduced for the moment, but it will soon
become more present as buffers will be released if emptied.

Also a call to offer_buffers() is added to conform with the dynamic
buffer management of haproxy.
2022-05-18 16:25:07 +02:00
Amaury Denoyelle
c830e1e904 MINOR: mux-quic: implement MAX_DATA emission
This commit is similar to the previous one but deals with MAX_DATA for
connection-level data flow control. It uses the same function
qcc_consume_qcs() to update flow control level and generate a MAX_DATA
frame if needed.
2022-05-18 16:25:07 +02:00
Amaury Denoyelle
a977355aa1 MINOR: mux-quic: implement MAX_STREAM_DATA emission
Send MAX_STREAM_DATA frames when at least half of the allocated
flow-control has been demuxed, frame and cleared. This is necessary to
support QUIC STREAM with received data greater than a buffer.

Transcoders must use the new function qcc_consume_qcs() to empty the QCS
buffer. This will allow to monitor current flow-control level and
generate a MAX_STREAM_DATA frame if required. This frame will be emitted
via qc_io_cb().
2022-05-18 16:25:07 +02:00
Amaury Denoyelle
c985cb167d MINOR: mux-quic: reorganize flow-control frames emission
Adjust the mechanism for MAX_STREAMS_BIDI emission. When a bidirectional
stream is removed, current flow-control level is checked. If needed, a
MAX_STREAMS_BIDI frame is generated and inserted in a new list in the
QCS instance. The new frames will be emitted at the start of qc_send().

This has no impact on the current MAX_STREAMS_BIDI behavior. However,
this mechanism is more flexible and will allow to implement quickly
MAX_STREAM_DATA/MAX_DATA emission.
2022-05-18 15:52:44 +02:00
Amaury Denoyelle
3a0864067a MINOR: mux-quic: remove qcc_decode_qcs() call in XPRT
Slightly change the interface for qcc_recv() between MUX and XPRT. The
MUX is now responsible to call qcc_decode_qcs(). This is cleaner as now
the XPRT does not have to deal with an extra QCS parameter and the MUX
will call qcc_decode_qcs() only if really needed.

This change is possible since there is no extra buffering for
out-of-order STREAM frames and the XPRT does not have to handle buffered
frames.
2022-05-18 15:50:57 +02:00
Amaury Denoyelle
37c2e4a65a MEDIUM: mux-quic: implement recv on io-cb
Previously, qc_io_cb() of mux-quic only dealt with TX. Add support for
RX in it. This is done through a new function qc_recv(qcc). It loops
over all QCS instances and call qcc_decode_qcs(qcs).

This has no impact from the quic-conn layer as qcc_decode_qcs(qcs) is
called directly. However, this allows to have a resume point when demux
is blocked on the upper layer HTX full buffer.

Note that for the moment, only RX for bidirectional streams is managed
in qc_io_cb(). Unidirectional streams use their own mechanism for both
TX/RX. It should be unified in the near future in a refactoring.
2022-05-18 15:43:22 +02:00
Amaury Denoyelle
73d6ffe832 MINOR: h3: flag demux as full on HTX full
Flag QCS if HTX buffer is full on demux. This will block all future
operations on QCS demux and should limit unnecessary decode_qcs() calls.
The flag is cleared on rcv_buf operation called by conn-stream.
2022-05-18 15:38:01 +02:00
Amaury Denoyelle
b5454d42df MINOR: h3: do not wait a complete frame for demuxing
Previously, H3 demuxer refused to proceed the payload if the frame was
not entirely received and the QCS buffer is not full. This code was
duplicated from the H2 demuxer.

In H2, this is a justified optimization as only one frame at a time can
be demuxed. However, this is not the case in H3 with interleaved frames
in the lower layer QUIC STREAM frames.

This condition is now removed. H3 demuxer will proceed payload as soon
as possible. An exception is kept for HEADERS frame as the code is not
able to deal with partial HEADERS.

With this change, H3 demuxer should consume less memory. To ensure that
we never received a HEADER bigger than the RX buffer, we should use the
H3 SETTINGS_MAX_FIELD_SECTION_SIZE.
2022-05-18 15:31:46 +02:00
Amaury Denoyelle
03dcf560ae BUG/MINOR: mux-quic: update session's idle delay before stream creation
This commit is an adaptation from the following patch :
  commit d0de6776826ee18da74e6949752e2f44cba8fdf2
  Author: Willy Tarreau <w@1wt.eu>
  Date:   Fri Feb 4 09:05:37 2022 +0100
  BUG/MINOR: mux-h2: update the session's idle delay before creating the stream

This should fix the incorrect timeouts present in httplog format for
QUIC requests.
2022-05-18 15:30:13 +02:00
Amaury Denoyelle
ca21c768b9 MINOR: ncbuf: refactor ncb_advance()
First adjusted some typos in comments inside the function. Second,
change the naming of some variable to reduce confusion.

A special case has been inserted when advance is done inside a GAP block
and this block is the last of the buffer. In this case, the whole buffer
will be emptied, equivalent to a ncb_init() operation.
2022-05-18 15:30:13 +02:00
Amaury Denoyelle
f6dbdc1444 BUG/MINOR: ncbuf: fix ncb_is_empty()
ncb_is_empty() was plainly incorrect as it directly dereferences the
memory to read offset blocks instead of ncb_read_off(). The result is
undefined.

Also, BUG_ON() statement is wrong when the buffer starts with a data
block. In this case, ncb_head() is not the first gap offset but instead
just random data. The calculated sum in BUG_ON() statement has thus no
meaning and may cause an abort. Adjust this by reorganizing the whole
function. Only the first data block size is read. If and only if not
nul, the first gap size is then checked.

ncb_is_full() has been rewritten to share the same model as
ncb_is_empty().
2022-05-18 15:23:29 +02:00
Amaury Denoyelle
82c51b561e OPTIM: quic: realign empty Rx buffer
quic_rx_pkts_del() function removes packets from QUIC RX buffer. In most
cases, the buffer will be emptied after it. In this case, it's useful to
realign it. This will avoid future data wrapping and use of an
unnecessary junk to fill a too small contiguous space.
2022-05-18 15:16:26 +02:00
Amaury Denoyelle
80d0572a31 BUG/MEDIUM: quic: fix Rx buffering
The quic-conn manages a buffer to store received QUIC packets. When the
buffer wraps, the gap is filled until the end with junk and packets can
be inserted at the start of the buffer.

On the other end, deletion is implemented via quic_rx_pkts_del().
Packets are removed one by one if their refcount is nul. If junk is
found, the buffer is emptied until its wrap.

This seems to work in most cases but a bug was found in a particular
case : on insertion if buffer gap is not at the end of the buffer. In
this case, the gap was filled, which is useless as now the buffer is
full and the packet cannot be inserted. Worst, on deletion, when junk is
removed there is a risk to removed new packets. This can happens in the
following case :
1. buffer contig space is too small, junk is inserted in the middle of
   it
2. on quic_rx_pkts_del() invocation, a packet is removed, but not the
   next one because its refcount is still positive. When a new packet is
   received, it will be stored after the junk.
3. on next quic_rx_pkts_del(), when junk is removed, all contig data is
   cleared, with newer packets data too.

This will cause a transfer between a client and haproxy to be stalled.
This can be reproduced with big enough POST requests. I triggered it
with ngtcp2 and 10M of posted data.

Hopefully, the solution of this bug is simple. If contig space is not
big enough to store a packet, but the space is not at the end of the
buffer, no junk is inserted and the packet is dropped as we cannot
buffered it. This ensures that junk is only present at the end of the
buffer and when removed no packets data is purged with it.
2022-05-18 15:02:14 +02:00
Christopher Faulet
f229e1894c CLEANUP: httpclient: Remove useless test on ss_dst in httpclient_applet_init()
In httpclient_applet_init() function, ss_dst variable is always defined
before the call to sockaddr_alloc(). There is no reason to test it.

This patch should fix the issue #1706.
2022-05-18 09:29:33 +02:00
Christopher Faulet
9e3c8d5512 CLEANUP: peers: Remove unreachable code in peer_session_create()
An error label is now unreachable in peer_session_create().

This patch should fix the issue #1704.
2022-05-18 09:04:53 +02:00
Christopher Faulet
fa463afa8f BUG/MINOR: spoe: Fix error handling in spoe_init_appctx()
labels used in goto statement was not called in the right order. Thus if
there is an error during the appctx startup, it is possible to leak a task.

This patch should fix the issue #1703. No backport needed.
2022-05-18 09:04:53 +02:00
Tim Duesterhus
7ad27d41b4 CLEANUP: http_ana: Make use of the return value of stream_generate_unique_id()
Even if `unique_id` and `s->unique_id` are identical it is a bit odd to
`isttest()` `unique_id` and then use `s->unique_id` in the call to `http_add_header()`.

This "issue" was introduced in a17e66289c08a5bfadc1bb5b5f2c618c9299fe1b,
because before that commit the function returned the length of the ID, as it
was not an ist.
2022-05-18 07:19:01 +02:00
Remi Tricot-Le Breton
ccc0355c41 MINOR: ssl: Add 'ssl-provider-path' global option
When loading providers with 'ssl-provider' global options, this
ssl-provider-path option can be used to set the search path that is to
be used by openssl. It behaves the same way as the OPENSSL_MODULES
environment variable.
2022-05-17 18:09:17 +02:00
Christopher Faulet
96816b0755 REGTESTS: abortonclose: Fix some race conditions
Depending on the timing, the second client that should be reported as a
client abort during connection attempt ("CC--" termination state) is
sometime logged as a server close ("SC--" termination state) instead. It
happens because sometime the connection failure to the server s1 is detected
by haproxy before the client c2 aborts. There is no retries and the
connection timeout is set to 100ms. So, to work, the client abort must be
performed and detected by haproxy in less than 100ms.

To fix the issue, the c2 client is now routed to a backend with a connection
timeout set to 1 second and 10 retries. It should be large enough to detect
the client aborts (~10s)

In addition, there is another race condition when the script is
started. sometime, server s1 is not stopped when the first client sends its
request. So a barrier was added to be sure it is stopped before starting to
send requests. And we wait to be sure the server is detected as DOWN to
unblock the barrier. It is performed by a dedicated backend with an
healthcheck on the server s1.

This patch should solve issue #1664.
2022-05-17 16:13:22 +02:00
Christopher Faulet
bc684acae7 CLEANUP: proxy: Remove dead code when parsing "http-restrict-req-hdr-names" option
negation or default modifiers are not supported for this option. However,
this was already tested earlier in cfg_parse_listen() function. Thus, when
"http-restrict-req-hdr-names" option is parsed, the keyword modifier is
always equal to KWM_STD. It is useless to test it again at this place.

This patch should solve the issue #1702.
2022-05-17 16:13:22 +02:00
Christopher Faulet
2d9cc85b74 MINOR: conn-stream/applet: Stop setting appctx as the endpoint context
The appctx is already the endpoint target. It is confusing to also use it to
set the endpoint context. So, never set the endpoint ctx when an appctx is
created or attached to an existing conn-stream.
2022-05-17 16:13:22 +02:00
Maciej Zdeb
34e4085f8a MEDIUM: peers: Balance applets across threads
When creating a new applet for peer outgoing connection, we check
the load on each thread. Threads with least applet count are
preferred.

With this solution we avoid a situation when many outgoing
connections run on the same thread causing significant load on
single CPU core.
2022-05-17 16:13:22 +02:00
Maciej Zdeb
d01be2ab13 MINOR: peers: Track number of applets run by thread
Maintain number of peers applets run on all threads. It will be used
in next patch for least loaded thread selection.
2022-05-17 16:13:22 +02:00
Christopher Faulet
d9c1d33fa1 MEDIUM: applet: Add support for async appctx startup on a thread subset
It is now possible to start an appctx on a thread subset. Some controls were
added here and there. It is forbidden to start a backend appctx on another
thread than the local one. If a frontend appctx is started on another thread
or a thread subset, the applet .init callback function must be defined. This
callback function is responsible to finalize the appctx startup. It can be
performed synchornously. In this case, the appctx is started on the local
thread. It is not really useful but it is valid. Or it can be performed
asynchronously. In this case, .init callback function is called when the
appctx is woken up for the first time. When this happens, the appctx
affinity is set to the current thread to be able to start the session and
the stream.
2022-05-17 16:13:22 +02:00
Christopher Faulet
6095d57701 MINOR: applet: Add API to start applet on a thread subset
In the same way than for the tasks, the applets api was changed to be able
to start a new appctx on a thread subset. For now the feature is
disabled. Only appctx_new_here() is working. But it will be possible to
start an appctx on a specific thread or a subset via a mask.
2022-05-17 16:13:22 +02:00
Christopher Faulet
6712dc680c MEDIUM: peers: Refactor peer appctx creation
A .init callback function is defined for the peer_applet applet. This
function finishes the appctx startup by calling appctx_finalize_startup()
and its handles the stream customization.
2022-05-17 16:13:22 +02:00
Christopher Faulet
387e79727c MINOR: peers: Add a ref to peers section in the peer structure
This change is required to handle asynchrone init of the appctx. It is now
possible to directly get the peers section associated to a peer.
2022-05-17 16:13:22 +02:00
Christopher Faulet
aee57fc277 MEDIUM: sink: Refactor sink forwarder appctx creation
A .init callback function is defined for the sink_forward_applet applet.
This function finishes the appctx startup by calling
appctx_finalize_startup() and its handles the stream customization.
2022-05-17 16:13:22 +02:00
Christopher Faulet
2ae25ea24b MINOR: sink: Add a ref to sink in the sink_forward_target structure
This change is required to be able to refactor the init stage of appctx. It
is now possible to directly get the sink from a forward target.
2022-05-17 16:13:22 +02:00
Christopher Faulet
b1e0836ecf MEDIUM: httpclient: Refactor http-client appctx creation
A .init callback function is defined for the httpclient_applet applet. This
function finishes the appctx startup by calling appctx_finalize_startup()
and its handles the stream customization.
2022-05-17 16:13:22 +02:00
Christopher Faulet
5f35a3e2ec MEDIUM: lua: Refactor cosocket appctx creation
A .init callback function is defined for the update_applet applet. This
function finishes the appctx startup by calling appctx_finalize_startup()
and its handles the stream customization.
2022-05-17 16:13:22 +02:00
Christopher Faulet
69ebc3093a MEDIUM: spoe: Refactor SPOE appctx creation
A .init callback function is defined for the spoe_applet applet. This
function finishes the spoe_appctx initialization. It also finishes the
appctx startup by calling appctx_finalize_startup() and its handles the
stream customization.
2022-05-17 16:13:22 +02:00
Christopher Faulet
9223851a80 MEDIUM: dns: Refactor dns appctx creation
A .init callback function is defined for the dns_session_applet applet. This
function finishes the appctx startup by calling appctx_finalize_startup()
and its handles the stream customization.
2022-05-17 16:13:21 +02:00
Christopher Faulet
d0c4ec04b8 MINOR: applet: Add function to release appctx on error during init stage
appctx_free_on_early_error() must be used to release a freshly created
frontend appctx if an error occurred during the init stage. It takes care to
release the stream instead of the appctx if it exists. For a backend appctx,
it just calls appctx_free().
2022-05-17 16:13:21 +02:00
Christopher Faulet
8718c95c0a MINOR: applet: Add a function to finalize frontend appctx startup
appctx_finalize_startup() may be used to finalize the frontend appctx
startup. It is responsible to create the appctx's session and the frontend
conn-stream. On error, it is the caller responsibility to release the
appctx. However, the session is released if it was created. On success, if
an error is encountered in the caller function, the stream must be released
instead of the appctx.

This function should ease the init stage when new appctx is created.
2022-05-17 16:13:21 +02:00
Christopher Faulet
16c0d9cda0 MINOR: applet: Add appctx_init() helper fnuction
It is just a helper function that call the .init applet callback function,
if it exists. This will simplify a bit the init stage when a new applet is
started. For now, this callback function is only used when a new service is
started.
2022-05-17 16:13:21 +02:00
Christopher Faulet
ab5d1dceed MINOR: stream: Export stream_free()
The stream_free() function is now public. It is mandatory to properly handle
errors when a new applet is started.
2022-05-17 16:13:21 +02:00
Christopher Faulet
c9929380a4 MINOR: applet: Change return value for .init callback function
0 is now returned on success and -1 on error.
2022-05-17 16:13:21 +02:00
Christopher Faulet
92202da2da MINOR: applet: Let the frontend appctx release the session
The session created for frontend applets is now totally owns by the
corresponding appctx. It means the appctx is now responsible to release
it. This removes the hack in stream_free() about frontend applets to be sure
to release the session.
2022-05-17 16:13:21 +02:00
Christopher Faulet
ac57bb527a MINOR: applet: Prepare appctx to own the session on frontend side
Applets were moved at the same level than multiplexers. Thus, gradually,
applets code is changed to be less dependent from the stream. With this
commit, the frontend appctx are ready to own the session. It means a
frontend appctx will be responsible to release the session.
2022-05-17 16:13:21 +02:00
Christopher Faulet
ef5e1bb4cf CLEANUP: conn-stream: Remove cs_applet_shut declaration from header file
This function was renamed and moved in applet code. cs_applet_shut() does
not exist anymore. Its declaration must be removed.
2022-05-17 16:13:21 +02:00
Remi Tricot-Le Breton
9bf3a1f67e BUG/MINOR: ssl: Fix crash when no private key is found in pem
If no private key can be found in a bind line's certificate and
ssl-load-extra-files is set to none we end up trying to call
X509_check_private_key with a NULL key, which crashes.

This fix should be backported to all stable branches.
2022-05-17 15:51:41 +02:00
David Carlier
7198c700bc MINOR: tools: add get_exec_path implementation for solaris based systems.
We can use getexecname() which fetches AT_SUN_EXECNAME from the auxiliary
vectors.
2022-05-17 11:44:21 +02:00
David Carlier
135c1ec139 BUILD: fix build warning on solaris based systems with __maybe_unused.
__maybe_unused is already defined there.
2022-05-17 11:42:20 +02:00
Tim Duesterhus
9b6becb312 CLEANUP: Remove unused function hlua_get_top_error_string
This function has no prototype defined in a header and is not used in hlua.c
either, thus it can be safely removed. Found with -Wmissing-prototypes.
2022-05-17 11:40:33 +02:00
Tim Duesterhus
6eded62f6a CLEANUP: Add missing header to hlua_fcn.c
Found with -Wmissing-prototypes:

    src/hlua_fcn.c:53:5: fatal error: no previous prototype for function 'hlua_checkboolean' [-Wmissing-prototypes]
    int hlua_checkboolean(lua_State *L, int index)
        ^
    src/hlua_fcn.c:53:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
    int hlua_checkboolean(lua_State *L, int index)
    ^
    static
    1 error generated.
2022-05-17 11:40:33 +02:00