summaryrefslogtreecommitdiff
path: root/bgpd/bgp_fsm.c
diff options
context:
space:
mode:
authorPaul Jakma <paul.jakma@sun.com>2007-02-22 17:48:42 +0000
committerPaul Jakma <paul.jakma@sun.com>2007-02-22 17:48:42 +0000
commitf2c31acb6f97688af0f368211536829324145919 (patch)
tree6f9887992eeb0890fdf673f9c0794e7d1384edbb /bgpd/bgp_fsm.c
parent553bdfe376c49886cbdc2d306fea7b003bead31f (diff)
[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.
Diffstat (limited to 'bgpd/bgp_fsm.c')
-rw-r--r--bgpd/bgp_fsm.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index d704c297..db7e69af 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -409,10 +409,16 @@ bgp_fsm_change_status (struct peer *peer, int status)
{
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 @@ bgp_event (struct thread *thread)
{
/* 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);