80 Commits

Author SHA1 Message Date
Willy Tarreau
4e4292b9af CLEANUP: stream-int: add si_ib/si_ob to dereference the buffers
This makes the code cleaner and is more intuitive to use.
2015-03-11 20:41:46 +01:00
Willy Tarreau
819d332dfd MEDIUM: stream-int: remove any reference to the owner
si->owner is not used anymore now, so let's remove any reference to it.
2015-03-11 20:41:46 +01:00
Willy Tarreau
07373b8660 MEDIUM: stream-int: use si_task() to retrieve the task from the stream int
We go back to the session to get the owner. Here again it's very easy
and is just a matter of relative offsets. Since the owner always exists
and always points to the session's task, we can remove some unneeded
tests.
2015-03-11 20:41:46 +01:00
Willy Tarreau
aefd79004c MEDIUM: stream-int: make si_sess() use the stream int's side
This one relies on the SI's side to find the pointer to the session.
That the stream interface doesn't have to look at the task's context
anymore.
2015-03-11 20:41:46 +01:00
Willy Tarreau
0b2fb7f9a3 MAJOR: stream-int: only rely on SI_FL_ISBACK to find the requested channel
In order to plan removal of si->ib / si->ob, we now check the side of the
stream interface and find the session, then the requested channel. In
practice it's just an offset applied to the pointer based on the flag.
2015-03-11 20:41:46 +01:00
Willy Tarreau
a5f5d8dc69 MEDIUM: stream-int: add a flag indicating which side the SI is on
This new flag "SI_FL_ISBACK" is set only on the back SI and is cleared
on the front SI. That way it's possible only by looking at the SI to
know what side it is.
2015-03-11 20:41:46 +01:00
Willy Tarreau
2bb4a96f8f REORG/MEDIUM: stream-int: introduce si_ic/si_oc to access channels
We'll soon remove direct references to the channels from the stream
interface since everything belongs to the same session, so let's
first not dereference si->ib / si->ob anymore and use macros instead.
2015-03-11 20:41:46 +01:00
Willy Tarreau
3dd6a25323 MINOR: stream-int: retrieve session pointer from stream-int
sess_from_si() does this via the owner (struct task). It works because
all stream ints belong to a task nowadays.
2014-12-24 23:47:31 +01:00
Willy Tarreau
9e5a3aacf4 MEDIUM: stream-int: make si_connect() return an established state when possible
si_connect() used to only return SI_ST_CON. But it already detect the
connection reuse and is the function which avoids calling connect().
So it already knows the connection is valid and reuse. Thus we make it
return SI_ST_EST when a connection is reused. This means that
connect_server() can return this state and sess_update_stream_int()
as well.

Thanks to this change, we don't need to leave process_session() in
SI_ST_CON state to immediately enter it again to switch to SI_ST_EST.
Implementing this removes one call to process_session() per request
in keep-alive mode. We're now at 2 calls per request, which is the
minimum (one for the request and another one for the response). The
number of calls to http_wait_for_response() has also dropped from 2
to one.

Tests indicate a performance gain of about 2.6% in request rate in
keep-alive mode. There should be no gain in http-server-close() since
we don't use this faster path.
2013-12-31 23:32:12 +01:00
Willy Tarreau
2737562e43 MEDIUM: stream-int: implement a very simplistic idle connection manager
Idle connections are not monitored right now. So if a server closes after
a response without advertising it, it won't be detected until a next
request wants to use the connection. This is a bit problematic because
it unnecessarily maintains file descriptors and sockets in an idle
state.

This patch implements a very simple idle connection manager for the stream
interface. It presents itself as an I/O callback. The HTTP engine enables
it when it recycles a connection. If a close or an error is detected on the
underlying socket, it tries to drain as much data as possible from the socket,
detect the close and responds with a close as well, then detaches from the
stream interface.
2013-12-17 00:00:28 +01:00
Willy Tarreau
b490b4e5ad MAJOR: stream-int: handle the connection reuse in si_connect()
This is the best place to reuse a connection. We centralize all
connection requests and we're at the best place to know exactly
what the current state of the underlying connection is. If the
connection is reused, we just enable polling for send() in order
to be able to emit the request.
2013-12-16 02:23:53 +01:00
Willy Tarreau
9471b8ced9 MEDIUM: connection: inform si_alloc_conn() whether existing conn is OK or not
When allocating a new connection, only the caller knows whether it's
acceptable to reuse the previous one or not. Let's pass this information
to si_alloc_conn() which will do the cleanup if the connection is not
acceptable.
2013-12-16 02:23:53 +01:00
Willy Tarreau
d02cdd23be MINOR: connection: add simple functions to report connection readiness
conn_xprt_ready() reports if the transport layer is ready.
conn_ctrl_ready() reports if the control layer is ready.

