On frontend side, when a conn-stream is detached from a H1 connection, the
H1 stream is destroyed and if we already have some data to parse (a
pipelined request), we process these data immedialtely calling
h1_process(). Then we adjust the H1 connection timeout. But h1_process() may
fail and release the H1 connection. For instance, a parsing error may be
reported. Thus, when that happens, we must not use anymore the H1 connection
and exit.
This patch must be backported as far as the 2.2. This bug can impact the 2.3
and the 2.2, in theory, if h1 stream creation fails. But, concretly, it only
fails on the 2.4 because the requests are now parsed at this step.
When a channel is set in TUNNEL mode, we now always set the CF_NEVER_WAIT flag,
to be sure to never wait for sending data. It is important because in TUNNEL
mode, we have no idea if more data are expected or not. Setting this flag
prevent the MSG_MORE flag to be set on the connection.
It is only a problem with the HTX, since the 2.2. On previous versions, the
MSG_MORE flag is only set on the mux initiative. In fact, the problem arises
because there is an ambiguity in tunnel mode about the HTX_FL_EOI flag. In this
mode, from the mux point of view, while the SHUTR is not received more data are
expected. But from the channel point of view, we want to send data asap.
At short term, this fix is good enough and is valid anyway. But for the long
term more reliable solution must be found. At least, the to_forward field must
regain its original meaning.
This patch must be backported as far as 2.2.
When a protocol upgrade request is received, once parsed, it is waiting for
the response in the DONE state. But we must not set the flag CS_FL_EOI
because we don't know if a protocol upgrade will be performed or not.
Now, it is set on the response path, if both sides reached the DONE
state. If a protocol upgrade is finally performed, both side are switched in
TUNNEL state. Thus the CS_FL_EOI flag is not set.
If backported, this patch must be adapted because for now it relies on last
2.4-dev changes. It may be backported as far as 2.0.
As stated in the rfc7231, section 4.3.6, an HTTP tunnel via a CONNECT method
is successfully established if the server replies with any 2xx status
code. However, only 200 responses are considered as valid. With this patch,
any 2xx responses are now considered to estalish the tunnel.
This patch may be backported on demand to all stable versions and adapted
for the legacy HTTP. It works this way since a very long time and nobody
complains.
Enabling memory poisonning is often pretty effective for detecting
uninitialized structure fields. Let's enable it by default and let
the user change the arguments at will (e.g. forcing some memory limits
or disabling a poller). This will work with the latest vtest version
to date (02a9bc1).
This commit adds the OpenTracing filter (hereinafter we will use the
abbreviated name 'the OT filter') to the contrib tree.
The OT filter adds native support for using distributed tracing in HAProxy.
This is enabled by sending an OpenTracing compliant request to one of the
supported tracers; such as Datadog, Jaeger, Lightstep and Zipkin tracers.
Please note: tracers are not listed by any preference, but alphabetically.
The OT filter is a standard HAProxy filter, so what applies to others also
applies to this one (of course, by that I mean what is described in the
documentation, more precisely in the doc/internals/filters.txt file).
The OT filter activation is done explicitly by specifying it in the HAProxy
configuration. If this is not done, the OT filter in no way participates
in the work of HAProxy.
As for the impact on HAProxy speed, this is documented with several tests
located in the test directory, and the result is found in the README-speed-*
files. In short, the speed of operation depends on the way it is used and
the complexity of the configuration, from an almost immeasurable impact to
a significant deceleration (5x and more). I think that in some normal use
the speed of HAProxy with the filter on will be quite satisfactory with a
slowdown of less than 4%.
The OT filter allows intensive use of ACLs, which can be defined anywhere in
the configuration. Thus, it is possible to use the filter only for those
connections that are of interest to us.
More detailed documentation related to the operation, configuration and use
of the filter can be found in the contrib/opentracing directory.
To make the OpenTracing filter easier to configure and compile, several
entries have been added to the Makefile. When running the make utility,
it is possible to use several new arguments:
USE_OT=1 : enable the OpenTracing filter
OT_DEBUG=1 : compile the OpenTracing filter in debug mode
OT_INC=path : force the include path to libopentracing-c-wrapper
OT_LIB=path : force the lib path to libopentracing-c-wrapper
OT_RUNPATH=1 : add libopentracing-c-wrapper RUNPATH to haproxy executable
If USE_OT is set, then an additional Makefile from the contrib/opentracing
directory is included in the compilation process.
Due to the addition of the OpenTracing filter it is necessary to define
ARGC_OT enum. This value is used in the functions fmt_directive() and
smp_resolve_args().
The OpenTracing filter uses several internal HAProxy functions to work
with variables and therefore requires two static local HAProxy functions,
var_accounting_diff() and var_clear(), to be declared global.
In fact, the var_clear() function was not originally defined as static,
but it lacked a declaration.
Now that we sometimes link some contrib subparts directly into the
haproxy binary, it's becoming a real problem that they're not cleaned
on make clean. Some of the tools there are useful as .so or pure
binaries and we don't want to remove them, but anything intermediary
susceptible to be linked into haproxy should be clenaed. This is what
this patch does for 3 levels of subdirs into contrib/, without touching
the rest. It should be sufficient for the vast majority of use cases.
This new option allows to tune the maximum number of simultaneous
entries with the same primary key in the cache (secondary entries).
When we try to store a response in the cache and there are already
max-secondary-entries living entries in the cache, the storage will
fail (but the response will still be sent to the client).
It defaults to 10 and does not have a maximum number.
The secondary entry counter cannot be updated without going over all the
items of a duplicates list periodically. In order to avoid doing it too
often and to impact the cache's performances, a timestamp is added to
the cache_entry. It will store the timestamp (with second precision) of
the last iteration over the list (actually the last call of the
clear_expired_duplicates function). This way, this function will not be
called more than once per second for a given duplicates list.
Add an arbitrary maximum number of secondary entries per primary hash
(10 for now) to the cache. This prevents the cache from being filled
with duplicates of the same resource.
This works thanks to an entry counter that is kept in one of the
duplicates of the list (the last one).
When an entry is added to the list, the ebtree's implementation ensures
that it will be added to the end of the existing list so the only thing
to do to keep the counter updated is to get the previous counter from
the second to last entry.
Likewise, when an entry is explicitely deleted, we update the counter
from the list's last item.
SSL_CTX_add_server_custom_ext is openssl specific function present
since openssl-1.0.2, let us define readable guard for it, not depending
on HA_OPENSSL_VERSION
The cache entries are now added into the tree even when they are not
complete yet. If we realized while trying to add a response's payload
that the shctx was full, the entry was disabled through the
disable_cache_entry function, which cleared the key field of the entry's
node, but without actually removing it from the tree. So the shctx row
could be stolen from the entry and the row's content be rewritten while
a lookup in the tree would still find a reference to the old entry. This
caused a random crash in case of cache saturation and row reuse.
This patch adds the missing removal of the node from the tree next to
the reset of the key in disable_cache_entry.
This bug was introduced by commit 3243447 ("MINOR: cache: Add entry
to the tree as soon as possible")
It does not need to be backported.
In issue #1004, it was reported that it is not possible to remove
correctly a certificate after updating it when it came from a crt-list.
Indeed the "commit ssl cert" command on the CLI does not update the list
of ckch_inst in the crtlist_entry. Because of this, the "del ssl
crt-list" command does not remove neither the instances nor the SNIs
because they were never linked to the crtlist_entry.
This patch fixes the issue by inserting the ckch_inst in the
crtlist_entry once generated.
Must be backported as far as 2.2.
When a frontend H1 connection timed out waiting for the next request, a 408
error message is returned to the client. It is performed into the H1C task
process function, h1_timeout_task(), and under the idle connection takeover
lock. If the 408 error message cannot be sent immediately, we wait for a
next retry. In this case, the lock must be released.
This bug was introduced by the commit c4bfa59f1d ("MAJOR: mux-h1: Create the
client stream as later as possible") and is specific to the 2.4-DEV. No
backport needed.
Depending on the context, the current eweight or the next one must be used
to reposition a server in the tree. When the server state is updated, for
instance its weight, the next eweight must be used because it is not yet
committed. However, when the server is used, on normal conditions, the
current eweight must be used.
In fact, it is only a bug on the 1.8. On newer versions, the changes on a
server are performed synchronously. But it is safer to rely on the right
eweight value to avoid any futur bugs.
On the 1.8, it is important to do so, because the server state is updated
and committed inside the rendez-vous point. Thus, the next server state may
be unsync with the current state for a short time, waiting all threads join
the rendez-vous point. It is especially a problem if the next eweight is set
to 0. Because otherwise, it must not be used to reposition the server in the
tree, leading to a divide by 0.
This patch must be backported as far as 1.8.
Released version 2.4-dev3 with the following main changes :
- MINOR: log: Logging HTTP path only with %HPO
- BUG/MINOR: mux-h2/stats: make stream/connection proto errors more accurate
- MINOR: traces: add a new level "error" below the "user" level
- MINOR: mux-h2/trace: add traces at level ERROR for protocol errors
- BUG/MINOR: mux-h2/stats: not all GOAWAY frames are errors
- BUG/MINOR: lua: missing "\n" in error message
- BUG/MINOR: lua: lua-load doesn't check its parameters
- BUG/MINOR: lua: Post init register function are not executed beyond the first one
- BUG/MINOR: lua: Some lua init operation are processed unsafe
- MINOR: actions: Export actions lookup functions
- MINOR: actions: add a function returning a service pointer from its name
- MINOR: cli: add a function to look up a CLI service description
- BUG/MINOR: lua: warn when registering action, conv, sf, cli or applet multiple times
- MINOR: cache: Improve accept_encoding_normalizer
- MINOR: cache: Add entry to the tree as soon as possible
- BUG/MINOR: trace: Wrong displayed trace level
- BUG/MAJOR: ring: tcp forward on ring can break the reader counter.
- MINOR: lua: simplify hlua_alloc() to only rely on realloc()
- MEDIUM: lua-thread: use atomics for memory accounting
- MINOR: lua-thread: remove struct hlua from function hlua_prepend_path()
- MEDIUM: lua-thread: make hlua_post_init() no longer use the runtime execution function
- MINOR: lua-thread: hlua_ctx_renew() is never called with main gL lua state
- MINOR: lua-thread: Use NULL context for main lua state
- MINOR: lua-thread: Stop usage of struct hlua for the global lua state
- MINOR: lua-thread: Replace embedded struct hlua_function by a pointer
- MINOR: lua-thread: Split hlua_init() function in two parts
- MINOR: lua-thread: make hlua_ctx_init() get L from its caller
- MINOR: lua-thread: Split hlua_load function in two parts
- MINOR: lua-thread: Split hlua_post_init() function in two parts
- MINOR: lua-thread: Add the "thread" core variable
- MEDIUM: lua-thread: No longer use locked context in initialization parts
- MEDIUM: lua-thread: Apply lock only if the parent state is the main thread
- MINOR: lua-thread: Replace global gL var with an array of states
- MINOR: lua-thread: Replace "struct hlua_function" allocation by dedicated function
- MINOR: lua-thread: Replace state_from by state_id
- MINOR: lua-thread: Store each function reference and init reference in array
- MEDIUM: lua-thread: Add the lua-load-per-thread directive
- MINOR: lua-thread: Add verbosity in errors
- REGTESTS: add a test for the threaded Lua code
- BUILD/MINOR: haproxy DragonFlyBSD affinity build update.
- DOC/MINOR: Fix formatting in Management Guide
- MINOR: cache: Do not store stale entry
- MINOR: cache: Add extra "cache-control" value checks
- MEDIUM: cache: Remove cache entry in case of POST on the same resource
- MINOR: cache: Consider invalid Age values as stale
- BUG/MEDIUM: lua-thread: some parts must be initialized once
- BUG/MINOR: lua-thread: close all states on deinit
- BUG/MINOR: listener: use sockaddr_in6 for IPv6
- BUG/MINOR: mux-h1: Handle keep-alive timeout for idle frontend connections
- MINOR: session: Add the idle duration field into the session
- MINOR: mux-h1: Update session idle duration when data are received
- MINOR: mux-h1: Reset session dates and durations info when the CS is detached
- MINOR: logs: Use session idle duration when no stream is provided
- MINOR: stream: Always get idle duration from the session
- MINOR: stream: Don't retrieve anymore timing info from the mux csinfo
- MINOR: mux-h1: Don't provide anymore timing info using cs_info structure
- MINOR: muxes: Remove get_cs_info callback function now useless
- MINOR: stream: Pass an optional input buffer when a stream is created
- MINOR: mux-h1: Add a flag to disable reads to wait opposite side
- MEDIUM: mux-h1: Use a h1c flag to block reads when splicing is in-progress
- MINOR: mux-h1: Introduce H1C_F_IS_BACK flag on the H1 connection
- MINOR: mux-h1: Separate parsing and formatting errors at H1 stream level
- MINOR: mux-h1: Split front/back h1 stream creation in 2 functions
- MINOR: mux-h1: Add a rxbuf into the H1 stream
- MINOR: mux-h1: Don't set CS flags in internal parsing functions
- MINOR: mux-h1: Add embryonic and attached states on the H1 connection
- MINOR: mux-h1: rework the h1_timeout_task() function
- MINOR: mux-h1: Reset more H1C flags when a H1 stream is destroyed
- MINOR: mux-h1: Disable reads if an error was reported on the H1 stream
- MINOR: mux-h1: Rework how shutdowns are handled
- MINOR: mux-h1: Rework h1_refresh_timeout to be easier to read
- MINOR: mux-h1: Process next request for IDLE connection only
- MINOR: mux-h1: Add a idle expiration date on the H1 connection
- MINOR: stick-tables: Add functions to update some values of a tracked counter
- MINOR: session: Add functions to increase http values of tracked counters
- MINOR: mux: Add a ctl parameter to get the exit status of the multiplexers
- MINOR: logs: Get the multiplexer exist status when no stream is provided
- MINOR: mux-h1: Add functions to send HTTP errors from the mux
- MAJOR: mux-h1: Create the client stream as later as possible
- DOC: config: Add notes about errors emitted by H1 mux
- CLEANUP: mux-h1: Rename H1C_F_CS_* flags and reorder H1C flags
- MINOR: http-ana: Remove useless update of t_idle duration of the stream
- CLEANUP: htx: Remove HTX_FL_UPGRADE unsued flag
- MEDIUM: http-ana: Don't process partial or empty request anymore
- CLEANUP: http-ana: Remove TX_WAIT_NEXT_RQ unsued flag
- CLEANUP: connection: Remove CS_FL_READ_PARTIAL flag
- REGTESTS: Fix proxy_protocol_tlv_validation
- MINOR: http-ana: Properly set message flags from the start-line flags
- MINOR: h1-htx/http-ana: Set BODYLESS flag on message in TUNNEL state
- MINOR: protocol: add a ->set_port() helper to address families
- MINOR: listener: automatically set the port when creating listeners
- MINOR: listener: now use a generic add_listener() function
- MEDIUM: ssl: fatal error with bundle + openssl < 1.1.1
- BUG/MEDIUM: stream: Xfer the input buffer to a fully created stream
- BUG/MINOR: stream: Don't use input buffer after the ownership xfer
- MINOR: protocol: remove the redundant ->sock_domain field
- MINOR: protocol: export protocol definitions
- CLEANUP: protocol: group protocol struct members by usage
- MINOR: protocol: add a set of ctrl_init/ctrl_close methods for setup/teardown
- MINOR: connection: use the control layer's init/close
- MINOR: udp: export udp_suspend_receiver() and udp_resume_receiver()
- BUG/MAJOR: spoa/python: Fixing return None
- DOC: spoa/python: Fixing typo in IP related error messages
- DOC: spoa/python: Rephrasing memory related error messages
- DOC: spoa/python: Fixing typos in comments
- BUG/MINOR: spoa/python: Cleanup references for failed Module Addobject operations
- BUG/MINOR: spoa/python: Cleanup ipaddress objects if initialization fails
- BUG/MEDIUM: spoa/python: Fixing PyObject_Call positional arguments
- BUG/MEDIUM: spoa/python: Fixing references to None
- DOC: email change of the DeviceAtlas maintainer
- MINOR: cache: Dump secondary entries in "show cache"
- CLEANUP: connection: use fd_stop_both() instead of conn_stop_polling()
- MINOR: stream-int: don't touch polling anymore on shutdown
- MINOR: connection: implement cs_drain_and_close()
- MINOR: mux-pt: take care of CS_SHR_DRAIN in shutr()
- MINOR: checks: use cs_drain_and_close() instead of draining the connection
- MINOR: checks: don't call conn_cond_update_polling() anymore
- CLEANUP: connection: open-code conn_cond_update_polling() and update the comment
- CLEANUP: connection: remove the unused conn_{stop,cond_update}_polling()
- BUG/MINOR: http-check: Use right condition to consider HTX message as full
- BUG/MINOR: tcpcheck: Don't rearm the check timeout on each read
- MINOR: tcpcheck: Only wait for more payload data on HTTP expect rules
- BUG/MINOR: tools: make parse_time_err() more strict on the timer validity
- BUG/MINOR: tools: Reject size format not starting by a digit
- MINOR: action: define enum for timeout type of the set-timeout rule
- MINOR: stream: prepare the hot refresh of timeouts
- MEDIUM: stream: support a dynamic server timeout
- MEDIUM: stream: support a dynamic tunnel timeout
- MEDIUM: http_act: define set-timeout server/tunnel action
- MINOR: frontend: add client timeout sample fetch
- MINOR: backend: add timeout sample fetches
- MINOR: stream: add sample fetches
- MINOR: stream: add timeout sample fetches
- REGTESTS: add regtest for http-request set-timeout
- CLEANUP: remove the unused fd_stop_send() in conn_xprt_shutw{,_hard}()
- CLEANUP: connection: remove the unneeded fd_stop_{recv,send} on read0/shutw
- MINOR: connection: remove sock-specific code from conn_sock_send()
- REORG: connection: move the socket iocb (conn_fd_handler) to sock.c
- MINOR: protocol: add a ->drain() function at the connection control layer
- MINOR: connection: make conn_sock_drain() use the control layer's ->drain()
- MINOR: protocol: add a pair of check_events/ignore_events functions at the ctrl layer
- MEDIUM: connection: make use of the control layer check_events/ignore_events
This changes the subscribe/unsubscribe functions to rely on the control
layer's check_events/ignore_events. At the moment only the socket version
of these functions is present so the code should basically be the same.
Right now the connection subscribe/unsubscribe code needs to manipulate
FDs, which is not compatible with QUIC. In practice what we need there
is to be able to either subscribe or wake up depending on readiness at
the moment of subscription.
This commit introduces two new functions at the control layer, which are
provided by the socket code, to check for FD readiness or subscribe to it
at the control layer. For now it's not used.
Now we don't touch the fd anymore there, instead we rely on the ->drain()
provided by the control layer. As such the function was renamed to
conn_ctrl_drain().
This is what we need to drain pending incoming data from an connection.
The code was taken from conn_sock_drain() without the connection-specific
stuff. It still takes a connection for now for API simplicity.
conn_fd_handler() is 100% specific to socket code. It's about time
it moves to sock.c which manipulates socket FDs. With it comes
conn_fd_check() which tests for the socket's readiness. The ugly
connection status check at the end of the iocb was moved to an inlined
function in connection.h so that if we need it for other socket layers
it's not too hard to reuse.
The code was really only moved and not changed at all.
The send() loop present in this function and the error handling is already
present in raw_sock_from_buf(). Let's rely on it instead and stop touching
the FD from this place. The send flag was changed to use a more agnostic
CO_SFL_*. The name was changed to "conn_ctrl_send()" to remind that it's
meant to be used to send at the lowest level.
These are two other areas where this fd_stop_recv()/fd_stop_send() makes no
sense anymore. Both happen by definition while the FD is *not* subscribed,
since nowadays it's subscribed after failing recv()/send(), in which case
we cannot close.
These functions used to disable polling for writes when shutting down
but this is no longer used as it still happens later when closing if the
connection was subscribed to FD events. Let's just remove this fake and
undesired dependency on the FD layer.
Add cur_server_timeout and cur_tunnel_timeout.
These sample fetches return the current timeout value for a stream. This
is useful to retrieve the value of a timeout which was changed via a
set-timeout rule.
Prepare the possibility to register sample fetches on the stream.
This commit is necessary to implement sample fetches to retrieve the
current timeout values.
Add a new http-request action 'set-timeout [server/tunnel]'. This action
can be used to update the server or tunnel timeout of a stream. It takes
two parameters, the timeout name to update and the new timeout value.
This rule is only valid for a proxy with backend capabilities. The
timeout value cannot be null. A sample expression can also be used
instead of a plain value.
Allow the modification of the tunnel timeout on the stream side.
Use a new field in the stream for the tunnel timeout. It is initialized
by the tunnel timeout from backend unless it has already been set by a
set-timeout tunnel rule.
Allow the modification of the timeout server value on the stream side.
Do not apply the default backend server timeout in back_establish if it
is already defined. This is the case if a set-timeout server rule has
been executed.
parse_size_err() function is now more strict on the size format. The first
character must be a digit. Otherwise an error is returned. Thus "size k" is
now rejected.
This patch must be backported to all stable versions.
First, an error is now reported if the first character is not a digit. Thus,
"timeout client s" triggers an error now. Then 'u' is also rejected
now. 'us' is valid and should be used set the timer in microseconds. However
'u' alone is not a valid unit. It was just ignored before (default to
milliseconds). Now, it is an error. Finally, a warning is reported if the
end of the text is not reached after the timer parsing. This warning will
probably be switched to an error in a futur version.
This patch must be backported to all stable versions.
For HTTP expect rules, if the buffer is not empty, it is guarantee that all
responses headers are received, with the start-line. Thus, except for
payload matching, there is no reason to wait for more data from the moment
the htx message is not empty.
This patch may be backported as far as 2.2.
The check timeout is used to limit a health-check execution. By default
inter timeout is used. But when defined the check timeout is used. In this
case, the inter timeout (or connect timeout) is used for the connection
establishment only. And the check timeout for the health-check
execution. Thus, it must be set after a successfull connect. It means it is
rearm at the end of each connect rule.
This patch with the previous one (BUG/MINOR: http-check: Use right condition
to consider HTX message as full) should solve the issue #991. It must be
backported as far as 2.2. On the 2.3 and 2.2, there are 2 places were the
connection establishement is handled. The check timeout must be set on both.
When an HTTP expect rule is evaluated, we must know if more data is expected
or not to wait if the matching fails. If the whole response is received or
if the HTX message is full, we must not wait. In this context,
htx_free_data_space() must be used instead of htx_free_space(). The fisrt
one count down the block size. Otherwise at the edge, when only the block
size remains free (8 bytes), we may think there is some place for more data
while the mux is unable to add more block.
This bug explains the loop described on the GH issue #991. It should be
backported as far as 2.2.
These functions are not used anymore and were quite confusing given that
their names reflected their original role and not the current ones. Let's
kill them before they inspire anyone.
This last call to conn_cond_update_polling() is now totally misleading as
the function only stops polling in case of unrecoverable connection error.
Let's open-code the test to make it more prominent and explain what we're
trying to do there. It's even almost certain this code is never executed
anymore, as the only remaining case should be a mux's wake function setting
CO_FL_ERROR without disabling the polling, but they need to be audited first
to make sure this is the case.
This was a leftover of the pre-mux v1.8-dev3 era. It makes no sense anymore
to try to disable polling on a connection we don't own, it's the mux's job
and it's properly done upon shutdowns and closes.
As explained in previous commit, the situation is absurd as we try to
cleanly drain pending data before impolitely shutting down, and it could
be counter productive on real muxes. Let's use cs_drain_and_close() instead.
When the shutr() requests CS_SHR_DRAIN and there's no particular shutr
implemented on the underlying transport layer, we must drain pending data.
This is what happens when cs_drain_and_close() is called. It is important
for TCP checks to drain large responses and close cleanly.