diff options
author | glebius <glebius@FreeBSD.org> | 2004-11-23 09:45:47 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2004-11-23 09:45:47 +0000 |
commit | d1939766d16ca2a349dd3edf7ab84b0b59add457 (patch) | |
tree | 3f25f594455b094691f35a03db9acc300c8f0d13 | |
parent | b437de8061981c7de5aff7cc8e490d45a117a7ce (diff) | |
download | FreeBSD-src-d1939766d16ca2a349dd3edf7ab84b0b59add457.zip FreeBSD-src-d1939766d16ca2a349dd3edf7ab84b0b59add457.tar.gz |
Introduce new failure detection algorithm, called NG_ONE2MANY_FAIL_NOTIFY.
It means, that node listens to flow control messages from downstreams
and removes link from list of active links whenever a LINK_IS_DOWN message
is received. If LINK_IS_UP message is received, then links is put
back into list of active links.
Approved by: julian (mentor), implicitly
MFC after: 1 week
-rw-r--r-- | sys/netgraph/ng_one2many.c | 64 | ||||
-rw-r--r-- | sys/netgraph/ng_one2many.h | 3 |
2 files changed, 66 insertions, 1 deletions
diff --git a/sys/netgraph/ng_one2many.c b/sys/netgraph/ng_one2many.c index df2dbdc..9ab21ee 100644 --- a/sys/netgraph/ng_one2many.c +++ b/sys/netgraph/ng_one2many.c @@ -68,6 +68,7 @@ struct ng_one2many_link { /* 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]; @@ -87,6 +88,7 @@ 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 @@ -190,7 +192,9 @@ ng_one2many_constructor(node_p node) 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); @@ -280,6 +284,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_NOTIFY: break; default: error = EINVAL; @@ -353,6 +358,42 @@ ng_one2many_rcvmsg(node_p node, item_p item, hook_p lasthook) 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; @@ -506,6 +547,7 @@ ng_one2many_disconnect(hook_p hook) static void ng_one2many_update_many(priv_p priv) { + uint16_t saveActive = priv->numActiveMany; int linkNum; /* Update list of which "many" links are up */ @@ -513,6 +555,7 @@ ng_one2many_update_many(priv_p priv) 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; @@ -526,6 +569,12 @@ ng_one2many_update_many(priv_p priv) } } + 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: @@ -541,4 +590,19 @@ ng_one2many_update_many(priv_p priv) } } +/* + * 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_NOWAIT); + if (msg != NULL) + NG_SEND_MSG_HOOK(dummy_error, priv->node, msg, priv->one.hook, 0); +} diff --git a/sys/netgraph/ng_one2many.h b/sys/netgraph/ng_one2many.h index bf79859..f9c4919 100644 --- a/sys/netgraph/ng_one2many.h +++ b/sys/netgraph/ng_one2many.h @@ -44,7 +44,7 @@ /* Node type name and magic cookie */ #define NG_ONE2MANY_NODE_TYPE "one2many" -#define NGM_ONE2MANY_COOKIE 971111383 +#define NGM_ONE2MANY_COOKIE 1100897444 /* Hook names */ #define NG_ONE2MANY_HOOK_ONE "one" @@ -63,6 +63,7 @@ /* 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 { |