summaryrefslogtreecommitdiff
path: root/nest/proto.c
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2021-09-29 16:15:13 +0200
committerMaria Matejka <mq@ucw.cz>2021-11-22 19:05:44 +0100
commit878eeec12bf020c9e7460040d225a929bbbd2bd2 (patch)
treee60ffcdbcf26972912271aba2353c572f02c679f /nest/proto.c
parentc7d0c5b2523a8cbfcaee9a235955dd5e58fab671 (diff)
Routing tables now have their own loops.
This basically means that: * there are some more levels of indirection and asynchronicity, mostly in cleanup procedures, requiring correct lock ordering * all the internal table operations (prune, next hop update) are done without blocking the other parts of BIRD * the protocols may get their own loops very soon
Diffstat (limited to 'nest/proto.c')
-rw-r--r--nest/proto.c75
1 files changed, 47 insertions, 28 deletions
diff --git a/nest/proto.c b/nest/proto.c
index 35af3c6c..4ae0cbfd 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -172,7 +172,7 @@ proto_cf_find_channel(struct proto_config *pc, uint net_type)
* Returns pointer to channel or NULL
*/
struct channel *
-proto_find_channel_by_table(struct proto *p, struct rtable *t)
+proto_find_channel_by_table(struct proto *p, rtable *t)
{
struct channel *c;
@@ -236,7 +236,9 @@ proto_add_channel(struct proto *p, struct channel_config *cf)
c->channel = cf->channel;
c->proto = p;
c->table = cf->table->table;
- rt_lock_table(c->table);
+
+ RT_LOCKED(c->table, t)
+ rt_lock_table(t);
c->in_filter = cf->in_filter;
c->out_filter = cf->out_filter;
@@ -277,7 +279,9 @@ proto_remove_channel(struct proto *p UNUSED, struct channel *c)
CD(c, "Removed", c->name);
- rt_unlock_table(c->table);
+ RT_LOCKED(c->table, t)
+ rt_unlock_table(t);
+
rem_node(&c->n);
mb_free(c);
}
@@ -391,7 +395,7 @@ static void
channel_roa_subscribe_filter(struct channel *c, int dir)
{
const struct filter *f = dir ? c->in_filter : c->out_filter;
- struct rtable *tab;
+ rtable *tab;
int valid = 1, found = 0;
if ((f == FILTER_ACCEPT) || (f == FILTER_REJECT))
@@ -560,11 +564,11 @@ channel_check_stopped(struct channel *c)
}
void
-channel_import_stopped(struct rt_import_request *req)
+channel_import_stopped(void *_c)
{
- struct channel *c = SKIP_BACK(struct channel, in_req, req);
+ struct channel *c = _c;
- req->hook = NULL;
+ c->in_req.hook = NULL;
mb_free(c->in_req.name);
c->in_req.name = NULL;
@@ -661,17 +665,16 @@ channel_aux_stopped(void *data)
else
c->in_table = NULL;
- rfree(cat->tab->rp);
-
+ rfree(cat->tab->priv.rp);
mb_free(cat);
- return channel_check_stopped(c);
+ channel_check_stopped(c);
}
static void
-channel_aux_import_stopped(struct rt_import_request *req)
+channel_aux_import_stopped(void *_cat)
{
- struct channel_aux_table *cat = SKIP_BACK(struct channel_aux_table, push, req);
- ASSERT_DIE(cat->tab->delete_event);
+ struct channel_aux_table *cat = _cat;
+ cat->push.hook = NULL;
}
static void
@@ -680,24 +683,35 @@ channel_aux_export_stopped(struct rt_export_request *req)
struct channel_aux_table *cat = SKIP_BACK(struct channel_aux_table, get, req);
req->hook = NULL;
- if (cat->refeed_pending && !cat->tab->delete_event)
- {
- cat->refeed_pending = 0;
- rt_request_export(cat->tab, req);
- }
- else
- ASSERT_DIE(cat->tab->delete_event);
+ int del;
+ RT_LOCKED(cat->tab, t)
+ del = !!t->delete_event;
+
+ if (del)
+ return;
+
+ ASSERT_DIE(cat->refeed_pending);
+ cat->refeed_pending = 0;
+ rt_request_export(cat->tab, req);
}
static void
channel_aux_stop(struct channel_aux_table *cat)
{
- rt_stop_import(&cat->push, channel_aux_import_stopped);
- rt_stop_export(&cat->get, channel_aux_export_stopped);
+ RT_LOCKED(cat->tab, t)
+ {
+ t->delete_event = ev_new_init(t->rp, channel_aux_stopped, cat);
+ t->delete_event->list = proto_event_list(cat->c->proto);
+ }
- cat->tab->delete_event = ev_new_init(cat->tab->rp, channel_aux_stopped, cat);
+ cat->push_stopped = (event) {
+ .hook = channel_aux_import_stopped,
+ .data = cat,
+ .list = proto_event_list(cat->c->proto),
+ };
- rt_unlock_table(cat->tab);
+ rt_stop_import(&cat->push, &cat->push_stopped);
+ rt_stop_export(&cat->get, channel_aux_export_stopped);
}
static void
@@ -889,7 +903,6 @@ channel_setup_in_table(struct channel *c, int best)
c->in_table->c = c;
c->in_table->tab = rt_setup(c->proto->pool, &cat->tab_cf);
- rt_lock_table(c->in_table->tab);
rt_request_import(c->in_table->tab, &c->in_table->push);
rt_request_export(c->in_table->tab, &c->in_table->get);
@@ -931,7 +944,6 @@ channel_setup_out_table(struct channel *c)
c->out_table->c = c;
c->out_table->tab = rt_setup(c->proto->pool, &cat->tab_cf);
- rt_lock_table(c->out_table->tab);
rt_request_import(c->out_table->tab, &c->out_table->push);
rt_request_export(c->out_table->tab, &c->out_table->get);
@@ -993,7 +1005,14 @@ channel_do_stop(struct channel *c)
/* Stop import */
if (c->in_req.hook)
- rt_stop_import(&c->in_req, channel_import_stopped);
+ {
+ c->in_stopped = (event) {
+ .hook = channel_import_stopped,
+ .data = c,
+ .list = proto_event_list(c->proto),
+ };
+ rt_stop_import(&c->in_req, &c->in_stopped);
+ }
c->gr_wait = 0;
if (c->gr_lock)
@@ -2339,7 +2358,7 @@ proto_do_start(struct proto *p)
{
p->active = 1;
- rt_init_sources(&p->sources, p->name, proto_event_list(p));
+ rt_init_sources(&p->sources, p->name, proto_work_list(p));
if (!p->sources.class)
p->sources.class = &default_rte_owner_class;