diff -rup netgraph.orig/ng_ether.c netgraph/ng_ether.c --- netgraph.orig/ng_ether.c Fri Jan 9 17:08:02 2004 +++ netgraph/ng_ether.c Wed Jan 28 03:35:17 2004 @@ -67,18 +67,7 @@ #define IFP2AC(IFP) ((struct arpcom *)IFP) #define IFP2NG(ifp) ((struct ng_node *)((struct arpcom *)(ifp))->ac_netgraph) -/* Per-node private data */ -struct private { - struct ifnet *ifp; /* associated interface */ - hook_p upper; /* upper hook connection */ - hook_p lower; /* lower OR orphan hook connection */ - u_char lowerOrphan; /* whether lower is lower or orphan */ - u_char autoSrcAddr; /* always overwrite source address */ - u_char promisc; /* promiscuous mode enabled */ - u_long hwassist; /* hardware checksum capabilities */ - u_int flags; /* flags e.g. really die */ -}; -typedef struct private *priv_p; +typedef struct ng_ether_private *priv_p; /* Hook pointers used by if_ethersubr.c to callback to netgraph */ extern void (*ng_ether_input_p)(struct ifnet *ifp, struct mbuf **mp); diff -rup netgraph.orig/ng_ether.h netgraph/ng_ether.h --- netgraph.orig/ng_ether.h Sat Dec 27 15:52:45 2003 +++ netgraph/ng_ether.h Wed Jan 28 03:35:22 2004 @@ -65,5 +65,17 @@ enum { NGM_ETHER_SET_AUTOSRC, /* enable/disable src addr override */ }; +/* Per-node private data */ +struct ng_ether_private { + struct ifnet *ifp; /* associated interface */ + hook_p upper; /* upper hook connection */ + hook_p lower; /* lower OR orphan hook connection */ + u_char lowerOrphan; /* whether lower is lower or orphan */ + u_char autoSrcAddr; /* always overwrite source address */ + u_char promisc; /* promiscuous mode enabled */ + u_long hwassist; /* hardware checksum capabilities */ + u_int flags; /* flags e.g. really die */ +}; + #endif /* _NETGRAPH_NG_ETHER_H_ */ diff -rup netgraph.orig/ng_one2many.c netgraph/ng_one2many.c --- netgraph.orig/ng_one2many.c Wed Feb 19 06:47:31 2003 +++ netgraph/ng_one2many.c Wed Jan 28 03:37:35 2004 @@ -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 i } 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 i /* 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 */ @@ -532,6 +614,13 @@ ng_one2many_update_many(priv_p priv) case NG_ONE2MANY_FAIL_MANUAL: if (priv->many[linkNum].hook != NULL && priv->conf.enabledLinks[linkNum]) { + priv->activeMany[priv->numActiveMany] = linkNum; + 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++; } diff -rup netgraph.orig/ng_one2many.h netgraph/ng_one2many.h --- netgraph.orig/ng_one2many.h Sat Jun 1 01:48:02 2002 +++ netgraph/ng_one2many.h Wed Jan 28 03:36:14 2004 @@ -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 } \ }