17544 Commits

Author SHA1 Message Date
Amaury Denoyelle
d68f8b5a4a CLEANUP: mux-quic: rename internal functions
This patch is similar to the previous one but for QUIC mux functions
used inside the mux code itself or application layer. Replace all
occurences of qc_* prefix by qcc_* or qcs_*. This should help to better
differentiate code between quic_conn and MUX.

This should be backported up to 2.7.
2023-05-30 15:45:55 +02:00
Amaury Denoyelle
0f61e4f6d3 CLEANUP: mux-quic: rename functions for mux_ops
Rename all QUIC mux function exposed through mux_ops structure. Use the
prefix qmux_* or qmux_strm_*. The objective is to remove qc_* prefix
which should only be used in quic_conn layer.

This should be backported up to 2.7.
2023-05-30 15:44:53 +02:00
Willy Tarreau
8fc7073906 BUG/MEDIUM: threads: fix a tiny race in thread_isolate()
Aurélien found a tiny race in thread_isolate() that can allow a thread
that was running under isolation to continue running while another one
enters isolation. The reason is that the check for harmless is only
done before winning the CAS, but since the previously isolated thread
doesn't wait for !rdv_request in thread_release(), it can effectively
continue its activities while the next one believes it's isolated. A
proper solution consists in looping once again in thread_isolate() to
recheck (and wait) for all threads to be isolated once the CAS is won.

