summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>1999-02-13 22:29:01 +0100
committerMartin Mares <mj@ucw.cz>1999-02-13 22:29:01 +0100
commit5996da6a1d2eb11ac45d9d578618b9350e58593d (patch)
tree07086d8159ee100e27c8240f3f06261c7ad833ed
parentf4a0a64e02c13b2b467f9c1a29222f817b54ce2d (diff)
downloadbird-5996da6a1d2eb11ac45d9d578618b9350e58593d.tar
bird-5996da6a1d2eb11ac45d9d578618b9350e58593d.zip
Implemented garbage collection of routing tables to delete orphaned network
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.
-rw-r--r--nest/rt-table.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 73b679d..621a835 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -14,11 +14,20 @@
#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);
}