Age | Commit message (Collapse) | Author |
|
Add a per session send queue. Messages sent by a session are added to
both tunnel and session queues. This allows sessions to remove their
unsent messages from tunnel's send queue before they disconnect.
The same approach is used for tunnels. Before disconnecting, they clear
their send queue to avoid sending useless messages.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Modify return value of l2tp_tunnel_push_sendqueue() to inform the
caller if a message has been sent or if the queue was empty. This
information, let l2tp_conn_read() automatically acknowledge
received messages using a ZLB when there's no response to send.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Stop checking for l2tp_{tunnel,session}_send() return values.
These functions now always succeed, unless the session or tunnel is
closing (in which case packet is automatically dropped and caller
doesn't need to take any special action).
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Don't send messages immediately, store them in conn->send_queue
instead, so we have control over how many and when messages are
sent on the network. Once a message is sent, it's removed from
the send queue and added to the retransmission queue.
Retransmission queue is automatically updated based on acknowledgements
received from peer.
For now, packets in the send queue are pushed on the network after
each incoming packet processing. So functions called by l2tp_conn_read()
don't have to call l2tp_tunnel_push_sendqueue().
Other functions (e.g. triton callbacks) have to manually push packets
out of the send queue.
The same applies for disconnection. The l2tp_tunnel_disconnect_push()
and l2tp_session_disconnect_push() functions have been defined for use
in functions that don't call l2tp_tunnel_push_sendqueue() automatically.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Remove message type switch from l2tp_conn_read(). Define
l2tp_tunnel_recv() instead to handle tunnel specific messages.
The Session ID field in L2TP control messages is used to determine if
packet is tunnel or session oriented.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Let l2tp_tunnel_disconnect() delete the tunnel when an error occurs.
Return an int to indicate if conn has been deleted.
Most callers are compatible with this new behaviour, either because
they never use the tunnel after disconnection or because they hold
a reference on the tunnel.
A few callers need to be adapted though:
-l2tp_conn_close() calls l2tp_tunnel_disconnect() to properly inform
the peer of tunnel disconnection. But it also deletes the tunnel
immediately, no matter if StopCCN message was sent or not. Since
l2tp_conn_close() doesn't hold a reference on the tunnel, care must
be taken not to access the tunnel if it was deleted by
l2tp_tunnel_disconnect().
Since immediate deletion isn't required, the l2tp_tunnel_free() call
is simply removed. The normal disconnection process is now followed,
with detection and retransmission of lost messages, acknowledgment
handling, etc.
-situation is similar for l2tp_tunnel_timeout() and handled in the
same way.
This patch also deletes tunnel's sessions, as well as the establishment
and hello timers. These are of no use once the tunnel enters the
disconnection process.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Now that l2tp_tunnel_free() can be called directly inside the main
reception loop, let l2tp_recv_StopCCN() delete the tunnel itself.
This avoids special handling in l2tp_conn_read().
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Let functions launched by l2tp_conn_read() delete the tunnel. This is
done by taking a reference on conn to ensure it'll remain a valid
tunnel, even after calling l2tp_tunnel_free(conn).
l2tp_conn_read() now detects if conn got deleted, so that we know if
the tunnel still holds a reference to itself. If it doesn't,
tunnel_put() may free the tunnel and thus the triton handler we're
running from. So we have to return -1 in this case.
l2tp_tunnel_free() also needs to be modified: it can't safely close
conn->hnd.fd anymore. Since l2tp_conn_read() relies on conn->hnd.fd
being a valid file descriptor, closing it inside the reception loop
would break this assumption in next iteration.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Upon failure, l2tp_recv_SCCRP() and l2tp_recv_SCCCN() disconnect their
tunnel, which is then immediately deleted by l2tp_conn_read(). Deleting
the tunnel isn't necessary at this stage and prevents retransmission of
the disconnection message if it gets lost. Same applies to unknown
message types with M bit set.
This path avoids immediate tunnel deletion, thus allowing the
disconnection process to handle acknowledgments from peer and to
retransmit messages if necessary.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Re-use the Session ID selection algorithm for generating Tunnel IDs.
When a peer always uses the same source port for establishing tunnels,
and if ephemeral ports aren't activated (default), then Tunnel IDs are
the only way to identify tunnels. Using ramdom Tunnel IDs then
minimises the risk of re-using IDs of half-closed tunnels (i.e. tunnels
closed locally, but still existing on the peer side).
As a minor side effect, the maximum value of a Tunnel ID is now
2^16 - 1.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Don't give up immediately when generating a new Session ID fails. Keep
trying until a valid Session ID is found. Abort when the number of
attempts exceeds the number of valid Session IDs.
This is derived from algorithm 3 of RFC 6056 (Port Randomization
Recommendations). Other algorithms may be used later on if need be.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
* Add "secret" to the list of options accepted by the
"l2tp create tunnel" command.
* Display one option per line to avoid too long help message.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Replace cli_sendv by cli_send where possible.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Verify tunnel or session states before handling HELLO, StopCCN and CDN
messages.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
WEN and SLI messages carry session specific data and should be handled
by the session rather than by the tunnel. Session's state can now be
checked before accepting these message types.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
l2tp_conn_read() already has code to free received packets. Let
l2tp_session_recv() take advantage of it.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Ease log file analysis by explicitely logging which L2TP control
channel carries a given data channel (PPP).
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Use a syntax closer to the one used by log_session() in order to ease
grep searching in log files.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Tunnel and session establishment timers should to be unset after they
expire. Otherwise, they may uselessly expire again while disconnection
is performed.
While here, rename l2tp_timeout() to l2tp_tunnel_timeout() for
consistency with its session counterpart.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
* missing space char (l2tp_send_StopCCN)
* missing new line char (l2tp_tunnel_create_session)
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Compute control channel statistics for L2TP sessions and report them
in the "show stat" command.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Report tunnel statistics with the "show stat" command.
Statistics are updated upon tunnel state modifications. Setting the
STATE_ESTB state is centralised in l2tp_tunnel_connect() to ensure
the tunnel state remains synchronised with the statistics even when
errors occur.
While there, connect tunnels after sending SCCCN and stop tunnel
establishment timer as soon as l2tp_tunnel_connect() is called (so
that it'll be deleted even upon failure).
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Since launching L2TP sessions doesn't require to create a new context
anymore, the only purpose of l2tp_tunnel_start_session() is to start
the session establishment timer. This patch let the session startup
functions handle this timer, so that sessions aren't started by a
function pointer anymore. Direct access to the session startup function
also let the caller handle startup failures using its existing error
handling path.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
* l2tp_session_disconnect() now always succeeds.
* l2tp_tunnel_cancel_session() now can be replaced by
l2tp_session_free().
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Run the control channels of L2TP sessions in their tunnel context to
avoid context calls between tunnels and sessions.
Tunnels and sessions now use the new state STATE_INIT as their initial
state (allows to differentiate between tunnels and sessions that are
starting or stopping). The STATE_CLOSE state isn't implicitely set to
0 by memset() anymore, so its value is changed for consistency with the
other STATE_* values.
With tunnels and sessions running in the same context, sessions can
remove themselves from their tunnel without having to perform context
calls. Tunnels can also remove sessions directly, without having to
asynchronously notify them. So the set of l2tp_tunnel_free_session*()
functions becomes useless. Sessions can also check if they're the last
session of the tunnel and automatically disconnect the tunnel if need
be. So the l2tp_tunnel_session_freed() callback can be removed.
The 'sess_count' field is now used to track the number of sessions
stored in the 'sessions' field of tunnels. It's incremented as soon
as a session is added and everytime one is removed.
The callback, used by data channels to notify their L2TP control session
of disconnection, is now executed in the tunnel context. The session ID
is used by the tunnel to find which session the disconnection applies
to. The session may well get destroyed by other means between the time
of the context call and the time of the callback execution.
The l2tp_tunnel_start_session() function doesn't need to create a new
context for the session. It now only sets the session establishment
timer and directly runs the session startup callback.
Since l2tp_session_free() can now handle sessions in any state and is
called within the tunnel context, there is no need for a special
l2tp_tunnel_cancel_session() (for now, this function is kept for patch
clarity).
Now that session packets are sent while in tunnel context,
l2tp_session_send() only needs to set the header session ID and can
directly call l2tp_tunnel_send(). For reception, the tunnel also
directly calls l2tp_session_recv().
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Split L2TP control and data channels operations. The data channel of an
L2TP session now runs in its own triton context.
The L2TP control session initialises and launches the data channel
context in l2tp_session_start_data_channel(). Then all data channel
operations (e.g. PPP negociation) are performed in this context.
When the data channel stops, it checks if the control channel is still
running; if so, it notifies the control channel about its disconnection
using the l2tp_session_apses_finished() callback.
The control channel similarly checks for data channel execution and
notifies about L2TP layer disconnection using apses_stop().
Since the presence of the data channel is checked using its context
field, the STATE_PPP state isn't required anymore. So L2TP control
sessions now automatically enter STATE_ESTB in l2tp_session_connect().
A new set of states (APSTATE_*) are defined for tracking evolution of
data channels. Data channels also handle statistics using these new
states.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Define a new function for initialising and starting the data channel of
an L2TP session. For now, l2tp_session_start_data_channel() only
gathers the data channel specific operations, previously handled by
l2tp_tunnel_alloc_session() and l2tp_session_connect().
While here, move deletion of the session establishment timer to the
beginning of l2tp_session_connect(), so that it will stop even if the
function fails.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Use reference counters to track tunnels and sessions usage.
Tunnels hold a reference to each of their sessions while sessions hold
a reference to the tunnel they belong to. Tunnels and sessions also
hold themselves to ensure that l2tp_{tunnel_session}_free() will be
called before their reference counter drops to zero.
Once the reference counter drops to zero, the tunnel or session is
destroyed. Destruction may happen in any context, so context dependant
operations still have to be done in l2tp_{tunnel,session}_free(). On
the other hand l2tp_{tunnel,session}_free() must not free data wich may
be required by their reference holders.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
A triton context handler may not unregister itself while executed by
the context thread, unless it returns -1 (otherwise the md thread may
free the handler before the context thread stops using it).
So l2tp_conn_read() must return -1 after calling l2tp_tunnel_free()
(the md handler associated to l2tp_conn_read() may be unregistered
by l2tp_tunnel_free()).
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Signed-off-by: Dmitry Kozlov <xeb@mail.ru>
|
|
Signed-off-by: Dmitry Kozlov <xeb@mail.ru>
|
|
The "reload" command frees the variable pointed to by conf_secret
in case the "secret" option gets removed from accel-ppp.conf. In
such a case, conf_secret must be reset to NULL to avoid dereferencing
the old pointer.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Store tunnel secret in the l2tp_conn_t structure so that different
tunnels may use different secrets.
The new "secret" option, added to the "l2tp create tunnel" command,
let the user define the secret to be used by the new tunnel.
By default, new tunnels keep using the "secret" option defined in
accel-ppp.conf.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Signed-off-by: Dmitry Kozlov <xeb@mail.ru>
|
|
There are a few inconsistencies between TR-101 and RFC 4679.
Since RFC 4679 is only informational, prefer TR-101 in case
of incompatibilities and explicitely document this choice.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
This TR-101 sub-tag has no payload.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
These are all 4 bytes integer values, except ACCESS_LOOP_ENCAP
which represents three independant values of one byte each.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
The length field of PPPoE TR-101 sub-tags only takes the payload size
into account (as opposed to its RADIUS counterpart that stores the
full sub-tag length, including the 2 bytes long header).
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
When a sub-tags is skipped while parsing a TR-101 tag, the ptr variable
must be updated to point to the next sub-tag, otherwise the next loop
iteration erroneously interprets tag information.
While here, fix the range of attribute that mustn't be present in RADIUS
access requests (RFC 4679, section 4).
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
As per TR-101 specifications and RFC 4679, 0x84 is the sub-tag
number for Minimum-Data-Rate-Downstream (instead of
Maximum-Data-Rate-Upstream).
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
Avoid parsing inconsistent PPPoE tags when handling PADR.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
warning if they're running already
Signed-off-by: Vladislav Grishenko <themiron@mail.ru>
|
|
start warning if they're running already"
This reverts commit c4ddc0fe1f402f84b1bb01b9568e2294569d0d15.
|
|
warning if they're running already
Signed-off-by: Vladislav Grishenko <themiron@mail.ru>
|
|
Signed-off-by: Dmitry Kozlov <xeb@mail.ru>
|
|
Signed-off-by: Dmitry Kozlov <xeb@mail.ru>
|
|
|
|
Signed-off-by: Vladislav Grishenko <themiron@mail.ru>
|
|
|
|
Signed-off-by: Dmitry Kozlov <xeb@mail.ru>
|