]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Implemented garbage collection of routing tables to delete orphaned network
authorMartin Mares <mj@ucw.cz>
Sat, 13 Feb 1999 21:29:01 +0000 (21:29 +0000)
committerMartin Mares <mj@ucw.cz>
Sat, 13 Feb 1999 21:29:01 +0000 (21:29 +0000)
nodes having no routes attached. Such cleanup must be done from event handler
since most functions manipulating the routing tables expect network entries
won't disappear from under their hands and it's also probably faster when
done asynchronously.

nest/rt-table.c

index 73b679d5af6dc9e2d54217cd466e2c256c53efd2..621a8353a6b89dce81ca9fd4ea1790469df8acab 100644 (file)
 #include "nest/route.h"
 #include "nest/protocol.h"
 #include "lib/resource.h"
+#include "lib/event.h"
 
 rtable master_table;
 static slab *rte_slab;
 
-void
+#define RT_GC_MIN_TIME 5               /* FIXME: Make configurable */
+#define RT_GC_MIN_COUNT 100
+
+static pool *rt_table_pool;
+static event *rt_gc_event;
+static bird_clock_t rt_last_gc;
+static int rt_gc_counter;
+
+static void
 rte_init(struct fib_node *N)
 {
   net *n = (net *) N;
@@ -206,6 +215,8 @@ rte_update(net *net, struct proto *p, rte *new)
                }
              r->next = net->routes;
              net->routes = r;
+             if (!r && rt_gc_counter++ >= RT_GC_MIN_COUNT && rt_last_gc + RT_GC_MIN_TIME <= now)
+               ev_schedule(rt_gc_event);
            }
        }
       if (new)                         /* Link in the new non-optimal route */
@@ -280,19 +291,32 @@ rt_dump_all(void)
   rt_dump(&master_table);
 }
 
+static void
+rt_gc(void *unused)
+{
+  DBG("Entered routing table garbage collector after %d seconds and %d deletes\n", (int)(now - rt_last_gc), rt_gc_counter);
+  rt_prune(&master_table);
+  rt_last_gc = now;
+  rt_gc_counter = 0;
+}
+
 void
 rt_init(void)
 {
   rta_init();
+  rt_table_pool = rp_new(&root_pool, "Routing tables");
   rt_setup(&master_table, "master");
-  rte_slab = sl_new(&root_pool, sizeof(rte));
+  rte_slab = sl_new(rt_table_pool, sizeof(rte));
+  rt_last_gc = now;
+  rt_gc_event = ev_new(rt_table_pool);
+  rt_gc_event->hook = rt_gc;
 }
 
 void
 rt_prune(rtable *tab)
 {
   struct fib_iterator fit;
-  int cnt = 0;
+  int rcnt = 0, rdel = 0, ncnt = 0, ndel = 0;
 
   DBG("Pruning route table %s\n", tab->name);
   while (tab)
@@ -303,17 +327,23 @@ rt_prune(rtable *tab)
        {
          net *n = (net *) f;
          rte *e;
-         for (e=n->routes; e; e=e->next)
+         ncnt++;
+         for (e=n->routes; e; e=e->next, rcnt++)
            if (e->attrs->proto->core_state != FS_HAPPY)
              {
-               FIB_ITERATE_PUT(&fit, f);
                rte_discard(e);
-               cnt++;
-               goto again;
+               rdel++;
              }
+         if (!n->routes)               /* Orphaned FIB entry? */
+           {
+             FIB_ITERATE_PUT(&fit, f);
+             fib_delete(&tab->fib, f);
+             ndel++;
+             goto again;
+           }
        }
       FIB_ITERATE_END(f);
       tab = tab->sibling;
     }
-  DBG("Pruned %d routes\n", cnt);
+  DBG("Pruned %d of %d routes and %d of %d networks\n", rcnt, rdel, ncnt, ndel);
 }