summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2022-06-20 21:29:10 +0200
committerMaria Matejka <mq@ucw.cz>2022-06-24 15:49:08 +0200
commit050b4b4e5e6d4c05345bed2ec62c865258b4e7ee (patch)
tree9c3fd008f73ed26172f3aba1558aa993200e9c72
parentbecab5072d6d84d6f9c9402387a9e1c14dcc384d (diff)
Table export generalized to allow for exporting from non-tables
-rw-r--r--nest/proto.c6
-rw-r--r--nest/rt-table.c90
-rw-r--r--nest/rt.h17
3 files changed, 79 insertions, 34 deletions
diff --git a/nest/proto.c b/nest/proto.c
index 5e67d940..8513b9cb 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -498,7 +498,7 @@ channel_start_export(struct channel *c)
}
DBG("%s.%s: Channel start export req=%p\n", c->proto->name, c->name, &c->out_req);
- rt_request_export(c->table, &c->out_req);
+ rt_request_export(&c->table->exporter, &c->out_req);
}
static void
@@ -552,7 +552,7 @@ channel_export_stopped(struct rt_export_request *req)
{
c->refeeding = 1;
c->refeed_pending = 0;
- rt_request_export(c->table, req);
+ rt_request_export(&c->table->exporter, req);
return;
}
@@ -600,7 +600,7 @@ channel_schedule_reload(struct channel *c)
{
ASSERT(c->in_req.hook);
- rt_request_export(c->table, &c->reload_req);
+ rt_request_export(&c->table->exporter, &c->reload_req);
}
static void
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 975da363..14c80138 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -139,7 +139,6 @@ const char *rt_import_state_name_array[TIS_MAX] = {
const char *rt_export_state_name_array[TES_MAX] = {
[TES_DOWN] = "DOWN",
- [TES_HUNGRY] = "HUNGRY",
[TES_FEEDING] = "FEEDING",
[TES_READY] = "READY",
[TES_STOP] = "STOP"
@@ -1183,7 +1182,7 @@ rte_announce(rtable *tab, net *net, struct rte_storage *new, struct rte_storage
}
struct rt_export_hook *eh;
- WALK_LIST(eh, tab->exports)
+ WALK_LIST(eh, tab->exporter.hooks)
{
if (eh->export_state == TES_STOP)
continue;
@@ -1678,10 +1677,20 @@ rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filte
}
static void
+rt_table_export_done(struct rt_export_hook *hook)
+{
+ struct rt_exporter *re = hook->table;
+ struct rtable *tab = SKIP_BACK(struct rtable, exporter, re);
+
+ rt_unlock_table(tab);
+ DBG("Export hook %p in table %s finished uc=%u\n", hook, tab->name, tab->use_count);
+}
+
+static void
rt_export_stopped(void *data)
{
struct rt_export_hook *hook = data;
- rtable *tab = hook->table;
+ struct rt_exporter *tab = hook->table;
/* Unlist */
rem_node(&hook->n);
@@ -1689,14 +1698,13 @@ rt_export_stopped(void *data)
/* Reporting the channel as stopped. */
hook->stopped(hook->req);
+ /* Reporting the hook as finished. */
+ tab->done(hook);
+
/* Freeing the hook together with its coroutine. */
rfree(hook->pool);
- rt_unlock_table(tab);
-
- DBG("Export hook %p in table %s finished uc=%u\n", hook, tab->name, tab->use_count);
}
-
static inline void
rt_set_import_state(struct rt_import_hook *hook, u8 state)
{
@@ -1748,54 +1756,73 @@ rt_stop_import(struct rt_import_request *req, void (*stopped)(struct rt_import_r
hook->stopped = stopped;
}
-void
-rt_request_export(rtable *tab, struct rt_export_request *req)
+static struct rt_export_hook *
+rt_table_export_start(struct rt_exporter *re, struct rt_export_request *req)
{
+ rtable *tab = SKIP_BACK(rtable, exporter, re);
rt_lock_table(tab);
pool *p = rp_new(tab->rp, "Export hook");
- struct rt_export_hook *hook = req->hook = mb_allocz(p, sizeof(struct rt_export_hook));
+ struct rt_export_hook *hook = mb_allocz(p, sizeof(struct rt_export_hook));
hook->pool = p;
hook->lp = lp_new_default(p);
-
- hook->req = req;
- hook->table = tab;
/* stats zeroed by mb_allocz */
- rt_set_export_state(hook, TES_HUNGRY);
-
- hook->n = (node) {};
- add_tail(&tab->exports, &hook->n);
-
FIB_ITERATE_INIT(&hook->feed_fit, &tab->fib);
DBG("New export hook %p req %p in table %s uc=%u\n", hook, req, tab->name, tab->use_count);
+ hook->event = ev_new_init(p, rt_feed_channel, hook);
+
+ return hook;
+}
+
+void
+rt_request_export(struct rt_exporter *re, struct rt_export_request *req)
+{
+ struct rt_export_hook *hook = req->hook = re->start(re, req);
+
+ hook->req = req;
+ hook->table = re;
+
+ hook->n = (node) {};
+ add_tail(&re->hooks, &hook->n);
+
rt_set_export_state(hook, TES_FEEDING);
- hook->event = ev_new_init(p, rt_feed_channel, hook);
ev_schedule_work(hook->event);
}
+static void
+rt_table_export_stop(struct rt_export_hook *hook)
+{
+ rtable *tab = SKIP_BACK(rtable, exporter, hook->table);
+
+ if (hook->export_state == TES_FEEDING)
+ fit_get(&tab->fib, &hook->feed_fit);
+}
+
void
rt_stop_export(struct rt_export_request *req, void (*stopped)(struct rt_export_request *))
{
ASSERT_DIE(req->hook);
struct rt_export_hook *hook = req->hook;
- rtable *tab = hook->table;
-
- /* Stop feeding */
+ /* Cancel the feeder event */
ev_postpone(hook->event);
- if (hook->export_state == TES_FEEDING)
- fit_get(&tab->fib, &hook->feed_fit);
+ /* Stop feeding from the exporter */
+ hook->table->stop(hook);
+ /* Reset the event as the stopped event */
hook->event->hook = rt_export_stopped;
hook->stopped = stopped;
+ /* Update export state */
rt_set_export_state(hook, TES_STOP);
+
+ /* Run the stopped event */
ev_schedule(hook->event);
}
@@ -1948,7 +1975,7 @@ rt_dump_hooks(rtable *tab)
}
struct rt_export_hook *eh;
- WALK_LIST(eh, tab->exports)
+ WALK_LIST(eh, tab->exporter.hooks)
{
eh->req->dump_req(eh->req);
debug(" Export hook %p requested by %p:"
@@ -2252,10 +2279,17 @@ rt_setup(pool *pp, struct rtable_config *cf)
init_list(&t->flowspec_links);
+ t->exporter = (struct rt_exporter) {
+ .start = rt_table_export_start,
+ .stop = rt_table_export_stop,
+ .done = rt_table_export_done,
+ };
+ init_list(&t->exporter.hooks);
+
if (!(t->internal = cf->internal))
{
init_list(&t->imports);
- init_list(&t->exports);
+
hmap_init(&t->id_map, p, 1024);
hmap_set(&t->id_map, 0);
@@ -3138,7 +3172,9 @@ rt_feed_channel(void *data)
ASSERT(c->export_state == TES_FEEDING);
- FIB_ITERATE_START(&c->table->fib, fit, net, n)
+ rtable *tab = SKIP_BACK(rtable, exporter, c->table);
+
+ FIB_ITERATE_START(&tab->fib, fit, net, n)
{
if (max_feed <= 0)
{
diff --git a/nest/rt.h b/nest/rt.h
index d5e28cb6..0f5a5ba7 100644
--- a/nest/rt.h
+++ b/nest/rt.h
@@ -56,6 +56,16 @@ struct rtable_config {
btime max_settle_time; /* Maximum settle time for notifications */
};
+struct rt_export_hook;
+struct rt_export_request;
+
+struct rt_exporter {
+ list hooks; /* Registered route export hooks */
+ struct rt_export_hook *(*start)(struct rt_exporter *, struct rt_export_request *);
+ void (*stop)(struct rt_export_hook *);
+ void (*done)(struct rt_export_hook *);
+};
+
typedef struct rtable {
resource r;
node n; /* Node in list of all tables */
@@ -69,7 +79,7 @@ typedef struct rtable {
u32 rt_count; /* Number of routes in the table */
list imports; /* Registered route importers */
- list exports; /* Registered route exporters */
+ struct rt_exporter exporter; /* Exporter API structure */
struct hmap id_map;
struct hostcache *hostcache;
@@ -221,7 +231,7 @@ struct rt_export_request {
struct rt_export_hook {
node n;
- rtable *table; /* The connected table */
+ struct rt_exporter *table; /* The connected table */
pool *pool;
linpool *lp;
@@ -255,14 +265,13 @@ struct rt_export_hook {
#define TIS_MAX 6
#define TES_DOWN 0
-#define TES_HUNGRY 1
#define TES_FEEDING 2
#define TES_READY 3
#define TES_STOP 4
#define TES_MAX 5
void rt_request_import(rtable *tab, struct rt_import_request *req);
-void rt_request_export(rtable *tab, struct rt_export_request *req);
+void rt_request_export(struct rt_exporter *tab, struct rt_export_request *req);
void rt_stop_import(struct rt_import_request *, void (*stopped)(struct rt_import_request *));
void rt_stop_export(struct rt_export_request *, void (*stopped)(struct rt_export_request *));