]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
7 years agoMINOR: h2: lookup the stream during demuxing
Willy Tarreau [Tue, 17 Oct 2017 06:18:25 +0000 (08:18 +0200)] 
MINOR: h2: lookup the stream during demuxing

Several stream-oriented functions will need to perform this lookup, so
better centralize it.

7 years agoMEDIUM: h2: decode SETTINGS frames and extract relevant settings
Willy Tarreau [Thu, 27 Jul 2017 13:41:03 +0000 (15:41 +0200)] 
MEDIUM: h2: decode SETTINGS frames and extract relevant settings

The INITIAL_WINDOW_SIZE and MAX_FRAME_SIZE settings are now extracted
from the settings frame, assigned to the connection, and attempted to
be propagated to all existing streams as per the specification. In
practice clients rarely update the settings after sending the first
stream, so the propagation will rarely be used. The ACK is properly
sent after the frame is completely parsed.

7 years agoMINOR: h2: implement PING frames
Willy Tarreau [Tue, 10 Oct 2017 15:11:41 +0000 (17:11 +0200)] 
MINOR: h2: implement PING frames

Now we can detect and properly parse PING frames as well as emit a
response containing the same payload.

7 years agoMINOR: h2: create a stream parser for the demuxer
Willy Tarreau [Tue, 10 Oct 2017 13:56:59 +0000 (15:56 +0200)] 
MINOR: h2: create a stream parser for the demuxer

The function h2_process_demux() now tries to parse the incoming bytes
to process as many streams as possible. For now it does nothing but
dropping all incoming frames.

7 years agoMEDIUM: h2: detect the presence of the first settings frame
Willy Tarreau [Tue, 10 Oct 2017 13:16:55 +0000 (15:16 +0200)] 
MEDIUM: h2: detect the presence of the first settings frame

Instead of doing a special processing of the first SETTINGS frame, we
simply parse its header, check that it matches the expected frame type
and flags (ie no ACK), and switch to FRAME_P to parse it as any regular
frame. The regular frame parser will take care of decoding it.

7 years agoMINOR: h2: send a real SETTINGS frame based on the configuration
Willy Tarreau [Mon, 25 Sep 2017 14:25:39 +0000 (16:25 +0200)] 
MINOR: h2: send a real SETTINGS frame based on the configuration

An initial settings frame is emitted upon receipt of the connection
preface, which takes care of configured values. These settings are
only emitted when they differ from the protocol's default value :

  - header_table_size (defaults to 4096)
  - initial_window_size (defaults to 65535)
  - max_concurrent_streams (defaults to unlimited)
  - max_frame_size (defaults to 16384)

The max frame size is a copy of tune.bufsize. Clients will most often
reject values lower than 16384 and currently there's no trivial way to
check if H2 is going to be used at boot time.

7 years agoMEDIUM: h2: process streams pending for sending
Willy Tarreau [Tue, 17 Oct 2017 08:57:04 +0000 (10:57 +0200)] 
MEDIUM: h2: process streams pending for sending

The send() callback calls h2_process_mux() which iterates over the list
of flow controlled streams first, then streams waiting for room in the
send_list. If a stream from the send_list ends up being flow controlled,
it is then moved to the fctl_list. This way we can maintain the most
accurate fairness by ensuring that flows are always processed in order
of arrival except when they're blocked by flow control, in which case
only the other ones may pass in front of them.

It's a bit tricky as we want to remove a stream from the active lists
if it doesn't block (ie it has no reason for staying there).

7 years agoMEDIUM: h2: enable reading again on the connection if it was blocked on stream buffer...
Willy Tarreau [Mon, 30 Oct 2017 14:38:23 +0000 (15:38 +0100)] 
MEDIUM: h2: enable reading again on the connection if it was blocked on stream buffer full

If the polling update function is called with RD_ENA while H2_CF_DEM_SFULL
indicates the demux had to block on a stream buffer full condition, we can
remove the flag and re-enable polling for receiving because this is the
indication that a consumer stream has made some room in the buffer. Probably
that we should improve this to ensure that h2s->id == h2c->dsi and avoid
trying to receive multiple times in a row for the wrong stream.

7 years agoMEDIUM: h2: enable connection polling for send when a cs wants to emit
Willy Tarreau [Tue, 17 Oct 2017 08:26:19 +0000 (10:26 +0200)] 
MEDIUM: h2: enable connection polling for send when a cs wants to emit

A conn_stream indicates its intent to send by setting the WR_ENA flag
and calling mux->update_poll(). There's no synchronous write so the only
way to emit a response from a stream is to proceed this way. The sender
h2s is then queued into the h2c's send_list if it was not yet queued.

Once the connection is ready, it will enter its send() callback to visit
writers, calling their data->send_cb() callback to complete the operation
using mux->snd_buf().

Also we enable polling if the mux contains data and wasn't enabled. This
may happen just after a response has been transmitted using chk_snd().
It likely is incomplete for now and should probably be refined.

7 years agoMINOR: h2: match the H2 connection preface on init
Willy Tarreau [Fri, 22 Sep 2017 13:05:09 +0000 (15:05 +0200)] 
MINOR: h2: match the H2 connection preface on init

The H2 preface is properly detected to switch to the settings state.
It's important to note that for now we don't send out settings frame
so the operation is not complete yet.

7 years agoMINOR: h2: add a function to send a GOAWAY error frame
Willy Tarreau [Tue, 16 May 2017 19:51:05 +0000 (21:51 +0200)] 
MINOR: h2: add a function to send a GOAWAY error frame

For now it's only used to report immediate errors by announcing the
highest known stream-id on the mux's error path. The function may be
used both while processing a stream or directly in relation with the
connection. The wake() callback will automatically ask for send access
if an error is reported. The function should be usable for graceful
shutdowns as well by simply setting h2c->last_sid to the highest
acceptable stream-id (2^31-1) prior to calling the function.

A connection flag (H2_CF_GOAWAY_SENT) is set once the frame was
successfully sent. It will be usable to detect when it's safe to
close the connection.

Another flag (H2_CF_GOAWAY_FAILED) is set in case of unrecoverable
error while trying to send. It will also be used to know when it's safe
to close the connection.

7 years agoMEDIUM: h2: start to implement the frames processing loop
Willy Tarreau [Mon, 9 Oct 2017 14:21:43 +0000 (16:21 +0200)] 
MEDIUM: h2: start to implement the frames processing loop