The stream interface uses si_conn_ready() to report that the
underlying connection is ready. This will be used for connection
reuse in keep-alive mode.
2013-12-16 02:23:52 +01:00
Willy Tarreau
0a23bcb8be MAJOR: stream-interface: dynamically allocate the applet context
From now on, a call to stream_int_register_handler() causes a call
to si_alloc_appctx() and returns an initialized appctx for the
current stream interface. If one was previously allocated, it is
released. If the stream interface was attached to a connection, it
is released as well.

The appctx are allocated from the same pools as the connections, because
they're substantially smaller in size, and we can't have both a connection
and an appctx on an interface at any moment.

In case of memory shortage, the call may return NULL, which is already
handled by all consumers of stream_int_register_handler().

The field appctx was removed from the stream interface since we only
rely on the endpoint now. On 32-bit, the stream_interface size went down
from 108 to 44 bytes. On 64-bit, it went down from 144 to 64 bytes. This
represents a memory saving of 160 bytes per session.

It seems that a later improvement could be to move the call to
stream_int_register_handler() to session.c for most cases.
2013-12-09 15:40:23 +01:00
Willy Tarreau
1fbe1c9ec8 MEDIUM: stream-int: return the allocated appctx in stream_int_register_handler()
The task returned by stream_int_register_handler() is never used, however we
always need to access the appctx afterwards. So make it return the appctx
instead. We already plan for it to fail, which is the reason for the addition
of a few tests and the possibility for the HTTP analyser to return a status
code 500.
2013-12-09 15:40:23 +01:00
Willy Tarreau
7b4b499fde MEDIUM: stream-int: replace occurrences of si->appctx with si_appctx()
We're about to remove si->appctx, so first let's replace all occurrences
of its usage with a dynamic extract from si->end. A lot of code was changed
by search-n-replace, but the behaviour was intentionally not altered.

The code surrounding calls to stream_int_register_handler() was slightly
changed since we can only use si->end *after* the registration.
2013-12-09 15:40:23 +01:00
Willy Tarreau
1ec74bf660 MINOR: connection: check for send_proxy during the connect(), not the SI
It's cleaner to check for a pending send_proxy_ofs while establishing
the connection (which already checks it anyway) and not in the stream
interface.
2013-12-09 15:40:23 +01:00
Willy Tarreau
b8020cefed MEDIUM: connection: move the send_proxy offset to the connection
Till now the send_proxy_ofs field remained in the stream interface,
but since the dynamic allocation of the connection, it makes a lot
of sense to move that into the connection instead of the stream
interface, since it will not be statically allocated for each
session.

Also, it turns out that moving it to the connection fils an alignment
hole on 64 bit architectures so it does not consume more memory, and
removing it from the stream interface was an opportunity to correctly
reorder fields and reduce the stream interface's size from 160 to 144
bytes (-10%). This is 32 bytes saved per session.
2013-12-09 15:40:23 +01:00
Willy Tarreau
32e3c6a607 MAJOR: stream interface: dynamically allocate the outgoing connection
The outgoing connection is now allocated dynamically upon the first attempt
to touch the connection's source or destination address. If this allocation
fails, we fail on SN_ERR_RESOURCE.

As we didn't use si->conn anymore, it was removed. The endpoints are released
upon session_free(), on the error path, and upon a new transaction. That way
we are able to carry the existing server's address across retries.

The stream interfaces are not initialized anymore before session_complete(),
so we could even think about allocating them dynamically as well, though
that would not provide much savings.

The session initialization now makes use of conn_new()/conn_free(). This
slightly simplifies the code and makes it more logical. The connection
initialization code is now shorter by about 120 bytes because it's done
at once, allowing the compiler to remove all redundant initializations.

The si_attach_applet() function now takes care of first detaching the
existing endpoint, and it is called from stream_int_register_handler(),
so we can safely remove the calls to si_release_endpoint() in the
application code around this call.

A call to si_detach() was made upon stream_int_unregister_handler() to
ensure we always free the allocated connection if one was allocated in
parallel to setting an applet (eg: detect HTTP proxy while proceeding
with stats maybe).
2013-12-09 15:40:23 +01:00
Willy Tarreau
2a6e8802c0 MEDIUM: stream-interface: introduce si_attach_conn to replace si_prepare_conn
si_prepare_conn() is not appropriate in our case as it both initializes and
attaches the connection to the stream interface. Due to the asymmetry between
accept() and connect(), it causes some fields such as the control and transport
layers to be reinitialized.

