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)
This commit is contained in:
bz 2004-08-03 06:52:55 +00:00
parent f0b5848c69
commit bbb27d590e
3 changed files with 120 additions and 9 deletions

View File

@ -261,18 +261,28 @@ the current configuration for the corresponding data session as a
.Vt "struct ng_l2tp_sess_config" .
The corresponding session hook must be connected.
.It Dv NGM_L2TP_GET_STATS
This command takes a two byte session ID as an argument and returns a
This command returns a
.Vt "struct ng_l2tp_stats"
containing statistics for the corresponding data session.
The corresponding session hook must be connected.
containing statistics of the L2TP tunnel.
.It Dv NGM_L2TP_CLR_STATS
This command takes a two byte session ID as an argument and
clears the statistics for that data session.
The corresponding session hook must be connected.
This command clears the statistics for the L2TP tunnel.
.It Dv NGM_L2TP_GETCLR_STATS
Same as
.Dv NGM_L2TP_GET_STATS ,
but also atomically clears the statistics as well.
.It Dv NGM_L2TP_GET_SESSION_STATS
This command takes a two byte session ID as an argument and returns a
.Vt "struct ng_l2tp_session_stats"
containing statistics for the corresponding data session.
The corresponding session hook must be connected.
.It Dv NGM_L2TP_CLR_SESSION_STATS
This command takes a two byte session ID as an argument and
clears the statistics for that data session.
The corresponding session hook must be connected.
.It Dv NGM_L2TP_GETCLR_SESSION_STATS
Same as
.Dv NGM_L2TP_GET_SESSION_STATS ,
but also atomically clears the statistics as well.
.It Dv NGM_L2TP_SET_SEQ
This command sets the sequence numbers of a not yet enabled node.
It takes a

View File

@ -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[] = {
{
@ -272,6 +281,27 @@ static const struct ng_cmdlist ng_l2tp_cmdlist[] = {
NULL,
&ng_l2tp_stats_type
},
{
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,
@ -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);

View File

@ -45,7 +45,7 @@
/* Node type name and magic cookie */
#define NG_L2TP_NODE_TYPE "l2tp"
#define NGM_L2TP_COOKIE 1091448040
#define NGM_L2TP_COOKIE 1091515793
/* Hook names */
#define NG_L2TP_HOOK_CTRL "ctrl" /* control channel hook */
@ -161,6 +161,23 @@ struct ng_l2tp_stats {
{ NULL } \
}
/* Session statistics struct. */
struct ng_l2tp_session_stats {
u_int64_t xmitPackets; /* number of packets xmit */
u_int64_t xmitOctets; /* number of octets xmit */
u_int64_t recvPackets; /* number of packets received */
u_int64_t recvOctets; /* number of octets received */
};
/* Keep this in sync with the above structure definition. */
#define NG_L2TP_SESSION_STATS_TYPE_INFO { \
{ "xmitPackets", &ng_parse_uint64_type }, \
{ "xmitOctets", &ng_parse_uint64_type }, \
{ "recvPackets", &ng_parse_uint64_type }, \
{ "recvOctets", &ng_parse_uint64_type }, \
{ NULL } \
}
/* Netgraph commands */
enum {
NGM_L2TP_SET_CONFIG = 1, /* supply a struct ng_l2tp_config */
@ -170,6 +187,9 @@ enum {
NGM_L2TP_GET_STATS, /* returns struct ng_l2tp_stats */
NGM_L2TP_CLR_STATS, /* clears stats */
NGM_L2TP_GETCLR_STATS, /* returns & clears stats */
NGM_L2TP_GET_SESSION_STATS, /* returns session stats */
NGM_L2TP_CLR_SESSION_STATS, /* clears session stats */
NGM_L2TP_GETCLR_SESSION_STATS, /* returns & clears session stats */
NGM_L2TP_ACK_FAILURE, /* sent *from* node after ack timeout */
NGM_L2TP_SET_SEQ /* supply a struct ng_l2tp_seq_config */
};