New netgraph node type ng_one2many(4).

This commit is contained in:
Archie Cobbs 2000-11-16 05:58:33 +00:00
parent c3427a5cc8
commit 6e8d625628
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=68810
5 changed files with 849 additions and 0 deletions

View File

@ -90,6 +90,7 @@ MAN4= aac.4 \
ng_ksocket.4 \
ng_lmi.4 \
ng_mppc.4 \
ng_one2many.4 \
ng_ppp.4 \
ng_pppoe.4 \
ng_pptpgre.4 \

View File

@ -0,0 +1,208 @@
.\" Copyright (c) 2000 Whistle Communications, Inc.
.\" All rights reserved.
.\"
.\" Subject to the following obligations and disclaimer of warranty, use and
.\" redistribution of this software, in source or object code forms, with or
.\" without modifications are expressly permitted by Whistle Communications;
.\" provided, however, that:
.\" 1. Any and all reproductions of the source or object code must include the
.\" copyright notice above and the following disclaimer of warranties; and
.\" 2. No rights are granted, in any manner or form, to use Whistle
.\" Communications, Inc. trademarks, including the mark "WHISTLE
.\" COMMUNICATIONS" on advertising, endorsements, or otherwise except as
.\" such appears in the above copyright notice or in the software.
.\"
.\" THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
.\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
.\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
.\" INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
.\" WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
.\" REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
.\" SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
.\" IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
.\" RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
.\" WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
.\" PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
.\" OF SUCH DAMAGE.
.\"
.\" Author: Archie Cobbs <archie@freebsd.org>
.\"
.\" $FreeBSD$
.\"
.Dd November 15, 2000
.Dt NG_ONE2MANY 4
.Os FreeBSD
.Sh NAME
.Nm ng_one2many
.Nd packet multiplexing netgraph node type
.Sh SYNOPSIS
.Fd #include <netgraph/ng_one2many.h>
.Sh DESCRIPTION
The
.Nm one2many
provides a simple mechanism for routing packets over several links
in a one-to-many (and in the reverse direction, many-to-one) fashion.
There is a single hook named
.Dv one ,
and multiple hooks named
.Dv many0 ,
.Dv many1 ,
etc.
Packets received on any of the
.Dv many
hooks are forwarded out the
.Dv one
hook.
Packets received on the
.Dv one
hook are forwarded out one of the
.Dv many
hooks; which hook is determined by the node's configured
transmit algorithm.
Packets are not altered in any way.
.Pp
Each of the connected many links may be considered to be up or down.
Packets are never delivered out a many hook that is down.
How a link is determined to be up or down depends on the node's
configured link failure detection algorithm.
.Sh TRANSMIT ALGORITHMS
At this time, the only algorithm for determing the outgoing
.Dv many
hook is a simple round-robin delivery algorithm.
Packets are delivered out the many hooks in sequential order.
.Pp
In the future other algorithms may be added as well.
.Sh LINK FAILURE DETECTION
At this time, the only algorithm for determining when a link
has failed, other than the hook being disconnected, is the
``manual'' algorithm: the node is explicitly told which of
the links are up via the
.Dv NGM_ONE2MANY_SET_CONFIG
control message (see below).
Newly connected links are down until configured otherwise.
.Pp
In the future other algorithms may be added as well.
.Sh HOOKS
This node type supports up to
.Dv NG_ONE2MANY_MAX_LINKS
hooks named
.Dv many0 ,
.Dv many1 ,
etc.,
plus a single hook named
.Dv one .
.Sh CONTROL MESSAGES
This node type supports the generic control messages, plus the
following:
.Bl -tag -width foo
.It Dv NGM_ONE2MANY_SET_CONFIG
Sets the node configuration using a
.Dv "struct ng_one2many_link_config"
as the control message argument:
.Bd -literal -offset 0
/* Node configuration structure */
struct ng_one2many_config {
u_int32_t xmitAlg; /* how to distribute packets */
u_int32_t failAlg; /* how to detect link failure */
u_char enabledLinks[NG_ONE2MANY_MAX_LINKS];
};
.Ed
.Pp
Currently, the only valid setting for the
.Dv xmitAlg
field is
.Dv NG_ONE2MANY_XMIT_ROUNDROBIN ;
this is also the default setting.
The only valid setting for
.Dv failAlg
is
.Dv NG_ONE2MANY_FAIL_MANUAL ;
this is also the default setting.
.It Dv NGM_ONE2MANY_GET_CONFIG
Returns the current node configuration in a
.Dv "struct ng_one2many_link_config" .
.It Dv NGM_ONE2MANY_GET_STATS
This command takes a 32 bit link number as an argument and
returns a
.Dv "struct ng_one2many_link_stats"
containing statistics for the corresponding
.Dv many
link, which may or may not be currently connected:
.Bd -literal -offset 0
/* Statistics structure (one for each link) */
struct ng_one2many_link_stats {
u_int64_t recvOctets; /* total octets rec'd on link */
u_int64_t recvPackets; /* total pkts rec'd on link */
u_int64_t xmitOctets; /* total octets xmit'd on link */
u_int64_t xmitPackets; /* total pkts xmit'd on link */
};
.Ed
.Pp
To access statistics for the
.Dv one
link, use the link number
.Dv -1 .
.It Dv NGM_ONE2MANY_CLR_STATS
This command takes a 32 bit link number as an argument and
clears the statistics for that link.
.It Dv NGM_ONE2MANY_GETCLR_STATS
Same as
.Dv NGM_ONE2MANY_GET_STATS ,
but also atomically clears the statistics for the link as well.
.Sh SHUTDOWN
This node shuts down upon receipt of a
.Dv NGM_SHUTDOWN
control message, or when all hooks have been disconnected.
.Sh EXAMPLE
The following commands will set up Ethernet interfaces
.Dv fxp0
to deliver packets alternating over the physical interfaces
corresponding to networking interfaces
.Dv fxp0
through
.Dv fxp3 :
.Bd -literal -offset 0
# Plumb nodes together
ngctl mkpeer fxp0: ng_one2many upper one
ngctl connect fxp0: fxp0:upper lower many0
ngctl connect fxp1: fxp0:upper lower many1
ngctl connect fxp2: fxp0:upper lower many2
ngctl connect fxp3: fxp0:upper lower many3
# Allow fxp1 through fxp3 to xmit/recv fxp0 frames
ngctl msg fxp1: setpromisc 1
ngctl msg fxp3: setpromisc 1
ngctl msg fxp2: setpromisc 1
ngctl msg fxp1: setautosrc 0
ngctl msg fxp3: setautosrc 0
ngctl msg fxp2: setautosrc 0
# Configure all four links as up
ngctl msg fxp0:upper \\
setconfig "{ xmitAlg=1 failAlg=1 enabledLinks={ 1 1 1 1 } }"
# Bring up interface
ifconfig fxp0 192.168.1.1 netmask 0xfffffffc
.Ed
.Pp
With a similar setup on a peer machine (using the address
192.168.1.2), a point-to-point
Ethernet connection with four times normal bandwidth is
achieved.
.Sh BUGS
More transmit and link failure algorithms should be supported.
A good candidate is Cisco's Etherchannel.
.Sh SEE ALSO
.Xr netgraph 4 ,
.Xr ng_bridge 4 ,
.Xr ng_ether 4 ,
.Xr ngctl 8
.Sh HISTORY
The
.Nm
node type was implemented in
.Fx 4.2 .
.Sh AUTHORS
.An Archie Cobbs Aq archie@freebsd.org