The rcv_buf() callback now calls h2_process_demux() after an recv() call
leaving some data in the buffer, and the snd_buf() callback calls
h2_process_mux() to try to process pending data from streams.

7 years agoMEDIUM: h2: wake the connection up for send on pending streams
Willy Tarreau [Tue, 17 Oct 2017 13:30:07 +0000 (15:30 +0200)] 
MEDIUM: h2: wake the connection up for send on pending streams

If some streams were blocked on flow control and the connection's
window was recently opened, or if some streams are waiting while
no block flag remains, we immediately want to try to send again.
This can happen if a recv() for a stream wants to send after the
send() loop has already been processed.

7 years agoMEDIUM: h2: properly consider all conditions for end of connection
Willy Tarreau [Tue, 31 Oct 2017 05:59:15 +0000 (06:59 +0100)] 
MEDIUM: h2: properly consider all conditions for end of connection

During h2_wake(), there are various situations that can lead to the
connection being closed :
  - low-level connection error
  - read0 received
  - fatal error (ERROR2)
  - failed to emit a GOAWAY
  - empty stream list with max_id >= last_sid

In such cases, all streams are notified and we have to wait for all
streams to leave while doing nothing, or if the last stream is gone,
we can simply terminate the connection.

It's important to do this test there again because an error might arise
while trying to send a pending GOAWAY after the last stream for example,
thus there's possibly no way to get notified of a closing stream.

7 years agoMINOR: h2: also terminate the connection on shutr
Willy Tarreau [Mon, 9 Oct 2017 14:47:04 +0000 (16:47 +0200)] 
MINOR: h2: also terminate the connection on shutr

It happens that an H2 mux is totally unusable once the client has shut,
so we must consider this situation equivalent to the connection error,
and let the possible streams drain their data if needed then stop.

7 years agoMEDIUM: h2: start to consider the H2_CF_{MUX,DEM}_* flags for polling
Willy Tarreau [Mon, 9 Oct 2017 13:14:19 +0000 (15:14 +0200)] 
MEDIUM: h2: start to consider the H2_CF_{MUX,DEM}_* flags for polling

Now we start to set the flags to indicate that the response buffer is
being awaited or that it is full, it makes it possible to centralize a
little bit the polling management into the wake() callback.

In case of error, we wake all the streams up so that they are aware of
the nature of the event and are able to detach if needed.

7 years agoMINOR: h2: update the {MUX,DEM}_{M,D}ALLOC flags on buffer availability
Willy Tarreau [Mon, 25 Sep 2017 09:55:01 +0000 (11:55 +0200)] 
MINOR: h2: update the {MUX,DEM}_{M,D}ALLOC flags on buffer availability

Flag H2_CF_DEM_DALLOC is set when the demux buffer fails to be allocated
in the recv() callback, and is cleared when it succeeds.

Both flags H2_CF_MUX_MALLOC and H2_CF_DEM_MROOM are cleared when the mux
buffer allocation succeeds.

In both cases it will be up to the callers to report allocation failures.

7 years agoMINOR: h2: add the function to create a new stream
Willy Tarreau [Fri, 13 Oct 2017 17:07:26 +0000 (19:07 +0200)] 
MINOR: h2: add the function to create a new stream

This one will be used by the HEADERS frame handler and maybe later by
the PUSH frame handler. It creates a conn_stream in the mux's connection.

The create streams are inserted in the h2c's tree sorted by IDs. The
caller is expected to have verified that the stream doesn't exist yet.

7 years agoMINOR: h2: create dummy idle and closed streams
Willy Tarreau [Tue, 16 May 2017 13:20:39 +0000 (15:20 +0200)] 
MINOR: h2: create dummy idle and closed streams

It will be more convenient to always manipulate existing streams than
null pointers. Here we create one idle stream and one closed stream.
The idea is that we can easily point any stream to one of these states
in order to merge maintenance operations.

7 years agoMINOR: h2: add stream lookup function based on the stream ID
Willy Tarreau [Thu, 12 Oct 2017 15:35:14 +0000 (17:35 +0200)] 
MINOR: h2: add stream lookup function based on the stream ID

The function performs a simple lookup in the tree and returns
either the matching h2s or NULL if not found.

7 years agoMINOR: h2: add a few functions to retrieve contents from a wrapping buffer
Willy Tarreau [Tue, 10 Oct 2017 15:10:03 +0000 (17:10 +0200)] 
MINOR: h2: add a few functions to retrieve contents from a wrapping buffer

Functions h2_get_buf_n{16,32,64}() and h2_get_buf_bytes() respectively
extract a network-ordered 16/32/64 bit value from a possibly wrapping
buffer, or any arbitrary size. They're convenient to retrieve a PING
payload or to parse SETTINGS frames. Since they copy one byte at a time,
they will be less efficient than a memcpy-based implementation on large
blocks.

7 years agoMINOR: h2: new function h2_peek_frame_hdr() to retrieve a new frame header
Willy Tarreau [Tue, 11 Jul 2017 13:20:24 +0000 (15:20 +0200)] 
MINOR: h2: new function h2_peek_frame_hdr() to retrieve a new frame header

This function extracts the next frame header but doesn't consume it.
This will allow to detect a stream-id change and to perform a yielding
window update without losing information. The result is stored into a
temporary frame descriptor. We could also store the next frame header
into the connection but parsing the header again is much cheaper than
wasting bytes in the connection for a rare use case.

A function (h2_skip_frame_hdr()) is also provided to skip the parsed
header (always 9 bytes) and another one (h2_get_frame_hdr()) to do both
at once.

7 years agoMINOR: h2: add h2_set_frame_size() to update the size in a binary frame
Willy Tarreau [Thu, 27 Jul 2017 11:37:23 +0000 (13:37 +0200)] 
MINOR: h2: add h2_set_frame_size() to update the size in a binary frame

This function is called after preparing a frame, in order to update the
frame's size in the frame header. It takes the frame payload length in
argument.

It simply writes a 24-bit frame size into a buffer, making use of the
net_helper functions which try to optimize per platform (this is a
frequently used operation).

7 years agoMINOR: h2: new function h2s_error() to mark an error on a stream
Willy Tarreau [Tue, 17 Oct 2017 06:03:59 +0000 (08:03 +0200)] 
MINOR: h2: new function h2s_error() to mark an error on a stream

This one will store the error into the stream's errcode if it's neither
idle nor closed (since these ones are read-only) and switch its state to
H2_SS_ERROR. If a conn_stream is attached, it will be flagged with
CS_FL_ERROR.

