[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.
diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog
index 2b40456..c862949 100644
--- a/bgpd/ChangeLog
+++ b/bgpd/ChangeLog
@@ -1,3 +1,14 @@
+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.
+
2006-10-27 Paul Jakma <paul.jakma@sun.com>
* bgp_route.c: (bgp_table_stats) oops, u_intXX_t should be
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 3cae06e..ce44842 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -192,6 +192,17 @@
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 @@
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_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 @@
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_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 @@
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_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);