]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: plug more memory leaks
authorRenato Westphal <renato@opensourcerouting.org>
Mon, 31 Oct 2016 17:15:16 +0000 (15:15 -0200)
committerRenato Westphal <renato@opensourcerouting.org>
Mon, 28 Nov 2016 18:18:35 +0000 (16:18 -0200)
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>
zebra/main.c
zebra/rib.h
zebra/zebra_rib.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zebra_rnh_null.c
zebra/zebra_vrf.c
zebra/zebra_vrf.h

index 1b41f8deffd318da50842dcb489552e3905ee0e4..4fea0104f51d8efe8c25a7c9c6cb1586d863b0de 100644 (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);
index c95a9ba0c30e332122f3a9b6b6917f336b684dbd..30929f1beb5c06135639cfccafc53b3df7732816 100644 (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);
 
index 54caeba8925e408837a1326d33a9e2208c1c1153..e29307be27d7b6247cf455d1e670d79dc4c98092 100644 (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)
index 7df759030d5fdf772bbe51955b7392a8f845adca..c6fc404bed3bbd547af24caecb2a10b52848691f 100644 (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
index 3a57ef1bc6bfab997c5b6b05658bc83596327306..4394fde4f3c366b2012878df6d9bc1d6efead8c4 100644 (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);
index eecb8519d56f0080af88e728eef50dd026233f4c..a97ae1a6129c0e28bcc75b475d9fabfa0fd73de3 100644 (file)
 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)
 {}
index 13010bfdcd177b36d150935c440c8c42174f89ca..b1c5e4dd35b6817eb123f643a875b14c64e35991 100644 (file)
 #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 ();
-
-  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();
+  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] =
+       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);
 
index 8c4f0b4a284c11bc64aa236a19ba9d19d482e91f..96d631d646e7d91ace47903c59fc660fc13f8754 100644 (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;