]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
6 years agoMEDIUM: connections: Remove CONN_FL_SOCK*
Olivier Houchard [Tue, 28 May 2019 08:12:02 +0000 (10:12 +0200)] 
MEDIUM: connections: Remove CONN_FL_SOCK*

Now that the various handshakes come with their own XPRT, there's no
need for the CONN_FL_SOCK* flags, and the conn_sock_want|stop functions,
so garbage-collect them.

6 years agoMEDIUM: connections: Introduce a handshake pseudo-XPRT.
Olivier Houchard [Mon, 27 May 2019 10:09:19 +0000 (12:09 +0200)] 
MEDIUM: connections: Introduce a handshake pseudo-XPRT.

Add a new XPRT that is used when using non-SSL handshakes, such as proxy
protocol or Netscaler, instead of taking care of it in conn_fd_handler().
This XPRT is installed when any of those is used, and it removes itself once
the handshake is done.
This should allow us to remove the distinction between CO_FL_SOCK* and
CO_FL_XPRT*.

6 years agoMINOR: connections: Add a new xprt method, add_xprt().
Olivier Houchard [Mon, 27 May 2019 17:50:12 +0000 (19:50 +0200)] 
MINOR: connections: Add a new xprt method, add_xprt().

Add a new method to xprt_ops, add_xprt(), that changes the underlying
xprt to the one provided, and optionally provide the old one.

6 years agoMINOR: connections: Add a new xprt method, remove_xprt.
Olivier Houchard [Thu, 23 May 2019 15:47:36 +0000 (17:47 +0200)] 
MINOR: connections: Add a new xprt method, remove_xprt.

Add a new method to xprt_ops, remove_xprt. When called, if the provided
xprt_ctx is the same as the xprt's underlying xprt_ctx, it then uses the
new xprt provided, otherwise it calls the remove_xprt method of the next
xprt.
The goal is to be able to add a temporary xprt, that removes itself from
the chain when it did what it had to do. This will be used to implement
a pseudo-xprt for anything that just requires a handshake (such as the
proxy protocol).

6 years agoMINOR: ssl: Make ssl_sock_handshake() static.
Olivier Houchard [Thu, 23 May 2019 12:45:12 +0000 (14:45 +0200)] 
MINOR: ssl: Make ssl_sock_handshake() static.

ssl_sock_handshake is now only used by the ssl code itself, there's no need
to export it anymore, so make it static.

6 years agoMEDIUM: ssl: Handle subscribe by itself.
Olivier Houchard [Mon, 20 May 2019 12:02:16 +0000 (14:02 +0200)] 
MEDIUM: ssl: Handle subscribe by itself.

As the SSL code may have different needs than the upper layer, ie it may want
to receive when the upper layer wants to right, instead of directly forwarding
the subscribe to the underlying xprt, handle it ourself. The SSL code will
know remember any subscribe call, and wake the tasklet when it is ready
for more I/O.

6 years agoMEDIUM: connections: Wake the upper layer even if sending/receiving is disabled.
Olivier Houchard [Wed, 5 Jun 2019 15:07:45 +0000 (17:07 +0200)] 
MEDIUM: connections: Wake the upper layer even if sending/receiving is disabled.

In conn_fd_handler(), if the fd is ready to send/recv, wake the upper layer
even if we have CO_FL_ERROR, or if CO_FL_XPRT_RD_ENA/CO_FL_XPRT_WR_ENA isn't
set. The only reason we should reach that point is if we had a shutw/shutr,
and the upper layer may want to know about it, and is supposed to handle it
anyway.

6 years agoMEDIUM: checks: Make sure we unsubscribe before calling cs_destroy().
Olivier Houchard [Fri, 31 May 2019 17:20:36 +0000 (19:20 +0200)] 
MEDIUM: checks: Make sure we unsubscribe before calling cs_destroy().

When we want to destroy the conn_stream for some reason, usually on error,
make sure we unsubscribed before doing so. If we subsscribed, the xprt may
ultimately wake our tasklet on close, aand the check tasklet doesn't expect
it ot happen when we have no longer any conn_stream.

6 years agoBUG/MEDIUM: servers: Don't attempt to destroy idle connections if disabled.
Olivier Houchard [Wed, 5 Jun 2019 11:55:01 +0000 (13:55 +0200)] 
BUG/MEDIUM: servers: Don't attempt to destroy idle connections if disabled.

In connect_server(), when deciding if we should attempt to remove idle
connections, because we have to many file descriptors opened, don't attempt
to do so if idle connection pool is disabled (with pool-max-conn 0), as
if it is, srv->idle_orphan_conns won't even be allocated, and trying to
dereference it will cause a crash.

6 years agoBUG/MINOR: peers: Wrong "server_name" decoding.
Frédéric Lécaille [Wed, 5 Jun 2019 08:20:09 +0000 (10:20 +0200)] 
BUG/MINOR: peers: Wrong "server_name" decoding.

This patch fixes a bug which does not occur at this time because the "server_name"
stick-table data type is the last one (see STKTABLE_DT_SERVER_NAME). It was introduced
by this commit: "MINOR: peers: Make peers protocol support new "server_name" data type".

Indeed when receiving STD_T_DICT stick-table data type we first decode the length
of these data, then we decode the ID of this dictionary entry. To know if there
is remaining data to parse, we check if we have reached the end of the current data,
relying on <msg_end> variable. But <msg_end> is at the end of the entire message!

So this patch computes the correct end of the current STD_T_DICT before doing
anything else with it.

Nothing to backport.

6 years agoBUG/MINOR: flt_trace/htx: Only apply the random forwarding on the message body.
Christopher Faulet [Tue, 4 Jun 2019 20:09:53 +0000 (22:09 +0200)] 
BUG/MINOR: flt_trace/htx: Only apply the random forwarding on the message body.

In the function trace_http_payload(), when the random forwarding is enabled,
only blocks of type HTX_BLK_DATA must be considered. Because other blocks must
be forwarding in one time.

This patch must be backported to 1.9. But it will have to be adapted. Because
several changes on the HTX in the 2.0 are missing in the 1.9.

6 years agoBUG/MINOR: mux-h1: Don't send more data than expected
Christopher Faulet [Tue, 4 Jun 2019 20:09:36 +0000 (22:09 +0200)] 
BUG/MINOR: mux-h1: Don't send more data than expected

In h1_snd_buf(), we try to consume as much data as possible in a loop. In this
loop, we first format the raw HTTP message from the HTX message, then we try to
send it. But we must be carefull to never send more data than specified by the
stream-interface.

This patch must be backported to 1.9.

6 years agoMINOR: htx: Don't use end-of-data blocks anymore
Christopher Faulet [Tue, 4 Jun 2019 08:08:28 +0000 (10:08 +0200)] 
MINOR: htx: Don't use end-of-data blocks anymore

This type of blocks is useless because transition between data and trailers is
obvious. And when there is no trailers, the end-of-message is still there to
know when data end for chunked messages.

6 years agoMEDIUM: htx: Add the parsing of trailers of chunked messages
Christopher Faulet [Mon, 3 Jun 2019 08:41:26 +0000 (10:41 +0200)] 
MEDIUM: htx: Add the parsing of trailers of chunked messages

HTTP trailers are now parsed in the same way headers are. It means trailers are
converted to K/V blocks followed by an end-of-trailer marker. For now, to make
things simple, the type for trailer blocks are not the same than for header
blocks. But the aim is to make no difference between headers and trailers by
using the same type. Probably for the end-of marker too.

6 years agoMEDIUM: cache/htx: Always store info about HTX blocks in the cache
Christopher Faulet [Mon, 3 Jun 2019 20:19:18 +0000 (22:19 +0200)] 
MEDIUM: cache/htx: Always store info about HTX blocks in the cache

It was only done for the headers (including the EOH marker). data were prefixed
by the info field of these blocks. The payload and the trailers of the messages
were stored in raw. The total size of headers and payload were kept in the
cached object state to help output formatting.

Now, info about each HTX block is store in the cache. Only data are allowed to
be splitted. Otherwise, all blocks of an HTX message are handled the same way,
both when storing a message in the cache and when delivering it from the
cache. This will help the cache implementation to be more robust to internal
changes in the HTX. Especially for the upcoming parsing of trailers. There is
also no more need to keep extra info in the cached object state.

6 years agoMINOR: mux-h1: Don't count the EOM in the estimated size of headers
Christopher Faulet [Fri, 24 May 2019 19:43:55 +0000 (21:43 +0200)] 
MINOR: mux-h1: Don't count the EOM in the estimated size of headers

If there is not enough space in the HTX message, the EOM can be delayed when a
bodyless message is added. So, don't count it in the estimated size of headers.

6 years agoMINOR: mux-h1: Add h1_eval_htx_hdrs_size() to estimate size of the HTX headers
Christopher Faulet [Fri, 24 May 2019 14:50:16 +0000 (16:50 +0200)] 
MINOR: mux-h1: Add h1_eval_htx_hdrs_size() to estimate size of the HTX headers

It is just a cosmetic change, to avoid code duplication.

6 years agoMINOR: mux-h1: Add the flag HAVE_O_CONN on h1s
Christopher Faulet [Fri, 24 May 2019 14:36:43 +0000 (16:36 +0200)] 
MINOR: mux-h1: Add the flag HAVE_O_CONN on h1s

This flag is set on h1s when output messages are formatted to know the
connection mode was already processed. It replace the variable process_conn_mode
in the function h1_process_output().

6 years agoMEDIUM: mux-h1: refactor output processing
Christopher Faulet [Fri, 24 May 2019 13:28:57 +0000 (15:28 +0200)] 
MEDIUM: mux-h1: refactor output processing

When we format the H1 output, in the loop on the HTX message, instead of
switching on the block types, we now switch on the message state. It is almost
the same, but it will ease futur changes, on trailers and end-of markers.

6 years agoBUG/MINOR: mux-h1: errflag must be set on H1S and not H1M during output processing
Christopher Faulet [Tue, 28 May 2019 08:35:18 +0000 (10:35 +0200)] 
BUG/MINOR: mux-h1: errflag must be set on H1S and not H1M during output processing

This bug is in an unexpected clause of the switch..case, inside
h1_process_output(). The wrong structure is used to set the error flag.

This patch must be backported to 1.9.

6 years agoBUG/MINOR: contrib/prometheus-exporter: Add HTX data block in one time
Christopher Faulet [Tue, 28 May 2019 19:56:07 +0000 (21:56 +0200)] 
BUG/MINOR: contrib/prometheus-exporter: Add HTX data block in one time

Since recent changes on the way HTX data blocks are added in an HTX message, we
must now be sure the prometheus service add its own blocks in one time. Indeed,
the function htx_add_data() may now decide to only copy a part of data. So
instead, we must call htx_add_data_atonce() instead.

6 years agoBUG/MINOR: channel/htx: Don't alter channel during forward for empty HTX message
Christopher Faulet [Wed, 29 May 2019 12:52:56 +0000 (14:52 +0200)] 
BUG/MINOR: channel/htx: Don't alter channel during forward for empty HTX message

In channel_htx_forward() and channel_htx_forward_forever(), if the HTX message
is empty, the underlying buffer may be really empty too. And we have no warranty
the caller will call htx_to_buf() later. And in practice, it is almost never
done. So the channel's buffer must not be altered. Otherwise, the buffer may be
considered as full (data == size) for an empty HTX message and no outgoing data.

This patch must be backported to 1.9.

6 years agoMINOR: SSL: add client/server random sample fetches
Patrick Hemmer [Tue, 4 Jun 2019 12:13:03 +0000 (08:13 -0400)] 
MINOR: SSL: add client/server random sample fetches

This adds 4 sample fetches:
- ssl_fc_client_random
- ssl_fc_server_random
- ssl_bc_client_random
- ssl_bc_server_random

These fetches retrieve the client or server random value sent during the
handshake.