7 years agoMINOR: h2: new function h2c_error to mark an error on the connection
Willy Tarreau [Tue, 17 Oct 2017 06:00:59 +0000 (08:00 +0200)] 
MINOR: h2: new function h2c_error to mark an error on the connection

This one sets the error code in h2c->errcode and changes the connection's
stat to H2_CS_ERROR.

7 years agoMINOR: h2: small function to know when the mux is busy
Willy Tarreau [Mon, 25 Sep 2017 14:17:25 +0000 (16:17 +0200)] 
MINOR: h2: small function to know when the mux is busy

A mux is busy when any stream id >= 0 is currently being handled
and the current stream's id doesn't match. When no stream is
involved (ie: demuxer), stream 0 is considered. This will be
necessary to know when it's possible to send frames.

7 years agoMINOR: h2: add function h2s_id() to report a stream's ID
Willy Tarreau [Mon, 23 Oct 2017 12:39:06 +0000 (14:39 +0200)] 
MINOR: h2: add function h2s_id() to report a stream's ID

This one supports being called with NULL and returns 0 in this case,
making it easier to check for stream IDs in various send functions.

7 years agoMINOR: h2: add the connection and stream flags listing the causes for blocking
Willy Tarreau [Mon, 25 Sep 2017 09:49:03 +0000 (11:49 +0200)] 
MINOR: h2: add the connection and stream flags listing the causes for blocking

A demux may be prevented from receiving for the following reasons :
  - no receive buffer could be allocated
  - the receive buffer is full
  - a response is needed and the mux is currently being used by a stream
  - a response is needed and some room could not be found in the mux
    buffer (either full or waiting for allocation)
  - the stream buffer is waiting for allocation
  - the stream buffer is full

A mux may stop accepting data for the following reasons :
  - the buffer could not be allocated
  - the buffer is full

A stream may stop sending data to a mux for the following reaons :
  - the mux is busy processing another stream
  - the mux buffer lacks room (full or not allocated)
  - the mux's flow control prevents from sending
  - the stream's flow control prevents from sending

All these conditions were turned into flags for use by the respective
places.

7 years agoMEDIUM: h2: implement the mux buffer allocator
Willy Tarreau [Fri, 22 Sep 2017 12:26:04 +0000 (14:26 +0200)] 
MEDIUM: h2: implement the mux buffer allocator

The idea is that we may need a mux buffer for anything, ranging from
receiving to sending traffic. For now it's unclear where exactly the
calls will be placed so let's block both send and recv when a buffer
is missing, and re-enable both of them at the end. This will have to
be changed later.

7 years agoMEDIUM: h2: dynamically allocate the demux buffer on Rx
Willy Tarreau [Fri, 22 Sep 2017 07:13:49 +0000 (09:13 +0200)] 
MEDIUM: h2: dynamically allocate the demux buffer on Rx

This patch implements a very basic Rx buffer management. The mux needs
an rx buffer to decode the connection's stream. If this buffer it
available upon Rx events, we fill it with whatever input data are
available. Otherwise we try to allocate it and subscribe to the buffer
wait queue in case of failure. In such a situation, a function
"h2_dbuf_available()" will be called once a buffer may be allocated.
The buffer is released if it's still empty after recv().

7 years agoMEDIUM: h2: implement basic recv/send/wake functions
Willy Tarreau [Mon, 9 Oct 2017 09:56:46 +0000 (11:56 +0200)] 
MEDIUM: h2: implement basic recv/send/wake functions

For now they don't do much since the buffers are not yet allocated, but
the squeletton is here.

7 years agoMEDIUM: h2: allocate and release the h2c context on connection init/end
Willy Tarreau [Fri, 22 Sep 2017 06:07:25 +0000 (08:07 +0200)] 
MEDIUM: h2: allocate and release the h2c context on connection init/end

The connection's h2c context is now allocated and initialized on mux
initialization, and released on mux destruction. Note that for now the
release() code is never called.

7 years agoMINOR: h2: add a frame header descriptor for incoming frames
Willy Tarreau [Thu, 21 Sep 2017 18:23:50 +0000 (20:23 +0200)] 
MINOR: h2: add a frame header descriptor for incoming frames

This descriptor will be used by the frame parser, it's designed to ease
manipulation of frame length, type, flags and sid.

7 years agoMINOR: h2: handle two extra stream states for errors
Willy Tarreau [Mon, 16 Oct 2017 16:34:34 +0000 (18:34 +0200)] 
MINOR: h2: handle two extra stream states for errors

We need to deal with stream error notifications (RST_STREAM) as well as
internal reporting. The problem is that we don't know in which order
this will be done so we can't unilaterally decide to deallocate the
stream. In order to help, we add two extra stream states, H2_SS_ERROR
and H2_SS_RESET. The former mentions that the stream has an error pending
and the latter indicates that the error was already sent and that the
stream is now closed. It's equivalent to H2_SS_CLOSED except that in this
state we'll avoid sending new RST_STREAM as per RFC7540#5.4.2.

With this it will be possible to only detach or deallocate the h2s once
the stream is closed.

7 years agoMINOR: h2: create the h2s struct and the associated pool
Willy Tarreau [Wed, 11 Oct 2017 05:57:07 +0000 (07:57 +0200)] 
MINOR: h2: create the h2s struct and the associated pool

This describes an HTTP/2 stream with its relation to the connection
and to the conn_stream on the other side.

For now we also allocate request and response state for HTTP/1 because
the internal HTTP representation is HTTP/1 at the moment. Later this
should evolve towards a version-agnostic representation and this H1
message state will disappear.

It's important to consider that the streams are necessarily polarized
depending on h2c : if the connection is incoming, streams initiated by
the connection receive requests and send responses. Otherwise it's the
other way around. Such information is known during the connection
instanciation by h2c_frt_init() and will normally be reflected in the
stream ID (odd=demux from client, even=demux from server). The initial
H2_CS_PREFACE state will also depend on the direction. The current h2c
state machine doesn't allow for outgoing connections as it uses a single
state for both (rx state only). It should be the demux state only.

7 years agoMINOR: h2: create the h2c struct and allocate its pool
Willy Tarreau [Fri, 22 Sep 2017 06:05:00 +0000 (08:05 +0200)] 
MINOR: h2: create the h2c struct and allocate its pool

The h2c struct describes an H2 connection context and is assigned as the
mux's context. It has its own pool, allocated at boot time and released
after deinit().

