summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria Matejka <mq@jmq.cz>2021-12-01 21:33:38 +0000
committerMaria Matejka <mq@jmq.cz>2021-12-01 21:33:38 +0000
commit387b279f605c096c6ecb16d6608c700c533edb13 (patch)
tree9d422ff47aac79fdb6013bfaa596698bc1ba2df9
parent5f94d684d0ae07306002c319d9a2e921b28b13cf (diff)
Faster prune on table deletion
-rw-r--r--nest/route.h1
-rw-r--r--nest/rt-table.c57
2 files changed, 57 insertions, 1 deletions
diff --git a/nest/route.h b/nest/route.h
index 9f09ae3a..afd7a783 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -164,6 +164,7 @@ typedef struct rtable_private {
int use_count; /* Number of protocols using this table */
u32 rt_count; /* Number of routes in the table */
u32 rr_count; /* Number of running route refresh requests */
+ u32 imports_up; /* Number of imports in TIS_UP state */
list imports; /* Registered route importers */
list exports; /* Registered route exporters */
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 39b9f0ac..2c0f1c63 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -66,6 +66,7 @@ static void rt_notify_hostcache(rtable_private *tab, net *net);
static void rt_update_hostcache(void *tab);
static void rt_next_hop_update(void *tab);
static inline void rt_prune_table(void *tab);
+static void rt_fast_prune_check(rtable_private *tab);
static inline void rt_schedule_notify(rtable_private *tab);
static void rt_feed_channel(void *);
@@ -1708,6 +1709,8 @@ rt_export_stopped(void *data)
rp_free(hook->pool, tab->rp);
rt_unlock_table(tab);
+ rt_fast_prune_check(tab);
+
DBG("Export hook %p in table %s finished uc=%u\n", hook, tab->name, tab->use_count);
}
}
@@ -1740,6 +1743,8 @@ rt_request_import(rtable *t, struct rt_import_request *req)
rtable_private *tab = RT_PRIV(t);
rt_lock_table(tab);
+ ASSERT_DIE(!tab->delete);
+
struct rt_import_hook *hook = req->hook = mb_allocz(tab->rp, sizeof(struct rt_import_hook));
DBG("Lock table %s for import %p req=%p uc=%u\n", tab->name, hook, req, tab->use_count);
@@ -1756,6 +1761,7 @@ rt_request_import(rtable *t, struct rt_import_request *req)
hook->n = (node) {};
add_tail(&tab->imports, &hook->n);
+ tab->imports_up++;
RT_UNLOCK(t);
}
@@ -1770,7 +1776,11 @@ rt_stop_import(struct rt_import_request *req, event *stopped)
rt_schedule_prune(tab);
+ tab->imports_up--;
+ rt_fast_prune_check(tab);
+
rt_set_import_state(hook, TIS_STOP);
+
hook->stopped = stopped;
if (hook->stale_set < hook->stale_valid)
@@ -2041,6 +2051,22 @@ rt_schedule_prune(rtable_private *tab)
tab->prune_state |= 1;
}
+static int
+rt_fast_prune_ready(rtable_private *tab)
+{
+ return EMPTY_LIST(tab->pending_exports) && EMPTY_LIST(tab->exports) && !tab->imports_up;
+}
+
+static void
+rt_fast_prune_check(rtable_private *tab)
+{
+ if (tab->delete && rt_fast_prune_ready(tab))
+ {
+ tab->prune_state |= 1;
+ ev_send_loop(tab->loop, tab->prune_event);
+ }
+}
+
void
rt_export_used(rtable_private *tab)
{
@@ -2272,7 +2298,7 @@ rt_prune_table(void *data)
ASSERT_DIE(birdloop_inside(tab->loop));
struct fib_iterator *fit = &tab->prune_fit;
- int limit = 512;
+ int limit = tab->delete ? 16384 : 512;
struct rt_import_hook *ih;
node *n, *x;
@@ -2289,6 +2315,12 @@ rt_prune_table(void *data)
if (tab->prune_state == 1)
{
+ if (tab->delete && !rt_fast_prune_ready(tab))
+ {
+ rt_unlock_table(tab);
+ return;
+ }
+
/* Mark channels to flush */
WALK_LIST2(ih, n, tab->imports, n)
if (ih->import_state == TIS_STOP)
@@ -2308,6 +2340,27 @@ rt_prune_table(void *data)
again:
FIB_ITERATE_START(&tab->fib, fit, net, n)
{
+ if (tab->delete)
+ {
+ ASSERT_DIE(!n->first);
+
+ for (struct rte_storage *e = n->routes, *next; e; e = next)
+ {
+ next = e->next;
+
+ struct rt_import_request *req = e->rte.sender->req;
+ if (req->preimport)
+ req->preimport(req, NULL, &e->rte);
+
+ tab->rt_count--;
+ hmap_clear(&tab->id_map, e->rte.id);
+ rte_free(e, tab);
+ limit--;
+ }
+
+ n->routes = NULL;
+ }
+ else
rescan:
for (struct rte_storage *e=n->routes; e; e=e->next)
{
@@ -2547,6 +2600,8 @@ done:;
if (config->table_debug)
log(L_TRACE "%s: cork released", tab->name);
}
+
+ rt_fast_prune_check(tab);
}
void