diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2008-07-24 14:19:47 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2008-07-24 14:19:47 -0700 |
commit | d10d6c178e3c91e0dc73b6924099cb8fa416c279 (patch) | |
tree | c9574e61265d641f7c104fc1b7d0a47f61f80201 | |
parent | 09523599d75b0161bbfff62bde436e4782a5864e (diff) | |
download | quagga-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
-rw-r--r-- | zebra/zebra_rib.c | 72 |
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; |