]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
19 months agoBUG/MAJOR: server/addr: fix a race during server addr:svc_port updates
Aurelien DARRAGON [Mon, 13 Nov 2023 17:14:24 +0000 (18:14 +0100)] 
BUG/MAJOR: server/addr: fix a race during server addr:svc_port updates

For inet families (IP4/IP6), it is expected that server's addr/port might
be updated at runtime from DNS, cli or lua for instance.

Such updates were performed under the server's lock.

Unfortunately, most readers such as backend.c or sink.c perform the read
without taking server's lock because they can't afford slowing down their
processing for a type of event which is normally rare. But this could
result in bad values being read for the server addr:svc_port tuple (ie:
during connection etablishment) as a result of concurrent updates from
external components, which can obviously cause some undesirable effects.

Instead of slowing the readers down, as we consider server's addr changes
are relatively rare, we take another approach and try to update the
addr:port atomically by performing changes under full thread isolation
when a new change is requested. The changes are performed by a dedicated
task which takes care of isolating the current thread and doesn't depend
on other threads (independent code path) to protect against dead locks.

As such, server's addr:port changes will now be performed atomically, but
they will not be processed instantly, they will be translated to events
that the dedicated task will pick up from time to time to apply the
pending changes.

This bug existed for a very long time and has never been reported so
far. It was discovered by reading the code during the implementation
of log backend ("mode log" in backends). As it involves changes in
sensitive areas as well as thread isolation, it is probably not
worth considering backporting it for now, unless it is proven that it
will help to solve bugs that are actually encountered in the field.

This patch depends on:
 - 24da4d3 ("MINOR: tools: use const for read only pointers in ip{cmp,cpy}")
 - c886fb5 ("MINOR: server/ip: centralize server ip updates")
 - event_hdl API (which was first seen on 2.8) +
   683b2ae ("MINOR: server/event_hdl: add SERVER_INETADDR event") +
   BUG/MEDIUM: server/event_hdl: memory overrun in _srv_event_hdl_prepare_inetaddr() +
   "MINOR: event_hdl: add global tunables"

   Note that the patch may be reworked so that it doesn't depend on
   event_hdl API for older versions, the approach would remain the same:
   this would result in a larger patch due to the need to manually
   implement a global queue of pending updates with its dedicated task
   responsible for picking updates and comitting them. An alternative
   approach could consist in per-server, lock-protected, temporary
   addr:svc_port storage dedicated to "updaters" were only the most
   recent values would be kept. The sync task would then use them as
   source values to atomically update the addr:svc_port members that the
   runtime readers are actually using.

19 months agoMINOR: event_hdl: add global tunables
Aurelien DARRAGON [Fri, 24 Nov 2023 14:37:40 +0000 (15:37 +0100)] 
MINOR: event_hdl: add global tunables

The local variable "event_hdl_async_max_notif_at_once" which was
introduced with the event_hdl API was left as is but with a TODO note
telling that we should make it a global tunable.

Well, we're doing this now. To prepare for upcoming tunables related to
event_hdl API, we add a dedicated struct named event_hdl_tune which is
globally exposed through the event_hdl header file so that it may be used
from everywhere. The struct is automatically initialized in
event_hdl_init() according to defaults.h.

"event_hdl_async_max_notif_at_once" now becomes
"event_hdl_tune.max_events_at_once" with it's dedicated
configuation keyword: "tune.events.max-events-at-once".

We're also taking this opportunity to raise the default value from 10
to 100 since it's seems quite reasonnable given existing async event_hdl
users.

The documentation was updated accordingly.

19 months agoBUG/MEDIUM: server/event_hdl: memory overrun in _srv_event_hdl_prepare_inetaddr()
Aurelien DARRAGON [Sat, 25 Nov 2023 15:39:19 +0000 (16:39 +0100)] 
BUG/MEDIUM: server/event_hdl: memory overrun in _srv_event_hdl_prepare_inetaddr()

As reported in GH #2358, #2359, #2360, #2361 and #2362: ipv6 address
handling may cause memory overrun due to struct in6_addr being handled
as sockaddr_in6 which is larger. Moreover, source variable wasn't properly
read from since the raw value was used as a pointer instead of pointing to
the actual variable's address.

This bug was introduced by 6fde37e046
("MINOR: server/event_hdl: add SERVER_INETADDR event")

Unfortunately for us, gcc didn't catch this and, this actually used to
"work" by accident since in6_addr struct is made of array so not passing
pointer explicitly still resolved to the proper starting address..
Hopefully this was caught by coverity so thanks to Ilya for that.

The fix is simple: we simply copy the whole in6_addr struct by accessing
it using a pointer and using the proper struct size for the copy.

19 months agoDOC: management: add documentation about customized payload pattern
William Lallemand [Mon, 27 Nov 2023 22:26:52 +0000 (23:26 +0100)] 
DOC: management: add documentation about customized payload pattern

One can customize a payload pattern in order to change the way the
payload ends.

19 months agoMINOR: mworker/cli: implements the customized payload pattern for master CLI
William Lallemand [Tue, 28 Nov 2023 16:57:21 +0000 (17:57 +0100)] 
MINOR: mworker/cli: implements the customized payload pattern for master CLI

Implements the customized payload pattern for the master CLI.

The pattern is stored in the stream in char pcli_payload_pat[8].

The principle is basically the same as the CLI one, it looks for '<<'
then stores what's between '<<' and '\n', and look for it to exit the
payload mode.

19 months agoCLEANUP: mworker/cli: use a label to return errors
William Lallemand [Tue, 28 Nov 2023 16:28:07 +0000 (17:28 +0100)] 
CLEANUP: mworker/cli: use a label to return errors

Remove the returns in the function to end directly at the end label.

19 months agoMEDIUM: cli: allow custom pattern for payload
William Lallemand [Mon, 27 Nov 2023 15:04:20 +0000 (16:04 +0100)] 
MEDIUM: cli: allow custom pattern for payload

The CLI payload syntax has some limitation, it can't handle payloads
with empty lines, which is a common problem when uploading a PEM file
over the CLI.

This patch implements a way to customize the ending pattern of the CLI,
so we can't look for other things than empty lines.

A char cli_payload_pat[8] is used in the appctx to store the customized
pattern. The pattern can't be more than 7 characters and can still empty
to match an empty line.

The cli_io_handler() identifies the pattern and stores it, and
cli_parse_request() identifies the end of the payload.

If the customized pattern between "<<" and "\n" is more than 7
characters, it is not considered as a pattern.

This patch only implements the parser for the 'stats socket', another
patch is needed for the 'master CLI'.

19 months agoBUG/MINOR: cache: Remove incomplete entries from the cache when stream is closed
Remi Tricot-Le Breton [Tue, 28 Nov 2023 16:08:56 +0000 (17:08 +0100)] 
BUG/MINOR: cache: Remove incomplete entries from the cache when stream is closed

When a stream is interrupted by the client before the full answer is
stored in the cache, we end up with an incomplete entry in the cache
that cannot be overwritten until it "naturally" expires. In such a case,
we call the cache filter's cache_store_strm_deinit callback without ever
calling cache_store_http_end which means that the 'complete' flag is
never set on the concerned cache_entry.
This patch adds a check on the 'complete' flag in the strm_deinit
callback and removes the entry from the cache if it is incomplete.

A way to exhibit this bug is to try to get the same "big" response on
multiple clients at the same time thanks to h2load for instance, and to
interrupt the client side before the answer can be fully stored in the
cache.

This patch can be backported up to 2.4 but it will need some rework
starting with branch 2.8 because of the latest cache changes.

19 months agoREORG: quic: Move quic_increment_curr_handshake() to quic_sock
Frédéric Lécaille [Tue, 28 Nov 2023 14:01:01 +0000 (15:01 +0100)] 
REORG: quic: Move quic_increment_curr_handshake() to quic_sock

Move quic_increment_curr_handshake() from quic_conn.c to quic_sock.h to be inlined.
Also move all the inlined functions at the end of this header.