Their use is to be able to decrypt traffic sent using ephemeral ciphers. Tools
like wireshark expect a TLS log file with lines in a few known formats
(https://code.wireshark.org/review/gitweb?p=wireshark.git;a=blob;f=epan/dissectors/packet-tls-utils.c;h=28a51fb1fb029eae5cea52d37ff5b67d9b11950f;hb=HEAD#l5209).
Previously the only format supported using data retrievable from HAProxy state
was the one utilizing the Session-ID. However an SSL/TLS session ID is
optional, and thus cannot be relied upon for this purpose.

This change introduces the ability to extract the client random instead which
can be used for one of the other formats. The change also adds the ability to
extract the server random, just in case it might have some other use, as the
code change to support this was trivial.

6 years agoBUILD: travis-ci improvements
Ilya Shipitsin [Tue, 4 Jun 2019 21:16:51 +0000 (02:16 +0500)] 
BUILD: travis-ci improvements

full list:

update LibreSSL to 2.9.2
speed up build by using "make -j3"
cache BoringSSL checkout
build prometeus exporter
add basic cygwin build
add USE_TFO=1, USE_SYSTEMD=1 to linux builds

6 years agoCLEANUP: ssl: remove unneeded defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet [Tue, 14 May 2019 14:27:35 +0000 (16:27 +0200)] 
CLEANUP: ssl: remove unneeded defined(OPENSSL_IS_BORINGSSL)

BoringSSL pretend to be compatible with OpenSSL 1.1.0 and
OPENSSL_VERSION_NUMBER is set accordly: cleanup redundante #ifdef.

6 years agoMINOR: peers: Replace hard-coded values for peer protocol messaging by macros.
Frédéric Lécaille [Tue, 4 Jun 2019 06:28:19 +0000 (08:28 +0200)] 
MINOR: peers: Replace hard-coded values for peer protocol messaging by macros.

Simple patch to replace hard-coded values in relation with bytes identifiers used
for stick-table messages by macros.

6 years agoMINOR: peers: Replace hard-coded for peer protocol 64-bits value encoding by macros.
Frédéric Lécaille [Mon, 3 Jun 2019 16:29:51 +0000 (18:29 +0200)] 
MINOR: peers: Replace hard-coded for peer protocol 64-bits value encoding by macros.

With this patch we define macros for the minimum values which are
encoded for 2 up to 10 bytes. This latter is big enough to encode
UINT64_MAX. We replaced at several places 240 value by PEER_ENC_2BYTES_MIN
which is the minimum value which is encoded with 2 bytes. The peer protocol
encoding consisting in encoding with only one byte a value which is
less than PEER_ENC_2BYTES_MIN and with at least 2 bytes a 64-bits value greater
than PEER_ENC_2BYTES_MIN.

6 years agoMINOR: peers: Add dictionary cache information to "show peers" CLI command.
Frédéric Lécaille [Wed, 29 May 2019 14:20:41 +0000 (16:20 +0200)] 
MINOR: peers: Add dictionary cache information to "show peers" CLI command.

This patch adds dictionary entries cached and used for the server by name
stickiness feature (exchanged thanks to peers protocol).

6 years agoREGTEST: Add a basic server by name stickiness reg test.
Frédéric Lécaille [Thu, 23 May 2019 14:13:16 +0000 (16:13 +0200)] 
REGTEST: Add a basic server by name stickiness reg test.

With this new reg test we ensure the server by names stickiness is functional
between servers organized differently (with identical names, but with different IDs)
among two haproxy processes backends.

6 years agoMINOR: stick-table: Make the CLI stick-table handler support dictionary entry data...
Frédéric Lécaille [Thu, 23 May 2019 10:15:04 +0000 (12:15 +0200)] 
MINOR: stick-table: Make the CLI stick-table handler support dictionary entry data type.

Simple patch to dump the values (strings) of dictionary entries stored in stick-table
entries with STD_T_DICT as internal data type.

6 years agoMINOR: peers: Make peers protocol support new "server_name" data type.
Frédéric Lécaille [Mon, 20 May 2019 16:22:52 +0000 (18:22 +0200)] 
MINOR: peers: Make peers protocol support new "server_name" data type.

Make usage of the APIs implemented for dictionaries (dict.c) and their LRU caches (struct dcache)
so that to send/receive server names used for the server by name stickiness. These
names are sent over the network as follows:

 - in every case we send the encode length of the data (STD_T_DICT), then
 - if the server names is not present in the cache used upon transmission (struct dcache_tx)
   we cache it and we the ID of this TX cache entry followed the encode length of the
   server name, and finally the sever name itseft (non NULL terminated string).
 - if the server name is present, we repead these operations but we only send the TX cache
   entry ID.

Upon receipt, the couple of (cache IDs, server name) are stored the LRU cache used
only upon receipt (struct dcache_rx). As the peers protocol is symetrical, the fact
that the server name is present in the received data (resp. or not) denotes if
the entry is absent (resp. or not).

6 years agoMINOR: stream: Stickiness server lookup by name.
Frédéric Lécaille [Mon, 20 May 2019 08:08:27 +0000 (10:08 +0200)] 
MINOR: stream: Stickiness server lookup by name.

With this patch we modify the stickiness server targets lookup behavior.
First we look for this server targets by their names before looking for them by their
IDs if not found. We also insert a dictionary entry for the name of the server targets
and store the address of this entry in the underlying stick-table.

6 years agoMINOR: server: Add a dictionary for server names.
Frédéric Lécaille [Mon, 20 May 2019 07:47:07 +0000 (09:47 +0200)] 
MINOR: server: Add a dictionary for server names.

This patch only declares and defines a dictionary for the server
names (stored as ->id member field).

6 years agoMINOR: proxy: Add a "server by name" tree to proxy.
Frédéric Lécaille [Fri, 17 May 2019 12:29:15 +0000 (14:29 +0200)] 
MINOR: proxy: Add a "server by name" tree to proxy.

Add a tree to proxy struct to lookup by name for servers attached
to this proxy and populated it at parsing time.

6 years agoMINOR: cfgparse: Space allocation for "server_name" stick-table data type.
Frédéric Lécaille [Fri, 17 May 2019 08:12:52 +0000 (10:12 +0200)] 
MINOR: cfgparse: Space allocation for "server_name" stick-table data type.

When parsing sticking rules, with this patch we reserve some room for the new
"server_name" stick-table data type, as this is already done for "server_id",
setting the offset and used space (in bytes) in the stick-table entry thanks
to stkable_alloc_data_type().

6 years agoMINOR: stick-table: Add "server_name" new data type.
Frédéric Lécaille [Fri, 17 May 2019 08:08:29 +0000 (10:08 +0200)] 
MINOR: stick-table: Add "server_name" new data type.

This simple patch only adds definitions to create a new stick-table
data type ID and a new standard type to store information in relation
wich dictionary entries (STD_T_DICT).

6 years agoMINOR: peers: Add a LRU cache implementation for dictionaries.
Frédéric Lécaille [Tue, 28 May 2019 17:02:42 +0000 (19:02 +0200)] 
MINOR: peers: Add a LRU cache implementation for dictionaries.

We want to send some stick-table data fields stored as strings in dictionaries
without consuming too much memory and CPU. To do so we implement with this patch
a cache for send/received dictionaries entries. These dictionary of strings entries are
stored in others real dictionary entries with an identifier as key (unsigned int)
and a pointer to the dictionary of strings entries as values.

6 years agoMINOR: dict: Add dictionary new data structure.
Frédéric Lécaille [Tue, 28 May 2019 12:47:17 +0000 (14:47 +0200)] 
MINOR: dict: Add dictionary new data structure.

This patch adds minimalistic definitions to implement dictionary new data structure
which is an ebtree of ebpt_node structs with strings as keys. Note that this has nothing
to see with real dictionary data structure (maps of keys in association with values).

6 years agoBUG/MINOR: peers: Wrong stick-table update message building.
Frédéric Lécaille [Fri, 24 May 2019 12:34:34 +0000 (14:34 +0200)] 
BUG/MINOR: peers: Wrong stick-table update message building.

When creating this patch "CLEANUP: peers: Replace hard-coded values by macros",
we realized there was a remaining place in peer_prepare_updatemsg() where the maximum
of an encoded length harcoded value could be replaced by PEER_MSG_ENCODED_LENGTH_MAXLEN
macro. But in this case, the 1 harcoded value for the header length is wrong. Should
be 2 or PEER_MSG_HEADER_LEN. So, there is a missing byte to encode the length of
remaining data after the header.

Note that the bug was never encountered because even with a missing byte, we could
encode a maximum length which would be (1<<25) (32MB) according to the following
extract of the peers protocol documentation which were from far a never reached limit
I guess:

  I) Encoded Integer and Bitfield.

         0  <= X < 240        : 1 byte  (7.875 bits)  [ XXXX XXXX ]
        240 <= X < 2288       : 2 bytes (11 bits)     [ 1111 XXXX ] [ 0XXX XXXX ]
       2288 <= X < 264432     : 3 bytes (18 bits)     [ 1111 XXXX ] [ 1XXX XXXX ]   [ 0XXX XXXX ]
     264432 <= X < 33818864   : 4 bytes (25 bits)     [ 1111 XXXX ] [ 1XXX XXXX ]*2 [ 0XXX XXXX ]
   33818864 <= X < 4328786160 : 5 bytes (32 bits)     [ 1111 XXXX ] [ 1XXX XXXX ]*3 [ 0XXX XXXX ]

6 years agoCLEANUP: peers: Replace hard-coded values by macros.
Frédéric Lécaille [Fri, 24 May 2019 12:32:27 +0000 (14:32 +0200)] 
CLEANUP: peers: Replace hard-coded values by macros.

All the peer stick-table messages are made of a 2-byte header (PEER_MSG_HEADER_LEN)
followed by the encoded length of the remaining data wich is harcoded as 5 (in bytes)
for the maximum (PEER_MSG_ENCODED_LENGTH_MAXLEN). With such a length we can encode
a maximum length which equals to (1 << 32) - 1, which is from far enough.

This patches replaces both these values by macros where applicable.

6 years agoCLEANUP: peers: Remove tabs characters.
Frédéric Lécaille [Wed, 15 May 2019 08:49:13 +0000 (10:49 +0200)] 
CLEANUP: peers: Remove tabs characters.

This patch only replaces very annoying tabulation characters by spaces
so that not to have to use again tabulations where they should not be used.

6 years agoBUILD: task: fix a build warning when threads are disabled
Willy Tarreau [Tue, 4 Jun 2019 15:16:29 +0000 (17:16 +0200)] 
BUILD: task: fix a build warning when threads are disabled

The __decl_hathreads() macro will leave a lone semi-colon making the end
of variables declarations, resulting in a warning if threads are disabled.
Let's simply swap it with the last variable. Thanks to Ilya Shipitsin for
reporting this issue.

No backport is needed.

6 years agoBUG/MEDIUM: vars: make the tcp/http unset-var() action support conditions
Willy Tarreau [Tue, 4 Jun 2019 14:43:29 +0000 (16:43 +0200)] 
BUG/MEDIUM: vars: make the tcp/http unset-var() action support conditions

Patrick Hemmer reported that http-request unset-var(foo) if ... fails to
parse. The reason is that it reuses the same parser as "set-var(foo)" which
makes a special case of the arguments, supposed to be a sample expression
for set-var, but which must not exist for unset-var. Unfortunately the
parser finds "if" or "unless" and believes it's an expression. Let's simply
drop the test so that the outer rule parser deals with potential extraneous
keywords.

This should be backported to all versions supporting unset-var().

6 years agoBUG/MEDIUM: vars: make sure the scope is always valid when accessing vars
Willy Tarreau [Tue, 4 Jun 2019 14:27:36 +0000 (16:27 +0200)] 
BUG/MEDIUM: vars: make sure the scope is always valid when accessing vars

