summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>2001-01-31 20:46:00 +0000
committerjulian <julian@FreeBSD.org>2001-01-31 20:46:00 +0000
commitd9ff7e1523af98d6d0fa4183f279fd6fa15ddfe8 (patch)
treed1ecad86a28ed4a79630ad373a615d5b86bef163
parent1904591561496046db76a7fed4aeeca690042d13 (diff)
downloadFreeBSD-src-d9ff7e1523af98d6d0fa4183f279fd6fa15ddfe8.zip
FreeBSD-src-d9ff7e1523af98d6d0fa4183f279fd6fa15ddfe8.tar.gz
Add the ability to declare ore-ride methods on a per-hook basis
for the rcvdata() and rcvmsg() methods. Also bring the man page up to sync with my last commit. (and this one)
-rw-r--r--share/man/man4/netgraph.448
-rw-r--r--sys/netgraph/netgraph.h49
-rw-r--r--sys/netgraph/ng_base.c47
3 files changed, 112 insertions, 32 deletions
diff --git a/share/man/man4/netgraph.4 b/share/man/man4/netgraph.4
index d191408..0414b11 100644
--- a/share/man/man4/netgraph.4
+++ b/share/man/man4/netgraph.4
@@ -143,6 +143,10 @@ A hook can be set into a state where incoming packets are always queued
by the input queuing system, rather than being delivered directly. This
is used when the two joined nodes need to be decoupled, e.g. if they are
running at different processor priority levels. (spl)
+.It
+A hook may supply over-riding receive data and receive message functions
+which should be used for data and messages received through that hook
+in preference to the general node-wide methods.
.El
.Pp
A node may decide to assign special meaning to some hooks.
@@ -341,21 +345,27 @@ may effect a total shutdown for the node.
.It Shutdown of a node
This method allows a node to clean up
and to ensure that any actions that need to be performed
-at this time are taken. The method must call the generic (i.e., superclass)
-node destructor to get rid of the generic components of the node.
+at this time are taken. The method is called by the generic (i.e., superclass)
+node destructor which will get rid of the generic components of the node.
Some nodes (usually associated with a piece of hardware) may be
.Em persistent
in that a shutdown breaks all edges and resets the node,
-but doesn't remove it, in which case the generic destructor is not called.
+but doesn't remove it. In this case the shutdown method should not
+free it's resources, but rather, clean up and then clear the
+.Em NG_INVALID
+flag to signal the generic code that the shutdown is aborted. In
+the case where the shutdown is started by the node itself due to hardware
+removal or unloading, (via ng_rmnode_self()) it should set the
+.Em NG_REALLY_DIE
+flag to signal to it's own shutdown method that it is not to persist.
.El
.Sh Sending and Receiving Data
Two other methods are also supported by all nodes:
.Bl -tag -width xxx
.It Receive data message
A
-.Em Netgraph queueable reqest item
-(usually refered to as an
-.Em item
+.Em Netgraph queueable reqest item ,usually refered to as an
+.Em item ,
is recieved by the function.
The item contains a pointer to an mbuf and metadata about the packet.
.Pp
@@ -427,6 +437,13 @@ presently used in frame-relay to indicate that management packets
should be queued for transmission
at a higher priority than data packets. This is required for
conformance with Frame Relay standards.
+.Pp
+The node may elect to nominate a different receive data function
+for data received on a particular hook, to simplify coding. It uses
+the
+.Fn NG_HOOK_SET_RCVDATA "hook, fn"
+macro to do this. The function receives the same arguments in every way
+other than it will receive all (and only) packets from that hook.
.It Receive control message
This method is called when a control message is addressed to the node.
As with the received data, an
@@ -470,6 +487,13 @@ If the message was delivered via a specific hook, that hook will
also be made known, which allows the use of such things as flow-control
messages, and status change messages, where the node may want to forward
the message out another hook to that on which it arrived.
+.Pp
+The node may elect to nominate a different receive message function
+for messages received on a particular hook, to simplify coding. It uses
+the
+.Fn NG_HOOK_SET_RCVMSG "hook, fn"
+macro to do this. The function receives the same arguments in every way
+other than it will receive all (and only) messages from that hook.
.El
.Pp
Much use has been made of reference counts, so that nodes being
@@ -732,6 +756,18 @@ and
increment and decrement the hook reference count accordingly.
After decrement you should always assume the hook has been freed
unless you have another reference still valid.
+.Pp
+.It
+Over-ride receive functions.
+.Pp
+The
+.Fn NG_HOOK_SET_RCVDATA "hook, fn"
+and
+.Fn NG_HOOK_SET_RCVMSG "hook, fn"
+macros can be used to set over-ride methods that will be used in preference
+to the generic receive data and reveive message functions. To unset these
+use the macros to set them to NULL. They will only be used for data and
+messages received on the hook on which they are set.
.El
.Pp
The maintenance of the names, reference counts, and linked list
diff --git a/sys/netgraph/netgraph.h b/sys/netgraph/netgraph.h
index 78f095a..c3c93eb 100644
--- a/sys/netgraph/netgraph.h
+++ b/sys/netgraph/netgraph.h
@@ -80,6 +80,17 @@ typedef struct ng_item *item_p;
typedef struct ng_node *node_p;
typedef struct ng_hook *hook_p;
+/* node method definitions */
+typedef int ng_constructor_t(node_p node);
+typedef int ng_shutdown_t(node_p node);
+typedef int ng_newhook_t(node_p node, hook_p hook, const char *name);
+typedef hook_p ng_findhook_t(node_p node, const char *name);
+typedef int ng_connect_t(hook_p hook);
+typedef int ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook);
+typedef int ng_rcvdata_t(hook_p hook, item_p item);
+typedef int ng_disconnect_t(hook_p hook);
+typedef int ng_rcvitem (node_p node, hook_p hook, item_p item);
+
/***********************************************************************
***************** Hook Structure and Methods **************************
***********************************************************************
@@ -94,6 +105,8 @@ struct ng_hook {
struct ng_hook *hk_peer; /* the other end of this link */
struct ng_node *hk_node; /* The node this hook is attached to */
LIST_ENTRY(ng_hook) hk_hooks; /* linked list of all hooks on node */
+ ng_rcvmsg_t *hk_rcvmsg; /* control messages come here */
+ ng_rcvdata_t *hk_rcvdata; /* data comes here */
#ifdef NETGRAPH_DEBUG /*----------------------------------------------*/
#define HK_MAGIC 0x78573011
int hk_magic;
@@ -117,6 +130,8 @@ void ng_unref_hook(hook_p hook); /* don't move this */
#define _NG_HOOK_NAME(hook) ((hook)->hk_name)
#define _NG_HOOK_UNREF(hook) ng_unref_hook(hook)
#define _NG_HOOK_SET_PRIVATE(hook, val) do {(hook)->hk_private = val;} while (0)
+#define _NG_HOOK_SET_RCVMSG(hook, val) do {(hook)->hk_rcvmsg = val;} while (0)
+#define _NG_HOOK_SET_RCVDATA(hook, val) do {(hook)->hk_rcvdata = val;} while (0)
#define _NG_HOOK_PRIVATE(hook) ((hook)->hk_private)
#define _NG_HOOK_NOT_VALID(hook) ((hook)->hk_flags & HK_INVALID)
#define _NG_HOOK_IS_VALID(hook) (!(hook)->hk_flags & HK_INVALID)
@@ -139,7 +154,11 @@ static __inline void _ng_hook_ref(hook_p hook, char * file, int line);
static __inline char * _ng_hook_name(hook_p hook, char * file, int line);
static __inline void _ng_hook_unref(hook_p hook, char * file, int line);
static __inline void _ng_hook_set_private(hook_p hook,
- void * val, char * file, int line);
+ void * val, char * file, int line);
+static __inline void _ng_hook_set_rcvmsg(hook_p hook,
+ ng_rcvmsg_t *val, char * file, int line);
+static __inline void _ng_hook_set_rcvdata(hook_p hook,
+ ng_rcvdata_t *val, char * file, int line);
static __inline void * _ng_hook_private(hook_p hook, char * file, int line);
static __inline int _ng_hook_not_valid(hook_p hook, char * file, int line);
static __inline int _ng_hook_is_valid(hook_p hook, char * file, int line);
@@ -188,6 +207,20 @@ _ng_hook_set_private(hook_p hook, void *val, char * file, int line)
_NG_HOOK_SET_PRIVATE(hook, val);
}
+static __inline void
+_ng_hook_set_rcvmsg(hook_p hook, ng_rcvmsg_t *val, char * file, int line)
+{
+ _chkhook(hook, file, line);
+ _NG_HOOK_SET_RCVMSG(hook, val);
+}
+
+static __inline void
+_ng_hook_set_rcvdata(hook_p hook, ng_rcvdata_t *val, char * file, int line)
+{
+ _chkhook(hook, file, line);
+ _NG_HOOK_SET_RCVDATA(hook, val);
+}
+
static __inline void *
_ng_hook_private(hook_p hook, char * file, int line)
{
@@ -242,6 +275,8 @@ _ng_hook_force_queue(hook_p hook, char * file, int line)
#define NG_HOOK_NAME(hook) _ng_hook_name(hook, _NN_)
#define NG_HOOK_UNREF(hook) _ng_hook_unref(hook, _NN_)
#define NG_HOOK_SET_PRIVATE(hook, val) _ng_hook_set_private(hook, val, _NN_)
+#define NG_HOOK_SET_RCVMSG(hook, val) _ng_hook_set_rcvmsg(hook, val, _NN_)
+#define NG_HOOK_SET_RCVDATA(hook, val) _ng_hook_set_rcvdata(hook, val, _NN_)
#define NG_HOOK_PRIVATE(hook) _ng_hook_private(hook, _NN_)
#define NG_HOOK_NOT_VALID(hook) _ng_hook_not_valid(hook, _NN_)
#define NG_HOOK_IS_VALID(hook) _ng_hook_is_valid(hook, _NN_)
@@ -256,6 +291,8 @@ _ng_hook_force_queue(hook_p hook, char * file, int line)
#define NG_HOOK_NAME(hook) _NG_HOOK_NAME(hook)
#define NG_HOOK_UNREF(hook) _NG_HOOK_UNREF(hook)
#define NG_HOOK_SET_PRIVATE(hook, val) _NG_HOOK_SET_PRIVATE(hook, val)
+#define NG_HOOK_SET_RCVMSG(hook, val) _NG_HOOK_SET_RCVMSG(hook, val)
+#define NG_HOOK_SET_RCVDATA(hook, val) _NG_HOOK_SET_RCVDATA(hook, val)
#define NG_HOOK_PRIVATE(hook) _NG_HOOK_PRIVATE(hook)
#define NG_HOOK_NOT_VALID(hook) _NG_HOOK_NOT_VALID(hook)
#define NG_HOOK_IS_VALID(hook) _NG_HOOK_IS_VALID(hook)
@@ -1007,16 +1044,6 @@ _ngi_hook(item_p item, char *file, int line)
* type.
*/
-/* node method definitions */
-typedef int ng_constructor_t(node_p node);
-typedef int ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook);
-typedef int ng_shutdown_t(node_p node);
-typedef int ng_newhook_t(node_p node, hook_p hook, const char *name);
-typedef hook_p ng_findhook_t(node_p node, const char *name);
-typedef int ng_connect_t(hook_p hook);
-typedef int ng_rcvdata_t(hook_p hook, item_p item);
-typedef int ng_disconnect_t(hook_p hook);
-typedef int ng_rcvitem (node_p node, hook_p hook, item_p item);
/*
* Command list -- each node type specifies the command that it knows
* how to convert between ASCII and binary using an array of these.
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c
index d5c456f..3e4e174 100644
--- a/sys/netgraph/ng_base.c
+++ b/sys/netgraph/ng_base.c
@@ -136,6 +136,8 @@ struct ng_hook ng_deadhook = {
&ng_deadhook, /* Peer is self */
&ng_deadnode, /* attached to deadnode */
{}, /* hooks list */
+ NULL, /* override rcvmsg() */
+ NULL, /* override rcvdata() */
#ifdef NETGRAPH_DEBUG
HK_MAGIC,
__FILE__,
@@ -2298,6 +2300,7 @@ ng_apply_item(item_p item)
int was_reader = ((item->el_flags & NGQF_RW));
int error = 0;
ng_rcvdata_t *rcvdata;
+ ng_rcvmsg_t *rcvmsg;
NGI_GET_HOOK(item, hook); /* clears stored hook */
NGI_GET_NODE(item, node); /* clears stored node */
@@ -2309,16 +2312,24 @@ ng_apply_item(item_p item)
/*
* Check things are still ok as when we were queued.
*/
-
if ((hook == NULL)
|| NG_HOOK_NOT_VALID(hook)
- || NG_NODE_NOT_VALID(node)
- || ((rcvdata = NG_HOOK_NODE(hook)->nd_type->rcvdata) == NULL)) {
+ || NG_NODE_NOT_VALID(node) ) {
error = EIO;
NG_FREE_ITEM(item);
- } else {
- error = (*rcvdata)(hook, item);
+ break;
}
+ /*
+ * If no receive method, just silently drop it.
+ * Give preference to the hook over-ride method
+ */
+ if ((!(rcvdata = hook->hk_rcvdata))
+ && (!(rcvdata = NG_HOOK_NODE(hook)->nd_type->rcvdata))) {
+ error = 0;
+ NG_FREE_ITEM(item);
+ break;
+ }
+ error = (*rcvdata)(hook, item);
break;
case NGQF_MESG:
if (hook) {
@@ -2355,20 +2366,26 @@ ng_apply_item(item_p item)
struct ng_mesg *msg = NGI_MSG(item);
+ /*
+ * check if the generic handler owns it.
+ */
if ((msg->header.typecookie == NGM_GENERIC_COOKIE)
&& ((msg->header.flags & NGF_RESP) == 0)) {
error = ng_generic_msg(node, item, hook);
- } else {
- if ((node)->nd_type->rcvmsg != NULL) {
- error = (*(node)->nd_type->rcvmsg)((node),
- (item), (hook));
- } else {
- TRAP_ERROR();
- error = EINVAL; /* XXX */
- NG_FREE_ITEM(item);
- }
+ break;
+ }
+ /*
+ * Now see if there is a handler (hook or node specific)
+ * in the target node. If none, silently discard.
+ */
+ if (((!hook) || (!(rcvmsg = hook->hk_rcvmsg)))
+ && (!(rcvmsg = node->nd_type->rcvmsg))) {
+ TRAP_ERROR();
+ error = 0;
+ NG_FREE_ITEM(item);
+ break;
}
- /* item is now invalid */
+ error = (*rcvmsg)(node, item, hook);
}
break;
case NGQF_FN:
OpenPOWER on IntegriCloud