View File

@ -0,0 +1,7 @@
# $FreeBSD$
KMOD= ng_one2many
SRCS= ng_one2many.c
NOMAN=
.include <bsd.kmod.mk>

521
sys/netgraph/ng_one2many.c Normal file
View File

@ -0,0 +1,521 @@
/*
* ng_one2many.c
*
* Copyright (c) 2000 Whistle Communications, Inc.
* All rights reserved.
*
* Subject to the following obligations and disclaimer of warranty, use and
* redistribution of this software, in source or object code forms, with or
* without modifications are expressly permitted by Whistle Communications;
* provided, however, that:
* 1. Any and all reproductions of the source or object code must include the
* copyright notice above and the following disclaimer of warranties; and
* 2. No rights are granted, in any manner or form, to use Whistle
* Communications, Inc. trademarks, including the mark "WHISTLE
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
* such appears in the above copyright notice or in the software.
*
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Archie Cobbs <archie@freebsd.org>
*
* $FreeBSD$
*/
/*
* ng_one2many(4) netgraph node type
*
* Packets received on the "one" hook are sent out each of the
* "many" hooks in round-robin fashion. Packets received on any
* "many" hook are always delivered to the "one" hook.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/ctype.h>
#include <sys/mbuf.h>
#include <sys/errno.h>
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
#include <netgraph/ng_parse.h>
#include <netgraph/ng_one2many.h>
/* Per-link private data */
struct ng_one2many_link {
hook_p hook; /* netgraph hook */
struct ng_one2many_link_stats stats; /* link stats */
};
/* Per-node private data */
struct ng_one2many_private {
struct ng_one2many_config conf; /* node configuration */
struct ng_one2many_link one; /* "one" hook */
struct ng_one2many_link many[NG_ONE2MANY_MAX_LINKS];
u_int16_t nextMany; /* next round-robin */
u_int16_t numActiveMany; /* # active "many" */
u_int16_t activeMany[NG_ONE2MANY_MAX_LINKS];
};
typedef struct ng_one2many_private *priv_p;
/* Netgraph node methods */
static ng_constructor_t ng_one2many_constructor;
static ng_rcvmsg_t ng_one2many_rcvmsg;
static ng_shutdown_t ng_one2many_rmnode;
static ng_newhook_t ng_one2many_newhook;
static ng_rcvdata_t ng_one2many_rcvdata;
static ng_disconnect_t ng_one2many_disconnect;
/* Other functions */
static void ng_one2many_update_many(priv_p priv);
/* Store each hook's link number in the private field */
#define LINK_NUM(hook) (*(int16_t *)(&(hook)->private))
/******************************************************************
NETGRAPH PARSE TYPES
******************************************************************/
/* Parse type for struct ng_one2many_config */
static const struct ng_parse_fixedarray_info
ng_one2many_enableLinks_array_type_info = {
&ng_parse_uint8_type,
NG_ONE2MANY_MAX_LINKS
};
static const struct ng_parse_type ng_one2many_enableLinks_array_type = {
&ng_parse_fixedarray_type,
&ng_one2many_enableLinks_array_type_info,
};
static const struct ng_parse_struct_info ng_one2many_config_type_info
= NG_ONE2MANY_CONFIG_TYPE_INFO(&ng_one2many_enableLinks_array_type);
static const struct ng_parse_type ng_one2many_config_type = {
&ng_parse_struct_type,
&ng_one2many_config_type_info,
};
/* Parse type for struct ng_one2many_link_stats */
static const struct ng_parse_struct_info
ng_one2many_link_stats_type_info = NG_ONE2MANY_LINK_STATS_TYPE_INFO;
static const struct ng_parse_type ng_one2many_link_stats_type = {
&ng_parse_struct_type,
&ng_one2many_link_stats_type_info
};
/* List of commands and how to convert arguments to/from ASCII */
static const struct ng_cmdlist ng_one2many_cmdlist[] = {
{
NGM_ONE2MANY_COOKIE,
NGM_ONE2MANY_SET_CONFIG,
"setconfig",
&ng_one2many_config_type,
NULL
},
{
NGM_ONE2MANY_COOKIE,
NGM_ONE2MANY_GET_CONFIG,
"getconfig",
NULL,
&ng_one2many_config_type
},
{
NGM_ONE2MANY_COOKIE,
NGM_ONE2MANY_GET_STATS,
"getstats",
&ng_parse_int32_type,
&ng_one2many_link_stats_type
},
{
NGM_ONE2MANY_COOKIE,
NGM_ONE2MANY_CLR_STATS,
"clrstats",
&ng_parse_int32_type,
NULL,
},
{
NGM_ONE2MANY_COOKIE,
NGM_ONE2MANY_GETCLR_STATS,
"getclrstats",
&ng_parse_int32_type,
&ng_one2many_link_stats_type
},
{ 0 }
};
/* Node type descriptor */
static struct ng_type ng_one2many_typestruct = {
NG_VERSION,
NG_ONE2MANY_NODE_TYPE,
NULL,
ng_one2many_constructor,
ng_one2many_rcvmsg,
ng_one2many_rmnode,
ng_one2many_newhook,
NULL,
NULL,
ng_one2many_rcvdata,
ng_one2many_rcvdata,
ng_one2many_disconnect,
ng_one2many_cmdlist,
};
NETGRAPH_INIT(one2many, &ng_one2many_typestruct);
/******************************************************************
NETGRAPH NODE METHODS
******************************************************************/
/*
* Node constructor
*/
static int
ng_one2many_constructor(node_p *nodep)
{
priv_p priv;
int error;
/* Allocate and initialize private info */
MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (priv == NULL)
return (ENOMEM);
priv->conf.xmitAlg = NG_ONE2MANY_XMIT_ROUNDROBIN;
priv->conf.failAlg = NG_ONE2MANY_FAIL_MANUAL;
/* Call superclass constructor */
if ((error = ng_make_node_common(&ng_one2many_typestruct, nodep))) {
FREE(priv, M_NETGRAPH);
return (error);
}
(*nodep)->private = priv;
/* Done */
return (0);
}
/*
* Method for attaching a new hook
*/
static int
ng_one2many_newhook(node_p node, hook_p hook, const char *name)
{
const priv_p priv = node->private;
struct ng_one2many_link *link;
int linkNum;
u_long i;
/* Which hook? */
if (strncmp(name, NG_ONE2MANY_HOOK_MANY_PREFIX,
strlen(NG_ONE2MANY_HOOK_MANY_PREFIX)) == 0) {
const char *cp;
char *eptr;
cp = name + strlen(NG_ONE2MANY_HOOK_MANY_PREFIX);
if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0'))
return (EINVAL);
i = strtoul(cp, &eptr, 10);
if (*eptr != '\0' || i < 0 || i >= NG_ONE2MANY_MAX_LINKS)
return (EINVAL);
linkNum = (int)i;
link = &priv->many[linkNum];
} else if (strcmp(name, NG_ONE2MANY_HOOK_ONE) == 0) {
linkNum = NG_ONE2MANY_ONE_LINKNUM;
link = &priv->one;
} else
return (EINVAL);
/* Is hook already connected? (should never happen) */
if (link->hook != NULL)
return (EISCONN);
/* Setup private info for this link */
LINK_NUM(hook) = linkNum;
link->hook = hook;
bzero(&link->stats, sizeof(link->stats));
if (linkNum != NG_ONE2MANY_ONE_LINKNUM) {
priv->conf.enabledLinks[linkNum] = 1; /* auto-enable link */
ng_one2many_update_many(priv);
}
/* Done */
return (0);
}
/*
* Receive a control message
*/
static int
ng_one2many_rcvmsg(node_p node, struct ng_mesg *msg,
const char *retaddr, struct ng_mesg **rptr, hook_p lasthook)
{
const priv_p priv = node->private;
struct ng_mesg *resp = NULL;
int error = 0;
switch (msg->header.typecookie) {
case NGM_ONE2MANY_COOKIE:
switch (msg->header.cmd) {
case NGM_ONE2MANY_SET_CONFIG:
{
struct ng_one2many_config *conf;
int i;
/* Check that new configuration is valid */
if (msg->header.arglen != sizeof(*conf)) {
error = EINVAL;
break;
}
conf = (struct ng_one2many_config *)msg->data;
switch (conf->xmitAlg) {
case NG_ONE2MANY_XMIT_ROUNDROBIN:
break;
default:
error = EINVAL;
break;
}
switch (conf->failAlg) {
case NG_ONE2MANY_FAIL_MANUAL:
break;
default:
error = EINVAL;
break;
}
if (error != 0)
break;
/* Normalized many link enabled bits */
for (i = 0; i < NG_ONE2MANY_MAX_LINKS; i++)
conf->enabledLinks[i] = !!conf->enabledLinks[i];
/* Copy config and reset */
bcopy(conf, &priv->conf, sizeof(*conf));
ng_one2many_update_many(priv);
break;
}
case NGM_ONE2MANY_GET_CONFIG:
{
struct ng_one2many_config *conf;
NG_MKRESPONSE(resp, msg, sizeof(*conf), M_NOWAIT);
if (resp == NULL) {
error = ENOMEM;
break;
}
conf = (struct ng_one2many_config *)resp->data;
bcopy(&priv->conf, conf, sizeof(priv->conf));
break;
}
case NGM_ONE2MANY_GET_STATS:
case NGM_ONE2MANY_CLR_STATS:
case NGM_ONE2MANY_GETCLR_STATS:
{
struct ng_one2many_link *link;
int linkNum;
/* Get link */
if (msg->header.arglen != sizeof(int32_t)) {
error = EINVAL;
break;
}
linkNum = *((int32_t *)msg->data);
if (linkNum == NG_ONE2MANY_ONE_LINKNUM)
link = &priv->one;
else if (linkNum == 0
&& linkNum < NG_ONE2MANY_MAX_LINKS) {
link = &priv->many[linkNum];
} else {
error = EINVAL;
break;
}
/* Get/clear stats */
if (msg->header.cmd != NGM_ONE2MANY_CLR_STATS) {
NG_MKRESPONSE(resp, msg,
sizeof(link->stats), M_NOWAIT);
if (resp == NULL) {
error = ENOMEM;
break;
}
bcopy(&link->stats,
resp->data, sizeof(link->stats));
}
if (msg->header.cmd != NGM_ONE2MANY_GET_STATS)
bzero(&link->stats, sizeof(link->stats));
break;
}
default:
error = EINVAL;
break;
}
break;
default:
error = EINVAL;
break;
}
/* Done */
if (rptr)
*rptr = resp;
else if (resp != NULL)
FREE(resp, M_NETGRAPH);
FREE(msg, M_NETGRAPH);
return (error);
}
/*
* Receive data on a hook
*/
static int
ng_one2many_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
{
const node_p node = hook->node;
const priv_p priv = node->private;
struct ng_one2many_link *src;
struct ng_one2many_link *dst;
int error = 0;
int linkNum;
/* Get link number */
linkNum = LINK_NUM(hook);
KASSERT(linkNum == NG_ONE2MANY_ONE_LINKNUM
|| (linkNum >= 0 && linkNum < NG_ONE2MANY_MAX_LINKS),
("%s: linkNum=%d", __FUNCTION__, linkNum));
/* Figure out source link */
src = (linkNum == NG_ONE2MANY_ONE_LINKNUM) ?
&priv->one : &priv->many[linkNum];
KASSERT(src->hook != NULL, ("%s: no src%d", __FUNCTION__, linkNum));
/* Update receive stats */
src->stats.recvPackets++;
src->stats.recvOctets += m->m_pkthdr.len;
/* Figure out destination link */
if (linkNum == NG_ONE2MANY_ONE_LINKNUM) {
if (priv->numActiveMany == 0) {
NG_FREE_DATA(m, meta);
return (ENOTCONN);
}
dst = &priv->many[priv->activeMany[priv->nextMany]];
priv->nextMany = (priv->nextMany + 1) % priv->numActiveMany;
} else
dst = &priv->one;
/* Update transmit stats */
dst->stats.xmitPackets++;
dst->stats.xmitOctets += m->m_pkthdr.len;
/* Deliver packet */
NG_SEND_DATA(error, dst->hook, m, meta);
return (error);
}
/*
* Shutdown node
*/
static int
ng_one2many_rmnode(node_p node)
{
const priv_p priv = node->private;
ng_unname(node);
ng_cutlinks(node);
KASSERT(priv->numActiveMany == 0,
("%s: numActiveMany=%d", __FUNCTION__, priv->numActiveMany));
FREE(priv, M_NETGRAPH);
node->private = NULL;
ng_unref(node);
return (0);
}
/*
* Hook disconnection.
*/
static int
ng_one2many_disconnect(hook_p hook)
{
const priv_p priv = hook->node->private;
int linkNum;
/* Get link number */
linkNum = LINK_NUM(hook);
KASSERT(linkNum == NG_ONE2MANY_ONE_LINKNUM
|| (linkNum >= 0 && linkNum < NG_ONE2MANY_MAX_LINKS),
("%s: linkNum=%d", __FUNCTION__, linkNum));
/* Nuke the link */
if (linkNum == NG_ONE2MANY_ONE_LINKNUM)
priv->one.hook = NULL;
else {
priv->many[linkNum].hook = NULL;
priv->conf.enabledLinks[linkNum] = 0;
ng_one2many_update_many(priv);
}
/* If no hooks left, go away */
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
return (0);
}
/******************************************************************
OTHER FUNCTIONS
******************************************************************/
/*
* Update internal state after the addition or removal of a "many" link
*/
static void
ng_one2many_update_many(priv_p priv)
{
int linkNum;
/* Update list of which "many" links are up */
priv->numActiveMany = 0;
for (linkNum = 0; linkNum < NG_ONE2MANY_MAX_LINKS; linkNum++) {
switch (priv->conf.failAlg) {
case NG_ONE2MANY_FAIL_MANUAL:
if (priv->many[linkNum].hook != NULL
&& priv->conf.enabledLinks[linkNum]) {
priv->activeMany[priv->numActiveMany] = linkNum;
priv->numActiveMany++;
}
break;
#ifdef INVARIANTS
default:
panic("%s: invalid failAlg", __FUNCTION__);
#endif
}
}
/* Update transmit algorithm state */
switch (priv->conf.xmitAlg) {
case NG_ONE2MANY_XMIT_ROUNDROBIN:
if (priv->numActiveMany > 0)
priv->nextMany %= priv->numActiveMany;
break;
#ifdef INVARIANTS
default:
panic("%s: invalid xmitAlg", __FUNCTION__);
#endif
}
}