Patrick Hemmer reported that a simple tcp rule involving a variable like
this is enough to crash haproxy :

    frontend foo
        bind :8001
        tcp-request session set-var(txn.foo) src

The tests on the variables scopes is not strict enough, it needs to always
verify if the stream is valid when accessing a req/res/txn variable. This
patch does this by adding a new get_vars() function which does the job
instead of open-coding all the lookups everywhere.

It must be backported to all versions supporting set-var and
"tcp-request session" so at least 1.9 and 1.8.

6 years agoBUILD: tools: do not use the weak attribute for trace() on obsolete linkers
Willy Tarreau [Tue, 4 Jun 2019 14:02:26 +0000 (16:02 +0200)] 
BUILD: tools: do not use the weak attribute for trace() on obsolete linkers

The default dummy trace() function is marked weak in order to be easily
replaced at link time. Some linkers are having issues with the weak
attribute, so let's not mark it on these linkers. They will simply not
be able to build with TRACE=1, which is no big deal since it's only used
by developers.

6 years agoMINOR: server: increase the default pool-purge-delay to 5 seconds
Willy Tarreau [Tue, 4 Jun 2019 12:06:31 +0000 (14:06 +0200)] 
MINOR: server: increase the default pool-purge-delay to 5 seconds

The default used to be a very aggressive delay of 1 second before starting
to purge idle connections, but tests show that with bursty traffic it's a
bit short. Let's increase this to 5 seconds.

6 years agoMEDIUM: stream: make a full process_stream() loop when completing I/O on exit
Willy Tarreau [Mon, 3 Jun 2019 15:27:52 +0000 (17:27 +0200)] 
MEDIUM: stream: make a full process_stream() loop when completing I/O on exit

During 1.9 development cycle a shortcut was made in process_stream() to
update the analysers immediately after an I/O even detected on the send()
path while leaving the function. In order to prevent this from being abused
by a single stream stealing all the CPU, the loop didn't cover the initial
recv() call, so that events ultimately converge.

This has caused a number of issues over time because the conditions to
decide to loop are a bit tricky. For example the CF_READ_PARTIAL flag is
not immediately removed from rqf_last and may appear for a long time at
this point, sometimes causing some loops to last long.

Another unexpected side effect is that all analysers are called again with
no data to process, just because CF_WRITE_PARTIAL is present. We cannot get
rid of this event even if of very rare use, because some analysers might
wait for some data to leave a buffer before proceeding. With a full loop,
this event would have been merged with a subsequent recv() allowing analysers
to do something more useful than just ack an event they don't care about.

While during early 1.9-dev it was very important to be kind with the
scheduler, nowadays it's lock-free for local tasks so this optimization
is much less interesting to use it for I/Os, especially if we factor in
the trouble it causes.

This patch thus removes the use of the loop for regular I/Os and instead
performs a task_wakeup() with an I/O event so that the task will be
scheduled after all other ones and will have a chance to perform another
recv() and possibly to gather more I/O events to be processed at once.
Synchronous errors and transitions to SI_ST_DIS however are still handled
by the loop.

Doing so significantly reduces the average number of calls to analysers
(those are typically halved when compression is enabled in legacy mode),
and as a side benefit, has increased the H1 performance by about 1%.

6 years agoCONTRIB: debug: add 4 missing connection/conn_stream flags
Willy Tarreau [Mon, 3 Jun 2019 12:26:54 +0000 (14:26 +0200)] 
CONTRIB: debug: add 4 missing connection/conn_stream flags

The following flags were missing thus added :
- CO_FL_SOCKS4_RECV
- CO_FL_SOCKS4_SEND
- CS_FL_READ_PARTIAL
- CS_FL_KILL_CONN

6 years agoCLEANUP: connection: remove the now unused CS_FL_REOS flag
Willy Tarreau [Mon, 3 Jun 2019 12:23:33 +0000 (14:23 +0200)] 
CLEANUP: connection: remove the now unused CS_FL_REOS flag

Let's remove it before it gets uesd again. It was mostly replaced with
CS_FL_EOI and by mux-specific states or flags.

6 years agoMEDIUM: mux-h1: don't use CS_FL_REOS anymore
Willy Tarreau [Mon, 3 Jun 2019 12:18:22 +0000 (14:18 +0200)] 
MEDIUM: mux-h1: don't use CS_FL_REOS anymore

This flag was already removed from other muxes and from the upper layers,
because it was misused. It indicates to the mux that the end of a stream
was already seen and is pending after existing data, but this should not
be on the conn_stream but internal to the mux.

This patch creates a new H1S flag H1S_F_REOS to replace it and uses it to
replace the last uses of CS_FL_REOS.

6 years agoBUG/MEDIUM: mux-h1: only check input data for the current stream, not next one
Willy Tarreau [Mon, 3 Jun 2019 11:42:54 +0000 (13:42 +0200)] 
BUG/MEDIUM: mux-h1: only check input data for the current stream, not next one

The mux-h1 doesn't properly propagate end of streams to the application
layer when requests are pipelined. This is visible by launching h2load
in h1 mode with -m greater than 1 : issuing Ctrl-C has no effect until
the client timeout expires.

The reason is that among the checks conditionning the reporting of the
end of stream status and waking up the streams, is a test on the presence
of remaining input data in the demux. But with pipelining, these data may
be present for another stream and should not prevent the end of stream
condition from being reported.

This patch addresses this issue by introducing a new function
"h1s_data_pending" which returns a boolean indicating if there are in
the demux buffer any data for the current stream. That is, if the stream
is in H1_MSG_DONE state, there are never any data for it. And if it's in
a different state, then the demux buffer is checked. This replaces the
tests on b_data(&h1c->ibuf) and correctly allows end of streams to be
reported at the end of requests.

It's worth noting that 1.9 doesn't suffer from this issue but it possibly
isn't completely immune either given that the same tests are present.

6 years agoMINOR: mux-h1: don't try to recv() before the connection is ready
Willy Tarreau [Mon, 3 Jun 2019 08:12:22 +0000 (10:12 +0200)] 
MINOR: mux-h1: don't try to recv() before the connection is ready

Just as we already do in h1_send(), if the connection is not yet ready,
do not proceed and instead subscribe. This avoids a needless recvfrom()
and subscription to polling for a case which will never work since the
request was not even sent.

6 years agoMINOR: connection: also stop receiving after a SOCKS4 response
Willy Tarreau [Mon, 3 Jun 2019 08:14:18 +0000 (10:14 +0200)] 
MINOR: connection: also stop receiving after a SOCKS4 response

Just as is done in previous patch for all handshake handlers,
also stop receiving after a SOCKS4 response was received. This
one escaped the previous cleanup but must be done to keep the
code safe.

6 years agoBUG/MEDIUM: connection: fix multiple handshake polling issues
Willy Tarreau [Mon, 3 Jun 2019 06:17:30 +0000 (08:17 +0200)] 
BUG/MEDIUM: connection: fix multiple handshake polling issues

Connection handshakes were rarely stacked on top of each other, but the
recent experiments consisting in sending PROXY over SOCKS4 revealed a
number of issues in these lower layers. First, each handler waiting for
data MUST subscribe to recv events with __conn_sock_want_recv() and MUST
unsubscribe from send events using __conn_sock_stop_send() to avoid any
wake-up loop in case a previous sender has set this. Second, each handler
waiting for sending MUST subscribe to send events with __conn_sock_want_send()
and MUST unsubscribe from recv events using __conn_sock_stop_recv() to
avoid any wake-up loop in case some data are available on the connection.

Till now this was done at various random places, and in particular the
cases where the FD was not ready for recv forgot to re-enable reading.

Second, while senders can happily use conn_sock_send() which automatically
handles EINTR, loops, and marks the FD as not ready with fd_cant_send(),
there is no equivalent for recv so receivers facing EAGAIN MUST call
fd_cant_send() to enable polling. It could be argued that implementing
an equivalent conn_sock_recv() function could be useful and more
long-term proof than the current situation.