7 years agoMINOR: h2: expose tune.h2.max-concurrent-streams to limit the number of streams
Willy Tarreau [Thu, 27 Jul 2017 09:47:28 +0000 (11:47 +0200)] 
MINOR: h2: expose tune.h2.max-concurrent-streams to limit the number of streams

This will be advertised in the settings frame.

7 years agoMINOR: h2: expose tune.h2.initial-window-size to configure the window size
Willy Tarreau [Thu, 27 Jul 2017 09:45:11 +0000 (11:45 +0200)] 
MINOR: h2: expose tune.h2.initial-window-size to configure the window size

This will be advertised in the settings frame.

7 years agoMINOR: h2: expose tune.h2.header-table-size to configure the table size
Willy Tarreau [Thu, 27 Jul 2017 09:42:14 +0000 (11:42 +0200)] 
MINOR: h2: expose tune.h2.header-table-size to configure the table size

It's the HPACK header table size which is to be advertised in the settings
frames. It defaults to 4096.

7 years agoMINOR: h2: create a very minimalistic h2 mux
Willy Tarreau [Sun, 8 Oct 2017 21:01:42 +0000 (23:01 +0200)] 
MINOR: h2: create a very minimalistic h2 mux

This one currently does nothing and rejects every connection. It
registers ALPN token "h2".

7 years agoMINOR: h2: centralize all HTTP/2 protocol elements and constants
Willy Tarreau [Tue, 13 Dec 2016 17:25:15 +0000 (18:25 +0100)] 
MINOR: h2: centralize all HTTP/2 protocol elements and constants

These constants from RFC7540 will be centralized into common/h2.h for
use by the future h2 mux and other places.

7 years agoMEDIUM: hpack: implement basic hpack encoding
Willy Tarreau [Thu, 21 Sep 2017 12:35:57 +0000 (14:35 +0200)] 
MEDIUM: hpack: implement basic hpack encoding

For now it only supports literals and a bit of static header table
references for the 9 most common header field names (date, server,
content-type, content-length, last-modified, accept-ranges, etag,
cache-control, location).

A previous incarnation of this commit used to strip the forbidden H2
header names (connection, proxy-connection, upgrade, transfer-encoding,
keep-alive) but this is no longer the case as this filtering is irrelevant
to HPACK encoding and is specific to H2, so this will have to be done by
the caller.

It's quite not optimal but works fine enough to prepare some valid and
partially compressed responses during development.

7 years agoMINOR: hpack: implement the decoder
Willy Tarreau [Tue, 30 May 2017 17:09:44 +0000 (19:09 +0200)] 
MINOR: hpack: implement the decoder

The decoder is now fully functional. It makes use of the dynamic header
table. Dynamic header table size updates are currently ignored, as our
initially advertised value is the highest we support. Strictly speaking,
the impact is that a client referencing a header field after such an
update wouldn't observe an error instead of the connection being dropped
if it was implemented.

Decoded header fields are copied into a target buffer in HTTP/1 format
using HTTP/1.1 as the version. The Host header field is automatically
appended if a ":authority" header field is present.

All decoded header fields can be displayed if the file is compiled with
DEBUG_HPACK.

7 years agoMINOR: hpack: implement the header tables management
Willy Tarreau [Tue, 30 May 2017 16:46:58 +0000 (18:46 +0200)] 
MINOR: hpack: implement the header tables management

This code deals with header insertion, retrieval and eviction, as well
as with dynamic header table defragmentation. It is functional for use
as a decoder and was heavily tested in this context. There's still some
room for optimization (eg: the defragmentation code currently does it
in place using a memcpy).

Also for now the dynamic header table is allocated using malloc() while
a pool needs to be created instead.

This code was mostly imported from https://github.com/wtarreau/http2-exp
with "hpack_" prepended in front of most names to avoid risks of conflicts.
Some small cleanups and renamings were applied during the import. This
version must be considered more recent.

Some HPACK error codes were placed here (HPACK_ERR_*), not exactly because
they're needed by the decoder but they'll be needed by all callers. Maybe
a different location should be found.

7 years agoMINOR: hpack: implement the HPACK Huffman table decoder
Willy Tarreau [Tue, 30 May 2017 15:22:18 +0000 (17:22 +0200)] 
MINOR: hpack: implement the HPACK Huffman table decoder

The code was borrowed from the HPACK experimental implementations
available here :

    https://github.com/wtarreau/http2-exp

It contains the Huffman table as specified in RFC7541 Appendix B, and a
set of reverse tables used to decode a Huffman byte stream, and produced
by contrib/h2/gen-rht. The encoder is not finalized, it doesn't emit the
byte stream but this is not needed for now.

7 years agoCONTRIB: hpack: implement a reverse huffman table generator for hpack
Willy Tarreau [Fri, 19 May 2017 16:14:51 +0000 (18:14 +0200)] 
CONTRIB: hpack: implement a reverse huffman table generator for hpack

This one was built by studying the HPACK Huffman table (RFC7541
appendix B). It creates 5 small tables (4*512 bytes, 1*64 bytes) to
map one byte at a time from the input stream based on the following
observations :

 * rht_bit31_24[256]   is indexed on bits 31..24 when < 0xfe
 * rht_bit24_17[256]   is indexed on bits 24..17 when 31..24 >= 0xfe
 * rht_bit15_11_fe[32] is indexed on bits 15..11 when 24..17 == 0xfe
 * rht_bit15_8[256]    is indexed on bits 15..8 when 24..17 == 0xff
 * rht_bit11_4[256]    is indexed on bits 11..4 when 15..8 == 0xff
 * when 11..4 == 0xff, 3..2 provide the following mapping :
 *   00 => 0x0a, 01 => 0x0d, 10 => 0x16, 11 => EOS

7 years agoMEDIUM: session: make use of the connection's destroy callback
Willy Tarreau [Sun, 8 Oct 2017 09:26:30 +0000 (11:26 +0200)] 
MEDIUM: session: make use of the connection's destroy callback

Now we don't remove the session when a stream dies, instead we
detach the stream and let the mux decide to release the connection
and call session_free() instead.

7 years agoMINOR: session: release the listener with the session, not the stream
Willy Tarreau [Wed, 18 Oct 2017 13:01:14 +0000 (15:01 +0200)] 
MINOR: session: release the listener with the session, not the stream

Since multiple streams can share one session attached to one listener,
the listener_release() call must be done in session_free() and not in
stream_free(), otherwise we end up with a negative count in H2.

7 years agoMEDIUM: connection: add a destroy callback
Willy Tarreau [Sun, 8 Oct 2017 09:16:46 +0000 (11:16 +0200)] 
MEDIUM: connection: add a destroy callback

