[bgpd] Peer delete can race with reconfig leading to crash
2007-02-22 Paul Jakma <paul.jakma@sun.com>
* bgp_fsm.c: (bgp_fsm_change_status) Handle state change into
clearing or greater here. Simpler.
(bgp_event) Clearing state change work moved to previous
* bgp_route.c: (bgp_clear_route_node) Clearing adj-in here
is too late, as it leaves a race between a peer being deleted
and an identical peer being configured before clearing
completes, leading to a crash.
Simplest fix is to clean peers Adj-in up-front, rather than
queueing such work.
(bgp_clear_route_table) Clear peer's Adj-In and Adj-Out
up-front here, rather than queueing such work.
Extensive comment added on the various bits of indexed data
that exist and how they need to be dealt with.
(bgp_clear_route) Update comment.
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index d704c29..db7e69a 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -409,10 +409,16 @@
{
bgp_dump_state (peer, peer->status, status);
+ /* Transition into Clearing or Deleted must /always/ clear all routes..
+ * (and must do so before actually changing into Deleted..
+ */
+ if (status >= Clearing)
+ bgp_clear_route_all (peer);
+
/* Preserve old status and change into new status. */
peer->ostatus = peer->status;
peer->status = status;
-
+
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("%s went from %s to %s",
peer->host,
@@ -1089,13 +1095,7 @@
{
/* If status is changed. */
if (next != peer->status)
- {
- /* Transition into Clearing must /always/ clear all routes.. */
- if (next == Clearing)
- bgp_clear_route_all (peer);
-
- bgp_fsm_change_status (peer, next);
- }
+ bgp_fsm_change_status (peer, next);
/* Make sure timer is set. */
bgp_timer_set (peer);