Third, both types of handlers MUST unsubscribe from their respective
events once they managed to do their job, and none may even play with
__conn_xprt_*(). Here again this was lacking, and one surprizing call
to __conn_xprt_stop_recv() was present in the proxy protocol parser
for TCP6 messages!

Thanks to Alexander Liu for his help on this issue.

This patch must be backported to 1.9 and possibly some older versions,
though the SOCKS parts should be dropped.

6 years ago[RELEASE] Released version 2.0-dev5 v2.0-dev5
Willy Tarreau [Sun, 2 Jun 2019 10:06:08 +0000 (12:06 +0200)] 
[RELEASE] Released version 2.0-dev5

Released version 2.0-dev5 with the following main changes :
    - BUILD: watchdog: use si_value.sival_int, not si_int for the timer's value
    - BUILD: signals: FreeBSD has SI_LWP instead of SI_TKILL
    - BUILD: watchdog: condition it to USE_RT
    - MINOR: raw_sock: report global traffic statistics
    - MINOR: stats: report the global output bit rate in human readable form
    - BUG/MINOR: proto-htx: Try to keep connections alive on redirect
    - BUG/MEDIUM: spoe: Don't use the SPOE applet after releasing it
    - BUG/MINOR: lua: Set right direction and flags on new HTTP objects
    - BUG/MINOR: mux-h2: Count EOM in bytes sent when a HEADERS frame is formatted
    - BUG/MINOR: mux-h1: Report EOI instead EOS on parsing error or H2 upgrade
    - BUG/MEDIUM: proto-htx: Not forward too much data when 1xx reponses are handled
    - BUG/MINOR: htx: Remove a forgotten while loop in htx_defrag()
    - DOC: fix typos
    - BUG/MINOR: ssl_sock: Fix memory leak when disabling compression
    - OPTIM: freq-ctr: don't take the date lock for most updates
    - MEDIUM: mux-h2: avoid doing expensive buffer realigns when not absolutely needed
    - CLEANUP: debug: remove the TRACE() macro
    - MINOR: buffer: introduce b_make() to make a buffer from its parameters
    - MINOR: buffer: add a new buffer ring API to manipulate rings of buffers
    - MEDIUM: mux-h2: replace all occurrences of mbuf with a buffer ring
    - MEDIUM: mux-h2: make the conditions to send based on mbuf, not just its tail
    - MINOR: mux-h2: introduce h2_release_mbuf() to release all buffers in the mbuf ring
    - MEDIUM: mux-h2: make the send() function iterate over all mux buffers
    - CLEANUP: mux-h2: consistently use a local variable for the mbuf
    - MINOR: mux-h2: report the mbuf's head and tail in "show fd"
    - MAJOR: mux-h2: switch to next mux buffer on buffer full condition.
    - BUILD: connections: shut up gcc about impossible out-of-bounds warning
    - BUILD: ssl: fix latest LibreSSL reg-test error
    - MINOR: cli/activity: remove "fd_del" and "fd_skip" from show activity
    - MINOR: cli/activity: add 3 general purpose counters in development mode
    - BUG/MAJOR: lb/threads: make sure the avoided server is not full on second pass
    - BUG/MEDIUM: queue: fix the tree walk in pendconn_redistribute.
    - BUG/MEDIUM: threads: fix double-word CAS on non-optimized 32-bit platforms
    - MEDIUM: config: now alert when two servers have the same name
    - MINOR: htx: Remove the macro IS_HTX_SMP() and always use IS_HTX_STRM() instead
    - MINOR: htx: Move the macro IS_HTX_STRM() in proto/stream.h
    - MINOR: htx: Store the head position instead of the wrap one
    - MINOR: htx: Store start-line block's position instead of address of its payload
    - MINOR: htx: Add functions to get the first block of an HTX message
    - MINOR: mux-h2/htx: Get the start-line from the head when HEADERS frame is built
    - MINOR: htx: Replace the function http_find_stline() by http_get_stline()
    - CLEANUP: htx: Remove unused function htx_get_stline()
    - MINOR: http/htx: Use sl_pos directly to replace the start-line
    - MEDIUM: http/htx: Perform analysis relatively to the first block
    - MINOR: channel/htx: Call channel_htx_recv_max() from channel_recv_max()
    - MINOR: htx: Add function htx_get_max_blksz()
    - BUG/MINOR: htx: Change htx_xfer_blk() to also count metadata
    - MEDIUM: mux-h1: Use the count value received from the SI in h1_rcv_buf()
    - MINOR: mux-h2: Use the count value received from the SI in h2_rcv_buf()
    - MINOR: stream-int: Don't use the flag CO_RFL_KEEP_RSV anymore in si_cs_recv()
    - MINOR: connection: Remove the unused flag CO_RFL_KEEP_RSV
    - MINOR: mux-h2/htx: Support zero-copy when possible in h2_rcv_buf()
    - MINOR: htx: Add a field to set the memory used by headers in the HTX start-line
    - MINOR: h2/htx: Set hdrs_bytes on the SL when an HTX message is produced
    - MINOR: mux-h1: Set hdrs_bytes on the SL when an HTX message is produced
    - MINOR: htx: Be sure to xfer all headers in one time in htx_xfer_blks()
    - MEDIUM: htx: 1xx messages are now part of the final reponses
    - MINOR: channel/htx: Add function to forward headers of an HTX message
    - MINOR: filters/htx: Use channel_htx_fwd_headers() after headers filtering
    - MINOR: proto-htx: Use channel_htx_fwd_headers() to forward 1xx responses
    - MEDIUM: htx: Store the first block position instead of the start-line one
    - MINOR: stats/htx: don't use the first block position but the head one
    - MINOR: channel/htx: Add functions to forward a part or all HTX payload
    - MINOR: proto-htx: Use channel_htx_fwd_all() when unfiltered body are forwarded
    - MEDIUM: filters/htx: Filter body relatively to the first block
    - MINOR: htx: Optimize htx_drain() when all data are drained
    - MINOR: htx: don't rely on htx_find_blk() anymore in the function htx_truncate()
    - MINOR: htx: remove the unused function htx_find_blk()
    - MINOR: htx: Remove support of pseudo headers because it is unused
    - BUG/MEDIUM: http: fix "http-request reject" when not final
    - MINOR: ssl: Make sure the underlying xprt's init method doesn't fail.
    - MINOR: ssl: Don't forget to call the close method of the underlying xprt.
    - MINOR: htx: rename htx_append_blk_value() to htx_add_data_atonce()
    - MINOR: htx: make htx_add_data() return the transmitted byte count
    - MEDIUM: htx: make htx_add_data() never defragment the buffer
    - MINOR: activity: write totals on the "show activity" output
    - MINOR: activity: report totals and average separately
    - MEDIUM: poller: separate the wait time from the wake events
    - MINOR: activity: report the number of failed pool/buffer allocations
    - MEDIUM: buffers: relax the buffer lock a little bit
    - MINOR: task: turn the WQ lock to an RW_LOCK
    - MEDIUM: task: don't grab the WR lock just to check the WQ
    - BUG/MEDIUM: mux-h1: Don't skip the TCP splicing when there is no more data to read
    - MEDIUM: sessions: Introduce session flags.
    - BUG/MEDIUM: h2: Don't forget to set h2s->cs to NULL after having free'd cs.
    - BUG/MEDIUM: mux-h2: fix the conditions to end the h2_send() loop
    - BUG/MEDIUM: mux-h2: don't refrain from offering oneself a used buffer
    - BUG/MEDIUM: connection: Use the session to get the origin address if needed.
    - MEDIUM: tasks: Get rid of active_tasks_mask.
    - MEDIUM: connection: Upstream SOCKS4 proxy support
    - BUILD: contrib/prometheus: fix build breakage caused by move of idle_pct
    - BUG/MINOR: deinit/threads: make hard-stop-after perform a clean exit

6 years agoBUG/MINOR: deinit/threads: make hard-stop-after perform a clean exit
Willy Tarreau [Sun, 2 Jun 2019 09:11:29 +0000 (11:11 +0200)] 
BUG/MINOR: deinit/threads: make hard-stop-after perform a clean exit

