]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
4 years agoMEDIUM: receivers: add an rx_unbind() method in the protocols
Willy Tarreau [Fri, 9 Oct 2020 14:32:08 +0000 (16:32 +0200)] 
MEDIUM: receivers: add an rx_unbind() method in the protocols

This is used as a generic way to unbind a receiver at the end of
do_unbind_listener(). This allows to considerably simplify that function
since we can now let the protocol perform the cleanup. The generic code
was moved to sock.c, along with the conditional rx_disable() call. Now
the code also supports that the ->disable() function of the protocol
which acts on the listener performs the close itself and adjusts the
RX_F_BUOND flag accordingly.

4 years agoMINOR: listeners: move the LI_O_MWORKER flag to the receiver
Willy Tarreau [Fri, 9 Oct 2020 14:11:46 +0000 (16:11 +0200)] 
MINOR: listeners: move the LI_O_MWORKER flag to the receiver

This listener flag indicates whether the receiver part of the listener
is specific to the master or to the workers. In practice it's only used
by the master's CLI right now. It's used to know whether or not the FD
must be closed before forking the workers. For this reason it's way more
of a receiver's property than a listener's property, so let's move it
there under the name RX_F_MWORKER. The rest of the code remains
unchanged.

4 years agoCLEANUP: listeners: remove the do_close argument to unbind_listener()
Willy Tarreau [Fri, 9 Oct 2020 13:55:23 +0000 (15:55 +0200)] 
CLEANUP: listeners: remove the do_close argument to unbind_listener()

And also remove it from its callers. This subtle distinction was added as
sort of a hack for the seamless reload feature but is not needed anymore
since the do_close turned unused since commit previous commit ("MEDIUM:
listener: let do_unbind_listener() decide whether to close or not").
This also removes the unbind_listener_no_close() function.

4 years agoMEDIUM: listener: let do_unbind_listener() decide whether to close or not
Willy Tarreau [Fri, 9 Oct 2020 13:47:17 +0000 (15:47 +0200)] 
MEDIUM: listener: let do_unbind_listener() decide whether to close or not

The listener contains all the information needed to decide to close on
unbind or not. The rule is the following (when we're not stopping):

  - worker process unbinding from a worker's FD with socket transfer enabled => keep
  - master process unbinding from a master's inherited FD => keep
  - master process unbinding from a master's FD => close
  - master process unbinding from a worker's FD => close
  - worker process unbinding from a master's FD => close
  - worker process unbinding from a worker's FD => close

Let's translate that into the function and stop using the do_close
argument that is a bit obscure for callers. It was not yet removed
to ease code testing.

4 years agoBROKEN/MEDIUM: listeners: rework the unbind logic to make it idempotent
Willy Tarreau [Thu, 8 Oct 2020 13:36:46 +0000 (15:36 +0200)] 
BROKEN/MEDIUM: listeners: rework the unbind logic to make it idempotent

BROKEN: the failure rate on reg-tests/seamless-reload/abns_socket.vtc has
significantly increased for no obvious reason. It fails 99% of the time vs
10% before.

do_unbind_listener() is not logical and is not even idempotent. It must
not touch the fd if already -1, which also means not touch the receiver.
In addition, when performing a partial stop on a socket (not closing),
we know the socket remains in the listening state yet it's marked as
LI_ASSIGNED, which is confusing as it doesn't translate its real state.

With this change, we make sure that FDs marked for close end up in
ASSIGNED state and that those which are really bound and on which a
listen() was made (i.e. not pause) remain in LISTEN state. This is what
is closest to reality.

Ideally this function should become a default proto->unbind() one but
it may still keep a bit too much state logic to become generalized to
other protocols (e.g. QUIC).

4 years agoMEDIUM: listeners: always close master vs worker listeners
Willy Tarreau [Fri, 9 Oct 2020 08:35:40 +0000 (10:35 +0200)] 
MEDIUM: listeners: always close master vs worker listeners

Right now in enable_listener(), we used to start all enabled
listeners then kill from the workers those that were for the master.
But this is incomplete. We must also close from the master the
listeners that are solely for workers, and do it before we even
start them. Otherwise we end up with a master responding to the
worker CLI connections if the listener remains in listen mode to
translate the socket's real state.

It doesn't seem like it could have caused bugs in the past because we
used to aggressively mark disabled listeners as LI_ASSIGNED despite
the fact that they were still bound and listening. If this patch were
ever seen as a candidate solution for any obscure bug, be careful in
that it subtly relies on the fact that fd_delete() doesn't close
inherited FDs anymore, otherwise that could break the master's ability
to pass inherited FDs on reloads.

4 years agoMINOR: listener: add a few BUG_ON() statements to detect inconsistencies
Willy Tarreau [Thu, 8 Oct 2020 13:32:21 +0000 (15:32 +0200)] 
MINOR: listener: add a few BUG_ON() statements to detect inconsistencies

We must not have an fd==-1 when switching to certain states. This will
later disappear but for now it helps detecting inconsistencies.

4 years agoMEDIUM: udp: implement udp_suspend() and udp_resume()
Willy Tarreau [Wed, 7 Oct 2020 17:55:15 +0000 (19:55 +0200)] 
MEDIUM: udp: implement udp_suspend() and udp_resume()

In Linux kernel's net/ipv4/udp.c there's a udp_disconnect() function
which is called when connecting to AF_UNSPEC, and which unhashes a
"connection". This property, which is also documented in connect(2)
both in Linux and Open Group's man pages for datagrams, is interesting
because it allows to reverse a connect() which is in fact a filter on
the source. As such we can suspend a receiver by making it connect to
itself, which will cause it not to receive any traffic anymore, letting
a new one receive it all, then resume it by breaking this connection.

This was tested to work well on Linux, other operating systems should
also be tested. Before this, sending a SIGTTOU to a process having a
UDP syslog forwarder would cause this error:

  [WARNING] 280/194249 (3268) : Paused frontend GLOBAL.
  [WARNING] 280/194249 (3268) : Some proxies refused to pause, performing soft stop now.
  [WARNING] 280/194249 (3268) : Proxy GLOBAL stopped (cumulated conns: FE: 0, BE: 0).
  [WARNING] 280/194249 (3268) : Proxy sylog-loadb stopped (cumulated conns: FE: 0, BE: 0).

With this change, it now proceeds just like with TCP listeners:

  [WARNING] 280/195503 (3885) : Paused frontend GLOBAL.
  [WARNING] 280/195503 (3885) : Paused frontend sylog-loadb.

And SIGTTIN also works:

  [WARNING] 280/195507 (3885) : Resumed frontend GLOBAL.
  [WARNING] 280/195507 (3885) : Resumed frontend sylog-loadb.

On Linux this also works with TCP listeners (which can then be resumed
using listen()) and established TCP sockets (which we currently kill
using setsockopt(so_linger)), both not being portable on other OSes.
UNIX sockets and ABNS sockets do not support it however (connect
always fails). This needs to be further explored to see if other OSes
might benefit from this to perform portable and reliable resets
particularly on the backend side.

4 years agoMEDIUM: proxy: make soft_stop() stop most listeners using protocol_stop_now()
Willy Tarreau [Wed, 7 Oct 2020 14:52:43 +0000 (16:52 +0200)] 
MEDIUM: proxy: make soft_stop() stop most listeners using protocol_stop_now()

One difficulty in soft-stopping is to make sure not to forget unlisted
listeners. By first doing a pass using protocol_stop_now() we catch the
vast majority of them. The few remaining ones are the ones belonging to
a proxy having a grace period. For these ones, the proxy will arm its
stop_time timer and emit a log message.

Since neither UDP listeners nor peers use the grace period, we can already
get rid of the special cases there since we know they will have been stopped
by the protocols.

4 years agoMINOR: protocol: add protocol_stop_now() to instant-stop listeners
Willy Tarreau [Wed, 7 Oct 2020 14:50:49 +0000 (16:50 +0200)] 
MINOR: protocol: add protocol_stop_now() to instant-stop listeners

This will instantly stop all listeners except those which belong to
a proxy configured with a grace time. This means that UDP listeners,
and peers will also be stopped when called this way.

4 years agoMEDIUM: proxy: centralize proxy status update and reporting
Willy Tarreau [Wed, 7 Oct 2020 14:31:39 +0000 (16:31 +0200)] 
MEDIUM: proxy: centralize proxy status update and reporting

There are multiple ways a proxy may switch to the disabled state,
but now it's essentially once it loses its last listener. Instead
of keeping duplicate code around and reporting the state change
before actually seeing it, we now report it at the moment it's
performed (from the last listener leaving) which allows to remove
the message from all other places.

4 years agoMEDIUM: proxy: add mode PR_MODE_PEERS to flag peers frontends
Willy Tarreau [Wed, 7 Oct 2020 15:49:42 +0000 (17:49 +0200)] 
MEDIUM: proxy: add mode PR_MODE_PEERS to flag peers frontends

For now we cannot easily distinguish a peers frontend from another one,
which will be problematic to avoid reporting them when stopping their
listeners. Let's add PR_MODE_PEERS for this. It's not supposed to cause
any issue since all non-HTTP proxies are handled similarly now.

4 years agoMEDIUM: proxy: make stop_proxy() now use stop_listener()
Willy Tarreau [Wed, 7 Oct 2020 14:20:34 +0000 (16:20 +0200)] 
MEDIUM: proxy: make stop_proxy() now use stop_listener()

The function will stop the listeners using this method, which in turn will
ping back once it finishes disabling the proxy.

4 years agoMINOR: listeners: add a new stop_listener() function
Willy Tarreau [Wed, 7 Oct 2020 13:58:50 +0000 (15:58 +0200)] 
MINOR: listeners: add a new stop_listener() function

This function will be used to definitely stop a listener (e.g. during a
soft_stop). This is actually tricky because it may be called for a proxy
or for a protocol, both of which require locks and already hold some. The
function takes booleans indicating which ones are already held, hoping
this will be enough. It's not well defined wether proto->disable() and
proto->rx_disable() are supposed to be called with any lock held, and
they are used from do_unbind_listener() with all these locks. Some back
annotations ought to be added on this point.

The proxy's listeners count is updated, and the proxy is marked as
disabled and woken up after the last one is gone. Note that a
listener in listen state is already not attached anymore since it
was disabled.

4 years agoMINOR: listeners: count unstoppable jobs on creation, not deletion
Willy Tarreau [Fri, 9 Oct 2020 16:25:14 +0000 (18:25 +0200)] 
MINOR: listeners: count unstoppable jobs on creation, not deletion

We have to count unstoppable jobs which correspond to worker sockpairs, in
order to know when to count. However the way it's currently done is quite
awkward because these are counted when stopping making the stop mechanism
non-idempotent. This is definitely something we want to fix before stopping
by protocol or our listeners count will quickly go wrong. Now they are
counted when the listeners are created.

4 years agoMINOR: listeners: split delete_listener() in two versions
Willy Tarreau [Wed, 7 Oct 2020 13:36:16 +0000 (15:36 +0200)] 
MINOR: listeners: split delete_listener() in two versions

We'll need an already locked variant of this function so let's make
__delete_listener() which will be called with the protocol lock held
and the listener's lock held.

4 years agoMEDIUM: listeners: now use the listener's ->enable/disable
Willy Tarreau [Fri, 25 Sep 2020 18:32:28 +0000 (20:32 +0200)] 
MEDIUM: listeners: now use the listener's ->enable/disable

At each place we used to manipulate the FDs directly we can now call
the listener protocol's enable/disable/rx_enable/rx_disable depending
on whether the state changes on the listener or the receiver. One
exception currently remains in listener_accept() which is a bit special
and which should be split into 2 or 3 parts in the various protocol
layers.

The test of fd_updt in do_unbind_listener() that was added by commit
a51885621 ("BUG/MEDIUM: listeners: Don't call fd_stop_recv() if fd_updt
is NULL.") could finally be removed since that part is correctly handled
in the low-level disable() function.

One disable() was added in resume_listener() before switching to LI_FULL
because rx_resume() enables polling on the FD for the receiver while
we want to disable it if the listener is full. There are different
ways to clean this up in the future. One of them could be to consider
that TCP receivers only act at the listener level. But in fact it does
not translate reality. The reality is that only the receiver is paused
and that the listener's state ought not be affected here. Ultimately
the resume_listener() function should be split so that the part
controlled by the protocols only acts on the receiver, and that the
receiver itself notifies the upper listener about the change so that
the listener protocol may decide to disable or enable polling. Conversely
the listener should automatically update its receiver when they share the
same state. Since there is no harm proceeding like this, let's keep this
for now.

4 years agoMINOR: protocol: add a new pair of enable/disable methods for listeners
Willy Tarreau [Fri, 25 Sep 2020 17:27:39 +0000 (19:27 +0200)] 
MINOR: protocol: add a new pair of enable/disable methods for listeners

These methods will be used to enable/disable accepting new connections
so that listeners do not play with FD directly anymore. Since all the
currently supported protocols work on socket for now, these are identical
to the rx_enable/rx_disable functions. However they were not defined in
sock.c since it's likely that some will quickly start to differ. At the
moment they're not used.

We have to take care of fd_updt before calling fd_{want,stop}_recv()
because it's allocated fairly late in the boot process and some such
functions may be called very early (e.g. to stop a disabled frontend's
listeners).

4 years agoMINOR: protocol: add a new pair of rx_enable/rx_disable methods
Willy Tarreau [Fri, 25 Sep 2020 17:09:53 +0000 (19:09 +0200)] 
MINOR: protocol: add a new pair of rx_enable/rx_disable methods

These methods will be used to enable/disable rx at the receiver level so
that callers don't play with FDs directly anymore. All our protocols use
the generic ones from sock.c at the moment. For now they're not used.

4 years agoMINOR: sock: provide a set of generic enable/disable functions
Willy Tarreau [Fri, 25 Sep 2020 17:00:01 +0000 (19:00 +0200)] 
MINOR: sock: provide a set of generic enable/disable functions

These will be used on receivers, to enable or disable receiving on a
listener, which most of the time just consists in enabling/disabling
the file descriptor.

We have to take care of the existence of fd_updt to know if we may
or not call fd_{want,stop}_recv() since it's not permitted in very
early boot.

4 years agoMINOR: listener: use the protocol's ->rx_resume() method when available
Willy Tarreau [Fri, 25 Sep 2020 15:31:05 +0000 (17:31 +0200)] 
MINOR: listener: use the protocol's ->rx_resume() method when available

Instead of calling listen() for IPPROTO_TCP in resume_listener(), let's
call the protocol's ->rx_resume() method when defined, which does the same.
This removes another hard-dependency on the fd and underlying protocol
from the generic functions.

4 years agoMINOR: protocol: implement an ->rx_resume() method
Willy Tarreau [Fri, 25 Sep 2020 17:40:31 +0000 (19:40 +0200)] 
MINOR: protocol: implement an ->rx_resume() method

This one undoes ->rx_suspend(), it tries to restore an operational socket.
It was only implemented for TCP since it's the only one we support right
now.

4 years agoMINOR: protocol: replace ->pause(listener) with ->rx_suspend(receiver)
Willy Tarreau [Fri, 25 Sep 2020 15:12:32 +0000 (17:12 +0200)] 
MINOR: protocol: replace ->pause(listener) with ->rx_suspend(receiver)

The ->pause method is inappropriate since it doesn't exactly "pause" a
listener but rather temporarily disables it so that it's not visible at
all to let another process take its place. The term "suspend" is more
suitable, since the "pause" is actually what we'll need to apply to the
FULL and LIMITED states which really need to make a pause in the accept
process. And it goes well with the use of the "resume" function that
will also need to be made per-protocol.

Let's rename the function and make it act on the receiver since it's
already what it essentially does, hence the prefix "_rx" to make it
more explicit.

The protocol struct was a bit reordered because it was becoming a real
mess between the parts related to the listeners and those for the
receivers.

4 years agoMINOR: protocol: rename the ->listeners field to ->receivers
Willy Tarreau [Fri, 25 Sep 2020 15:01:43 +0000 (17:01 +0200)] 
MINOR: protocol: rename the ->listeners field to ->receivers

Since the listeners were split into receiver+listener, this field ought
to have been renamed because it's confusing. It really links receivers
and not listeners, as most of the time it's used via rx.proto_list!
The nb_listeners field was updated accordingly.

4 years agoCLEANUP: listeners: remove the now unused enable_all_listeners()
Willy Tarreau [Fri, 25 Sep 2020 14:46:38 +0000 (16:46 +0200)] 
CLEANUP: listeners: remove the now unused enable_all_listeners()

It's not used anymore since previous commit. The good thing is that
no more listener function now directly acts on a protocol.

4 years agoCLEANUP: protocol: remove the ->enable_all method
Willy Tarreau [Fri, 25 Sep 2020 14:45:12 +0000 (16:45 +0200)] 
CLEANUP: protocol: remove the ->enable_all method

It's not used anymore, now the listeners are enabled from
protocol_enable_all().

4 years agoMINOR: protocol: directly call enable_listener() from protocol_enable_all()
Willy Tarreau [Fri, 25 Sep 2020 14:41:05 +0000 (16:41 +0200)] 
MINOR: protocol: directly call enable_listener() from protocol_enable_all()

protocol_enable_all() calls proto->enable_all() for all protocols,
which is always equal to enable_all_listeners() which in turn simply is
a generic loop calling enable_listener() always returning ERR_NONE. Let's
clean this madness by first calling enable_listener() directly from
protocol_enable_all().

4 years agoMINOR: listeners: export enable_listener()
Willy Tarreau [Fri, 25 Sep 2020 14:40:18 +0000 (16:40 +0200)] 
MINOR: listeners: export enable_listener()

we'll soon call it from outside.

4 years agoCLEANUP: listeners: remove unused disable_listener and disable_all_listeners
Willy Tarreau [Fri, 25 Sep 2020 14:31:30 +0000 (16:31 +0200)] 
CLEANUP: listeners: remove unused disable_listener and disable_all_listeners

These ones have never been called, they were referenced by the protocol's
disable_all for some protocols but there are no traces of their use, so
in addition to not being sure the code works, it has never been tested.
Let's remove a bit of complexity starting from there.

4 years agoCLEANUP: protocol: remove the ->disable_all method
Willy Tarreau [Fri, 25 Sep 2020 14:30:22 +0000 (16:30 +0200)] 
CLEANUP: protocol: remove the ->disable_all method

This one has never been used, is only referenced by proto_uxst and
proto_sockpair, and it's not even certain it works at all. Let's
get rid of it.

4 years agoMINOR: listeners: move fd_stop_recv() to the receiver's socket code
Willy Tarreau [Thu, 24 Sep 2020 16:20:37 +0000 (18:20 +0200)] 
MINOR: listeners: move fd_stop_recv() to the receiver's socket code

fd_stop_recv() has nothing to do in the generic listener code, it's per
protocol as some don't need it. For instance with abns@ it could even
lead to fd_stop_recv(-1). And later with QUIC we don't want to touch
the fd at all! It used to be that since commit f2cb169487 delegating
fd manipulation to their respective threads it wasn't possible to call
it down there but it's not the case anymore, so let's perform the action
in the protocol-specific code.

4 years agoBUG/MEDIUM: listeners: correctly report pause() errors
Willy Tarreau [Thu, 24 Sep 2020 16:07:48 +0000 (18:07 +0200)] 
BUG/MEDIUM: listeners: correctly report pause() errors

By using the same "ret" variable in the "if" block to test the return
value of pause(), the second one shadows the first one and when forcing
the result to zero in case of an error, it doesn't do anything. The
problem is that some listeners used to fail to pause in multi-process
mode and this was not reported, but their failure was automatically
resolved by the last process to pause. By properly checking for errors
we might now possibly report a race once in a while so we may have to
roll this back later if some users meet it.

The test on ==0 is wrong too since technically speaking a total stop
validates the need for a pause, but stops the listener so it's just
the resume that won't work anymore. We could switch to stopped but
it's an involuntary switch and the user will not know. Better then
mark it as paused and let the resume continue to fail so that only
the resume will eventually report an error (e.g. abns@).

This must not be backported as there is a risk of side effect by fixing
this bug, given that it hides other bugs itself.

4 years agoMEDIUM: proto_tcp: make the pause() more robust in multi-process
Willy Tarreau [Thu, 8 Oct 2020 14:51:09 +0000 (16:51 +0200)] 
MEDIUM: proto_tcp: make the pause() more robust in multi-process

In multi-process, the TCP pause is very brittle and we never noticed
it because the error was lost in the upper layers. The problem is that
shutdown() may fail if another process already did it, and will cause
a process to fail to pause.

What we do here in case of error is that we double-check the socket's
state to verify if it's still accepting connections, and if not, we
can conclude that another process already did the job in parallel.

The difficulty here is that we're trying to eliminate false positives
where some OSes will silently report a success on shutdown() while they
don't shut the socket down, hence this dance of shutw/listen/shutr that
only keeps the compatible ones. Probably that a new approach relying on
connect(AF_UNSPEC) would provide better results.

4 years agoCLEANUP: proxy: remove the now unused pause_proxies() and resume_proxies()
Willy Tarreau [Thu, 24 Sep 2020 14:42:00 +0000 (16:42 +0200)] 
CLEANUP: proxy: remove the now unused pause_proxies() and resume_proxies()

They're not used anymore, delete them before someone thinks about using
them again!

4 years agoMAJOR: signals: use protocol_pause_all() and protocol_resume_all()
Willy Tarreau [Thu, 24 Sep 2020 14:36:26 +0000 (16:36 +0200)] 
MAJOR: signals: use protocol_pause_all() and protocol_resume_all()

When temporarily pausing the listeners with SIG_TTOU, we now pause
all listeners via the protocols instead of the proxies. This has the
benefits that listeners are paused regardless of whether or not they
belong to a visible proxy. And for resuming via SIG_TTIN we do the
same, which allows to report binding conflicts and address them,
since the operation can be repeated on a per-listener basis instead
of a per-proxy basis.

While in appearance all cases were properly handled, it's impossible
to completely rule out the possibility that something broken used to
work by luck due to the scan ordering which is naturally different,
hence the major tag.

4 years agoMINOR: protocol: introduce protocol_{pause,resume}_all()
Willy Tarreau [Thu, 24 Sep 2020 14:26:50 +0000 (16:26 +0200)] 
MINOR: protocol: introduce protocol_{pause,resume}_all()

These two functions are used to pause and resume all listeners of
all protocols. They use the standard listener functions for this
so they're supposed to handle the situation gracefully regardless
of the upper proxies' states, and they will report completion on
proxies once the switch is performed.

It might be nice to define a particular "failed" state for listeners
that cannot resume and to count them on proxies in order to mention
that they're definitely stuck. On the other hand, the current
situation is retryable which is quite appreciable as well.

4 years agoMEDIUM: listener/proxy: make the listeners notify about proxy pause/resume
Willy Tarreau [Thu, 24 Sep 2020 14:03:29 +0000 (16:03 +0200)] 
MEDIUM: listener/proxy: make the listeners notify about proxy pause/resume

Till now, we used to call pause_proxy()/resume_proxy() to enable/disable
processing on a proxy, which is used during soft reloads. But since we want
to drive this process from the listeners themselves, we have to instead
proceed the other way around so that when we enable/disable a listener,
it checks if it changed anything for the proxy and notifies about updates
at this level.

The detection is made using li_ready=0 for pause(), and li_paused=0
for resume(). Note that we must not include any test for li_bound because
this state is seen by processes which share the listener with another one
and which must not act on it since the other process will do it. As such
the socket behind the FD will automatically be paused and resume without
its local state changing, but this is the limit of a multi-process system
with shared listeners.

4 years agoMINOR: listeners: check the current listener earlier state in resume_listener()
Willy Tarreau [Thu, 24 Sep 2020 16:54:11 +0000 (18:54 +0200)] 
MINOR: listeners: check the current listener earlier state in resume_listener()

It's quite confusing to have the test on LI_READY very low in the function
as it should be made much earlier. Just like with previous commit, let's
do it when entering. The additional states, however (limited, full) continue
to go through the whole function.

4 years agoMINOR: listeners: check the current listener state in pause_listener()
Willy Tarreau [Thu, 24 Sep 2020 12:46:34 +0000 (14:46 +0200)] 
MINOR: listeners: check the current listener state in pause_listener()

It's better not to try to perform pause() actions on wrong states, so
let's check this and make sure that all callers are now safe. This
means that we must not try to pause a listener which is already paused
(e.g. it could possibly fail if the pause operation isn't idempotent at
the socket level), nor should we try it on earlier states.

4 years agoMEDIUM: proxy: merge zombify_proxy() with stop_proxy()
Willy Tarreau [Thu, 24 Sep 2020 08:51:29 +0000 (10:51 +0200)] 
MEDIUM: proxy: merge zombify_proxy() with stop_proxy()

The two functions don't need to be distinguished anymore since they have
all the necessary info to act as needed on their listeners. Let's just
pass via stop_proxy() and make it check for each listener which one to
close or not.

4 years agoMEDIUM: proxy: remove start_proxies()
Willy Tarreau [Thu, 24 Sep 2020 07:57:32 +0000 (09:57 +0200)] 
MEDIUM: proxy: remove start_proxies()

Its sole remaining purpose was to display "proxy foo started", which
has little benefit and pollutes output for those with plenty of proxies.
Let's remove it now.

The VTCs were updated to reflect this, because many of them had explicit
counts of dropped lines to match this message.

This is tagged as MEDIUM because some users may be surprized by the
loss of this quite old message.

4 years agoMEDIUM: proxy: replace proxy->state with proxy->disabled
Willy Tarreau [Thu, 24 Sep 2020 06:39:22 +0000 (08:39 +0200)] 
MEDIUM: proxy: replace proxy->state with proxy->disabled

The remaining proxy states were only used to distinguish an enabled
proxy from a disabled one. Due to the initialization order, both
PR_STNEW and PR_STREADY were equivalent after startup, and they
would only differ from PR_STSTOPPED when the proxy is disabled or
shutdown (which is effectively another way to disable it).

Now we just have a "disabled" field which allows to distinguish them.
It's becoming obvious that start_proxies() is only used to print a
greeting message now, that we'd rather get rid of. Probably that
zombify_proxy() and stop_proxy() should be merged once their
differences move to the right place.

4 years agoCLEANUP: peers: don't use the PR_ST* states to mark enabled/disabled
Willy Tarreau [Thu, 24 Sep 2020 06:48:08 +0000 (08:48 +0200)] 
CLEANUP: peers: don't use the PR_ST* states to mark enabled/disabled

The enabled/disabled config options were stored into a "state" field
that is an integer but contained only PR_STNEW or PR_STSTOPPED, which
is a bit confusing, and causes a dependency with proxies. This was
renamed to "disabled" and is used as a boolean. The field was also
moved to the end of the struct to stop creating a hole and fill another
one.

4 years agoMINOR: startup: don't rely on PR_STNEW to check for listeners
Willy Tarreau [Thu, 24 Sep 2020 06:15:48 +0000 (08:15 +0200)] 
MINOR: startup: don't rely on PR_STNEW to check for listeners

Instead of looking at listeners in proxies in PR_STNEW state, we'd
rather check for listeners in those not in PR_STSTOPPED as it's only
this state which indicates the proxy was disabled. And let's check
the listeners count instead of testing the list's head.

4 years agoMEDIUM: proxy: remove state PR_STPAUSED
Willy Tarreau [Thu, 24 Sep 2020 06:04:27 +0000 (08:04 +0200)] 
MEDIUM: proxy: remove state PR_STPAUSED

This state was used to mention that a proxy was in PAUSED state, as opposed
to the READY state. This was causing some trouble because if a listener
failed to resume (e.g. because its port was temporarily in use during the
resume), it was not possible to retry the operation later. Now by checking
the number of READY or PAUSED listeners instead, we can accurately know if
something went bad and try to fix it again later. The case of the temporary
port conflict during resume now works well:

  $ socat readline /tmp/sock1
  prompt
  > disable frontend testme3

  > disable frontend testme3
  All sockets are already disabled.

  > enable frontend testme3
  Failed to resume frontend, check logs for precise cause (port conflict?).

  > enable frontend testme3

  > enable frontend testme3
  All sockets are already enabled.

4 years agoMEDIUM: proxy: remove the PR_STERROR state
Willy Tarreau [Thu, 24 Sep 2020 05:44:34 +0000 (07:44 +0200)] 
MEDIUM: proxy: remove the PR_STERROR state

This state is only set when a pause() fails but isn't even set when a
resume() fails. And we cannot recover from this state. Instead, let's
just count remaining ready listeners to decide to emit an error or not.
It's more accurate and will better support new attempts if needed.

4 years agoMEDIUM: proxy: remove the unused PR_STFULL state
Willy Tarreau [Thu, 24 Sep 2020 05:35:46 +0000 (07:35 +0200)] 
MEDIUM: proxy: remove the unused PR_STFULL state

Since v1.4 or so, it's almost not possible anymore to set this state. The
only exception is by using the CLI to change a frontend's maxconn setting
below its current usage. This case makes no sense, and for other cases it
doesn't make sense either because "full" is a vague concept when only
certain listeners are full and not all. Let's just remove this unused
state and make it clear that it's not reported. The "ready" or "open"
states will continue to be reported without being misleading as they
will be opposed to "stop".

4 years agoMINOR: proxy: maintain per-state counters of listeners
Willy Tarreau [Thu, 24 Sep 2020 05:27:06 +0000 (07:27 +0200)] 
MINOR: proxy: maintain per-state counters of listeners

The proxy state tries to be synthetic but that doesn't work well with
many listeners, especially for transition phases or after a failed
pause/resume.

In order to address this, we'll instead rely on counters of listeners in
a given state for the 3 major states (ready, paused, listen) and a total
counter. We'll now be able to determine a proxy's state by comparing these
counters only.

4 years agoMINOR: listeners: introduce listener_set_state()
Willy Tarreau [Thu, 24 Sep 2020 05:23:45 +0000 (07:23 +0200)] 
MINOR: listeners: introduce listener_set_state()

This function is used as a wrapper to set a listener's state everywhere.
We'll use it later to maintain some counters in a consistent state when
switching state so it's capital that all state changes go through it.
No functional change was made beyond calling the wrapper.

4 years agoCLEANUP: proxy: remove the first_to_listen hack in zombify_proxy()
Willy Tarreau [Wed, 23 Sep 2020 16:16:03 +0000 (18:16 +0200)] 
CLEANUP: proxy: remove the first_to_listen hack in zombify_proxy()

This thing was needed for an optimization used in soft_stop() which
doesn't exist anymore, so let's remove it as it's cryptic and hinders
the listeners cleanup.

4 years agoMINOR: listeners: do not uselessly try to close zombie listeners in soft_stop()
Willy Tarreau [Wed, 23 Sep 2020 16:12:11 +0000 (18:12 +0200)] 
MINOR: listeners: do not uselessly try to close zombie listeners in soft_stop()

The loop doesn't match anymore since the non-started listeners are in
LI_INIT and even if it had ever worked the benefit of closing zombies
at this point looks void at best.

4 years agoMEDIUM: listeners: remove the now unused ZOMBIE state
Willy Tarreau [Wed, 23 Sep 2020 15:34:22 +0000 (17:34 +0200)] 
MEDIUM: listeners: remove the now unused ZOMBIE state

The zombie state is not used anymore by the listeners, because in the
last two cases where it was tested it couldn't match as it was covered
by the test on the process mask. Instead now the FD is either in the
LISTEN state or the INIT state. This also avoids forcing the listener
to be single-dimensional because actually belonging to another process
isn't totally exclusive with the other states, which explains some of
the difficulties requiring to check the proc_mask and the fd sometimes.

So let's get rid of it now not to be tempted to reuse it.

The doc on the listeners state was updated.

4 years agoMEDIUM: deinit: close all receivers/listeners before scanning proxies
Willy Tarreau [Wed, 23 Sep 2020 14:46:22 +0000 (16:46 +0200)] 
MEDIUM: deinit: close all receivers/listeners before scanning proxies

Because of the zombie state, proxies have a skewed vision of the state
of listeners, which explains why there are hacks switching the state
from ZOMBIE to INIT in the proxy cleaning loop. This is particularly
complicated and not needed, as all the information is now available
in the protocol list and the fdtab.

What we do here instead is to first close all active listeners or
receivers by protocol and clean their protocol parts. Then we scan the
fdtab to get rid of remaining ones that were necessarily in INIT state
after a previous invocation of delete_listener(). From this point, we
know the listeners are cleaned, the can safely be freed by scanning the
proxies.

4 years agoMEDIUM: listeners: make unbind_listener() converge if needed
Willy Tarreau [Wed, 23 Sep 2020 14:24:23 +0000 (16:24 +0200)] 
MEDIUM: listeners: make unbind_listener() converge if needed

The ZOMBIE state on listener is a real mess. Listeners passing through
this state have lost their consistency with the proxy AND with the fdtab.
Plus this state is not used for all foreign listeners, only for those
belonging to a proxy that entirely runs on another process, otherwise it
stays in INIT state, which makes the usefulness extremely questionable.
But the real issue is that it's impossible to untangle the receivers
from the proxy state as long as we have this because of deinit()...

So what we do here is to start by making unbind_listener() support being
called more than once. This will permit to call it again to really close
the FD and finish the operations if it's called with an FD that's in a
fake state (such as INIT but with a valid fd).

4 years agoMEDIUM: init: stop disabled proxies after initializing fdtab
Willy Tarreau [Wed, 7 Oct 2020 16:36:54 +0000 (18:36 +0200)] 
MEDIUM: init: stop disabled proxies after initializing fdtab

During the startup process we don't have any fdtab nor fd_updt for quite
a long time, and as such some operations on the listeners are not
permitted, such as fd_want_*/fd_stop_* or fd_delete(). The latter is of
particular concern because it's used when stopping a disabled frontend,
and it's performed very early during check_config_validity() while there
is no fdtab yet. The trick till now relies on the listener's state which
is a bit brittle.

There is absolutely no valid reason for stopping a proxy's listeners this
early, we can postpone it after init_pollers() which will at least have
allocated fdtab.

4 years agoMEDIUM: listeners: don't bounce listeners management between queues
Willy Tarreau [Fri, 25 Sep 2020 09:22:59 +0000 (11:22 +0200)] 
MEDIUM: listeners: don't bounce listeners management between queues

During 2.1 development, commit f2cb16948 ("BUG/MAJOR: listener: fix
thread safety in resume_listener()") was introduced to bounce the
enabling/disabling of a listener's FD to one of its threads because
the remains of fd_update_cache() were fundamentally incompatible with
the need to call fd_want_recv() or fd_stop_recv() for another thread.

However since then we've totally dropped such code and it's totally
safe to use these functions on an FD that is solely used by another
thread (this is even used by the FD migration code). The only remaining
limitation concerning the wake up delay was addressed by previous commit
"MEDIUM: fd: always wake up one thread when enabling a foreing FD".

The current situation forces the FD management to remain in the
pause_listener() and resume_listener() functions just so that it can
bounce between threads, without having the ability to delegate it to
the suitable protocol layer.

So let's first remove this now unneeded workaround.

4 years agoMEDIUM: fd: always wake up one thread when enabling a foreing FD
Willy Tarreau [Fri, 25 Sep 2020 10:18:53 +0000 (12:18 +0200)] 
MEDIUM: fd: always wake up one thread when enabling a foreing FD

Since 2.2 it's safe to enable/disable another thread's FD but the fd_wake
calls will not immediately be considered because nothing wakes the other
threads up. This will have an impact on listeners when deciding to resume
them after they were paused, so at minima we want to wake up one of their
threads, just like the scheduler does on task_kill(). This is what this
patch does.

4 years agoREGTESTS: mark abns_socket as broken
Willy Tarreau [Fri, 9 Oct 2020 09:14:35 +0000 (11:14 +0200)] 
REGTESTS: mark abns_socket as broken

This test is inherently racy. It regularly pops up on the CI, and I've
spent one hour chasing a bug that apparently doesn't exist, just because
I'm running it 10 times in a row and it reports from 4 to 8 failures
when built at -O2 and generally even more at -O0. The logs are very
confusing, often reporting that it failed with status 0, with nothing
else wrong. I suspect it might sometimes be the shell command that fails
if it executes faster than haproxy finishes to start up, which would
also explain the relation with the optimization level. E.g:

>  Testing with haproxy version: 2.2.0
>  #    top  TEST reg-tests/seamless-reload/abns_socket.vtc FAILED (3.006) exit=2
>  #    top  TEST reg-tests/seamless-reload/abns_socket.vtc FAILED (3.006) exit=2
>  #    top  TEST reg-tests/seamless-reload/abns_socket.vtc FAILED (3.009) exit=2
>  #    top  TEST reg-tests/seamless-reload/abns_socket.vtc FAILED (3.008) exit=2
>  #    top  TEST reg-tests/seamless-reload/abns_socket.vtc FAILED (3.007) exit=2
>  #    top  TEST reg-tests/seamless-reload/abns_socket.vtc FAILED (3.007) exit=2
>  6 tests failed, 0 tests skipped, 4 tests passed

Some of the failures include this, suggesting that some barriers could
help:
  ---- h1   haproxy h1 PID file check failed:
       Could not read PID file '/tmp/haregtests-2020-10-09_11-19-40.kgsDB4/vtc.30539.04dbea7f/h1/pid

Since it has been causing false positives and consumed way more
troubleshooting time than it saved, let's mark it as broken so that it
doesn't waste more time. We can bring it back when someone manages to
figure what the problem is.

4 years agoBUG/MINOR: http-htx: Expect no body for 204/304 internal HTTP responses
Christopher Faulet [Fri, 9 Oct 2020 06:50:26 +0000 (08:50 +0200)] 
BUG/MINOR: http-htx: Expect no body for 204/304 internal HTTP responses

204 and 304 HTTP responses must no contain message body. These status codes are
correctly handled when the responses are received from a server. But there is no
specific processing for internal HTTP reponses (errorfile and http replies).

Now, when errorfiles or an http replies are parsed during the configuration
parsing, an error is triggered if a 204/304 message contains a body. An extra
check is also performed to ensure the body length matches the announce
content-length.

This patch should fix the issue #891. It must be backported as far as 2.0. For
2.1 and 2.0, only the http_str_to_htx() function must be fixed.
http_parse_http_reply() function does not exist.

4 years agoBUG/MINOR: http: Fix content-length of the default 500 error
Christopher Faulet [Fri, 9 Oct 2020 06:39:26 +0000 (08:39 +0200)] 
BUG/MINOR: http: Fix content-length of the default 500 error

96 bytes is announce in the C-L header for a message of body of 97 bytes. This
bug was introduced by the patch 46a030cdd ("CLEANUP: assorted typo fixes in the
code and comments").

This patch must be backported in all versions where the patch above is (the 2.2
for now).

4 years agoDOC: Fix typos in configuration.txt
Sébastien Gross [Thu, 8 Oct 2020 08:06:03 +0000 (10:06 +0200)] 
DOC: Fix typos in configuration.txt

This patch fixes small typos and grammar in configuration.txt for the
http-request return documentation.

4 years agoBUG/MEDIUM: mux-h2: Don't handle pending read0 too early on streams
Christopher Faulet [Thu, 8 Oct 2020 13:38:41 +0000 (15:38 +0200)] 
BUG/MEDIUM: mux-h2: Don't handle pending read0 too early on streams

This patch is similar to the previous one on the fcgi. Same is true for the
H2. But the bug is far harder to trigger because of the protocol cinematic. But
it may explain strange aborts in some edge cases.

A read0 received on the connection must not be handled too early by H2 streams.
If the demux buffer is not empty, the pending read0 must not be considered. The
H2 streams must not be passed in half-closed remote state in
h2s_wake_one_stream() and the CS_FL_EOS flag must not be set on the associated
conn-stream in h2_rcv_buf(). To sum up, it means, if there are still data
pending in the demux buffer, no abort must be reported to the streams.

To fix the issue, a dedicated function has been added, responsible for detecting
pending read0 for a H2 connection. A read0 is reported only if the demux buffer
is empty. This function is used instead of conn_xprt_read0_pending() at some
places.

Note that the HREM stream state should not be used to report aborts. It is
performed on h2s_wake_one_stream() function and it is a legacy of the very first
versions of the mux-h2.

This patch should be backported as far as 2.0. In the 1.8, the code is too
different to apply it like that. But it is probably useless because the mux-h2
can only be installed on the client side.

4 years agoBUG/MEDIUM: mux-fcgi: Don't handle pending read0 too early on streams
Christopher Faulet [Thu, 8 Oct 2020 13:26:33 +0000 (15:26 +0200)] 
BUG/MEDIUM: mux-fcgi: Don't handle pending read0 too early on streams

A read0 received on the connection must not be handled too early by FCGI
streams. If the demux buffer is not empty, the pending read0 must not be
considered. The FCGI streams must not be passed in half-closed remote state in
fcgi_strm_wake_one_stream() and the CS_FL_EOS flag must not be set on the
associated conn-stream in fcgi_rcv_buf(). To sum up, it means, if there are
still data pending in the demux buffer, no abort must be reported to the
streams.

To fix the issue, a dedicated function has been added, responsible for detecting
pending read0 for a FCGI connection. A read0 is reported only if the demux
buffer is empty. This function is used instead of conn_xprt_read0_pending() at
some places.

This patch should fix the issue #886. It must be backported as far as 2.1.

4 years agoDOC: Add missing stats fields in the management doc
Pierre Cheynier [Thu, 8 Oct 2020 14:37:14 +0000 (16:37 +0200)] 
DOC: Add missing stats fields in the management doc

Added latest fields: idle_conn_cur, safe_conn_cur, used_conn_cur, need_conn_est

4 years agoCI: travis-ci: help Coverity to detect BUG_ON() as a real stop
Ilya Shipitsin [Thu, 8 Oct 2020 22:05:11 +0000 (03:05 +0500)] 
CI: travis-ci: help Coverity to detect BUG_ON() as a real stop

Let's add DEBUG_STRICT=1 to coverity build definition. Hopefully,
it will resolve 1 coverity issue.

4 years agoBUILD: makefile: Update feature flags for NetBSD
Brad Smith [Thu, 8 Oct 2020 20:24:52 +0000 (16:24 -0400)] 
BUILD: makefile: Update feature flags for NetBSD

This updates the feature flags for NetBSD.

NetBSD 8 adds support for accept4().

Enable getaddrinfo().

4 years agoBUG/MINOR: makefile: fix a tiny typo in the target list
Willy Tarreau [Fri, 9 Oct 2020 03:56:56 +0000 (05:56 +0200)] 
BUG/MINOR: makefile: fix a tiny typo in the target list

Previous commit 382001b46 ("BUILD: Add a DragonFlyBSD target") introduced
a tiny typo in the target list ("iopenbs" vs "openbsd"). This will have to
be backported if that patch is backported.

4 years agoBUILD: Add a DragonFlyBSD target
Brad Smith [Thu, 8 Oct 2020 05:15:06 +0000 (01:15 -0400)] 
BUILD: Add a DragonFlyBSD target

Add a target for DragonFlyBSD 4.3 and above.

4 years agoDOC: fix a confusing typo on a regsub example
Willy Tarreau [Thu, 8 Oct 2020 16:05:56 +0000 (18:05 +0200)] 
DOC: fix a confusing typo on a regsub example

Sébastien reported a confusing example in the doc about regsub when used
with quotes. Nested quotes are already not trivial to grasp, but when
typos are there and result in something valid, it's even worse. The closing
quote ought to have been inside the brackets. However haproxy will not make
any difference because the single quotes delimit a word and the delimited
word remains the same. Let's just not add yet another level of confusion.

4 years agoDOC: re-work log forward bind statement documentation.
Emeric Brun [Thu, 8 Oct 2020 06:39:02 +0000 (08:39 +0200)] 
DOC: re-work log forward bind statement documentation.

This patch re-work the documentation about the bind statement
of log forward section.

4 years agoBUG/MINOR: proxy/log: frontend/backend and log forward names must differ
Emeric Brun [Wed, 7 Oct 2020 15:05:59 +0000 (17:05 +0200)] 
BUG/MINOR: proxy/log: frontend/backend and log forward names must differ

This patch disallow to use same name for a log forward section
and a frontend/backend section.

4 years agoMEDIUM: log: syslog TCP support on log forward section.
Emeric Brun [Mon, 5 Oct 2020 12:39:35 +0000 (14:39 +0200)] 
MEDIUM: log: syslog TCP support on log forward section.

This patch re-introduce the "bind" statement on log forward
sections to handle syslog TCP listeners as defined in
rfc-6587.

As complement it introduce "maxconn", "backlog" and "timeout
client" statements to parameter those listeners.

4 years agoMINOR: channel: new getword and getchar functions on channel.
Emeric Brun [Mon, 5 Oct 2020 12:35:21 +0000 (14:35 +0200)] 
MINOR: channel: new getword and getchar functions on channel.

This patch adds two new functions to get a char
or a word from a channel.

4 years agoMINOR: stats: inc req counter on listeners.
Emeric Brun [Wed, 7 Oct 2020 06:50:09 +0000 (08:50 +0200)] 
MINOR: stats: inc req counter on listeners.

This patch enables count of requests for listeners
if listener's counters are enabled.

4 years agoBUG/MEDIUM: log: old processes with log foward section don't die on soft stop.
Emeric Brun [Wed, 7 Oct 2020 08:13:10 +0000 (10:13 +0200)] 
BUG/MEDIUM: log: old processes with log foward section don't die on soft stop.

Old processes didn't die if a log foward section is declared and
a soft stop is requested.

This patch fix this issue and should be backpored in banches including
the log forward feature.

4 years agoBUG/MINOR: proxy: inc req counter on new syslog messages.
Emeric Brun [Mon, 5 Oct 2020 12:33:12 +0000 (14:33 +0200)] 
BUG/MINOR: proxy: inc req counter on new syslog messages.

Increase req counter instead of conn counter on
new syslog messages.

This should be backported on branches including the
syslog forward feature.

4 years agoCLEANUP: sock-unix: Remove an unreachable goto clause
Christopher Faulet [Wed, 7 Oct 2020 12:37:00 +0000 (14:37 +0200)] 
CLEANUP: sock-unix: Remove an unreachable goto clause

Coverity reported dead code in sock_unix_bind_receiver() function. A goto clause
is unreachable because of the preceeding if/else block.

This patch should fix the issue #865. No backport needed.

4 years agoMINOR: mux-h1: Don't wakeup the H1C when output buffer become available
Christopher Faulet [Wed, 30 Sep 2020 15:30:15 +0000 (17:30 +0200)] 
MINOR: mux-h1: Don't wakeup the H1C when output buffer become available

There is no reason to wake up the H1 connection when a new output buffer is
retrieved after an allocation failure because only the H1 stream will fill it.

4 years agoBUG/MINOR: mux-h1: Always set the session on frontend h1 stream
Christopher Faulet [Wed, 30 Sep 2020 13:00:13 +0000 (15:00 +0200)] 
BUG/MINOR: mux-h1: Always set the session on frontend h1 stream

The session is always defined for a frontend connection. When a new client
connection is established, the session is set for the first H1 stream. But on
keep-alived connections, it is not set for the followings H1 streams while it is
possible.

This patch is tagged as a bug because it fixes an inconsistency in the H1
streams creation. But it does not fixed a known bug.

This patch must be backported as far as 2.0.

4 years agoBUG/MINOR: mux-h1: Be sure to only set CO_RFL_READ_ONCE for the first read
Christopher Faulet [Mon, 21 Sep 2020 09:59:21 +0000 (11:59 +0200)] 
BUG/MINOR: mux-h1: Be sure to only set CO_RFL_READ_ONCE for the first read

The condition to set CO_RFL_READ_ONCE flag is not really accurate. We must check
the request state on frontend connection only and, in the opposite, the response
state on backend connection only. Only the parsed side must be considered, not
the opposite one.

This patch must be backported to 2.2.

4 years agoCLEANUP: ssl: Release cached SSL sessions on deinit
Christopher Faulet [Wed, 7 Oct 2020 11:20:23 +0000 (13:20 +0200)] 
CLEANUP: ssl: Release cached SSL sessions on deinit

On deinit, when the server SSL ctx is released, we must take care to release the
cached SSL sessions stored in the array <ssl_ctx.reused_sess>. There are
global.nbthread entries in this array, each one may have a pointer on a cached
session.

This patch should fix the issue #802. No backport needed.

4 years agoCLEANUP: cache: Fix leak of cconf->c.name during config check
Tim Duesterhus [Mon, 14 Sep 2020 16:01:33 +0000 (18:01 +0200)] 
CLEANUP: cache: Fix leak of cconf->c.name during config check

During the config check, the post parsing is not performed. Thus, cache filters
are not fully initialized and their cache name are never released. To be able to
release them, a flag is now set when a cache filter is fully initialized. On
deinit, if the flag is not set, it means the cache name must be freed.

The patch should fix #849. No backport needed.

[Cf: Tim is the patch author, but I added the commit message]

4 years agoBUG/MINOR: proto_tcp: Report warning messages when listeners are bound
Christopher Faulet [Wed, 7 Oct 2020 09:14:47 +0000 (11:14 +0200)] 
BUG/MINOR: proto_tcp: Report warning messages when listeners are bound

When a TCP listener is bound, in the tcp_bind_listener() function, a warning
message may be reported and should be displayed on verbose mode. But the warning
message is actually lost if the socket is successfully bound because we don't
fill the <errmsg> variable in this case.

This patch should fix the issue #863. No backport is needed.

4 years agoDOC: update INSTALL with supported OpenBSD / FreeBSD versions
Brad Smith [Fri, 2 Oct 2020 22:36:58 +0000 (18:36 -0400)] 
DOC: update INSTALL with supported OpenBSD / FreeBSD versions

Update INSTALL with the OpenBSD / FreeBSD versions that are supported.

4 years agoBUG/MINOR: peers: Inconsistency when dumping peer status codes.
Frédéric Lécaille [Mon, 5 Oct 2020 10:33:07 +0000 (12:33 +0200)] 
BUG/MINOR: peers: Inconsistency when dumping peer status codes.

A peer connection status must be considered as valid only if there is an applet
which has been instantiated for the connection to the peer. So, ->statuscode
should be considered as the last known peer connection status from the last
connection to this peer if any. To reflect this, "statuscode" field of peer dump
is renamed to "last_statuscode".
This patch also add "active"/"inactive" field after the peer location type
("remote" or "local") if an applet has been instantiated for this peer connection
or not.

Thank you to Emeric for having noticed this issue.

Must be backported in >=1.9 version.

4 years agoDOC: ssl: fix typo about ocsp files
William Dauchy [Tue, 6 Oct 2020 13:22:37 +0000 (15:22 +0200)] 
DOC: ssl: fix typo about ocsp files

one of the last I saw in this section while working on github issue #872

might be backported in all still supported versions

Signed-off-by: William Dauchy <w.dauchy@criteo.com>
4 years agoMINOR: stats: remove for loop declaration
Amaury Denoyelle [Mon, 5 Oct 2020 14:57:33 +0000 (16:57 +0200)] 
MINOR: stats: remove for loop declaration

Remove variable declaration inside a for-loop. This was introduced by my
patches serie of the implementation of dynamic stats. This is not
supported by older gcc, notably on the freebsd environment of the ci.

4 years agoMINOR: dns/stats: integrate dns counters in stats
Amaury Denoyelle [Mon, 5 Oct 2020 09:49:46 +0000 (11:49 +0200)] 
MINOR: dns/stats: integrate dns counters in stats

Use the new stats module API to integrate the dns counters in the
standard stats. This is done in order to avoid code duplication, keep
the code related to cli out of dns and use the full possibility of the
stats function, allowing to print dns stats in csv or json format.

4 years agoMINOR: stats: add config "stats show modules"
Amaury Denoyelle [Mon, 5 Oct 2020 09:49:45 +0000 (11:49 +0200)] 
MINOR: stats: add config "stats show modules"

By default, hide the extra statistics on the html page. Define a new
flag STAT_SHMODULES which is activated if the config "stats show
modules" is set.

4 years agoMINOR: stats: display extra proxy stats on the html page
Amaury Denoyelle [Mon, 5 Oct 2020 09:49:44 +0000 (11:49 +0200)] 
MINOR: stats: display extra proxy stats on the html page

Integrate the additional proxy stats on the html stats page. For each
module, a new column is displayed with the individual stats available as
a tooltip.

4 years agoMINOR: stats: support clear counters for dynamic stats
Amaury Denoyelle [Mon, 5 Oct 2020 09:49:43 +0000 (11:49 +0200)] 
MINOR: stats: support clear counters for dynamic stats

Add a boolean 'clearable' on stats module structure. If set, it forces
all the counters to be reset on 'clear counters' cli command. If not,
the counters are reset only when 'clear counters all' is used.

4 years agoMEDIUM: stats: integrate static proxies stats in new stats
Amaury Denoyelle [Mon, 5 Oct 2020 09:49:42 +0000 (11:49 +0200)] 
MEDIUM: stats: integrate static proxies stats in new stats

This is executed on startup with the registered statistics module. The
existing statistics have been merged in a list containing all
statistics for each domain. This is useful to print all available
statistics in a generic way.

Allocate extra counters for all proxies/servers/listeners instances.
These counters are allocated with the counters from the stats modules
registered on startup.

4 years agoMEDIUM: stats: add abstract type to store counters
Amaury Denoyelle [Mon, 5 Oct 2020 09:49:41 +0000 (11:49 +0200)] 
MEDIUM: stats: add abstract type to store counters

Implement a small API to easily add extra counters inside a structure
instance. This will be used to implement dynamic statistics linked on
every type of object as needed.

The counters are stored in a dynamic array inside the relevant objects.

4 years agoMEDIUM: stats: define an API to register stat modules
Amaury Denoyelle [Mon, 5 Oct 2020 09:49:40 +0000 (11:49 +0200)] 
MEDIUM: stats: define an API to register stat modules

A stat module can be registered to quickly add new statistics on
haproxy. It must be attached to one of the available stats domain. The
register must be done using INITCALL on STG_REGISTER.

The stat module has a name which should be unique for each new module in
a domain. It also contains a statistics list with their name/desc and a
pointer to a function used to fill the stats from the module counters.

The module also provides the initial counters values used on
automatically allocated counters. The offset for these counters
are stored in the module structure.

4 years agoMEDIUM: stats: add delimiter for static proxy stats on csv
Amaury Denoyelle [Mon, 5 Oct 2020 09:49:39 +0000 (11:49 +0200)] 
MEDIUM: stats: add delimiter for static proxy stats on csv

Use the character '-' to mark the end of static statistics on proxy
domain. After this marker, the order of the fields is not guaranteed and
should be parsed with care.

4 years agoMINOR: stats: define additional flag px cap on domain
Amaury Denoyelle [Mon, 5 Oct 2020 09:49:38 +0000 (11:49 +0200)] 
MINOR: stats: define additional flag px cap on domain

This flag can be used to determine on what type of proxy object the
statistics should be relevant. It will be useful when adding dynamic
statistics. Currently, this flag is not used.

4 years agoMINOR: stats: define the concept of domain for statistics
Amaury Denoyelle [Mon, 5 Oct 2020 09:49:37 +0000 (11:49 +0200)] 
MINOR: stats: define the concept of domain for statistics

The domain option will be used to have statistics attached to other
objects than proxies/listeners/servers. At the moment, only the PROXY
domain is available.

Add an argument 'domain' on the 'show stats' cli command to specify the
domain. Only 'domain proxy' is available now. If not specified, proxy
will be considered the default domain.

For HTML output, only proxy statistics will be displayed.

4 years agoMINOR: hlua: Display debug messages on stderr only in debug mode
Christopher Faulet [Fri, 2 Oct 2020 16:13:52 +0000 (18:13 +0200)] 
MINOR: hlua: Display debug messages on stderr only in debug mode

Debug Messages emitted in lua using core.Debug() or core.log() are now only
displayed on stderr if HAProxy is started in debug mode (-d parameter on the
command line). There is no change for other message levels.

This patch should fix the issue #879. It may be backported to all stable
versions.

4 years agoREORG: stats: extract proxies dump loop in a function
Amaury Denoyelle [Fri, 2 Oct 2020 16:32:04 +0000 (18:32 +0200)] 
REORG: stats: extract proxies dump loop in a function

Create a dedicated function to loop on proxies and dump them. This will
be clearer when other object will be dump as well.

This patch is needed to extend stat support to components other than
proxies objects.

4 years agoREORG: stats: extract proxy json dump
Amaury Denoyelle [Fri, 2 Oct 2020 16:32:03 +0000 (18:32 +0200)] 
REORG: stats: extract proxy json dump

Create a dedicated function to dump a proxy as a json content. This
patch will be needed when other types of objects will be available for
json dump.

This patch is needed to extend stat support to components other than
proxies objects.