summaryrefslogtreecommitdiffstats
path: root/zebra/zebra_rib.c
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2008-07-24 14:19:47 -0700
committerStephen Hemminger <stephen.hemminger@vyatta.com>2008-07-24 14:19:47 -0700
commitd10d6c178e3c91e0dc73b6924099cb8fa416c279 (patch)
treec9574e61265d641f7c104fc1b7d0a47f61f80201 /zebra/zebra_rib.c
parent09523599d75b0161bbfff62bde436e4782a5864e (diff)
downloadquagga-d10d6c178e3c91e0dc73b6924099cb8fa416c279.tar.bz2
quagga-d10d6c178e3c91e0dc73b6924099cb8fa416c279.tar.xz
Fix management of route changes
Earlier changes to route management caused any route change to cause the whole RIB to marked as changed. This then causes route flapping. Fix by being more selective about what changes get flagged. Bugfix 3488
Diffstat (limited to 'zebra/zebra_rib.c')
-rw-r--r--zebra/zebra_rib.c72
1 files changed, 45 insertions, 27 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 145005d3..a511577b 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -381,11 +381,12 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
struct rib *match;
struct nexthop *newhop;
- if (nexthop->type == NEXTHOP_TYPE_IPV4)
- nexthop->ifindex = 0;
-
if (set)
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
+ {
+ UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
+ if (nexthop->type == NEXTHOP_TYPE_IPV4)
+ nexthop->ifindex = 0;
+ }
/* Make lookup prefix. */
memset (&p, 0, sizeof (struct prefix_ipv4));
@@ -411,7 +412,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
for (match = rn->info; match; match = match->next)
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
- continue;
+ continue;
if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
break;
}
@@ -436,17 +437,19 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
if (!newhop)
return 0; /* dead route */
- /* recursive route, remember index */
- if (set && nexthop->type == NEXTHOP_TYPE_IPV4)
- nexthop->ifindex = newhop->ifindex;
-
if (nexthop_isactive (newhop))
{
- /* 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);
+ if (set)
+ {
+ if (nexthop->type == NEXTHOP_TYPE_IPV4)
+ nexthop->ifindex = newhop->ifindex;
+ }
+ else
+ {
+ if (nexthop->ifindex != newhop->ifindex ||
+ CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
+ }
return 1;
}
}
@@ -458,9 +461,6 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
&& ! 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);
@@ -472,7 +472,14 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
|| newhop->type == NEXTHOP_TYPE_IFNAME
|| newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
nexthop->rifindex = newhop->ifindex;
+ if (nexthop->type == NEXTHOP_TYPE_IPV4)
+ nexthop->ifindex = newhop->ifindex;
}
+ else if (! CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)
+ || newhop->ifindex != nexthop->ifindex
+ || nexthop->gate.ipv4.s_addr != newhop->gate.ipv4.s_addr)
+ SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
+
return 1;
}
@@ -530,7 +537,7 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
for (match = rn->info; match; match = match->next)
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
- continue;
+ continue;
if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
break;
}
@@ -556,16 +563,22 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
return 0; /* dead route */
/* recursive route, remember index */
- if (set && nexthop->type == NEXTHOP_TYPE_IPV6)
+ if (nexthop->type == NEXTHOP_TYPE_IPV6)
nexthop->ifindex = newhop->ifindex;
if (nexthop_isactive (newhop))
{
- /* 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);
+ if (set)
+ {
+ if (nexthop->type == NEXTHOP_TYPE_IPV6)
+ nexthop->ifindex = newhop->ifindex;
+ }
+ else
+ {
+ if (nexthop->ifindex != newhop->ifindex ||
+ CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
+ }
return 1;
}
}
@@ -576,9 +589,6 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
&& ! 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);
@@ -592,7 +602,15 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
|| newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
|| newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
nexthop->rifindex = newhop->ifindex;
+ if (nexthop->type == NEXTHOP_TYPE_IPV6)
+ nexthop->ifindex = newhop->ifindex;
}
+ else if (! CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)
+ || newhop->ifindex != nexthop->ifindex
+ || !IPV6_ADDR_SAME(&nexthop->gate.ipv6,
+ &newhop->gate.ipv4))
+ SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
+
return 1;
}
return 0;