Now that we can separately initialize these fields using conn_prepare(), let's
break this function to only attach the connection to the stream interface.

Also, by analogy, si_prepare_none() was renamed si_detach(), and
si_prepare_applet() was renamed si_attach_applet().
2013-12-09 15:40:23 +01:00
Willy Tarreau
7abddb5c67 MINOR: connection: replace conn_assign with conn_attach
We don't want to assign the control nor transport layers anymore
at the same time as the data layer, because it prevents one from
keeping existing settings when reattaching a connection to an
existing stream interface.

Let's have conn_attach() replace conn_assign() for this purpose.

Thus, conn_prepare() + conn_attach() do exactly the same as the
previous conn_assign().
2013-12-09 15:40:23 +01:00
Willy Tarreau
3ed35ef05b MINOR: stream-interface: introduce si_reset() and si_set_state()
The first function is used to (re)initialize a stream interface and
the second to force it into a known state. These are intended for
cleaning up the stream interface initialization code in session.c
and peers.c and avoiding future issues with missing initializations.
2013-12-09 15:40:23 +01:00
Willy Tarreau
c10aec299f MINOR: get rid of si_takeover_conn()
Since last commit, this function is an exact copy of si_prepare_conn().
2013-12-09 15:40:23 +01:00
Willy Tarreau
37213433a8 MEDIUM: connection: replace conn_prepare with conn_assign
Everywhere conn_prepare() is used, the call to conn_init() has already
been done. We can now safely replace all instances of conn_prepare()
with conn_assign() which does not reset the transport layer, and remove
conn_prepare().
2013-12-09 15:40:23 +01:00
Willy Tarreau
b363a1f469 MAJOR: stream-int: stop using si->conn and use si->end instead
The connection will only remain there as a pre-allocated entity whose
goal is to be placed in ->end when establishing an outgoing connection.
All connection initialization can be made on this connection, but all
information retrieved should be applied to the end point only.

This change is huge because there were many users of si->conn. Now the
only users are those who initialize the new connection. The difficulty
appears in a few places such as backend.c, proto_http.c, peers.c where
si->conn is used to hold the connection's target address before assigning
the connection to the stream interface. This is why we have to keep
si->conn for now. A future improvement might consist in dynamically
allocating the connection when it is needed.
2013-12-09 15:40:22 +01:00
Willy Tarreau
691b1f429e CLEANUP: stream-int: remove obsolete si_ctrl function
This function makes no sense anymore and will cause trouble to convert
the remains of connection/applet to end points. Let's replace it now
with its contents.
2013-12-09 15:40:22 +01:00
Willy Tarreau
cf644ed37a MEDIUM: stream-int: make ->end point to the connection or the appctx
The long-term goal is to have a context for applets as an alternative
to the connection and not as a complement. At the moment, the context
is still stored into the stream interface, and we only put a pointer
to the applet's context in si->end, initialize the context with object
type OBJ_TYPE_APPCTX, and this allows us not to allocate an entry when
deciding to switch to an applet.

A special care is taken to never dereference si->conn anymore when
dealing with an applet. That's why it's important that si->end is
always set to the proper type :

    si->end == NULL             => not connected to anything
   *si->end == OBJ_TYPE_APPCTX  => connected to an applet
   *si->end == OBJ_TYPE_CONN    => real connection (server, proxy, ...)

The session management code used to check the applet from the connection's
target. Now it uses the stream interface's end point and does not touch the
connection at all. Similarly, we stop checking the connection's addresses
and file descriptors when reporting the applet's status in the stats dump.
2013-12-09 15:40:22 +01:00
Willy Tarreau
4a59f2f954 MAJOR: stream interface: remove the ->release function pointer
Since last commit, we now have a pointer to the applet in the
applet context. So we don't need the si->release function pointer
anymore, it can be extracted from applet->applet.release. At many
places, the ->release function was still tested for real connections
while it is only limited to applets, so most of them were simply
removed. For the remaining valid uses, a new inline function
si_applet_release() was added to simplify the check and the call.
2013-12-09 15:40:22 +01:00
Willy Tarreau
48099c7a07 MEDIUM: stream-interface: set the pointer to the applet into the applet context
In preparation for a later move of all the applet context outside of the
stream interface, we'll need to have access to the applet itself from the
context. Let's have a pointer to it inside the context.
2013-12-09 15:40:22 +01:00
Willy Tarreau
7d67d7b9e5 MINOR: stream-int: add a new pointer to the end point
The end point will correspond to either an applet context or a connection,
depending on the object type. For now the pointer remains null.
2013-12-09 15:40:22 +01:00
Willy Tarreau
372d6708fb MINOR: stream-int: split si_prepare_embedded into si_prepare_none and si_prepare_applet
si_prepare_embedded() was used both to attach an applet and to detach
anything from a stream interface. Split it into si_prepare_none() to
detach and si_prepare_applet() to attach an applet.

