Commit 6b7bdcd7 authored by Tom Parkin's avatar Tom Parkin Committed by David S. Miller

l2tp: add tracepoints to l2tp_core.c

Add lifetime event tracing for tunnel and session instances, tracking
tunnel and session registration, deletion, and eventual freeing.

Port the data path sequence number debug logging to use trace points
rather than custom debug macros.
Signed-off-by: default avatarTom Parkin <tparkin@katalix.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2a03dd8e
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#include <linux/atomic.h> #include <linux/atomic.h>
#include "l2tp_core.h" #include "l2tp_core.h"
#include "trace.h"
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include "trace.h" #include "trace.h"
...@@ -154,6 +155,7 @@ l2tp_session_id_hash(struct l2tp_tunnel *tunnel, u32 session_id) ...@@ -154,6 +155,7 @@ l2tp_session_id_hash(struct l2tp_tunnel *tunnel, u32 session_id)
static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel) static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel)
{ {
trace_free_tunnel(tunnel);
sock_put(tunnel->sock); sock_put(tunnel->sock);
/* the tunnel is freed in the socket destructor */ /* the tunnel is freed in the socket destructor */
} }
...@@ -162,6 +164,8 @@ static void l2tp_session_free(struct l2tp_session *session) ...@@ -162,6 +164,8 @@ static void l2tp_session_free(struct l2tp_session *session)
{ {
struct l2tp_tunnel *tunnel = session->tunnel; struct l2tp_tunnel *tunnel = session->tunnel;
trace_free_session(session);
if (tunnel) { if (tunnel) {
if (WARN_ON(tunnel->magic != L2TP_TUNNEL_MAGIC)) if (WARN_ON(tunnel->magic != L2TP_TUNNEL_MAGIC))
goto out; goto out;
...@@ -384,6 +388,8 @@ int l2tp_session_register(struct l2tp_session *session, ...@@ -384,6 +388,8 @@ int l2tp_session_register(struct l2tp_session *session,
hlist_add_head(&session->hlist, head); hlist_add_head(&session->hlist, head);
write_unlock_bh(&tunnel->hlist_lock); write_unlock_bh(&tunnel->hlist_lock);
trace_register_session(session);
return 0; return 0;
err_tlock_pnlock: err_tlock_pnlock:
...@@ -412,10 +418,6 @@ static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *sk ...@@ -412,10 +418,6 @@ static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *sk
skb_queue_walk_safe(&session->reorder_q, skbp, tmp) { skb_queue_walk_safe(&session->reorder_q, skbp, tmp) {
if (L2TP_SKB_CB(skbp)->ns > ns) { if (L2TP_SKB_CB(skbp)->ns > ns) {
__skb_queue_before(&session->reorder_q, skbp, skb); __skb_queue_before(&session->reorder_q, skbp, skb);
l2tp_dbg(session, L2TP_MSG_SEQ,
"%s: pkt %hu, inserted before %hu, reorder_q len=%d\n",
session->name, ns, L2TP_SKB_CB(skbp)->ns,
skb_queue_len(&session->reorder_q));
atomic_long_inc(&session->stats.rx_oos_packets); atomic_long_inc(&session->stats.rx_oos_packets);
goto out; goto out;
} }
...@@ -448,9 +450,7 @@ static void l2tp_recv_dequeue_skb(struct l2tp_session *session, struct sk_buff * ...@@ -448,9 +450,7 @@ static void l2tp_recv_dequeue_skb(struct l2tp_session *session, struct sk_buff *
/* Bump our Nr */ /* Bump our Nr */
session->nr++; session->nr++;
session->nr &= session->nr_max; session->nr &= session->nr_max;
trace_session_seqnum_update(session);
l2tp_dbg(session, L2TP_MSG_SEQ, "%s: updated nr to %hu\n",
session->name, session->nr);
} }
/* call private receive handler */ /* call private receive handler */
...@@ -475,37 +475,27 @@ static void l2tp_recv_dequeue(struct l2tp_session *session) ...@@ -475,37 +475,27 @@ static void l2tp_recv_dequeue(struct l2tp_session *session)
start: start:
spin_lock_bh(&session->reorder_q.lock); spin_lock_bh(&session->reorder_q.lock);
skb_queue_walk_safe(&session->reorder_q, skb, tmp) { skb_queue_walk_safe(&session->reorder_q, skb, tmp) {
if (time_after(jiffies, L2TP_SKB_CB(skb)->expires)) { struct l2tp_skb_cb *cb = L2TP_SKB_CB(skb);
/* If the packet has been pending on the queue for too long, discard it */
if (time_after(jiffies, cb->expires)) {
atomic_long_inc(&session->stats.rx_seq_discards); atomic_long_inc(&session->stats.rx_seq_discards);
atomic_long_inc(&session->stats.rx_errors); atomic_long_inc(&session->stats.rx_errors);
l2tp_dbg(session, L2TP_MSG_SEQ, trace_session_pkt_expired(session, cb->ns);
"%s: oos pkt %u len %d discarded (too old), waiting for %u, reorder_q_len=%d\n",
session->name, L2TP_SKB_CB(skb)->ns,
L2TP_SKB_CB(skb)->length, session->nr,
skb_queue_len(&session->reorder_q));
session->reorder_skip = 1; session->reorder_skip = 1;
__skb_unlink(skb, &session->reorder_q); __skb_unlink(skb, &session->reorder_q);
kfree_skb(skb); kfree_skb(skb);
continue; continue;
} }
if (L2TP_SKB_CB(skb)->has_seq) { if (cb->has_seq) {
if (session->reorder_skip) { if (session->reorder_skip) {
l2tp_dbg(session, L2TP_MSG_SEQ,
"%s: advancing nr to next pkt: %u -> %u",
session->name, session->nr,
L2TP_SKB_CB(skb)->ns);
session->reorder_skip = 0; session->reorder_skip = 0;
session->nr = L2TP_SKB_CB(skb)->ns; session->nr = cb->ns;
trace_session_seqnum_reset(session);
} }
if (L2TP_SKB_CB(skb)->ns != session->nr) { if (cb->ns != session->nr)
l2tp_dbg(session, L2TP_MSG_SEQ,
"%s: holding oos pkt %u len %d, waiting for %u, reorder_q_len=%d\n",
session->name, L2TP_SKB_CB(skb)->ns,
L2TP_SKB_CB(skb)->length, session->nr,
skb_queue_len(&session->reorder_q));
goto out; goto out;
}
} }
__skb_unlink(skb, &session->reorder_q); __skb_unlink(skb, &session->reorder_q);
...@@ -538,14 +528,13 @@ static int l2tp_seq_check_rx_window(struct l2tp_session *session, u32 nr) ...@@ -538,14 +528,13 @@ static int l2tp_seq_check_rx_window(struct l2tp_session *session, u32 nr)
*/ */
static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb) static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb)
{ {
if (!l2tp_seq_check_rx_window(session, L2TP_SKB_CB(skb)->ns)) { struct l2tp_skb_cb *cb = L2TP_SKB_CB(skb);
if (!l2tp_seq_check_rx_window(session, cb->ns)) {
/* Packet sequence number is outside allowed window. /* Packet sequence number is outside allowed window.
* Discard it. * Discard it.
*/ */
l2tp_dbg(session, L2TP_MSG_SEQ, trace_session_pkt_outside_rx_window(session, cb->ns);
"%s: pkt %u len %d discarded, outside window, nr=%u\n",
session->name, L2TP_SKB_CB(skb)->ns,
L2TP_SKB_CB(skb)->length, session->nr);
goto discard; goto discard;
} }
...@@ -562,10 +551,10 @@ static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb) ...@@ -562,10 +551,10 @@ static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb)
* is seen. After nr_oos_count_max in-sequence packets, reset the * is seen. After nr_oos_count_max in-sequence packets, reset the
* sequence number to re-enable packet reception. * sequence number to re-enable packet reception.
*/ */
if (L2TP_SKB_CB(skb)->ns == session->nr) { if (cb->ns == session->nr) {
skb_queue_tail(&session->reorder_q, skb); skb_queue_tail(&session->reorder_q, skb);
} else { } else {
u32 nr_oos = L2TP_SKB_CB(skb)->ns; u32 nr_oos = cb->ns;
u32 nr_next = (session->nr_oos + 1) & session->nr_max; u32 nr_next = (session->nr_oos + 1) & session->nr_max;
if (nr_oos == nr_next) if (nr_oos == nr_next)
...@@ -576,17 +565,10 @@ static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb) ...@@ -576,17 +565,10 @@ static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb)
session->nr_oos = nr_oos; session->nr_oos = nr_oos;
if (session->nr_oos_count > session->nr_oos_count_max) { if (session->nr_oos_count > session->nr_oos_count_max) {
session->reorder_skip = 1; session->reorder_skip = 1;
l2tp_dbg(session, L2TP_MSG_SEQ,
"%s: %d oos packets received. Resetting sequence numbers\n",
session->name, session->nr_oos_count);
} }
if (!session->reorder_skip) { if (!session->reorder_skip) {
atomic_long_inc(&session->stats.rx_seq_discards); atomic_long_inc(&session->stats.rx_seq_discards);
l2tp_dbg(session, L2TP_MSG_SEQ, trace_session_pkt_oos(session, cb->ns);
"%s: oos pkt %u len %d discarded, waiting for %u, reorder_q_len=%d\n",
session->name, L2TP_SKB_CB(skb)->ns,
L2TP_SKB_CB(skb)->length, session->nr,
skb_queue_len(&session->reorder_q));
goto discard; goto discard;
} }
skb_queue_tail(&session->reorder_q, skb); skb_queue_tail(&session->reorder_q, skb);
...@@ -712,9 +694,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, ...@@ -712,9 +694,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
* configure it so. * configure it so.
*/ */
if (!session->lns_mode && !session->send_seq) { if (!session->lns_mode && !session->send_seq) {
l2tp_info(session, L2TP_MSG_SEQ, trace_session_seqnum_lns_enable(session);
"%s: requested to enable seq numbers by LNS\n",
session->name);
session->send_seq = 1; session->send_seq = 1;
l2tp_session_set_header_len(session, tunnel->version); l2tp_session_set_header_len(session, tunnel->version);
} }
...@@ -735,9 +715,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, ...@@ -735,9 +715,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
* LAC is broken. Discard the frame. * LAC is broken. Discard the frame.
*/ */
if (!session->lns_mode && session->send_seq) { if (!session->lns_mode && session->send_seq) {
l2tp_info(session, L2TP_MSG_SEQ, trace_session_seqnum_lns_disable(session);
"%s: requested to disable seq numbers by LNS\n",
session->name);
session->send_seq = 0; session->send_seq = 0;
l2tp_session_set_header_len(session, tunnel->version); l2tp_session_set_header_len(session, tunnel->version);
} else if (session->send_seq) { } else if (session->send_seq) {
...@@ -961,8 +939,7 @@ static int l2tp_build_l2tpv2_header(struct l2tp_session *session, void *buf) ...@@ -961,8 +939,7 @@ static int l2tp_build_l2tpv2_header(struct l2tp_session *session, void *buf)
*bufp++ = 0; *bufp++ = 0;
session->ns++; session->ns++;
session->ns &= 0xffff; session->ns &= 0xffff;
l2tp_dbg(session, L2TP_MSG_SEQ, "%s: updated ns to %u\n", trace_session_seqnum_update(session);
session->name, session->ns);
} }
return bufp - optr; return bufp - optr;
...@@ -998,9 +975,7 @@ static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf) ...@@ -998,9 +975,7 @@ static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf)
l2h = 0x40000000 | session->ns; l2h = 0x40000000 | session->ns;
session->ns++; session->ns++;
session->ns &= 0xffffff; session->ns &= 0xffffff;
l2tp_dbg(session, L2TP_MSG_SEQ, trace_session_seqnum_update(session);
"%s: updated ns to %u\n",
session->name, session->ns);
} }
*((__be32 *)bufp) = htonl(l2h); *((__be32 *)bufp) = htonl(l2h);
...@@ -1540,6 +1515,8 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, ...@@ -1540,6 +1515,8 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
"l2tp_sock"); "l2tp_sock");
sk->sk_allocation = GFP_ATOMIC; sk->sk_allocation = GFP_ATOMIC;
trace_register_tunnel(tunnel);
if (tunnel->fd >= 0) if (tunnel->fd >= 0)
sockfd_put(sock); sockfd_put(sock);
...@@ -1560,6 +1537,7 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_register); ...@@ -1560,6 +1537,7 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_register);
void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
{ {
if (!test_and_set_bit(0, &tunnel->dead)) { if (!test_and_set_bit(0, &tunnel->dead)) {
trace_delete_tunnel(tunnel);
l2tp_tunnel_inc_refcount(tunnel); l2tp_tunnel_inc_refcount(tunnel);
queue_work(l2tp_wq, &tunnel->del_work); queue_work(l2tp_wq, &tunnel->del_work);
} }
...@@ -1571,6 +1549,7 @@ void l2tp_session_delete(struct l2tp_session *session) ...@@ -1571,6 +1549,7 @@ void l2tp_session_delete(struct l2tp_session *session)
if (test_and_set_bit(0, &session->dead)) if (test_and_set_bit(0, &session->dead))
return; return;
trace_delete_session(session);
l2tp_session_unhash(session); l2tp_session_unhash(session);
l2tp_session_queue_purge(session); l2tp_session_queue_purge(session);
if (session->session_close) if (session->session_close)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment