New netgraph node type ng_one2many(4).
This commit is contained in:
parent
c3427a5cc8
commit
6e8d625628
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=68810
@ -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 \
|
||||
|
208
share/man/man4/ng_one2many.4
Normal file
208
share/man/man4/ng_one2many.4
Normal 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
|
7
sys/modules/netgraph/one2many/Makefile
Normal file
7
sys/modules/netgraph/one2many/Makefile
Normal 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
521
sys/netgraph/ng_one2many.c
Normal 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
112
sys/netgraph/ng_one2many.h
Normal 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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user