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.
This commit is contained in:
parent
f4a0a64e02
commit
5996da6a1d
1 changed files with 38 additions and 8 deletions
|
@ -14,11 +14,20 @@
|
||||||
#include "nest/route.h"
|
#include "nest/route.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
|
#include "lib/event.h"
|
||||||
|
|
||||||
rtable master_table;
|
rtable master_table;
|
||||||
static slab *rte_slab;
|
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)
|
rte_init(struct fib_node *N)
|
||||||
{
|
{
|
||||||
net *n = (net *) N;
|
net *n = (net *) N;
|
||||||
|
@ -206,6 +215,8 @@ rte_update(net *net, struct proto *p, rte *new)
|
||||||
}
|
}
|
||||||
r->next = net->routes;
|
r->next = net->routes;
|
||||||
net->routes = r;
|
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 */
|
if (new) /* Link in the new non-optimal route */
|
||||||
|
@ -280,19 +291,32 @@ rt_dump_all(void)
|
||||||
rt_dump(&master_table);
|
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
|
void
|
||||||
rt_init(void)
|
rt_init(void)
|
||||||
{
|
{
|
||||||
rta_init();
|
rta_init();
|
||||||
|
rt_table_pool = rp_new(&root_pool, "Routing tables");
|
||||||
rt_setup(&master_table, "master");
|
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
|
void
|
||||||
rt_prune(rtable *tab)
|
rt_prune(rtable *tab)
|
||||||
{
|
{
|
||||||
struct fib_iterator fit;
|
struct fib_iterator fit;
|
||||||
int cnt = 0;
|
int rcnt = 0, rdel = 0, ncnt = 0, ndel = 0;
|
||||||
|
|
||||||
DBG("Pruning route table %s\n", tab->name);
|
DBG("Pruning route table %s\n", tab->name);
|
||||||
while (tab)
|
while (tab)
|
||||||
|
@ -303,17 +327,23 @@ rt_prune(rtable *tab)
|
||||||
{
|
{
|
||||||
net *n = (net *) f;
|
net *n = (net *) f;
|
||||||
rte *e;
|
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)
|
if (e->attrs->proto->core_state != FS_HAPPY)
|
||||||
{
|
{
|
||||||
FIB_ITERATE_PUT(&fit, f);
|
|
||||||
rte_discard(e);
|
rte_discard(e);
|
||||||
cnt++;
|
rdel++;
|
||||||
goto again;
|
|
||||||
}
|
}
|
||||||
|
if (!n->routes) /* Orphaned FIB entry? */
|
||||||
|
{
|
||||||
|
FIB_ITERATE_PUT(&fit, f);
|
||||||
|
fib_delete(&tab->fib, f);
|
||||||
|
ndel++;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FIB_ITERATE_END(f);
|
FIB_ITERATE_END(f);
|
||||||
tab = tab->sibling;
|
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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue