]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
4 years agoCLEANUP: freq_ctr: make arguments of freq_ctr_total() const
Willy Tarreau [Wed, 28 Apr 2021 15:44:37 +0000 (17:44 +0200)] 
CLEANUP: freq_ctr: make arguments of freq_ctr_total() const

freq_ctr_total() doesn't modify the freq counters, it should take a
const argument.

4 years agoBUG/MEDIUM: time: fix updating of global_now upon clock drift
Willy Tarreau [Wed, 28 Apr 2021 15:31:22 +0000 (17:31 +0200)] 
BUG/MEDIUM: time: fix updating of global_now upon clock drift

During commit 7e4a557f6 ("MINOR: time: change the global timeval and the
the global tick at once") the approach made sure that the new now_ms was
always higher than or equal to global_now_ms, but by forgetting the old
value. This can cause the first update to global_now_ms to fail if it's
already out of sync, going back into the loop, and the subsequent call
would then succeed due to commit 4d01f3dcd ("MINOR: time: avoid
overwriting the same values of global_now").

And if it goes out of sync, it will fail to update forever, as observed
by Ashley Penney in github issue #1194, causing incorrect freq counters
calculations everywhere. One possible trigger for this issue is one thread
spinning for a few milliseconds while the other ones continue to work.

The issue really is that old_now_ms ought not to be modified in the loop
as it's used for the CAS. But we don't need to structurally guarantee that
global_now_ms grows monotonically as it's computed from the new global_now
which is already verified for this via the __tv_islt() test. Thus, dropping
any corrections on global_now_ms in the loop is the correct way to proceed
as long as this one is always updated to follow global_now.

No backport is needed, this is only for 2.4-dev.

4 years agoMINOR: peers: add informative flags about resync process for debugging
Emeric Brun [Wed, 28 Apr 2021 10:59:35 +0000 (12:59 +0200)] 
MINOR: peers: add informative flags about resync process for debugging

This patch adds miscellenous informative flags raised during the initial
full resync process performed during the reload for debugging purpose.

0x00000010: Timeout waiting for a full resync from a local node
0x00000020: Timeout waiting for a full resync from a remote node
0x00000040: Session aborted learning from a local node
0x00000080: Session aborted learning from a remote node
0x00000100: A local node teach us and was fully up to date
0x00000200: A remote node teach us and was fully up to date
0x00000400: A local node teach us but was partially up to date
0x00000800: A remote node teach us but was partially up to date
0x00001000: A local node was assigned for a full resync
0x00002000: A remote node was assigned for a full resync
0x00004000: A resync was explicitly requested

This patch could be backported on any supported branch

4 years agoBUG/MEDIUM: peers: reset tables stage flags stages on new conns
Emeric Brun [Tue, 20 Apr 2021 12:43:46 +0000 (14:43 +0200)] 
BUG/MEDIUM: peers: reset tables stage flags stages on new conns

Flags used as context to know current status of each table pushing a
full resync to a peer were correctly reset receiving a new resync
request or confirmation message but in case of local peer sync during
reload the resync request is implicit and those flags were not
correctly reset in this case.

This could result to a partial initial resync of some tables after reload
if the connection with the old process was broken and retried.

This patch reset those flags at the end of the handshake for all new
connections to be sure to push a entire full resync if needed.

This patch should be backported on all supported branches ( v >= 1.6 )

4 years agoBUG/MEDIUM: peers: re-work updates lookup during the sync on the fly
Emeric Brun [Wed, 28 Apr 2021 09:48:15 +0000 (11:48 +0200)] 
BUG/MEDIUM: peers: re-work updates lookup during the sync on the fly

Only entries between the opposite of the last 'local update' rotating
counter were considered to be pushed. This processing worked in most
cases because updates are continually pushed trying to reach this point
but it remains some cases where updates id are more far away in the past
and appearing in futur and the push of updates is stuck until the head
reach again the tail which could take a very long time.

This patch re-work the lookup to consider that all positions on the
rotating counter is considered in the past until we reach exactly
the 'local update' value. Doing this, the updates push won't be stuck
anymore.

This patch should be backported on all supported branches ( >= 1.6 )

4 years agoBUG/MEDIUM: peers: reset commitupdate value in new conns
Emeric Brun [Tue, 23 Feb 2021 16:08:08 +0000 (17:08 +0100)] 
BUG/MEDIUM: peers: reset commitupdate value in new conns

The commitupdate value of the table is used to check if the update
is still pending for a push for all peers. To be sure to not miss a
push we reset it just after a handshake success.

This patch should be backported on all supported branches ( >= 1.6 )

4 years agoBUG/MEDIUM: peers: reset starting point if peers appears longly disconnected
Emeric Brun [Tue, 23 Feb 2021 15:50:53 +0000 (16:50 +0100)] 
BUG/MEDIUM: peers: reset starting point if peers appears longly disconnected

If two peers are disconnected and during this period they continue to
process a large amount of local updates, after a reconnection they
may take a long time before restarting to push their updates. because
the last pushed update would appear internally in futur.

This patch fix this resetting the cursor on acked updates at the maximum
point considered in the past if it appears in futur but it means we
may lost some updates. A clean fix would be to update the protocol to
be able to signal a remote peer that is was not updated for a too long
period and needs a full resync but this is not yet supported by the
protocol.

This patch should be backported on all supported branches ( >= 1.6 )

4 years agoBUG/MEDIUM: peers: stop considering ack messages teaching a full resync
Emeric Brun [Thu, 4 Mar 2021 09:27:10 +0000 (10:27 +0100)] 
BUG/MEDIUM: peers: stop considering ack messages teaching a full resync

The re-con cursor was updated receiving any ack message
even if we are pushing a complete resync to a peer. This cursor
is reset at the end of the resync but if the connection is broken
during resync, we could re-start at an unwanted point.

With this patch, the peer stops to consider ack messages pushing
a resync since the resync process has is own acknowlegement and
is always restarted from the beginning in case of broken connection.

This patch should be backported on all supported branches ( >= 1.6 )

4 years agoBUG/MEDIUM: peers: register last acked value as origin receiving a resync req
Emeric Brun [Wed, 28 Apr 2021 07:49:33 +0000 (09:49 +0200)] 
BUG/MEDIUM: peers: register last acked value as origin receiving a resync req

Receiving a resync request, the origins to start the full sync and
to reset after the full resync are mistakenly computed based on
the last update on the table instead of computed based on the
the last update acked by the node requesting the resync.

It could result in disordered or missing updates pushing to the
requester

This patch sets correctly those origins.

This patch should be backported on all supported branches ( >= 1.6 )

4 years agoBUG/MEDIUM: peers: initialize resync timer to get an initial full resync
Emeric Brun [Wed, 21 Apr 2021 14:06:35 +0000 (16:06 +0200)] 
BUG/MEDIUM: peers: initialize resync timer to get an initial full resync

If a reload is performed and there is no incoming connections
from the old process to push a full resync, the new process
can be stuck waiting indefinitely for this conn and it never tries a
fallback requesting a full resync from a remote peer because the resync
timer was init to TICK_ETERNITY.

This patch forces a reset of the resync timer to default value (5 secs)
if we detect value is TICK_ETERNITY.

This patch should be backported on all supported branches ( >= 1.6 )

4 years agoMINOR: config: add a new "default-path" global directive
Willy Tarreau [Tue, 27 Apr 2021 18:29:11 +0000 (20:29 +0200)] 
MINOR: config: add a new "default-path" global directive

By default haproxy loads all files designated by a relative path from the
location the process is started in. In some circumstances it might be
desirable to force all relative paths to start from a different location
just as if the process was started from such locations. This is what this
directive is made for. Technically it will perform a temporary chdir() to
the designated location while processing each configuration file, and will
return to the original directory after processing each file. It takes an
argument indicating the policy to use when loading files whose path does
not start with a slash ('/').

A few options are offered, "current" (the default), "config" (files
relative to config file's dir), "parent" (files relative to config file's
parent dir), and "origin" with an absolute path.

This should address issue #1198.

4 years agoCLEANUP: cfgparse: de-uglify early file error handling in readcfgfile()
Willy Tarreau [Tue, 27 Apr 2021 16:30:28 +0000 (18:30 +0200)] 
CLEANUP: cfgparse: de-uglify early file error handling in readcfgfile()

In readcfgfile() when malloc() fails to allocate a buffer for the
config line, it currently says "parsing[<file>]: out of memory" while
the error is unrelated to the config file and may make one think it has
to do with the file's size. The second test (fopen() returning error)
needs to release the previously allocated line. Both directly return -1
which is not even documented as a valid error code for the function.

Let's simply make sure that the few variables freed at the end are
properly preset, and jump there upon error, after having displayed a
meaningful error message. Now at least we can get this:

  $ ./haproxy -f /dev/kmem
  [NOTICE] 116/191904 (23233) : haproxy version is 2.4-dev17-c3808c-13
  [NOTICE] 116/191904 (23233) : path to executable is ./haproxy
  [ALERT] 116/191904 (23233) : Could not open configuration file /dev/kmem : Permission denied

4 years agoDOC: general: fix example in set-timeout
Alex [Tue, 27 Apr 2021 10:57:07 +0000 (12:57 +0200)] 
DOC: general: fix example in set-timeout

The alternative arguments are always in curly brackets, let's fix it for
set-timeout.
The Example in set-timeout does not have the one of the required argument.

This commit makes the PR https://github.com/cbonte/haproxy-dconv/pull/34
obsolete.

4 years agoCLEANUP: channel: No longer notify the producer in co_skip()/co_htx_skip()
Christopher Faulet [Tue, 27 Apr 2021 21:06:20 +0000 (23:06 +0200)] 
CLEANUP: channel: No longer notify the producer in co_skip()/co_htx_skip()

Thanks to the commit "BUG/MINOR: applet: Notify the other side if data were
consumed by an applet", it is no longer necessary to notify the producer when an
applet skips output data. Now, it is the default applet handler responsibility
to take care of that.

4 years agoBUG/MEDIUM: mux-h2: Handle EOM flag when sending a DATA frame with zero-copy
Christopher Faulet [Tue, 27 Apr 2021 20:51:07 +0000 (22:51 +0200)] 
BUG/MEDIUM: mux-h2: Handle EOM flag when sending a DATA frame with zero-copy

When a DATA frame is sent, we must take care to properly detect the EOM flag
on the HTX message to set ES flag on the frame when necessary, to finish the
stream. But it is only done when data are copied from the HTX message to the
mux buffer and not when the frame are sent via a zero-copy. This patch fixes
this bug.

It is a 2.4-specific bug. No backport is needed.

4 years agoBUG/MINOR: hlua: Don't consume headers when starting an HTTP lua service
Christopher Faulet [Wed, 28 Apr 2021 08:50:21 +0000 (10:50 +0200)] 
BUG/MINOR: hlua: Don't consume headers when starting an HTTP lua service

When an HTTP lua service is started, headers are consumed before calling the
script. When it was initialized, the headers were stored in a lua array,
thus they can be removed from the HTX message because the lua service will
no longer access them. But it is a problem with bodyless messages because
the EOM flag is lost. Indeed, once the headers are consumed, the message is
empty and the buffer is reset, included the flags.

Now, the headers are not immediately consumed. We will skip them if
applet:receive() or applet:getline(). This way, the EOM flag is preserved.
At the end, when the script is finished, all output data are consumed, thus
this remains safe.

It is a 2.4-specific bug. No backport is needed.

4 years agoBUG/MINOR: applet: Notify the other side if data were consumed by an applet
Christopher Faulet [Tue, 27 Apr 2021 15:08:10 +0000 (17:08 +0200)] 
BUG/MINOR: applet: Notify the other side if data were consumed by an applet

If an applet consumed output data (the amount of output data has changed
between before and after the call to the applet), the producer is
notified. It means CF_WRITE_PARTIAL and CF_WROTE_DATA are set on the output
channel and the opposite stream interface is notified some room was made in
its input buffer. This way, it is no longer the applet responsibility to
take care of it. However, it doesn't matter if the applet does the same.

Said like that, it looks like an improvement not a bug. But it really fixes
a bug in the lua, for HTTP applets. Indeed, applet:receive() and
applet:getline() are buggy for HTTP applets. Data are consumed but the
producer is not notified. It means if the payload is not fully received in
one time, the applet may be blocked because the producer remains blocked (it
is time dependent).

This patch must be backported as far as 2.0 (only for the HTX part).

4 years agoMINOR: htx: Limit length of headers name/value when a HTX message is dumped
Christopher Faulet [Tue, 27 Apr 2021 09:29:00 +0000 (11:29 +0200)] 
MINOR: htx: Limit length of headers name/value when a HTX message is dumped

In htx_dump() function, we now limit the length of the headers name and the
value to not fully print huge headers.

4 years agoMEDIUM: http-ana: handle read error on server side if waiting for response
Christopher Faulet [Tue, 27 Apr 2021 08:56:28 +0000 (10:56 +0200)] 
MEDIUM: http-ana: handle read error on server side if waiting for response

A read error on the server side is also reported as a write error on the
client side. It means some times, a server side error is handled on the
client side. Among others, it is the case when the client side is waiting
for the response while the request processing is already finished. In this
case, the error is not handled as a server error. It is not accurate.

So now, when the request processing is finished but not the response
processing and if a read error was encountered on the server side, the error
is not immediatly processed on the client side, to let a chance to response
analysers to properly catch the error.

4 years agoBUG/MINOR: mux-h2: Don't encroach on the reserve when decoding headers
Christopher Faulet [Mon, 26 Apr 2021 15:46:13 +0000 (17:46 +0200)] 
BUG/MINOR: mux-h2: Don't encroach on the reserve when decoding headers

Since the input buffer is transferred to the stream when it is created,
there is no longer control on the request size to be sure the buffer's
reserve is still respected. It was automatically performed in h2_rcv_buf()
because the caller took care to provide the correct available space in the
buffer. The control is still there but it is no longer applied on the
request headers. Now, we should take care of the reserve when the headers
are decoded, before the stream creation.

The test is performed for the request and the response.

It is a 2.4-specific bug. No backport is needed.

4 years agoCLEANUP: htx: Remove unsued hdrs_bytes field from the HTX start-line
Christopher Faulet [Thu, 22 Apr 2021 07:50:14 +0000 (09:50 +0200)] 
CLEANUP: htx: Remove unsued hdrs_bytes field from the HTX start-line

Thanks to the htx_xfer_blks() refactoring, it is now possible to remove
hdrs_bytes field from the start-line because no function rely on it anymore.

4 years agoMEDIUM: htx: Refactor htx_xfer_blks() to not rely on hdrs_bytes field
Christopher Faulet [Thu, 22 Apr 2021 07:45:18 +0000 (09:45 +0200)] 
MEDIUM: htx: Refactor htx_xfer_blks() to not rely on hdrs_bytes field

It is the only function using the hdrs_bytes start-line field. Thus the
function has been refactored to no longer rely on it. To do so, we first
copy HTX blocks to the destination message, without removing them from the
source message. If the copy is interrupted on headers or trailers, we roll
back. Otherwise, data are drained from the source buffer.

Most of time, the copy will succeeds. So the roll back is only performed in
the worst but very rare case.

4 years agoBUG/MINOR: htx: Preserve HTX flags when draining data from an HTX message
Christopher Faulet [Thu, 22 Apr 2021 07:43:47 +0000 (09:43 +0200)] 
BUG/MINOR: htx: Preserve HTX flags when draining data from an HTX message

When all data of an HTX message are drained, we rely on htx_reset() to
reinit the message state. However, the flags must be preserved. It is, among
other things, important to preserve processing or parsing errors.

This patch must be backported as far as 2.0.

4 years agoBUG/MEDIUM: cpuset: fix build on MacOS
Amaury Denoyelle [Tue, 27 Apr 2021 14:45:29 +0000 (16:45 +0200)] 
BUG/MEDIUM: cpuset: fix build on MacOS

The compilation fails due to the following commit:
fc6ac53dca8391ba9c32bc716fb61267b475ba71
BUG/MAJOR: fix build on musl with cpu_set_t support

The new global variable cpu_map conflicted with a local variable of the
same name in the code path for the apple platform when setting the
process affinity.

This does not need to be backported.

4 years agoBUG/MAJOR: fix build on musl with cpu_set_t support
Amaury Denoyelle [Tue, 27 Apr 2021 08:46:36 +0000 (10:46 +0200)] 
BUG/MAJOR: fix build on musl with cpu_set_t support

Move cpu_map structure outside of the global struct to a global
variable defined in cpuset.c compilation unit. This allows to reorganize
the includes without having to define _GNU_SOURCE everywhere for the
support of the cpu_set_t.

This fixes the compilation with musl libc, most notably used for the
alpine based docker image.

This fixes the github issue #1235.

No need to backport as this feature is new in the current
2.4-dev.

4 years agoBUG/MINOR: cpuset: move include guard at the very beginning
Amaury Denoyelle [Tue, 27 Apr 2021 08:39:39 +0000 (10:39 +0200)] 
BUG/MINOR: cpuset: move include guard at the very beginning

The include guard in cpuset-t.h were misplaced and should be the first
directive of the file.

No need to backport.

4 years agoBUG/MINOR: ssl: ssl_sock_prepare_ssl_ctx does not return an error code
Remi Tricot-Le Breton [Wed, 21 Apr 2021 13:32:46 +0000 (15:32 +0200)] 
BUG/MINOR: ssl: ssl_sock_prepare_ssl_ctx does not return an error code

The return value check was wrongly based on error codes when the
function actually returns an error number.
This bug was introduced by f3eedfe19592ebcbaa5b97d8c68aa162e7f6f8fa
which is a feature not present before branch 2.4.

It does not need to be backported.

4 years agoDOC: general: fix white spaces for HTML converter
Alex [Sat, 24 Apr 2021 11:02:21 +0000 (13:02 +0200)] 
DOC: general: fix white spaces for HTML converter

The HTML converter expects some formats to recognize if a keyword is a
keyword.

4 years agoCLEANUP: assorted typo fixes in the code and comments
Ilya Shipitsin [Sat, 24 Apr 2021 08:25:42 +0000 (13:25 +0500)] 
CLEANUP: assorted typo fixes in the code and comments

This is 22nd iteration of typo fixes

4 years agoREORG: htx: Inline htx functions to add HTX blocks in a message
Christopher Faulet [Mon, 26 Apr 2021 08:18:16 +0000 (10:18 +0200)] 
REORG: htx: Inline htx functions to add HTX blocks in a message

The HTX functions used to add new HTX blocks in a message have been moved to
the header file to inline them in calling functions. These functions are
small enough.

4 years agoBUG/MINOR: mux-fcgi: Don't send normalized uri to FCGI application
Christopher Faulet [Mon, 26 Apr 2021 07:38:55 +0000 (09:38 +0200)] 
BUG/MINOR: mux-fcgi: Don't send normalized uri to FCGI application

A normalized URI is the internal term used to specify an URI is stored using
the absolute format (scheme + authority + path). For now, it is only used
for H2 clients. It is the default and recommended format for H2 request.
However, it is unusual for H1 servers to receive such URI. So in this case,
we only send the path of the absolute URI. It is performed for H1 servers,
but not for FCGI applications. This patch fixes the difference.

Note that it is not a real bug, because FCGI applications should support
abosolute URI.

Note also a normalized URI is only detected for H2 clients when a request is
received. There is no such test on the H1 side. It means an absolute URI
received from an H1 client will be sent without modification to an H1 server
or a FCGI application.

To make it possible, a dedicated function has been added to get the H1
URI. This function is called by the H1 and the FCGI multiplexer when a
request is sent to a server.

This patch should fix the issue #1232. It must be backported as far as 2.2.

4 years agoMINOR: uri_normalizer: Add a `percent-decode-unreserved` normalizer
Tim Duesterhus [Wed, 21 Apr 2021 19:20:36 +0000 (21:20 +0200)] 
MINOR: uri_normalizer: Add a `percent-decode-unreserved` normalizer

This normalizer decodes percent encoded characters within the RFC 3986
unreserved set.

See GitHub Issue #714.

4 years agoDOC: Add RFC references for the path-strip-dot(dot)? normalizers
Tim Duesterhus [Wed, 21 Apr 2021 19:20:35 +0000 (21:20 +0200)] 
DOC: Add RFC references for the path-strip-dot(dot)? normalizers

This is RFC 3986#6.2.2.3.

4 years agoDOC: Fix RFC reference for the percent-to-uppercase normalizer
Tim Duesterhus [Wed, 21 Apr 2021 19:20:34 +0000 (21:20 +0200)] 
DOC: Fix RFC reference for the percent-to-uppercase normalizer

The section is 6.2.2.1, not 6.2.21 (missing dot).

4 years agoDOC: Fix indentation for `path-strip-dot` normalizer
Tim Duesterhus [Wed, 21 Apr 2021 19:20:33 +0000 (21:20 +0200)] 
DOC: Fix indentation for `path-strip-dot` normalizer

The long explanation should be indented two additional spaces.

4 years ago[RELEASE] Released version 2.4-dev17 v2.4-dev17
Willy Tarreau [Fri, 23 Apr 2021 17:11:10 +0000 (19:11 +0200)] 
[RELEASE] Released version 2.4-dev17

Released version 2.4-dev17 with the following main changes :
    - MINOIR: mux-pt/trace: Register a new trace source with its events
    - BUG/MINOR: mux-pt: Fix a possible UAF because of traces in mux_pt_io_cb
    - CI: travis: Drastically clean up .travis.yml
    - CLEANUP: pattern: make all pattern tables read-only
    - MINOR: trace: replace the trace() inline function with an equivalent macro
    - MINOR: initcall: uniformize the section names between MacOS and other unixes
    - CLEANUP: initcall: rename HA_SECTION to HA_INIT_SECTION
    - MINOR: compiler: add macros to declare section names
    - CLEANUP: initcall: rely on HA_SECTION_* instead of defining its own
    - MINOR: global: declare a read_mostly section
    - MINOR: fd: move a few read-mostly variables to their own section
    - MINOR: epoll: move epoll_fd to read_mostly
    - MINOR: kqueue: move kqueue_fd to read_mostly
    - MINOR: pool: move pool declarations to read_mostly
    - MINOR: threads: mark all_threads_mask as read_mostly
    - MINOR: server: move idle_conn_task to read_mostly
    - MINOR: protocol: move __protocol_by_family to read_mostly
    - MINOR: pattern: make the pat_lru_seed read_mostly
    - MINOR: trace: make trace sources read_mostly
    - MINOR: freq_ctr: add a generic function to report the total value
    - MEDIUM: freq_ctr: make read_freq_ctr_period() use freq_ctr_total()
    - MEDIUM: freq_ctr: reimplement freq_ctr_remain_period() from freq_ctr_total()
    - MINOR: freq_ctr: add the missing next_event_delay_period()
    - MINOR: freq_ctr: unify freq_ctr and freq_ctr_period into freq_ctr
    - MEDIUM: freq_ctr: replace the per-second counters with the generic ones
    - MINOR: freq_ctr: add cpu_relax in the rotation loop of update_freq_ctr_period()
    - MINOR: freq_ctr: simplify and improve the update function
    - CLEANUP: time: remove the now unused ms_left_scaled
    - MINOR: time: move the time initialization out of tv_update_date()
    - MINOR: time: remove useless variable copies in tv_update_date()
    - MINOR: time: change the global timeval and the the global tick at once
    - MEDIUM: time: make the clock offset global and no per-thread
    - MINOR: atomic: reimplement the relaxed version of x86 BTS/BTR
    - MINOR: trace: Add the checks as a possible trace source
    - MINOIR: checks/trace: Register a new trace source with its events
    - MINOR: hlua: Add function to release a lua function
    - BUG/MINOR: hlua: Fix memory leaks on error path when registering a task
    - BUG/MINOR: hlua: Fix memory leaks on error path when registering a converter
    - BUG/MINOR: hlua: Fix memory leaks on error path when registering a fetch
    - BUG/MINOR: hlua: Fix memory leaks on error path when parsing a lua action
    - BUG/MINOR: hlua: Fix memory leaks on error path when registering an action
    - BUG/MINOR: hlua: Fix memory leaks on error path when registering a service
    - BUG/MINOR: hlua: Fix memory leaks on error path when registering a cli keyword
    - BUG/MINOR: cfgparse/proxy: Fix some leaks during proxy section parsing
    - BUG/MINOR: listener: Handle allocation error when allocating a new bind_conf
    - BUG/MINOR: cfgparse/proxy: Hande allocation errors during proxy section parsing
    - MINOR: cfgparse/proxy: Group alloc error handling during proxy section parsing
    - DOC: internals: update the SSL architecture schema
    - BUG/MEDIUM: sample: Fix adjusting size in field converter
    - MINOR: sample: add ub64dec and ub64enc converters
    - CLEANUP: sample: align samples list in sample.c
    - MINOR: ist: Add `istclear(struct ist*)`
    - CI: cirrus: install "pcre" package
    - MINOR: opentracing: correct calculation of the number of arguments in the args[]
    - MINOR: opentracing: transfer of context names without prefix
    - MINOR: sample: converter: Add mjson library.
    - MINOR: sample: converter: Add json_query converter
    - CI: travis-ci: enable weekly graviton2 builds
    - DOC: ssl: Certificate hot update only works on fronted certificates
    - DOC: ssl: Certificate hot update works on server certificates
    - BUG/MEDIUM: threads: Ignore current thread to end its harmless period
    - MINOR: threads: Only consider running threads to end a thread harmeless period
    - BUG/MINOR: checks: Set missing id to the dummy checks frontend
    - MINOR: logs: Add support of checks as session origin to format lf strings
    - BUG/MINOR: connection: Fix fc_http_major and bc_http_major for TCP connections
    - MINOR: connection: Make bc_http_major compatible with tcp-checks
    - BUG/MINOR: ssl-samples: Fix ssl_bc_* samples when called from a health-check
    - BUG/MINOR: http-fetch: Make method smp safe if headers were already forwarded
    - MINOR: tcp_samples: Add samples to get src/dst info of the backend connection
    - MINOR: tcp_samples: Be able to call bc_src/bc_dst from the health-checks
    - BUG/MINOR: http_htx: Remove BUG_ON() from http_get_stline() function
    - BUG/MINOR: logs: Report the true number of retries if there was no connection
    - BUILD: makefile: Redirect stderr to /dev/null when probing options
    - MINOR: uri_normalizer: Add uri_normalizer module
    - MINOR: uri_normalizer: Add `enum uri_normalizer_err`
    - MINOR: uri_normalizer: Add `http-request normalize-uri`
    - MINOR: uri_normalizer: Add a `merge-slashes` normalizer to http-request normalize-uri
    - MINOR: uri_normalizer: Add a `dotdot` normalizer to http-request normalize-uri
    - MINOR: uri_normalizer: Add support for supressing leading `../` for dotdot normalizer
    - MINOR: uri_normalizer: Add a `sort-query` normalizer
    - MINOR: uri_normalizer: Add a `percent-upper` normalizer
    - MEDIUM: http_act: Rename uri-normalizers
    - DOC: Add introduction to http-request normalize-uri
    - DOC: Note that URI normalization is experimental
    - BUG/MINOR: pools: maintain consistent ->allocated count on alloc failures
    - BUG/MINOR: pools/buffers: make sure to always reserve the required buffers
    - MINOR: pools: drop the unused static history of artificially failed allocs
    - CLEANUP: pools: remove unused arguments to pool_evict_from_cache()
    - MEDIUM: pools: move the cache into the pool header
    - MINOR: pool: remove the size field from pool_cache_head
    - MINOR: pools: rename CONFIG_HAP_LOCAL_POOLS to CONFIG_HAP_POOLS
    - MINOR: pools: enable the fault injector in all allocation modes
    - MINOR: pools: make the basic pool_refill_alloc()/pool_free() update needed_avg
    - MEDIUM: pools: unify pool_refill_alloc() across all models
    - CLEANUP: pools: re-merge pool_refill_alloc() and __pool_refill_alloc()
    - MINOR: pools: call pool_alloc_nocache() out of the pool's lock
    - CLEANUP: pools: move the lock to the only __pool_get_first() that needs it
    - CLEANUP: pools: rename __pool_get_first() to pool_get_from_shared_cache()
    - CLEANUP: pools: rename pool_*_{from,to}_cache() to *_local_cache()
    - CLEANUP: pools: rename __pool_free() to pool_put_to_shared_cache()
    - MINOR: tools: add statistical_prng_range() to get a random number over a range
    - MINOR: pools: use cheaper randoms for fault injections
    - MINOR: pools: move the fault injector to __pool_alloc()
    - MINOR: pools: split the OS-based allocator in two
    - MINOR: pools: always use atomic ops to maintain counters
    - MINOR: pools: move pool_free_area() out of the lock in the locked version
    - MINOR: pools: factor the release code into pool_put_to_os()
    - MEDIUM: pools: make CONFIG_HAP_POOLS control both local and shared pools
    - MINOR: pools: create unified pool_{get_from,put_to}_cache()
    - MINOR: pools: evict excess objects using pool_evict_from_local_cache()
    - MEDIUM: pools: make pool_put_to_cache() always call pool_put_to_local_cache()
    - CLEANUP: pools: make the local cache allocator fall back to the shared cache
    - CLEANUP: pools: merge pool_{get_from,put_to}_local_caches with generic ones
    - CLEANUP: pools: uninline pool_put_to_cache()
    - CLEANUP: pools: declare dummy pool functions to remove some ifdefs
    - BUILD: pools: fix build with DEBUG_FAIL_ALLOC
    - BUG/MINOR: server: make srv_alloc_lb() allocate lb_nodes for consistent hash
    - CONTRIB: mod_defender: import the minimal number of includes
    - CONTRIB: mod_defender: make the code build with the embedded includes
    - CONTRIB: modsecurity: import the minimal number of includes
    - CONTRIB: modsecurity: make the code build with the embedded includes
    - CLEANUP: sample: Improve local variables in sample_conv_json_query
    - CLEANUP: sample: Explicitly handle all possible enum values from mjson
    - CLEANUP: sample: Use explicit return for successful `json_query`s
    - CLEANUP: lists/tree-wide: rename some list operations to avoid some confusion
    - CONTRIB: move spoa_example out of the tree
    - BUG/MINOR: server: free srv.lb_nodes in free_server
    - BUG/MINOR: logs: free logsrv.conf.file on exit
    - BUG/MEDIUM: server: ensure thread-safety of server runtime creation
    - MINOR: server: add log on dynamic server creation
    - MINOR: server: implement delete server cli command
    - CONTRIB: move spoa_server out of the tree
    - CONTRIB: move modsecurity out of the tree
    - BUG/MINOR: server: fix potential null gcc error in delete server
    - BUG/MAJOR: mux-h2: Properly detect too large frames when decoding headers
    - BUG/MEDIUM: mux-h2: Fix dfl calculation when merging CONTINUATION frames
    - BUG/MINOR: uri_normalizer: Use delim parameter when building the sorted query in uri_normalizer_query_sort
    - CLEANUP: uri_normalizer: Remove trailing whitespace
    - MINOR: uri_normalizer: Add a `strip-dot` normalizer
    - CONTRIB: move mod_defender out of the tree
    - CLEANUP: contrib: remove the last references to the now dead contrib/ directory
    - BUG/MEDIUM: config: fix cpu-map notation with both process and threads
    - MINOR: config: add a diag for invalid cpu-map statement
    - BUG/MINOR: mworker/init: don't reset nb_oldpids in non-mworker cases
    - BUG/MINOR: mworker: don't use oldpids[] anymore for reload
    - BUILD: makefile: fix the "make clean" target on strict bourne shells
    - IMPORT: slz: import slz into the tree
    - BUILD: compression: switch SLZ from out-of-tree to in-tree
    - CI: github: do not build libslz any more
    - CLEANUP: compression: remove calls to SLZ init functions
    - BUG/MEDIUM: mux-h2: Properly handle shutdowns when received with data
    - MINOR: cpuset: define a platform-independent cpuset type
    - MINOR: cfgparse: use hap_cpuset for parse_cpu_set
    - MEDIUM: config: use platform independent type hap_cpuset for cpu-map
    - MINOR: thread: implement the detection of forced cpu affinity
    - MINOR: cfgparse: support the comma separator on parse_cpu_set
    - MEDIUM: cfgparse: detect numa and set affinity if needed
    - MINOR: global: add option to disable numa detection
    - BUG/MINOR: haproxy: fix compilation on macOS
    - BUG/MINOR: cpuset: fix compilation on platform without cpu affinity
    - MINOR: time: avoid unneeded updates to now_offset
    - MINOR: time: avoid overwriting the same values of global_now
    - CLEANUP: time: use __tv_to_ms() in tv_update_date() instead of open-coding
    - MINOR: time: avoid u64 needlessly expensive computations for the 32-bit now_ms
    - BUG/MINOR: peers: remove useless table check if initial resync is finished
    - BUG/MEDIUM: peers: re-work connection to new process during reload.
    - BUG/MEDIUM: peers: re-work refcnt on table to protect against flush
    - BUG/MEDIUM: config: fix missing initialization in numa_detect_topology()

4 years agoBUG/MEDIUM: config: fix missing initialization in numa_detect_topology()
Willy Tarreau [Fri, 23 Apr 2021 17:09:16 +0000 (19:09 +0200)] 
BUG/MEDIUM: config: fix missing initialization in numa_detect_topology()

The error path of the NUMA topology detection introduced in commit
b56a7c89a ("MEDIUM: cfgparse: detect numa and set affinity if needed")
lacks an initialization resulting in possible crashes at boot. No
backport is needed since that was introduced in 2.4-dev.

4 years agoBUG/MEDIUM: peers: re-work refcnt on table to protect against flush
Emeric Brun [Fri, 23 Apr 2021 10:21:26 +0000 (12:21 +0200)] 
BUG/MEDIUM: peers: re-work refcnt on table to protect against flush

In proxy.c, when process is stopping we try to flush tables content
using 'stktable_trash_oldest'. A check on a counter "table->syncing" was
made to verify if there is no pending resync in progress.
But using multiple threads this counter can be increased by an other thread
only after some delay, so the content of some tables can be trashed earlier and
won't be pushed to the new process (after reload, some tables appear reset and
others don't).

This patch re-names the counter "table->syncing" to "table->refcnt" and
the counter is increased during configuration parsing (registering a table to
a peer section) to protect tables during runtime and until resync of a new
process has succeeded or failed.

The inc/dec operations are now made using atomic operations
because multiple peer sections could refer to the same table in futur.

This fix addresses github #1216.

This patch should be backported on all branches multi-thread support (v >= 1.8)

4 years agoBUG/MEDIUM: peers: re-work connection to new process during reload.
Emeric Brun [Thu, 22 Apr 2021 16:20:37 +0000 (18:20 +0200)] 
BUG/MEDIUM: peers: re-work connection to new process during reload.

The peers task handling the "stopping" could wake up multiple
times in stopping state with WOKEN_SIGNAL: the connection to the
local peer initiated on the first processing was immediatly
shutdown by the next processing of the task and the old process
exits considering it is unable to connect. It results on
empty stick-tables after a reload.

This patch checks the flag 'PEERS_F_DONOTSTOP' to know if the
signal is considered and if remote peers connections shutdown
is already done or if a connection to the local peer must be
established.

This patch should be backported on all supported branches (v >= 1.6)

4 years agoBUG/MINOR: peers: remove useless table check if initial resync is finished
Emeric Brun [Thu, 22 Apr 2021 16:13:13 +0000 (18:13 +0200)] 
BUG/MINOR: peers: remove useless table check if initial resync is finished

The old process checked each table resync status even if
the resync process is finished. This behavior had no known impact
except useless processing and was discovered during debugging on
an other issue.

This patch could be backported in all supported branches (v >= 1.6)
but once again, it has no impact except avoid useless processing.

4 years agoMINOR: time: avoid u64 needlessly expensive computations for the 32-bit now_ms
Willy Tarreau [Fri, 23 Apr 2021 14:04:18 +0000 (16:04 +0200)] 
MINOR: time: avoid u64 needlessly expensive computations for the 32-bit now_ms

The compiler cannot guess that tv_sec or tv_usec might have unused
parts, so the multiply by 1000 and the divide by 1000 are both
performed using 64-bit constants to stick to the common type. This is
not needed since we only keep the final 32 bits, let's help the compiler
here by casting these fields to uint. The tv_update_date() code is much
cleaner (48 bytes smaller in the CAS loop) as it avoids some register
spilling at a location where that's really unwanted.

4 years agoCLEANUP: time: use __tv_to_ms() in tv_update_date() instead of open-coding
Willy Tarreau [Fri, 23 Apr 2021 14:03:21 +0000 (16:03 +0200)] 
CLEANUP: time: use __tv_to_ms() in tv_update_date() instead of open-coding

Instead of calculating the current date in milliseconds by hand, let's
use __tv_to_ms() which was made exactly for this purpose.

4 years agoMINOR: time: avoid overwriting the same values of global_now
Willy Tarreau [Fri, 23 Apr 2021 13:36:47 +0000 (15:36 +0200)] 
MINOR: time: avoid overwriting the same values of global_now

In tv_update_date(), we calculate the new global date based on the local
one. It's very likely that other threads will end up with the exact same
now_ms date (at 1 million wakeups/s it happens 99.9% of the time), and
even the microsecond was measured to remain unchanged ~70% of the time
with 16 threads, simply because sometimes another thread already updated
a more recent version of it.

In such cases, performing a CAS to the global variable requires a cache
line flush which brings nothing. By checking if they're changed before
writing, we can divide by about 6 the number of writes to the global
variables, hence the overall contention.

In addition, it's worth noting that all threads will want to update at
the same time, so let's place a cpu relax call before trying again, this
will spread attempts apart.

4 years agoMINOR: time: avoid unneeded updates to now_offset
Willy Tarreau [Fri, 23 Apr 2021 13:17:27 +0000 (15:17 +0200)] 
MINOR: time: avoid unneeded updates to now_offset

The time adjustment is very rare, even at high pool rates. Tests show
that only 0.2% of tv_update_date() calls require a change of offset. Such
concurrent writes to a shared variable have an important impact on future
loads, so let's only update the variable if it changed.

4 years agoBUG/MINOR: cpuset: fix compilation on platform without cpu affinity
Amaury Denoyelle [Fri, 23 Apr 2021 14:58:08 +0000 (16:58 +0200)] 
BUG/MINOR: cpuset: fix compilation on platform without cpu affinity

The compilation is currently broken on platform without USE_CPU_AFFINITY
set. An error has been reported by the cygwin build of the CI.

This does not need to be backported.

In file included from include/haproxy/global-t.h:27,
                 from include/haproxy/global.h:26,
                 from include/haproxy/fd.h:33,
                 from src/ev_poll.c:22:
include/haproxy/cpuset-t.h:32:3: error: #error "No cpuset support implemented on this platform"
   32 | # error "No cpuset support implemented on this platform"
      |   ^~~~~
include/haproxy/cpuset-t.h:37:2: error: unknown type name â€˜CPUSET_REPR’
   37 |  CPUSET_REPR cpuset;
      |  ^~~~~~~~~~~
make: *** [Makefile:944: src/ev_poll.o] Error 1
make: *** Waiting for unfinished jobs....
In file included from include/haproxy/global-t.h:27,
                 from include/haproxy/global.h:26,
                 from include/haproxy/fd.h:33,
                 from include/haproxy/connection.h:30,
                 from include/haproxy/ssl_sock.h:27,
                 from src/ssl_sample.c:30:
include/haproxy/cpuset-t.h:32:3: error: #error "No cpuset support implemented on this platform"
   32 | # error "No cpuset support implemented on this platform"
      |   ^~~~~
include/haproxy/cpuset-t.h:37:2: error: unknown type name â€˜CPUSET_REPR’
   37 |  CPUSET_REPR cpuset;
      |  ^~~~~~~~~~~
make: *** [Makefile:944: src/ssl_sample.o] Error 1

4 years agoBUG/MINOR: haproxy: fix compilation on macOS
Amaury Denoyelle [Fri, 23 Apr 2021 14:41:22 +0000 (16:41 +0200)] 
BUG/MINOR: haproxy: fix compilation on macOS

Fix the warning treated as error on the CI for the macOS compilation :
"src/haproxy.c:2939:23: error: unused variable 'set'
 [-Werror,-Wunused-variable]"

This does not need to be backported.

4 years agoMINOR: global: add option to disable numa detection
Amaury Denoyelle [Fri, 26 Mar 2021 17:50:33 +0000 (18:50 +0100)] 
MINOR: global: add option to disable numa detection

Render numa detection optional with a global configuration statement
'no numa-cpu-mapping'. This can be used if the applied affinity of the
algorithm is not optimal. Also complete the documentation with this new
keyword.

4 years agoMEDIUM: cfgparse: detect numa and set affinity if needed
Amaury Denoyelle [Fri, 26 Mar 2021 17:20:47 +0000 (18:20 +0100)] 
MEDIUM: cfgparse: detect numa and set affinity if needed

On process startup, the CPU topology of the machine is inspected. If a
multi-socket CPU machine is detected, automatically define the process
affinity on the first node with active cpus. This is done to prevent an
impact on the overall performance of the process in case the topology of
the machine is unknown to the user.

This step is not executed in the following condition :
- a non-null nbthread statement is present
- a restrictive 'cpu-map' statement is present
- the process affinity is already restricted, for example via a taskset
  call

For the record, benchmarks were executed on a machine with 2 CPUs
Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz. In both clear and ssl
scenario, the performance were sub-optimal without the automatic
rebinding on a single node.

4 years agoMINOR: cfgparse: support the comma separator on parse_cpu_set
Amaury Denoyelle [Tue, 6 Apr 2021 14:46:15 +0000 (16:46 +0200)] 
MINOR: cfgparse: support the comma separator on parse_cpu_set

Allow to specify multiple cpu ids/ranges in parse_cpu_set separated by a
comma. This is optional and must be activated by a parameter.

The comma support is disabled for the parsing of the 'cpu-map' config
statement. However, it will be useful to parse files in sysfs when
inspecting the cpus topology for NUMA automatic process binding.

4 years agoMINOR: thread: implement the detection of forced cpu affinity
Amaury Denoyelle [Wed, 31 Mar 2021 14:57:39 +0000 (16:57 +0200)] 
MINOR: thread: implement the detection of forced cpu affinity

Create a function thread_cpu_mask_forced. Its purpose is to report if a
restrictive cpu mask is active for the current proces, for example due
to a taskset invocation. It is only implemented for the linux platform
currently.

4 years agoMEDIUM: config: use platform independent type hap_cpuset for cpu-map
Amaury Denoyelle [Wed, 21 Apr 2021 16:39:58 +0000 (18:39 +0200)] 
MEDIUM: config: use platform independent type hap_cpuset for cpu-map

Use the platform independent type hap_cpuset for the cpu-map statement
parsing. This allow to address CPU index greater than LONGBITS.

Update the documentation to reflect the removal of this limit except for
platforms without cpu_set_t type or equivalent.

4 years agoMINOR: cfgparse: use hap_cpuset for parse_cpu_set
Amaury Denoyelle [Wed, 14 Apr 2021 14:16:03 +0000 (16:16 +0200)] 
MINOR: cfgparse: use hap_cpuset for parse_cpu_set

Replace the unsigned long parameter by a hap_cpuset. This allows to
address CPU with index greater than LONGBITS.

This function is used to parse the 'cpu-map' statement. However at the
moment, the result is casted back to a long to store it in the global
structure. The next step is to replace ulong in in cpu_map in the
global structure with hap_cpuset.

4 years agoMINOR: cpuset: define a platform-independent cpuset type
Amaury Denoyelle [Wed, 14 Apr 2021 13:03:51 +0000 (15:03 +0200)] 
MINOR: cpuset: define a platform-independent cpuset type

This module can be used to manipulate a cpu sets in a platform agnostic
way. Use the type cpu_set_t/cpuset_t if available on the platform, or
fallback to unsigned long, which limits de facto the maximum cpu index
to LONGBITS.

4 years agoBUG/MEDIUM: mux-h2: Properly handle shutdowns when received with data
Christopher Faulet [Fri, 23 Apr 2021 10:25:18 +0000 (12:25 +0200)] 
BUG/MEDIUM: mux-h2: Properly handle shutdowns when received with data

The H2_CF_RCVD_SHUT flag is used to report a read0 was encountered. It is
used by the H2 mux to properly handle shutdowns. However, this flag is only
set when no data are received. If it is detected at the socket level when
some data are received, it is not handled. And because the event was
reported on the connection, any other read attempts are blocked. In this
case, we are unable to close the connection and release the mux
immediately. We must wait the mux timeout expires.

This patch should fix the issue #1231. It must be backported as far as 2.0.

4 years agoCLEANUP: compression: remove calls to SLZ init functions
Willy Tarreau [Thu, 22 Apr 2021 12:43:49 +0000 (14:43 +0200)] 
CLEANUP: compression: remove calls to SLZ init functions

As we now embed the library we don't need to support the older 1.0 API
any more, so we can remove the explicit calls to slz_make_crc_table()
and slz_prepare_dist_table().

4 years agoCI: github: do not build libslz any more
Willy Tarreau [Thu, 22 Apr 2021 14:10:32 +0000 (16:10 +0200)] 
CI: github: do not build libslz any more

As hinted by Tim, it's not needed any more since it's now integrated,
let's get rid of this step.

4 years agoBUILD: compression: switch SLZ from out-of-tree to in-tree
Willy Tarreau [Thu, 22 Apr 2021 12:14:22 +0000 (14:14 +0200)] 
BUILD: compression: switch SLZ from out-of-tree to in-tree

Now that SLZ is merged, let's update the makefile and compression
files to use it. As a result, SLZ_INC and SLZ_LIB are neither defined
nor used anymore.

USE_SLZ is enabled by default ("USE_SLZ=default") and can be disabled
by passing "USE_SLZ=" or by enabling USE_ZLIB=1.

The doc was updated to reflect the changes.

4 years agoIMPORT: slz: import slz into the tree
Willy Tarreau [Thu, 22 Apr 2021 12:09:44 +0000 (14:09 +0200)] 
IMPORT: slz: import slz into the tree

SLZ is rarely packaged by distros and there have been complaints about
the CPU and memory usage of ZLIB, leading to some suggestions to better
address the issue by simply integrating SLZ into the tree (just 3 files).
See discussions below:

   https://www.mail-archive.com/haproxy@formilux.org/msg38037.html
   https://www.mail-archive.com/haproxy@formilux.org/msg40079.html
   https://www.mail-archive.com/haproxy@formilux.org/msg40365.html

This patch does just this, after minor adjustments to these files:
  - tables.h was renamed to slz-tables.h
  - tables.h had the precomputed tables removed since not used here
  - slz.c uses includes <import/slz*> instead of "slz*.h"

The slz commit imported here was b06c172 ("slz: avoid a build warning
with -Wimplicit-fallthrough"). No other change was performed either to
SLZ nor to haproxy at this point so that this operation may be replicated
if needed for a future version.

4 years agoBUILD: makefile: fix the "make clean" target on strict bourne shells
Willy Tarreau [Wed, 21 Apr 2021 15:17:16 +0000 (17:17 +0200)] 
BUILD: makefile: fix the "make clean" target on strict bourne shells

As reported by @axinojolais in issue #1217, some older bourne shells do
not expand on braces so some files were not cleaned since the recent
splitting of the contrib/ subdir. Let's fix that by explicitly listing
the patterns to be cleared (which are in much smaller quantity now that
contrib was removed), and for grouping them with their respective dirs.

At some point, some recursive makefiles would probably help there.

4 years agoBUG/MINOR: mworker: don't use oldpids[] anymore for reload
William Lallemand [Wed, 21 Apr 2021 14:55:34 +0000 (16:55 +0200)] 
BUG/MINOR: mworker: don't use oldpids[] anymore for reload

Since commit 3f12887 ("MINOR: mworker: don't use children variable
anymore"), the oldpids array is not used anymore to generate the new -sf
parameters. So we don't need to set nb_oldpids to 0 during the first
start of the master process.

This patch fixes a bug when 2 masters process tries to synchronize their
peers, there is a small chances that it won't work because nb_oldpids
equals 0.

Should be backported as far as 2.0.

4 years agoBUG/MINOR: mworker/init: don't reset nb_oldpids in non-mworker cases
William Lallemand [Wed, 21 Apr 2021 14:42:18 +0000 (16:42 +0200)] 
BUG/MINOR: mworker/init: don't reset nb_oldpids in non-mworker cases

This bug affects the peers synchronisation code which rely on the
nb_oldpids variable to synchronize the peer from the old PID.

In the case the process is not started in master-worker mode and tries
to synchronize using the peers, there is a small chance that won't work
because nb_oldpids equals 0.

Fix the bug by setting the variable to 0 only in the case of the
master-worker when not reloaded.

It could also be a problem when trying to synchronize the peers between
2 masters process which should be fixed in another patch.

Bug exists since commit 8a361b5 ("BUG/MEDIUM: mworker: don't reuse PIDs
passed to the master").

Sould be backported as far as 1.8.

4 years agoMINOR: config: add a diag for invalid cpu-map statement
Amaury Denoyelle [Thu, 15 Apr 2021 16:07:07 +0000 (18:07 +0200)] 
MINOR: config: add a diag for invalid cpu-map statement

If a cpu-statement is refering to multiple processes and threads, it is
silently ignored. Add a diag message to report it to the user.

4 years agoBUG/MEDIUM: config: fix cpu-map notation with both process and threads
Amaury Denoyelle [Thu, 15 Apr 2021 14:29:58 +0000 (16:29 +0200)] 
BUG/MEDIUM: config: fix cpu-map notation with both process and threads

The application of a cpu-map statement with both process and threads
is broken (P-Q/1 or 1/P-Q notation).

For example, before the fix, when using P-Q/1, proc_t1 would be updated.
Then it would be AND'ed with thread which is still 0 and thus does
nothing.

Another problem is when using 1/1[-Q], thread[0] is defined. But if
there is multiple processes, every processes will use this define
affinity even if it should be applied only to 1st process.

The solution to the fix is a little bit too complex for my taste and
there is maybe a simpler solution but I did not wish to break the
storage of global.cpu_map, as it is quite painful to test all the
use-cases. Besides, this code will probably be clean up when
multiprocess support removed on the future version.

Let's try to explain my logic.

* either haproxy runs in multiprocess or multithread mode. If on
  multiprocess, we should consider proc_t1 (P-Q/1 notation). If on
  multithread, we should consider thread (1/P-Q notation). However
  during parsing, the final number of processes or threads is unknown,
  thus we have to consider the two possibilities.

* there is a special case for the first thread / first process which is
  present in both execution modes. And as a matter of fact cpu-map 1 or
  1/1 notation represents the same thing. Thus, thread[0] and proc_t1[0]
  represents the same thing. To solve this problem, only thread[0] is
  used for this special case.

This fix must be backported up to 2.0.

4 years agoCLEANUP: contrib: remove the last references to the now dead contrib/ directory
Willy Tarreau [Wed, 21 Apr 2021 13:13:10 +0000 (15:13 +0200)] 
CLEANUP: contrib: remove the last references to the now dead contrib/ directory

Now with the last SPOA modules gone, contrib/ doesn't exist anymore
and does not need to be referenced in the Makefile nor .gitignore.

4 years agoCONTRIB: move mod_defender out of the tree
Willy Tarreau [Wed, 21 Apr 2021 13:05:52 +0000 (15:05 +0200)] 
CONTRIB: move mod_defender out of the tree

As previously mentioned SPOA code has nothing to do in the haproxy core
since they're not dependent on haproxy's version. This one was moved to
its own repository here with complete history:

  https://github.com/haproxytech/spoa-mod_defender

4 years agoMINOR: uri_normalizer: Add a `strip-dot` normalizer
Maximilian Mader [Tue, 20 Apr 2021 22:22:50 +0000 (00:22 +0200)] 
MINOR: uri_normalizer: Add a `strip-dot` normalizer

This normalizer removes "/./" segments from the path component.
Usually the dot refers to the current directory which renders those segments redundant.

See GitHub Issue #714.

4 years agoCLEANUP: uri_normalizer: Remove trailing whitespace
Maximilian Mader [Tue, 20 Apr 2021 22:22:49 +0000 (00:22 +0200)] 
CLEANUP: uri_normalizer: Remove trailing whitespace

This patch removes a single trailing space.

4 years agoBUG/MINOR: uri_normalizer: Use delim parameter when building the sorted query in...
Maximilian Mader [Tue, 20 Apr 2021 22:22:48 +0000 (00:22 +0200)] 
BUG/MINOR: uri_normalizer: Use delim parameter when building the sorted query in uri_normalizer_query_sort

Currently the delimiter is hardcoded as ampersand (&) but the function takes the delimiter as a paramter.
This patch replaces the hardcoded ampersand with the given delimiter.

4 years agoBUG/MEDIUM: mux-h2: Fix dfl calculation when merging CONTINUATION frames
Christopher Faulet [Wed, 21 Apr 2021 09:11:21 +0000 (11:11 +0200)] 
BUG/MEDIUM: mux-h2: Fix dfl calculation when merging CONTINUATION frames

When header are splitted over several frames, payload of HEADERS and
CONTINUATION frames are merged to form a unique HEADERS frame before
decoding the payload. To do so, info about the current frame are updated
(dff, dfl..) with info of the next one. Here there is a bug when the frame
length (dfl) is update. We must add the next frame length (hdr.dfl) and not
only the amount of data found in the buffer (clen). Because HEADERS frames
are decoded in one pass, dfl value is the whole frame length or 0. nothing
intermediary.

This patch must be backported as far as 2.0.

4 years agoBUG/MAJOR: mux-h2: Properly detect too large frames when decoding headers
Christopher Faulet [Wed, 21 Apr 2021 08:39:53 +0000 (10:39 +0200)] 
BUG/MAJOR: mux-h2: Properly detect too large frames when decoding headers

In the function decoding payload of HEADERS frames, an internal error is
returned if the frame length is too large. it cannot exceed the buffer
size. The same is true when headers are splitted on several frames. The
payload of HEADERS and CONTINUATION frames are merged and the overall size
must not exceed the buffer size.

However, there is a bug when the current frame is big enough to only have
the space for a part of the header of the next frame. Because, in this case,
we wait for more data, to have the whole frame header. We don't properly
detect that the headers are too large to be stored in one buffer. In fact
the test to trigger this error is not accurate. When the buffer is full, the
error is reported if the frame length exceeds the amount of data in the
buffer. But in reality, an error must be reported when we are unable to
decode the current frame while the buffer is full. Because, in this case, we
know there is no way to change this state.

When the bug happens, the H2 connection is woken up in loop, consumming all
the CPU. But the traffic is not blocked for all that.

This patch must be backported as far as 2.0.

4 years agoBUG/MINOR: server: fix potential null gcc error in delete server
Amaury Denoyelle [Wed, 21 Apr 2021 09:50:26 +0000 (11:50 +0200)] 
BUG/MINOR: server: fix potential null gcc error in delete server

gcc still reports a potential null pointer dereference in delete server
function event with a BUG_ON before it. Remove the misleading NULL check
in the for loop which should never happen.

This does not need to be backported.

4 years agoCONTRIB: move modsecurity out of the tree
Willy Tarreau [Wed, 21 Apr 2021 09:29:47 +0000 (11:29 +0200)] 
CONTRIB: move modsecurity out of the tree

As previously mentioned SPOA code has nothing to do in the haproxy core
since they're not dependent on haproxy's version. This one was moved to
its own repository here with complete history:

    https://github.com/haproxy/spoa-modsecurity

4 years agoCONTRIB: move spoa_server out of the tree
Willy Tarreau [Wed, 21 Apr 2021 09:28:48 +0000 (11:28 +0200)] 
CONTRIB: move spoa_server out of the tree

As previously mentioned SPOA code has nothing to do in the haproxy core
since they're not dependent on haproxy's version. This one was moved to
its own repository here with complete history:

    https://github.com/haproxy/spoa-server

4 years agoMINOR: server: implement delete server cli command
Amaury Denoyelle [Thu, 15 Apr 2021 12:41:20 +0000 (14:41 +0200)] 
MINOR: server: implement delete server cli command

Implement a new CLI command 'del server'. It can be used to removed a
dynamically added server. Only servers in maintenance mode can be
removed, and without pending/active/idle connection on it.

Add a new reg-test for this feature. The scenario of the reg-test need
to first add a dynamic server. It is then deleted and a client is used
to ensure that the server is non joinable.

The management doc is updated with the new command 'del server'.

4 years agoMINOR: server: add log on dynamic server creation
Amaury Denoyelle [Tue, 20 Apr 2021 16:35:19 +0000 (18:35 +0200)] 
MINOR: server: add log on dynamic server creation

Add a notice log to report the creation of a new server. The log is
printed at the end of the function.

4 years agoBUG/MEDIUM: server: ensure thread-safety of server runtime creation
Amaury Denoyelle [Tue, 20 Apr 2021 15:09:08 +0000 (17:09 +0200)] 
BUG/MEDIUM: server: ensure thread-safety of server runtime creation

cli_parse_add_server can be executed in parallel by several CLI
instances and so must be thread-safe. The critical points of the
function are :
- server duplicate detection
- insertion of the server in the proxy list

The mode of operation has been reversed. The server is first
instantiated and parsed. The duplicate check has been moved at the end
just before the insertion in the proxy list, under the thread isolation.
Thus, the thread safety is guaranteed and server allocation is kept
outside of locks/thread isolation.

4 years agoBUG/MINOR: logs: free logsrv.conf.file on exit
Amaury Denoyelle [Tue, 20 Apr 2021 15:05:47 +0000 (17:05 +0200)] 
BUG/MINOR: logs: free logsrv.conf.file on exit

Config information has been added into the logsrv struct. The filename
is duplicated and should be freed on exit.

Introduced in the current release.
This does not need to be backported.

4 years agoBUG/MINOR: server: free srv.lb_nodes in free_server
Amaury Denoyelle [Tue, 20 Apr 2021 14:48:22 +0000 (16:48 +0200)] 
BUG/MINOR: server: free srv.lb_nodes in free_server

lb_nodes is allocated for servers using lb_chash (balance random or
hash-type consistent).

It can be backported up to 1.8.

4 years agoCONTRIB: move spoa_example out of the tree
Willy Tarreau [Wed, 21 Apr 2021 07:39:06 +0000 (09:39 +0200)] 
CONTRIB: move spoa_example out of the tree

As previously mentioned SPOA code has nothing to do in the haproxy core
since they're not dependent on haproxy's version. This one was moved to
its own repository here with complete history:

     https://github.com/haproxy/spoa-example

4 years agoCLEANUP: lists/tree-wide: rename some list operations to avoid some confusion
Willy Tarreau [Wed, 21 Apr 2021 05:32:39 +0000 (07:32 +0200)] 
CLEANUP: lists/tree-wide: rename some list operations to avoid some confusion

The current "ADD" vs "ADDQ" is confusing because when thinking in terms
of appending at the end of a list, "ADD" naturally comes to mind, but
here it does the opposite, it inserts. Several times already it's been
incorrectly used where ADDQ was expected, the latest of which was a
fortunate accident explained in 6fa922562 ("CLEANUP: stream: explain
why we queue the stream at the head of the server list").

Let's use more explicit (but slightly longer) names now:

   LIST_ADD        ->       LIST_INSERT
   LIST_ADDQ       ->       LIST_APPEND
   LIST_ADDED      ->       LIST_INLIST
   LIST_DEL        ->       LIST_DELETE

The same is true for MT_LISTs, including their "TRY" variant.
LIST_DEL_INIT keeps its short name to encourage to use it instead of the
lazier LIST_DELETE which is often less safe.

The change is large (~674 non-comment entries) but is mechanical enough
to remain safe. No permutation was performed, so any out-of-tree code
can easily map older names to new ones.

The list doc was updated.

4 years agoCLEANUP: sample: Use explicit return for successful `json_query`s
Tim Duesterhus [Thu, 15 Apr 2021 16:40:06 +0000 (18:40 +0200)] 
CLEANUP: sample: Use explicit return for successful `json_query`s

Move the `return 1` into each of the cases, instead of relying on the single
`return 1` at the bottom of the function.

4 years agoCLEANUP: sample: Explicitly handle all possible enum values from mjson
Tim Duesterhus [Thu, 15 Apr 2021 16:14:32 +0000 (18:14 +0200)] 
CLEANUP: sample: Explicitly handle all possible enum values from mjson

This makes it easier to find bugs, because -Wswitch can help us.

4 years agoCLEANUP: sample: Improve local variables in sample_conv_json_query
Tim Duesterhus [Thu, 15 Apr 2021 16:08:48 +0000 (18:08 +0200)] 
CLEANUP: sample: Improve local variables in sample_conv_json_query

This improves the use of local variables in sample_conv_json_query:

- Use the enum type for the return value of `mjson_find`.
- Do not use single letter variables.
- Reduce the scope of variables that are only needed in a single branch.
- Add missing newlines after variable declaration.

4 years agoCONTRIB: modsecurity: make the code build with the embedded includes
Willy Tarreau [Tue, 20 Apr 2021 17:32:15 +0000 (19:32 +0200)] 
CONTRIB: modsecurity: make the code build with the embedded includes

From now on the code only needs its embedded dependencies and does not
depend any more on external haproxy dependencies. It can now be built
as a standalone project.

4 years agoCONTRIB: modsecurity: import the minimal number of includes
Willy Tarreau [Tue, 20 Apr 2021 17:30:56 +0000 (19:30 +0200)] 
CONTRIB: modsecurity: import the minimal number of includes

Just like mod_defender, modsecurity depends on a few haproxy includes
and it shouldn't since it's expected to be agnostic to the version.

This imports the strictly minimum number of includes required to build
it. These have been manually stripped from their exported functions
prototypes and their unneeded dependencies.

4 years agoCONTRIB: mod_defender: make the code build with the embedded includes
Willy Tarreau [Tue, 20 Apr 2021 17:19:53 +0000 (19:19 +0200)] 
CONTRIB: mod_defender: make the code build with the embedded includes

From now on the code only needs its embedded dependencies and does not
depend any more on external haproxy dependencies. It can now be built
as a standalone project.

4 years agoCONTRIB: mod_defender: import the minimal number of includes
Willy Tarreau [Tue, 20 Apr 2021 17:16:59 +0000 (19:16 +0200)] 
CONTRIB: mod_defender: import the minimal number of includes

mod_defender currently depends on haproxy includes while it should be
totally autonomous since it should build without and not even depend
on any specific haproxy version.

This imports the strictly minimum number of includes required to build
it. These have been manually stripped from their exported functions
prototypes and their unneeded dependencies.

In reality, the defender.c mostly needs sample.h because it stores its
data this way, spoe.h for the protocol definitions, and a few intops
and tools to decode varints. The rest mostly comes as intermediate
dependencies.

4 years agoBUG/MINOR: server: make srv_alloc_lb() allocate lb_nodes for consistent hash
Willy Tarreau [Tue, 20 Apr 2021 09:37:45 +0000 (11:37 +0200)] 
BUG/MINOR: server: make srv_alloc_lb() allocate lb_nodes for consistent hash

The test in srv_alloc_lb() to allocate the lb_nodes[] array used in the
consistent hash was incorrect, it wouldn't do it for consistent hash and
could do it for regular random.

No backport is needed as this was added for dynamic servers in 2.4-dev by
commit f99f77a50 ("MEDIUM: server: implement 'add server' cli command").

4 years agoBUILD: pools: fix build with DEBUG_FAIL_ALLOC
Willy Tarreau [Mon, 19 Apr 2021 16:36:48 +0000 (18:36 +0200)] 
BUILD: pools: fix build with DEBUG_FAIL_ALLOC

Amaury noticed that I managed to break the build of DEBUG_FAIL_ALLOC
for the second time with 207c09509 ("MINOR: pools: move the fault
injector to __pool_alloc()"). The joy of endlessly reworking patch
sets... No backport is needed, that was in the just merged cleanup
series.

4 years agoCLEANUP: pools: declare dummy pool functions to remove some ifdefs
Willy Tarreau [Mon, 19 Apr 2021 10:29:16 +0000 (12:29 +0200)] 
CLEANUP: pools: declare dummy pool functions to remove some ifdefs

By having a pair of dummy pool_get_from_cache() and pool_put_to_cache()
we can remove some ugly ifdefs, so let's do this. We've already done it
for the shared cache.

4 years agoCLEANUP: pools: uninline pool_put_to_cache()
Willy Tarreau [Mon, 19 Apr 2021 09:49:26 +0000 (11:49 +0200)] 
CLEANUP: pools: uninline pool_put_to_cache()

This function has become too big (251 bytes) and is now hurting
performance a lot, with up to 4% request rate being lost over the last
pool changes. Let's move it to pool.c as a regular function. Other
attempts were made to cut it in half but it's still inefficient. Doing
this results in saving ~90kB of object code, and even 112kB since the
pool changes, with code that is even slightly faster!

Conversely, pool_get_from_cache(), which remains half of this size, is
still faster inlined, likely in part due to the immediate use of the
returned pointer afterwards.

4 years agoCLEANUP: pools: merge pool_{get_from,put_to}_local_caches with generic ones
Willy Tarreau [Mon, 19 Apr 2021 07:02:15 +0000 (09:02 +0200)] 
CLEANUP: pools: merge pool_{get_from,put_to}_local_caches with generic ones

Since pool_get_from_cache() and pool_put_to_cache() were now only wrappers
to the local cache versions which do all the job, let's merge them together
so that there is no more local-cache specific function.

4 years agoCLEANUP: pools: make the local cache allocator fall back to the shared cache
Willy Tarreau [Mon, 19 Apr 2021 06:56:22 +0000 (08:56 +0200)] 
CLEANUP: pools: make the local cache allocator fall back to the shared cache

Now when pool_get_from_local_cache() fails, it automatically falls back
to pool_get_from_shared_cache(), which used to always be done in
pool_get_from_cache(). Thus now the API is simpler as we always allocate
and free from/to the local caches.

4 years agoMEDIUM: pools: make pool_put_to_cache() always call pool_put_to_local_cache()
Willy Tarreau [Mon, 19 Apr 2021 06:50:45 +0000 (08:50 +0200)] 
MEDIUM: pools: make pool_put_to_cache() always call pool_put_to_local_cache()

Till now it used to call it only if there were not too many objects into
the local cache otherwise would send the latest one directly into the
shared cache. Now it always sends to the local cache and it's up to the
local cache to free its oldest objects. From a cache freshness perspective
it's better this way since we always evict cold objects instead of hot
ones. From an API perspective it's better because it will help make the
shared cache invisible to the public API.

4 years agoMINOR: pools: evict excess objects using pool_evict_from_local_cache()
Willy Tarreau [Mon, 19 Apr 2021 06:14:03 +0000 (08:14 +0200)] 
MINOR: pools: evict excess objects using pool_evict_from_local_cache()

Till now we could only evict oldest objects from all local caches using
pool_evict_from_local_caches() until the cache size was satisfying again,
but there was no way to evict excess objects from a single cache, which
is the reason why pool_put_to_cache() used to refrain from putting into
the local cache and would directly write to the shared cache, resulting
in massive writes when caches were full.

Let's add this new function now. It will stop once the number of objects
in the local cache is no higher than 16+total/8 or the cache size is no
more than 75% full, just like before.

For now the function is not used.

4 years agoMINOR: pools: create unified pool_{get_from,put_to}_cache()
Willy Tarreau [Sun, 18 Apr 2021 09:11:14 +0000 (11:11 +0200)] 
MINOR: pools: create unified pool_{get_from,put_to}_cache()

These two functions are now responsible for allocating directly from
the cache and releasing to the cache.

Now the pool_alloc() function simply does this:

    if cache enabled
       return pool_alloc_from_cache() if no NULL
    return pool_alloc_nocache() otherwise

and the pool_free() function does this:

    if cache enabled
       pool_put_to_cache()
    else
       pool_free_nocache()

For now this only introduces these two functions without changing anything
else, but the goal is to soon allow to make them implementation-specific.

4 years agoMEDIUM: pools: make CONFIG_HAP_POOLS control both local and shared pools
Willy Tarreau [Sun, 18 Apr 2021 08:23:02 +0000 (10:23 +0200)] 
MEDIUM: pools: make CONFIG_HAP_POOLS control both local and shared pools

Continuing the unification of local and shared pools, now the usage of
pools is governed by CONFIG_HAP_POOLS without which allocations and
releases are performed directly from the OS using pool_alloc_nocache()
and pool_free_nocache().

4 years agoMINOR: pools: factor the release code into pool_put_to_os()
Willy Tarreau [Sat, 17 Apr 2021 15:48:40 +0000 (17:48 +0200)] 
MINOR: pools: factor the release code into pool_put_to_os()

There are two levels of freeing to the OS:
  - code that wants to keep the pool's usage counters updated uses
    pool_free_area() and handles the counters itself. That's what
    pool_put_to_shared_cache() does in the no-global-pools case.
  - code that does not want to update the counters because they were
    already updated only calls pool_free_area().

Let's extract these calls to establish the symmetry with pool_get_from_os()
and pool_alloc_nocache(), resulting in pool_put_to_os() (which only updates
the allocated counter) and pool_free_nocache() (which also updates the used
counter). This will later allow to simplify the generic code.

4 years agoMINOR: pools: move pool_free_area() out of the lock in the locked version
Willy Tarreau [Sat, 17 Apr 2021 16:19:51 +0000 (18:19 +0200)] 
MINOR: pools: move pool_free_area() out of the lock in the locked version

Calling pool_free_area() inside a lock in pool_put_to_shared_cache() is
a very bad idea. Fortunately this only happens on the lowest end platforms
which almost never use threads or in very small counts.

This change consists in zeroing the pointer once already released to the
cache in the first test so that the second stage knows if it needs to
pass it to the OS or not. This has slightly reduced the length of the

4 years agoMINOR: pools: always use atomic ops to maintain counters
Willy Tarreau [Sat, 17 Apr 2021 16:06:57 +0000 (18:06 +0200)] 
MINOR: pools: always use atomic ops to maintain counters

A part of the code cannot be factored out because it still uses non-atomic
inc/dec for pool->used and pool->allocated as these are located under the
pool's lock. While it can make sense in terms of bus cycles, it does not
make sense in terms of code normalization. Further, some operations were
still performed under a lock that could be totally removed via the use of
atomic ops.

There is still one occurrence in pool_put_to_shared_cache() in the locked
code where pool_free_area() is called under the lock, which must absolutely
be fixed.