This callback will be used to release upper layers when a mux is in
use. Given that the mux can be asynchronously deleted, we need a way
to release the extra information such as the session.

This callback will be called directly by the mux upon releasing
everything and before the connection itself is released, so that
the callee can find its information inside the connection if needed.

The way it currently works is not perfect, and most likely this should
instead become a mux release callback, but for now we have no easy way
to add mux-specific stuff, and since there's one mux per connection,
it works fine this way.

7 years agoMEDIUM: checks: exclusively use cs_destroy() to release a connection
Willy Tarreau [Sun, 8 Oct 2017 09:10:19 +0000 (11:10 +0200)] 
MEDIUM: checks: exclusively use cs_destroy() to release a connection

This way we're using the more consistent API everywhere.

7 years agoMEDIUM: stream: do not forcefully close the client connection anymore
Willy Tarreau [Sun, 8 Oct 2017 09:33:44 +0000 (11:33 +0200)] 
MEDIUM: stream: do not forcefully close the client connection anymore

Now that the mux will take care of closing the client connection at the
right moment, we don't need to close the client connection anymore, and
we just need to close the conn_stream.

7 years agoMEDIUM: connection: make mux->detach() release the connection
Willy Tarreau [Sun, 8 Oct 2017 09:00:17 +0000 (11:00 +0200)] 
MEDIUM: connection: make mux->detach() release the connection

For H2, only the mux's timeout or other conditions might cause a
release of the mux and the connection, no stream should be allowed
to kill such a shared connection. So a stream will only detach using
cs_destroy() which will call mux->detach() then free the cs.

For now it's only handled by mux_pt. The goal is that the data layer
never has to care about the connection, which will have to be released
depending on the mux's mood.

7 years agoMEDIUM: connection: replace conn_full_close() with cs_close()
Willy Tarreau [Thu, 5 Oct 2017 16:52:17 +0000 (18:52 +0200)] 
MEDIUM: connection: replace conn_full_close() with cs_close()

At all call places where a conn_stream is in use, we can now use
cs_close() to get rid of a conn_stream and of its underlying connection
if the mux estimates it makes sense. This is what is currently being
done for the pass-through mux.

7 years agoMEDIUM: mux_pt: make cs_shutr() / cs_shutw() properly close the connection
Willy Tarreau [Thu, 5 Oct 2017 16:47:38 +0000 (18:47 +0200)] 
MEDIUM: mux_pt: make cs_shutr() / cs_shutw() properly close the connection

Now these functions are able to automatically close both the transport
and the socket layer, causing the whole connection to be torn down if
needed.

The two shutdown modes are implemented for both directions, and when
a direction is closed, if it sees the other one is closed as well, it
completes by closing the connection. This is similar to what is performed
in the stream interface.

It's not deployed yet but the purpose is to get rid of conn_full_close()
where only conn_stream should be known.

7 years agoMINOR: connection: add cs_close() to close a conn_stream
Willy Tarreau [Thu, 5 Oct 2017 16:19:43 +0000 (18:19 +0200)] 
MINOR: connection: add cs_close() to close a conn_stream

This basically calls cs_shutw() followed by cs_shutr(). Both of them
are called in the most conservative mode so that any previous call is
still respected. The CS flags are cleared so that it can be reused
(this is important for connection retries when conn and CS are reused
without being reallocated).

7 years agoMEDIUM: connection: make conn_sock_shutw() aware of lingering
Willy Tarreau [Thu, 5 Oct 2017 15:24:42 +0000 (17:24 +0200)] 
MEDIUM: connection: make conn_sock_shutw() aware of lingering

Instead of having to manually handle lingering outside, let's make
conn_sock_shutw() check for it before calling shutdown(). We simply
don't want to emit the FIN if we're going to reset the connection
due to lingering. It's particularly important for silent-drop where
it's absolutely mandatory that no packet leaves the machine.

7 years agoMINOR: conn_stream: modify cs_shut{r,w} API to pass the desired mode
Willy Tarreau [Thu, 5 Oct 2017 13:25:48 +0000 (15:25 +0200)] 
MINOR: conn_stream: modify cs_shut{r,w} API to pass the desired mode

Now we can specify how we want to shutdown (drain vs reset, and normal
vs silent), and this propagates to the mux then the transport layer.

7 years agoMINOR: conn_stream: new shutr/w status flags
Willy Tarreau [Thu, 5 Oct 2017 13:06:07 +0000 (15:06 +0200)] 
MINOR: conn_stream: new shutr/w status flags

In order to support all shutdown modes on the CS, we introduce the
following flags :
  CS_FL_SHRD : shut read, drain extra data
  CS_FL_SHRR : shut read, reset extra data
  CS_FL_SHWN : shut write, normal notification
  CS_FL_SHWS : shut write, silent mode (no notification)

And the following modes for shutr/shutw :

  CS_SHR_DRAIN, CS_SHR_RESET, CS_SHW_NORMAL, CS_SHW_SILENT.

Note: it's possible that we won't need to distinguish the two shutw
above as they're only an action.

For now they are not used.

7 years agoMINOR: connection: make conn_stream users also check for per-stream error flag
Willy Tarreau [Mon, 16 Oct 2017 13:17:17 +0000 (15:17 +0200)] 
MINOR: connection: make conn_stream users also check for per-stream error flag

In a 1:1 connection:stream there's no problem relying on the connection
flags alone to check for errors. But in a mux, it will be possible to mark
certain streams in error without having to mark all of them. An example is
an H2 client sending RST_STREAM frames to abort a long download, or a parse
error requiring to abort only this specific stream.

This commit ensures that stream-interface and checks properly check for
CS_FL_ERROR in cs->flags wherever CO_FL_ERROR was in use. Most likely over
the long term, any check for CO_FL_ERROR will have to disappear.

7 years agoMAJOR: connection : Split struct connection into struct connection and struct conn_st...
Olivier Houchard [Wed, 13 Sep 2017 16:30:23 +0000 (18:30 +0200)] 
MAJOR: connection : Split struct connection into struct connection and struct conn_stream.

All the references to connections in the data path from streams and
stream_interfaces were changed to use conn_streams. Most functions named
"something_conn" were renamed to "something_cs" for this. Sometimes the
connection still is what matters (eg during a connection establishment)
and were not always renamed. The change is significant and minimal at the
same time, and was quite thoroughly tested now. As of this patch, all
accesses to the connection from upper layers go through the pass-through
mux.

