diff options
author | Lou Berger <lberger@labn.net> | 2016-01-12 13:41:57 -0500 |
---|---|---|
committer | Paul Jakma <paul.jakma@hpe.com> | 2016-02-26 14:11:43 +0000 |
commit | 82dd707988b7481e203cab058c92f0b3041dd558 (patch) | |
tree | 01923f2a1a5b0ca381e9eb7b093f467ca4cc942b /bgpd | |
parent | 13c378d96a57017f5995b2e0df46cfc31123f0e8 (diff) | |
download | quagga-82dd707988b7481e203cab058c92f0b3041dd558.tar.bz2 quagga-82dd707988b7481e203cab058c92f0b3041dd558.tar.xz |
bgpd: improve cleanup in bgp_delete()
Signed-off-by: Lou Berger <lberger@labn.net>
Diffstat (limited to 'bgpd')
-rw-r--r-- | bgpd/bgp_nexthop.c | 21 | ||||
-rw-r--r-- | bgpd/bgp_nexthop.h | 2 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 105 | ||||
-rw-r--r-- | bgpd/bgp_route.h | 3 | ||||
-rw-r--r-- | bgpd/bgp_routemap.c | 3 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 4 | ||||
-rw-r--r-- | bgpd/bgp_zebra.c | 10 | ||||
-rw-r--r-- | bgpd/bgp_zebra.h | 1 | ||||
-rw-r--r-- | bgpd/bgpd.c | 19 | ||||
-rw-r--r-- | bgpd/bgpd.h | 1 |
10 files changed, 149 insertions, 20 deletions
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index fa2f4882..d1c5c864 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -591,6 +591,14 @@ bgp_address_init (void) bgp_address_hash_cmp); } +void +bgp_address_destroy (void) +{ + hash_clean(bgp_address_hash, NULL); + hash_free(bgp_address_hash); + bgp_address_hash = NULL; +} + static void bgp_address_add (struct prefix *p) { @@ -1467,3 +1475,16 @@ bgp_scan_finish (void) bgp_connected_table[AFI_IP6] = NULL; #endif /* HAVE_IPV6 */ } + +void +bgp_scan_destroy (void) +{ + if (zlookup == NULL) + return; + THREAD_OFF(bgp_import_thread); + THREAD_OFF(bgp_scan_thread); + THREAD_OFF(zlookup->t_connect); + bgp_scan_finish(); + zclient_free (zlookup); + zlookup = NULL; +} diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h index c8aef58b..85c5a5d0 100644 --- a/bgpd/bgp_nexthop.h +++ b/bgpd/bgp_nexthop.h @@ -66,5 +66,7 @@ extern int bgp_config_write_scan_time (struct vty *); extern int bgp_nexthop_onlink (afi_t, struct attr *); extern int bgp_nexthop_self (struct attr *); extern void bgp_address_init (void); +extern void bgp_address_destroy (void); +extern void bgp_scan_destroy (void); #endif /* _QUAGGA_BGP_NEXTHOP_H */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index ff541e84..868fbe56 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3051,6 +3051,57 @@ bgp_clear_route_all (struct peer *peer) bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL); } +/* + * Finish freeing things when exiting + */ +static void +bgp_drain_workqueue_immediate (struct work_queue *wq) +{ + if (!wq) + return; + + if (!wq->thread) + { + /* + * no thread implies no queued items + */ + assert(!wq->items->count); + return; + } + + while (wq->items->count) + { + if (wq->thread) + thread_cancel(wq->thread); + work_queue_run(wq->thread); + } +} + +/* + * Special function to process clear node queue when bgpd is exiting + * and the thread scheduler is no longer running. + */ +void +bgp_peer_clear_node_queue_drain_immediate(struct peer *peer) +{ + if (!peer) + return; + + bgp_drain_workqueue_immediate(peer->clear_node_queue); +} + +/* + * The work queues are not specific to a BGP instance, but the + * items in them refer to BGP instances, so this should be called + * before each BGP instance is deleted. + */ +void +bgp_process_queues_drain_immediate(void) +{ + bgp_drain_workqueue_immediate(bm->process_main_queue); + bgp_drain_workqueue_immediate(bm->process_rsclient_queue); +} + void bgp_clear_adj_in (struct peer *peer, afi_t afi, safi_t safi) { @@ -3091,35 +3142,53 @@ bgp_clear_stale_route (struct peer *peer, afi_t afi, safi_t safi) } } +static void +bgp_cleanup_table(struct bgp_table *table, safi_t safi) +{ + struct bgp_node *rn; + struct bgp_info *ri; + struct bgp_info *next; + + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + for (ri = rn->info; ri; ri = next) + { + next = ri->next; + if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) + && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_NORMAL) + bgp_zebra_withdraw (&rn->p, ri, safi); + } +} + /* Delete all kernel routes. */ void bgp_cleanup_routes (void) { struct bgp *bgp; struct listnode *node, *nnode; - struct bgp_node *rn; - struct bgp_table *table; - struct bgp_info *ri; + afi_t afi; for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) { - table = bgp->rib[AFI_IP][SAFI_UNICAST]; - - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - for (ri = rn->info; ri; ri = ri->next) - if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_NORMAL) - bgp_zebra_withdraw (&rn->p, ri,SAFI_UNICAST); + for (afi = AFI_IP; afi < AFI_MAX; ++afi) + { + struct bgp_node *rn; - table = bgp->rib[AFI_IP6][SAFI_UNICAST]; + bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST); - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - for (ri = rn->info; ri; ri = ri->next) - if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_NORMAL) - bgp_zebra_withdraw (&rn->p, ri,SAFI_UNICAST); + /* + * VPN and ENCAP tables are two-level (RD is top level) + */ + for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn; + rn = bgp_route_next (rn)) + if (rn->info) + { + bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_MPLS_VPN); + bgp_table_finish ((struct bgp_table **)&(rn->info)); + rn->info = NULL; + bgp_unlock_node(rn); + } + } } } diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 0482c6fc..5a93b445 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -244,4 +244,7 @@ extern void route_vty_out (struct vty *, struct prefix *, struct bgp_info *, int extern void route_vty_out_tag (struct vty *, struct prefix *, struct bgp_info *, int, safi_t); extern void route_vty_out_tmp (struct vty *, struct prefix *, struct attr *, safi_t); +extern void bgp_peer_clear_node_queue_drain_immediate (struct peer *peer); +extern void bgp_process_queues_drain_immediate (void); + #endif /* _QUAGGA_BGP_ROUTE_H */ diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 7555ca77..b449cae0 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -2295,6 +2295,9 @@ bgp_route_map_update (const char *unused) struct bgp_node *bn; struct bgp_static *bgp_static; + if (bm->bgp == NULL) /* may be called during cleanup */ + return; + /* For neighbor route-map updates. */ for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) { diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 304da253..041a6a1f 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -9825,9 +9825,9 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &neighbor_unsuppress_map_cmd); install_element (BGP_IPV6M_NODE, &no_neighbor_unsuppress_map_cmd); install_element (BGP_VPNV4_NODE, &neighbor_unsuppress_map_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_unsuppress_map_cmd); + install_element (BGP_VPNV4_NODE, &no_neighbor_unsuppress_map_cmd); install_element (BGP_VPNV6_NODE, &neighbor_unsuppress_map_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_unsuppress_map_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_unsuppress_map_cmd); /* "neighbor maximum-prefix" commands. */ install_element (BGP_NODE, &neighbor_maximum_prefix_cmd); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 4a25aa91..1be4440a 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1081,3 +1081,13 @@ bgp_zebra_init (struct thread_master *master) bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE); } + +void +bgp_zebra_destroy(void) +{ + if (zclient == NULL) + return; + zclient_stop(zclient); + zclient_free(zclient); + zclient = NULL; +} diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 50f727df..ff9b375b 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -26,6 +26,7 @@ Boston, MA 02111-1307, USA. */ extern struct stream *bgp_nexthop_buf; extern void bgp_zebra_init (struct thread_master *master); +extern void bgp_zebra_destroy (void); extern int bgp_if_update_all (void); extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t, safi_t, int *); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index d9c32cee..636f5693 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1377,6 +1377,9 @@ peer_delete (struct peer *peer) } } + if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETING)) + bgp_peer_clear_node_queue_drain_immediate(peer); + peer_unlock (peer); /* initial reference */ return 0; @@ -2165,6 +2168,8 @@ bgp_delete (struct bgp *bgp) afi_t afi; int i; + SET_FLAG(bgp->flags, BGP_FLAG_DELETING); + THREAD_OFF (bgp->t_startup); /* Delete static route. */ @@ -2206,7 +2211,21 @@ bgp_delete (struct bgp *bgp) peer_delete(bgp->peer_self); bgp->peer_self = NULL; } + + /* + * Free pending deleted routes. Unfortunately, it also has to process + * all the pending activity for other instances of struct bgp. + * + * This call was added to achieve clean memory allocation at exit, + * for the sake of valgrind. + */ + bgp_process_queues_drain_immediate(); + + bgp_zebra_destroy(); + bgp_scan_destroy(); + bgp_address_destroy(); + /* Remove visibility via the master list - there may however still be * routes to be processed still referencing the struct bgp. */ diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 2c4fb209..0b3d449c 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -123,6 +123,7 @@ struct bgp #define BGP_FLAG_GRACEFUL_RESTART (1 << 12) #define BGP_FLAG_ASPATH_CONFED (1 << 13) #define BGP_FLAG_ASPATH_MULTIPATH_RELAX (1 << 14) +#define BGP_FLAG_DELETING (1 << 15) /* BGP Per AF flags */ u_int16_t af_flags[AFI_MAX][SAFI_MAX]; |