The issue was introduced in 2.7 by commit 598cf3f22 ("MAJOR: threads:
change thread_isolate to support inter-group synchronization") so the
fix needs to be backported there.
2023-05-27 13:53:46 +02:00
Amaury Denoyelle
bfddb42c05 BUG/MEDIUM: mux-quic: only set EOI on FIN
Recently stconn flags were reviewed for QUIC mux to be conform with
other HTTP muxes. However, a mistake was made when dealing with a proper
stream FIN with both EOI and EOS set. This was done as RESET_STREAM
received after a FIN are ignored by QUIC mux and thus there is no
difference between EOI or EOI+EOS. However, analyzers may interpret EOS
as an interrupted request which result in a 400 HTTP error code.

To fix this, only set EOI on proper stream FIN. EOS is set when input is
interrupted (RESET_STREAM before FIN) or a STOP_SENDING is received
which prevent transfer to complete. In this last case, EOS must be
manually set too if FIN has been received before STOP_SENDING to go
directly from ERR_PENDING to final ERROR state.

This must be backported up to 2.7.
2023-05-26 17:17:25 +02:00
Amaury Denoyelle
6d6ee0dc0b MINOR: quic: fix stats naming for flow control BLOCKED frames
There was a misnaming in stats counter for *_BLOCKED frames in regard to
QUIC rfc convention. This patch fixes it to prevent future ambiguity :

- STREAMS_BLOCKED -> STREAM_DATA_BLOCKED
- STREAMS_DATA_BLOCKED_BIDI -> STREAMS_BLOCKED_BIDI
- STREAMS_DATA_BLOCKED_UNI -> STREAMS_BLOCKED_UNI

This should be backported up to 2.7.
2023-05-26 17:17:00 +02:00
Amaury Denoyelle
087c5f041b MINOR: mux-quic: remove nb_streams from qcc
Remove nb_streams field from qcc. It was not used outside of a BUG_ON()
statement to ensure we never have a negative count of streams. However
this is already checked with other fields.

This should be backported up to 2.7.
2023-05-26 17:17:00 +02:00
Amaury Denoyelle
7b41dfd834 CLEANUP: mux-quic: remove unneeded fields in qcc
Remove fields from qcc structure which are unused.

This should be backported up to 2.7.
2023-05-26 17:17:00 +02:00
Aurelien DARRAGON
33bbeecde3 BUILD: init: print rlim_cur as regular integer
haproxy does not compile anymore on macOS+clang since 425d7ad ("MINOR:
init: pre-allocate kernel data structures on init"). This is due to
rlim_cur being printed uncasted using %lu format specifier, with rlim_cur
being stored as a rlim_t which is a typedef so its size may vary depending
on the system's architecture.

This is not the first time we need to dump rlim_cur in case of errors,
there are already multiple occurences in the init code. Everywhere this
happens, rlim is casted as a regular int and printed using the '%d'
format specifier, so we do the same here as well to fix the build issue.

No backport needed unless 425d7ad gets backported.
2023-05-26 14:29:52 +02:00
eaglegai
ef667b1ad8 BUG/MINOR: thread: add a check for pthread_create
preload_libgcc_s() use pthread_create to create a thread and then call
pthread_join to use it, but it doesn't check if the option is successful.
So add a check to aviod potential crash.
2023-05-26 12:08:23 +02:00
eaglegai
15c3d20e31 BUG/MINOR: ssl_sock: add check for ha_meth
in __ssl_sock_init, BIO_meth_new may failed and return NULL if
OPENSSL_zalloc failed.  in this case, ha_meth  will be NULL, and then
crash happens in  BIO_meth_set_write.  So, we add a check for ha_meth.
2023-05-26 12:07:43 +02:00
Patrick Hemmer
425d7ad89d MINOR: init: pre-allocate kernel data structures on init
The Linux kernel maintains data structures to track a processes' open file
descriptors, and it expands these structures as necessary when FD usage grows
(at every FD=2^X starting at 64). However when threading is in use, during
expansion the kernel will pause (observed up to 47ms) while it waits for thread
synchronization (see https://bugzilla.kernel.org/show_bug.cgi?id=217366).

This change addresses the issue and avoids the random pauses by opening the
maximum file descriptor during initialization, so that expansion will not occur
while processing traffic.
2023-05-26 09:28:18 +02:00
Christopher Faulet
535dd920df MINOR: compression: Improve the way Vary header is added
When a message is compressed, A "Vary" header is added with
"accept-encoding" value. However, a new header is always added, regardless
there is already a Vary header or not. In addition, if there is already a
Vary header, there is no check on values to be sure "accept-encoding" value
is not already there. So it is possible to have it twice.

To improve this part, we now test Vary header values and "accept-encoding"
is only added if it was not found. In addition, "accept-encoding" value is
appended to the last Vary header found, if any. Otherwise, a new header is
added.
2023-05-25 11:25:31 +02:00
Aurelien DARRAGON
1c07da4b48 BUG/MINOR: hlua: unsafe hlua_lua2smp() usage
Fixing hlua_lua2smp() usage in hlua's code since it was assumed that
hlua_lua2smp() makes a standalone smp out of lua data, but it is not
the case.

This is especially true when dealing with lua strings (string is
extracted using lua_tolstring() which returns a pointer to lua string
memory location that may be reclaimed by lua at any time when no longer
used from lua's point of view). Thus, smp generated by hlua_lua2smp() may
only be used from the lua context where the call was initially made, else
it should be explicitly duplicated before exporting it out of lua's
context to ensure safe (standalone) usage.

This should be backported to all stable versions.
2023-05-24 16:48:17 +02:00
Aurelien DARRAGON
a3624cb528 DOC: hlua: document hlua_lua2smp() function
Add some developer notes to hlua_lua2smp() function description since
it lacks some important infos, including a critical usage restriction.
2023-05-24 16:48:17 +02:00
Aurelien DARRAGON
0aaf6c45ca DOC: hlua: document hlua_lua2arg() function
Add some developer notes to hlua_lua2arg() function description since
it lacks some important infos, including an usage restriction.
2023-05-24 16:48:17 +02:00
Aurelien DARRAGON
e5c048a72d MINOR: hlua: hlua_arg2lua() may LJMP
Add LJMP hint to hlua_arg2lua() prototype since it relies on
functions (e.g.: lua_pushlstring()) which may raise lua memory errors.
2023-05-24 16:48:17 +02:00
Aurelien DARRAGON
4121772c50 MINOR: hlua: hlua_smp2lua() may LJMP
Add LJMP hint to hlua_smp2lua() prototype since it relies on
functions (e.g.: lua_pushstring()) which may raise lua memory errors.
2023-05-24 16:48:17 +02:00
Aurelien DARRAGON
742b1a8797 MINOR: hlua: hlua_smp2lua_str() may LJMP
Add LJMP hint to hlua_smp2lua_str() prototype since it relies on
functions (e.g.: lua_pushstring()) which may raise lua memory errors.
2023-05-24 16:48:17 +02:00
Frédéric Lécaille
12a815ad19 MINOR: quic: Add a counter for sent packets
Add ->sent_pkt counter to quic_conn struct to count the packet at QUIC connection
level. Then, when the connection is released, the ->sent_pkt counter value
is added to the one for the listener.

Must be backported to 2.7.
2023-05-24 16:30:11 +02:00
Frédéric Lécaille
bdd64fd71d MINOR: quic: Add some counters at QUIC connection level
Add some statistical counters to quic_conn struct from quic_counters struct which
are used at listener level to handle them at QUIC connection level. This avoid
calling atomic functions. Furthermore this will be useful soon when a counter will
be added for the total number of packets which have been sent which will be very
often incremented.

Some counters were not added, espcially those which count the number of QUIC errors
by QUIC error types. Indeed such counters would be incremented most of the time
only one time at QUIC connection level.

Implement quic_conn_prx_cntrs_update() which accumulates the QUIC connection level
statistical counters to the listener level statistical counters.

Must be backported to 2.7.
2023-05-24 16:30:11 +02:00
Frédéric Lécaille
464281af46 CLEANUP: quic: Useless tests in qc_rx_pkt_handle()
There is no reason to test <qc> nullity at the end of this function because it is
clearly not null, furthermore the trace handle the case where <qc> is null.

Must be backported to 2.7.
2023-05-24 16:30:11 +02:00
Frédéric Lécaille
ab3aa0ff22 CLEANUP: quic: Indentation fix quic_rx_pkt_retrieve_conn()
Add missing spaces.

Must be backported to 2.7.
2023-05-24 16:30:11 +02:00
Frédéric Lécaille
5fa633e22f MINOR: quic: Align "show quic" command help information
Align the "show quic" help information with all the others command help information.
Furthermore, makes this information match the management documentation.

Must be backported to 2.7.
2023-05-24 16:30:11 +02:00
Frédéric Lécaille
35b63964a0 BUG/MINOR: quic: Missing Retry token length on receipt
quic_retry_token_check() must decipher the token sent to and received back from
clients. This token is made of the token format byte, the ODCID prefixed by its one byte
length, the timestamp of its creation, and terminated by an AEAD TAG followed
by the salt used to derive the secret to cipher the token.

So, the length of these data must be between
2 + QUIC_ODCID_MINLEN + sizeof(uint32_t) + QUIC_TLS_TAG_LEN + QUIC_RETRY_TOKEN_SALTLEN
and
2 + QUIC_CID_MAXLEN + sizeof(uint32_t) + QUIC_TLS_TAG_LEN + QUIC_RETRY_TOKEN_SALTLEN.

Must be backported to 2.7 and 2.6.
2023-05-24 16:30:11 +02:00
Frédéric Lécaille
6d6ddb2ce5 BUG/MINOR: quic: Wrong token length check (quic_generate_retry_token())
This bug would never occur because the buffer supplied to quic_generate_retry_token()
to build a Retry token is large enough to embed such a token. Anyway, this patch
fixes quic_generate_retry_token() implementation.

There were two errors: this is the ODCID which is added to the token. Furthermore
the timestamp was not taken into an account.

Must be backported to 2.6 and 2.7.
2023-05-24 16:30:11 +02:00
Frédéric Lécaille
aaf32f0c83 MINOR: quic: Add low level traces (addresses, DCID)
Add source and destination addresses to QUIC_EV_CONN_RCV trace event. This is
used by datagram/socket level functions (quic_sock.c).

Must be backported to 2.7.
2023-05-24 16:30:11 +02:00
Christopher Faulet
c2f1d0ee5e BUG/MEDIUM: mux-h2: Propagate termination flags when frontend SC is created
We must evaluate if EOS/EOI/ERR_PENDING/ERROR flags must be set on the SE
when the frontend SC is created because the rxbuf is transferred to the
steeam at this stage. It means the call to h2_rcv_buf() may be skipped on
some circumstances.

And indeed, it happens when HAproxy quickly replies, for instance because of
a deny rule. In this case, depending on the scheduling, the abort may block
the receive attempt from the SC. In this case if SE flags were not properly
set earlier, there is no way to terminate the request and the session may be
freezed.

For now, I can't explain why there is no timeout when this happens but it
remains an issue because here we should not rely on timeouts to close the
stream.

This patch relies on following commits:

    * MINOR: mux-h2: Add a function to propagate termination flags from h2s to SE
    * MINOR: mux-h2: Set H2_SF_ES_RCVD flag when decoding the HEADERS frame

The issue was encountered on the 2.8 but it seems the bug exists since the
2.4. But it is probably a good idea to only backport the series to 2.7 only
and wait for a bug report on earlier versions.

This patch should solve the issue #2147.
2023-05-24 16:06:11 +02:00
Christopher Faulet
531dd050ff MINOR: mux-h2: Add a function to propagate termination flags from h2s to SE
The function h2s_propagate_term_flags() was added to check the H2S state and
evaluate when EOI/EOS/ERR_PENDING/ERROR flags must be set on the SE. It is
not the only place where those flags are set. But it centralizes the synchro
between the H2 stream and the SC.

For now, this function is only used at the end of h2_rcv_buf(). But it will
be used to fix a bug.
2023-05-24 16:06:11 +02:00
Christopher Faulet
1a60a66306 MINOR: mux-h2: Set H2_SF_ES_RCVD flag when decoding the HEADERS frame
The flag H2_SF_ES_RCVD is set on the H2 stream when the ES flag is found in
a frame. On HEADERS frame, it was set in function processing the frame. It
is moved in the function decoding the frame. Fundamentally, this changes
nothing. But it will be useful to have this information earlier when a
client H2 stream is created.
2023-05-24 16:06:11 +02:00
Christopher Faulet
78b1eb2b04 BUG/MINOR: mux-h2: Check H2_SF_BODY_TUNNEL on H2S flags and not demux frame ones
In h2c_frt_stream_new(), H2_SF_BODY_TUNNEL flags was tested on demux frame
flags (h2c->dff) instead of the h2s flags.  By chance, it is a noop test
becasue H2_SF_BODY_TUNNEL value, once converted to an int8_t, is 0.

It is a 2.8-specific issue. No backport needed.
2023-05-24 16:06:11 +02:00
Amaury Denoyelle
152beeec34 MINOR: mux-quic: report error on stream-endpoint earlier
A RESET_STREAM is emitted in several occasions :
- protocol error during HTTP/3.0 parsing
- STOP_SENDING reception

In both cases, if a stream-endpoint is attached we must set its ERR
flag. This was correctly done but after some delay as it was only when
the RESET_STREAM was emitted. Change this to set the ERR flag as soon as
one of the upper cases has been encountered. This should help to release
faster streams in error.

This should be backported up to 2.7.
2023-05-24 14:46:52 +02:00
Amaury Denoyelle
37d78997ae MINOR: mux-quic: only set EOS on RESET_STREAM recv
A recent review was done to rationalize ERR/EOS/EOI flags on stream
endpoint. A common definition for both H1/H2/QUIC mux have been written
in the following documentation :
 ./doc/internals/stconn-close.txt

In QUIC it is possible to close each channels of a stream independently
with RESET_STREAM and STOP_SENDING frames. When a RESET_STREAM is
received, it indicates that the peer has ended its transmission in an
abnormal way. However, it is still ready to receive.

Previously, on RESET_STREAM reception, QUIC MUX set the ERR flag on
stream-endpoint. However, according to the QUIC mechanism, it should be
instead EOS but this was impossible due to a BUG_ON() which prevents EOS
without EOI or ERR. This BUG_ON was only present because this case was
never used before the introduction of QUIC. It was removed in a recent
commit which allows us to now properly set EOS alone on RESET_STREAM
reception.

In practice, this change allows to continue to send data even after
RESET_STREAM reception. However, currently browsers always emit it with
a STOP_SENDING as this is used to abort the whole H3 streams. In the end
this will result in a stream-endpoint with EOS and ERR_PENDING/ERR
flags.

This should be backported up to 2.7.
2023-05-24 14:39:17 +02:00
Amaury Denoyelle
8de35925f7 MINOR: mux-quic: set both EOI EOS for stream fin
A recent review was done to rationalize ERR/EOS/EOI flags on stream
endpoint. A common definition for both H1/H2/QUIC mux have been written
in the following documentation :
 ./doc/internals/stconn-close.txt

Always set EOS with EOI flag to conform to this specification. EOI is
set whenever the proper stream end has been encountered : with QUIC it
corresponds to a STREAM frame with FIN bit. At this step, RESET_STREAM
frames are ignored by QUIC MUX as allowed by RFC 9000. This means we can
always set EOS at the same time with EOI.

This should be backported up to 2.7.
2023-05-24 14:23:22 +02:00
Christopher Faulet
2437377445 MEDIUM: stconn/applet: Allow SF_SL_EOS flag alone
During the refactoring on SC/SE flags, it was stated that SE_FL_EOS flag
should not be set without on of SE_FL_EOI or SE_FL_ERROR flags. In fact, it
is a problem for the QUIC/H3 multiplexer. When a RST_STREAM frame is
received, it means no more data will be received from the peer. And this
happens before the end of the message (RST_STREAM frame received after the
end of the message are ignored). At this stage, it is a problem to report an
error because from the QUIC point of view, it is valid. Data may still be
sent to the peer. If an error is reported, this will stop the data sending
too.

In the same idea, the H1 mulitplexer reports an error when the message is
truncated because of a read0. But only an EOS flag should be reported in
this case, not an error. Fundamentally, it is important to distinguish
errors from shuts for reads because some cases are valid. For instance a H1
client can choose to stop uploading data if it received the server response.

So, relax tests on SE flags by removing BUG_ON_HOT() on SE_FL_EOS flag. For
now, the abort will be handled in the HTTP analyzers.
2023-05-23 15:52:35 +02:00
Amaury Denoyelle
aa39cc9f42 MINOR: quic: fix alignment of oneline show quic
Output of 'show quic' CLI in oneline mode was not correctly done. This
was caused both due to differing qc pointer size and ports length. Force
proper alignment by using maximum sizes as expected and complete with
blanks if needed.

This should be backported up to 2.7.
2023-05-22 14:18:02 +02:00
Amaury Denoyelle
7385ff3f0c BUG/MINOR: quic: handle Tx packet allocation failure properly
qc_prep_app_pkts() is responsible to built several new packets for
sending. It can fail due to memory allocation error. Before this patch,
the Tx buffer was released on error even if some packets were properly
generated.

With this patch, if an error happens on qc_prep_app_pkts(), we still try
to send already built packets if Tx buffer is not empty. The sending
loop is then interrupted and the Tx buffer is released with data
cleared.

This should be backported up to 2.7.
2023-05-22 14:18:02 +02:00
Amaury Denoyelle
f8fbb0b94e MINOR: quic: use WARN_ON for encrypt failures
It is expected that quic_packet_encrypt() and
quic_apply_header_protection() never fails as encryption is done in
place. This allows to remove their return value.

This is useful to simplify error handling on sending path. An error can
only be encountered on the first steps when allocating a new packet or
copying its frame content. After a clear packet is successfully built,
no error is expected on encryption.

However, it's still unclear if our assumption that in-place encryption
function never fail. As such, a WARN_ON() statement is used if an error
is detected at this stage. Currently, it's impossible to properly manage
this without data loss as this will leave partially unencrypted data in
the send buffer. If warning are reported a solution will have to be
implemented.

This should be backported up to 2.7.
2023-05-22 11:20:44 +02:00
Amaury Denoyelle
5eadc27623 MINOR: quic: remove return val of quic_aead_iv_build()
quic_aead_iv_build() should never fail unless we call it with buffers of
different size. This never happens in the code as every input buffers
are of size QUIC_TLS_IV_LEN.

Remove the return value and add a BUG_ON() to prevent future misusage.
This is especially useful to remove one error handling on the sending
patch via quic_packet_encrypt().

This should be backported up to 2.7.
2023-05-22 11:17:18 +02:00
Amaury Denoyelle
8d6d246dbc CLEANUP: mux-quic/h3: complete BUG_ON with comments
Complete each useful BUG_ON statements with a comment to explain its
purpose. Also convert BUG_ON_HOT to BUG_ON as they should not have a
big impact.

This should be backported up to 2.7.
2023-05-22 11:17:18 +02:00
Aurelien DARRAGON
b6a24a52a2 BUG/MINOR: debug: fix pointer check in debug_parse_cli_task()
Task pointer check in debug_parse_cli_task() computes the theoric end
address of provided task pointer to check if it is valid or not thanks to
may_access() helper function.

However, relative ending address is calculated by adding task size to 't'
pointer (which is a struct task pointer), thus it will result to incorrect
address since the compiler automatically translates 't + x' to
't + x * sizeof(*t)' internally (with sizeof(*t) != 1 here).

Solving the issue by using 'ptr' (which is the void * raw address) as
starting address to prevent automatic address scaling.

This was revealed by coverity, see GH #2157.

No backport is needed, unless 9867987 ("DEBUG: cli: add "debug dev task"
to show/wake/expire/kill tasks and tasklets") gets backported.
2023-05-17 16:49:17 +02:00
Aurelien DARRAGON
7428adaf0d BUG/MINOR: hlua: SET_SAFE_LJMP misuse in hlua_event_runner()
When hlua_event_runner() pauses the subscription (ie: if the consumer
can't keep up the pace), hlua_traceback() is used to get the current
lua trace (running context) to provide some info to the user.

However, as hlua_traceback() may raise an error (__LJMP) is set, it is
used within a SET_SAFE_LJMP() / RESET_SAFE_LJMP() combination to ensure
lua errors are properly handled and don't result in unexpected behavior.

But the current usage of SET_SAFE_LJMP() within the function is wrong
since hlua_traceback() will run a second time (unprotected) if the
first (protected) attempt fails. This is undefined behavior and could
even lead to crashes.

Hopefully it is very hard to trigger this code path, thus we can consider
this as a minor bug.

Also using this as an opportunity to enhance the message report to make
it more meaningful to the user.

This should fix GH #2159.

It is a 2.8 specific bug, no backport needed unless c84899c636
("MEDIUM: hlua/event_hdl: initial support for event handlers") gets
backported.
2023-05-17 16:48:40 +02:00
Christopher Faulet
06e9c81bd0 MEDIUM: resolvers: Stop scheduling resolution during stopping stage
When the process is stopping, the server resolutions are suspended. However
the task is still periodically woken up for nothing. If there is a huge
number of resolution, it may lead to a noticeable CPU consumption for no
reason.

To avoid this extra CPU cost, we stop to schedule the the resolution tasks
during the stopping stage. Of course, it is only true for server
resolutinos. Dynamic ones, via do-resolve actions, are not concerned. These
ones must still be triggered during stopping stage.

Concretly, during the stopping stage, the resolvers task is no longer
scheduled if there is no running resolutions. In this case, if a do-resolve
action is evaluated, the task is woken up.

This patch should partially solve the issue #2145.
2023-05-17 16:48:33 +02:00
Christopher Faulet
8bca3cc8c7 MEDIUM: checks: Stop scheduling healthchecks during stopping stage
When the process is stopping, the health-checks are suspended. However the
task is still periodically woken up for nothing. If there is a huge number
of health-checks and if they are woken up in same time, it may lead to a
noticeable CPU consumption for no reason.

To avoid this extra CPU cost, we stop to schedule the health-check tasks
when the proxy is disabled or stopped.

This patch should partially solve the issue #2145.
2023-05-17 14:57:10 +02:00
Christopher Faulet
c8a7bb16b7 CLEANUP: fcgi-app; Remove useless assignment to NULL
When the fcgi configuration is checked and fcgi rules are created, a useless
assignment to NULL is reported by Covertiy. Let's remove it.

This patch should fix the coverity report #2161.
2023-05-17 09:42:37 +02:00
Willy Tarreau
c7b9308f20 BUG/MINOR: clock: automatically adjust the internal clock with the boot time
This is a better and more general solution to the problem described in
this commit:

    BUG/MINOR: checks: postpone the startup of health checks by the boot time

Now we're updating the now_offset that is used to compute now_ms at the
few points where we update the ready date during boot. This ensures that
now_ms while being stable during all the boot process will be correct
and will start with the boot value right after the boot is finished. As
such the patch above is rolled back (we don't want to count the boot
time twice).

This must not be backported because it relies on the more flexible clock
architecture in 2.8.
2023-05-17 09:33:54 +02:00
Willy Tarreau
5345490b8e MINOR: clock: provide a function to automatically adjust now_offset
Right now there's no way to enforce a specific value of now_ms upon
startup in order to compensate for the time it takes to load a config,
specifically when dealing with the health check startup. For this we'd
need to force the now_offset value to compensate for the last known
value of the current date. This patch exposes a function to do exactly
this.
2023-05-17 09:33:54 +02:00
Willy Tarreau
8e978a094d BUG/MINOR: checks: postpone the startup of health checks by the boot time
When health checks are started at boot, now_ms could be off by the boot
time. In general it's not even noticeable, but with very large configs
taking up to one or even a few seconds to start, this can result in a
part of the servers' checks being scheduled slightly in the past. As
such all of them will start groupped, partially defeating the purpose of
the spread-checks setting. For example, this can cause a burst of
connections for the network, or an excess of CPU usage during SSL
handshakes, possibly even causing some timeouts to expire early.

Here in order to compensate for this, we simply add the known boot time
to the computed delay when scheduling the startup of checks. That's very
simple and particularly efficient. For example, a config with 5k servers
in 800 backends checked every 5 seconds, that was taking 3.8 seconds to
start used to show this distribution of health checks previously despite
the spread-checks 50:

   3690 08:59:25
    417 08:59:26
    213 08:59:27
     71 08:59:28
    428 08:59:29
    860 08:59:30
    918 08:59:31
    938 08:59:32
   1124 08:59:33
    904 08:59:34
    647 08:59:35
    890 08:59:36
    973 08:59:37
    856 08:59:38
    893 08:59:39
    154 08:59:40

Now with the fix it shows this:
    470 08:59:59
    929 09:00:00
    896 09:00:01
    937 09:00:02
    854 09:00:03
    827 09:00:04
    906 09:00:05
    863 09:00:06
    913 09:00:07
    873 09:00:08
    162 09:00:09

This should be backported to all supported versions. It depends on
this commit:

    MINOR: clock: measure the total boot time

For 2.8 where the internal clock is now totally independent on the human
one, an more generic fix will consist in simply updating now_ms to reflect
the startup time.
2023-05-17 09:33:54 +02:00
Willy Tarreau
5723b382ed MINOR: stats: report the boot time in "show info"
Just like we have the uptime in "show info", let's add the boot time.
It's trivial to collect as it's just the difference between the ready
date and the start date, and will allow users to monitor this element
in order to take action before it starts becoming problematic. Here
the boot time is reported in milliseconds, so this allows to even
observe sub-second anomalies in startup delays.
2023-05-17 09:33:54 +02:00
Willy Tarreau
da4aa6905c MINOR: clock: measure the total boot time
Some huge configs take a significant amount of time to start and this
can cause some trouble (e.g. health checks getting delayed and grouped,
process not responding to the CLI etc). For example, some configs might
start fast in certain environments and slowly in other ones just due to
the use of a wrong DNS server that delays all libc's resolutions. Let's
first start by measuring it by keeping a copy of the most recently known
ready date, once before calling check_config_validity() and then refine
it when leaving this function. A last call is finally performed just
before deciding to split between master and worker processes, and it covers
the whole boot. It's trivial to collect and even allows to get rid of a
call to clock_update_date() in function check_config_validity() that was
used in hope to better schedule future events.
2023-05-17 09:33:54 +02:00
Willy Tarreau
52fd879953 CLEANUP: stats: update the trash chunk where it's used
When integrating the number of warnings in "show info" in 2.8 with commit
3c4a297d2 ("MINOR: stats: report the total number of warnings issued"),
the update of the trash buffer used by the Tainted flag got displaced
lower. There's no harm for now util someone adds a new metric requiring
a call to chunk_newstr() and gets both values merged. Let's move the
call to its location now.
2023-05-17 09:33:54 +02:00