si->conn->target is now assigned from within these two functions instead
of their respective callers.
2013-12-09 15:40:22 +01:00
Willy Tarreau
6fe1541285 MINOR: stream-int: make the shutr/shutw functions void
This is to be more consistent with the other functions. The only
reason why these functions used to return a value was to let the
caller adjust polling by itself, but now their only callers were
the si_shutr()/si_shutw() inline functions. Now these functions
do not depend anymore on the connection.

These connection variant of these functions now call
conn_data_stop_recv()/conn_data_stop_send() before returning order
not to require a return code anymore. The applet version does not
need this at all.
2013-12-09 15:40:22 +01:00
Willy Tarreau
8b3d7dfd7c MEDIUM: stream-int: split the shutr/shutw functions between applet and conn
These functions induce a lot of ifs everywhere because they consider two
different cases, one which is where the connection exists and has a file
descriptor, and the other one which is the default case where at most an
applet has to be notified.

Let's have them in si_ops and automatically decide which one to use.

The connection shutdown sequence has been slightly simplified, and we
now clear the flags at the end.

Also we remove SHUTR_NOW after a shutw with nolinger, as it's cleaner
not to keep it.
2013-12-09 15:40:22 +01:00
Willy Tarreau
55e4ecd928 MINOR: stats: add a few more information on session dump
We also report fd.spec_p, fd.updt and a few names instead of the values.
2012-12-08 17:48:47 +01:00
Willy Tarreau
f0837b259b MEDIUM: tcp: add explicit support for delayed ACK in connect()
Commit 24db47e0 tried to improve support for delayed ACK upon connect
but it was incomplete, because checks with the proxy protocol would
always enable polling for data receive and there was no way of
distinguishing data polling and delayed ack.

So we add a distinct delack flag to the connect() function so that
the caller decides whether or not to use a delayed ack regardless
of pending data (eg: when send-proxy is in use). Doing so covers all
combinations of { (check with data), (sendproxy), (smart-connect) }.
2012-11-24 10:24:27 +01:00
Willy Tarreau
128b03c9ab CLEANUP: stream_interface: remove the external task type target
Before connections were introduced, it was possible to connect an
external task to a stream interface. However it was left as an
exercise for the brave implementer to find how that ought to be
done.

The feature was broken since the introduction of connections and
was never fixed since due to lack of users. Better remove this dead
code now.
2012-11-11 23:14:16 +01:00
Willy Tarreau
7f7ad91056 BUILD: stream_interface: remove si_fd() and its references
si_fd() is not used a lot, and breaks builds on OpenBSD 5.2 which
defines this name for its own purpose. It's easy enough to remove
this one-liner function, so let's do it.
2012-11-11 20:53:29 +01:00
Willy Tarreau
f2943dccd0 MAJOR: session: detach the connections from the stream interfaces
We will need to be able to switch server connections on a session and
to keep idle connections. In order to achieve this, the preliminary
requirement is that the connections can survive the session and be
detached from them.

Right now they're still allocated at exactly the same place, so when
there is a session, there are always 2 connections. We could soon
improve on this by allocating the outgoing connection only during a
connect().

This current patch touches a lot of code and intentionally does not
change any functionnality. Performance tests show no regression (even
a very minor improvement). The doc has not yet been updated.
2012-10-26 20:15:20 +02:00
Willy Tarreau
bd99aab91f MINOR: connection: split conn_prepare() in two functions
We'll also need a function to takeover an existing connection without
reinitializing it. The same will be needed at the stream interface level.
2012-10-04 22:26:10 +02:00
Willy Tarreau
4aa3683b2d MINOR: connection: provide a generic data layer wakeup callback
Instead of calling conn_notify_si() from the connection handler, we
now call data->wake(), which will allow us to use a different callback
with health checks.

Note that we still rely on a flag in order to decide whether or not
to call this function. The reason is that with embryonic sessions,
the callback is already initialized to si_conn_cb without the flag,
and we can't call the SI notify function in the leave path before
the stream interface is initialized.