19 months agoREORG: quic: Remove qc_pkt_insert() implementation
Frédéric Lécaille [Tue, 28 Nov 2023 13:52:22 +0000 (14:52 +0100)] 
REORG: quic: Remove qc_pkt_insert() implementation

As this function does only a few things with a not very well chosen name,
remove it and replace it by the its statements at the unique location it
is called.

19 months agoREORG: quic: Add a new module for retransmissions
Frédéric Lécaille [Tue, 28 Nov 2023 13:27:33 +0000 (14:27 +0100)] 
REORG: quic: Add a new module for retransmissions

Move several functions in relation with the retransmissions from TX part
(quic_tx.c) to quic_retransmit.c new C file.

19 months agoREORG: quic: Move qc_notify_send() to quic_conn
Frédéric Lécaille [Tue, 28 Nov 2023 13:02:17 +0000 (14:02 +0100)] 
REORG: quic: Move qc_notify_send() to quic_conn

Move qc_notify_send() from quic_tx.c to quic_conn.c. Note that it was already
exported from both quic_conn.h and quic_tx.h. Modify this latter header
to fix the duplication.

19 months agoBUILD: quic: Several compiler warns fixes after retry module creation
Frédéric Lécaille [Tue, 28 Nov 2023 10:37:44 +0000 (11:37 +0100)] 
BUILD: quic: Several compiler warns fixes after retry module creation

Such a warning appeared after having added quic_retry.h which includes only
headers for types (quic_cid-t.h, clock-t.h...)

In file included from include/haproxy/quic_retry.h:12,
                 from src/quic_retry.c:5:
include/haproxy/quic_cid-t.h:26:26: error: field ‘seq_num’ has incomplete type
   26 |         struct eb64_node seq_num;

19 months agoREORG: quic: Add a new module for QUIC retry
Frédéric Lécaille [Tue, 28 Nov 2023 10:25:04 +0000 (11:25 +0100)] 
REORG: quic: Add a new module for QUIC retry

Add quic_retry.c new C file for the QUIC retry feature:
   quic_saddr_cpy() moved from quic_tx.c,
   quic_generate_retry_token_aad() moved from
   quic_generate_retry_token() moved from
   parse_retry_token() moved from
   quic_retry_token_check() moved from
   quic_retry_token_check() moved from

19 months agoREORG: quic: Move ncbuf related function from quic_rx to quic_conn
Frédéric Lécaille [Tue, 28 Nov 2023 08:09:36 +0000 (09:09 +0100)] 
REORG: quic: Move ncbuf related function from quic_rx to quic_conn

Move quic_get_ncbuf() and quic_free_ncbuf() from quic_rx.c to quic_conn.h
as static inlined functions.

19 months agoREORG: quic: Move NEW_CONNECTION_ID frame builder to quic_cid
Frédéric Lécaille [Tue, 28 Nov 2023 07:59:15 +0000 (08:59 +0100)] 
REORG: quic: Move NEW_CONNECTION_ID frame builder to quic_cid

Move qc_build_new_connection_id_frm() from quic_conn.c to quic_cid.c.
Also move quic_connection_id_to_frm_cpy() from quic_conn.h to quic_cid.h.

19 months agoREORG: quic: Rename some (quic|qc)_conn* objects to quic_conn_closed
Frédéric Lécaille [Tue, 28 Nov 2023 07:29:12 +0000 (08:29 +0100)] 
REORG: quic: Rename some (quic|qc)_conn* objects to quic_conn_closed

These objects could be confused with the ones defined by the congestion control
part (quic_cc.c).

19 months agoREORG: quic: Move qc_pkt_long() to quic_rx.h
Frédéric Lécaille [Mon, 27 Nov 2023 17:00:25 +0000 (18:00 +0100)] 
REORG: quic: Move qc_pkt_long() to quic_rx.h

This inlined function takes a quic_rx_packet struct as argument unique argument.
Let's move it to QUIC RX part.

19 months agoREORG: quic: Move qc_may_probe_ipktns() to quic_tls.h
Frédéric Lécaille [Mon, 27 Nov 2023 16:28:40 +0000 (17:28 +0100)] 
REORG: quic: Move qc_may_probe_ipktns() to quic_tls.h

This function is in relation with the Initial packet number space which is
more linked to the QUIC TLS specifications. Let's move it to quic_tls.h
to be inlined.

19 months agoREORG: quic: Move quic_build_post_handshake_frames() to quic_conn module
Frédéric Lécaille [Mon, 27 Nov 2023 16:04:32 +0000 (17:04 +0100)] 
REORG: quic: Move quic_build_post_handshake_frames() to quic_conn module

Move quic_build_post_handshake_frames() from quic_rx.c to quic_conn.c. This
is a function which is also called from the TX part (quic_tx.c).

19 months agoREORG: quic: Move qc_handle_conn_migration() to quic_conn.c
Frédéric Lécaille [Mon, 27 Nov 2023 15:56:50 +0000 (16:56 +0100)] 
REORG: quic: Move qc_handle_conn_migration() to quic_conn.c

This function manipulates only quic_conn objects. Its location is definitively
in quic_conn.c.

19 months agoREORG: quic: Move QUIC path definitions/declarations to quic_cc module
Frédéric Lécaille [Mon, 27 Nov 2023 15:50:17 +0000 (16:50 +0100)] 
REORG: quic: Move QUIC path definitions/declarations to quic_cc module

Move quic_path struct from quic_conn-t.h to quic_cc-t.h and rename it to quic_cc_path.
Update the code consequently.
Also some inlined functions in relation with QUIC path to quic_cc.h

19 months agoREORG: quic: Rename some functions used upon ACK receipt
Frédéric Lécaille [Mon, 27 Nov 2023 15:25:53 +0000 (16:25 +0100)] 
REORG: quic: Rename some functions used upon ACK receipt

Rename some functions to reflect more their jobs.
Move qc_release_lost_pkts() to quic_loss.c

19 months agoREORG: quic: Move the QUIC DCID parser to quic_sock.c
Frédéric Lécaille [Mon, 27 Nov 2023 11:01:36 +0000 (12:01 +0100)] 
REORG: quic: Move the QUIC DCID parser to quic_sock.c

Move quic_get_dgram_dcid() from quic_conn.c to quic_sock.c because
only used in this file and define it as static.

19 months agoREORG: quic: Move QUIC SSL BIO method related functions to quic_ssl.c
Frédéric Lécaille [Mon, 27 Nov 2023 10:54:05 +0000 (11:54 +0100)] 
REORG: quic: Move QUIC SSL BIO method related functions to quic_ssl.c

Move __quic_conn_init() and __quic_conn_deinit() from quic_conn.c to quic_ssl.c.

19 months agoREORG: quic: Move several inlined functions from quic_conn.h
Frédéric Lécaille [Mon, 27 Nov 2023 10:34:03 +0000 (11:34 +0100)] 
REORG: quic: Move several inlined functions from quic_conn.h

Move quic_pkt_type(), quic_saddr_cpy(), quic_write_uint32(), max_available_room(),
max_stream_data_size(), quic_packet_number_length(), quic_packet_number_encode()
and quic_compute_ack_delay_us() to quic_tx.c because only used in this file.
Also move quic_ack_delay_ms() and quic_read_uint32() to quic_tx.c because they
are used only in this file.

Move quic_rx_packet_refinc() and quic_rx_packet_refdec() to quic_rx.h header.
Move qc_el_rx_pkts(), qc_el_rx_pkts_del() and qc_list_qel_rx_pkts() to quic_tls.h
header.

19 months agoREORG: quic: Move QUIC CRYPTO stream definitions/declarations to QUIC TLS
Frédéric Lécaille [Mon, 27 Nov 2023 09:30:41 +0000 (10:30 +0100)] 
REORG: quic: Move QUIC CRYPTO stream definitions/declarations to QUIC TLS

Move quic_cstream struct definition from quic_conn-t.h to quic_tls-t.h.
Its pool is also moved from quic_conn module to quic_tls. Same thing for
quic_cstream_new() and quic_cstream_free().

19 months agoREORG: quic: Move CRYPTO data buffer defintions to QUIC TLS module
Frédéric Lécaille [Mon, 27 Nov 2023 09:09:12 +0000 (10:09 +0100)] 
REORG: quic: Move CRYPTO data buffer defintions to QUIC TLS module