7 years agoMINOR: mux_pt: implement remaining mux_ops methods
Olivier Houchard [Wed, 13 Sep 2017 16:30:23 +0000 (18:30 +0200)] 
MINOR: mux_pt: implement remaining mux_ops methods

This is a basic pass-through implementation which is now basic but
complete and operational, just not used yet.

7 years agoMINOR: connection: introduce the conn_stream manipulation functions
Willy Tarreau [Sun, 8 Oct 2017 13:16:00 +0000 (15:16 +0200)] 
MINOR: connection: introduce the conn_stream manipulation functions

Most of the functions dealing with conn_streams are here. They act at
the data layer and interact with the mux. For now they are not used yet
but everything builds.

7 years agoMINOR: mux: add more methods to mux_ops
Olivier Houchard [Wed, 13 Sep 2017 16:30:23 +0000 (18:30 +0200)] 
MINOR: mux: add more methods to mux_ops

We'll need to support reading/writing from both sides, with buffers and
pipes, as well as retrieving/updating flags.

7 years agoMINOR: connection: introduce conn_stream
Olivier Houchard [Wed, 13 Sep 2017 16:30:23 +0000 (18:30 +0200)] 
MINOR: connection: introduce conn_stream

This patch introduces a new struct conn_stream. It's the stream-side of
a multiplexed connection. A pool is created and destroyed on exit. For
now the conn_streams are not used at all.

7 years agoMINOR: connection: report the major HTTP version from the MUX for logging (fc_http_major)
Willy Tarreau [Fri, 18 Aug 2017 13:26:54 +0000 (15:26 +0200)] 
MINOR: connection: report the major HTTP version from the MUX for logging (fc_http_major)

A new sample fetch function reports either 1 or 2 for the on-wire encoding,
to indicate if the request was received using the HTTP/1.x format or HTTP/2
format. Note that it reports the on-wire encoding, not the version presented
in the request header.

This will possibly have to evolve if it becomes necessary to report the
encoding on the server side as well.

7 years agoMEDIUM: session: use the ALPN token and proxy mode to select the mux
Willy Tarreau [Fri, 15 Sep 2017 04:59:55 +0000 (06:59 +0200)] 
MEDIUM: session: use the ALPN token and proxy mode to select the mux

When an incoming connection is made on an HTTP mode frontend, the
session now looks up the mux to use based on the ALPN token and the
proxy mode. This will allow easier mux registration, and we don't
need to hard-code the mux_pt_ops anymore.

7 years agoMINOR: mux: register the pass-through mux for any ALPN string
Willy Tarreau [Thu, 21 Sep 2017 17:43:21 +0000 (19:43 +0200)] 
MINOR: mux: register the pass-through mux for any ALPN string

The pass-through mux is the fallback used on any incoming connection
unless another mux claims the ALPN name and the proxy mode. Thus mux_pt
registers ALPN token "" (empty name) which catches everything.

7 years agoMINOR: connection: implement alpn registration of muxes
Willy Tarreau [Thu, 21 Sep 2017 17:40:52 +0000 (19:40 +0200)] 
MINOR: connection: implement alpn registration of muxes

Selecting a mux based on ALPN and the proxy mode will quickly become a
pain. This commit provides new functions to register/lookup a mux based
on the ALPN string and the proxy mode to make this easier. Given that
we're not supposed to support a wide range of muxes, the lookup should
not have any measurable performance impact.

7 years agoMEDIUM: connection: start to introduce a mux layer between xprt and data
Willy Tarreau [Mon, 28 Aug 2017 08:53:00 +0000 (10:53 +0200)] 
MEDIUM: connection: start to introduce a mux layer between xprt and data

For HTTP/2 and QUIC, we'll need to deal with multiplexed streams inside
a connection. After quite a long brainstorming, it appears that the
connection interface to the existing streams is appropriate just like
the connection interface to the lower layers. In fact we need to have
the mux layer in the middle of the connection, between the transport
and the data layer.

A mux can exist on two directions/sides. On the inbound direction, it
instanciates new streams from incoming connections, while on the outbound
direction it muxes streams into outgoing connections. The difference is
visible on the mux->init() call : in one case, an upper context is already
known (outgoing connection), and in the other case, the upper context is
not yet known (incoming connection) and will have to be allocated by the
mux. The session doesn't have to create the new streams anymore, as this
is performed by the mux itself.

This patch introduces this and creates a pass-through mux called
"mux_pt" which is used for all new connections and which only
calls the data layer's recv,send,wake() calls. One incoming stream
is immediately created when init() is called on the inbound direction.
There should not be any visible impact.

Note that the connection's mux is purposely not set until the session
is completed so that we don't accidently run with the wrong mux. This
must not cause any issue as the xprt_done_cb function is always called
prior to using mux's recv/send functions.

7 years agoBUG/MEDIUM: threads: Initialize the sync-point
Christopher Faulet [Tue, 31 Oct 2017 16:30:12 +0000 (17:30 +0100)] 
BUG/MEDIUM: threads: Initialize the sync-point

The sync point must be initialized before starting threads. This line was lost
in one of merges preparing the threads support integration.

7 years agoBUG/MAJOR: threads/freq_ctr: use a memory barrier to detect changes
Willy Tarreau [Tue, 31 Oct 2017 16:54:15 +0000 (17:54 +0100)] 
BUG/MAJOR: threads/freq_ctr: use a memory barrier to detect changes

commit 6e01286 (BUG/MAJOR: threads/freq_ctr: fix lock on freq counters)
attempted to fix the loop using volatile but that doesn't work depending
on the level of optimization, resulting in situations where the threads
could remain looping forever. Here we use memory barriers between reads
to enforce a strict ordering and the asm code produced does exactly what
the C code does and works perfectly, with a 3-digit measurement accuracy
observed during a test.

7 years agoMINOR: threads: add a portable barrier for threads and non-threads
Willy Tarreau [Tue, 31 Oct 2017 17:00:20 +0000 (18:00 +0100)] 
MINOR: threads: add a portable barrier for threads and non-threads

HA_BARRIER() is just a simple memory barrier to prevent the compiler
from reordering our code.

7 years agoMINOR: h1: add a function to measure the trailers length
Willy Tarreau [Tue, 31 Oct 2017 16:14:16 +0000 (17:14 +0100)] 
MINOR: h1: add a function to measure the trailers length

This is needed in the H2->H1 gateway so that we know how long the trailers
block is in chunked encoding. It returns the number of bytes, or 0 if some
are missing, or -1 in case of parse error.