112
sys/netgraph/ng_one2many.h Normal file
View File

@ -0,0 +1,112 @@
/*
* ng_one2many.h
*
* Copyright (c) 2000 Whistle Communications, Inc.
* All rights reserved.
*
* Subject to the following obligations and disclaimer of warranty, use and
* redistribution of this software, in source or object code forms, with or
* without modifications are expressly permitted by Whistle Communications;
* provided, however, that:
* 1. Any and all reproductions of the source or object code must include the
* copyright notice above and the following disclaimer of warranties; and
* 2. No rights are granted, in any manner or form, to use Whistle
* Communications, Inc. trademarks, including the mark "WHISTLE
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
* such appears in the above copyright notice or in the software.
*
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Archie Cobbs <archie@freebsd.org>
*
* $FreeBSD$
*/
#ifndef _NETGRAPH_NG_ONE2MANY_H_
#define _NETGRAPH_NG_ONE2MANY_H_
/* Node type name and magic cookie */
#define NG_ONE2MANY_NODE_TYPE "one2many"
#define NGM_ONE2MANY_COOKIE 971111383
/* Hook names */
#define NG_ONE2MANY_HOOK_ONE "one"
#define NG_ONE2MANY_HOOK_MANY_PREFIX "many" /* append decimal integer */
#define NG_ONE2MANY_HOOK_MANY_FMT "many%d" /* for use with printf(3) */
/* Maximum number of supported "many" links */
#define NG_ONE2MANY_MAX_LINKS 64
/* Link number used to indicate the "one" hook */
#define NG_ONE2MANY_ONE_LINKNUM (-1)
/* Algorithms for outgoing packet distribution (XXX only one so far) */
#define NG_ONE2MANY_XMIT_ROUNDROBIN 1 /* round-robin delivery */
/* Algorithms for detecting link failure (XXX only one so far) */
#define NG_ONE2MANY_FAIL_MANUAL 1 /* use enabledLinks[] array */
/* Node configuration structure */
struct ng_one2many_config {
u_int32_t xmitAlg; /* how to distribute packets */
u_int32_t failAlg; /* how to detect link failure */
u_char enabledLinks[NG_ONE2MANY_MAX_LINKS];
};
/* Keep this in sync with the above structure definition */
#define NG_ONE2MANY_CONFIG_TYPE_INFO(atype) { \
{ \
{ "xmitAlg", &ng_parse_uint64_type }, \
{ "failAlg", &ng_parse_uint64_type }, \
{ "enabledLinks", (atype) }, \
{ NULL } \
} \
}
/* Statistics structure (one for each link) */
struct ng_one2many_link_stats {
u_int64_t recvOctets; /* total octets rec'd on link */
u_int64_t recvPackets; /* total pkts rec'd on link */
u_int64_t xmitOctets; /* total octets xmit'd on link */
u_int64_t xmitPackets; /* total pkts xmit'd on link */
};
/* Keep this in sync with the above structure definition */
#define NG_ONE2MANY_LINK_STATS_TYPE_INFO { \
{ \
{ "recvOctets", &ng_parse_uint64_type }, \
{ "recvPackets", &ng_parse_uint64_type }, \
{ "xmitOctets", &ng_parse_uint64_type }, \
{ "xmitPackets", &ng_parse_uint64_type }, \
{ NULL } \
} \
}
/* Netgraph control messages */
enum {
NGM_ONE2MANY_SET_CONFIG, /* set configuration */
NGM_ONE2MANY_GET_CONFIG, /* get configuration */
NGM_ONE2MANY_GET_STATS, /* get link stats */
NGM_ONE2MANY_CLR_STATS, /* clear link stats */
NGM_ONE2MANY_GETCLR_STATS, /* atomically get & clear link stats */
};
#endif /* _NETGRAPH_NG_ONE2MANY_H_ */