Move quic_crypto_buf struct definition from quic_conn-t.h to quic_tls-t.h.
Also move its pool definition/declaration to quic_tls-t.h/quic_tls.c.

19 months agoBUILD: quic: Missing RX header inclusions
Frédéric Lécaille [Mon, 27 Nov 2023 08:10:29 +0000 (09:10 +0100)] 
BUILD: quic: Missing RX header inclusions

Fix such building issues:
   In file included from src/quic_tx.c:15:
        include/haproxy/quic_tx.h:51:23: warning: ‘struct quic_rx_packet’

Do not know why the compiler warns about such missing header inclusions
just now. It should have complained a long time ago during the big QUIC
source code split.

19 months agoREORG: quic: QUIC connection types header cleaning
Frédéric Lécaille [Mon, 27 Nov 2023 08:07:12 +0000 (09:07 +0100)] 
REORG: quic: QUIC connection types header cleaning

Move UDP datagram definitions from quic_conn-t.h to quic_sock-t.h
Move debug quic_rx_crypto_frm struct from quic_conn-t.h to quic_trace-t.h

19 months agoREORG: quic: Add a new module to handle QUIC connection IDs
Frédéric Lécaille [Thu, 23 Nov 2023 18:21:03 +0000 (19:21 +0100)] 
REORG: quic: Add a new module to handle QUIC connection IDs

Move quic_cid and quic_connnection_id from quic_conn-t.h to new quic_cid-t.h header.
Move defintions of quic_stateless_reset_token_init(), quic_derive_cid(),
new_quic_cid(), quic_get_cid_tid() and retrieve_qc_conn_from_cid() to quic_cid.c
new C file.

19 months agoREORG: quic: Move some QUIC CLI code to its C file
Frédéric Lécaille [Thu, 23 Nov 2023 14:57:53 +0000 (15:57 +0100)] 
REORG: quic: Move some QUIC CLI code to its C file

Move init_quic() from quic_conn.c to quic_cli.c and rename it to cli_quic_init().

19 months agoCLEANUP: quic: Remove dead definitions/declarations
Frédéric Lécaille [Thu, 23 Nov 2023 14:50:18 +0000 (15:50 +0100)] 
CLEANUP: quic: Remove dead definitions/declarations

Remove useless definitions and declarations.

19 months agoBUG/MEDIUM: mux-h2: Remove H2_SF_NOTIFIED flag for H2S blocked on fast-forward
Christopher Faulet [Mon, 27 Nov 2023 17:02:16 +0000 (18:02 +0100)] 
BUG/MEDIUM: mux-h2: Remove H2_SF_NOTIFIED flag for H2S blocked on fast-forward

When a H2 stream is blocked during data fast-forwarding, we must take care
to remove H2_SF_NOTIFIED flag. This was only performed when data
fast-forward was attempted. However, if the H2 stream was blocked for any
reason, this flag was not removed. During our tests, we found it was
possible to infinitely block a connection because one of its streams was in
the send_list with the flag set. In this case, the stream was no longer
woken up to resume the sends, blocking all other streams.

No backport needed.

19 months agoBUG/MEDIUM: stconn: Don't perform zero-copy FF if opposite SC is blocked
Christopher Faulet [Mon, 27 Nov 2023 16:56:30 +0000 (17:56 +0100)] 
BUG/MEDIUM: stconn: Don't perform zero-copy FF if opposite SC is blocked

When zero-copy data fast-forwarding is inuse, if the opposite SC is blocked,
there is no reason to try to fast-forward more data. Worst, in some cases,
this can lead to a receive loop of the producer side while the consumer side
is blocked.

No backport needed.

19 months agoBUG/MINOR: quic: fix CONNECTION_CLOSE_APP encoding
Amaury Denoyelle [Tue, 28 Nov 2023 10:23:41 +0000 (11:23 +0100)] 
BUG/MINOR: quic: fix CONNECTION_CLOSE_APP encoding

CONNECTION_CLOSE_APP encoding is broken, which prevents the sending of
every packet with such a frame. This bug was always present in quic
haproxy. However, it was slightly dissimulated by the previous code
which always initialized all frame members to zero, which was sufficient
to ensure CONNECTION_CLOSE_APP encoding was ok. The below patch changes
this behavior by removing this costly initialization step.

  4cf784f38ed20b42f6e71bd8a2e8157b95329ee5
  MINOR: quic: Avoid zeroing frame structures

Now, frames members must always be initialized individually given the
type of frame to used. However, for CONNECTION_CLOSE_APP this was not
done as qc_cc_build_frm() accessed the wrong union member refering to a
CONNECTION_CLOSE instead.

This bug was detected when trying to generate a HTTP/3 error. The
CONNECTION_CLOSE_APP frame encoding failed due to a non-initialized
<reason_phrase_len> which was too big. This was reported by the
following trace :
  "frame building error : qc@0x5555561b86c0 idle_timer_task@0x5555561e5050 flags=0x86038058 CONNECTION_CLOSE_APP"

This must be backported up to 2.6. This is necessary even if above
commit is not as previous code is also buggy, albeit with a different
behavior.

19 months agoOPTIM: mux-h2/zero-copy: don't allocate more buffers per connections than streams
Willy Tarreau [Tue, 28 Nov 2023 08:15:26 +0000 (09:15 +0100)] 
OPTIM: mux-h2/zero-copy: don't allocate more buffers per connections than streams

It's the exact same as commit 0a7ab7067 ("OPTIM: mux-h2: don't allocate
more buffers per connections than streams"), but for the zero-copy case
this time. Previously it was only done on the regular snd_buf() path, but
this one is needed as well. A transfer on 16 parallel streams now consumes
half of the memory, and a single stream consumes much less.

An alternate approach would be worth investigating in the future, based
on the same principle as the CF_STREAMER_FAST at the higher level: in
short, by monitoring how many mux buffers we write at once before refilling
them, we would get an idea of how much is worth keeping in buffers max,
given that anything beyond would just waste memory. Some tests show that
a single buffer already seems almost as good, except for single-stream
transfers, which is why it's worth spending more time on this.

19 months agoMINOR: trace: support -dt optional format
Amaury Denoyelle [Wed, 22 Nov 2023 16:27:57 +0000 (17:27 +0100)] 
MINOR: trace: support -dt optional format

Add an optional argument for "-dt". This argument is interpreted as a
list of several trace statement separated by comma. For each statement,
a specific trace name can be specifed, or none to act on all sources.
Using double-colon separator, it is possible to add specifications on
the wanted level and verbosity.

19 months agoMINOR: trace: parse verbosity in a function
Amaury Denoyelle [Wed, 22 Nov 2023 16:26:24 +0000 (17:26 +0100)] 
MINOR: trace: parse verbosity in a function

This patch is similar to the previous one except that it handles trace
verbosity. Trace source must be specified unless "quiet" is used.

19 months agoMINOR: trace: parse level in a function
Amaury Denoyelle [Wed, 22 Nov 2023 16:25:52 +0000 (17:25 +0100)] 
MINOR: trace: parse level in a function

Extract conversion of level string argument to integer value in a
dedicated internal function trace_parse_level(). This function is used
to for CLI trace parsing and will also be useful for "-dt" process
argument.

19 months agoMINOR: trace: define simple -dt argument
Amaury Denoyelle [Wed, 22 Nov 2023 13:58:59 +0000 (14:58 +0100)] 
MINOR: trace: define simple -dt argument

Add '-dt' haproxy process argument. This will automatically activate all
trace sources on stderr with the error level. This could be useful to
troubleshoot issues such as protocol violations.

19 months agoBUILD: map: fix build warning
Amaury Denoyelle [Mon, 27 Nov 2023 13:49:33 +0000 (14:49 +0100)] 
BUILD: map: fix build warning

<pattern> field pointer of pat_ref_elt structure has been by a
zero-length array. As such, it's now unneeded to check for NULL address
before printing it.

