summaryrefslogtreecommitdiff
path: root/nest/rt-table.c
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2022-09-01 11:17:35 +0200
committerMaria Matejka <mq@ucw.cz>2022-09-01 22:22:31 +0200
commit66ccdc2a0c8f10263679e7fac37c1db1adf64b4f (patch)
tree3940cfc08f7f364aebef839fd808eb2ecb66dc46 /nest/rt-table.c
parentdd786e338c4adccee7077c8ecfaf56df2831ee4c (diff)
Added an indirection to the export announcement routine
There are performance reasons for this, mostly that we don't want to ping the table service routine with every import.
Diffstat (limited to 'nest/rt-table.c')
-rw-r--r--nest/rt-table.c72
1 files changed, 50 insertions, 22 deletions
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 2fa736e2..3188ddf8 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -1354,9 +1354,6 @@ rte_announce(rtable *tab, net *net, struct rte_storage *new, struct rte_storage
tab->exporter.first = rpe;
rt_check_cork_high(tab);
-
- if (!tm_active(tab->exporter.export_timer))
- tm_start(tab->exporter.export_timer, tab->config->export_settle_time);
}
static struct rt_pending_export *
@@ -1410,6 +1407,9 @@ rt_announce_exports(timer *tm)
{
rtable *tab = tm->data;
+ if (EMPTY_LIST(tab->exporter.pending))
+ return;
+
struct rt_export_hook *c; node *n;
WALK_LIST2(c, n, tab->exporter.hooks, n)
{
@@ -1420,6 +1420,28 @@ rt_announce_exports(timer *tm)
}
}
+static void
+rt_import_announce_exports(void *_hook)
+{
+ struct rt_import_hook *hook = _hook;
+ rtable *tab = hook->table;
+
+
+ if (hook->import_state == TIS_CLEARED)
+ {
+ rt_trace(tab, D_EVENTS, "Hook %s stopped", hook->req->name);
+ hook->stopped(hook->req);
+ rem_node(&hook->n);
+ mb_free(hook);
+ rt_unlock_table(tab);
+ }
+
+ rt_trace(tab, D_EVENTS, "Announcing exports after imports from %s", hook->req->name);
+
+ if (!tm_active(tab->exporter.export_timer))
+ tm_start(tab->exporter.export_timer, tab->config->export_settle_time);
+}
+
static struct rt_pending_export *
rt_last_export(struct rt_exporter *tab)
{
@@ -1535,7 +1557,7 @@ rte_same(rte *x, rte *y)
static inline int rte_is_ok(rte *e) { return e && !rte_is_filtered(e); }
-static void
+static int
rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *src)
{
struct rt_import_request *req = c->req;
@@ -1588,7 +1610,7 @@ rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *sr
/* We need to free the already stored route here before returning */
rte_free(new_stored);
- return;
+ return 0;
}
*before_old = (*before_old)->next;
@@ -1598,7 +1620,7 @@ rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *sr
if (!old && !new)
{
stats->withdraws_ignored++;
- return;
+ return 0;
}
/* If rejected by import limit, we need to pretend there is no route */
@@ -1734,14 +1756,7 @@ rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *sr
rte_announce(table, net, new_stored, old_stored,
net->routes, old_best_stored);
-#if 0
- /* Enable and reimplement these callbacks if anybody wants to use them */
- if (old_ok && p->rte_remove)
- p->rte_remove(net, old);
- if (new_ok && p->rte_insert)
- p->rte_insert(net, &new_stored->rte);
-#endif
-
+ return 1;
}
int
@@ -1869,8 +1884,9 @@ rte_import(struct rt_import_request *req, const net_addr *n, rte *new, struct rt
return;
}
- /* And recalculate the best route */
- rte_recalculate(hook, nn, new, src);
+ /* Recalculate the best route */
+ if (rte_recalculate(hook, nn, new, src))
+ ev_send(req->list, &hook->announce_event);
}
/* Check rtable for best route to given net whether it would be exported do p */
@@ -1951,14 +1967,14 @@ rt_request_import(rtable *tab, struct rt_import_request *req)
struct rt_import_hook *hook = req->hook = mb_allocz(tab->rp, sizeof(struct rt_import_hook));
+ hook->announce_event = (event) { .hook = rt_import_announce_exports, .data = hook };
+
DBG("Lock table %s for import %p req=%p uc=%u\n", tab->name, hook, req, tab->use_count);
hook->req = req;
hook->table = tab;
rt_set_import_state(hook, TIS_UP);
-
- hook->n = (node) {};
add_tail(&tab->imports, &hook->n);
}
@@ -2313,7 +2329,13 @@ rt_event(void *ptr)
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;
@@ -2699,6 +2721,10 @@ again:
}
FIB_ITERATE_END;
+ rt_trace(tab, D_EVENTS, "Prune done, scheduling export timer");
+ if (!tm_active(tab->exporter.export_timer))
+ tm_start(tab->exporter.export_timer, tab->config->export_settle_time);
+
#ifdef DEBUGGING
fib_check(&tab->fib);
#endif
@@ -2912,10 +2938,7 @@ done:;
if (!first || (first->seq >= ih->flush_seq))
{
ih->import_state = TIS_CLEARED;
- ih->stopped(ih->req);
- rem_node(&ih->n);
- mb_free(ih);
- rt_unlock_table(tab);
+ ev_send(ih->req->list, &ih->announce_event);
}
if ((tab->gc_counter += want_prune) >= tab->config->gc_threshold)
@@ -3497,6 +3520,11 @@ rt_next_hop_update(rtable *tab)
}
FIB_ITERATE_END;
+ rt_trace(tab, D_EVENTS, "NHU done, scheduling export timer");
+
+ if (!tm_active(tab->exporter.export_timer))
+ tm_start(tab->exporter.export_timer, tab->config->export_settle_time);
+
/* State change:
* NHU_DIRTY -> NHU_SCHEDULED
* NHU_RUNNING -> NHU_CLEAN