summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/ChangeLog15
-rw-r--r--bgpd/bgp_route.c44
2 files changed, 40 insertions, 19 deletions
diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog
index a0ba520c..5599801e 100644
--- a/bgpd/ChangeLog
+++ b/bgpd/ChangeLog
@@ -7,6 +7,21 @@
* bgp_packet.c: (bgp_{update,withdraw}_packet) Enable some
VPNv4 code which inexplicably was ifdef'd out. comments from
a tester on IRC suggest this fixes bug #210.
+ * 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.
2006-03-30 Paul Jakma <paul.jakma@sun.com>
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