Maintain statistics about the received frames.
This commit is contained in:
parent
be28a6af38
commit
171e08dc7f
@ -35,7 +35,7 @@
|
||||
.\" $FreeBSD$
|
||||
.\" $Whistle: ng_hole.8,v 1.4 1999/01/25 23:46:26 archie Exp $
|
||||
.\"
|
||||
.Dd January 19, 1999
|
||||
.Dd May 19, 2004
|
||||
.Dt NG_HOLE 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -54,8 +54,25 @@ A
|
||||
node accepts any request to connect, regardless of the hook name,
|
||||
as long as the name is unique.
|
||||
.Sh CONTROL MESSAGES
|
||||
This node type supports only the generic control messages.
|
||||
Other control messages are silently discarded.
|
||||
This node type supports the generic control messages, plus the
|
||||
following:
|
||||
.Bl -tag -width indent
|
||||
.It Dv NGM_BPF_GET_STATS
|
||||
This command takes an
|
||||
.Tn ASCII
|
||||
string argument, the hook name, and returns the statistics
|
||||
associated with the hook as a
|
||||
.Vt "struct ng_hole_hookstat" .
|
||||
.It Dv NGM_BPF_CLR_STATS
|
||||
This command takes an
|
||||
.Tn ASCII
|
||||
string argument, the hook name, and clears the statistics
|
||||
associated with the hook.
|
||||
.It Dv NGM_BPF_GETCLR_STATS
|
||||
This command is identical to
|
||||
.Dv NGM_BPF_GET_STATS ,
|
||||
except that the statistics are also atomically cleared.
|
||||
.El
|
||||
.Sh SHUTDOWN
|
||||
This node shuts down upon receipt of a
|
||||
.Dv NGM_SHUTDOWN
|
||||
|
@ -51,10 +51,53 @@
|
||||
#include <sys/mbuf.h>
|
||||
#include <netgraph/ng_message.h>
|
||||
#include <netgraph/netgraph.h>
|
||||
#include <netgraph/ng_parse.h>
|
||||
#include <netgraph/ng_hole.h>
|
||||
|
||||
/* Per hook private info. */
|
||||
struct ng_hole_hookinfo {
|
||||
struct ng_hole_hookstat stats;
|
||||
};
|
||||
typedef struct ng_hole_hookinfo *hinfo_p;
|
||||
|
||||
/* Parse type for struct ng_hole_hookstat. */
|
||||
static const struct ng_parse_struct_field ng_hole_hookstat_type_fields[] =
|
||||
NG_HOLE_HOOKSTAT_TYPE_INFO;
|
||||
static const struct ng_parse_type ng_hole_hookstat_type = {
|
||||
&ng_parse_struct_type,
|
||||
&ng_hole_hookstat_type_fields
|
||||
};
|
||||
|
||||
/* List of commands and how to convert arguments to/from ASCII. */
|
||||
static const struct ng_cmdlist ng_hole_cmdlist[] = {
|
||||
{
|
||||
NGM_HOLE_COOKIE,
|
||||
NGM_HOLE_GET_STATS,
|
||||
"getstats",
|
||||
&ng_parse_hookbuf_type,
|
||||
&ng_hole_hookstat_type
|
||||
},
|
||||
{
|
||||
NGM_HOLE_COOKIE,
|
||||
NGM_HOLE_CLR_STATS,
|
||||
"clrstats",
|
||||
&ng_parse_hookbuf_type,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
NGM_HOLE_COOKIE,
|
||||
NGM_HOLE_GETCLR_STATS,
|
||||
"getclrstats",
|
||||
&ng_parse_hookbuf_type,
|
||||
&ng_hole_hookstat_type
|
||||
},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Netgraph methods */
|
||||
static ng_constructor_t ngh_cons;
|
||||
static ng_rcvmsg_t ngh_rcvmsg;
|
||||
static ng_newhook_t ngh_newhook;
|
||||
static ng_rcvdata_t ngh_rcvdata;
|
||||
static ng_disconnect_t ngh_disconnect;
|
||||
|
||||
@ -63,14 +106,14 @@ static struct ng_type typestruct = {
|
||||
NG_HOLE_NODE_TYPE,
|
||||
NULL, /* modeventhand_t */
|
||||
ngh_cons, /* ng_constructor_t */
|
||||
NULL, /* ng_rcvmsg_t */
|
||||
ngh_rcvmsg, /* ng_rcvmsg_t */
|
||||
NULL, /* ng_shutdown_t */
|
||||
NULL, /* ng_newhook_t */
|
||||
ngh_newhook, /* ng_newhook_t */
|
||||
NULL, /* ng_findhook_t */
|
||||
NULL, /* ng_connect_t */
|
||||
ngh_rcvdata, /* ng_rcvdata_t */
|
||||
ngh_disconnect, /* ng_disconnect_t */
|
||||
NULL /* ng_cmdlist */
|
||||
ng_hole_cmdlist /* ng_cmdlist */
|
||||
};
|
||||
NETGRAPH_INIT(hole, &typestruct);
|
||||
|
||||
@ -83,12 +126,91 @@ ngh_cons(node_p node)
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a hook.
|
||||
*/
|
||||
static int
|
||||
ngh_newhook(node_p node, hook_p hook, const char *name)
|
||||
{
|
||||
hinfo_p hip;
|
||||
|
||||
/* Create hook private structure. */
|
||||
MALLOC(hip, hinfo_p, sizeof(*hip), M_NETGRAPH, M_NOWAIT | M_ZERO);
|
||||
if (hip == NULL)
|
||||
return (ENOMEM);
|
||||
NG_HOOK_SET_PRIVATE(hook, hip);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a control message.
|
||||
*/
|
||||
static int
|
||||
ngh_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
{
|
||||
struct ng_mesg *msg;
|
||||
struct ng_mesg *resp = NULL;
|
||||
int error = 0;
|
||||
struct ng_hole_hookstat *stats;
|
||||
hook_p hook;
|
||||
|
||||
NGI_GET_MSG(item, msg);
|
||||
switch (msg->header.typecookie) {
|
||||
case NGM_HOLE_COOKIE:
|
||||
switch (msg->header.cmd) {
|
||||
case NGM_HOLE_GET_STATS:
|
||||
case NGM_HOLE_CLR_STATS:
|
||||
case NGM_HOLE_GETCLR_STATS:
|
||||
/* Sanity check. */
|
||||
if (msg->header.arglen != NG_HOOKLEN + 1) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
/* Find hook. */
|
||||
hook = ng_findhook(node, (char *)msg->data);
|
||||
if (hook == NULL) {
|
||||
error = ENOENT;
|
||||
break;
|
||||
}
|
||||
stats = &((hinfo_p)NG_HOOK_PRIVATE(hook))->stats;
|
||||
/* Build response (if desired). */
|
||||
if (msg->header.cmd != NGM_HOLE_CLR_STATS) {
|
||||
NG_MKRESPONSE(resp, msg, sizeof(*stats),
|
||||
M_NOWAIT);
|
||||
if (resp == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
bcopy(stats, resp->data, sizeof(*stats));
|
||||
}
|
||||
/* Clear stats (if desired). */
|
||||
if (msg->header.cmd != NGM_HOLE_GET_STATS)
|
||||
bzero(stats, sizeof(*stats));
|
||||
break;
|
||||
default: /* Unknown command. */
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default: /* Unknown type cookie. */
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
NG_RESPOND_MSG(error, node, item, resp);
|
||||
NG_FREE_MSG(msg);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive data
|
||||
*/
|
||||
static int
|
||||
ngh_rcvdata(hook_p hook, item_p item)
|
||||
{
|
||||
const hinfo_p hip = NG_HOOK_PRIVATE(hook);
|
||||
|
||||
hip->stats.frames++;
|
||||
hip->stats.octets += NGI_M(item)->m_pkthdr.len;
|
||||
NG_FREE_ITEM(item);
|
||||
return 0;
|
||||
}
|
||||
@ -99,6 +221,8 @@ ngh_rcvdata(hook_p hook, item_p item)
|
||||
static int
|
||||
ngh_disconnect(hook_p hook)
|
||||
{
|
||||
|
||||
NG_HOOK_SET_PRIVATE(hook, NULL);
|
||||
if (NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
|
||||
ng_rmnode_self(NG_HOOK_NODE(hook));
|
||||
return (0);
|
||||
|
@ -46,5 +46,25 @@
|
||||
/* Node type name and magic cookie */
|
||||
#define NG_HOLE_NODE_TYPE "hole"
|
||||
#define NGM_HOLE_COOKIE 915433206
|
||||
|
||||
/* Statistics structure for one hook. */
|
||||
struct ng_hole_hookstat {
|
||||
uint64_t frames;
|
||||
uint64_t octets;
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition. */
|
||||
#define NG_HOLE_HOOKSTAT_TYPE_INFO { \
|
||||
{ "frames", &ng_parse_uint64_type }, \
|
||||
{ "octets", &ng_parse_uint64_type }, \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
/* Netgraph commands. */
|
||||
enum {
|
||||
NGM_HOLE_GET_STATS = 1,
|
||||
NGM_HOLE_CLR_STATS,
|
||||
NGM_HOLE_GETCLR_STATS,
|
||||
};
|
||||
|
||||
#endif /* _NETGRAPH_NG_HOLE_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user