As reported in GH issue #99, when hard-stop-after triggers and threads
are in use, the chance that any thread releases the resources in use by
the other ones is non-null. Thus no thread should be allowed to deinit()
nor exit by itself.

Here we take a different approach. We simply use a 3rd possible value
for the "killed" variable so that all threads know they must break out
of the run-poll-loop and immediately stop.

This patch was tested by commenting the stream_shutdown() calls in
hard_stop() to increase the chances to see a stream use released
resources. With this fix applied, it never crashes anymore.

This fix should be backported to 1.9 and 1.8.

6 years agoBUILD: contrib/prometheus: fix build breakage caused by move of idle_pct
Willy Tarreau [Sun, 2 Jun 2019 08:38:48 +0000 (10:38 +0200)] 
BUILD: contrib/prometheus: fix build breakage caused by move of idle_pct

The idle_pct thread-local variable was moved to struct thread_info by
commit 81036f2 ("MINOR: time: move the cpu, mono, and idle time to
thread_info") but not updated in service-prometheus.c, thus breaking
it.

No backport is needed. This fixes GH issue #110.

6 years agoMEDIUM: connection: Upstream SOCKS4 proxy support
Alexander Liu [Wed, 22 May 2019 11:44:48 +0000 (19:44 +0800)] 
MEDIUM: connection: Upstream SOCKS4 proxy support

Have "socks4" and "check-via-socks4" server keyword added.
Implement handshake with SOCKS4 proxy server for tcp stream connection.
See issue #82.

I have the "SOCKS: A protocol for TCP proxy across firewalls" doc found
at "https://www.openssh.com/txt/socks4.protocol". Please reference to it.

[wt: for now connecting to the SOCKS4 proxy over unix sockets is not
 supported, and mixing IPv4/IPv6 is discouraged; indeed, the control
 layer is unique for a connection and will be used both for connecting
 and for target address manipulation. As such it may for example report
 incorrect destination addresses in logs if the proxy is reached over
 IPv6]

6 years agoMEDIUM: tasks: Get rid of active_tasks_mask.
Olivier Houchard [Wed, 29 May 2019 17:22:43 +0000 (19:22 +0200)] 
MEDIUM: tasks: Get rid of active_tasks_mask.

Remove the active_tasks_mask variable, we can deduce if we've work to do
by other means, and it is costly to maintain. Instead, introduce a new
function, thread_has_tasks(), that returns non-zero if there's tasks
scheduled for the thread, zero otherwise.

6 years agoBUG/MEDIUM: connection: Use the session to get the origin address if needed.
Olivier Houchard [Wed, 29 May 2019 15:08:03 +0000 (17:08 +0200)] 
BUG/MEDIUM: connection: Use the session to get the origin address if needed.

In conn_si_send_proxy(), if we don't have a conn_stream yet, because the mux
won't be created until the SSL handshake is done, retrieve the opposite's
connection from the session. At this point, we know the session associated
with the connection is the one that initiated it, and we can thus just use
the session's origin.

This should be backported to 1.9.

6 years agoBUG/MEDIUM: mux-h2: don't refrain from offering oneself a used buffer
Willy Tarreau [Wed, 29 May 2019 15:50:48 +0000 (17:50 +0200)] 
BUG/MEDIUM: mux-h2: don't refrain from offering oneself a used buffer

Usually when calling offer_buffer(), we don't expect to offer it to
ourselves. But with h2 we have the same buffer_wait for the two directions
so we can unblock the recv path when completing a send(), or we can unblock
part of the mux buffer after sending the first few buffers that we managed
to collect. Thus it is important to always accept to wake up any requester.

A few parts of this patch could possibly be backported but earlier versions
already have other issues related to low-buffer condition so it's not sure
it's worth taking the risk to make things worse.

6 years agoBUG/MEDIUM: mux-h2: fix the conditions to end the h2_send() loop
Willy Tarreau [Wed, 29 May 2019 15:36:37 +0000 (17:36 +0200)] 
BUG/MEDIUM: mux-h2: fix the conditions to end the h2_send() loop

The test for the mux alloc failure in h2_send() right after an attempt
at h2_process_mux() used to make sense as it tried to detect that this
latter failed to produce data. But now that we have a list of buffers,
it is a perfectly valid situation where there can still be data in the
buffer(s).

So now when we see this flag we only declare it's the last run on the
loop. In addition we need to make sure we break out of the loop on
snd_buf failure, or we'll loop indefinitely, for example when the buf
is full and we can't send.

No backport is needed.

6 years agoBUG/MEDIUM: h2: Don't forget to set h2s->cs to NULL after having free'd cs.
Olivier Houchard [Wed, 29 May 2019 14:44:17 +0000 (16:44 +0200)] 
BUG/MEDIUM: h2: Don't forget to set h2s->cs to NULL after having free'd cs.

In h2c_frt_stream_new, if we failed to create the stream for some reason,
don't forget to set h2s->cs to NULL before calling h2s_destroy(), otherwise
h2s_destroy() will call h2s_close(), which will attempt to access
h2s->cs->flags if it's non-NULL.

This should be backported to 1.9.

6 years agoMEDIUM: sessions: Introduce session flags.
Olivier Houchard [Wed, 29 May 2019 13:01:50 +0000 (15:01 +0200)] 
MEDIUM: sessions: Introduce session flags.

Add session flags, and add a new flag, SESS_FL_PREFER_LAST, to be set when
we use NTLM authentication, and we should reuse the last connection. This
should fix using NTLM with HTX. This totally replaces TX_PREFER_LAST.

This should be backported to 1.9.

6 years agoBUG/MEDIUM: mux-h1: Don't skip the TCP splicing when there is no more data to read
Christopher Faulet [Wed, 29 May 2019 12:35:24 +0000 (14:35 +0200)] 
BUG/MEDIUM: mux-h1: Don't skip the TCP splicing when there is no more data to read

When there is no more data to read (h1m->curr_len == 0 in the state
H1_MSG_DATA), we still call xprt->rcv_pipe() callback. It is important to update
connection's flags. Especially to remove the flag CO_FL_WAIT_ROOM. Otherwise,
the pipe remains marked as full, preventing the stream-interface to fallback on
rcv_buf(). So the connection may be freezed because no more data is received and
the mux H1 remains blocked in the state H1_MSG_DATA.

This patch must be backported to 1.9.

6 years agoMEDIUM: task: don't grab the WR lock just to check the WQ
Willy Tarreau [Tue, 28 May 2019 16:57:25 +0000 (18:57 +0200)] 
MEDIUM: task: don't grab the WR lock just to check the WQ

When profiling locks, it appears that the WQ's lock has become the most
contended one, despite the WQ being split by thread. The reason is that
each thread takes the WQ lock before checking if it it does have something
to do. In practice the WQ almost only contains health checks and rare tasks
that can be scheduled anywhere, so this is a real waste of resources.

This patch proceeds differently. Now that the WQ's lock was turned to RW
lock, we proceed in 3 phases :
  1) locklessly check for the queue's emptiness

  2) take an R lock to retrieve the first element and check if it is
     expired. This way most visits are performed with an R lock to find
     and return the next expiration date.

  3) if one expiration is found, we perform the WR-locked lookup as
     usual.

As a result, on a one-minute test involving 8 threads and 64 streams at
1.3 million ctxsw/s, before this patch the lock profiler reported this :

    Stats about Lock TASK_WQ:
         # write lock  : 1125496
         # write unlock: 1125496 (0)
         # wait time for write     : 263.143 msec
         # wait time for write/lock: 233.802 nsec
         # read lock   : 0
         # read unlock : 0 (0)
         # wait time for read      : 0.000 msec
         # wait time for read/lock : 0.000 nsec

And after :

    Stats about Lock TASK_WQ:
         # write lock  : 173
         # write unlock: 173 (0)
         # wait time for write     : 0.018 msec
         # wait time for write/lock: 103.988 nsec
         # read lock   : 1072706
         # read unlock : 1072706 (0)
         # wait time for read      : 60.702 msec
         # wait time for read/lock : 56.588 nsec

Thus the contention was divided by 4.3.

6 years agoMINOR: task: turn the WQ lock to an RW_LOCK
Willy Tarreau [Tue, 28 May 2019 16:48:07 +0000 (18:48 +0200)] 
MINOR: task: turn the WQ lock to an RW_LOCK

For now it's exclusively used as a write lock though, thus it remains
100% equivalent to the spinlock it replaces.

6 years agoMEDIUM: buffers: relax the buffer lock a little bit
Willy Tarreau [Tue, 28 May 2019 15:21:18 +0000 (17:21 +0200)] 
MEDIUM: buffers: relax the buffer lock a little bit

In lock profiles it's visible that there is a huge contention on the
buffer lock. The reason is that when offer_buffers() is called, it
systematically takes the lock before verifying if there is any
waiter. However doing so doesn't protect against races since a
waiter can happen just after we release the lock as well. Similarly
in h2 we take the lock every time an h2c is going to be released,
even without checking that the h2c belongs to a wait list. These
two have now been addressed by verifying non-emptiness of the list
prior to taking the lock.

6 years agoMINOR: activity: report the number of failed pool/buffer allocations
Willy Tarreau [Tue, 28 May 2019 15:04:16 +0000 (17:04 +0200)] 
MINOR: activity: report the number of failed pool/buffer allocations

Haproxy is designed to be able to continue to run even under very low
memory conditions. However this can sometimes have a serious impact on
performance that it hard to diagnose. Let's report counters of failed
pool and buffer allocations per thread in show activity.

6 years agoMEDIUM: poller: separate the wait time from the wake events
Willy Tarreau [Tue, 28 May 2019 14:44:05 +0000 (16:44 +0200)] 
MEDIUM: poller: separate the wait time from the wake events

We have been abusing the do_poll()'s timeout for a while, making it zero
whenever there is some known activity. The problem this poses is that it
complicates activity diagnostic by incrementing the poll_exp field for
each known activity. It also requires extra computations that could be
avoided.

This change passes a "wake" argument to say that the poller must not
sleep. This simplifies the operations and allows one to differenciate
expirations from activity.

6 years agoMINOR: activity: report totals and average separately
Willy Tarreau [Tue, 28 May 2019 14:32:06 +0000 (16:32 +0200)] 
MINOR: activity: report totals and average separately

Some fields need to be averaged instead of summed (e.g. avg_poll_us)
when reported on the CLI. Let's have a distinct macro for this.

6 years agoMINOR: activity: write totals on the "show activity" output
Willy Tarreau [Tue, 28 May 2019 13:09:08 +0000 (15:09 +0200)] 
MINOR: activity: write totals on the "show activity" output

Most of the time we find ourselves adding per-thread fields to observe
activity, so let's compute these on the fly and display them. Now the
output shows "field: total [ thr0 thr1 ... thrn ]".

6 years agoMEDIUM: htx: make htx_add_data() never defragment the buffer
Willy Tarreau [Tue, 28 May 2019 08:58:50 +0000 (10:58 +0200)] 
MEDIUM: htx: make htx_add_data() never defragment the buffer

Now instead of trying to fit 100% of the input data into the output
buffer at the risk of defragmenting it, we put what fits into it only
and return the amount of bytes transferred. In a test, compared to the
previous commit, it increases the cached data rate from 44 Gbps to
55 Gbps and saves a lot in case of large buffers : with a 1 MB buffer,
uncached transfers jumped from 700 Mbps to 30 Gbps.

6 years agoMINOR: htx: make htx_add_data() return the transmitted byte count
Willy Tarreau [Tue, 28 May 2019 08:30:11 +0000 (10:30 +0200)] 
MINOR: htx: make htx_add_data() return the transmitted byte count

In order to later allow htx_add_data() to transmit partial blocks and
avoid defragmenting the buffer, we'll need to return the number of bytes
consumed. This first modification makes the function do this and its
callers take this into account. At the moment the function still works
atomically so it returns either the block size or zero. However all
call places have been adapted to consider any value between zero and
the block size.

6 years agoMINOR: htx: rename htx_append_blk_value() to htx_add_data_atonce()
Willy Tarreau [Tue, 28 May 2019 08:23:46 +0000 (10:23 +0200)] 
MINOR: htx: rename htx_append_blk_value() to htx_add_data_atonce()

This function is now dedicated to data blocks, and we'll soon need to
access it from outside in a rare few cases. Let's rename it and export
it.

6 years agoMINOR: ssl: Don't forget to call the close method of the underlying xprt.
Olivier Houchard [Thu, 23 May 2019 16:41:47 +0000 (18:41 +0200)] 
MINOR: ssl: Don't forget to call the close method of the underlying xprt.

In ssl_sock_close(), don't forget to call the underlying xprt's close method
if it exists. For now it's harmless not to do so, because the only available
layer is the raw socket, which doesn't have a close method, but that will
change when we implement QUIC.

6 years agoMINOR: ssl: Make sure the underlying xprt's init method doesn't fail.
Olivier Houchard [Thu, 23 May 2019 16:24:07 +0000 (18:24 +0200)] 
MINOR: ssl: Make sure the underlying xprt's init method doesn't fail.

In ssl_sock_init(), when initting the underlying xprt, check the return value,
and give up if it fails.

6 years agoBUG/MEDIUM: http: fix "http-request reject" when not final
Willy Tarreau [Tue, 28 May 2019 06:26:17 +0000 (08:26 +0200)] 
BUG/MEDIUM: http: fix "http-request reject" when not final

When "http-request reject" was introduced in 1.8 with commit 53275e8b0
("MINOR: http: implement the "http-request reject" rule"), it was already
broken. The code mentions "it always returns ACT_RET_STOP" and obviously
a gross copy-paste made it ACT_RET_CONT. If the rule is the last one it
properly blocks, but if not the last one it gets ignored, as can be seen
with this simple configuration :

    frontend f1
        bind :8011
        mode http
        http-request reject
        http-request redirect location /

This trivial fix must be backported to 1.9 and 1.8. It is tracked by
github issue #107.

6 years agoMINOR: htx: Remove support of pseudo headers because it is unused
Christopher Faulet [Fri, 24 May 2019 12:54:00 +0000 (14:54 +0200)] 
MINOR: htx: Remove support of pseudo headers because it is unused

The code to handle pseudo headers is unused and with no real value. So remove
it.

6 years agoMINOR: htx: remove the unused function htx_find_blk()
Christopher Faulet [Thu, 23 May 2019 09:13:07 +0000 (11:13 +0200)] 
MINOR: htx: remove the unused function htx_find_blk()

6 years agoMINOR: htx: don't rely on htx_find_blk() anymore in the function htx_truncate()
Christopher Faulet [Thu, 23 May 2019 09:12:43 +0000 (11:12 +0200)] 
MINOR: htx: don't rely on htx_find_blk() anymore in the function htx_truncate()

the function htx_find_blk() is used by only one function, htx_truncate(). So
because this function does nothing very smart, we don't use it anymore. It will
be removed by another commit.

6 years agoMINOR: htx: Optimize htx_drain() when all data are drained
Christopher Faulet [Thu, 23 May 2019 09:11:52 +0000 (11:11 +0200)] 
MINOR: htx: Optimize htx_drain() when all data are drained

Instead of looping on the HTX message to drain all data, the message is now
reset..

6 years agoMEDIUM: filters/htx: Filter body relatively to the first block
Christopher Faulet [Thu, 23 May 2019 09:55:33 +0000 (11:55 +0200)] 
MEDIUM: filters/htx: Filter body relatively to the first block

The filters filtering HTX body, in the callback http_payload, must now loop on
an HTX message starting from the first block position. The offset passed as
parameter is relative to this position and not the head one. It is mandatory
because once filtered, data are now forwarded using the function
channel_htx_fwd_payload(). So the first block position is always updated.

