summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2008-07-17 10:51:18 -0700
committerStephen Hemminger <stephen.hemminger@vyatta.com>2008-07-17 10:51:18 -0700
commit9a0c65088cf66b8a5eeb89338b249840271360eb (patch)
tree3beaeec5b1af090d9b9f0836a37d03cf4eb31479
parentdeaccb3d66b902bb3523c451af6d408dd2b32656 (diff)
downloadquagga-9a0c65088cf66b8a5eeb89338b249840271360eb.tar.bz2
quagga-9a0c65088cf66b8a5eeb89338b249840271360eb.tar.xz
Handle state transistions when there are multiple nexthops
When multipath is being used, the state of one nexthop maybe down, but another one may be up.
-rw-r--r--zebra/zebra_rib.c116
1 files changed, 53 insertions, 63 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 28f88c51..2774a93c 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -340,13 +340,41 @@ nexthop_blackhole_add (struct rib *rib)
return nexthop;
}
+static int
+nexthop_isactive(const struct nexthop *nexthop)
+{
+ struct interface *ifp;
+
+ switch(nexthop->type)
+ {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV6:
+ if (nexthop->ifindex == 0)
+ return 0;
+ /* fall through */
+ case NEXTHOP_TYPE_IFINDEX:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ ifp = if_lookup_by_index (nexthop->ifindex);
+ return (ifp && if_is_operative (ifp));
+
+ case NEXTHOP_TYPE_IFNAME:
+ case NEXTHOP_TYPE_IPV4_IFNAME:
+ case NEXTHOP_TYPE_IPV6_IFNAME:
+ ifp = if_lookup_by_name(nexthop->ifname);
+ return (ifp && if_is_operative (ifp));
+
+ default:
+ return 1;
+ }
+}
+
/* If force flag is not set, do not modify falgs at all for uninstall
the route from FIB. */
static int
nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
struct route_node *top)
{
- struct interface *ifp;
struct prefix_ipv4 p;
struct route_table *table;
struct route_node *rn;
@@ -404,28 +432,17 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
if (!newhop)
return 0; /* dead route */
- /* if scanning and the new match is different than the old one
- * then force the CHANGED flag.
- * FIXME (have this routine return NULL or nexhop instead)
- */
- if (!set && newhop != nexthop)
- SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
-
/* recursive route, remember index */
if (nexthop->type == NEXTHOP_TYPE_IPV4)
nexthop->ifindex = newhop->ifindex;
- switch(newhop->type)
+ if (nexthop_isactive (newhop))
{
- case NEXTHOP_TYPE_IFINDEX:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- ifp = if_lookup_by_index (newhop->ifindex);
- return (ifp && if_is_operative (ifp));
- case NEXTHOP_TYPE_IFNAME:
- case NEXTHOP_TYPE_IPV4_IFNAME:
- ifp = if_lookup_by_name(newhop->ifname);
- return (ifp && if_is_operative (ifp));
- default:
+ /* if new match is different then force the CHANGED flag.
+ * FIXME (have this routine return NULL or nexhop instead)
+ */
+ if (newhop != nexthop)
+ SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
return 1;
}
}
@@ -433,8 +450,13 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
match->type == ZEBRA_ROUTE_STATIC)
{
for (newhop = match->nexthop; newhop; newhop = newhop->next)
- if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
+ if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
+ && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE)
+ && nexthop_isactive (newhop))
{
+ if (newhop != nexthop)
+ SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
+
if (set)
{
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
@@ -447,19 +469,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
|| newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
nexthop->rifindex = newhop->ifindex;
}
- else if (newhop != nexthop)
- SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
- if (newhop->type == NEXTHOP_TYPE_IFINDEX)
- {
- ifp = if_lookup_by_index (newhop->ifindex);
- return (ifp && if_is_operative (ifp));
- }
- else if (newhop && newhop->type == NEXTHOP_TYPE_IFNAME)
- {
- ifp = if_lookup_by_name(newhop->ifname);
- return (ifp && if_is_operative (ifp));
- }
return 1;
}
return 0;
@@ -480,7 +490,6 @@ static int
nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
struct route_node *top)
{
- struct interface *ifp;
struct prefix_ipv6 p;
struct route_table *table;
struct route_node *rn;
@@ -538,36 +547,30 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
if (!newhop)
return 0; /* dead route */
- /* if scanning and the new match is different than the old one
- * then force the CHANGED flag.
- * FIXME (have this routine return NULL or nexhop instead)
- */
- if (!set && newhop != nexthop)
- SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
-
/* recursive route, remember index */
if (nexthop->type == NEXTHOP_TYPE_IPV6)
nexthop->ifindex = newhop->ifindex;
- switch(newhop->type)
+ if (nexthop_isactive (newhop))
{
- case NEXTHOP_TYPE_IFINDEX:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- ifp = if_lookup_by_index (newhop->ifindex);
- return (ifp && if_is_operative (ifp));
- case NEXTHOP_TYPE_IFNAME:
- case NEXTHOP_TYPE_IPV6_IFNAME:
- ifp = if_lookup_by_name(newhop->ifname);
- return (ifp && if_is_operative (ifp));
- default:
+ /* if new match is different then force the CHANGED flag.
+ * FIXME (have this routine return NULL or nexhop instead)
+ */
+ if (newhop != nexthop)
+ SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
return 1;
}
}
else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
{
for (newhop = match->nexthop; newhop; newhop = newhop->next)
- if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
+ if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
+ && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE)
+ && nexthop_isactive (newhop))
{
+ if (newhop != nexthop)
+ SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
+
if (set)
{
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
@@ -582,19 +585,6 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
|| newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
nexthop->rifindex = newhop->ifindex;
}
- else if (newhop != nexthop)
- SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
-
- if (newhop && newhop->type == NEXTHOP_TYPE_IFINDEX)
- {
- ifp = if_lookup_by_index (newhop->ifindex);
- return (ifp && if_is_operative (ifp));
- }
- else if (newhop && newhop->type == NEXTHOP_TYPE_IFNAME)
- {
- ifp = if_lookup_by_name(newhop->ifname);
- return (ifp && if_is_operative (ifp));
- }
return 1;
}
return 0;