summaryrefslogtreecommitdiff
path: root/nest/rt-table.c
diff options
context:
space:
mode:
Diffstat (limited to 'nest/rt-table.c')
-rw-r--r--nest/rt-table.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 65fc142a..c1f3098b 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -119,6 +119,8 @@ static linpool *rte_update_pool;
list routing_tables;
list deleted_routing_tables;
+struct rt_cork rt_cork;
+
/* Data structures for export journal */
#define RT_PENDING_EXPORT_ITEMS (page_size - sizeof(struct rt_export_block)) / sizeof(struct rt_pending_export)
@@ -144,6 +146,9 @@ static void rt_feed_by_trie(void *);
static void rt_feed_equal(void *);
static void rt_feed_for(void *);
static uint rt_feed_net(struct rt_export_hook *c, net *n);
+static void rt_check_cork_low(rtable *tab);
+static void rt_check_cork_high(rtable *tab);
+static void rt_cork_release_hook(void *);
static inline void rt_export_used(struct rt_exporter *);
static void rt_export_cleanup(rtable *tab);
@@ -1371,6 +1376,8 @@ rte_announce(rtable *tab, net *net, struct rte_storage *new, struct rte_storage
if (tab->exporter.first == NULL)
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);
}
@@ -2667,6 +2674,8 @@ rt_setup(pool *pp, struct rtable_config *cf)
t->last_rt_change = t->gc_time = current_time();
t->exporter.next_seq = 1;
+ t->cork_threshold = cf->cork_threshold;
+
t->rl_pipe = (struct tbf) TBF_DEFAULT_LOG_LIMITS;
if (rt_is_flow(t))
@@ -2692,6 +2701,8 @@ rt_init(void)
rte_update_pool = lp_new_default(rt_table_pool);
init_list(&routing_tables);
init_list(&deleted_routing_tables);
+ ev_init_list(&rt_cork.queue, &main_birdloop, "Route cork release");
+ rt_cork.run = (event) { .hook = rt_cork_release_hook };
}
@@ -3000,6 +3011,8 @@ rt_export_cleanup(rtable *tab)
first = next;
}
+ rt_check_cork_low(tab);
+
done:;
struct rt_import_hook *ih; node *x;
_Bool imports_stopped = 0;
@@ -3030,6 +3043,16 @@ done:;
tm_stop(tab->exporter.export_timer);
}
+static void
+rt_cork_release_hook(void *data UNUSED)
+{
+ do synchronize_rcu();
+ while (
+ !atomic_load_explicit(&rt_cork.active, memory_order_acquire) &&
+ ev_run_list(&rt_cork.queue)
+ );
+}
+
/**
* rt_lock_trie - lock a prefix trie of a routing table
* @tab: routing table with prefix trie to be locked
@@ -3610,6 +3633,8 @@ rt_new_table(struct symbol *s, uint addr_type)
c->gc_period = (uint) -1; /* set in rt_postconfig() */
c->min_settle_time = 1 S;
c->max_settle_time = 20 S;
+ c->cork_threshold.low = 128;
+ c->cork_threshold.high = 512;
add_tail(&new_config->tables, &c->n);
@@ -3655,6 +3680,36 @@ rt_unlock_table(rtable *r)
}
}
+static void
+rt_check_cork_low(rtable *tab)
+{
+ if (!tab->cork_active)
+ return;
+
+ if (!tab->exporter.first || (tab->exporter.first->seq + tab->cork_threshold.low > tab->exporter.next_seq))
+ {
+ tab->cork_active = 0;
+ rt_cork_release();
+
+ if (config->table_debug)
+ log(L_TRACE "%s: Uncorked", tab->name);
+ }
+}
+
+static void
+rt_check_cork_high(rtable *tab)
+{
+ if (!tab->cork_active && tab->exporter.first && (tab->exporter.first->seq + tab->cork_threshold.high <= tab->exporter.next_seq))
+ {
+ tab->cork_active = 1;
+ rt_cork_acquire();
+
+ if (config->table_debug)
+ log(L_TRACE "%s: Corked", tab->name);
+ }
+}
+
+
static int
rt_reconfigure(rtable *tab, struct rtable_config *new, struct rtable_config *old)
{
@@ -3668,6 +3723,14 @@ rt_reconfigure(rtable *tab, struct rtable_config *new, struct rtable_config *old
tab->name = new->name;
tab->config = new;
+ tab->cork_threshold = new->cork_threshold;
+
+ if (new->cork_threshold.high != old->cork_threshold.high)
+ rt_check_cork_high(tab);
+
+ if (new->cork_threshold.low != old->cork_threshold.low)
+ rt_check_cork_low(tab);
+
return 1;
}