zebra: plug more memory leaks

Try to free all memory explicitly on exit. This should help to detect
new memory leaks in the future with tools like valgrind.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2016-10-31 15:15:16 -02:00
parent 2414ffe50c
commit 5a8dfcd891
8 changed files with 191 additions and 68 deletions

View File

@ -182,17 +182,27 @@ sighup (void)
static void
sigint (void)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;
struct zebra_ns *zns;
zlog_notice ("Terminating on signal");
if (!retain_mode)
rib_close ();
#ifdef HAVE_IRDP
irdp_finish();
#endif
zebra_ptm_finish();
list_delete_all_node (zebrad.client_list);
if (retain_mode)
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
{
zvrf = vrf->info;
if (zvrf)
SET_FLAG (zvrf->flags, ZEBRA_VRF_RETAIN);
}
vrf_terminate ();
zns = zebra_ns_lookup (NS_DEFAULT);
zebra_ns_disable (0, (void **)&zns);
@ -204,6 +214,10 @@ sigint (void)
vty_terminate ();
zprivs_terminate (&zserv_privs);
list_delete (zebrad.client_list);
work_queue_free (zebrad.ribq);
if (zebrad.lsp_process_q)
work_queue_free (zebrad.lsp_process_q);
meta_queue_free (zebrad.mq);
thread_master_free (zebrad.master);
if (zlog_default)
closezlog (zlog_default);

View File

@ -366,13 +366,14 @@ extern void rib_update (vrf_id_t, rib_update_event_t);
extern void rib_weed_tables (void);
extern void rib_sweep_route (void);
extern void rib_close_table (struct route_table *);
extern void rib_close (void);
extern void rib_init (void);
extern unsigned long rib_score_proto (u_char proto, u_short instance);
extern void rib_queue_add (struct route_node *rn);
extern void meta_queue_free (struct meta_queue *mq);
extern struct route_table *rib_table_ipv6;
extern void rib_unlink (struct route_node *, struct rib *);
extern int rib_gc_dest (struct route_node *rn);
extern struct route_table *rib_tables_iter_next (rib_tables_iter_t *iter);

View File

@ -1304,8 +1304,6 @@ rib_uninstall (struct route_node *rn, struct rib *rib)
}
}
static void rib_unlink (struct route_node *, struct rib *);
/*
* rib_can_delete_dest
*
@ -2216,6 +2214,17 @@ meta_queue_new (void)
return new;
}
void
meta_queue_free (struct meta_queue *mq)
{
unsigned i;
for (i = 0; i < MQ_SIZE; i++)
list_delete (mq->subq[i]);
XFREE (MTYPE_WORK_QUEUE, mq);
}
/* initialise zebra rib work queue */
static void
rib_queue_init (struct zebra_t *zebra)
@ -2351,7 +2360,7 @@ rib_addnode (struct route_node *rn, struct rib *rib, int process)
* rib_gc_dest() at some point. This allows a rib_dest_t that is no
* longer required to be deleted.
*/
static void
void
rib_unlink (struct route_node *rn, struct rib *rib)
{
rib_dest_t *dest;
@ -3153,43 +3162,6 @@ rib_close_table (struct route_table *table)
}
}
/* Close all RIB tables. */
void
rib_close (void)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;
struct listnode *node;
struct interface *ifp;
u_int32_t table_id;
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
{
if ((zvrf = vrf->info) != NULL)
{
rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
}
for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp))
if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
}
/* If we do multiple tables per vrf, need to move this to loop above */
zvrf = vrf_info_lookup (VRF_DEFAULT);
for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++)
{
if (zvrf->other_table[AFI_IP][table_id])
rib_close_table (zvrf->other_table[AFI_IP][table_id]);
if (zvrf->other_table[AFI_IP6][table_id])
rib_close_table (zvrf->other_table[AFI_IP6][table_id]);
}
zebra_mpls_close_tables(zvrf);
}
/* Routing information base initialize. */
void
rib_init (void)