This issue should be addressed by involving a different data_cb for
embryonic sessions and for stream interfaces, that would be changed
during session_complete() for the final data_cb.
2012-10-04 22:26:10 +02:00
Willy Tarreau
74beec32a5 REORG: connection: rename app_cb "data"
Now conn->data will designate the data layer which is the client for
the transport layer. In practice it's the stream interface and will
soon also be the health checks.
2012-10-04 22:26:10 +02:00
Willy Tarreau
f7bc57ca6e REORG: connection: rename the data layer the "transport layer"
While working on the changes required to make the health checks use the
new connections, it started to become obvious that some naming was not
logical at all in the connections. Specifically, it is not logical to
call the "data layer" the layer which is in charge for all the handshake
and which does not yet provide a data layer once established until a
session has allocated all the required buffers.

In fact, it's more a transport layer, which makes much more sense. The
transport layer offers a medium on which data can transit, and it offers
the functions to move these data when the upper layer requests this. And
it is the upper layer which iterates over the transport layer's functions
to move data which should be called the data layer.

The use case where it's obvious is with embryonic sessions : an incoming
SSL connection is accepted. Only the connection is allocated, not the
buffers nor stream interface, etc... The connection handles the SSL
handshake by itself. Once this handshake is complete, we can't use the
data functions because the buffers and stream interface are not there
yet. Hence we have to first call a specific function to complete the
session initialization, after which we'll be able to use the data
functions. This clearly proves that SSL here is only a transport layer
and that the stream interface constitutes the data layer.

A similar change will be performed to rename app_cb => data, but the
two could not be in the same commit for obvious reasons.
2012-10-04 22:26:09 +02:00
Willy Tarreau
cd379950a7 MINOR: connection: add a pointer to the connection owner
This will be needed to find the stream interface from the connection
once they're detached, but in the more immediate term, we'll need this
for health checks since they don't use a stream interface.
2012-09-28 00:01:22 +02:00
Willy Tarreau
dda5e7c986 CLEANUP: connection: offer conn_prepare() to set up a connection
This will be used by checks as well as stream interfaces.
2012-09-24 22:49:06 +02:00
Willy Tarreau
14f8e86da5 MEDIUM: proto_tcp: remove any dependence on stream_interface
The last uses of the stream interfaces were in tcp_connect_server() and
could easily and more appropriately be moved to its callers, si_connect()
and connect_server(), making a lot more sense.

Now the function should theorically be usable for health checks.

It also appears more obvious that the file is split into two distinct
parts :
  - the protocol layer used at the connection level
  - the tcp analysers executing tcp-* rules and their samples/acls.
2012-09-03 20:47:34 +02:00
Willy Tarreau
986a9d2d12 MAJOR: connection: move the addr field from the stream_interface
We need to have the source and destination addresses in the connection.
They were lying in the stream interface so let's move them. The flags
SI_FL_FROM_SET and SI_FL_TO_SET have been moved as well.

It's worth noting that tcp_connect_server() almost does not use the
stream interface anymore except for a few flags.

It has been identified that once we detach the connection from the SI,
it will probably be needed to keep a copy of the server-side addresses
in the SI just for logging purposes. This has not been implemented right
now though.
2012-09-03 20:47:34 +02:00
Willy Tarreau
3cefd521fa REORG: connection: move the target pointer from si to connection
The target is per connection and is directly used by the connection, so
we need it there. It's not needed anymore in the SI however.
2012-09-03 20:47:34 +02:00
Willy Tarreau
c578891112 CLEANUP: connection: split sock_ops into data_ops, app_cp and si_ops
Some parts of the sock_ops structure were only used by the stream
interface and have been moved into si_ops. Some of them were callbacks
to the stream interface from the connection and have been moved into
app_cp as they're the application seen from the connection (later,
health-checks will need to use them). The rest has moved to data_ops.

Normally at this point the connection could live without knowing about
stream interfaces at all.
2012-09-03 20:47:31 +02:00
Willy Tarreau
ce323dea14 REORG: stream-interface: move sock_raw_read() to si_conn_recv_cb()
The recv function is now generic and is usable to iterate any connection-to-buf
reading function from a stream interface. So let's move it to stream-interface.
2012-09-03 20:47:30 +02:00
Willy Tarreau
9bf9c14c12 MEDIUM: stream-interface: provide a generic stream_sock_read0() function
This function is used by the data layer when a zero has been read over a
connection. At the moment it only handles sockets and nothing else. Once
the complete split is done between buffers and stream interfaces, it should
become possible to work regardless on the connection type.
2012-09-02 21:54:55 +02:00