Commit graph

5064 commits

Author SHA1 Message Date
Tim Duesterhus
763342646f MINOR: ist: Add istclear(struct ist*)
istclear allows one to easily reset an ist to zero-size, while preserving the
previous size, indicating the length of the underlying buffer.
2021-04-14 19:49:33 +02:00
Moemen MHEDHBI
92f7d43c5d MINOR: sample: add ub64dec and ub64enc converters
ub64dec and ub64enc are the base64url equivalent of b64dec and base64
converters. base64url encoding is the "URL and Filename Safe Alphabet"
variant of base64 encoding. It is also used in in JWT (JSON Web Token)
standard.
RFC1421 mention in base64.c file is deprecated so it was replaced with
RFC4648 to which existing converters, base64/b64dec, still apply.

Example:
  HAProxy:
    http-request return content-type text/plain lf-string %[req.hdr(Authorization),word(2,.),ub64dec]
  Client:
    Token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZm9vIiwia2V5IjoiY2hhZTZBaFhhaTZlIn0.5VsVj7mdxVvo1wP5c0dVHnr-S_khnIdFkThqvwukmdg
    $ curl -H "Authorization: Bearer ${TOKEN}" http://haproxy.local
    {"user":"foo","key":"chae6AhXai6e"}
2021-04-13 17:28:13 +02:00
Christopher Faulet
0c6d1dcf7d BUG/MINOR: listener: Handle allocation error when allocating a new bind_conf
Allocation error are now handled in bind_conf_alloc() functions. Thus
callers, when not already done, are also updated to catch NULL return value.

This patch may be backported (at least partially) to all stable
versions. However, it only fix errors durung configuration parsing. Thus it
is not mandatory.
2021-04-12 21:33:43 +02:00
Christopher Faulet
147b8c919c MINOIR: checks/trace: Register a new trace source with its events
Add the trace support for the checks. Only tcp-check based health-checks are
supported, including the agent-check.