View File

@ -163,6 +163,16 @@ zebra_lookup_rnh (struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
return (rn->info);
}
void
zebra_free_rnh (struct rnh *rnh)
{
rnh->flags |= ZEBRA_NHT_DELETED;
list_free (rnh->client_list);
list_free (rnh->zebra_static_route_list);
free_state (rnh->vrf_id, rnh->state, rnh->node);
XFREE (MTYPE_RNH, rnh);
}
void
zebra_delete_rnh (struct rnh *rnh, rnh_type_t type)
{
@ -178,14 +188,9 @@ zebra_delete_rnh (struct rnh *rnh, rnh_type_t type)
rnh->vrf_id, rnh_str(rnh, buf, sizeof (buf)), type);
}
rnh->flags |= ZEBRA_NHT_DELETED;
list_free(rnh->client_list);
list_free(rnh->zebra_static_route_list);
free_state(rnh->vrf_id, rnh->state, rn);
XFREE(MTYPE_RNH, rn->info);
zebra_free_rnh (rnh);
rn->info = NULL;
route_unlock_node (rn);
return;
}
void

View File

@ -59,6 +59,7 @@ extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid,
rnh_type_t type);
extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
rnh_type_t type);
extern void zebra_free_rnh (struct rnh *rnh);
extern void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type);
extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
vrf_id_t vrfid);

View File

@ -26,6 +26,10 @@
int zebra_rnh_ip_default_route = 0;
int zebra_rnh_ipv6_default_route = 0;
void
zebra_free_rnh (struct rnh *rnh)
{}
void zebra_evaluate_rnh (vrf_id_t vrfid, int family, int force, rnh_type_t type,
struct prefix *p)
{}

View File

@ -30,9 +30,11 @@
#include "zebra/zserv.h"
#include "zebra/rib.h"
#include "zebra/zebra_vrf.h"
#include "zebra/zebra_rnh.h"
#include "zebra/router-id.h"
#include "zebra/zebra_memory.h"
#include "zebra/zebra_static.h"
#include "zebra/interface.h"
#include "zebra/zebra_mpls.h"
extern struct zebra_t zebrad;
@ -214,18 +216,84 @@ static int
zebra_vrf_delete (struct vrf *vrf)
{
struct zebra_vrf *zvrf = vrf->info;
struct route_table *table;
u_int32_t table_id;
afi_t afi;
safi_t safi;
unsigned i;
assert (zvrf);
zebra_vrf_delete_update (zvrf);
rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
/* uninstall everything */
if (! CHECK_FLAG (zvrf->flags, ZEBRA_VRF_RETAIN))
{
struct listnode *node;
struct interface *ifp;
for (afi = AFI_IP; afi <= AFI_IP6; afi++)
{
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
rib_close_table (zvrf->table[afi][safi]);
if (vrf->vrf_id == VRF_DEFAULT)
for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++)
if (zvrf->other_table[afi][table_id])
rib_close_table (zvrf->other_table[afi][table_id]);
}
zebra_mpls_close_tables (zvrf);
for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp))
if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp);
}
/* clean-up work queues */
for (i = 0; i < MQ_SIZE; i++)
{
struct listnode *lnode, *nnode;
struct route_node *rnode;
rib_dest_t *dest;
for (ALL_LIST_ELEMENTS (zebrad.mq->subq[i], lnode, nnode, rnode))
{
dest = rib_dest_from_rnode (rnode);
if (dest && rib_dest_vrf (dest) == zvrf)
{
route_unlock_node (rnode);
list_delete_node (zebrad.mq->subq[i], lnode);
}
}
}
/* release allocated memory */
for (afi = AFI_IP; afi <= AFI_IP6; afi++)
{
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
{
table = zvrf->table[afi][safi];
XFREE (MTYPE_RIB_TABLE_INFO, table->info);
route_table_finish (table);
table = zvrf->stable[afi][safi];
route_table_finish (table);
}
for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++)
if (zvrf->other_table[afi][table_id])
{
table = zvrf->other_table[afi][table_id];
XFREE (MTYPE_RIB_TABLE_INFO, table->info);
route_table_finish (table);
}
route_table_finish (zvrf->rnh_table[afi]);
route_table_finish (zvrf->import_check_table[afi]);
}
list_delete_all_node (zvrf->rid_all_sorted_list);
list_delete_all_node (zvrf->rid_lo_sorted_list);
vrf->vrf_id = VRF_UNKNOWN;
XFREE (MTYPE_ZEBRA_VRF, zvrf);
vrf->info = NULL;
return 0;
@ -257,6 +325,62 @@ zebra_vrf_table_with_table_id (afi_t afi, safi_t safi,
return table;
}
static void
zebra_rtable_node_destroy (route_table_delegate_t *delegate,
struct route_table *table, struct route_node *node)
{
struct rib *rib, *next;
RNODE_FOREACH_RIB_SAFE (node, rib, next)
rib_unlink (node, rib);
if (node->info)
XFREE (MTYPE_RIB_DEST, node->info);
route_node_destroy (delegate, table, node);
}
static void
zebra_stable_node_destroy (route_table_delegate_t *delegate,
struct route_table *table, struct route_node *node)
{
struct static_route *si, *next;
if (node->info)
for (si = node->info; si; si = next)
{
next = si->next;
XFREE (MTYPE_STATIC_ROUTE, si);
}
route_node_destroy (delegate, table, node);
}
static void
zebra_rnhtable_node_destroy (route_table_delegate_t *delegate,
struct route_table *table, struct route_node *node)
{
if (node->info)
zebra_free_rnh (node->info);
route_node_destroy (delegate, table, node);
}
route_table_delegate_t zebra_rtable_delegate = {
.create_node = route_node_create,
.destroy_node = zebra_rtable_node_destroy
};
route_table_delegate_t zebra_stable_delegate = {
.create_node = route_node_create,
.destroy_node = zebra_stable_node_destroy
};
route_table_delegate_t zebra_rnhtable_delegate = {
.create_node = route_node_create,
.destroy_node = zebra_rnhtable_node_destroy
};
/*
* Create a routing table for the specific AFI/SAFI in the given VRF.
*/
@ -268,7 +392,7 @@ zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
assert (!zvrf->table[afi][safi]);
table = route_table_init ();
table = route_table_init_with_delegate (&zebra_rtable_delegate);
zvrf->table[afi][safi] = table;
info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
@ -283,24 +407,25 @@ struct zebra_vrf *
zebra_vrf_alloc (void)
{
struct zebra_vrf *zvrf;
afi_t afi;
safi_t safi;
zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
/* Allocate routing table and static table. */
zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
for (afi = AFI_IP; afi <= AFI_IP6; afi++)
{
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
{
zebra_vrf_table_create (zvrf, afi, safi);
zvrf->stable[afi][safi] =
route_table_init_with_delegate (&zebra_stable_delegate);
}
zvrf->rnh_table[AFI_IP] = route_table_init();
zvrf->rnh_table[AFI_IP6] = route_table_init();
zvrf->import_check_table[AFI_IP] = route_table_init();
zvrf->import_check_table[AFI_IP6] = route_table_init();
zvrf->rnh_table[afi] =
route_table_init_with_delegate (&zebra_rnhtable_delegate);
zvrf->import_check_table[afi] =
route_table_init_with_delegate (&zebra_rnhtable_delegate);
}
zebra_mpls_init_tables (zvrf);

View File

@ -40,6 +40,7 @@ struct zebra_vrf
/* Flags. */
u_int16_t flags;
#define ZEBRA_VRF_RIB_SCHEDULED (1 << 0)
#define ZEBRA_VRF_RETAIN (2 << 0)
u_int32_t table_id;