0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 02:01:55 +00:00

Refactoring: back-merged export data structures

Table-specific structures inheriting commons are too crazy.
This commit is contained in:
Maria Matejka 2024-02-09 17:02:44 +01:00 committed by Katerina Kubecova
parent dea78a5c51
commit 22f58ac316
4 changed files with 125 additions and 148 deletions

View File

@ -772,8 +772,9 @@ r_args:
} }
| r_args IMPORT TABLE channel_arg { | r_args IMPORT TABLE channel_arg {
if (!($4->in_keep & RIK_PREFILTER)) cf_error("No import table in channel %s.%s", $4->proto->name, $4->name); if (!($4->in_keep & RIK_PREFILTER)) cf_error("No import table in channel %s.%s", $4->proto->name, $4->name);
RT_LOCKED($4->table, tab) struct rt_show_data_rtable *rsdr = rt_show_add_table($$, $4->table);
rt_show_add_exporter($$, &tab->exporter.e, "import")->prefilter = $4; rsdr->name = "import";
rsdr->prefilter = $4;
$$->tables_defined_by = RSD_TDB_DIRECT; $$->tables_defined_by = RSD_TDB_DIRECT;
} }
| r_args FILTER filter { | r_args FILTER filter {

View File

@ -87,10 +87,9 @@ struct rt_exporter {
pool *rp; pool *rp;
list hooks; /* Registered route export hooks */ list hooks; /* Registered route export hooks */
uint addr_type; /* Type of address data exported (NET_*) */ uint addr_type; /* Type of address data exported (NET_*) */
};
struct rt_table_exporter { /* Table-specific */
struct rt_exporter e;
list pending; /* List of packed struct rt_pending_export */ list pending; /* List of packed struct rt_pending_export */
struct rt_pending_export *first; /* First export to announce */ struct rt_pending_export *first; /* First export to announce */
@ -129,7 +128,7 @@ struct rtable_private {
u32 debug; /* Debugging flags (D_*) */ u32 debug; /* Debugging flags (D_*) */
list imports; /* Registered route importers */ list imports; /* Registered route importers */
struct rt_table_exporter exporter; /* Exporter API structure */ struct rt_exporter exporter; /* Exporter API structure */
struct hmap id_map; struct hmap id_map;
struct hostcache *hostcache; struct hostcache *hostcache;
@ -384,16 +383,8 @@ struct rt_export_hook {
struct bmap seq_map; /* Keep track which exports were already procesed */ struct bmap seq_map; /* Keep track which exports were already procesed */
void (*stopped)(struct rt_export_request *); /* Stored callback when export is stopped */ void (*stopped)(struct rt_export_request *); /* Stored callback when export is stopped */
};
struct rt_table_export_hook { /* Table-specific items */
union {
struct rt_export_hook h;
struct { /* Overriding the parent structure beginning */
node _n;
struct rt_table_exporter *table;
};
};
union { union {
u32 feed_index; /* Routing table iterator used during feeding */ u32 feed_index; /* Routing table iterator used during feeding */
@ -413,7 +404,6 @@ struct rt_table_export_hook {
u8 refeed_pending; /* Refeeding and another refeed is scheduled */ u8 refeed_pending; /* Refeeding and another refeed is scheduled */
u8 feed_type; /* Which feeding method is used (TFT_*, see below) */ u8 feed_type; /* Which feeding method is used (TFT_*, see below) */
}; };
#define TIS_DOWN 0 #define TIS_DOWN 0
@ -659,7 +649,7 @@ extern const int rt_default_ecmp;
struct rt_show_data_rtable { struct rt_show_data_rtable {
node n; node n;
const char *name; const char *name;
struct rt_exporter *table; rtable *table;
struct channel *export_channel; struct channel *export_channel;
struct channel *prefilter; struct channel *prefilter;
struct krt_proto *kernel; struct krt_proto *kernel;

View File

@ -313,7 +313,7 @@ rt_show_cont(struct rt_show_data *d)
if (d->tables_defined_by & RSD_TDB_SET) if (d->tables_defined_by & RSD_TDB_SET)
rt_show_table(d); rt_show_table(d);
rt_request_export_other(d->tab->table, &d->req); rt_request_export(d->tab->table, &d->req);
} }
static void static void
@ -355,22 +355,13 @@ rt_show_export_stopped(struct rt_export_request *req)
rt_show_done(d); rt_show_done(d);
} }
struct rt_show_data_rtable *
rt_show_add_exporter(struct rt_show_data *d, struct rt_exporter *t, const char *name)
{
struct rt_show_data_rtable *tab = cfg_allocz(sizeof(struct rt_show_data_rtable));
tab->table = t;
tab->name = name;
add_tail(&(d->tables), &(tab->n));
return tab;
}
struct rt_show_data_rtable * struct rt_show_data_rtable *
rt_show_add_table(struct rt_show_data *d, rtable *t) rt_show_add_table(struct rt_show_data *d, rtable *t)
{ {
struct rt_show_data_rtable *rsdr; struct rt_show_data_rtable *rsdr = cfg_allocz(sizeof(struct rt_show_data_rtable));
RT_LOCKED(t, tp) rsdr->table = t;
rsdr = rt_show_add_exporter(d, &tp->exporter.e, t->name); rsdr->name = t->name;
add_tail(&(d->tables), &(rsdr->n));
struct proto_config *krt = t->config->krt_attached; struct proto_config *krt = t->config->krt_attached;
if (krt) if (krt)
@ -432,7 +423,7 @@ rt_show_prepare_tables(struct rt_show_data *d)
/* Ensure there is defined export_channel for each table */ /* Ensure there is defined export_channel for each table */
if (d->export_mode) if (d->export_mode)
{ {
rtable *rt = SKIP_BACK(rtable, priv.exporter.e, tab->table); rtable *rt = tab->table;
if (!tab->export_channel && d->export_channel && if (!tab->export_channel && d->export_channel &&
(rt == d->export_channel->table)) (rt == d->export_channel->table))
tab->export_channel = d->export_channel; tab->export_channel = d->export_channel;

View File

@ -155,7 +155,7 @@ static void rt_cork_release_hook(void *);
static void rt_shutdown(void *); static void rt_shutdown(void *);
static void rt_delete(void *); static void rt_delete(void *);
static void rt_export_used(struct rt_table_exporter *, const char *, const char *); static void rt_export_used(struct rt_exporter *, const char *, const char *);
static void rt_export_cleanup(struct rtable_private *tab); static void rt_export_cleanup(struct rtable_private *tab);
int rte_same(const rte *x, const rte *y); int rte_same(const rte *x, const rte *y);
@ -1102,10 +1102,9 @@ rpe_next(struct rt_pending_export *rpe, struct rte_src *src)
static struct rt_pending_export * rt_next_export_fast(struct rt_pending_export *last); static struct rt_pending_export * rt_next_export_fast(struct rt_pending_export *last);
static int static int
rte_export(struct rt_table_export_hook *th, struct rt_pending_export *rpe) rte_export(struct rt_export_hook *hook, struct rt_pending_export *rpe)
{ {
rtable *tab = RT_PUB(SKIP_BACK(struct rtable_private, exporter, th->table)); rtable *tab = RT_PUB(SKIP_BACK(struct rtable_private, exporter, hook->table));
struct rt_export_hook *hook = &th->h;
if (bmap_test(&hook->seq_map, rpe->seq)) if (bmap_test(&hook->seq_map, rpe->seq))
goto ignore; /* Seen already */ goto ignore; /* Seen already */
@ -1152,14 +1151,14 @@ rte_export(struct rt_table_export_hook *th, struct rt_pending_export *rpe)
ignore: ignore:
/* Get the next export if exists */ /* Get the next export if exists */
th->rpe_next = rt_next_export_fast(rpe); hook->rpe_next = rt_next_export_fast(rpe);
/* The last block may be available to free */ /* The last block may be available to free */
int used = (PAGE_HEAD(th->rpe_next) != PAGE_HEAD(rpe)); int used = (PAGE_HEAD(hook->rpe_next) != PAGE_HEAD(rpe));
/* Releasing this export for cleanup routine */ /* Releasing this export for cleanup routine */
DBG("store hook=%p last_export=%p seq=%lu\n", hook, rpe, rpe->seq); DBG("store hook=%p last_export=%p seq=%lu\n", hook, rpe, rpe->seq);
atomic_store_explicit(&th->last_export, rpe, memory_order_release); atomic_store_explicit(&hook->last_export, rpe, memory_order_release);
return used; return used;
} }
@ -1213,7 +1212,7 @@ rte_announce(struct rtable_private *tab, const struct netindex *i, net *net, con
if (old_best_valid) if (old_best_valid)
old_best->sender->stats.pref--; old_best->sender->stats.pref--;
if (EMPTY_LIST(tab->exporter.e.hooks) && EMPTY_LIST(tab->exporter.pending)) if (EMPTY_LIST(tab->exporter.hooks) && EMPTY_LIST(tab->exporter.pending))
{ {
/* No export hook and no pending exports to cleanup. We may free the route immediately. */ /* No export hook and no pending exports to cleanup. We may free the route immediately. */
if (!old) if (!old)
@ -1328,7 +1327,7 @@ rt_next_export_fast(struct rt_pending_export *last)
} }
static struct rt_pending_export * static struct rt_pending_export *
rt_next_export(struct rt_table_export_hook *hook, struct rt_table_exporter *tab) rt_next_export(struct rt_export_hook *hook, struct rt_exporter *tab)
{ {
ASSERT_DIE(RT_IS_LOCKED(SKIP_BACK(struct rtable_private, exporter, tab))); ASSERT_DIE(RT_IS_LOCKED(SKIP_BACK(struct rtable_private, exporter, tab)));
@ -1357,7 +1356,7 @@ rt_announce_exports(struct settle *s)
if (!EMPTY_LIST(tab->exporter.pending)) if (!EMPTY_LIST(tab->exporter.pending))
{ {
struct rt_export_hook *c; node *n; struct rt_export_hook *c; node *n;
WALK_LIST2(c, n, tab->exporter.e.hooks, n) WALK_LIST2(c, n, tab->exporter.hooks, n)
{ {
if (atomic_load_explicit(&c->export_state, memory_order_acquire) != TES_READY) if (atomic_load_explicit(&c->export_state, memory_order_acquire) != TES_READY)
continue; continue;
@ -1402,7 +1401,7 @@ rt_import_announce_exports(void *_hook)
} }
static struct rt_pending_export * static struct rt_pending_export *
rt_last_export(struct rt_table_exporter *tab) rt_last_export(struct rt_exporter *tab)
{ {
struct rt_pending_export *rpe = NULL; struct rt_pending_export *rpe = NULL;
@ -1422,10 +1421,10 @@ rt_last_export(struct rt_table_exporter *tab)
static void static void
rt_export_hook(void *_data) rt_export_hook(void *_data)
{ {
struct rt_table_export_hook *c = _data; struct rt_export_hook *c = _data;
rtable *tab = SKIP_BACK(rtable, priv.exporter, c->table); rtable *tab = SKIP_BACK(rtable, priv.exporter, c->table);
ASSERT_DIE(atomic_load_explicit(&c->h.export_state, memory_order_relaxed) == TES_READY); ASSERT_DIE(atomic_load_explicit(&c->export_state, memory_order_relaxed) == TES_READY);
if (!c->rpe_next) if (!c->rpe_next)
RT_LOCKED(tab, tp) RT_LOCKED(tab, tp)
@ -1434,7 +1433,7 @@ rt_export_hook(void *_data)
if (!c->rpe_next) if (!c->rpe_next)
{ {
rt_export_used(c->table, c->h.req->name, "done exporting"); rt_export_used(c->table, c->req->name, "done exporting");
return; return;
} }
} }
@ -1457,9 +1456,9 @@ rt_export_hook(void *_data)
if (used) if (used)
RT_LOCKED(tab, t) RT_LOCKED(tab, t)
if (no_next || t->cork_active) if (no_next || t->cork_active)
rt_export_used(c->table, c->h.req->name, no_next ? "finished export bulk" : "cork active"); rt_export_used(c->table, c->req->name, no_next ? "finished export bulk" : "cork active");
rt_send_export_event(&c->h); rt_send_export_event(c);
} }
@ -1922,9 +1921,9 @@ rt_examine(rtable *tp, net_addr *a, struct channel *c, const struct filter *filt
static void static void
rt_table_export_done(void *hh) rt_table_export_done(void *hh)
{ {
struct rt_table_export_hook *hook = hh; struct rt_export_hook *hook = hh;
struct rt_export_request *req = hook->h.req; struct rt_export_request *req = hook->req;
void (*stopped)(struct rt_export_request *) = hook->h.stopped; void (*stopped)(struct rt_export_request *) = hook->stopped;
rtable *t = SKIP_BACK(rtable, priv.exporter, hook->table); rtable *t = SKIP_BACK(rtable, priv.exporter, hook->table);
RT_LOCKED(t, tab) RT_LOCKED(t, tab)
@ -1932,10 +1931,10 @@ rt_table_export_done(void *hh)
DBG("Export hook %p in table %s finished uc=%u\n", hook, tab->name, tab->use_count); DBG("Export hook %p in table %s finished uc=%u\n", hook, tab->name, tab->use_count);
/* Drop pending exports */ /* Drop pending exports */
rt_export_used(&tab->exporter, hook->h.req->name, "stopped"); rt_export_used(&tab->exporter, hook->req->name, "stopped");
/* Do the common code; this frees the hook */ /* Do the common code; this frees the hook */
rt_export_stopped(&hook->h); rt_export_stopped(hook);
} }
/* Report the channel as stopped. */ /* Report the channel as stopped. */
@ -2030,30 +2029,30 @@ rt_stop_import(struct rt_import_request *req, void (*stopped)(struct rt_import_r
} }
} }
static void rt_table_export_start_feed(struct rtable_private *tab, struct rt_table_export_hook *hook); static void rt_table_export_start_feed(struct rtable_private *tab, struct rt_export_hook *hook);
static void static void
rt_table_export_uncork(void *_hook) rt_table_export_uncork(void *_hook)
{ {
ASSERT_DIE(birdloop_inside(&main_birdloop)); ASSERT_DIE(birdloop_inside(&main_birdloop));
struct rt_table_export_hook *hook = _hook; struct rt_export_hook *hook = _hook;
struct birdloop *loop = hook->h.req->list->loop; struct birdloop *loop = hook->req->list->loop;
if (loop != &main_birdloop) if (loop != &main_birdloop)
birdloop_enter(loop); birdloop_enter(loop);
u8 state; u8 state;
switch (state = atomic_load_explicit(&hook->h.export_state, memory_order_relaxed)) switch (state = atomic_load_explicit(&hook->export_state, memory_order_relaxed))
{ {
case TES_HUNGRY: case TES_HUNGRY:
RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, hook->table)), tab) RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, hook->table)), tab)
if ((state = atomic_load_explicit(&hook->h.export_state, memory_order_relaxed)) == TES_HUNGRY) if ((state = atomic_load_explicit(&hook->export_state, memory_order_relaxed)) == TES_HUNGRY)
rt_table_export_start_feed(tab, hook); rt_table_export_start_feed(tab, hook);
if (state != TES_STOP) if (state != TES_STOP)
break; break;
/* fall through */ /* fall through */
case TES_STOP: case TES_STOP:
rt_stop_export_common(&hook->h); rt_stop_export_common(hook);
break; break;
default: default:
bug("Uncorking a table export in a strange state: %u", state); bug("Uncorking a table export in a strange state: %u", state);
@ -2066,29 +2065,29 @@ rt_table_export_uncork(void *_hook)
static void static void
rt_table_export_start_locked(struct rtable_private *tab, struct rt_export_request *req) rt_table_export_start_locked(struct rtable_private *tab, struct rt_export_request *req)
{ {
struct rt_exporter *re = &tab->exporter.e; struct rt_exporter *re = &tab->exporter;
rt_lock_table(tab); rt_lock_table(tab);
req->hook = rt_alloc_export(re, req->pool, sizeof(struct rt_table_export_hook)); req->hook = rt_alloc_export(re, req->pool, sizeof(struct rt_export_hook));
req->hook->req = req; req->hook->req = req;
struct rt_table_export_hook *hook = SKIP_BACK(struct rt_table_export_hook, h, req->hook); struct rt_export_hook *hook = req->hook;
hook->h.event = (event) { hook->event = (event) {
.hook = rt_table_export_uncork, .hook = rt_table_export_uncork,
.data = hook, .data = hook,
}; };
if (rt_cork_check(&hook->h.event)) if (rt_cork_check(&hook->event))
rt_set_export_state(&hook->h, BIT32_ALL(TES_DOWN), TES_HUNGRY); rt_set_export_state(hook, BIT32_ALL(TES_DOWN), TES_HUNGRY);
else else
rt_table_export_start_feed(tab, hook); rt_table_export_start_feed(tab, hook);
} }
static void static void
rt_table_export_start_feed(struct rtable_private *tab, struct rt_table_export_hook *hook) rt_table_export_start_feed(struct rtable_private *tab, struct rt_export_hook *hook)
{ {
struct rt_exporter *re = &tab->exporter.e; struct rt_exporter *re = &tab->exporter;
struct rt_export_request *req = hook->h.req; struct rt_export_request *req = hook->req;
/* stats zeroed by mb_allocz */ /* stats zeroed by mb_allocz */
switch (req->prefilter.mode) switch (req->prefilter.mode)
@ -2096,10 +2095,10 @@ rt_table_export_start_feed(struct rtable_private *tab, struct rt_table_export_ho
case TE_ADDR_IN: case TE_ADDR_IN:
if (tab->trie && net_val_match(tab->addr_type, NB_IP)) if (tab->trie && net_val_match(tab->addr_type, NB_IP))
{ {
hook->walk_state = mb_allocz(hook->h.pool, sizeof (struct f_trie_walk_state)); hook->walk_state = mb_allocz(hook->pool, sizeof (struct f_trie_walk_state));
hook->walk_lock = rt_lock_trie(tab); hook->walk_lock = rt_lock_trie(tab);
trie_walk_init(hook->walk_state, tab->trie, req->prefilter.addr); trie_walk_init(hook->walk_state, tab->trie, req->prefilter.addr);
hook->h.event.hook = rt_feed_by_trie; hook->event.hook = rt_feed_by_trie;
hook->walk_last.type = 0; hook->walk_last.type = 0;
break; break;
} }
@ -2108,15 +2107,15 @@ rt_table_export_start_feed(struct rtable_private *tab, struct rt_table_export_ho
case TE_ADDR_TRIE: case TE_ADDR_TRIE:
case TE_ADDR_HOOK: case TE_ADDR_HOOK:
hook->feed_index = 0; hook->feed_index = 0;
hook->h.event.hook = rt_feed_by_fib; hook->event.hook = rt_feed_by_fib;
break; break;
case TE_ADDR_EQUAL: case TE_ADDR_EQUAL:
hook->h.event.hook = rt_feed_equal; hook->event.hook = rt_feed_equal;
break; break;
case TE_ADDR_FOR: case TE_ADDR_FOR:
hook->h.event.hook = rt_feed_for; hook->event.hook = rt_feed_for;
break; break;
default: default:
@ -2135,7 +2134,7 @@ rt_table_export_start_feed(struct rtable_private *tab, struct rt_table_export_ho
static void static void
rt_table_export_start(struct rt_exporter *re, struct rt_export_request *req) rt_table_export_start(struct rt_exporter *re, struct rt_export_request *req)
{ {
RT_LOCKED(SKIP_BACK(rtable, priv.exporter.e, re), tab) RT_LOCKED(SKIP_BACK(rtable, priv.exporter, re), tab)
rt_table_export_start_locked(tab, req); rt_table_export_start_locked(tab, req);
} }
@ -2180,19 +2179,18 @@ rt_init_export(struct rt_exporter *re UNUSED, struct rt_export_hook *hook)
} }
static int static int
rt_table_export_stop_locked(struct rt_export_hook *hh) rt_table_export_stop_locked(struct rt_export_hook *hook)
{ {
struct rt_table_export_hook *hook = SKIP_BACK(struct rt_table_export_hook, h, hh);
struct rtable_private *tab = SKIP_BACK(struct rtable_private, exporter, hook->table); struct rtable_private *tab = SKIP_BACK(struct rtable_private, exporter, hook->table);
/* Update export state, get old */ /* Update export state, get old */
switch (rt_set_export_state(hh, BIT32_ALL(TES_HUNGRY, TES_FEEDING, TES_READY), TES_STOP)) switch (rt_set_export_state(hook, BIT32_ALL(TES_HUNGRY, TES_FEEDING, TES_READY), TES_STOP))
{ {
case TES_HUNGRY: case TES_HUNGRY:
rt_trace(tab, D_EVENTS, "Stopping export hook %s must wait for uncorking", hook->h.req->name); rt_trace(tab, D_EVENTS, "Stopping export hook %s must wait for uncorking", hook->req->name);
return 0; return 0;
case TES_FEEDING: case TES_FEEDING:
switch (hh->req->prefilter.mode) switch (hook->req->prefilter.mode)
{ {
case TE_ADDR_IN: case TE_ADDR_IN:
if (hook->walk_lock) if (hook->walk_lock)
@ -2214,28 +2212,27 @@ rt_table_export_stop_locked(struct rt_export_hook *hh)
break; break;
case TES_STOP: case TES_STOP:
bug("Tried to repeatedly stop the same export hook %s", hook->h.req->name); bug("Tried to repeatedly stop the same export hook %s", hook->req->name);
} }
rt_trace(tab, D_EVENTS, "Stopping export hook %s right now", hook->h.req->name); rt_trace(tab, D_EVENTS, "Stopping export hook %s right now", hook->req->name);
return 1; return 1;
} }
static void static void
rt_table_export_stop(struct rt_export_hook *hh) rt_table_export_stop(struct rt_export_hook *hook)
{ {
struct rt_table_export_hook *hook = SKIP_BACK(struct rt_table_export_hook, h, hh);
int ok = 0; int ok = 0;
rtable *t = SKIP_BACK(rtable, priv.exporter, hook->table); rtable *t = SKIP_BACK(rtable, priv.exporter, hook->table);
if (RT_IS_LOCKED(t)) if (RT_IS_LOCKED(t))
ok = rt_table_export_stop_locked(hh); ok = rt_table_export_stop_locked(hook);
else else
RT_LOCKED(t, tab) RT_LOCKED(t, tab)
ok = rt_table_export_stop_locked(hh); ok = rt_table_export_stop_locked(hook);
if (ok) if (ok)
rt_stop_export_common(hh); rt_stop_export_common(hook);
} }
void void
@ -2436,14 +2433,14 @@ rt_dump_hooks(rtable *tp)
ih->last_state_change, ih->import_state, ih->stopped); ih->last_state_change, ih->import_state, ih->stopped);
} }
struct rt_table_export_hook *eh; struct rt_export_hook *eh;
WALK_LIST(eh, tab->exporter.e.hooks) WALK_LIST(eh, tab->exporter.hooks)
{ {
eh->h.req->dump_req(eh->h.req); eh->req->dump_req(eh->req);
debug(" Export hook %p requested by %p:" debug(" Export hook %p requested by %p:"
" refeed_pending=%u last_state_change=%t export_state=%u\n", " refeed_pending=%u last_state_change=%t export_state=%u\n",
eh, eh->h.req, eh->refeed_pending, eh->h.last_state_change, eh, eh->req, eh->refeed_pending, eh->last_state_change,
atomic_load_explicit(&eh->h.export_state, memory_order_relaxed)); atomic_load_explicit(&eh->export_state, memory_order_relaxed));
} }
debug("\n"); debug("\n");
@ -2497,7 +2494,7 @@ rt_schedule_prune(struct rtable_private *tab)
} }
static void static void
rt_export_used(struct rt_table_exporter *e, const char *who, const char *why) rt_export_used(struct rt_exporter *e, const char *who, const char *why)
{ {
struct rtable_private *tab = SKIP_BACK(struct rtable_private, exporter, e); struct rtable_private *tab = SKIP_BACK(struct rtable_private, exporter, e);
ASSERT_DIE(RT_IS_LOCKED(tab)); ASSERT_DIE(RT_IS_LOCKED(tab));
@ -2621,16 +2618,16 @@ rt_flowspec_log_state_change(struct rt_export_request *req, u8 state)
static struct rt_flowspec_link * static struct rt_flowspec_link *
rt_flowspec_find_link(struct rtable_private *src, rtable *dst) rt_flowspec_find_link(struct rtable_private *src, rtable *dst)
{ {
struct rt_table_export_hook *hook; node *n; struct rt_export_hook *hook; node *n;
WALK_LIST2(hook, n, src->exporter.e.hooks, h.n) WALK_LIST2(hook, n, src->exporter.hooks, n)
switch (atomic_load_explicit(&hook->h.export_state, memory_order_acquire)) switch (atomic_load_explicit(&hook->export_state, memory_order_acquire))
{ {
case TES_HUNGRY: case TES_HUNGRY:
case TES_FEEDING: case TES_FEEDING:
case TES_READY: case TES_READY:
if (hook->h.req->export_one == rt_flowspec_export_one) if (hook->req->export_one == rt_flowspec_export_one)
{ {
struct rt_flowspec_link *ln = SKIP_BACK(struct rt_flowspec_link, req, hook->h.req); struct rt_flowspec_link *ln = SKIP_BACK(struct rt_flowspec_link, req, hook->req);
if (ln->dst == dst) if (ln->dst == dst)
return ln; return ln;
} }
@ -2770,7 +2767,7 @@ static struct resclass rt_class = {
.memsize = NULL, .memsize = NULL,
}; };
static const struct rt_exporter_class rt_table_exporter_class = { static const struct rt_exporter_class rt_exporter_class = {
.start = rt_table_export_start, .start = rt_table_export_start,
.stop = rt_table_export_stop, .stop = rt_table_export_stop,
.done = rt_table_export_done, .done = rt_table_export_done,
@ -2838,16 +2835,14 @@ rt_setup(pool *pp, struct rtable_config *cf)
t->export_settle = SETTLE_INIT(&cf->export_settle, rt_announce_exports, NULL); t->export_settle = SETTLE_INIT(&cf->export_settle, rt_announce_exports, NULL);
t->exporter = (struct rt_table_exporter) { t->exporter = (struct rt_exporter) {
.e = { .class = &rt_exporter_class,
.class = &rt_table_exporter_class,
.addr_type = t->addr_type, .addr_type = t->addr_type,
.rp = t->rp, .rp = t->rp,
},
.next_seq = 1, .next_seq = 1,
}; };
rt_exporter_init(&t->exporter.e); rt_exporter_init(&t->exporter);
init_list(&t->exporter.pending); init_list(&t->exporter.pending);
@ -3040,7 +3035,7 @@ rt_prune_table(struct rtable_private *tab)
} }
/* In some cases, we may want to directly proceed to export cleanup */ /* In some cases, we may want to directly proceed to export cleanup */
if (tab->wait_counter && (EMPTY_LIST(tab->exporter.e.hooks) || !tab->exporter.first)) if (tab->wait_counter && (EMPTY_LIST(tab->exporter.hooks) || !tab->exporter.first))
rt_export_cleanup(tab); rt_export_cleanup(tab);
} }
@ -3054,11 +3049,11 @@ rt_export_cleanup(struct rtable_private *tab)
struct rt_pending_export *first = tab->exporter.first; struct rt_pending_export *first = tab->exporter.first;
int want_prune = 0; int want_prune = 0;
struct rt_table_export_hook *eh; struct rt_export_hook *eh;
node *n; node *n;
WALK_LIST2(eh, n, tab->exporter.e.hooks, h.n) WALK_LIST2(eh, n, tab->exporter.hooks, n)
{ {
switch (atomic_load_explicit(&eh->h.export_state, memory_order_acquire)) switch (atomic_load_explicit(&eh->export_state, memory_order_acquire))
{ {
/* Export cleanup while feeding isn't implemented */ /* Export cleanup while feeding isn't implemented */
case TES_FEEDING: case TES_FEEDING:
@ -3066,7 +3061,7 @@ rt_export_cleanup(struct rtable_private *tab)
/* States not interfering with export cleanup */ /* States not interfering with export cleanup */
case TES_DOWN: /* This should not happen at all */ case TES_DOWN: /* This should not happen at all */
log(L_WARN "%s: Export cleanup found hook %s in explicit state TES_DOWN", tab->name, eh->h.req->name); log(L_WARN "%s: Export cleanup found hook %s in explicit state TES_DOWN", tab->name, eh->req->name);
/* fall through */ /* fall through */
case TES_HUNGRY: /* Feeding waiting for uncork */ case TES_HUNGRY: /* Feeding waiting for uncork */
case TES_STOP: /* No more export will happen on this hook */ case TES_STOP: /* No more export will happen on this hook */
@ -3089,7 +3084,7 @@ rt_export_cleanup(struct rtable_private *tab)
} }
default: default:
bug("%s: Strange export state of hook %s: %d", tab->name, eh->h.req->name, atomic_load_explicit(&eh->h.export_state, memory_order_relaxed)); bug("%s: Strange export state of hook %s: %d", tab->name, eh->req->name, atomic_load_explicit(&eh->export_state, memory_order_relaxed));
} }
} }
@ -3100,9 +3095,9 @@ rt_export_cleanup(struct rtable_private *tab)
tab->exporter.first ? tab->exporter.first->seq : 0, tab->exporter.first ? tab->exporter.first->seq : 0,
min_seq); min_seq);
WALK_LIST2(eh, n, tab->exporter.e.hooks, h.n) WALK_LIST2(eh, n, tab->exporter.hooks, n)
{ {
if (atomic_load_explicit(&eh->h.export_state, memory_order_acquire) != TES_READY) if (atomic_load_explicit(&eh->export_state, memory_order_acquire) != TES_READY)
continue; continue;
struct rt_pending_export *last = atomic_load_explicit(&eh->last_export, memory_order_acquire); struct rt_pending_export *last = atomic_load_explicit(&eh->last_export, memory_order_acquire);
@ -3178,13 +3173,13 @@ rt_export_cleanup(struct rtable_private *tab)
rt_trace(tab, D_EVENTS, "Resetting export seq"); rt_trace(tab, D_EVENTS, "Resetting export seq");
node *n; node *n;
WALK_LIST2(eh, n, tab->exporter.e.hooks, h.n) WALK_LIST2(eh, n, tab->exporter.hooks, n)
{ {
if (atomic_load_explicit(&eh->h.export_state, memory_order_acquire) != TES_READY) if (atomic_load_explicit(&eh->export_state, memory_order_acquire) != TES_READY)
continue; continue;
ASSERT_DIE(atomic_load_explicit(&eh->last_export, memory_order_acquire) == NULL); ASSERT_DIE(atomic_load_explicit(&eh->last_export, memory_order_acquire) == NULL);
bmap_reset(&eh->h.seq_map, 16); bmap_reset(&eh->seq_map, 16);
} }
tab->exporter.next_seq = 1; tab->exporter.next_seq = 1;
@ -4085,10 +4080,10 @@ rt_reconfigure(struct rtable_private *tab, struct rtable_config *new, struct rta
if (tab->hostcache) if (tab->hostcache)
tab->hostcache->req.trace_routes = new->debug; tab->hostcache->req.trace_routes = new->debug;
struct rt_table_export_hook *hook; node *n; struct rt_export_hook *hook; node *n;
WALK_LIST2(hook, n, tab->exporter.e.hooks, h.n) WALK_LIST2(hook, n, tab->exporter.hooks, n)
if (hook->h.req->export_one == rt_flowspec_export_one) if (hook->req->export_one == rt_flowspec_export_one)
hook->h.req->trace_routes = new->debug; hook->req->trace_routes = new->debug;
tab->cork_threshold = new->cork_threshold; tab->cork_threshold = new->cork_threshold;
@ -4188,9 +4183,9 @@ typedef struct {
} rt_feed_block; } rt_feed_block;
static int static int
rt_prepare_feed(struct rt_table_export_hook *c, net *n, rt_feed_block *b) rt_prepare_feed(struct rt_export_hook *c, net *n, rt_feed_block *b)
{ {
struct rt_export_request *req = c->h.req; struct rt_export_request *req = c->req;
uint bs = req->feed_block_size ?: 16384; uint bs = req->feed_block_size ?: 16384;
if (n->routes) if (n->routes)
@ -4236,18 +4231,18 @@ rt_prepare_feed(struct rt_table_export_hook *c, net *n, rt_feed_block *b)
req->mark_seen(req, rpe); req->mark_seen(req, rpe);
else else
RPE_WALK(n->first, rpe, NULL) RPE_WALK(n->first, rpe, NULL)
rpe_mark_seen(&c->h, rpe); rpe_mark_seen(c, rpe);
return 1; return 1;
} }
static void static void
rt_process_feed(struct rt_table_export_hook *c, rt_feed_block *b) rt_process_feed(struct rt_export_hook *c, rt_feed_block *b)
{ {
if (!b->pos) if (!b->pos)
return; return;
if (c->h.req->export_bulk) if (c->req->export_bulk)
{ {
b->aux[b->pos].start = b->cnt; b->aux[b->pos].start = b->cnt;
for (uint p = 0; p < b->pos; p++) for (uint p = 0; p < b->pos; p++)
@ -4255,12 +4250,12 @@ rt_process_feed(struct rt_table_export_hook *c, rt_feed_block *b)
struct rt_feed_block_aux *aux = &b->aux[p]; struct rt_feed_block_aux *aux = &b->aux[p];
const rte **feed = &b->feed[aux->start]; const rte **feed = &b->feed[aux->start];
c->h.req->export_bulk(c->h.req, feed[0]->net, aux->first, aux->last, feed, (aux+1)->start - aux->start); c->req->export_bulk(c->req, feed[0]->net, aux->first, aux->last, feed, (aux+1)->start - aux->start);
} }
} }
else else
for (uint p = 0; p < b->pos; p++) for (uint p = 0; p < b->pos; p++)
c->h.req->export_one(c->h.req, b->rpe[p].new->net, &b->rpe[p]); c->req->export_one(c->req, b->rpe[p].new->net, &b->rpe[p]);
} }
/** /**
@ -4275,12 +4270,12 @@ rt_process_feed(struct rt_table_export_hook *c, rt_feed_block *b)
static void static void
rt_feed_by_fib(void *data) rt_feed_by_fib(void *data)
{ {
struct rt_table_export_hook *c = data; struct rt_export_hook *c = data;
rt_feed_block block = {}; rt_feed_block block = {};
_Bool done = 1; _Bool done = 1;
ASSERT(atomic_load_explicit(&c->h.export_state, memory_order_relaxed) == TES_FEEDING); ASSERT(atomic_load_explicit(&c->export_state, memory_order_relaxed) == TES_FEEDING);
RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, c->table)), tab) RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, c->table)), tab)
{ {
@ -4298,7 +4293,7 @@ rt_feed_by_fib(void *data)
else else
a = n->first->new->net; a = n->first->new->net;
if (rt_prefilter_net(&c->h.req->prefilter, a)) if (rt_prefilter_net(&c->req->prefilter, a))
{ {
if (!rt_prepare_feed(c, n, &block)) if (!rt_prepare_feed(c, n, &block))
{ {
@ -4307,22 +4302,22 @@ rt_feed_by_fib(void *data)
} }
} }
else else
req_trace(c->h.req, D_ROUTES, "Feeding %N rejected by prefilter", a); req_trace(c->req, D_ROUTES, "Feeding %N rejected by prefilter", a);
} }
} }
rt_process_feed(c, &block); rt_process_feed(c, &block);
if (done) if (done)
rt_feed_done(&c->h); rt_feed_done(c);
else else
rt_send_export_event(&c->h); rt_send_export_event(c);
} }
static void static void
rt_feed_by_trie(void *data) rt_feed_by_trie(void *data)
{ {
struct rt_table_export_hook *c = data; struct rt_export_hook *c = data;
rt_feed_block block = {}; rt_feed_block block = {};
RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, c->table)), tab) RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, c->table)), tab)
@ -4331,7 +4326,7 @@ rt_feed_by_trie(void *data)
ASSERT_DIE(c->walk_state); ASSERT_DIE(c->walk_state);
struct f_trie_walk_state *ws = c->walk_state; struct f_trie_walk_state *ws = c->walk_state;
ASSERT(atomic_load_explicit(&c->h.export_state, memory_order_relaxed) == TES_FEEDING); ASSERT(atomic_load_explicit(&c->export_state, memory_order_relaxed) == TES_FEEDING);
do { do {
if (!c->walk_last.type) if (!c->walk_last.type)
@ -4345,7 +4340,7 @@ rt_feed_by_trie(void *data)
if (!rt_prepare_feed(c, n, &block)) if (!rt_prepare_feed(c, n, &block))
return return
rt_process_feed(c, &block), rt_process_feed(c, &block),
rt_send_export_event(&c->h); rt_send_export_event(c);
} }
while (trie_walk_next(ws, &c->walk_last)); while (trie_walk_next(ws, &c->walk_last));
@ -4360,22 +4355,22 @@ rt_feed_by_trie(void *data)
} }
rt_process_feed(c, &block); rt_process_feed(c, &block);
rt_feed_done(&c->h); rt_feed_done(c);
} }
static void static void
rt_feed_equal(void *data) rt_feed_equal(void *data)
{ {
struct rt_table_export_hook *c = data; struct rt_export_hook *c = data;
rt_feed_block block = {}; rt_feed_block block = {};
net *n; net *n;
RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, c->table)), tab) RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, c->table)), tab)
{ {
ASSERT_DIE(atomic_load_explicit(&c->h.export_state, memory_order_relaxed) == TES_FEEDING); ASSERT_DIE(atomic_load_explicit(&c->export_state, memory_order_relaxed) == TES_FEEDING);
ASSERT_DIE(c->h.req->prefilter.mode == TE_ADDR_EQUAL); ASSERT_DIE(c->req->prefilter.mode == TE_ADDR_EQUAL);
const struct netindex *i = net_find_index(tab->netindex, c->h.req->prefilter.addr); const struct netindex *i = net_find_index(tab->netindex, c->req->prefilter.addr);
if (i && (n = net_find(tab, i))) if (i && (n = net_find(tab, i)))
ASSERT_DIE(rt_prepare_feed(c, n, &block)); ASSERT_DIE(rt_prepare_feed(c, n, &block));
} }
@ -4383,29 +4378,29 @@ rt_feed_equal(void *data)
if (n) if (n)
rt_process_feed(c, &block); rt_process_feed(c, &block);
rt_feed_done(&c->h); rt_feed_done(c);
} }
static void static void
rt_feed_for(void *data) rt_feed_for(void *data)
{ {
struct rt_table_export_hook *c = data; struct rt_export_hook *c = data;
rt_feed_block block = {}; rt_feed_block block = {};
net *n; net *n;
RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, c->table)), tab) RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, c->table)), tab)
{ {
ASSERT_DIE(atomic_load_explicit(&c->h.export_state, memory_order_relaxed) == TES_FEEDING); ASSERT_DIE(atomic_load_explicit(&c->export_state, memory_order_relaxed) == TES_FEEDING);
ASSERT_DIE(c->h.req->prefilter.mode == TE_ADDR_FOR); ASSERT_DIE(c->req->prefilter.mode == TE_ADDR_FOR);
if (n = net_route(tab, c->h.req->prefilter.addr)) if (n = net_route(tab, c->req->prefilter.addr))
ASSERT_DIE(rt_prepare_feed(c, n, &block)); ASSERT_DIE(rt_prepare_feed(c, n, &block));
} }
if (n) if (n)
rt_process_feed(c, &block); rt_process_feed(c, &block);
rt_feed_done(&c->h); rt_feed_done(c);
} }