6 years agoMINOR: proto-htx: Use channel_htx_fwd_all() when unfiltered body are forwarded
Christopher Faulet [Thu, 23 May 2019 09:53:17 +0000 (11:53 +0200)] 
MINOR: proto-htx: Use channel_htx_fwd_all() when unfiltered body are forwarded

So the first block position of the HTX message will always be updated
accordingly.

6 years agoMINOR: channel/htx: Add functions to forward a part or all HTX payload
Christopher Faulet [Thu, 23 May 2019 09:06:10 +0000 (11:06 +0200)] 
MINOR: channel/htx: Add functions to forward a part or all HTX payload

The functions channel_htx_fwd_payload() and channel_htx_fwd_all() should now be
used to forward, respectively, a part of the HTX payload or all of it. These
functions forward data and update the first block position.

6 years agoMINOR: stats/htx: don't use the first block position but the head one
Christopher Faulet [Thu, 23 May 2019 09:04:05 +0000 (11:04 +0200)] 
MINOR: stats/htx: don't use the first block position but the head one

Applets must never rely on the first block position to consume an HTX
message. The head position must be used instead. For the request it is always
the start-line. At this stage, it is not a bug, because the first position of
the request is never changed by HTX analysers.

6 years agoMEDIUM: htx: Store the first block position instead of the start-line one
Christopher Faulet [Thu, 23 May 2019 09:03:26 +0000 (11:03 +0200)] 
MEDIUM: htx: Store the first block position instead of the start-line one

We don't store the start-line position anymore in the HTX message. Instead we
store the first block position to analyze. For now, it is almost the same. But
once all changes will be made on this part, this position will have to be used
by HTX analyzers, and only in the analysis context, to know where the analyse
should start.

When new blocks are added in an HTX message, if the first block position is not
defined, it is set. When the block pointed by it is removed, it is set to the
block following it. -1 remains the value to unset the position. the first block
position is unset when the HTX message is empty. It may also be unset on a
non-empty message, meaning every blocks were already analyzed.

From HTX analyzers point of view, this position is always set during headers
analysis. When they are waiting for a request or a response, if it is unset, it
means the analysis should wait. But once the analysis is started, and as long as
headers are not forwarded, it points to the message start-line.

As mentionned, outside the HTX analysis, no code must rely on the first block
position. So multiplexers and applets must always use the head position to start
a loop on an HTX message.

6 years agoMINOR: proto-htx: Use channel_htx_fwd_headers() to forward 1xx responses
Christopher Faulet [Thu, 23 May 2019 08:33:12 +0000 (10:33 +0200)] 
MINOR: proto-htx: Use channel_htx_fwd_headers() to forward 1xx responses

Instead of doing it by hand, we now call the dedicated function to do so.

6 years agoMINOR: filters/htx: Use channel_htx_fwd_headers() after headers filtering
Christopher Faulet [Thu, 23 May 2019 08:31:07 +0000 (10:31 +0200)] 
MINOR: filters/htx: Use channel_htx_fwd_headers() after headers filtering

Instead of doing it by hand in the function flt_analyze_http_headers(), we now
call the dedicated function to do so.

6 years agoMINOR: channel/htx: Add function to forward headers of an HTX message
Christopher Faulet [Thu, 23 May 2019 08:01:34 +0000 (10:01 +0200)] 
MINOR: channel/htx: Add function to forward headers of an HTX message

The function channel_htx_fwd_headers() should now be used by HTX analyzers to
forward all headers of an HTX message, from the start-line to the corresponding
EOH. It takes care to update the star-line position.

6 years agoMEDIUM: htx: 1xx messages are now part of the final reponses
Christopher Faulet [Fri, 17 May 2019 06:37:28 +0000 (08:37 +0200)] 
MEDIUM: htx: 1xx messages are now part of the final reponses

1xx informational messages (all except 101) are now part of the HTTP reponse,
semantically speaking. These messages are not followed by an EOM anymore,
because a final reponse is always expected. All these parts can also be
transferred to the channel in same time, if possible. The HTX response analyzer
has been update to forward them in loop, as the legacy one.

6 years agoMINOR: htx: Be sure to xfer all headers in one time in htx_xfer_blks()
Christopher Faulet [Thu, 16 May 2019 09:30:31 +0000 (11:30 +0200)] 
MINOR: htx: Be sure to xfer all headers in one time in htx_xfer_blks()

In the function htx_xfer_blks(), we take care to transfer all headers in one
time. When the current block is a start-line, we check if there is enough space
to transfer all headers too. If not, and if the destination is empty, a parsing
error is reported on the source.

The H2 multiplexer is the only one to use this function. When a parsing error is
reported during the transfer, the flag CS_FL_EOI is also set on the conn_stream.

6 years agoMINOR: mux-h1: Set hdrs_bytes on the SL when an HTX message is produced
Christopher Faulet [Wed, 15 May 2019 13:54:39 +0000 (15:54 +0200)] 
MINOR: mux-h1: Set hdrs_bytes on the SL when an HTX message is produced

6 years agoMINOR: h2/htx: Set hdrs_bytes on the SL when an HTX message is produced
Christopher Faulet [Wed, 15 May 2019 13:53:20 +0000 (15:53 +0200)] 
MINOR: h2/htx: Set hdrs_bytes on the SL when an HTX message is produced

6 years agoMINOR: htx: Add a field to set the memory used by headers in the HTX start-line
Christopher Faulet [Wed, 15 May 2019 12:56:47 +0000 (14:56 +0200)] 
MINOR: htx: Add a field to set the memory used by headers in the HTX start-line

The field hdrs_bytes has been added in the structure htx_sl. It should be used
to set how many bytes are help by all headers, from the start-line to the
corresponding EOH block. it must be set to -1 if it is unknown.

6 years agoMINOR: mux-h2/htx: Support zero-copy when possible in h2_rcv_buf()
Christopher Faulet [Wed, 15 May 2019 08:07:59 +0000 (10:07 +0200)] 
MINOR: mux-h2/htx: Support zero-copy when possible in h2_rcv_buf()

If the channel's buffer is empty and the message is small enough, we can swap
the H2S buffer with the channel one.

6 years agoMINOR: connection: Remove the unused flag CO_RFL_KEEP_RSV
Christopher Faulet [Tue, 14 May 2019 20:47:37 +0000 (22:47 +0200)] 
MINOR: connection: Remove the unused flag CO_RFL_KEEP_RSV

6 years agoMINOR: stream-int: Don't use the flag CO_RFL_KEEP_RSV anymore in si_cs_recv()
Christopher Faulet [Tue, 14 May 2019 20:46:41 +0000 (22:46 +0200)] 
MINOR: stream-int: Don't use the flag CO_RFL_KEEP_RSV anymore in si_cs_recv()

Because the channel_recv_max() always return the right value, for HTX and legacy
streams, we don't need to set this flag. The multiplexer don't use it anymore.

6 years agoMINOR: mux-h2: Use the count value received from the SI in h2_rcv_buf()
Christopher Faulet [Tue, 14 May 2019 20:44:43 +0000 (22:44 +0200)] 
MINOR: mux-h2: Use the count value received from the SI in h2_rcv_buf()

Now, the SI calls h2_rcv_buf() with the right count value. So we can rely on
it. Unlike the H1 multiplexer, it is fairly easier for the H2 multiplexer
because the HTX message already exists, we only transfer blocks from the H2S to
the channel. And this part is handled by htx_xfer_blks().

6 years agoMEDIUM: mux-h1: Use the count value received from the SI in h1_rcv_buf()
Christopher Faulet [Fri, 17 May 2019 13:35:33 +0000 (15:35 +0200)] 
MEDIUM: mux-h1: Use the count value received from the SI in h1_rcv_buf()

Now, the SI calls h1_rcv_buf() with the right count value. So we can rely on
it. During the parsing, we now really respect this value to be sure to never
exceed it. To do so, once headers are parsed, we should estimate the size of the
HTX message before copying data.