diff options
author | Andrew J. Schorr <ajschorr@alumni.princeton.edu> | 2006-11-28 20:50:46 +0100 |
---|---|---|
committer | Andrew J. Schorr <ajschorr@alumni.princeton.edu> | 2006-11-28 20:50:46 +0100 |
commit | 8d45210e7c9e221b519d975825cb83aea5ebe47e (patch) | |
tree | 62629c7693b24c3b4a8e37eed7abe51e5695417d /bgpd/bgp_route.c | |
parent | [ospfd] Fix bug in passive-interface default commands. (diff) | |
download | frr-8d45210e7c9e221b519d975825cb83aea5ebe47e.tar.xz frr-8d45210e7c9e221b519d975825cb83aea5ebe47e.zip |
[bgpd] Fix bug where a deleted route that was quickly re-added was being lost
2006-11-28 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* bgp_route.c: (bgp_info_restore) New function that undoes
the effects of a previous call to bgp_info_delete. This is
used when a route is deleted and quickly re-added before the
deletion has been processed.
(bgp_static_update_rsclient, bgp_static_update_main,
bgp_redistribute_add) Check whether a pre-existing route
has the BGP_INFO_REMOVED set, and, if so, we need to call
bgp_info_restore to resurrect it.
Diffstat (limited to '')
-rw-r--r-- | bgpd/bgp_route.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 3cae06e28..ce44842ee 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -192,6 +192,17 @@ bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri) UNSET_FLAG (ri->flags, BGP_INFO_VALID); } +/* undo the effects of a previous call to bgp_info_delete; typically + called when a route is deleted and then quickly re-added before the + deletion has been processed */ +static void +bgp_info_restore (struct bgp_node *rn, struct bgp_info *ri) +{ + bgp_info_unset_flag (rn, ri, BGP_INFO_REMOVED); + /* unset of previous already took care of pcount */ + SET_FLAG (ri->flags, BGP_INFO_VALID); +} + /* Adjust pcount as required */ static void bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri) @@ -3051,7 +3062,8 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, if (ri) { - if (attrhash_cmp (ri->attr, attr_new)) + if (attrhash_cmp (ri->attr, attr_new) && + !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { bgp_unlock_node (rn); bgp_attr_unintern (attr_new); @@ -3064,6 +3076,8 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); /* Rewrite BGP route information. */ + if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) + bgp_info_restore(rn, ri); bgp_attr_unintern (ri->attr); ri->attr = attr_new; ri->uptime = time (NULL); @@ -3158,7 +3172,8 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, if (ri) { - if (attrhash_cmp (ri->attr, attr_new)) + if (attrhash_cmp (ri->attr, attr_new) && + !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { bgp_unlock_node (rn); bgp_attr_unintern (attr_new); @@ -3171,7 +3186,10 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); /* Rewrite BGP route information. */ - bgp_aggregate_decrement (bgp, p, ri, afi, safi); + if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) + bgp_info_restore(rn, ri); + else + bgp_aggregate_decrement (bgp, p, ri, afi, safi); bgp_attr_unintern (ri->attr); ri->attr = attr_new; ri->uptime = time (NULL); @@ -4952,7 +4970,8 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, if (bi) { - if (attrhash_cmp (bi->attr, new_attr)) + if (attrhash_cmp (bi->attr, new_attr) && + !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { bgp_attr_unintern (new_attr); aspath_unintern (attr.aspath); @@ -4965,7 +4984,10 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, bgp_info_set_flag (bn, bi, BGP_INFO_ATTR_CHANGED); /* Rewrite BGP route information. */ - bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST); + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + bgp_info_restore(bn, bi); + else + bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST); bgp_attr_unintern (bi->attr); bi->attr = new_attr; bi->uptime = time (NULL); |