diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2021-02-10 03:09:57 +0100 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2021-02-10 03:09:57 +0100 |
commit | 00b85905b9f5081eb2fce0ed79542085278e9f42 (patch) | |
tree | 964728bcef7dfb03136898a12e1ebbaccc13409c /nest/rt-table.c | |
parent | d06a875b042b608e61b2d5a2bb594641d3e1322f (diff) |
Nest: Automatic channel reloads based on RPKI changes
If there are roa_check() calls in channel filters, then the channel
subscribes to ROA table notifications, which are sent when ROA tables
are updated (subject to settle time) and trigger channel reload or
refeed.
Diffstat (limited to 'nest/rt-table.c')
-rw-r--r-- | nest/rt-table.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/nest/rt-table.c b/nest/rt-table.c index 298320d9..626c2fb8 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -36,6 +36,7 @@ #include "nest/iface.h" #include "lib/resource.h" #include "lib/event.h" +#include "lib/timer.h" #include "lib/string.h" #include "conf/conf.h" #include "filter/filter.h" @@ -60,6 +61,7 @@ static void rt_notify_hostcache(rtable *tab, net *net); static void rt_update_hostcache(rtable *tab); static void rt_next_hop_update(rtable *tab); static inline void rt_prune_table(rtable *tab); +static inline void rt_schedule_notify(rtable *tab); /* Like fib_route(), but skips empty net entries */ @@ -968,6 +970,8 @@ rte_announce(rtable *tab, uint type, net *net, rte *new, rte *old, rt_notify_hostcache(tab, net); } + rt_schedule_notify(tab); + struct channel *c; node *n; WALK_LIST2(c, n, tab->channels, table_node) { @@ -1211,6 +1215,9 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) else stats->imp_withdraws_ignored++; + if (old_ok || new_ok) + table->last_rt_change = current_time(); + skip_stats1: if (new) @@ -1792,6 +1799,78 @@ rt_event(void *ptr) rt_unlock_table(tab); } + +static inline btime +rt_settled_time(rtable *tab) +{ + ASSUME(tab->base_settle_time != 0); + + return MIN(tab->last_rt_change + tab->config->min_settle_time, + tab->base_settle_time + tab->config->max_settle_time); +} + +static void +rt_settle_timer(timer *t) +{ + rtable *tab = t->data; + + if (!tab->base_settle_time) + return; + + btime settled_time = rt_settled_time(tab); + if (current_time() < settled_time) + { + tm_set(tab->settle_timer, settled_time); + return; + } + + /* Settled */ + tab->base_settle_time = 0; + + struct rt_subscription *s; + WALK_LIST(s, tab->subscribers) + s->hook(s); +} + +static void +rt_kick_settle_timer(rtable *tab) +{ + tab->base_settle_time = current_time(); + + if (!tab->settle_timer) + tab->settle_timer = tm_new_init(rt_table_pool, rt_settle_timer, tab, 0, 0); + + if (!tm_active(tab->settle_timer)) + tm_set(tab->settle_timer, rt_settled_time(tab)); +} + +static inline void +rt_schedule_notify(rtable *tab) +{ + if (EMPTY_LIST(tab->subscribers)) + return; + + if (tab->base_settle_time) + return; + + rt_kick_settle_timer(tab); +} + +void +rt_subscribe(rtable *tab, struct rt_subscription *s) +{ + s->tab = tab; + rt_lock_table(tab); + add_tail(&tab->subscribers, &s->n); +} + +void +rt_unsubscribe(struct rt_subscription *s) +{ + rem_node(&s->n); + rt_unlock_table(s->tab); +} + void rt_setup(pool *p, rtable *t, struct rtable_config *cf) { @@ -1806,7 +1885,9 @@ rt_setup(pool *p, rtable *t, struct rtable_config *cf) hmap_set(&t->id_map, 0); t->rt_event = ev_new_init(p, rt_event, t); - t->gc_time = current_time(); + t->last_rt_change = t->gc_time = current_time(); + + init_list(&t->subscribers); } /** @@ -2204,6 +2285,8 @@ rt_new_table(struct symbol *s, uint addr_type) c->addr_type = addr_type; c->gc_max_ops = 1000; c->gc_min_time = 5; + c->min_settle_time = 1 S; + c->max_settle_time = 20 S; add_tail(&new_config->tables, &c->n); @@ -2250,6 +2333,7 @@ rt_unlock_table(rtable *r) fib_free(&r->fib); hmap_free(&r->id_map); rfree(r->rt_event); + rfree(r->settle_timer); mb_free(r); config_del_obstacle(conf); } |