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
This commit is contained in:
parent
e4b50334ec
commit
f8aab721b2
@ -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
|
||||
|
@ -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 ,
|
||||
|
@ -84,7 +84,7 @@
|
||||
#include <netgraph/ng_bridge.h>
|
||||
|
||||
#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
|
||||
@ -106,6 +106,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;
|
||||
@ -271,6 +272,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 }
|
||||
};
|
||||
|
||||
@ -495,6 +503,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;
|
||||
@ -800,7 +813,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);
|
||||
|
@ -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_ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user