7 years agoCLEANUP: threads: rename process_mask to thread_mask
Willy Tarreau [Tue, 31 Oct 2017 15:06:06 +0000 (16:06 +0100)] 
CLEANUP: threads: rename process_mask to thread_mask

It was a leftover from the last cleaning session; this mask applies
to threads and calling it process_mask is a bit confusing. It's the
same in fd, task and applets.

7 years agoCLEANUP: threads: replace the last few 1UL<<tid with tid_bit
Willy Tarreau [Tue, 31 Oct 2017 14:59:32 +0000 (15:59 +0100)] 
CLEANUP: threads: replace the last few 1UL<<tid with tid_bit

There were a few occurences left, better replace them now.

7 years agoMINOR: ssl: Remove the global allow-0rtt option.
Olivier Houchard [Tue, 31 Oct 2017 12:32:10 +0000 (13:32 +0100)] 
MINOR: ssl: Remove the global allow-0rtt option.

7 years agoBUG/MINOR: dns: Fix SRV records with the new thread code.
Olivier Houchard [Tue, 31 Oct 2017 14:21:19 +0000 (15:21 +0100)] 
BUG/MINOR: dns: Fix SRV records with the new thread code.

srv_set_fqdn() may be called with the DNS lock already held, but tries to
lock it anyway. So, add a new parameter to let it know if it was already
locked or not;

7 years agoBUILD: stick-tables: silence an uninitialized variable warning
Willy Tarreau [Tue, 31 Oct 2017 14:45:42 +0000 (15:45 +0100)] 
BUILD: stick-tables: silence an uninitialized variable warning

Commit 819fc6f ("MEDIUM: threads/stick-tables: handle multithreads on
stick tables") introduced a valid warning about an uninitialized return
value in stksess_kill_if_expired(). It just happens that this result is
never used, so let's turn the function back to void as previously.

7 years agoBUG/MAJOR: threads/time: Store the time deviation in an 64-bits integer
Christopher Faulet [Tue, 31 Oct 2017 08:03:51 +0000 (09:03 +0100)] 
BUG/MAJOR: threads/time: Store the time deviation in an 64-bits integer

In function tv_update_date, we keep an offset reprenting the time deviation to
adjust the system time. At every call, we check if this offset must be updated
or not. Of course, It must be shared by all threads. It was store in a
timeval. But it cannot be atomically updated. So now, instead, we store it in a
64-bits integer. And in tv_update_date, we convert this integer in a
timeval. Once updated, it is converted back in an integer to be atomically
stored.

To store a tv_offset into an integer, we use 32 bits from tv_sec and 32 bits
tv_usec to avoid shift operations.

7 years agoBUG/MAJOR: threads/freq_ctr: fix lock on freq counters.
Emeric Brun [Mon, 30 Oct 2017 17:04:28 +0000 (18:04 +0100)] 
BUG/MAJOR: threads/freq_ctr: fix lock on freq counters.

The wrong bit was set to keep the lock on freq counter update. And the read
functions were re-worked to use volatile.

Moreover, when a freq counter is updated, it is now rotated only if the current
counter is in the past (now.tv_sec > ctr->curr_sec). It is important with
threads because the current time (now) is thread-local. So, rounded to the
second, the time may vary by more or less 1 second. So a freq counter rotated by
one thread may be see 1 second in the future. In this case, it is updated but
not rotated.

7 years agoMAJOR: threads: Offically enable the threads support in HAProxy
Christopher Faulet [Wed, 25 Oct 2017 15:55:27 +0000 (17:55 +0200)] 
MAJOR: threads: Offically enable the threads support in HAProxy

Now, USE_THREAD option is implicitly enabled when HAProxy is compiled, for
targets linux2628 and freebsd. To enable it for other targets, you can set
"USE_THREAD=1" explicitly on the command line. And to disable it explicitly, you
must set "USE_THREAD=" on the command line.

Now, to be clear. This does not means it is bug free, far from that. But it
seems stable enough to be tested. You can try to experiment it and to report
bugs of course by setting nbthread parameter. By leaving it to 1 (or not using
it at all), it should be as safe as an HAProxy compiled without threads.

Between the commit "MINOR: threads: Prepare makefile to link with pthread" and
this one, the feature was in development and really unstable. It could be hard
to track a bug using a bisect for all these commits.

7 years agoBUG/MINOR: threads: Add missing THREAD_LOCAL on static here and there
Christopher Faulet [Sun, 29 Oct 2017 19:14:08 +0000 (20:14 +0100)] 
BUG/MINOR: threads: Add missing THREAD_LOCAL on static here and there

7 years agoBUG/MEDIUM: threads: Run the poll loop on the main thread too
Christopher Faulet [Fri, 27 Oct 2017 11:53:47 +0000 (13:53 +0200)] 
BUG/MEDIUM: threads: Run the poll loop on the main thread too

There was a flaw in the way the threads was created. the main one was just used
to create all the others and just wait to exit. Now, it is used to run a poll
loop. So we only create nbthread-1 threads.

This also fixes a bug about the compression filter when there is only 1 thread
(nbthread == 1 or no threads support). The bug was in the way thread-local
resources was initialized. per-thread init/deinit callbacks were never called
for the main process. So, with nthread set to 1, some buffers remained
uninitialized.

7 years agoMINOR: threads: Don't start when device a detection module is used
Christopher Faulet [Wed, 25 Oct 2017 15:23:02 +0000 (17:23 +0200)] 
MINOR: threads: Don't start when device a detection module is used

For now, we don't know if device detection modules (51degrees, deviceatlas and
wurfl) are thread-safe or not. So HAproxy exits with an error when you try to
use one of them with nbthread greater than 1.

We will ask to maintainers of these modules to make them thread-safe or to give
us hints to do so.

7 years agoMEDIUM: threads/server: Use the server lock to protect health check and cli concurrency
Emeric Brun [Mon, 23 Oct 2017 12:39:51 +0000 (14:39 +0200)] 
MEDIUM: threads/server: Use the server lock to protect health check and cli concurrency

7 years agoMINOR: threads/mailers: Add a lock to protect queues of email alerts
Christopher Faulet [Mon, 23 Oct 2017 13:54:24 +0000 (15:54 +0200)] 
MINOR: threads/mailers: Add a lock to protect queues of email alerts