This type conversion was done in the following commit :
  3ac9912837118a81f3291e106ce9a7c4be6c934f
  OPTIM: pattern: save memory and time using ebst instead of ebis

The current patch is mandatory to fix the following GCC warning :
  CC      src/map.o
  src/map.c: In function ‘cli_io_handler_map_lookup’:
  src/map.c:549:54: error: the comparison will always evaluate as ‘true’ for the address of ‘pattern’ will never be NULL [-Werror=address]
  549 |                                         if (pat->ref && pat->ref->pattern)
      |

No need to backport it unless the above commit is.

19 months agoOPTIM: pattern: save memory and time using ebst instead of ebis
Willy Tarreau [Sun, 26 Nov 2023 10:56:08 +0000 (11:56 +0100)] 
OPTIM: pattern: save memory and time using ebst instead of ebis

In the pat_ref_elt struct, the pattern string is stored outside of the
node element, using a pointer to an strdup(). Not only this needlessly
wastes at least 16-24 bytes per entry (8 for the pointer, 8-16 for the
allocator), it also makes the tree descent less efficient since both
the node and the string have to be visited for each layer (hence at least
two cache lines). Let's use an ebmb storage and place the pattern right
at the end of the pat_ref_elt, making it a variable-sized element instead.

The set-map test below jumps from 173 to 182 kreq/s/core, and the memory
usage drops from 356 MB to 324 MB:

  http-request set-map(/dev/null) %[rand(1000000)] 1

This is even more visible with large maps: after loading 16M IP addresses
into a map, the process uses this amount of memory:

  - 3.15 GB with haproxy-2.8
  - 4.21 GB with haproxy-2.9-dev11
  - 3.68 GB with this patch

So that's a net saving of 32 bytes per entry here, which cuts in half the
extra cost of the tree, and loading a large map takes about 20% less time.

19 months agoMINOR: task/profiling: do not record task_drop_running() as a caller
Willy Tarreau [Fri, 24 Nov 2023 15:45:34 +0000 (16:45 +0100)] 
MINOR: task/profiling: do not record task_drop_running() as a caller

Task_drop_running() is used to remove the RUNNING bit and check if
while the task was running it got a new wakeup from itself. Thus
each time task_drop_running() marks itself as a caller, it in fact
removes the previous caller that woke up the task, such as below:

Tasks activity over 10.439 sec till 0.000 sec ago:
  function                      calls   cpu_tot   cpu_avg   lat_tot   lat_avg
  task_run_applet            57895273   6.396m    6.628us   2.733h    170.0us <- run_tasks_from_lists@src/task.c:658 task_drop_running

Better not mark this function as a caller and keep the original one:

Tasks activity over 13.834 sec till 0.000 sec ago:
  function                      calls   cpu_tot   cpu_avg   lat_tot   lat_avg
  task_run_applet            62424582   5.825m    5.599us   5.717h    329.7us <- sc_app_chk_rcv_applet@src/stconn.c:952 appctx_wakeup

19 months agoBUG/MEDIUM: mux-h1: Properly ignore trailers when a content-length is announced
Christopher Faulet [Mon, 27 Nov 2023 07:23:45 +0000 (08:23 +0100)] 
BUG/MEDIUM: mux-h1: Properly ignore trailers when a content-length is announced

It is not possible in H1, but in H2 (and probably H3) it is possible to have
trailers at the end of a message while a Content-Length was announced.

However, depending if the trailers are received with the last HTX DATA block
or the zero-copy forwarding is used or not, an processing error may be
triggered, leading to a 500-internal-error.

To fix the issue, when a content-length is announced and all the payload was
processed, we switch the message to H1_MSG_DONE state only if the
end-of-message was also reported (HTX_FL_EOM flag set). Otherwise, it is
switched to H1_MSG_TRAILERS state to be able to properly ignored the
trailers, if so.

The patch must be backported as far as 2.4. Be careful, this part was highly
refactored. The patch will have to be adapted to be backported.

19 months agoMINOR: mworker/cli: implement hard-reload over the master CLI
William Lallemand [Fri, 24 Nov 2023 20:20:32 +0000 (21:20 +0100)] 
MINOR: mworker/cli: implement hard-reload over the master CLI

The mworker mode never had a proper 'hard-stop' (-st) for the reload,
this is a mode which was commonly used with the daemon mode, but it was
never implemented in mworker mode.

This patch fixes the problem by implementing a "hard-reload" command
over the master CLI. It does the same as the "reload" command, but
instead of waiting for the connections to stop in the previous process,
it immediately quits the previous process after binding.

19 months agoMEDIUM: ssl: use ssl_sock_chose_sni_ctx() in the clienthello callback
William Lallemand [Thu, 23 Nov 2023 16:54:47 +0000 (17:54 +0100)] 
MEDIUM: ssl: use ssl_sock_chose_sni_ctx() in the clienthello callback

This patch removes the code which selects the SSL certificate in the
OpenSSL Client Hello callback, to use the ssl_sock_chose_sni_ctx()
function which does the same.

The bigger part of the function which remains is the extraction of the
servername, ciphers and sigalgs, because it's done manually by parsing
the TLS extensions.

This is not supposed to change anything functionally.

19 months agoMINOR: ssl: move certificate selection in a dedicate function
William Lallemand [Thu, 23 Nov 2023 15:35:52 +0000 (16:35 +0100)] 
MINOR: ssl: move certificate selection in a dedicate function

The certificate selection used in the WolfSSL cert_cb and in the OpenSSL
clienthello callback is the same, the function was duplicate to achieve
the same.

This patch move the selection code to a common function called
ssl_sock_chose_sni_ctx().

The servername string is still lowered in the callback, however the
search for the first dot in the string (wildp) is done in
ssl_sock_chose_sni_ctx()

The function uses the same certificate selection algorithm as before, it
needs to know if you need rsa or ecdsa, the bind_conf to achieve the
lookup, and the servername string.

This patch moves the code for WolSSL only.

19 months agoMINOR: ssl: replace 'trash.area' by 'servername' in ssl_sock_switchctx_cbk()
William Lallemand [Fri, 24 Nov 2023 18:20:28 +0000 (19:20 +0100)] 
MINOR: ssl: replace 'trash.area' by 'servername' in ssl_sock_switchctx_cbk()

Replace 'trash.area' by 'servername' for more readibility.

19 months agoMEDIUM: ssl: implement rsa/ecdsa selection with WolfSSL
William Lallemand [Thu, 16 Nov 2023 17:16:53 +0000 (18:16 +0100)] 
MEDIUM: ssl: implement rsa/ecdsa selection with WolfSSL

PR https://github.com/wolfSSL/wolfssl/pull/6963 implements primitives to
extract ciphers and algorithm signatures.

It allows to chose a certificate depending on the sigals and
ciphers presented by the client (RSA or ECDSA).

Since WolfSSL does not implement the clienthello callback, the patch
uses the certificate callback (SSL_CTX_set_cert_cb())

The callback is inspired by our clienthello callback, however the
extraction of client ciphers and sigalgs is simpler,
wolfSSL_get_sigalg_info() and wolfSSL_get_ciphersuite_info() are used.

This is not enabled by default yet as the PR was not merged.

19 months agoDOC: lua: add "syslog" to Proxy.get_mode() output
Aurelien DARRAGON [Thu, 23 Nov 2023 15:12:23 +0000 (16:12 +0100)] 
DOC: lua: add "syslog" to Proxy.get_mode() output

Following previous commit: in this patch we add the "syslog" output as
possible return value for Proxy.get_mode() function since log backend
may now be enumerated from lua with 9a74a6c ("MAJOR: log: introduce log
backends")

19 months agoDOC: lua: fix Proxy.get_mode() output
Aurelien DARRAGON [Thu, 23 Nov 2023 15:02:14 +0000 (16:02 +0100)] 
DOC: lua: fix Proxy.get_mode() output

Proxy.get_mode() function internally relies on proxy_mode_str() to return
the proxy mode. The current function description is exhaustive about the
possible outputs for the function. I can't tell if it's relevant or not
but it's subject to changes. Here it is the case, the documentation
indicates that "health" mode may be returned, which cannot happen
since 77e0daef9 ("MEDIUM: proxy: remove obsolete "mode health"").

This should be backported up to 2.4

19 months agoDOC: lua: add sticktable class reference from Proxy.stktable
Aurelien DARRAGON [Thu, 23 Nov 2023 12:47:54 +0000 (13:47 +0100)] 
DOC: lua: add sticktable class reference from Proxy.stktable

Add a reference hint for the sticktable class and mention it from
Proxy.stktable documentation to allow easy navigation from a web
browser.

19 months agoREGTESTS: connection: disable http_reuse_be_transparent.vtc if !TPROXY
Aurelien DARRAGON [Thu, 23 Nov 2023 08:23:30 +0000 (09:23 +0100)] 
REGTESTS: connection: disable http_reuse_be_transparent.vtc if !TPROXY

http_reuse_be_transparent.vtc relies on "transparent" proxy option which
is guarded by the USE_TPROXY ifdef at multiple places in the code.

Hence, executing the above test when haproxy was compiled without the
USE_TPROXY feature (ie: generic target) results in this kind of error:

  ***  h1    debug|[NOTICE]   (1189756) : haproxy version is 2.9-dev1-8fc21e-807
  ***  h1    debug|[NOTICE]   (1189756) : path to executable is ./haproxy
  ***  h1    debug|[ALERT]    (1189756) : config : parsing [/tmp/vtc.1189751.18665e7b/h1/cfg:11]: option 'transparent' is not supported due to build options.
  ***  h1    debug|[ALERT]    (1189756) : config : Error(s) found in configuration file : /tmp/vtc.1189751.18665e7b/h1/cfg

Now we skip the regtest if TPROXY feature is missing.

19 months agoDOC: config: fix timeout check inheritance restrictions
Aurelien DARRAGON [Tue, 21 Nov 2023 09:35:52 +0000 (10:35 +0100)] 
DOC: config: fix timeout check inheritance restrictions

In 6e0425b718 ("DOC: config: Add documentation about TCP/HTTP rules in
defaults section") an error was made: the restriction note about the
setting not being inherited from anonymous default section was added
by mistake in the "timeout check" documentation. But it is wrong,
"timeout check" behaves like other "timeout" directives for proxy
sections.

This should be backported up to 2.6.

19 months agoDOC: config: specify supported sections for "max-session-srv-conns"
Aurelien DARRAGON [Mon, 20 Nov 2023 16:53:36 +0000 (17:53 +0100)] 
DOC: config: specify supported sections for "max-session-srv-conns"

There was no info about supported sections for "max-session-srv-conns"
proxy directive. A quick look at the code tells us that it may be used
in proxies with the FE capability set.

19 months agoMINOR: log/balance: set lbprm tot_weight on server on queue/dequeue
Aurelien DARRAGON [Tue, 21 Nov 2023 12:19:12 +0000 (13:19 +0100)] 
MINOR: log/balance: set lbprm tot_weight on server on queue/dequeue

Maintain proper px->lbprm.tot_weight for log backends. server's weight is
considered as 1 as long as the server is usable.

This will allow the stats page to correctly display the proxy status since
the check currently relies on proxy's lbprm.tot_weight variable.

19 months agoMINOR: log/backend: prevent "use-server" rules use with LOG mode
Aurelien DARRAGON [Thu, 23 Nov 2023 15:40:19 +0000 (16:40 +0100)] 
MINOR: log/backend: prevent "use-server" rules use with LOG mode

server_rules declared using "use-server" keyword within a proxy are not
supported inside a log backend (with "mode log" set), so we report a
warning to the user and reset the setting.

19 months agoMINOR: proxy: add free_server_rules() helper function
Aurelien DARRAGON [Thu, 23 Nov 2023 15:27:45 +0000 (16:27 +0100)] 
MINOR: proxy: add free_server_rules() helper function

Take the px->server_rules freeing part out of free_proxy() and make it
a dedicated helper function so that it becomes possible to use it from
anywhere.

19 months agoMINOR: proxy: add free_logformat_list() helper function
Aurelien DARRAGON [Thu, 23 Nov 2023 16:30:10 +0000 (17:30 +0100)] 
MINOR: proxy: add free_logformat_list() helper function

There are multiple places inside free_proxy() where we need to perform
the exact same operation: freeing a logformat list which includes freeing
every member.

To prevent code duplication, we add the free_logformat_list() function
that takes such list as parameter and does all the freeing job on its
own.

19 months agoRevert "MINOR: cfgparse-listen: warn when use-server rules is used in wrong mode"
Aurelien DARRAGON [Thu, 23 Nov 2023 15:15:10 +0000 (16:15 +0100)] 
Revert "MINOR: cfgparse-listen: warn when use-server rules is used in wrong mode"

This reverts commit 5884e46ec8c8231e73c68e1bdd345c75c9af97a0 since we
cannot perform the test during parsing as the effective proxy mode is
not yet known.

19 months agoMINOR: backend: remove invalid mode test for "hash-balance-factor"
Aurelien DARRAGON [Mon, 20 Nov 2023 10:33:20 +0000 (11:33 +0100)] 
MINOR: backend: remove invalid mode test for "hash-balance-factor"

This is a leftover from 1e0093a317 ("MINOR: backend/balance: "balance"
requires TCP or HTTP mode").

Indeed, we cannot perform the test during parsing as the effective proxy
type is not yet known. Moreover, thanks to b61147fd ("MEDIUM: log/balance:
merge tcp/http algo with log ones") we could potentially benefit from
this setting even in log mode, but for now it is ignored by all log
compatible load-balancing algorithms.

19 months agoMINOR: server/ip: centralize server ip updates
Aurelien DARRAGON [Mon, 13 Nov 2023 15:42:56 +0000 (16:42 +0100)] 
MINOR: server/ip: centralize server ip updates

Add a new helper function named _srv_update_inetaddr() to centralize ip
addr and port updates during runtime.

19 months agoMINOR: tools: use const for read only pointers in ip{cmp,cpy}
Aurelien DARRAGON [Mon, 13 Nov 2023 13:12:04 +0000 (14:12 +0100)] 
MINOR: tools: use const for read only pointers in ip{cmp,cpy}

In this patch we fix the prototype for ipcmp() and ipcpy() functions so
that input pointers that are used exclusively for reads are used as const
pointers. This way, the compiler can safely assume that those variables
won't be altered by the function.

19 months agoMINOR: server/event_hdl: add SERVER_INETADDR event
Aurelien DARRAGON [Fri, 10 Nov 2023 19:12:00 +0000 (20:12 +0100)] 
MINOR: server/event_hdl: add SERVER_INETADDR event

In this patch we add the support for a new SERVER event in the
event_hdl API.

SERVER_INETADDR is implemented as an advanced server event.
It is published each time the server's ip address or port is
about to change. (ie: from the cli, dns, lua...)

SERVER_INETADDR data is an event_hdl_cb_data_server_inetaddr struct
that provides additional info related to the server inet addr change,
but can be casted as a regular event_hdl_cb_data_server struct if
additional info is not needed.

19 months agoDOC: config: removing "log-balance" references
Aurelien DARRAGON [Tue, 21 Nov 2023 10:28:26 +0000 (11:28 +0100)] 
DOC: config: removing "log-balance" references

"log-balance" keyword was removed by b61147f ("MEDIUM: log/balance: merge
tcp/http algo with log ones") but it was still documented.

Removing "log-balance" references in the documentation where needed.

19 months agoBUG/MINOR: global: Fix tune.disable-(fast-forward/zero-copy-forwarding) options
Christopher Faulet [Fri, 24 Nov 2023 08:23:04 +0000 (09:23 +0100)] 
BUG/MINOR: global: Fix tune.disable-(fast-forward/zero-copy-forwarding) options

These options were not properly handled during configration parsing. A wrong
bitwise operation was used.

No backport needed.

19 months ago[RELEASE] Released version 2.9-dev11 v2.9-dev11
Willy Tarreau [Fri, 24 Nov 2023 07:14:31 +0000 (08:14 +0100)] 
[RELEASE] Released version 2.9-dev11

Released version 2.9-dev11 with the following main changes :
    - BUG/MINOR: startup: set GTUNE_SOCKET_TRANSFER correctly
    - BUG/MINOR: sock: mark abns sockets as non-suspendable and always unbind them
    - BUILD: cache: fix build error on older compilers
    - BUG/MAJOR: quic: complete thread migration before tcp-rules
    - BUG/MEDIUM: quic: Possible crash for connections to be killed
    - MINOR: quic: remove unneeded QUIC specific stopping function
    - MINOR: acl: define explicit HTTP_3.0
    - DEBUG: connection/flags: update flags for reverse HTTP
    - BUILD: log: silence a build warning when threads are disabled
    - MINOR: quic: Add traces to debug frames handling during retransmissions
    - BUG/MEDIUM: quic: Possible crash during retransmissions and heavy load
    - BUG/MINOR: quic: Possible leak of TX packets under heavy load
    - BUG/MINOR: quic: Possible RX packet memory leak under heavy load
    - BUG/MINOR: server: do not leak default-server in defaults sections
    - DEBUG: tinfo: store the pthread ID and the stack pointer in tinfo
    - MINOR: debug: start to create a new struct post_mortem
    - MINOR: debug: add OS/hardware info to the post_mortem struct
    - MINOR: debug: report in port_mortem whether a container was detected
    - MINOR: debug: report in post_mortem if the container techno used is docker
    - MINOR: debug: detect CPU model and store it in post_mortem
    - MINOR: debug: report any detected hypervisor in post_mortem
    - MINOR: debug: collect some boot-time info related to the process
    - MINOR: debug: copy the thread info into the post_mortem struct
    - MINOR: debug: dump the mapping of the libs into post_mortem
    - MINOR: debug: add the ability to enter components in the post_mortem struct
    - MINOR: init: add info about the main program to the post_mortem struct
    - DOC: management: document "show dev"
    - CLEANUP: assorted typo fixes in the code and comments
    - CI: limit codespell checks to main repo, not forks
    - DOC: 51d: updated 51Degrees repo URL for v3.2.10
    - DOC: install: update the list of openssl versions
    - MINOR: ext-check: add an option to preserve environment variables
    - BUG/MEDIUM: mux-h1: Don't set CO_SFL_MSG_MORE flag on last fast-forward send
    - MINOR: rhttp: rename proto_reverse_connect
    - MINOR: rhttp: large renaming to use rhttp prefix
    - MINOR: rhttp: add count of active conns per thread
    - MEDIUM: rhttp: support multi-thread active connect
    - MINOR: listener: allow thread kw for rhttp bind
    - DOC: rhttp: replace maxconn by nbconn
    - MINOR: log/balance: rename "log-sticky" to "sticky"
    - MEDIUM: mux-quic: Add consumer-side fast-forwarding support
    - MAJOR: h3: Implement zero-copy support to send DATA frame

19 months agoMAJOR: h3: Implement zero-copy support to send DATA frame
Christopher Faulet [Fri, 27 Oct 2023 14:41:58 +0000 (16:41 +0200)] 
MAJOR: h3: Implement zero-copy support to send DATA frame

When possible, we try send DATA frame without copying data. To do so, we
swap the input buffer with QCS tx buffer. It is only possible iff:

 * There is only one HTX block of data at the beginning of the message
 * Amount of data to send is equal to the size of the HTX data block
 * The QCS tx buffer is empty

In this case, both buffers are swapped. The frame metadata are written at
the begining of the buffer, before data and where the HTX structure is
stored.

19 months agoMEDIUM: mux-quic: Add consumer-side fast-forwarding support
Christopher Faulet [Fri, 27 Oct 2023 13:48:13 +0000 (15:48 +0200)] 
MEDIUM: mux-quic: Add consumer-side fast-forwarding support

The QUIC multiplexer now implements callbacks to consume fast-forwarded
data. It relies on the H3 stack to acquire the buffer and format the frame.

19 months agoMINOR: log/balance: rename "log-sticky" to "sticky"
Willy Tarreau [Thu, 23 Nov 2023 17:19:41 +0000 (18:19 +0100)] 
MINOR: log/balance: rename "log-sticky" to "sticky"

After giving it some thought, it could pretty well happen that other
protocols benefit from the sticky algorithm that some used to emulate
using a "stick-on int(0)" or things like this previously. So better
rename it to "sticky" right now instead of having to keep that "log-"
prefix forever. It's still limited to logs, of course, only the algo
is renamed in the config.

19 months agoDOC: rhttp: replace maxconn by nbconn
Amaury Denoyelle [Thu, 23 Nov 2023 16:37:26 +0000 (17:37 +0100)] 
DOC: rhttp: replace maxconn by nbconn

Usage of existing "maxconn" for rhttp listeners configuration was
replaced recently by a new dedicating "nbconn" keyword. Update the
documentation part to reflect this.

No need to backport.

19 months agoMINOR: listener: allow thread kw for rhttp bind
Amaury Denoyelle [Thu, 23 Nov 2023 16:31:05 +0000 (17:31 +0100)] 
MINOR: listener: allow thread kw for rhttp bind

Thanks to previous commit, a reverse HTTP listener is able to distribute
actively opened connections accross its threads. To be able to exploit
this, allow "thread" keyword for such a listener.

An extra check is added to explicitely forbids a reverse bind to span
multiple thread groups. Without this, multiple listeners instances will
be created, each with its owned "nbconn" value. This may surprise users
so for now, better to deactivate this possibility.

19 months agoMEDIUM: rhttp: support multi-thread active connect
Amaury Denoyelle [Wed, 22 Nov 2023 17:02:37 +0000 (18:02 +0100)] 
MEDIUM: rhttp: support multi-thread active connect

Implement support for active HTTP reverse task migration on listener
threads. This operation is done each time a new reversable connection
will be instantiated. Instead of directly allocate the connection, a
lookup is done among all the listener threads.

A comparison is done to select the thread with the smallest number of
current reverse connection. If the thread found is different from the
current one, the connection allocation is delayed and the task
rescheduled on the chosen thread. The connection will then be created
and pinned on the new thread. This mechanisms allows to balance reverse
HTTP connections accross different threads.

Note that rhttp_set_affinity is still defined to disable thread
migration on accept. This is necessary as it's unsafe to move an
existing connection to another thread. However, active reverse task
migration should be sufficient to distribute connections accross several
threads. Better than that, this design allows to differentiate standard
frontend and reversable connections. The latest are designed to be
long-lived so it's useful to have their repartition solely based on
others reversed connections.

19 months agoMINOR: rhttp: add count of active conns per thread
Amaury Denoyelle [Wed, 22 Nov 2023 16:55:58 +0000 (17:55 +0100)] 
MINOR: rhttp: add count of active conns per thread

Add a new member <nb_rhttp_conns> in thread_ctx structure. Its purpose
is to count the current number of opened reverse HTTP connections
regarding from their listeners membership.

This patch will be useful to support multi-thread for active reverse
HTTP, in order to select the less loaded thread.

Note that despite access to <nb_rhttp_conns> are only done by the
current thread, atomic operations are used. This is because once
multi-thread support will be added, external threads will also retrieve
values from others.

19 months agoMINOR: rhttp: large renaming to use rhttp prefix
Amaury Denoyelle [Tue, 21 Nov 2023 10:10:34 +0000 (11:10 +0100)] 
MINOR: rhttp: large renaming to use rhttp prefix

Previous commit renames 'proto_reverse_connect' module to 'proto_rhttp'.
This commits follows this by replacing various custom prefix by 'rhttp_'
to make the code uniform.

Note that 'reverse_' prefix was kept in connection module. This is
because if a new reversable protocol not based on HTTP is implemented,
it may be necessary to reused the same connection function which are
protocol agnostic.

19 months agoMINOR: rhttp: rename proto_reverse_connect
Amaury Denoyelle [Tue, 21 Nov 2023 09:41:06 +0000 (10:41 +0100)] 
MINOR: rhttp: rename proto_reverse_connect

This commit is renaming of module proto_reverse_connect to proto_rhttp.
This name is selected as it is shorter and more precise.

19 months agoBUG/MEDIUM: mux-h1: Don't set CO_SFL_MSG_MORE flag on last fast-forward send
Christopher Faulet [Thu, 23 Nov 2023 16:26:26 +0000 (17:26 +0100)] 
BUG/MEDIUM: mux-h1: Don't set CO_SFL_MSG_MORE flag on last fast-forward send

In the mux-to-mux fast-forwarding, when end-of-input is reached on the producer
side, the consumer side must not set the CO_SFL_MSG_MORE flag on send. It means
the H1C_F_CO_MSG_MORE flag must be removed from the H1 connection.

No backport needed.

19 months agoMINOR: ext-check: add an option to preserve environment variables
Willy Tarreau [Thu, 23 Nov 2023 15:48:48 +0000 (16:48 +0100)] 
MINOR: ext-check: add an option to preserve environment variables

In Github issue #2128, @jvincze84 explained the complexity of using
external checks in some advanced setups due to the systematic purge of
environment variables, and expressed the desire to preserve the
existing environment. During the discussion an agreement was found
around having an option to "external-check" to do that and that
solution was tested and confirmed to work by user @nyxi.

This patch just cleans this up, implements the option as
"preserve-env" and documents it. The default behavior does not change,
the environment is still purged, unless "preserve-env" is passed. The
choice of not using "import-env" instead was made so that we could
later use it to name specific variables that have to be imported
instead of keeping the whole environment.

The patch is simple enough that it could be backported if needed (and
was in fact tested on 2.6 first).

19 months agoDOC: install: update the list of openssl versions
Willy Tarreau [Thu, 23 Nov 2023 15:29:42 +0000 (16:29 +0100)] 
DOC: install: update the list of openssl versions

3.2-final still builds without warnings and works at first glance, so
let's update the list of versions in the INSTALL file.

19 months agoDOC: 51d: updated 51Degrees repo URL for v3.2.10
Eugene Dorfman [Mon, 20 Nov 2023 19:41:48 +0000 (20:41 +0100)] 
DOC: 51d: updated 51Degrees repo URL for v3.2.10

The v3.2.10 branch has been migrated from the legacy git.51Degrees.com
repo to github.com.  The files on the frozen branch are exactly the same.

19 months agoCI: limit codespell checks to main repo, not forks
Ilya Shipitsin [Tue, 21 Nov 2023 18:54:17 +0000 (19:54 +0100)] 
CI: limit codespell checks to main repo, not forks

19 months agoCLEANUP: assorted typo fixes in the code and comments
Ilya Shipitsin [Tue, 21 Nov 2023 18:54:16 +0000 (19:54 +0100)] 
CLEANUP: assorted typo fixes in the code and comments

This is 37th iteration of typo fixes

19 months agoDOC: management: document "show dev"
Willy Tarreau [Thu, 23 Nov 2023 14:34:25 +0000 (15:34 +0100)] 
DOC: management: document "show dev"

Explain what "show dev" is used for and provide an example of output.

19 months agoMINOR: init: add info about the main program to the post_mortem struct
Willy Tarreau [Thu, 23 Nov 2023 10:32:24 +0000 (11:32 +0100)] 
MINOR: init: add info about the main program to the post_mortem struct

This way we'll still have haproxy's version, build options etc in core
dumps and centralized all at once.

19 months agoMINOR: debug: add the ability to enter components in the post_mortem struct
Willy Tarreau [Thu, 23 Nov 2023 10:25:34 +0000 (11:25 +0100)] 
MINOR: debug: add the ability to enter components in the post_mortem struct

Here the idea is to collect components' versions and build options. The
main component is haproxy, but the API is made so that any sub-system
can easily add a component there (for example the detailed version of a
device detection lib, or some info about a lib loaded from Lua).

The elements are stored as a pointer to an array of structs and its count
so that it's sufficient to issue this in gdb to list them all at once:

  print *post_mortem.components@post_mortem.nb_components

For now we collect name, version, toolchain, toolchain options, build
options and path. Maybe more could be useful in the future.

19 months agoMINOR: debug: dump the mapping of the libs into post_mortem
Willy Tarreau [Thu, 23 Nov 2023 07:26:52 +0000 (08:26 +0100)] 
MINOR: debug: dump the mapping of the libs into post_mortem

Having the libs and their addresses listed in the post_mortem struct
is also helpful. Sometimes it helps notice that one version is not the
expected one, e.g. due to some LD_LIBRARY_PATH. We don't emit it on
"show dev" however since that's already available via "show libs".

19 months agoMINOR: debug: copy the thread info into the post_mortem struct
Willy Tarreau [Wed, 22 Nov 2023 17:30:19 +0000 (18:30 +0100)] 
MINOR: debug: copy the thread info into the post_mortem struct

The last starting thread now copies the pthread ID and stack top of
each thread into post_mortem. That way it's as easy as issuing
"p post_mortem" in gdb to see all thread IDs and stack frames and more
easily map them to the threads met in a core.

19 months agoMINOR: debug: collect some boot-time info related to the process
Willy Tarreau [Wed, 22 Nov 2023 14:37:57 +0000 (15:37 +0100)] 
MINOR: debug: collect some boot-time info related to the process

Here we collect the original uid/gid/rlimits for FD and RAM since these
ones do affect behavior and are sometimes different from expected in
containers or when starting as a service.

19 months agoMINOR: debug: report any detected hypervisor in post_mortem
Willy Tarreau [Wed, 22 Nov 2023 11:04:02 +0000 (12:04 +0100)] 
MINOR: debug: report any detected hypervisor in post_mortem

When the x86 CPU flags show the "hypervisor" flag, we know we're running
inside QEMU, VMware or possibly other flavors of hypervisors. In this
case we'll report either "qemu", "vmware" or "yes" for other ones in
the "virt_techno" field, based on the DMI hardware vendor name,
otherwise "no" when the flag is not found.

19 months agoMINOR: debug: detect CPU model and store it in post_mortem
Willy Tarreau [Wed, 22 Nov 2023 10:55:22 +0000 (11:55 +0100)] 
MINOR: debug: detect CPU model and store it in post_mortem

The CPU model and type has significant impact on certain bugs, such
as contention issues caused by CPUs having split L3 caches, or stricter
memory models that exhibit some barrier issues. It's complicated though
because the info about the model depends on the arch. For example, x86
reports an SKU name while ARM rather reports the CPU core types, families
and versions for each CPU core. There, the SoC will sometimes be reported
in the device tree or DMI info instead. But we don't really care, it's
essentially useful to know if the code is running on an armv8.0 such as
A53, a 8.2 such as A55/A76/Neoverse etc. For MIPS the model appears to
generally be there, and in addition the SoC is often present in the
"system type" field before the first CPU, and the type of machine in the
"machine" field, to replace the missing DMI and DT, so they are also
collected. Note that only the first CPU is checked and reported, that's
expected to be vastly sufficient, since we're just trying to spot known
incompatibilities or issues.

19 months agoMINOR: debug: report in post_mortem if the container techno used is docker
Willy Tarreau [Wed, 22 Nov 2023 10:48:23 +0000 (11:48 +0100)] 
MINOR: debug: report in post_mortem if the container techno used is docker

If we detect we're running inside a container on Linux, let's check if
it seems to be docker. Docker usually creates a /.dockerenv file, which
is easy to check. It's uncertain whether it's always the case, but on the
few tested instances that was true, and we don't really care, what matters
is to place helpful debugging info for developers. When this file is
detected, we report "docker" instead of "yes" in the container techno.

19 months agoMINOR: debug: report in port_mortem whether a container was detected
Willy Tarreau [Wed, 22 Nov 2023 10:37:37 +0000 (11:37 +0100)] 
MINOR: debug: report in port_mortem whether a container was detected

Containers often cause significant trouble depending on how they're
set up, and they're not always trivial for their users to extract info
from. Here we're trying to detect if we're running inside a container
on Linux. There are plenty of approaches and none is perfectly clean
nor reliable, which makes sense since the goal is to remain transparent
enough.

One interesting approach is to rely on the observation that containers
generally do not expose most kernel threads, and that the very firsts
of them are extremely stable across all kernel versions: pid 2 was
called "keventd" in kernel 2.4, became "kthreadd" in kernel 2.6, and
has since not changed. This is true on all architectures tested, even
with highly stripped down kernels such as those found on 15 year-old
OpenWRT images. And this one doesn't appear inside containers. Thus
here we check if we find such a thread via /proc and whether it's
called keventd or kthreadd, to detect a container, and we set the
"cont_techno" variable to "yes" or "no" depending on what is found.

19 months agoMINOR: debug: add OS/hardware info to the post_mortem struct
Willy Tarreau [Wed, 22 Nov 2023 10:32:51 +0000 (11:32 +0100)] 
MINOR: debug: add OS/hardware info to the post_mortem struct

Let's extract some info about the system (board model, vendor etc),
this will indicate some hypervisors, some cloud instances or some
uncommon embedded boards etc. Typically, vmware, qemu and raspberry-pi
are visible here and can help during the troubleshooting session.

19 months agoMINOR: debug: start to create a new struct post_mortem
Willy Tarreau [Wed, 22 Nov 2023 10:28:06 +0000 (11:28 +0100)] 
MINOR: debug: start to create a new struct post_mortem

The goal here is to accumulate precious debugging information in a
struct that is easy to find in memory. It's aligned to 256-byte as
it also helps. We'll progressively add a lot of info about the
startup conditions, the operating system, the hardware and hypervisor
so as to limit the number of round trips between developers and users
during debugging sessions. Also, opening a core file with an hex editor
should often be sufficient to extract most of the info.

In addition, a new "show dev" command will show these information so
that they can be checked at runtime without having to wait for a crash
(e.g. if a limit is bad in a container, better know it early).

For now the struct only contains utsname that's fed at boot time.

19 months agoDEBUG: tinfo: store the pthread ID and the stack pointer in tinfo
Willy Tarreau [Wed, 22 Nov 2023 17:01:25 +0000 (18:01 +0100)] 
DEBUG: tinfo: store the pthread ID and the stack pointer in tinfo

When debugging a core, it's difficult to match a given gdb thread number
against an internal thread. Let's just store the pthread ID and the stack
pointer in each tinfo. This could help in the future by allowing to just
glance over them and pick the right one depending what info is found
first.

19 months agoBUG/MINOR: server: do not leak default-server in defaults sections
Willy Tarreau [Thu, 23 Nov 2023 13:28:14 +0000 (14:28 +0100)] 
BUG/MINOR: server: do not leak default-server in defaults sections

When a default-server directive is used in a defaults section, it's never
freed and the "defaults" proxy gets reset without freeing the fields from
that default-server. Normally there are no allocation there, except for
the config file location stored in srv->conf.file form an strdup() since
commit 9394a9444 ("REORG: server: move alert traces in parse_server")
that appeared in 2.4. In addition, if a "default-server" directive
appears multiple times in a defaults section, one more entry will be
leaked per call.

This commit addresses this by checking that we don't overwrite the file
upon multiple calls, and by clearing it when resetting the default proxy.
This should be backported to 2.4.

19 months agoBUG/MINOR: quic: Possible RX packet memory leak under heavy load
Frédéric Lécaille [Wed, 22 Nov 2023 15:29:08 +0000 (16:29 +0100)] 
BUG/MINOR: quic: Possible RX packet memory leak under heavy load

This bug could be reproduced with -dMfail and h2load generating plenty of connections.
A "show pools" CLI command showed that some memory in relation with RX packet pool
was never release. Furthermore, adding a RX packet counter to each connection
and a BUG_ON() in quic_conn_release() has proved that this unreleased memory
was in relation with RX packet which were not linked to a connection.

The responsible is quic_dgram_parse() which does not release some RX packet
memory before exiting after the connection thread affinity has changed.

Must be backported as far as 2.7.

19 months agoBUG/MINOR: quic: Possible leak of TX packets under heavy load
Frédéric Lécaille [Wed, 22 Nov 2023 13:57:28 +0000 (14:57 +0100)] 
BUG/MINOR: quic: Possible leak of TX packets under heavy load

This bug could be reproduced with -dMfail and detected added a counter of TX packet
to the QUIC connection. When released calling quic_conn_release() the connection
should have a null counter of TX packets. This was not always the case.
This could occur during the handshake step: a first packet was built, then another
one should have followed in the same datagram, but fail due to a memory allocation
issue. As the datagram length and first TX packet were not written in the TX
buffer, this latter could not really be purged by qc_purge_tx_buf() even if
called. This bug occured only when building coalesced packets in the same datagram.

To fix this, write the packet information (datagram length and first packet
address) in the TX buffer before purging it.

Must be backported as far as 2.6.

19 months agoBUG/MEDIUM: quic: Possible crash during retransmissions and heavy load
Frédéric Lécaille [Tue, 21 Nov 2023 19:31:32 +0000 (20:31 +0100)] 
BUG/MEDIUM: quic: Possible crash during retransmissions and heavy load

This bug could be reproduced with -dMfail and dectected by libasan as follows:

$ ASAN_OPTIONS=disable_coredump=0:unmap_shadow_on_exit=1:abort_on_error=f quic-freeze.cfg -dMfail -dMno-cache -dM0x55
=================================================================
==82989==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ffc 0x560790cc4749 bp 0x7fff8e0e8e30 sp 0x7fff8e0e8e28
WRITE of size 8 at 0x7fff8e0ea338 thread T0
    #0 0x560790cc4748 in qc_frm_free src/quic_frame.c:1222
    #1 0x560790cc5260 in qc_release_frm src/quic_frame.c:1261
    #2 0x560790d1de99 in qc_treat_acked_tx_frm src/quic_rx.c:312
    #3 0x560790d1e708 in qc_ackrng_pkts src/quic_rx.c:370
    #4 0x560790d22a1d in qc_parse_ack_frm src/quic_rx.c:694
    #5 0x560790d25daa in qc_parse_pkt_frms src/quic_rx.c:988
    #6 0x560790d2a509 in qc_treat_rx_pkts src/quic_rx.c:1373
    #7 0x560790c72d45 in quic_conn_io_cb src/quic_conn.c:906
    #8 0x560791207847 in run_tasks_from_lists src/task.c:596
    #9 0x5607912095f0 in process_runnable_tasks src/task.c:876
    #10 0x560791135564 in run_poll_loop src/haproxy.c:2966
    #11 0x5607911363af in run_thread_poll_loop src/haproxy.c:3165
    #12 0x56079113938c in main src/haproxy.c:3862
    #13 0x7f92606edd09 in __libc_start_main ../csu/libc-start.c:308
    #14 0x560790bcd529 in _start (/home/flecaille/src/haproxy/haproxy+0x

Address 0x7fff8e0ea338 is located in stack of thread T0 at offset 1032 i
    #0 0x560790d29b52 in qc_treat_rx_pkts src/quic_rx.c:1341

  This frame has 2 object(s):
    [32, 48) 'ar' (line 1380)
    [64, 1088) '_msg' (line 1368) <== Memory access at offset 1032 is inable
HINT: this may be a false positive if your program uses some custom stacnism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope src/quic_frame.c:1222 i
Shadow bytes around the buggy address:
  0x100071c15410: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x100071c15420: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x100071c15430: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x100071c15440: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x100071c15450: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
=>0x100071c15460: f8 f8 f8 f8 f8 f8 f8[f8]f8 f8 f8 f8 f8 f8 f3 f3
  0x100071c15470: f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 00 00
  0x100071c15480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100071c15490: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100071c154a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100071c154b0: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 04 f3 f3 f3
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==82989==ABORTING
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
Aborted (core dumped)

Note that a coredump could not always be produced with all compilers. This was
always the case with clang 11.

When allocating frames to be retransmitted from qc_dgrams_retransmit(), if they
could not be sent for any reason, they could remain attached to a local list to
qc_dgrams_retransmit() and trigger a crash with libasan when releasing the
original frames they were duplicated from.

To fix this, always release the frames which could not be sent during
retransmissions calling qc_free_frm_list() where needed.

Must be backported as far as 2.6.