summaryrefslogtreecommitdiffstats
path: root/sys/netgraph
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2004-02-19 17:04:23 +0000
committerpjd <pjd@FreeBSD.org>2004-02-19 17:04:23 +0000
commit112dc996defecd05c1a61f9c1b39f107aa1d2b52 (patch)
treea9d7592e1ec7b5f671be14d6841bb7518950a828 /sys/netgraph
parenteb34e2938ab63180b53f296f366dcbb753b2b47f (diff)
downloadFreeBSD-src-112dc996defecd05c1a61f9c1b39f107aa1d2b52.zip
FreeBSD-src-112dc996defecd05c1a61f9c1b39f107aa1d2b52.tar.gz
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)
Diffstat (limited to 'sys/netgraph')
-rw-r--r--sys/netgraph/ng_one2many.c89
-rw-r--r--sys/netgraph/ng_one2many.h6
2 files changed, 94 insertions, 1 deletions
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 <sys/malloc.h>
#include <sys/ctype.h>
#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
#include <sys/errno.h>
+#include <net/if.h>
+#include <net/if_media.h>
+
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
#include <netgraph/ng_parse.h>
+#include <netgraph/ng_ether.h>
#include <netgraph/ng_one2many.h>
/* 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 } \
}
OpenPOWER on IntegriCloud