7 years agoMINOR: threads/checks: Set the task process_mask when a check is executed
Christopher Faulet [Fri, 20 Oct 2017 13:41:18 +0000 (15:41 +0200)] 
MINOR: threads/checks: Set the task process_mask when a check is executed

Tasks used to process checks are created to be processed by any threads. But,
once a check is started, we must be sure to be sticky on the running thread
because I/O will be also sticky on it. This is a requirement for now: Tasks and
I/O handlers linked to the same session must be executed on the same thread.

7 years agoMINOR: threads/checks: Add a lock to protect the pid list used by external checks
Christopher Faulet [Fri, 20 Oct 2017 13:40:23 +0000 (15:40 +0200)] 
MINOR: threads/checks: Add a lock to protect the pid list used by external checks

7 years agoMINOR: threads: Add thread-map config parameter in the global section
Christopher Faulet [Mon, 16 Oct 2017 13:49:32 +0000 (15:49 +0200)] 
MINOR: threads: Add thread-map config parameter in the global section

By default, no affinity is set for threads. To bind threads on CPU, you must
define a "thread-map" in the global section. The format is the same than the
"cpu-map" parameter, with a small difference. The process number must be
defined, with the same format than cpu-map ("all", "even", "odd" or a number
between 1 and 31/63).

A thread will be bound on the intersection of its mapping and the one of the
process on which it is attached. If the intersection is null, no specific bind
will be set for the thread.

7 years agoMEDIUM: thread/dns: Make DNS thread-safe
Christopher Faulet [Wed, 4 Oct 2017 14:17:58 +0000 (16:17 +0200)] 
MEDIUM: thread/dns: Make DNS thread-safe

7 years agoMEDIUM: thread/spoe: Make the SPOE thread-safe
Christopher Faulet [Mon, 25 Sep 2017 12:48:02 +0000 (14:48 +0200)] 
MEDIUM: thread/spoe: Make the SPOE thread-safe

Because there is not migration mechanism yet, all runtime information about an
SPOE agent are thread-local and async exchanges with agents are disabled when we
have serveral threads. Howerver, pipelining is still available. So for now, the
thread part of the SPOE is pretty simple.

7 years agoMEDIUM: threads/tasks: Add lock around notifications
Thierry FOURNIER [Sun, 16 Jul 2017 22:14:07 +0000 (00:14 +0200)] 
MEDIUM: threads/tasks: Add lock around notifications

This patch add lock around some notification calls

7 years agoMEDIUM: threads/xref: Convert xref function to a thread safe model
Thierry FOURNIER [Fri, 1 Sep 2017 12:17:32 +0000 (14:17 +0200)] 
MEDIUM: threads/xref: Convert xref function to a thread safe model

Ensure that the unlink is done safely between thread and that
the peer struct will not destroy between the usage of the peer.

7 years agoMEDIUM: threads/lua: Cannot acces to the socket if we try to access from another...
Thierry FOURNIER [Wed, 12 Jul 2017 10:10:44 +0000 (12:10 +0200)] 
MEDIUM: threads/lua: Cannot acces to the socket if we try to access from another thread.

We have two y for nsuring that the data is not concurently manipulated:
 - locks
 - running task on the same thread.
locks are expensives, it is better to avoid it.

This patch cecks that the Lua task run on the same thread that
the stream associated to the coprocess.

TODO: in a next version, the error should be replaced by a yield
and thread migration request.

7 years agoMEDIUM: threads/lua: Ensure that the launched tasks runs on the same threads than me
Thierry FOURNIER [Wed, 12 Jul 2017 09:53:38 +0000 (11:53 +0200)] 
MEDIUM: threads/lua: Ensure that the launched tasks runs on the same threads than me

The applet manipulates the session and its buffers. We have two methods for
ensuring that the memory of the session will not change during its manipulation
by the task:
 1 - adding mutex
 2 - running on the same threads than the task.
The second point is smart because it cannot lock the execution of another thread.

7 years agoMEDIUM: threads/lua: Add locks around the Lua execution parts.
Thierry FOURNIER [Wed, 12 Jul 2017 09:41:21 +0000 (11:41 +0200)] 
MEDIUM: threads/lua: Add locks around the Lua execution parts.

Note that the Lua processing is not really thread safe. It provides
heavy system which consists to add our own lock function in the Lua
code and recompile the library. This system will probably not accepted
by maintainers of various distribs.

Our main excution point of the Lua is the function lua_resume(). A
quick looking on the Lua sources displays a lua_lock() a the start
of function and a lua_unlock() at the end of the function. So I
conclude that the Lua thread safe mode just perform a mutex around
all execution. So I prefer to do this in the HAProxy code, it will be
easier for distro maintainers.

Note that the HAProxy lua functions rounded by the macro SET_SAFE_LJMP
and RESET_SAFE_LJMP manipulates the Lua stack, so it will be careful
to set mutex around these functions.

7 years agoMEDIUM: threads/lua: Makes the jmpbuf and some other buffers local to the current...
Thierry FOURNIER [Wed, 12 Jul 2017 09:39:04 +0000 (11:39 +0200)] 
MEDIUM: threads/lua: Makes the jmpbuf and some other buffers local to the current thread.

The jmpbuf contains pointer on the stack memory address currently use
when the jmpbuf is set. So the information is local to each thread.

The struct field is too big to put it in the stack, but it is used
as buffer for retriving stats values. So, this buffer si local to each
threads. Each function using this buffer, use it whithout break (yield)
so, the consistency of local buffer is ensured.

7 years agoMEDIUM: threads/compression: Make HTTP compression thread-safe
Christopher Faulet [Tue, 25 Jul 2017 09:07:15 +0000 (11:07 +0200)] 
MEDIUM: threads/compression: Make HTTP compression thread-safe

7 years agoMINOR: threads/filters: Update trace filter to add _per_thread callbacks
Christopher Faulet [Thu, 27 Jul 2017 14:58:42 +0000 (16:58 +0200)] 
MINOR: threads/filters: Update trace filter to add _per_thread callbacks

7 years agoMEDIUM: threads/filters: Add init/deinit callback per thread
Christopher Faulet [Thu, 27 Jul 2017 14:33:28 +0000 (16:33 +0200)] 
MEDIUM: threads/filters: Add init/deinit callback per thread

Now, it is possible to define init_per_thread and deinit_per_thread callbacks to
deal with ressources allocation for each thread.

This is the filter responsibility to deal with concurrency. This is also the
filter responsibility to know if HAProxy is started with some threads. A good
way to do so is to check "global.nbthread" value. If it is greater than 1, then
_per_thread callbacks will be called.