summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/ng_l2tp.c
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2004-08-03 06:52:55 +0000
committerbz <bz@FreeBSD.org>2004-08-03 06:52:55 +0000
commit5b63f751da98ab5dbadacc02675a9aa28607bb79 (patch)
tree976c9696cf76c92273abe7826705ce192e51891e /sys/netgraph/ng_l2tp.c
parent30d8b6d6ada8bcd6d6c75d7076b628f4e926cf55 (diff)
downloadFreeBSD-src-5b63f751da98ab5dbadacc02675a9aa28607bb79.zip
FreeBSD-src-5b63f751da98ab5dbadacc02675a9aa28607bb79.tar.gz
Implement minimalistic L2TP sessions statistics and correct man page
for L2TP tunnel statistics (which do not take an argument sessionID). Reviewed by: archie Approved by: pjd (mentor)
Diffstat (limited to 'sys/netgraph/ng_l2tp.c')
-rw-r--r--sys/netgraph/ng_l2tp.c85
1 files changed, 83 insertions, 2 deletions
diff --git a/sys/netgraph/ng_l2tp.c b/sys/netgraph/ng_l2tp.c
index 4d7efc7..6e5d6a7 100644
--- a/sys/netgraph/ng_l2tp.c
+++ b/sys/netgraph/ng_l2tp.c
@@ -150,6 +150,7 @@ typedef struct ng_l2tp_private *priv_p;
/* Hook private data (data session hooks only) */
struct ng_l2tp_hook_private {
struct ng_l2tp_sess_config conf; /* hook/session config */
+ struct ng_l2tp_session_stats stats; /* per sessions statistics */
u_int16_t ns; /* data ns sequence number */
u_int16_t nr; /* data nr sequence number */
};
@@ -221,6 +222,14 @@ static const struct ng_parse_type ng_l2tp_stats_type = {
&ng_l2tp_stats_type_fields
};
+/* Parse type for struct ng_l2tp_session_stats. */
+static const struct ng_parse_struct_field
+ ng_l2tp_session_stats_type_fields[] = NG_L2TP_SESSION_STATS_TYPE_INFO;
+static const struct ng_parse_type ng_l2tp_session_stats_type = {
+ &ng_parse_struct_type,
+ &ng_l2tp_session_stats_type_fields
+};
+
/* List of commands and how to convert arguments to/from ASCII */
static const struct ng_cmdlist ng_l2tp_cmdlist[] = {
{
@@ -274,6 +283,27 @@ static const struct ng_cmdlist ng_l2tp_cmdlist[] = {
},
{
NGM_L2TP_COOKIE,
+ NGM_L2TP_GET_SESSION_STATS,
+ "getsessstats",
+ &ng_parse_int16_type,
+ &ng_l2tp_session_stats_type
+ },
+ {
+ NGM_L2TP_COOKIE,
+ NGM_L2TP_CLR_SESSION_STATS,
+ "clrsessstats",
+ &ng_parse_int16_type,
+ NULL
+ },
+ {
+ NGM_L2TP_COOKIE,
+ NGM_L2TP_GETCLR_SESSION_STATS,
+ "getclrsessstats",
+ &ng_parse_int16_type,
+ &ng_l2tp_session_stats_type
+ },
+ {
+ NGM_L2TP_COOKIE,
NGM_L2TP_ACK_FAILURE,
"ackfailure",
NULL,
@@ -553,6 +583,45 @@ ng_l2tp_rcvmsg(node_p node, item_p item, hook_p lasthook)
memset(&priv->stats, 0, sizeof(priv->stats));
break;
}
+ case NGM_L2TP_GET_SESSION_STATS:
+ case NGM_L2TP_CLR_SESSION_STATS:
+ case NGM_L2TP_GETCLR_SESSION_STATS:
+ {
+ uint16_t session_id;
+ hookpriv_p hpriv;
+ hook_p hook;
+
+ /* Get session ID. */
+ if (msg->header.arglen != sizeof(session_id)) {
+ error = EINVAL;
+ break;
+ }
+ bcopy(msg->data, &session_id, sizeof(uint16_t));
+ session_id = htons(session_id);
+
+ /* Find matching hook. */
+ NG_NODE_FOREACH_HOOK(node, ng_l2tp_find_session,
+ (void *)(uintptr_t)session_id, hook);
+ if (hook == NULL) {
+ error = ENOENT;
+ break;
+ }
+ hpriv = NG_HOOK_PRIVATE(hook);
+
+ if (msg->header.cmd != NGM_L2TP_CLR_SESSION_STATS) {
+ NG_MKRESPONSE(resp, msg,
+ sizeof(hpriv->stats), M_NOWAIT);
+ if (resp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ bcopy(&hpriv->stats, resp->data,
+ sizeof(hpriv->stats));
+ }
+ if (msg->header.cmd != NGM_L2TP_GET_SESSION_STATS)
+ bzero(&hpriv->stats, sizeof(hpriv->stats));
+ break;
+ }
case NGM_L2TP_SET_SEQ:
{
struct ng_l2tp_seq_config *const conf =
@@ -708,6 +777,7 @@ ng_l2tp_reset_session(hook_p hook, void *arg)
if (hpriv != NULL) {
hpriv->conf.control_dseq = 0;
hpriv->conf.enable_dseq = 0;
+ bzero(&hpriv->conf, sizeof(struct ng_l2tp_session_stats));
hpriv->nr = 0;
hpriv->ns = 0;
}
@@ -734,14 +804,17 @@ ng_l2tp_recv_lower(node_p node, item_p item)
u_int16_t nr;
int is_ctrl;
int error;
- int len;
+ int len, plen;
/* Grab mbuf */
NGI_GET_M(item, m);
+ /* Remember full packet length; needed for per session accounting. */
+ plen = m->m_pkthdr.len;
+
/* Update stats */
priv->stats.recvPackets++;
- priv->stats.recvOctets += m->m_pkthdr.len;
+ priv->stats.recvOctets += plen;
/* Get initial header */
if (m->m_pkthdr.len < 6) {
@@ -904,6 +977,10 @@ ng_l2tp_recv_lower(node_p node, item_p item)
return (error);
}
+ /* Per session packet, account it. */
+ hpriv->stats.recvPackets++;
+ hpriv->stats.recvOctets += plen;
+
/* Follow peer's lead in data sequencing, if configured to do so */
if (!hpriv->conf.control_dseq)
hpriv->conf.enable_dseq = ((hdr & L2TP_HDR_SEQ) != 0);
@@ -1045,6 +1122,10 @@ ng_l2tp_recv_data(node_p node, item_p item, hookpriv_p hpriv)
}
mtod(m, u_int16_t *)[0] = htons(hdr);
+ /* Update per session stats. */
+ hpriv->stats.xmitPackets++;
+ hpriv->stats.xmitOctets += m->m_pkthdr.len;
+
/* Send packet */
NG_FWD_NEW_DATA(error, item, priv->lower, m);
return (error);
OpenPOWER on IntegriCloud