mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
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)
This commit is contained in:
parent
16241a05dd
commit
c4b5eea4e2
3 changed files with 112 additions and 32 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
/* item is now invalid */
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
error = (*rcvmsg)(node, item, hook);
|
||||
}
|
||||
break;
|
||||
case NGQF_FN:
|
||||
|
|
|
|||
Loading…
Reference in a new issue