summaryrefslogtreecommitdiff
path: root/sys/netgraph
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netgraph')
-rw-r--r--sys/netgraph/ng_l2tp.c99
1 files changed, 45 insertions, 54 deletions
diff --git a/sys/netgraph/ng_l2tp.c b/sys/netgraph/ng_l2tp.c
index accf48d477fa..64fe0e33ded9 100644
--- a/sys/netgraph/ng_l2tp.c
+++ b/sys/netgraph/ng_l2tp.c
@@ -118,6 +118,7 @@ MALLOC_DEFINE(M_NETGRAPH_L2TP, "netgraph_l2tp", "netgraph l2tp node");
struct l2tp_seq {
u_int16_t ns; /* next xmit seq we send */
u_int16_t nr; /* next recv seq we expect */
+ u_int16_t inproc; /* packet is in processing */
u_int16_t rack; /* last 'nr' we rec'd */
u_int16_t xack; /* last 'nr' we sent */
u_int16_t wmax; /* peer's max recv window */
@@ -173,7 +174,6 @@ static int ng_l2tp_seq_adjust(priv_p priv,
static void ng_l2tp_seq_reset(priv_p priv);
static void ng_l2tp_seq_failure(priv_p priv);
static void ng_l2tp_seq_recv_nr(priv_p priv, u_int16_t nr);
-static int ng_l2tp_seq_recv_ns(priv_p priv, u_int16_t ns);
static void ng_l2tp_seq_xack_timeout(node_p node, hook_p hook,
void *arg1, int arg2);
static void ng_l2tp_seq_rack_timeout(node_p node, hook_p hook,
@@ -911,6 +911,7 @@ ng_l2tp_rcvdata_lower(hook_p h, item_p item)
/* Handle control packets */
if ((hdr & L2TP_HDR_CTRL) != 0) {
+ struct l2tp_seq *const seq = &priv->seq;
/* Handle receive ack sequence number Nr */
ng_l2tp_seq_recv_nr(priv, nr);
@@ -923,29 +924,59 @@ ng_l2tp_rcvdata_lower(hook_p h, item_p item)
ERROUT(0);
}
+ mtx_lock(&seq->mtx);
/*
- * Prepend session ID to packet here: we don't want to accept
- * the send sequence number Ns if we have to drop the packet
- * later because of a memory error, because then the upper
- * layer would never get the packet.
+ * If not what we expect or we are busy, drop packet and
+ * send an immediate ZLB ack.
*/
+ if (ns != seq->nr || seq->inproc) {
+ if (L2TP_SEQ_DIFF(ns, seq->nr) <= 0)
+ priv->stats.recvDuplicates++;
+ else
+ priv->stats.recvOutOfOrder++;
+ mtx_unlock(&seq->mtx);
+ ng_l2tp_xmit_ctrl(priv, NULL, seq->ns);
+ NG_FREE_ITEM(item);
+ NG_FREE_M(m);
+ ERROUT(0);
+ }
+ /*
+ * Until we deliver this packet we can't receive next one as
+ * we have no information for sending ack.
+ */
+ seq->inproc = 1;
+ mtx_unlock(&seq->mtx);
+
+ /* Prepend session ID to packet. */
M_PREPEND(m, 2, M_DONTWAIT);
if (m == NULL) {
+ seq->inproc = 0;
priv->stats.memoryFailures++;
NG_FREE_ITEM(item);
ERROUT(ENOBUFS);
}
memcpy(mtod(m, u_int16_t *), &ids[1], 2);
- /* Now handle send sequence number */
- if (ng_l2tp_seq_recv_ns(priv, ns) == -1) {
- NG_FREE_ITEM(item);
- NG_FREE_M(m);
- ERROUT(0);
- }
-
/* Deliver packet to upper layers */
NG_FWD_NEW_DATA(error, item, priv->ctrl, m);
+
+ mtx_lock(&seq->mtx);
+ /* Ready to process next packet. */
+ seq->inproc = 0;
+
+ /* If packet was successfully delivered send ack. */
+ if (error == 0) {
+ /* Update recv sequence number */
+ seq->nr++;
+ /* Start receive ack timer, if not already running */
+ if (!callout_active(&seq->xack_timer)) {
+ ng_callout(&seq->xack_timer, priv->node, NULL,
+ L2TP_DELAYED_ACK, ng_l2tp_seq_xack_timeout,
+ NULL, 0);
+ }
+ }
+ mtx_unlock(&seq->mtx);
+
ERROUT(error);
}
@@ -1389,47 +1420,6 @@ ng_l2tp_seq_recv_nr(priv_p priv, u_int16_t nr)
}
/*
- * Handle receipt of a sequence number value (Ns) from peer.
- * We make no attempt to re-order out of order packets.
- *
- * This function should only be called for non-ZLB packets.
- *
- * Returns:
- * 0 Accept packet
- * -1 Drop packet
- */
-static int
-ng_l2tp_seq_recv_ns(priv_p priv, u_int16_t ns)
-{
- struct l2tp_seq *const seq = &priv->seq;
-
- /* If not what we expect, drop packet and send an immediate ZLB ack */
- if (ns != seq->nr) {
- if (L2TP_SEQ_DIFF(ns, seq->nr) < 0)
- priv->stats.recvDuplicates++;
- else
- priv->stats.recvOutOfOrder++;
- ng_l2tp_xmit_ctrl(priv, NULL, seq->ns);
- return (-1);
- }
-
- mtx_lock(&seq->mtx);
-
- /* Update recv sequence number */
- seq->nr++;
-
- /* Start receive ack timer, if not already running */
- if (!callout_active(&seq->xack_timer))
- ng_callout(&seq->xack_timer, priv->node, NULL,
- L2TP_DELAYED_ACK, ng_l2tp_seq_xack_timeout, NULL, 0);
-
- mtx_unlock(&seq->mtx);
-
- /* Accept packet */
- return (0);
-}
-
-/*
* Handle an ack timeout. We have an outstanding ack that we
* were hoping to piggy-back, but haven't, so send a ZLB.
*/
@@ -1491,6 +1481,7 @@ ng_l2tp_seq_rack_timeout(node_p node, hook_p hook, void *arg1, int arg2)
hz * delay, ng_l2tp_seq_rack_timeout, NULL, 0);
/* Do slow-start/congestion algorithm windowing algorithm */
+ seq->ns = seq->rack;
seq->ssth = (seq->cwnd + 1) / 2;
seq->cwnd = 1;
seq->acks = 0;
@@ -1499,7 +1490,7 @@ ng_l2tp_seq_rack_timeout(node_p node, hook_p hook, void *arg1, int arg2)
if ((m = L2TP_COPY_MBUF(seq->xwin[0], M_DONTWAIT)) == NULL)
priv->stats.memoryFailures++;
else
- ng_l2tp_xmit_ctrl(priv, m, seq->rack);
+ ng_l2tp_xmit_ctrl(priv, m, seq->ns++);
/* callout_deactivate() is not needed here
as ng_callout() is getting called each time */