diff options
author | zec <zec@FreeBSD.org> | 2010-05-05 22:06:05 +0000 |
---|---|---|
committer | zec <zec@FreeBSD.org> | 2010-05-05 22:06:05 +0000 |
commit | fc65bde07d9854848d689e2c1fefa55448b3880a (patch) | |
tree | a12bc1a8023da35bc5ab9ba5c3811bbb1dcca19d /sys/netgraph/ng_hub.c | |
parent | f3856c6cf2fb115757967b7e32bdeb21bd27d1ee (diff) | |
download | FreeBSD-src-fc65bde07d9854848d689e2c1fefa55448b3880a.zip FreeBSD-src-fc65bde07d9854848d689e2c1fefa55448b3880a.tar.gz |
Add an optional "persistent" flag to ng_hub and ng_bridge, which if set,
disables automatic node shutdown when the last hook gets disconnected.
Reviewed by: julian
Diffstat (limited to 'sys/netgraph/ng_hub.c')
-rw-r--r-- | sys/netgraph/ng_hub.c | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/sys/netgraph/ng_hub.c b/sys/netgraph/ng_hub.c index ba298e5..0770745 100644 --- a/sys/netgraph/ng_hub.c +++ b/sys/netgraph/ng_hub.c @@ -36,16 +36,46 @@ #include <netgraph/ng_hub.h> #include <netgraph/netgraph.h> +#ifdef NG_SEPARATE_MALLOC +MALLOC_DEFINE(M_NETGRAPH_HUB, "netgraph_hub", "netgraph hub node"); +#else +#define M_NETGRAPH_HUB M_NETGRAPH +#endif + +/* Per-node private data */ +struct ng_hub_private { + int persistent; /* can exist w/o hooks */ +}; +typedef struct ng_hub_private *priv_p; + +/* Netgraph node methods */ static ng_constructor_t ng_hub_constructor; +static ng_rcvmsg_t ng_hub_rcvmsg; +static ng_shutdown_t ng_hub_shutdown; static ng_rcvdata_t ng_hub_rcvdata; static ng_disconnect_t ng_hub_disconnect; +/* List of commands and how to convert arguments to/from ASCII */ +static const struct ng_cmdlist ng_hub_cmdlist[] = { + { + NGM_HUB_COOKIE, + NGM_HUB_SET_PERSISTENT, + "setpersistent", + NULL, + NULL + }, + { 0 } +}; + static struct ng_type ng_hub_typestruct = { .version = NG_ABI_VERSION, .name = NG_HUB_NODE_TYPE, .constructor = ng_hub_constructor, + .rcvmsg = ng_hub_rcvmsg, + .shutdown = ng_hub_shutdown, .rcvdata = ng_hub_rcvdata, .disconnect = ng_hub_disconnect, + .cmdlist = ng_hub_cmdlist, }; NETGRAPH_INIT(hub, &ng_hub_typestruct); @@ -53,10 +83,39 @@ NETGRAPH_INIT(hub, &ng_hub_typestruct); static int ng_hub_constructor(node_p node) { + priv_p priv; + + /* Allocate and initialize private info */ + priv = malloc(sizeof(*priv), M_NETGRAPH_HUB, M_NOWAIT | M_ZERO); + if (priv == NULL) + return (ENOMEM); + NG_NODE_SET_PRIVATE(node, priv); return (0); } +/* + * Receive a control message + */ +static int +ng_hub_rcvmsg(node_p node, item_p item, hook_p lasthook) +{ + const priv_p priv = NG_NODE_PRIVATE(node); + int error = 0; + struct ng_mesg *msg; + + NGI_GET_MSG(item, msg); + if (msg->header.typecookie == NGM_HUB_COOKIE && + msg->header.cmd == NGM_HUB_SET_PERSISTENT) { + priv->persistent = 1; + } else { + error = EINVAL; + } + + NG_FREE_MSG(msg); + return (error); +} + static int ng_hub_rcvdata(hook_p hook, item_p item) { @@ -89,12 +148,25 @@ ng_hub_rcvdata(hook_p hook, item_p item) return (error); } +/* + * Shutdown node + */ +static int +ng_hub_shutdown(node_p node) +{ + const priv_p priv = NG_NODE_PRIVATE(node); + + free(priv, M_NETGRAPH_HUB); + return (0); +} + static int ng_hub_disconnect(hook_p hook) { + const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); if (NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0 && - NG_NODE_IS_VALID(NG_HOOK_NODE(hook))) + NG_NODE_IS_VALID(NG_HOOK_NODE(hook)) && !priv->persistent) ng_rmnode_self(NG_HOOK_NODE(hook)); return (0); } |