From 119de7c20d207cfc51d87582f40ad036c65eda21 Mon Sep 17 00:00:00 2001 From: Nuno Antunes Date: Sat, 18 Sep 2010 02:45:25 +0100 Subject: [PATCH] netgraph7: Welcome ng_one2many. --- etc/mtree/BSD.include.dist | 2 + include/Makefile | 2 +- lib/libnetgraph7/debug.c | 4 - sys/conf/files | 2 +- sys/netgraph7/Makefile | 2 +- sys/netgraph7/ng_one2many.c | 611 ---------------------------------- sys/netgraph7/ng_one2many.h | 114 ------- sys/netgraph7/one2many/Makefile | 7 + sys/netgraph7/one2many/ng_one2many.c | 611 ++++++++++++++++++++++++++++++++++ sys/netgraph7/one2many/ng_one2many.h | 114 +++++++ 10 files changed, 737 insertions(+), 732 deletions(-) delete mode 100644 sys/netgraph7/ng_one2many.c delete mode 100644 sys/netgraph7/ng_one2many.h create mode 100644 sys/netgraph7/one2many/Makefile create mode 100644 sys/netgraph7/one2many/ng_one2many.c create mode 100644 sys/netgraph7/one2many/ng_one2many.h diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index ad933e5..9d2aa8f 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -240,6 +240,8 @@ .. mppc .. + one2many + .. ppp .. pptpgre diff --git a/include/Makefile b/include/Makefile index a1962b4..042cfcb 100644 --- a/include/Makefile +++ b/include/Makefile @@ -71,7 +71,7 @@ LSUBDIRS= bus/cam bus/cam/scsi \ netgraph7/bridge netgraph7/cisco netgraph7/deflate netgraph7/echo \ netgraph7/etf netgraph7/ether netgraph7/frame_relay netgraph7/hole \ netgraph7/iface netgraph7/ksocket netgraph7/l2tp netgraph7/lmi \ - netgraph7/mppc netgraph7/ppp \ + netgraph7/mppc netgraph7/one2many netgraph7/ppp \ netgraph7/pptpgre netgraph7/socket netgraph7/tee netgraph7/vjc \ bus/cam bus/usb bus/pccard bus/pci bus/isa bus/ppbus bus/smbus \ netproto/atm netproto/ipsec netproto/ipx \ diff --git a/lib/libnetgraph7/debug.c b/lib/libnetgraph7/debug.c index 6dbb930..a06a409 100644 --- a/lib/libnetgraph7/debug.c +++ b/lib/libnetgraph7/debug.c @@ -85,9 +85,7 @@ #include #include #include -/* #include -*/ #include /* #include @@ -164,9 +162,7 @@ static const struct ng_cookie cookies[] = { COOKIE(L2TP), COOKIE(LMI), COOKIE(MPPC), -/* COOKIE(ONE2MANY), -*/ COOKIE(PPP), /* COOKIE(PPPOE), diff --git a/sys/conf/files b/sys/conf/files index f2e158e..59ac1a1 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1328,7 +1328,7 @@ netgraph7/lmi/ng_lmi.c optional netgraph7_lmi netgraph7/mppc/ng_mppc.c optional netgraph7_mppc_compression netgraph7/mppc/ng_mppc.c optional netgraph7_mppc_encryption netgraph7/ng_nat.c optional netgraph7_nat -netgraph7/ng_one2many.c optional netgraph7_one2many +netgraph7/one2many/ng_one2many.c optional netgraph7_one2many netgraph7/netgraph/ng_parse.c optional netgraph7 netgraph7/ppp/ng_ppp.c optional netgraph7_ppp netgraph7/ng_pppoe.c optional netgraph7_pppoe diff --git a/sys/netgraph7/Makefile b/sys/netgraph7/Makefile index bb9af38..e9b3b35 100644 --- a/sys/netgraph7/Makefile +++ b/sys/netgraph7/Makefile @@ -20,6 +20,7 @@ SUBDIR= UI \ lmi \ mppc \ netgraph \ + one2many \ ppp \ pptpgre \ socket \ @@ -28,7 +29,6 @@ SUBDIR= UI \ # eiface \ # fec \ # netgraph \ -# one2many \ # pppoe \ # rfc1490 \ # socket \ diff --git a/sys/netgraph7/ng_one2many.c b/sys/netgraph7/ng_one2many.c deleted file mode 100644 index 7b692b1..0000000 --- a/sys/netgraph7/ng_one2many.c +++ /dev/null @@ -1,611 +0,0 @@ -/* - * 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 - * - * $FreeBSD: src/sys/netgraph/ng_one2many.c,v 1.21 2005/03/11 10:29:38 glebius Exp $ - * $DragonFly: src/sys/netgraph7/ng_one2many.c,v 1.2 2008/06/26 23:05:35 dillon Exp $ - */ - -/* - * ng_one2many(4) netgraph node type - * - * Packets received on the "one" hook are sent out each of the - * "many" hooks accoring to an algorithm. Packets received on any - * "many" hook are always delivered to the "one" hook. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "ng_message.h" -#include "netgraph.h" -#include "ng_parse.h" -#include "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 { - node_p node; /* link to node */ - 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_shutdown; -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); -static void ng_one2many_notify(priv_p priv, uint32_t cmd); - -/****************************************************************** - 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_field ng_one2many_config_type_fields[] - = 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_fields -}; - -/* Parse type for struct ng_one2many_link_stats */ -static const struct ng_parse_struct_field ng_one2many_link_stats_type_fields[] - = 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_fields -}; - -/* 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 = { - .version = NG_ABI_VERSION, - .name = NG_ONE2MANY_NODE_TYPE, - .constructor = ng_one2many_constructor, - .rcvmsg = ng_one2many_rcvmsg, - .shutdown = ng_one2many_shutdown, - .newhook = ng_one2many_newhook, - .rcvdata = ng_one2many_rcvdata, - .disconnect = ng_one2many_disconnect, - .cmdlist = ng_one2many_cmdlist, -}; -NETGRAPH_INIT(one2many, &ng_one2many_typestruct); - -/****************************************************************** - NETGRAPH NODE METHODS -******************************************************************/ - -/* - * Node constructor - */ -static int -ng_one2many_constructor(node_p node) -{ - priv_p priv; - - /* Allocate and initialize private info */ - priv = kmalloc(sizeof(*priv), M_NETGRAPH, - M_WAITOK | M_NULLOK | M_ZERO); - if (priv == NULL) - return (ENOMEM); - priv->conf.xmitAlg = NG_ONE2MANY_XMIT_ROUNDROBIN; - priv->conf.failAlg = NG_ONE2MANY_FAIL_MANUAL; - - /* cross reference */ - NG_NODE_SET_PRIVATE(node, priv); - priv->node = node; - - /* 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 = NG_NODE_PRIVATE(node); - 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 */ - NG_HOOK_SET_PRIVATE(hook, (void *)(intptr_t)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, item_p item, hook_p lasthook) -{ - const priv_p priv = NG_NODE_PRIVATE(node); - struct ng_mesg *resp = NULL; - int error = 0; - struct ng_mesg *msg; - - NGI_GET_MSG(item, msg); - 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: - case NG_ONE2MANY_XMIT_ALL: - break; - default: - error = EINVAL; - break; - } - switch (conf->failAlg) { - case NG_ONE2MANY_FAIL_MANUAL: - case NG_ONE2MANY_FAIL_NOTIFY: - 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_WAITOK | M_NULLOK); - 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_WAITOK | M_NULLOK); - 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; - /* - * One of our downstreams notifies us of link change. If we are - * configured to listen to these message, then we remove/add - * this hook from array of active hooks. - */ - case NGM_FLOW_COOKIE: - { - int linkNum; - - if (priv->conf.failAlg != NG_ONE2MANY_FAIL_NOTIFY) - break; - - if (lasthook == NULL) - break; - - linkNum = (intptr_t)NG_HOOK_PRIVATE(lasthook); - if (linkNum == NG_ONE2MANY_ONE_LINKNUM) - break; - - KASSERT((linkNum >= 0 && linkNum < NG_ONE2MANY_MAX_LINKS), - ("%s: linkNum=%d", __func__, linkNum)); - - switch (msg->header.cmd) { - case NGM_LINK_IS_UP: - priv->conf.enabledLinks[linkNum] = 1; - ng_one2many_update_many(priv); - break; - case NGM_LINK_IS_DOWN: - priv->conf.enabledLinks[linkNum] = 0; - ng_one2many_update_many(priv); - break; - default: - break; - } - break; - } - default: - error = EINVAL; - break; - } - - /* Done */ - NG_RESPOND_MSG(error, node, item, resp); - NG_FREE_MSG(msg); - return (error); -} - -/* - * Receive data on a hook - */ -static int -ng_one2many_rcvdata(hook_p hook, item_p item) -{ - const node_p node = NG_HOOK_NODE(hook); - const priv_p priv = NG_NODE_PRIVATE(node); - struct ng_one2many_link *src; - struct ng_one2many_link *dst = NULL; - int error = 0; - int linkNum; - int i; - struct mbuf *m; - - m = NGI_M(item); /* just peaking, mbuf still owned by item */ - /* Get link number */ - linkNum = (intptr_t)NG_HOOK_PRIVATE(hook); - KASSERT(linkNum == NG_ONE2MANY_ONE_LINKNUM - || (linkNum >= 0 && linkNum < NG_ONE2MANY_MAX_LINKS), - ("%s: linkNum=%d", __func__, linkNum)); - - /* Figure out source link */ - src = (linkNum == NG_ONE2MANY_ONE_LINKNUM) ? - &priv->one : &priv->many[linkNum]; - KASSERT(src->hook != NULL, ("%s: no src%d", __func__, 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_ITEM(item); - return (ENOTCONN); - } - switch(priv->conf.xmitAlg) { - case NG_ONE2MANY_XMIT_ROUNDROBIN: - dst = &priv->many[priv->activeMany[priv->nextMany]]; - priv->nextMany = (priv->nextMany + 1) % priv->numActiveMany; - break; - case NG_ONE2MANY_XMIT_ALL: - /* no need to copy data for the 1st one */ - dst = &priv->many[priv->activeMany[0]]; - - /* make copies of data and send for all links - * except the first one, which we'll do last - */ - for (i = 1; i < priv->numActiveMany; i++) { - struct mbuf *m2; - struct ng_one2many_link *mdst; - - mdst = &priv->many[priv->activeMany[i]]; - m2 = m_dup(m, MB_DONTWAIT); /* XXX m_copypacket() */ - if (m2 == NULL) { - mdst->stats.memoryFailures++; - NG_FREE_ITEM(item); - NG_FREE_M(m); - return (ENOBUFS); - } - /* Update transmit stats */ - mdst->stats.xmitPackets++; - mdst->stats.xmitOctets += m->m_pkthdr.len; - NG_SEND_DATA_ONLY(error, mdst->hook, m2); - } - break; -#ifdef INVARIANTS - default: - panic("%s: invalid xmitAlg", __func__); -#endif - } - } else { - dst = &priv->one; - } - - /* Update transmit stats */ - dst->stats.xmitPackets++; - dst->stats.xmitOctets += m->m_pkthdr.len; - - /* Deliver packet */ - NG_FWD_ITEM_HOOK(error, item, dst->hook); - return (error); -} - -/* - * Shutdown node - */ -static int -ng_one2many_shutdown(node_p node) -{ - const priv_p priv = NG_NODE_PRIVATE(node); - - KASSERT(priv->numActiveMany == 0, - ("%s: numActiveMany=%d", __func__, priv->numActiveMany)); - kfree(priv, M_NETGRAPH); - NG_NODE_SET_PRIVATE(node, NULL); - NG_NODE_UNREF(node); - return (0); -} - -/* - * Hook disconnection. - */ -static int -ng_one2many_disconnect(hook_p hook) -{ - const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); - int linkNum; - - /* Get link number */ - linkNum = (intptr_t)NG_HOOK_PRIVATE(hook); - KASSERT(linkNum == NG_ONE2MANY_ONE_LINKNUM - || (linkNum >= 0 && linkNum < NG_ONE2MANY_MAX_LINKS), - ("%s: linkNum=%d", __func__, 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 ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) - && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) - ng_rmnode_self(NG_HOOK_NODE(hook)); - 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) -{ - uint16_t saveActive = priv->numActiveMany; - 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: - case NG_ONE2MANY_FAIL_NOTIFY: - 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", __func__); -#endif - } - } - - if (priv->numActiveMany == 0 && saveActive > 0) - ng_one2many_notify(priv, NGM_LINK_IS_DOWN); - - if (saveActive == 0 && priv->numActiveMany > 0) - ng_one2many_notify(priv, NGM_LINK_IS_UP); - - /* Update transmit algorithm state */ - switch (priv->conf.xmitAlg) { - case NG_ONE2MANY_XMIT_ROUNDROBIN: - if (priv->numActiveMany > 0) - priv->nextMany %= priv->numActiveMany; - break; - case NG_ONE2MANY_XMIT_ALL: - break; -#ifdef INVARIANTS - default: - panic("%s: invalid xmitAlg", __func__); -#endif - } -} - -/* - * Notify upstream if we are out of links, or we have at least one link. - */ -static void -ng_one2many_notify(priv_p priv, uint32_t cmd) -{ - struct ng_mesg *msg; - int dummy_error = 0; - - if (priv->one.hook == NULL) - return; - - NG_MKMESSAGE(msg, NGM_FLOW_COOKIE, cmd, 0, M_WAITOK | M_NULLOK); - if (msg != NULL) - NG_SEND_MSG_HOOK(dummy_error, priv->node, msg, priv->one.hook, 0); -} diff --git a/sys/netgraph7/ng_one2many.h b/sys/netgraph7/ng_one2many.h deleted file mode 100644 index 9e4ba7f..0000000 --- a/sys/netgraph7/ng_one2many.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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 - * - * $FreeBSD: src/sys/netgraph/ng_one2many.h,v 1.8 2005/01/07 01:45:39 imp Exp $ - * $DragonFly: src/sys/netgraph7/ng_one2many.h,v 1.2 2008/06/26 23:05:35 dillon Exp $ - */ - -#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 1100897444 - -/* 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 */ -#define NG_ONE2MANY_XMIT_ALL 2 /* send packets to all many hooks */ - -/* Algorithms for detecting link failure (XXX only one so far) */ -#define NG_ONE2MANY_FAIL_MANUAL 1 /* use enabledLinks[] array */ -#define NG_ONE2MANY_FAIL_NOTIFY 2 /* listen to flow control msgs */ - -/* 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_uint32_type }, \ - { "failAlg", &ng_parse_uint32_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 */ - u_int64_t memoryFailures; /* times couldn't get mem or mbuf */ -}; - -/* 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 }, \ - { "memoryFailures", &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_ */ - diff --git a/sys/netgraph7/one2many/Makefile b/sys/netgraph7/one2many/Makefile new file mode 100644 index 0000000..7bfbc95 --- /dev/null +++ b/sys/netgraph7/one2many/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD: src/sys/modules/netgraph/one2many/Makefile,v 1.1.2.1 2000/11/16 17:28:32 archie Exp $ +# $DragonFly: src/sys/netgraph/one2many/Makefile,v 1.2 2003/06/17 04:28:46 dillon Exp $ + +KMOD= ng_one2many +SRCS= ng_one2many.c + +.include diff --git a/sys/netgraph7/one2many/ng_one2many.c b/sys/netgraph7/one2many/ng_one2many.c new file mode 100644 index 0000000..3ab57ff --- /dev/null +++ b/sys/netgraph7/one2many/ng_one2many.c @@ -0,0 +1,611 @@ +/* + * 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 + * + * $FreeBSD: src/sys/netgraph/ng_one2many.c,v 1.21 2005/03/11 10:29:38 glebius Exp $ + * $DragonFly: src/sys/netgraph7/ng_one2many.c,v 1.2 2008/06/26 23:05:35 dillon Exp $ + */ + +/* + * ng_one2many(4) netgraph node type + * + * Packets received on the "one" hook are sent out each of the + * "many" hooks accoring to an algorithm. Packets received on any + * "many" hook are always delivered to the "one" hook. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "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 { + node_p node; /* link to node */ + 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_shutdown; +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); +static void ng_one2many_notify(priv_p priv, uint32_t cmd); + +/****************************************************************** + 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_field ng_one2many_config_type_fields[] + = 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_fields +}; + +/* Parse type for struct ng_one2many_link_stats */ +static const struct ng_parse_struct_field ng_one2many_link_stats_type_fields[] + = 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_fields +}; + +/* 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 = { + .version = NG_ABI_VERSION, + .name = NG_ONE2MANY_NODE_TYPE, + .constructor = ng_one2many_constructor, + .rcvmsg = ng_one2many_rcvmsg, + .shutdown = ng_one2many_shutdown, + .newhook = ng_one2many_newhook, + .rcvdata = ng_one2many_rcvdata, + .disconnect = ng_one2many_disconnect, + .cmdlist = ng_one2many_cmdlist, +}; +NETGRAPH_INIT(one2many, &ng_one2many_typestruct); + +/****************************************************************** + NETGRAPH NODE METHODS +******************************************************************/ + +/* + * Node constructor + */ +static int +ng_one2many_constructor(node_p node) +{ + priv_p priv; + + /* Allocate and initialize private info */ + priv = kmalloc(sizeof(*priv), M_NETGRAPH, + M_WAITOK | M_NULLOK | M_ZERO); + if (priv == NULL) + return (ENOMEM); + priv->conf.xmitAlg = NG_ONE2MANY_XMIT_ROUNDROBIN; + priv->conf.failAlg = NG_ONE2MANY_FAIL_MANUAL; + + /* cross reference */ + NG_NODE_SET_PRIVATE(node, priv); + priv->node = node; + + /* 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 = NG_NODE_PRIVATE(node); + 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 */ + NG_HOOK_SET_PRIVATE(hook, (void *)(intptr_t)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, item_p item, hook_p lasthook) +{ + const priv_p priv = NG_NODE_PRIVATE(node); + struct ng_mesg *resp = NULL; + int error = 0; + struct ng_mesg *msg; + + NGI_GET_MSG(item, msg); + 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: + case NG_ONE2MANY_XMIT_ALL: + break; + default: + error = EINVAL; + break; + } + switch (conf->failAlg) { + case NG_ONE2MANY_FAIL_MANUAL: + case NG_ONE2MANY_FAIL_NOTIFY: + 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_WAITOK | M_NULLOK); + 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_WAITOK | M_NULLOK); + 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; + /* + * One of our downstreams notifies us of link change. If we are + * configured to listen to these message, then we remove/add + * this hook from array of active hooks. + */ + case NGM_FLOW_COOKIE: + { + int linkNum; + + if (priv->conf.failAlg != NG_ONE2MANY_FAIL_NOTIFY) + break; + + if (lasthook == NULL) + break; + + linkNum = (intptr_t)NG_HOOK_PRIVATE(lasthook); + if (linkNum == NG_ONE2MANY_ONE_LINKNUM) + break; + + KASSERT((linkNum >= 0 && linkNum < NG_ONE2MANY_MAX_LINKS), + ("%s: linkNum=%d", __func__, linkNum)); + + switch (msg->header.cmd) { + case NGM_LINK_IS_UP: + priv->conf.enabledLinks[linkNum] = 1; + ng_one2many_update_many(priv); + break; + case NGM_LINK_IS_DOWN: + priv->conf.enabledLinks[linkNum] = 0; + ng_one2many_update_many(priv); + break; + default: + break; + } + break; + } + default: + error = EINVAL; + break; + } + + /* Done */ + NG_RESPOND_MSG(error, node, item, resp); + NG_FREE_MSG(msg); + return (error); +} + +/* + * Receive data on a hook + */ +static int +ng_one2many_rcvdata(hook_p hook, item_p item) +{ + const node_p node = NG_HOOK_NODE(hook); + const priv_p priv = NG_NODE_PRIVATE(node); + struct ng_one2many_link *src; + struct ng_one2many_link *dst = NULL; + int error = 0; + int linkNum; + int i; + struct mbuf *m; + + m = NGI_M(item); /* just peaking, mbuf still owned by item */ + /* Get link number */ + linkNum = (intptr_t)NG_HOOK_PRIVATE(hook); + KASSERT(linkNum == NG_ONE2MANY_ONE_LINKNUM + || (linkNum >= 0 && linkNum < NG_ONE2MANY_MAX_LINKS), + ("%s: linkNum=%d", __func__, linkNum)); + + /* Figure out source link */ + src = (linkNum == NG_ONE2MANY_ONE_LINKNUM) ? + &priv->one : &priv->many[linkNum]; + KASSERT(src->hook != NULL, ("%s: no src%d", __func__, 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_ITEM(item); + return (ENOTCONN); + } + switch(priv->conf.xmitAlg) { + case NG_ONE2MANY_XMIT_ROUNDROBIN: + dst = &priv->many[priv->activeMany[priv->nextMany]]; + priv->nextMany = (priv->nextMany + 1) % priv->numActiveMany; + break; + case NG_ONE2MANY_XMIT_ALL: + /* no need to copy data for the 1st one */ + dst = &priv->many[priv->activeMany[0]]; + + /* make copies of data and send for all links + * except the first one, which we'll do last + */ + for (i = 1; i < priv->numActiveMany; i++) { + struct mbuf *m2; + struct ng_one2many_link *mdst; + + mdst = &priv->many[priv->activeMany[i]]; + m2 = m_dup(m, MB_DONTWAIT); /* XXX m_copypacket() */ + if (m2 == NULL) { + mdst->stats.memoryFailures++; + NG_FREE_ITEM(item); + NG_FREE_M(m); + return (ENOBUFS); + } + /* Update transmit stats */ + mdst->stats.xmitPackets++; + mdst->stats.xmitOctets += m->m_pkthdr.len; + NG_SEND_DATA_ONLY(error, mdst->hook, m2); + } + break; +#ifdef INVARIANTS + default: + panic("%s: invalid xmitAlg", __func__); +#endif + } + } else { + dst = &priv->one; + } + + /* Update transmit stats */ + dst->stats.xmitPackets++; + dst->stats.xmitOctets += m->m_pkthdr.len; + + /* Deliver packet */ + NG_FWD_ITEM_HOOK(error, item, dst->hook); + return (error); +} + +/* + * Shutdown node + */ +static int +ng_one2many_shutdown(node_p node) +{ + const priv_p priv = NG_NODE_PRIVATE(node); + + KASSERT(priv->numActiveMany == 0, + ("%s: numActiveMany=%d", __func__, priv->numActiveMany)); + kfree(priv, M_NETGRAPH); + NG_NODE_SET_PRIVATE(node, NULL); + NG_NODE_UNREF(node); + return (0); +} + +/* + * Hook disconnection. + */ +static int +ng_one2many_disconnect(hook_p hook) +{ + const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); + int linkNum; + + /* Get link number */ + linkNum = (intptr_t)NG_HOOK_PRIVATE(hook); + KASSERT(linkNum == NG_ONE2MANY_ONE_LINKNUM + || (linkNum >= 0 && linkNum < NG_ONE2MANY_MAX_LINKS), + ("%s: linkNum=%d", __func__, 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 ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) + && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) + ng_rmnode_self(NG_HOOK_NODE(hook)); + 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) +{ + uint16_t saveActive = priv->numActiveMany; + 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: + case NG_ONE2MANY_FAIL_NOTIFY: + 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", __func__); +#endif + } + } + + if (priv->numActiveMany == 0 && saveActive > 0) + ng_one2many_notify(priv, NGM_LINK_IS_DOWN); + + if (saveActive == 0 && priv->numActiveMany > 0) + ng_one2many_notify(priv, NGM_LINK_IS_UP); + + /* Update transmit algorithm state */ + switch (priv->conf.xmitAlg) { + case NG_ONE2MANY_XMIT_ROUNDROBIN: + if (priv->numActiveMany > 0) + priv->nextMany %= priv->numActiveMany; + break; + case NG_ONE2MANY_XMIT_ALL: + break; +#ifdef INVARIANTS + default: + panic("%s: invalid xmitAlg", __func__); +#endif + } +} + +/* + * Notify upstream if we are out of links, or we have at least one link. + */ +static void +ng_one2many_notify(priv_p priv, uint32_t cmd) +{ + struct ng_mesg *msg; + int dummy_error = 0; + + if (priv->one.hook == NULL) + return; + + NG_MKMESSAGE(msg, NGM_FLOW_COOKIE, cmd, 0, M_WAITOK | M_NULLOK); + if (msg != NULL) + NG_SEND_MSG_HOOK(dummy_error, priv->node, msg, priv->one.hook, 0); +} diff --git a/sys/netgraph7/one2many/ng_one2many.h b/sys/netgraph7/one2many/ng_one2many.h new file mode 100644 index 0000000..9e4ba7f --- /dev/null +++ b/sys/netgraph7/one2many/ng_one2many.h @@ -0,0 +1,114 @@ +/* + * 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 + * + * $FreeBSD: src/sys/netgraph/ng_one2many.h,v 1.8 2005/01/07 01:45:39 imp Exp $ + * $DragonFly: src/sys/netgraph7/ng_one2many.h,v 1.2 2008/06/26 23:05:35 dillon Exp $ + */ + +#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 1100897444 + +/* 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 */ +#define NG_ONE2MANY_XMIT_ALL 2 /* send packets to all many hooks */ + +/* Algorithms for detecting link failure (XXX only one so far) */ +#define NG_ONE2MANY_FAIL_MANUAL 1 /* use enabledLinks[] array */ +#define NG_ONE2MANY_FAIL_NOTIFY 2 /* listen to flow control msgs */ + +/* 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_uint32_type }, \ + { "failAlg", &ng_parse_uint32_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 */ + u_int64_t memoryFailures; /* times couldn't get mem or mbuf */ +}; + +/* 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 }, \ + { "memoryFailures", &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_ */ + -- 1.7.7.2