summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/ng_sample.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netgraph/ng_sample.c')
-rw-r--r--sys/netgraph/ng_sample.c100
1 files changed, 62 insertions, 38 deletions
diff --git a/sys/netgraph/ng_sample.c b/sys/netgraph/ng_sample.c
index 831e070..76558f3 100644
--- a/sys/netgraph/ng_sample.c
+++ b/sys/netgraph/ng_sample.c
@@ -61,7 +61,7 @@
static ng_constructor_t ng_xxx_constructor;
static ng_rcvmsg_t ng_xxx_rcvmsg;
-static ng_shutdown_t ng_xxx_rmnode;
+static ng_shutdown_t ng_xxx_shutdown;
static ng_newhook_t ng_xxx_newhook;
static ng_connect_t ng_xxx_connect;
static ng_rcvdata_t ng_xxx_rcvdata; /* note these are both ng_rcvdata_t */
@@ -101,7 +101,7 @@ static struct ng_type typestruct = {
NULL,
ng_xxx_constructor,
ng_xxx_rcvmsg,
- ng_xxx_rmnode,
+ ng_xxx_shutdown,
ng_xxx_newhook,
NULL,
ng_xxx_connect,
@@ -131,20 +131,16 @@ struct XXX {
typedef struct XXX *xxx_p;
/*
- * Allocate the private data structure and the generic node
- * and link them together.
- *
- * ng_make_node_common() returns with a generic node struct
- * with a single reference for us.. we transfer it to the
- * private structure.. when we free the private struct we must
- * unref the node so it gets freed too.
+ * Allocate the private data structure. The generic node has already
+ * been created. Link them together. We arrive with a reference to the node
+ * i.e. the reference count is incremented for us already.
*
* If this were a device node than this work would be done in the attach()
* routine and the constructor would return EINVAL as you should not be able
* to creatednodes that depend on hardware (unless you can add the hardware :)
*/
static int
-ng_xxx_constructor(node_p *nodep)
+ng_xxx_constructor(node_p nodep)
{
xxx_p privdata;
int i, error;
@@ -159,12 +155,6 @@ ng_xxx_constructor(node_p *nodep)
privdata->channel[i].channel = i;
}
- /* Call the 'generic' (ie, superclass) node constructor */
- if ((error = ng_make_node_common(&typestruct, nodep))) {
- FREE(privdata, M_NETGRAPH);
- return (error);
- }
-
/* Link structs together; this counts as our one reference to *nodep */
(*nodep)->private = privdata;
privdata->node = *nodep;
@@ -245,6 +235,11 @@ ng_xxx_newhook(node_p node, hook_p hook, const char *name)
/*
* Get a netgraph control message.
+ * We actually recieve a queue item that has a pointer to the message.
+ * If we free the item, the message will be freed too, unless we remove
+ * it from the item using NGI_GET_MSG();
+ * The return address is also stored in the item, as an ng_ID_t,
+ * accessible as NGI_RETADDR(item);
* Check it is one we understand. If needed, send a response.
* We could save the address for an async action later, but don't here.
* Always free the message.
@@ -255,13 +250,14 @@ ng_xxx_newhook(node_p node, hook_p hook, const char *name)
* (so that old userland programs could continue to work).
*/
static int
-ng_xxx_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
- struct ng_mesg **rptr, hook_p lasthook)
+ng_xxx_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const xxx_p xxxp = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
+ struct ng_mesg *msg;
+ NGI_GET_MSG(item, msg);
/* Deal with message according to cookie and command */
switch (msg->header.typecookie) {
case NGM_XXX_COOKIE:
@@ -298,18 +294,17 @@ ng_xxx_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
}
/* Take care of synchronous response, if any */
- if (rptr)
- *rptr = resp;
- else if (resp)
- FREE(resp, M_NETGRAPH);
-
+ NG_RESPOND_MSG(error, node, item, resp);
/* Free the message and return */
- FREE(msg, M_NETGRAPH);
+ NG_FREE_MSG(msg);
return(error);
}
/*
* Receive data, and do something with it.
+ * Actually we receive a queue item which holds the data.
+ * If we free the item it wil also froo the data and metadata unless
+ * we have previously disassociated them using the NGI_GET_xxx() macros.
* Possibly send it out on another link after processing.
* Possibly do something different if it comes from different
* hooks. the caller will never free m or meta, so
@@ -321,14 +316,17 @@ ng_xxx_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* in the connect() method.
*/
static int
-ng_xxx_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
- struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
+ng_xxx_rcvdata(hook_p hook, item_p item )
{
const xxx_p xxxp = hook->node->private;
int chan = -2;
int dlci = -2;
int error;
+ struct mbuf *m;
+ meta_p meta;
+
+ NGI_GET_M(item, m);
if (hook->private) {
dlci = ((struct XXX_hookinfo *) hook->private)->dlci;
chan = ((struct XXX_hookinfo *) hook->private)->channel;
@@ -339,8 +337,8 @@ ng_xxx_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* the front here */
/* M_PREPEND(....) ; */
/* mtod(m, xxxxxx)->dlci = dlci; */
- NG_SEND_DATA(error, xxxp->downstream_hook.hook,
- m, meta);
+ NG_FWD_NEW_DATA(error, item,
+ xxxp->downstream_hook.hook, m);
xxxp->packets_out++;
} else {
/* data came from the multiplexed link */
@@ -350,7 +348,8 @@ ng_xxx_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
if (xxxp->channel[chan].dlci == dlci)
break;
if (chan == XXX_NUM_DLCIS) {
- NG_FREE_DATA(m, meta);
+ NG_FREE_ITEM(item);
+ NG_FREE_M(m);
return (ENETUNREACH);
}
/* If we were called at splnet, use the following:
@@ -364,13 +363,15 @@ ng_xxx_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* the processing of the data can continue. after
* these are run 'm' and 'meta' should be considered
* as invalid and NG_SEND_DATA actually zaps them. */
- NG_SEND_DATA(error, xxxp->channel[chan].hook, m, meta);
+ NG_FWD_NEW_DATA(error, item,
+ xxxp->channel[chan].hook, m);
xxxp->packets_in++;
}
} else {
/* It's the debug hook, throw it away.. */
if (hook == xxxp->downstream_hook.hook)
- NG_FREE_DATA(m, meta);
+ NG_FREE_ITEM(item);
+ NG_FREE_M(m);
}
return 0;
}
@@ -398,24 +399,46 @@ devintr()
/*
* Do local shutdown processing..
+ * All our links and the name have already been removed.
* If we are a persistant device, we might refuse to go away, and
- * we'd only remove our links and reset ourself.
+ * we'd create a new node immediatly.
*/
static int
-ng_xxx_rmnode(node_p node)
+ng_xxx_shutdown(node_p node)
{
const xxx_p privdata = node->private;
+ int error;
node->flags |= NG_INVALID;
- ng_cutlinks(node);
-#ifndef PERSISTANT_NODE
- ng_unname(node);
node->private = NULL;
ng_unref(privdata->node);
+#ifndef PERSISTANT_NODE
FREE(privdata, M_NETGRAPH);
#else
+ /*
+ * Create a new node. This is basically what a device
+ * driver would do in the attach routine.
+ */
+ error = ng_make_node_common(&typestruct, &node);
+ if (node == NULL) {
+ printf ("node recreation failed:");
+ return (error);
+ }
+ if ( ng_name_node(node, "name")) { /* whatever name is needed */
+ printf("something informative");
+ ng_unref(node); /* drop it again */
+ return (0);
+ }
privdata->packets_in = 0; /* reset stats */
privdata->packets_out = 0;
+ for (i = 0; i < XXX_NUM_DLCIS; i++) {
+ privdata->channel[i].dlci = -2;
+ privdata->channel[i].channel = i;
+ }
+
+ /* Link structs together; this counts as our one reference to node */
+ privdata->node = node;
+ node->private = privdata;
node->flags &= ~NG_INVALID; /* reset invalid flag */
#endif /* PERSISTANT_NODE */
return (0);
@@ -470,8 +493,9 @@ ng_xxx_disconnect(hook_p hook)
{
if (hook->private)
((struct XXX_hookinfo *) (hook->private))->hook = NULL;
- if (hook->node->numhooks == 0)
- ng_rmnode(hook->node);
+ if ((hook->node->numhooks == 0)
+ && ((hook->node->flags & NG_INVALID) == 0)) /* already shutting down? */
+ ng_rmnode_self(hook->node);
return (0);
}
OpenPOWER on IntegriCloud