Commit b9626ec6 authored by Martin Mareš's avatar Martin Mareš

Garbage collector events and counters are now per table and one day

they can be made configurable if it turns out to be useful.
parent 16c07e3d
......@@ -61,11 +61,7 @@ idval:
CF_ADDTO(conf, newtab)
newtab: TABLE SYM {
struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config));
struct symbol *s = $2;
cf_define_symbol(s, SYM_TABLE, c);
c->name = s->name;
add_tail(&new_config->tables, &c->n);
rt_new_table($2);
}
;
......
......@@ -113,6 +113,8 @@ struct rtable_config {
char *name;
struct rtable *table;
struct proto_config *krt_attached; /* Kernel syncer attached to this table */
int gc_max_ops; /* Maximum number of operations before GC is run */
int gc_min_time; /* Minimum time between two consecutive GC runs */
};
typedef struct rtable {
......@@ -122,10 +124,14 @@ typedef struct rtable {
list hooks; /* List of announcement hooks */
int pipe_busy; /* Pipe loop detection */
int use_count; /* Number of protocols using this table */
struct rtable_config *config; /* Configuration of this table */
struct config *deleted; /* Table doesn't exist in current configuration,
* delete as soon as use_count becomes 0 and remove
* obstacle from this routing table.
*/
struct event *gc_event; /* Garbage collector event */
int gc_counter; /* Number of operations since last GC */
bird_clock_t gc_time; /* Time of last GC */
} rtable;
typedef struct network {
......@@ -179,7 +185,7 @@ void rt_preconfig(struct config *);
void rt_commit(struct config *new, struct config *old);
void rt_lock_table(rtable *);
void rt_unlock_table(rtable *);
void rt_setup(pool *, rtable *, char *);
void rt_setup(pool *, rtable *, char *, struct rtable_config *);
static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_find(&tab->fib, &addr, len); }
static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); }
rte *rte_find(net *net, struct proto *p);
......@@ -195,6 +201,7 @@ void rt_dump_all(void);
void rt_feed_baby(struct proto *p);
void rt_prune(rtable *tab);
void rt_prune_all(void);
struct rtable_config *rt_new_table(struct symbol *s);
struct rt_show_data {
ip_addr prefix;
......
......@@ -24,14 +24,8 @@
static slab *rte_slab;
static linpool *rte_update_pool;
#define RT_GC_MIN_TIME 5 /* FIXME: Make configurable */
#define RT_GC_MIN_COUNT 100
static pool *rt_table_pool;
static list routing_tables;
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)
......@@ -42,15 +36,6 @@ rte_init(struct fib_node *N)
n->routes = NULL;
}
void
rt_setup(pool *p, rtable *t, char *name)
{
bzero(t, sizeof(*t));
fib_init(&t->fib, p, sizeof(net), 0, rte_init);
t->name = name;
init_list(&t->hooks);
}
rte *
rte_find(net *net, struct proto *p)
{
......@@ -277,8 +262,10 @@ rte_recalculate(rtable *table, net *net, struct proto *p, rte *new, ea_list *tmp
}
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 (!r &&
table->gc_counter++ >= table->config->gc_max_ops &&
table->gc_time + table->config->gc_min_time <= now)
ev_schedule(table->gc_event);
}
}
if (new) /* Link in the new non-optimal route */
......@@ -406,17 +393,32 @@ rt_dump_all(void)
}
static int
rt_gc(void *unused)
rt_gc(void *tab)
{
rtable *t;
rtable *t = tab;
DBG("Entered routing table garbage collector after %d seconds and %d deletes\n", (int)(now - rt_last_gc), rt_gc_counter);
rt_prune_all();
rt_last_gc = now;
rt_gc_counter = 0;
DBG("Entered routing table garbage collector for %s after %d seconds and %d deletes\n",
t->name, (int)(now - t->gc_time), t->gc_counter);
rt_prune(t);
return 0;
}
void
rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf)
{
bzero(t, sizeof(*t));
fib_init(&t->fib, p, sizeof(net), 0, rte_init);
t->name = name;
t->config = cf;
init_list(&t->hooks);
if (cf)
{
t->gc_event = ev_new(p);
t->gc_event->hook = rt_gc;
t->gc_event->data = t;
}
}
void
rt_init(void)
{
......@@ -424,9 +426,6 @@ rt_init(void)
rt_table_pool = rp_new(&root_pool, "Routing tables");
rte_update_pool = lp_new(rt_table_pool, 4080);
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;
init_list(&routing_tables);
}
......@@ -462,6 +461,8 @@ again:
}
FIB_ITERATE_END(f);
DBG("Pruned %d of %d routes and %d of %d networks\n", rcnt, rdel, ncnt, ndel);
tab->gc_counter = 0;
tab->gc_time = now;
}
void
......@@ -473,17 +474,26 @@ rt_prune_all(void)
rt_prune(t);
}
struct rtable_config *
rt_new_table(struct symbol *s)
{
struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config));
cf_define_symbol(s, SYM_TABLE, c);
c->name = s->name;
add_tail(&new_config->tables, &c->n);
c->gc_max_ops = 100;
c->gc_min_time = 5;
return c;
}
void
rt_preconfig(struct config *c)
{
struct symbol *s = cf_find_symbol("master");
struct rtable_config *r = cfg_allocz(sizeof(struct rtable_config));
cf_define_symbol(s, SYM_TABLE, r);
r->name = s->name;
init_list(&c->tables);
add_tail(&c->tables, &r->n);
c->master_rtc = r;
c->master_rtc = rt_new_table(s);
}
void
......@@ -526,6 +536,7 @@ rt_commit(struct config *new, struct config *old)
r = sym->def;
r->table = ot;
ot->name = r->name;
ot->config = r;
}
else
{
......@@ -544,7 +555,7 @@ rt_commit(struct config *new, struct config *old)
{
rtable *t = mb_alloc(rt_table_pool, sizeof(struct rtable));
DBG("\t%s: created\n", r->name);
rt_setup(rt_table_pool, t, r->name);
rt_setup(rt_table_pool, t, r->name, r);
add_tail(&routing_tables, &t->n);
r->table = t;
}
......
......@@ -385,7 +385,7 @@ static void
krt_learn_init(struct krt_proto *p)
{
if (KRT_CF->learn)
rt_setup(p->p.pool, &p->krt_table, "Inherited");
rt_setup(p->p.pool, &p->krt_table, "Inherited", NULL);
}
static void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment