From c779c4cdfde6c60be24c795ccab20cb548f9ab2b Mon Sep 17 00:00:00 2001 From: zec Date: Sun, 16 May 2010 14:51:36 +0000 Subject: MFC r207680: 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 --- share/man/man4/ng_bridge.4 | 10 +++++-- share/man/man4/ng_hub.4 | 15 ++++++++-- sys/netgraph/ng_bridge.c | 18 +++++++++-- sys/netgraph/ng_bridge.h | 1 + sys/netgraph/ng_hub.c | 74 +++++++++++++++++++++++++++++++++++++++++++++- sys/netgraph/ng_hub.h | 5 ++++ 6 files changed, 115 insertions(+), 8 deletions(-) diff --git a/share/man/man4/ng_bridge.4 b/share/man/man4/ng_bridge.4 index 3b1dd71..8884e33 100644 --- a/share/man/man4/ng_bridge.4 +++ b/share/man/man4/ng_bridge.4 @@ -34,7 +34,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 31, 2000 +.Dd May 5, 2010 .Dt NG_BRIDGE 4 .Os .Sh NAME @@ -181,11 +181,17 @@ but also atomically clears the statistics as well. .It Dv NGM_BRIDGE_GET_TABLE Returns the current host mapping table used to direct packets, in a .Dv "struct ng_bridge_host_ary" . +.It Dv NGM_BRIDGE_SET_PERSISTENT +This command sets the persistent flag on the node, and takes no arguments. .El .Sh SHUTDOWN This node shuts down upon receipt of a .Dv NGM_SHUTDOWN -control message, or when all hooks have been disconnected. +control message, or when all hooks have been disconnected. Setting the +persistent flag via a +.Dv NGM_BRIDGE_SET_PERSISTENT +control message disables automatic node shutdown when the last hook gets +disconnected. .Sh FILES .Bl -tag -width XXXXXXXX -compact .It Pa /usr/share/examples/netgraph/ether.bridge diff --git a/share/man/man4/ng_hub.4 b/share/man/man4/ng_hub.4 index a1ad068..c52aba0 100644 --- a/share/man/man4/ng_hub.4 +++ b/share/man/man4/ng_hub.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 17, 2004 +.Dd May 5, 2010 .Dt NG_HUB 4 .Os .Sh NAME @@ -45,11 +45,20 @@ 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. +This node type supports the generic control messages, plus the +following: +.Bl -tag -width foo +.It Dv NGM_HUB_SET_PERSISTENT +This command sets the persistent flag on the node, and takes no arguments. +.El .Sh SHUTDOWN This node shuts down upon receipt of a .Dv NGM_SHUTDOWN -control message, or when all hooks have been disconnected. +control message, or when all hooks have been disconnected. Setting the +persistent flag via a +.Dv NGM_HUB_SET_PERSISTENT +control message disables automatic node shutdown when the last hook gets +disconnected. .Sh SEE ALSO .Xr netgraph 4 , .Xr ng_bridge 4 , diff --git a/sys/netgraph/ng_bridge.c b/sys/netgraph/ng_bridge.c index c6f4183..e28e034 100644 --- a/sys/netgraph/ng_bridge.c +++ b/sys/netgraph/ng_bridge.c @@ -83,7 +83,7 @@ #include #ifdef NG_SEPARATE_MALLOC -MALLOC_DEFINE(M_NETGRAPH_BRIDGE, "netgraph_bridge", "netgraph bridge node "); +MALLOC_DEFINE(M_NETGRAPH_BRIDGE, "netgraph_bridge", "netgraph bridge node"); #else #define M_NETGRAPH_BRIDGE M_NETGRAPH #endif @@ -105,6 +105,7 @@ struct ng_bridge_private { u_int numBuckets; /* num buckets in table */ u_int hashMask; /* numBuckets - 1 */ int numLinks; /* num connected links */ + int persistent; /* can exist w/o hooks */ struct callout timer; /* one second periodic timer */ }; typedef struct ng_bridge_private *priv_p; @@ -270,6 +271,13 @@ static const struct ng_cmdlist ng_bridge_cmdlist[] = { NULL, &ng_bridge_host_ary_type }, + { + NGM_BRIDGE_COOKIE, + NGM_BRIDGE_SET_PERSISTENT, + "setpersistent", + NULL, + NULL + }, { 0 } }; @@ -494,6 +502,11 @@ ng_bridge_rcvmsg(node_p node, item_p item, hook_p lasthook) } break; } + case NGM_BRIDGE_SET_PERSISTENT: + { + priv->persistent = 1; + break; + } default: error = EINVAL; break; @@ -799,7 +812,8 @@ ng_bridge_disconnect(hook_p hook) /* If no more hooks, go away */ 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); diff --git a/sys/netgraph/ng_bridge.h b/sys/netgraph/ng_bridge.h index 0524a96..c34d27d 100644 --- a/sys/netgraph/ng_bridge.h +++ b/sys/netgraph/ng_bridge.h @@ -149,6 +149,7 @@ enum { NGM_BRIDGE_CLR_STATS, /* clear link stats */ NGM_BRIDGE_GETCLR_STATS, /* atomically get & clear link stats */ NGM_BRIDGE_GET_TABLE, /* get link table */ + NGM_BRIDGE_SET_PERSISTENT, /* set persistent mode */ }; #endif /* _NETGRAPH_NG_BRIDGE_H_ */ 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 #include +#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); } diff --git a/sys/netgraph/ng_hub.h b/sys/netgraph/ng_hub.h index a735d7b..d6b16e0 100644 --- a/sys/netgraph/ng_hub.h +++ b/sys/netgraph/ng_hub.h @@ -33,4 +33,9 @@ #define NG_HUB_NODE_TYPE "hub" #define NGM_HUB_COOKIE 1082189597 +/* Netgraph control messages */ +enum { + NGM_HUB_SET_PERSISTENT = 1, /* set persistent mode */ +}; + #endif /* _NETGRAPH_NG_HUB_H_ */ -- cgit v1.1