From f2c31acb6f97688af0f368211536829324145919 Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Thu, 22 Feb 2007 17:48:42 +0000 Subject: [bgpd] Peer delete can race with reconfig leading to crash 2007-02-22 Paul Jakma * 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. --- bgpd/bgp_fsm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'bgpd/bgp_fsm.c') 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); -- cgit v1.2.1