In traces, the first argument is always a check object. So it is easy to get
all info related to the check. The tcp-check ruleset, the conn-stream and
the connection, the server state...
2021-04-12 12:09:36 +02:00
Christopher Faulet
6d80b63e3c MINOR: trace: Add the checks as a possible trace source
To be able to add the trace support for the checks, a new kind of source
must be added for this purpose.
2021-04-12 12:09:36 +02:00
Willy Tarreau
7b1425a91b MINOR: atomic: reimplement the relaxed version of x86 BTS/BTR
Olivier spotted that I messed up during a rebase of commit 92c059c2a
("MINOR: atomic: implement native BTS/BTR for x86"), losing the x86
version of the BTS/BTR and leaving the generic version for it instead
of having this block in the #else. Since this variant is not used for
now it was easy to overlook it. Let's re-implement it here.
2021-04-12 10:01:44 +02:00
Willy Tarreau
c4c80fb4ea MINOR: time: move the time initialization out of tv_update_date()
The time initialization was made a bit complex because we rely on a
dummy negative argument to reset all fields, leaving no distinction
between process-level initialization and thread-level initialization.
This patch changes this by introducing two functions, one for the
process and the second one for the threads. This removes ambigous
test and makes sure that the relevant fields are always initialized
exactly once. This also offers a better solution to the bug fixed in
commit b48e7c001 ("BUG/MEDIUM: time: make sure to always initialize
the global tick") as there is no more special values for global_now_ms.

It's simple enough to be backported if any other time-related issues
are encountered in stable versions in the future.
2021-04-11 23:45:48 +02:00
Willy Tarreau
61c72c366e CLEANUP: time: remove the now unused ms_left_scaled
It was only used by freq_ctr and is not used anymore. In addition the
local curr_sec_ms was removed, as well as the equivalent extern
definitions which did not exist anymore either.
2021-04-11 14:01:53 +02:00
Willy Tarreau
d46ed5c26b MINOR: freq_ctr: simplify and improve the update function
update_freq_ctr_period() was still not very clean and didn't wait for
the rotation lock to be dropped before trying again, thus maintaining
the contention at a high level. In addition, the rotation update was
made in three steps, which are not very efficient in terms of bus
cycles.

Here the wait loop was reworked so that the fast path remains short
and that the contended path waits for the lock to be dropped before
attempting another write, but it only waits a relax cycle before
attempting a read. The rotation block was simplified to remove a
test that was already validated by the first loop, and so that the
retrieval of the current period, its reset and its increment are all
performed in a single atomic op and the store to the previous period
is performed immediately after.

All this results in significantly smaller code for the inline function
(~1kB total) and a shorter critical path.
2021-04-11 14:01:53 +02:00
Willy Tarreau
6339c19cac MINOR: freq_ctr: add cpu_relax in the rotation loop of update_freq_ctr_period()
When counters are rotated, there is contention between the threads which
can slow down the operation of the thread performing the rotation. Let's
apply a cpu_relax there to let the first thread finish faster.
2021-04-11 11:12:57 +02:00
Willy Tarreau
fc6323ad82 MEDIUM: freq_ctr: replace the per-second counters with the generic ones
It remains cumbersome to preserve two versions of the freq counters and
two different internal clocks just for this. In addition, the savings
from using two different mechanisms are not that important as the only
saving is a divide that is replaced by a multiply, but now thanks to
the freq_ctr_total() unificaiton the code could also be simplified to
optimize it in case of constants.

This patch turns all non-period freq_ctr functions to static inlines
which call the period-based ones with a period of 1 second. A direct
benefit is that a single internal clock is now needed for any counter
and that they now all rely on ticks.

These 1-second counters are essentially used to report request rates
and to enforce a connection rate limitation in listeners. It was
verified that these continue to work like before.
2021-04-11 11:12:55 +02:00
Willy Tarreau
fa1258f02c MINOR: freq_ctr: unify freq_ctr and freq_ctr_period into freq_ctr
Both structures are identical except the name of the field starting
the period and its description. Let's call them all freq_ctr and the
period's start "curr_tick" which is generic.

This is only a temporary change and fields are expected to remain
the same with no code change (verified).
2021-04-11 11:11:27 +02:00
Willy Tarreau
d209c87142 MINOR: freq_ctr: add the missing next_event_delay_period()
There was still no function to compute a wait time for periods, let's
implement it on top of freq_ctr_total() as we'll soon need it for the
per-second one. The divide here is applied on the frequency so that it
will be replaced with a reciprocal multiply when constant.
2021-04-11 11:11:03 +02:00
Willy Tarreau
607be24a85 MEDIUM: freq_ctr: reimplement freq_ctr_remain_period() from freq_ctr_total()
Now the function becomes an inline one and only contains a divide and
a max. The divide will automatically go away with constant periods.
2021-04-11 11:11:03 +02:00
Willy Tarreau
a7a31b2602 MEDIUM: freq_ctr: make read_freq_ctr_period() use freq_ctr_total()
This one is the easiest to implement, it just requires a call and a
divide of the result. Anti-flapping correction for low-rates was
preserved.

Now calls using a constant period will be able to use a reciprocal
multiply for the period instead of a divide.
2021-04-11 11:11:03 +02:00
Willy Tarreau
f3a9f8dc5a MINOR: freq_ctr: add a generic function to report the total value
Most of the functions designed to read a counter over a period go through
the same complex loop and only differ in the way they use the returned
values, so it was worth implementing all this into freq_ctr_total() which
returns the total number of events over a period so that the caller can
finish its operation using a divide or a remaining time calculation. As
a special case, read_freq_ctr_period() doesn't take pending events but
requires to enable an anti-flapping correction at very low frequencies.
Thus the function implements it when pend<0.

Thanks to this function it will be possible to reimplement the other ones
as inline and merge the per-second ones with the arbitrary period ones
without always adding the cost of a 64 bit divide.
2021-04-11 11:10:57 +02:00
Willy Tarreau
ff88270ef9 MINOR: pool: move pool declarations to read_mostly
All pool heads are accessed via a pointer and should not be shared with
highly written variables. Move them to the read_mostly section.
2021-04-10 19:27:41 +02:00
Willy Tarreau
f459640ef6 MINOR: global: declare a read_mostly section
Some variables are mostly read (mostly pointers) but they tend to be
merged with other ones in the same cache line, slowing their access down
in multi-thread setups. This patch declares an empty, aligned variable
in a section called "read_mostly". This will force a cache-line alignment
on this section so that any variable declared in it will be certain to
avoid false sharing with other ones. The section will be eliminated at
link time if not used.

A __read_mostly attribute was added to compiler.h to ease use of this
section.
2021-04-10 19:27:41 +02:00
Willy Tarreau
ba386f6a8d CLEANUP: initcall: rely on HA_SECTION_* instead of defining its own
Now initcalls are defined using the regular section definitions from
compiler.h in order to ease maintenance.
2021-04-10 19:27:41 +02:00
Willy Tarreau
5bec4c42ed MINOR: compiler: add macros to declare section names
HA_SECTION() is used as an attribute to force a section name. This is
required because OSX prepends "__DATA, " in front of the declaration.
HA_SECTION_START() and HA_SECTION_STOP() are used as post-attribute on
variable declaration to designate the section start/end (needed only on
OSX, empty on others).

For platforms with an obsolete linker, all macros are left empty. It would
possibly still work on some of them but this will not be needed anyway.
2021-04-10 19:27:41 +02:00
Willy Tarreau
731f0c6502 CLEANUP: initcall: rename HA_SECTION to HA_INIT_SECTION
The HA_SECTION name is too generic and will be reused globally. Let's
rename this one.
2021-04-10 19:27:41 +02:00
Willy Tarreau
afa9bc0ec5 MINOR: initcall: uniformize the section names between MacOS and other unixes
Due to length restrictions on OSX the initcall sections are called "i_"
there while they're called "init_" on other OSes. However the start and
end of sections are still called "__start_init_" and "__stop_init_",
which forces to have distinct code between the OSes. Let's switch everyone
to "i_" and rename the symbols accordingly.
2021-04-10 19:27:41 +02:00
Willy Tarreau
ad14c2681b MINOR: trace: replace the trace() inline function with an equivalent macro
The trace() function is convenient to avoid calling trace() when traces
are not enabled, but there starts to be some callers which place complex
expressions in their trace calls, which results in all of them to be
evaluated before being passed as arguments to the trace() function. This
needlessly wastes precious CPU cycles.

Let's change the function for a macro, so that the arguments are now only
evaluated when the surce has traces enabled. However having a generic
macro being called "trace()" can easily cause conflicts with innocent
code so we rename it "_trace".

Just doing this has resulted in a 2.5% increase of the HTTP/1 request rate.
2021-04-10 19:27:41 +02:00
Willy Tarreau
9057a0026e CLEANUP: pattern: make all pattern tables read-only
Interestingly, all arrays used to declare patterns were read-write while
only hard-coded. Let's mark them const so that they move from data to
rodata and don't risk to experience false sharing.
2021-04-10 17:49:41 +02:00
Tim Duesterhus
403fd722ac CLEANUP: Remove useless malloc() casts
This is not C++.
2021-04-08 20:11:58 +02:00
Tim Duesterhus
fea59fcf79 CLEANUP: ist: Remove unused count argument from ist2str*
This argument is not being used inside the function (and the functions
themselves are unused as well) and not documented. Its purpose is not clear.
Just remove it.
2021-04-08 19:40:59 +02:00
Tim Duesterhus
b8ee894b66 CLEANUP: htx: Make http_get_stline take a const struct
Nothing is being modified there, so this can be `const`.
2021-04-08 19:40:59 +02:00
Tim Duesterhus
fbc2b79743 MINOR: ist: Rename istappend() to __istappend()
Indicate that this function is not inherently safe by adding two underscores as
a prefix.
2021-04-08 19:35:52 +02:00
Willy Tarreau
1197459e0a BUG/MAJOR: fd: switch temp values to uint in fd_stop_both()
With latest commit f50906519 ("MEDIUM: fd: merge fdtab[].ev and state
for FD_EV_* and FD_POLL_* into state") one occurrence of a pair of
chars was missed in fd_stop_both(), resulting in the operation to
fail if the upper flags were set. Interestingly it managed to fail
2 tests in all setups in the CI while all used to work fine on my
local machines. Probably that the reason is that the chars had enough
room above them for the CAS to fail then refill "old" overwriting the
upper parts of the stack, and that thanks to this the subsequent tests
worked. With ASAN being used on lots of tests, it very likely caught
it but used to only report failed tests with no more info.

No backport is needed, as this was never released nor backported.
2021-04-07 20:46:26 +02:00
Tim Duesterhus
8daf8dceb9 MINOR: ist: Add istsplit(struct ist*, char)
istsplit is a combination of iststop + istadv.
2021-04-07 19:50:43 +02:00
Tim Duesterhus
90aa8c7f02 MINOR: ist: Add istshift(struct ist*)
istshift() returns the first character and advances the ist by 1.
2021-04-07 19:50:43 +02:00
Tim Duesterhus
551eeaec91 MINOR: ist: Add istappend(struct ist, char)
This function appends the given char to the given `ist` and returns
the resulting `ist`.
2021-04-07 19:50:43 +02:00
Willy Tarreau
92c059c2ac MINOR: atomic: implement native BTS/BTR for x86
The current BTS/BTR operations on x86 are ugly because they rely on a
CAS, so they may be unfair and take time to converge. Fortunately,
where they are currently used (mostly FDs) the contention is expected
to be rare (mostly listeners). But this also limits their use to such
few low-load cases.

On x86 there is a set of BTS/BTR instructions which help for this,
but before the FD's state migrated to 32 bits there was little use of
them since they do not exist in 8 bits.

Now at least it makes sense to use them, at the very least in order
to significantly reduce the code size (one BTS instead of a CMPXCHG
loop). The implementation relies on modern gcc's ability to return
condition flags and limit code inflation and register spilling. The
fall back is retained on the old implementation for all other situations
(inappropriate target size or non-capable compiler). The code shrank
by 1.6 kB on the fast path.

As expected, for now on up to 4 threads there is no measurable difference
of performance.
2021-04-07 18:47:22 +02:00
Willy Tarreau
fa68d2641b CLEANUP: atomic: use the __atomic variant of BTS/BTR on modern compilers
Probably due to the result of an old copy-paste, HA_ATOMIC_BTS/BTR were
still implemented using the __sync_*  builtins instead of the more
modern __atomic_* which allow to specify the memory model. Let's update
this to use the newer there and also implement the relaxed variants
(which are not used for now).
2021-04-07 18:18:37 +02:00
Willy Tarreau
4781b1521a CLEANUP: atomic/tree-wide: replace single increments/decrements with inc/dec
This patch replaces roughly all occurrences of an HA_ATOMIC_ADD(&foo, 1)
or HA_ATOMIC_SUB(&foo, 1) with the equivalent HA_ATOMIC_INC(&foo) and
HA_ATOMIC_DEC(&foo) respectively. These are 507 changes over 45 files.
2021-04-07 18:18:37 +02:00
Willy Tarreau
22d675cb77 CLEANUP: atomic: add HA_ATOMIC_INC/DEC for unit increments
Most ADD/SUB callers use them for a single unit (e.g. refcounts) and
it's a pain to always pass ",1". Let's add them to simplify the API.
However we currently don't add any return value. If needed in the future
better report zero/non-zero than a real value for the sake of efficiency
at the instruction level.
2021-04-07 18:18:37 +02:00
Willy Tarreau
185157201c CLEANUP: atomic: add a fetch-and-xxx variant for common operations
The fetch_and_xxx variant is often missing for add/sub/and/or. In fact
it was only provided for ADD under the name XADD which corresponds to
the x86 instruction name. But for destructive operations like AND and
OR it's missing even more as it's not possible to know the value before
modifying it.

This patch explicitly adds HA_ATOMIC_FETCH_{OR,AND,ADD,SUB} which
cover these standard operations, and renames XADD to FETCH_ADD (there
were only 6 call places).

In the future, backport of fixes involving such operations could simply
remap FETCH_ADD(x) to XADD(x), FETCH_SUB(x) to XADD(-x), and for the
OR/AND if needed, these could possibly be done using BTS/BTR.

It's worth noting that xchg could have been renamed to fetch_and_store()
but xchg already has well understood semantics and it wasn't needed to
go further.
2021-04-07 18:18:37 +02:00
Willy Tarreau
a477150fd7 CLEANUP: atomic: make all standard add/or/and/sub operations return void
In order to make sure these ones will not be used anymore in an expression,
let's make them always void. New callers will now be forced to use the
explicit _FETCH variant if required.
2021-04-07 18:18:37 +02:00
Willy Tarreau
1db427399c CLEANUP: atomic: add an explicit _FETCH variant for add/sub/and/or
Currently our atomic ops return a value but it's never known whether
the fetch is done before or after the operation, which causes some
confusion each time the value is desired. Let's create an explicit
variant of these operations suffixed with _FETCH to explicitly mention
that the fetch occurs after the operation, and make use of it at the
few call places.
2021-04-07 18:18:37 +02:00
Willy Tarreau
6756d95a8e MINOR: atomic/arm64: detect and use builtins for the double-word CAS
Gcc 10.2 implements outline atomics on aarch64. The replace all inline
atomic ops with a function call that checks if the machine supports LSE
atomics. This comes with a small cost but allows modern machines to scale
much better than with the old LL/SC ones even when built for full 8.0
compatibility.

This patch enables the use of the __atomic_compare_exchange() builtin
for the double-word CAS when detected as available instead of using the
hand-written LL/SC version. The extra cost is negligible because we do
very few DWCAS operations (essentially FD migrations and shared pools)
so the cost is low but under high contention it can still be beneficial.
As expected no performance difference was measured in either direction
on 4-core machines with this change.

This could be backported to 2.3 if it was shown that FD migrations were
representing a significant source of contention, but for now it does
not appear to be needed.
2021-04-07 18:18:37 +02:00
Willy Tarreau
1673c4a883 MINOR: fd: implement an exclusive syscall bit to remove the ugly "log" lock
There is a function called fd_write_frag_line() that's essentially used
by loggers and that is used to write an atomic message line over a file
descriptor using writev(). However a lock is required around the writev()
call to prevent messages from multiple threads from being interleaved.
Till now a SPIN_TRYLOCK was used on a dedicated lock that was common to
all FDs. This is quite not pretty as if there are multiple output pipes
to collect logs, there will be quite some contention. Now that there
are empty flags left in the FD state and that we can finally use atomic
ops on them, let's add a flag to indicate the FD is locked for exclusive
access by a syscall. At least the locking will now be on an FD basis and
not the whole process, so we can remove the log_lock.
2021-04-07 18:18:37 +02:00
Willy Tarreau
9063a660cc MINOR: fd: move .exported into fdtab[].state
No need to keep this flag apart any more, let's merge it into the global
state.
2021-04-07 18:10:36 +02:00
Willy Tarreau
5362bc9044 MINOR: fd: move .et_possible into fdtab[].state
No need to keep this flag apart any more, let's merge it into the global
state.
2021-04-07 18:09:43 +02:00
Willy Tarreau
0cc612818d MINOR: fd: move .initialized into fdtab[].state
No need to keep this flag apart any more, let's merge it into the global
state. The bit was not cleared in fd_insert() because the only user is
the function used to create and atomically send a log message to a pipe
FD, which never registers the fd. Here we clear it nevertheless for the
sake of clarity.

Note that with an extra cleaning pass we could have a bit number
here and simply use a BTS to test and set it.
2021-04-07 18:09:08 +02:00
Willy Tarreau
030dae13a0 MINOR: fd: move .cloned into fdtab[].state
No need to keep this flag apart any more, let's merge it into the global
state.
2021-04-07 18:08:29 +02:00
Willy Tarreau
b41a6e9101 MINOR: fd: move .linger_risk into fdtab[].state
No need to keep this flag apart any more, let's merge it into the global
state. The CLI's output state was extended to 6 digits and the linger/cloned
flags moved inside the parenthesis.
2021-04-07 18:07:49 +02:00
Willy Tarreau
f509065191 MEDIUM: fd: merge fdtab[].ev and state for FD_EV_* and FD_POLL_* into state
For a long time we've had fdtab[].ev and fdtab[].state which contain two
arbitrary sets of information, one is mostly the configuration plus some
shutdown reports and the other one is the latest polling status report
which also contains some sticky error and shutdown reports.

These ones used to be stored into distinct chars, complicating certain
operations and not even allowing to clearly see concurrent accesses (e.g.
fd_delete_orphan() would set the state to zero while fd_insert() would
only set the event to zero).

This patch creates a single uint with the two sets in it, still delimited
at the byte level for better readability. The original FD_EV_* values
remained at the lowest bit levels as they are also known by their bit
value. The next step will consist in merging the remaining bits into it.

The whole bits are now cleared both in fd_insert() and _fd_delete_orphan()
because after a complete check, it is certain that in both cases these
functions are the only ones touching these areas. Indeed, for
_fd_delete_orphan(), the thread_mask has already been zeroed before a
poller can call fd_update_event() which would touch the state, so it
is certain that _fd_delete_orphan() is alone. Regarding fd_insert(),
only one thread will get an FD at any moment, and it as this FD has
already been released by _fd_delete_orphan() by definition it is certain
that previous users have definitely stopped touching it.

Strictly speaking there's no need for clearing the state again in
fd_insert() but it's cheap and will remove some doubts during some
troubleshooting sessions.
2021-04-07 18:04:39 +02:00
Willy Tarreau
8d27c203ed MEDIUM: fd: prepare FD_POLL_* to move to bits 8-15
In preparation of merging FD_POLL* and FD_EV*, this only changes the
value of FD_POLL_* to use bits 8-15 (the second byte). The size of the
field has been temporarily extended to 32 bits already, as well as
the temporary variables that carry the new composite value inside
fd_update_events(). The resulting fdtab entry becomes temporarily
unaligned. All places making access to .ev or FD_POLL_* were carefully
inspected to make sure they were safe regarding this change. Only one
temporary update was needed for the "show fd" code. The code was only
slightly inflated at this step.
2021-04-07 15:08:40 +02:00
Willy Tarreau
fc0cdfb9b7 CLEANUP: fd: remove FD_POLL_DATA and FD_POLL_STICKY
The former was not used and the second was used only as a positive mask
of the flags to keep instead of having the flags that are updated. Both
were removed in favor of a new FD_POLL_UPDT_MASK that only mentions the
updated flags. This will ease merging of state and ev later.
2021-04-07 15:08:40 +02:00
Emeric Brun
9533a70381 MINOR: log: register config file and line number on log servers.
This patch registers the parsed file and the line where a log server
is declared to make those information available in configuration
post check.

Those new informations were added on error messages probed resolving
ring names on post configuration check.
2021-04-07 09:18:34 +02:00
Amaury Denoyelle
5a6926dcf0 MINOR: diag: create cfgdiag module
This module is intended to serve as a placeholder for various
diagnostics executed after the configuration file has been fully loaded.
2021-04-01 18:03:37 +02:00
Amaury Denoyelle
7b01a8dbdd MINOR: global: define diagnostic mode of execution
Define MODE_DIAG which is used to run haproxy in diagnostic mode. This
mode is used to output extra warnings about possible configuration
blunder or sub-optimal usage. It can be activated with argument '-dD'.

A new output function ha_diag_warning is implemented reserved for
diagnostic output. It serves to standardize the format of diagnostic
messages.

A macro HA_DIAG_WARN_COND is also available to automatically check if
diagnostic mode is on before executing the diagnostic check.
2021-04-01 18:03:37 +02:00
Christopher Faulet
021a8e4d7b MEDIUM: http-rules: Add wait-for-body action on request and response side
Historically, an option was added to wait for the request payload (option
http-buffer-request). This option has 2 drawbacks. First, it is an ON/OFF
option for the whole proxy. It cannot be enabled on demand depending on the
message. Then, as its name suggests, it only works on the request side. The
only option to wait for the response payload was to write a dedicated
filter. While it is an acceptable solution for complex applications, it is a
bit overkill to simply match strings in the body.

To make everyone happy, this patch adds a dedicated HTTP action to wait for
the message payload, for the request or the response depending it is used in
an http-request or an http-response ruleset. The time to wait is
configurable and, optionally, the minimum payload size to have before stop
to wait.

Both the http action and the old http analyzer rely on the same internal
function.
2021-04-01 16:27:40 +02:00
Christopher Faulet
581db2b829 MINOR: payload/config: Warn if a L6 sample fetch is used from an HTTP proxy
L6 sample fetches are now ignored when called from an HTTP proxy. Thus, a
warning is emitted during the startup if such usage is detected. It is true
for most ACLs and for log-format strings. Unfortunately, it is a bit painful
to do so for sample expressions.

This patch relies on the commit "MINOR: action: Use a generic function to
check validity of an action rule list".
2021-04-01 15:34:22 +02:00
Christopher Faulet
42c6cf9501 MINOR: action: Use a generic function to check validity of an action rule list
The check_action_rules() function is now used to check the validity of an
action rule list. It is used from check_config_validity() function to check
L5/6/7 rulesets.
2021-04-01 15:34:22 +02:00
Christopher Faulet
3b6446f4d9 MINOR: config/proxy: Don't warn for HTTP rules in TCP if 'switch-mode http' set
Warnings about ignored HTTP directives in a TCP proxy are inhibited if at
least one switch-mode tcp action is configured to perform HTTP upgraded.
2021-04-01 13:22:42 +02:00
Christopher Faulet
ae863c62e3 MEDIUM: Add tcp-request switch-mode action to perform HTTP upgrade
It is now possible to perform HTTP upgrades on a TCP stream from the
frontend side. To do so, a tcp-request content rule must be defined with the
switch-mode action, specifying the mode (for now, only http is supported)
and optionnaly the proto (h1 or h2).

This way it could be possible to set HTTP directives on a TCP frontend which
will only be evaluated if an upgrade is performed. This new way to perform
HTTP upgrades should replace progressively the old way, consisting to route
the request to an HTTP backend. And it should be also a good start to remove
all HTTP processing from tcp-request content rules.

This action is terminal, it stops the ruleset evaluation. It is only
available on proxy with the frontend capability.

The configuration manual has been updated accordingly.
2021-04-01 13:17:19 +02:00
Christopher Faulet
6c1fd987f6 MINOR: stream: Handle stream HTTP upgrade in a dedicated function
The code responsible to perform an HTTP upgrade from a TCP stream is moved
in a dedicated function, stream_set_http_mode().

The stream_set_backend() function is slightly updated, especially to
correctly set the request analysers.
2021-04-01 11:06:48 +02:00
Christopher Faulet
75f619ad92 MINOR: http-ana: Simplify creation/destruction of HTTP transactions
Now allocation and initialization of HTTP transactions are performed in a
unique function. Historically, there were two functions because the same TXN
was reset for K/A connections in the legacy HTTP mode. Now, in HTX, K/A
connections are handled at the mux level. A new stream, and thus a new TXN,
is created for each request. In addition, the function responsible to end
the TXN is now also reponsible to release it.

So, now, http_create_txn() and http_destroy_txn() must be used to create and
destroy an HTTP transaction.
2021-04-01 11:06:48 +02:00
Christopher Faulet
bb69d781c8 MINOR: muxes: Show muxes flags when the mux list is displayed
When the mux list is displayed on "haproxy -vv" output, the mux flags are
now diplayed. The flags meaning may be found in the configuration manual.
2021-04-01 11:06:48 +02:00
Christopher Faulet
a460057f2e MINOR: muxes: Add a flag to notify a mux does not support any upgrade
MX_FL_NO_UPG flag may now be set on a multiplexer to explicitly disable
upgrades from this mux. For now, it is set on the FCGI multiplexer because
it is not supported and there is no upgrade on backend-only multiplexers. It
is also set on the H2 multiplexer because it is clearly not supported.
2021-04-01 11:06:47 +02:00
Willy Tarreau
4bfc6630ba CLEANUP: socket: replace SOL_IP/IPV6/TCP with IPPROTO_IP/IPV6/TCP
Historically we've used SOL_IP/SOL_IPV6/SOL_TCP everywhere as the socket
level value in getsockopt() and setsockopt() but as we've seen over time
it regularly broke the build and required to have them defined to their
IPPROTO_* equivalent. The Linux ip(7) man page says:

   Using the SOL_IP socket options level isn't portable; BSD-based
   stacks use the IPPROTO_IP level.

And it indeed looks like a pure linuxism inherited from old examples and
documentation. strace also reports SOL_* instead of IPPROTO_*, which does
not help... A check to linux/in.h shows they have the same values. Only
SOL_SOCKET and other non-IP values make sense since there is no IPPROTO
equivalent.

Let's get rid of this annoying confusion by removing all redefinitions of
SOL_IP/IPV6/TCP and using IPPROTO_* instead, just like any other operating
system. This also removes duplicated tests for the same value.

Note that this should not result in exposing syscalls to other OSes
as the only ones that were still conditionned to SOL_IPV6 were for
IPV6_UNICAST_HOPS which already had an IPPROTO_IPV6 equivalent, and
IPV6_TRANSPARENT which is Linux-specific.
2021-03-31 08:59:34 +02:00
Willy Tarreau
be362fd992 MINOR: compat: add short aliases for a few very commonly used types
Very often we use "int" where negative numbers are not needed (and can
further cause trouble) just because it's painful to type "unsigned int"
or "unsigned", or ugly to use in function arguments. Similarly sometimes
chars would absolutely need to be signed but nobody types "signed char".
Let's add a few aliases for such types and make them part of the standard
internal API so that over time we can get used to them and get rid of
horrible definitions. A comment also reminds some commonly available
types and their properties regarding other types.
2021-03-26 17:54:15 +01:00
Willy Tarreau
2f836de100 MINOR: action: add a new ACT_F_CLI_PARSER origin designation
In order to process samples from the command line interface we'll need
rules as well, and these rules will have to be marked as coming from
the CLI parser. This new origin is used for this.
2021-03-26 16:34:53 +01:00
Willy Tarreau
db5e0dbea9 MINOR: sample: add a new CLI_PARSER context for samples
In order to prepare for supporting calling sample expressions from the
CLI, let's create a new CLI_PARSER parsing context. This one supports
constants and internal samples only.
2021-03-26 16:34:53 +01:00
Willy Tarreau
01d580ae86 MINOR: action: add a new ACT_F_CFG_PARSER origin designation
In order to process samples from the config file we'll need rules as
well, and these rules will have to be marked as coming from the
config parser. This new origin is used for this.
2021-03-26 16:23:45 +01:00
Willy Tarreau
f9a7a8fd8e MINOR: sample: add a new CFG_PARSER context for samples
We'd sometimes like to be able to process samples while parsing
the configuration based on purely internal thing but that's not
possible right now. Let's add a new CFG_PARSER context for samples
which only permits constant samples (i.e. those which do not change
in the process' life and which are stable during config parsing).
2021-03-26 16:23:45 +01:00
Willy Tarreau
be2159b946 MINOR: sample: add a new SMP_SRC_CONST sample capability
This level indicates that everything it constant in the expression during
the whole process' life and that it may safely be used at config parsing
time.
2021-03-26 16:23:45 +01:00
Willy Tarreau
77e6a4ef0f MINOR: sample: make smp_resolve_args() return an allocate error message
For now smp_resolve_args() complains on stderr via ha_alert(), but if we
want to make it a bit more dynamic, we need it to return errors in an
allocated message. Let's pass it an error pointer and have it fill it.
On return we indent the output if it contains more than one line.
2021-03-26 16:23:45 +01:00
Amaury Denoyelle
6f26faecd8 MINOR: proxy: define cap PR_CAP_LUA
Define a new cap PR_CAP_LUA. It can be used to allocate the internal
proxy for lua Socket class. This cap overrides default settings for
preferable values in the lua context.
2021-03-26 15:28:33 +01:00
Amaury Denoyelle
27fefa1967 MINOR: proxy: implement a free_proxy function
Move all liberation code related to a proxy in a dedicated function
free_proxy in proxy.c. For now, this function is only called in
haproxy.c. In the future, it will be used to free the lua proxy.

This helps to clean up haproxy.c.
2021-03-26 15:28:33 +01:00
Amaury Denoyelle
476b9ad97a REORG: split proxy allocation functions
Create a new function parse_new_proxy specifically designed to allocate
a new proxy from the configuration file and copy settings from the
default proxy.

The function alloc_new_proxy is reduced to a minimal allocation. It is
used for default proxy allocation and could also be used for internal
proxies such as the lua Socket proxy.
2021-03-26 15:28:33 +01:00
Amaury Denoyelle
68fd7e43d3 REORG: global: move free acl/action in their related source files
Move deinit_acl_cond and deinit_act_rules from haproxy.c respectively in
acl.c and action.c. The name of the functions has been slightly altered,
replacing the prefix deinit_* by free_* to reflect their purpose more
clearly.

This change has been made in preparation to the implementation of a free
proxy function. As a side-effect, it helps to clean up haproxy.c.
2021-03-26 15:28:33 +01:00
Amaury Denoyelle
ce44482fe5 REORG: global: move initcall register code in a dedicated file
Create a new module init which contains code related to REGISTER_*
macros for initcalls. init.h is included in api.h to make init code
available to all modules.

It's a step to clean up a bit haproxy.c/global.h.
2021-03-26 15:28:33 +01:00
Ilya Shipitsin
df627943a4 BUILD: ssl: introduce fine guard for ssl random extraction functions
SSL_get_{client,server}_random are supported in OpenSSL-1.1.0, BoringSSL,
LibreSSL-2.7.0

let us introduce HAVE_SSL_EXTRACT_RANDOM for that purpose
2021-03-26 15:19:07 +01:00
Remi Tricot-Le Breton
8218aed90e BUG/MINOR: ssl: Fix update of default certificate
The default SSL_CTX used by a specific frontend is the one of the first
ckch instance created for this frontend. If this instance has SNIs, then
the SSL context is linked to the instance through the list of SNIs
contained in it. If the instance does not have any SNIs though, then the
SSL_CTX is only referenced by the bind_conf structure and the instance
itself has no link to it.
When trying to update a certificate used by the default instance through
a cli command, a new version of the default instance was rebuilt but the
default SSL context referenced in the bind_conf structure would not be
changed, resulting in a buggy behavior in which depending on the SNI
used by the client, he could either use the new version of the updated
certificate or the original one.

This patch adds a reference to the default SSL context in the default
ckch instances so that it can be hot swapped during a certificate
update.

This should fix GitHub issue #1143.

It can be backported as far as 2.2.
2021-03-26 13:06:29 +01:00
Willy Tarreau
6cf13119e2 CLEANUP: fd: remove unused fd_set_running_excl()
This one is no longer used and was the origin of the previously mentioned
deadlock.
2021-03-24 17:17:21 +01:00
Willy Tarreau
2c3f9818e8 BUG/MEDIUM: fd: do not wait on FD removal in fd_delete()
Christopher discovered an issue mostly affecting 2.2 and to a less extent
2.3 and above, which is that it's possible to deadlock a soft-stop when
several threads are using a same listener:

          thread1                             thread2

      unbind_listener()                   fd_set_running()
          lock(listener)                  listener_accept()
          fd_delete()                          lock(listener)
             while (running_mask);  -----> deadlock
          unlock(listener)

This simple case disappeared from 2.3 due to the removal of some locked
operations at the end of listener_accept() on the regular path, but the
architectural problem is still here and caused by a lock inversion built
around the loop on running_mask in fd_clr_running_excl(), because there
are situations where the caller of fd_delete() may hold a lock that is
preventing other threads from dropping their bit in running_mask.

The real need here is to make sure the last user deletes the FD. We have
all we need to know the last one, it's the one calling fd_clr_running()
last, or entering fd_delete() last, both of which can be summed up as
the last one calling fd_clr_running() if fd_delete() calls fd_clr_running()
at the end. And we can prevent new threads from appearing in running_mask
by removing their bits in thread_mask.

So what this patch does is that it sets the running_mask for the thread
in fd_delete(), clears the thread_mask, thus marking the FD as orphaned,
then clears the running mask again, and completes the deletion if it was
the last one. If it was not, another thread will pass through fd_clr_running
and will complete the deletion of the FD.

The bug is easily reproducible in 2.2 under high connection rates during
soft close. When the old process stops its listener, occasionally two
threads will deadlock and the old process will then be killed by the
watchdog. It's strongly believed that similar situations do exist in 2.3
and 2.4 (e.g. if the removal attempt happens during resume_listener()
called from listener_accept()) but if so, they should be much harder to
trigger.

This should be backported to 2.2 as the issue appeared with the FD
migration. It requires previous patches "fd: make fd_clr_running() return
the remaining running mask" and "MINOR: fd: remove the unneeded running
bit from fd_insert()".

Notes for backport: in 2.2, the fd_dodelete() function requires an extra
argument "do_close" indicating whether we want to remove and close the FD
(fd_delete) or just delete it (fd_remove). While this information is not
conveyed along the chain, we know that late calls always imply do_close=1
become do_close=0 exclusively results from fd_remove() which is only used
by the config parser and the master, both of which are single-threaded,
hence are always the last ones in the running_mask. Thus it is safe to
assume that a postponed FD deletion always implies do_close=1.

Thanks to Olivier for his help in designing this optimal solution.
2021-03-24 17:17:21 +01:00
Willy Tarreau
71bada5ca4 MINOR: fd: remove the unneeded running bit from fd_insert()
There's no point taking the running bit in fd_insert() since by
definition there will never be more than one thread inserting the FD,
and that fd_insert() may only be done after the fd was allocated by
the system, indicating the end of use by any other thread.

This will need to be backported to 2.2 to fix an issue.
2021-03-24 17:17:21 +01:00
Willy Tarreau
6e8e10b415 MINOR: fd: make fd_clr_running() return the remaining running mask
We'll need to know that a thread is the last one to use an fd, so let's
make fd_clr_running() return the remaining bits after removal. Note that
in practice we're only interested in knowing if it's zero but the compiler
doesn't make use of the clags after the AND and emits a CMPXCHG anyway :-/

This will need to be backported to 2.2 to fix an issue.
2021-03-24 17:17:21 +01:00
Christopher Faulet
cc2c4f8f4c BUG/MEDIUM: debug/lua: Use internal hlua function to dump the lua traceback
The commit reverts following commits:
  * 83926a04 BUG/MEDIUM: debug/lua: Don't dump the lua stack if not dumpable
  * a61789a1 MEDIUM: lua: Use a per-thread counter to track some non-reentrant parts of lua

Instead of relying on a Lua function to print the lua traceback into the
debugger, we are now using our own internal function (hlua_traceback()).
This one does not allocate memory and use a chunk instead. This avoids any
issue with a possible deadlock in the memory allocator because the thread
processing was interrupted during a memory allocation.

This patch relies on the commit "BUG/MEDIUM: debug/lua: Use internal hlua
function to dump the lua traceback". Both must be backported wherever the
patches above are backported, thus as far as 2.0
2021-03-24 16:35:23 +01:00
Christopher Faulet
d09cc519bd MINOR: lua: Slightly improve function dumping the lua traceback
The separator string is now configurable, passing it as parameter when the
function is called. In addition, the message have been slightly changed to
be a bit more readable.
2021-03-24 16:33:26 +01:00
Ilya Shipitsin
8cd1627599 CLEANUP: ssl: remove unused definitions
not need since 	e7eb1fec2f
2021-03-24 09:52:32 +01:00
Remi Tricot-Le Breton
fb00f31af4 BUG/MINOR: ssl: Prevent disk access when using "add ssl crt-list"
If an unknown CA file was first mentioned in an "add ssl crt-list" CLI
command, it would result in a call to X509_STORE_load_locations which
performs a disk access which is forbidden during runtime. The same would
happen if a "ca-verify-file" or "crl-file" was specified. This was due
to the fact that the crt-list file parsing and the crt-list related CLI
commands parsing use the same functions.
The patch simply adds a new parameter to all the ssl_bind parsing
functions so that they know if the call is made during init or by the
CLI, and the ssl_store_load_locations function can then reject any new
cafile_entry creation coming from a CLI call.

It can be backported as far as 2.2.
2021-03-23 19:29:46 +01:00
Emeric Brun
69ba35146f MINOR: tools: introduce new option PA_O_DEFAULT_DGRAM on str2sa_range.
str2sa_range function options PA_O_DGRAM and PA_O_STREAM are used to
define the supported address types but also to set the default type
if it is not explicit. If the used address support both STREAM and DGRAM,
the default was always set to STREAM.

This patch introduce a new option PA_O_DEFAULT_DGRAM to force the
default to DGRAM type if it is not explicit in the address field
and both STREAM and DGRAM are supported. If only DGRAM or only STREAM
is supported, it continues to be considered as the default.
2021-03-23 15:32:22 +01:00
Willy Tarreau
8cc586c73f BUG/MEDIUM: freq_ctr/threads: use the global_now_ms variable
In commit a1ecbca0a ("BUG/MINOR: freq_ctr/threads: make use of the last
updated global time"), for period-based counters, the millisecond part
of the global_now variable was used as the date for the new period. But
it's wrong, it only works with sub-second periods as it wraps every
second, and for other periods the counters never rotate anymore.

Let's make use of the newly introduced global_now_ms variable instead,
which contains the global monotonic time expressed in milliseconds.

This patch needs to be backported wherever the patch above is backported.
It depends on previous commit "MINOR: time: also provide a global,
monotonic global_now_ms timer".
2021-03-23 09:03:37 +01:00
Willy Tarreau
6064b34be0 MINOR: time: also provide a global, monotonic global_now_ms timer
The period-based freq counters need the global date in milliseconds,
so better calculate it and expose it rather than letting all call
places incorrectly retrieve it.

Here what we do is that we maintain a new globally monotonic timer,
global_now_ms, which ought to be very close to the global_now one,
but maintains the monotonic approach of now_ms between all threads
in that global_now_ms is always ahead of any now_ms.

This patch is made simple to ease backporting (it will be needed for
a subsequent fix), but it also opens the way to some simplifications
on the time handling: instead of computing the local time and trying
to force it to the global one, we should soon be able to proceed in
the opposite way, that is computing the new global time an making the
local one just the latest snapshot of it. This will bring the benefit
of making sure that the global time is always ahead of the local one.
2021-03-23 09:01:37 +01:00
Willy Tarreau
5d110b25dd CLEANUP: connection: use pool_zalloc() in conn_alloc_hash_node()
This one used to alloc then zero the area, let's have the allocator do it.
2021-03-22 23:17:24 +01:00
Willy Tarreau
18759079b6 MINOR: pools: add pool_zalloc() to return a zeroed area
It's like pool_alloc() but the output is zeroed before being returned
and is never poisonned.
2021-03-22 22:05:05 +01:00
Willy Tarreau
de749a9333 MINOR: pools: make the pool allocator support a few flags
The pool_alloc_dirty() function was renamed to __pool_alloc() and now
takes a set of flags indicating whether poisonning is permitted or not
and whether zeroing the area is needed or not. The pool_alloc() function
is now just a wrapper calling __pool_alloc(pool, 0).
2021-03-22 20:54:15 +01:00
Willy Tarreau
a213b683f7 CLEANUP: pools: remove the unused pool_get_first() function
This one used to maintain a shortcut in the pools allocation path that
was only justified by b_alloc_fast() which was not used! Let's get rid
of it as well so that the allocator becomes a bit more straight forward.
2021-03-22 16:28:08 +01:00
Willy Tarreau
7be7ffac15 CLEANUP: dynbuf: remove the unused b_alloc_fast() function
It is never used anymore since 1.7 where it was used by b_alloc_margin()
then replaced by direct calls to the pools function, and it maintains a
dependency on the exposed pools functions. It's time to get rid of it,
as it's not even certain it still works.
2021-03-22 16:28:05 +01:00
Willy Tarreau
f44ca97fcb CLEANUP: dynbuf: remove b_alloc_margin()
It's not used anymore, let's completely remove it before anyone uses it
again by accident.
2021-03-22 16:28:02 +01:00
Willy Tarreau
0f495b3d87 MINOR: channel: simplify the channel's buffer allocation
The channel's buffer allocator, channel_alloc_buffer(), was still relying
on the principle of a margin for the request and not for the response.
But this margin stopped working around 1.7 with the introduction of the
content filters such as SPOE, and was completely anihilated with the
local pools that came with threads. Let's simplify this and just use
b_alloc().
2021-03-22 16:19:45 +01:00
Willy Tarreau
766b6cf206 MINOR: dynbuf: make b_alloc() always check if the buffer is allocated
Right now there is a discrepancy beteween b_alloc() and b_allow_margin():
the former forcefully overwrites the target pointer while the latter tests
it and returns it as-is if already allocated.

As a matter of fact, all callers of b_alloc() either preliminary test the
buffer, or assume it's already null.

Let's remove this pain and make the function test the buffer's allocation
before doing it again, and match call places' expectations.
2021-03-22 16:14:45 +01:00
Christopher Faulet
a61789a1d6 MEDIUM: lua: Use a per-thread counter to track some non-reentrant parts of lua
Some parts of the Lua are non-reentrant. We must be sure to carefully track
these parts to not dump the lua stack when it is interrupted inside such
parts. For now, we only identified the custom lua allocator. If the thread
is interrupted during the memory allocation, we must not try to print the
lua stack wich also allocate memory. Indeed, realloc() is not
async-signal-safe.

In this patch we introduce a thread-local counter. It is incremented before
entering in a non-reentrant part and decremented when exiting. It is only
performed in hlua_alloc() for now.
2021-03-19 16:16:23 +01:00
Olivier Houchard
dae6975498 MINOR: muxes: garbage collect the reset() method.
Now that connections aren't being reused when they failed, remove the
reset() method. It was unimplemented anywhere, except for H1 where it did
nothing, anyway.
2021-03-19 15:33:04 +01:00
Olivier Houchard
1b3c931bff MEDIUM: connections: Introduce a new XPRT method, start().
Introduce a new XPRT method, start(). The init() method will now only
initialize whatever is needed for the XPRT to run, but any action the XPRT
has to do before being ready, such as handshakes, will be done in the new
start() method. That way, we will be sure the full stack of xprt will be
initialized before attempting to do anything.
The init() call is also moved to conn_prepare(). There's no longer any reason
to wait for the ctrl to be ready, any action will be deferred until start(),
anyway. This means conn_xprt_init() is no longer needed.
2021-03-19 15:33:04 +01:00
Amaury Denoyelle
216a1ce3b9 MINOR: stats: export function to allocate extra proxy counters
Remove static qualifier on stats_allocate_proxy_counters_internal. This
function will be used to allocate extra counters at runtime for dynamic
servers.
2021-03-18 15:52:07 +01:00
Amaury Denoyelle
76e10e78bb MINOR: server: prepare parsing for dynamic servers
Prepare the server parsing API to support dynamic servers.
- define a new parsing flag to be used for dynamic servers
- each keyword contains a new field dynamic_ok to indicate if it can be
  used for a dynamic server. For now, no keyword are supported.
- do not copy settings from the default server for a new dynamic server.
- a dynamic server is created in a maintenance mode and requires an
  explicit 'enable server' command.
- a new server flag named SRV_F_DYNAMIC is created. This flag is set for
  all servers created at runtime. It might be useful later, for example
  to know if a server can be purged.
2021-03-18 15:51:12 +01:00