summaryrefslogtreecommitdiff
path: root/bgpd/bgp_route.c
diff options
context:
space:
mode:
authorPaul Jakma <paul.jakma@sun.com>2006-05-04 08:08:15 +0000
committerPaul Jakma <paul.jakma@sun.com>2006-05-04 08:08:15 +0000
commit65ca75e0d1e7e440bf0d2a6a031d4148024c9d12 (patch)
tree71826429ce3985bf3900be4a965de238ac668e82 /bgpd/bgp_route.c
parenta3b6ea56a0add7d0972a66d96e1fbcf5461eecdb (diff)
[bgpd] Fix bug where FSM can stay hung forever in Idle/Clrng
2006-05-04 Paul Jakma <paul.jakma@sun.com> * bgp_route.c: (general) Fix logical bug in clearing, noted by Chris Caputo in [quagga-users 6728] - clearing depended on at least one route being added to workqueue, in order for workqueue completion function to restart FSM. However, if no routes are cleared, then the completion function never is called, it needs to be called manually if the workqueue didn't get scheduled. Finally, clearing is per-peer-session, not per AFI/SAFI, so the FSM synchronisation should be in bgp_clear_route_table. (bgp_clear_route_table) Wrong place for FSM/clearing synchronisation, move to.. (bgp_clear_route) FSM/clearing synchronisation should be here. If no routes were cleared, no workqueue scheduled, call the completion func to ensure FSM kicks off again.
Diffstat (limited to 'bgpd/bgp_route.c')
-rw-r--r--bgpd/bgp_route.c44
1 files changed, 25 insertions, 19 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index b49bea98..10c88697 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2555,6 +2555,25 @@ bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi,
/* If still no table => afi/safi isn't configured at all or smth. */
if (! table)
return;
+
+ for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+ {
+ if (rn->info == NULL)
+ continue;
+
+ bgp_lock_node (rn); /* unlocked: bgp_clear_node_queue_del */
+ work_queue_add (peer->clear_node_queue, rn);
+ }
+ return;
+}
+
+void
+bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi)
+{
+ struct bgp_node *rn;
+ struct bgp_table *table;
+ struct peer *rsclient;
+ struct listnode *node, *nnode;
if (peer->clear_node_queue == NULL)
bgp_clear_node_queue_init (peer);
@@ -2576,25 +2595,6 @@ bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi,
peer_lock (peer); /* bgp_clear_node_complete */
}
- for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
- {
- if (rn->info == NULL)
- continue;
-
- bgp_lock_node (rn); /* unlocked: bgp_clear_node_queue_del */
- work_queue_add (peer->clear_node_queue, rn);
- }
- return;
-}
-
-void
-bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi)
-{
- struct bgp_node *rn;
- struct bgp_table *table;
- struct peer *rsclient;
- struct listnode *node, *nnode;
-
if (safi != SAFI_MPLS_VPN)
bgp_clear_route_table (peer, afi, safi, NULL, NULL);
else
@@ -2608,6 +2608,12 @@ bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi)
if (CHECK_FLAG(rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
bgp_clear_route_table (peer, afi, safi, NULL, rsclient);
}
+
+ /* If no routes were cleared, nothing was added to workqueue, run the
+ * completion function now.
+ */
+ if (!peer->clear_node_queue->thread)
+ bgp_clear_node_complete (peer->clear_node_queue);
}
void