summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/rt-table.c119
-rw-r--r--nest/rt.h2
2 files changed, 65 insertions, 56 deletions
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 07933332..eb53eff7 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -130,7 +130,7 @@ struct rt_export_block {
static void rt_free_hostcache(rtable *tab);
static void rt_update_hostcache(void *tab);
-static void rt_next_hop_update(rtable *tab);
+static void rt_next_hop_update(void *tab);
static inline void rt_next_hop_resolve_rte(rte *r);
static inline void rt_flowspec_resolve_rte(rte *r, struct channel *c);
static inline void rt_prune_table(rtable *tab);
@@ -2309,14 +2309,26 @@ rt_dump_hooks_all(void)
static inline void
rt_schedule_nhu(rtable *tab)
{
- if (tab->nhu_state == NHU_CLEAN)
- ev_schedule(tab->rt_event);
-
- /* state change:
- * NHU_CLEAN -> NHU_SCHEDULED
- * NHU_RUNNING -> NHU_DIRTY
- */
- tab->nhu_state |= NHU_SCHEDULED;
+ if (tab->nhu_corked)
+ {
+ if (!(tab->nhu_corked & NHU_SCHEDULED))
+ {
+ tab->nhu_corked |= NHU_SCHEDULED;
+ rt_lock_table(tab);
+ }
+ }
+ else if (!(tab->nhu_state & NHU_SCHEDULED))
+ {
+ rt_trace(tab, D_EVENTS, "Scheduling NHU");
+ rt_lock_table(tab);
+
+ /* state change:
+ * NHU_CLEAN -> NHU_SCHEDULED
+ * NHU_RUNNING -> NHU_DIRTY
+ */
+ if ((tab->nhu_state |= NHU_SCHEDULED) == NHU_SCHEDULED)
+ ev_schedule(tab->nhu_event);
+ }
}
void
@@ -2353,24 +2365,6 @@ rt_event(void *ptr)
if (tab->export_used)
rt_export_cleanup(tab);
- if (tab->nhu_corked || tab->nhu_state && rt_cork_check(tab->uncork_event))
- {
- if (!tab->nhu_corked)
- {
- rt_trace(tab, D_STATES, "Next hop updater corked");
- if ((tab->nhu_state & NHU_RUNNING)
- && !EMPTY_LIST(tab->exporter.pending)
- && !tm_active(tab->exporter.export_timer))
- tm_start(tab->exporter.export_timer, tab->config->export_settle_time);
- }
-
- tab->nhu_corked |= tab->nhu_state;
- tab->nhu_state = 0;
- }
-
- if (tab->nhu_state)
- rt_next_hop_update(tab);
-
if (tab->prune_state)
rt_prune_table(tab);
@@ -2378,19 +2372,6 @@ rt_event(void *ptr)
}
static void
-rt_uncork_event(void *ptr)
-{
- rtable *tab = ptr;
-
- tab->nhu_state |= tab->nhu_corked;
- tab->nhu_corked = 0;
-
- rt_trace(tab, D_STATES, "Next hop updater uncorked");
-
- ev_schedule(tab->rt_event);
-}
-
-static void
rt_prune_timer(timer *t)
{
rtable *tab = t->data;
@@ -2619,7 +2600,7 @@ rt_setup(pool *pp, struct rtable_config *cf)
hmap_set(&t->id_map, 0);
t->rt_event = ev_new_init(p, rt_event, t);
- t->uncork_event = ev_new_init(p, rt_uncork_event, t);
+ t->nhu_event = ev_new_init(p, rt_next_hop_update, t);
t->prune_timer = tm_new_init(p, rt_prune_timer, t, 0, 0);
t->last_rt_change = t->gc_time = current_time();
@@ -3563,29 +3544,56 @@ rt_next_hop_update_net(rtable *tab, net *n)
}
static void
-rt_next_hop_update(rtable *tab)
+rt_next_hop_update(void *_tab)
{
- struct fib_iterator *fit = &tab->nhu_fit;
- int max_feed = 32;
+ rtable *tab = _tab;
+
+ /* If called from an uncork hook, reset the state */
+ if (tab->nhu_corked)
+ {
+ ASSERT_DIE(tab->nhu_state == 0);
+ tab->nhu_state = tab->nhu_corked;
+ tab->nhu_corked = 0;
+ rt_trace(tab, D_STATES, "Next hop updater uncorked");
+ }
+
+ if (!tab->nhu_state)
+ bug("Called NHU event for no reason in table %s", tab->name);
- if (tab->nhu_state == NHU_CLEAN)
+ /* Check corkedness */
+ if (rt_cork_check(tab->nhu_event))
+ {
+ rt_trace(tab, D_STATES, "Next hop updater corked");
+ if ((tab->nhu_state & NHU_RUNNING)
+ && !EMPTY_LIST(tab->exporter.pending)
+ && !tm_active(tab->exporter.export_timer))
+ tm_start(tab->exporter.export_timer, tab->config->export_settle_time);
+
+ tab->nhu_corked = tab->nhu_state;
+ tab->nhu_state = 0;
return;
+ }
+
+ struct fib_iterator *fit = &tab->nhu_fit;
+ int max_feed = 32;
+ /* Initialize a new run */
if (tab->nhu_state == NHU_SCHEDULED)
- {
- FIB_ITERATE_INIT(fit, &tab->fib);
- tab->nhu_state = NHU_RUNNING;
+ {
+ FIB_ITERATE_INIT(fit, &tab->fib);
+ tab->nhu_state = NHU_RUNNING;
- if (tab->flowspec_trie)
- rt_flowspec_reset_trie(tab);
- }
+ if (tab->flowspec_trie)
+ rt_flowspec_reset_trie(tab);
+ }
+ /* Walk the fib one net after another */
FIB_ITERATE_START(&tab->fib, fit, net, n)
{
if (max_feed <= 0)
{
FIB_ITERATE_PUT(fit);
- ev_schedule(tab->rt_event);
+ ev_schedule(tab->nhu_event);
return;
}
lp_state lps;
@@ -3595,6 +3603,7 @@ rt_next_hop_update(rtable *tab)
}
FIB_ITERATE_END;
+ /* Finished NHU, cleanup */
rt_trace(tab, D_EVENTS, "NHU done, scheduling export timer");
if (!tm_active(tab->exporter.export_timer))
@@ -3604,10 +3613,10 @@ rt_next_hop_update(rtable *tab)
* NHU_DIRTY -> NHU_SCHEDULED
* NHU_RUNNING -> NHU_CLEAN
*/
- tab->nhu_state &= 1;
+ if ((tab->nhu_state &= NHU_SCHEDULED) == NHU_SCHEDULED)
+ ev_schedule(tab->nhu_event);
- if (tab->nhu_state != NHU_CLEAN)
- ev_schedule(tab->rt_event);
+ rt_unlock_table(tab);
}
void
diff --git a/nest/rt.h b/nest/rt.h
index b94024fd..987a9ff8 100644
--- a/nest/rt.h
+++ b/nest/rt.h
@@ -117,7 +117,7 @@ typedef struct rtable {
* obstacle from this routing table.
*/
struct event *rt_event; /* Routing table event */
- struct event *uncork_event; /* Called when uncork happens */
+ struct event *nhu_event; /* Specific event for next hop update */
struct timer *prune_timer; /* Timer for periodic pruning / GC */
btime last_rt_change; /* Last time when route changed */
btime gc_time; /* Time of last GC */