From 112dc996defecd05c1a61f9c1b39f107aa1d2b52 Mon Sep 17 00:00:00 2001 From: pjd Date: Thu, 19 Feb 2004 17:04:23 +0000 Subject: Add new failure detection algorithm. It works as follows: In every 'interval' seconds defined links are checked. If they are non-active they will not be used by to data transfer. No response from: julian, archie Silent on: net@ Approved by: scottl (mentor) --- sys/netgraph/ng_one2many.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++ sys/netgraph/ng_one2many.h | 6 +++- 2 files changed, 94 insertions(+), 1 deletion(-) (limited to 'sys/netgraph') diff --git a/sys/netgraph/ng_one2many.c b/sys/netgraph/ng_one2many.c index 927bb77..a11a0b7 100644 --- a/sys/netgraph/ng_one2many.c +++ b/sys/netgraph/ng_one2many.c @@ -53,11 +53,17 @@ #include #include #include +#include +#include #include +#include +#include + #include #include #include +#include #include /* Per-link private data */ @@ -74,6 +80,7 @@ struct ng_one2many_private { u_int16_t nextMany; /* next round-robin */ u_int16_t numActiveMany; /* # active "many" */ u_int16_t activeMany[NG_ONE2MANY_MAX_LINKS]; + struct callout_handle callout; }; typedef struct ng_one2many_private *priv_p; @@ -86,6 +93,8 @@ static ng_rcvdata_t ng_one2many_rcvdata; static ng_disconnect_t ng_one2many_disconnect; /* Other functions */ +static void ng_one2many_scan(node_p node, hook_p hook __unused, + void *arg1 __unused, int arg2 __unused); static void ng_one2many_update_many(priv_p priv); /* Store each hook's link number in the private field */ @@ -195,9 +204,15 @@ ng_one2many_constructor(node_p node) return (ENOMEM); priv->conf.xmitAlg = NG_ONE2MANY_XMIT_ROUNDROBIN; priv->conf.failAlg = NG_ONE2MANY_FAIL_MANUAL; + priv->conf.interval = 5; NG_NODE_SET_PRIVATE(node, priv); + if (priv->conf.failAlg == NG_ONE2MANY_FAIL_IFACE_LINK) { + priv->callout = ng_timeout(node, NULL, priv->conf.interval * hz, + ng_one2many_scan, NULL, 0); + } + /* Done */ return (0); } @@ -286,6 +301,7 @@ ng_one2many_rcvmsg(node_p node, item_p item, hook_p lasthook) } switch (conf->failAlg) { case NG_ONE2MANY_FAIL_MANUAL: + case NG_ONE2MANY_FAIL_IFACE_LINK: break; default: error = EINVAL; @@ -301,6 +317,13 @@ ng_one2many_rcvmsg(node_p node, item_p item, hook_p lasthook) /* Copy config and reset */ bcopy(conf, &priv->conf, sizeof(*conf)); ng_one2many_update_many(priv); + + ng_untimeout(priv->callout, node); + if (priv->conf.failAlg == NG_ONE2MANY_FAIL_IFACE_LINK) { + priv->callout = ng_timeout(node, NULL, + priv->conf.interval * hz, ng_one2many_scan, + NULL, 0); + } break; } case NGM_ONE2MANY_GET_CONFIG: @@ -476,6 +499,8 @@ ng_one2many_shutdown(node_p node) KASSERT(priv->numActiveMany == 0, ("%s: numActiveMany=%d", __func__, priv->numActiveMany)); + if (priv->conf.failAlg == NG_ONE2MANY_FAIL_IFACE_LINK) + ng_untimeout(priv->callout, node); FREE(priv, M_NETGRAPH); NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(node); @@ -517,6 +542,63 @@ ng_one2many_disconnect(hook_p hook) OTHER FUNCTIONS ******************************************************************/ +#if 0 +/* + * Get interface name. + */ +static const char * +ng_one2many_ifname(struct ng_one2many_link *link) +{ + node_p node; + + node = link->hook->hk_peer->hk_node; + if (strcmp(node->nd_type->name, "ether") != 0) + return ("unknown"); + return (node->nd_name); +} +#endif + +/* + * Check if interface related to given node is active. + */ +static int +ng_one2many_active(struct ng_one2many_link *link) +{ + struct ng_ether_private *ethpriv; + struct ifmediareq ifmr; + struct ifnet *ifp; + node_p node; + int error; + + node = link->hook->hk_peer->hk_node; + if (strcmp(node->nd_type->name, "ether") != 0) + return (0); + ethpriv = NG_NODE_PRIVATE(node); + ifp = ethpriv->ifp; + bzero(&ifmr, sizeof(ifmr)); + error = ifp->if_ioctl(ifp, SIOCGIFMEDIA, (char *)&ifmr); + if (error != 0) + return (0); + if ((ifmr.ifm_status & IFM_ACTIVE) == 0) + return (0); + return (1); +} + +/* + * Check every priv->conf.interval seconds for active links. + */ +static void +ng_one2many_scan(node_p node, hook_p hook __unused, void *arg1 __unused, + int arg2 __unused) +{ + const priv_p priv = NG_NODE_PRIVATE(node); + + ng_one2many_update_many(priv); + + priv->callout = ng_timeout(node, NULL, priv->conf.interval * hz, + ng_one2many_scan, NULL, 0); +} + /* * Update internal state after the addition or removal of a "many" link */ @@ -536,6 +618,13 @@ ng_one2many_update_many(priv_p priv) priv->numActiveMany++; } break; + case NG_ONE2MANY_FAIL_IFACE_LINK: + if (priv->many[linkNum].hook != NULL && + ng_one2many_active(&priv->many[linkNum])) { + priv->activeMany[priv->numActiveMany] = linkNum; + priv->numActiveMany++; + } + break; #ifdef INVARIANTS default: panic("%s: invalid failAlg", __func__); diff --git a/sys/netgraph/ng_one2many.h b/sys/netgraph/ng_one2many.h index bf79859..3f7ceec 100644 --- a/sys/netgraph/ng_one2many.h +++ b/sys/netgraph/ng_one2many.h @@ -61,13 +61,16 @@ #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) */ +/* Algorithms for detecting link failure */ #define NG_ONE2MANY_FAIL_MANUAL 1 /* use enabledLinks[] array */ +#define NG_ONE2MANY_FAIL_IFACE_LINK 2 /* use interface state */ /* 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_int32_t interval; /* interval for IFACE_LINK + failure algorithm */ u_char enabledLinks[NG_ONE2MANY_MAX_LINKS]; }; @@ -75,6 +78,7 @@ struct ng_one2many_config { #define NG_ONE2MANY_CONFIG_TYPE_INFO(atype) { \ { "xmitAlg", &ng_parse_uint32_type }, \ { "failAlg", &ng_parse_uint32_type }, \ + { "interval", &ng_parse_uint32_type }, \ { "enabledLinks", (atype) }, \ { NULL } \ } -- cgit v1.1