From f44f570356521e169b6d1024d3089a7f765cef09 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Wed, 8 May 2024 21:32:46 +0200 Subject: [PATCH] Gotten to rt-table.c again --- nest/proto.c | 209 +++++++++++++++-------------------------------- nest/protocol.h | 3 +- nest/route.h | 30 ++++--- nest/rt-export.c | 12 +-- nest/rt-show.c | 6 +- 5 files changed, 95 insertions(+), 165 deletions(-) diff --git a/nest/proto.c b/nest/proto.c index 85f4ca20..bdf999ed 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -789,68 +789,45 @@ channel_do_reload(void *_c) { struct channel *c = _c; - while ( - - RT_EXPORT_WALK(&c->reimport, u) - { - switch (u->kind) + RT_FEED_WALK(&c->reimporter, f) + if (task_still_in_limit()) { - case RT_EXPORT_STOP: - bug("Main table export stopped"); - - case RT_EXPORT_FEED: - for (uint i = 0; i < u->feed->count_routes; i++) + for (uint i = 0; i < f->count_routes; i++) + { + rte *r = &f->block[i]; + if (r->sender == c->in_req.hook) { - rte *r = &u->feed->block[i]; - if (r->sender == c->in_req.hook) - { - /* Strip the table-specific information */ - rte new = rte_init_from(r); + /* Strip the table-specific information */ + rte new = rte_init_from(r); - /* Strip the later attribute layers */ - new.attrs = ea_strip_to(new.attrs, BIT32_ALL(EALS_PREIMPORT)); + /* Strip the later attribute layers */ + new.attrs = ea_strip_to(new.attrs, BIT32_ALL(EALS_PREIMPORT)); - /* And reload the route */ - rte_update(c, r->net, &new, new.src); - } + /* And reload the route */ + rte_update(c, r->net, &new, new.src); } - break; + } - case RT_EXPORT_UPDATE: - bug(" - - if (channel_reload_check_done(c)) - return; - else - break; + /* Local data needed no more */ + tmp_flush(); + } + else + { + ev_send(proto_work_list(c->proto), &c->reimport_event); + return; } - } - - if (!channel_reload_check_done(c)) - ev_send(c->reload_req.r.target, &c->reload_event); } /* Called by protocol to activate in_table */ static void channel_setup_in_table(struct channel *c) { - c->reload_req = (struct rt_export_request) { - .name = mb_sprintf(c->proto->pool, "%s.%s.import", c->proto->name, c->name), - .r = { - .target = proto_work_list(c->proto), - .event = &c->reload_event, - }, - .pool = c->proto->pool, - .trace_routes = c->debug | c->proto->debug, -// .feed = channel_reload_export, - .dump = channel_reload_dump_req, -// .state_change = channel_reload_state_change, - }; - - c->reload_event = (event) { + c->reimporter = (struct rt_export_feeder) {}; + c->reimport_event = (event) { .hook = channel_do_reload, .data = c, }; + rt_feeder_subscribe(&c->table->export_all, &c->reimporter); } @@ -901,9 +878,8 @@ channel_do_pause(struct channel *c) /* Drop ROA subscriptions */ channel_roa_unsubscribe_all(c); - /* Need to abort feeding */ - c->reload_pending = 0; - channel_stop_export_req_if_running(&c->reload_req); + /* Need to abort reimports as well */ + rt_feeder_unsubscribe(&c->reimporter); /* Stop export */ channel_stop_export(c); @@ -927,7 +903,7 @@ channel_do_stop(struct channel *c) static void channel_do_down(struct channel *c) { - ASSERT_DIE(rt_export_get_state(&c->reload_req) == TES_DOWN); + ASSERT_DIE(!rt_export_feed_active(&c->reimporter)); c->proto->active_channels--; @@ -1012,39 +988,19 @@ channel_stop_export(struct channel *c) channel_stop_export_req_if_running(&c->out_req); } -static void -channel_import_request_done_dynamic(struct channel_import_request *req) -{ - mb_free(req); -} - void -channel_request_reload(struct channel *c) +channel_request_reload(struct channel *c, struct rt_feeding_request *cir) { ASSERT_DIE(c->in_req.hook); ASSERT_DIE(channel_reloadable(c)); - CD(c, "Reload requested"); - struct channel_import_request* cir = mb_alloc(c->proto->pool, sizeof *cir); - cir->trie = NULL; - cir->done = channel_import_request_done_dynamic; + if (cir) + CD(c, "Partial import reload requested"); + else + CD(c, "Full import reload requested"); if ((c->in_keep & RIK_PREFILTER) == RIK_PREFILTER) - return channel_schedule_reload(c, cir); - else if (! c->proto->reload_routes(c, cir)) - bug("Channel %s.%s refused full import reload.", c->proto->name, c->name); -} - -static void -channel_request_partial_reload(struct channel *c, struct channel_import_request *cir) -{ - ASSERT_DIE(c->in_req.hook); - ASSERT_DIE(channel_reloadable(c)); - - CD(c, "Partial import reload requested"); - - if ((c->in_keep & RIK_PREFILTER) == RIK_PREFILTER) - channel_schedule_reload(c, cir); + channel_reimport(c, cir); else if (! c->proto->reload_routes(c, cir)) cli_msg(-15, "%s.%s: partial reload refused, please run full reload instead", c->proto->name, c->name); } @@ -1171,7 +1127,7 @@ channel_reconfigure(struct channel *c, struct channel_config *cf) // c->ra_mode = cf->ra_mode; c->merge_limit = cf->merge_limit; c->preference = cf->preference; - c->out_req.prefilter.addr = c->out_subprefix = cf->out_subprefix; + c->out_req.feeder.prefilter.addr = c->out_subprefix = cf->out_subprefix; c->debug = cf->debug; c->in_req.trace_routes = c->out_req.trace_routes = c->debug | c->proto->debug; c->rpki_reload = cf->rpki_reload; @@ -1231,7 +1187,7 @@ channel_reconfigure(struct channel *c, struct channel_config *cf) log(L_INFO "Reloading channel %s.%s", c->proto->name, c->name); if (import_changed) - channel_request_reload(c); + channel_request_reload(c, NULL); if (export_changed) rt_export_refeed(&c->out_req, NULL); @@ -2647,30 +2603,42 @@ proto_cmd_restart(struct proto *p, uintptr_t arg, int cnt UNUSED) cli_msg(-12, "%s: restarted", p->name); } -struct channel_cmd_reload_feeding_request { +struct channel_cmd_reload_request { struct rt_feeding_request cfr; struct proto_reload_request *prr; }; -struct channel_cmd_reload_import_request { - struct channel_import_request cir; - struct proto_reload_request *prr; -}; - static void -channel_reload_out_done(struct rt_feeding_request *cfr) +channel_reload_done(struct rt_feeding_request *cfr) { - SKIP_BACK_DECLARE(struct channel_cmd_reload_feeding_request, ccrfr, cfr, cfr); + SKIP_BACK_DECLARE(struct channel_cmd_reload_request, ccrfr, cfr, cfr); if (atomic_fetch_sub_explicit(&ccrfr->prr->counter, 1, memory_order_acq_rel) == 1) ev_send_loop(&main_birdloop, &ccrfr->prr->ev); } -static void -channel_reload_in_done(struct channel_import_request *cir) +static struct rt_feeding_request * +channel_create_reload_request(struct proto_reload_request *prr) { - SKIP_BACK_DECLARE(struct channel_cmd_reload_import_request, ccrir, cir, cir); - if (atomic_fetch_sub_explicit(&ccrir->prr->counter, 1, memory_order_acq_rel) == 1) - ev_send_loop(&main_birdloop, &ccrir->prr->ev); + if (!prr->trie) + return NULL; + + /* Increase the refeed counter */ + atomic_fetch_add_explicit(&prr->counter, 1, memory_order_relaxed); + ASSERT_DIE(this_cli->parser_pool != prr->trie->lp); + + struct channel_cmd_reload_request *req = lp_alloc(prr->trie->lp, sizeof *req); + *req = (struct channel_cmd_reload_request) { + .cfr = { + .done = channel_reload_done, + .prefilter = { + .mode = TE_ADDR_TRIE, + .trie = prr->trie, + }, + }, + .prr = prr, + }; + + return &req->cfr; } void @@ -2700,58 +2668,15 @@ proto_cmd_reload(struct proto *p, uintptr_t _prr, int cnt UNUSED) log(L_INFO "Reloading protocol %s", p->name); /* re-importing routes */ - if (prr->dir & CMD_RELOAD_IN) - WALK_LIST(c, p->channels) - if (c->channel_state == CS_UP) - { - if (prr->trie) - { - /* Increase the refeed counter */ - atomic_fetch_add_explicit(&prr->counter, 1, memory_order_relaxed); - ASSERT_DIE(this_cli->parser_pool != prr->trie->lp); + WALK_LIST(c, p->channels) + if (c->channel_state == CS_UP) + { + if (prr->dir & CMD_RELOAD_IN) + channel_request_reload(c, channel_create_reload_request(prr)); - struct channel_cmd_reload_import_request *req = lp_alloc(prr->trie->lp, sizeof *req); - *req = (struct channel_cmd_reload_import_request) { - .cir = { - .done = channel_reload_in_done, - .trie = prr->trie, - }, - .prr = prr, - }; - channel_request_partial_reload(c, &req->cir); - } - else - channel_request_reload(c); - } - - /* re-exporting routes */ - if (prr->dir & CMD_RELOAD_OUT) - WALK_LIST(c, p->channels) - if ((c->channel_state == CS_UP) && (rt_export_get_state(&c->out_req) != TES_DOWN)) - if (prr->trie) - { - /* Increase the refeed counter */ - atomic_fetch_add_explicit(&prr->counter, 1, memory_order_relaxed); - ASSERT_DIE(this_cli->parser_pool != prr->trie->lp); - - /* Request actually the feeding */ - - struct channel_cmd_reload_feeding_request *req = lp_alloc(prr->trie->lp, sizeof *req); - *req = (struct channel_cmd_reload_feeding_request) { - .cfr = { - .done = channel_reload_out_done, - .prefilter = { - .mode = TE_ADDR_TRIE, - .trie = prr->trie, - }, - }, - .prr = prr, - }; - - rt_export_refeed(&c->out_req, &req->cfr); - } - else - rt_export_refeed(&c->out_req, NULL); + if (prr->dir & CMD_RELOAD_OUT) + rt_export_refeed(&c->out_req, channel_create_reload_request(prr)); + } cli_msg(-15, "%s: reloading", p->name); } diff --git a/nest/protocol.h b/nest/protocol.h index fd0d009c..c36df0cf 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -671,7 +671,6 @@ void proto_remove_channel(struct proto *p, struct channel *c); int proto_configure_channel(struct proto *p, struct channel **c, struct channel_config *cf); void channel_set_state(struct channel *c, uint state); -void channel_schedule_reload(struct channel *c, struct rt_feeding_request *cir); void channel_add_obstacle(struct channel *c); void channel_del_obstacle(struct channel *c); @@ -696,7 +695,7 @@ static inline int channel_net_is_refeeding(struct channel *c, const net_addr *n) } #endif -void channel_request_reload(struct channel *c); +void channel_request_reload(struct channel *c, struct rt_feeding_request *cir); void *channel_config_new(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto); void *channel_config_get(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto); diff --git a/nest/route.h b/nest/route.h index b4918f34..0c11a7f9 100644 --- a/nest/route.h +++ b/nest/route.h @@ -181,7 +181,7 @@ struct rt_exporter { void (*stopped)(struct rt_exporter *); /* Callback when exporter can stop */ void (*cleanup_done)(struct rt_exporter *); /* Callback when cleanup has been done */ struct rt_export_feed *(*feed_next)(struct rt_exporter *, struct rt_export_request *); - struct rt_export_feed *(*feed_net)(struct rt_exporter *, struct rt_export_request *, net_addr *); + struct rt_export_feed *(*feed_net)(struct rt_exporter *, struct rt_export_request *, const net_addr *); TLIST_LIST(rt_export_feeder) feeders; /* Feed penders */ }; @@ -208,26 +208,31 @@ struct rt_export_union { struct rt_export_request *req; }; +/* Exporter API */ void rt_exporter_init(struct rt_exporter *, struct settle_config *); const struct rt_export_item *rt_exporter_push(struct rt_exporter *, const struct rt_export_item *); void rt_exporter_shutdown(struct rt_exporter *, void (*stopped)(struct rt_exporter *)); +/* Standalone feeds */ +void rt_feeder_subscribe(struct rt_exporter *, struct rt_export_feeder *); +void rt_feeder_unsubscribe(struct rt_export_feeder *); +void rt_export_refeed_feeder(struct rt_export_feeder *, struct rt_feeding_request *); +struct rt_export_feed *rt_export_next_feed(struct rt_export_feeder *); +#define RT_FEED_WALK(_feeder, _f) \ + for (const struct rt_export_feed *_f; _f = rt_export_next_feed(_feeder); ) \ + +static inline _Bool rt_export_feed_active(struct rt_export_feeder *f) +{ return !!atomic_load_explicit(&f->exporter, memory_order_acquire); } + +/* Full blown exports */ void rt_export_subscribe(struct rt_exporter *, struct rt_export_request *); void rt_export_unsubscribe(struct rt_export_request *); const struct rt_export_union * rt_export_get(struct rt_export_request *); void rt_export_release(const struct rt_export_union *); void rt_export_processed(struct rt_export_request *, u64); -void rt_export_refeed_feeder(struct rt_export_feeder *, struct rt_feeding_request *); static inline void rt_export_refeed_request(struct rt_export_request *rer, struct rt_feeding_request *rfr) { return rt_export_refeed_feeder(&rer->feeder, rfr); } -#define rt_export_refeed(h, r) _Generic((h), \ - struct rt_export_feeder *: rt_export_refeed_feeder, \ - struct rt_export_request *: rt_export_refeed_request, \ - void *: bug)(h, r) - -static inline _Bool rt_export_feed_active(struct rt_export_feeder *f) -{ return !!atomic_load_explicit(&f->exporter, memory_order_acquire); } static inline enum rt_export_state rt_export_get_state(struct rt_export_request *r) { return atomic_load_explicit(&r->export_state, memory_order_acquire); } @@ -244,8 +249,11 @@ static inline void rt_export_walk_cleanup(const struct rt_export_union **up) _u = rt_export_get(_reader); \ rt_export_release(_u)) \ -#define RT_FEED_WALK(_feeder, _f) \ - for (const struct rt_export_feed *_f; _f = rt_export_next_feed(_feeder); ) TMP_SAVED \ +/* Convenince common call to request refeed */ +#define rt_export_refeed(h, r) _Generic((h), \ + struct rt_export_feeder *: rt_export_refeed_feeder, \ + struct rt_export_request *: rt_export_refeed_request, \ + void *: bug)(h, r) static inline int rt_prefilter_net(const struct rt_prefilter *p, const net_addr *n) diff --git a/nest/rt-export.c b/nest/rt-export.c index 3416f3b7..9f342e78 100644 --- a/nest/rt-export.c +++ b/nest/rt-export.c @@ -87,7 +87,7 @@ rt_export_get(struct rt_export_request *r) } const net_addr *n = (reu.update->new ?: reu.update->old)->net; - if ((es != TES_READY) && rt_net_is_feeding(r, n)) + if ((es != TES_READY) && rt_net_is_feeding(&r->feeder, n)) { /* But this net shall get a feed first! */ reu.feed = e->feed_net(e, r, n); @@ -151,12 +151,11 @@ rt_export_processed(struct rt_export_request *r, u64 seq) } void -rt_export_subscribe(struct rt_export_request *r) +rt_export_subscribe(struct rt_exporter *e, struct rt_export_request *r) { rt_export_change_state(r, BIT32_ALL(TES_DOWN), TES_FEEDING); - ASSERT_DIE(r->exporter); - struct rt_exporter *e = r->exporter; + rt_feeder_subscribe(e, &r->feeder); ASSERT_DIE(r->r.target); ASSERT_DIE(r->r.event); @@ -165,15 +164,12 @@ rt_export_subscribe(struct rt_export_request *r) r->stats = (struct rt_export_stats) {}; r->last_state_change = current_time(); bmap_init(&r->seq_map, r->pool, 4); - - /* We should init feeding but this is not implemented yet */ - rt_export_change_state(r, BIT32_ALL(TES_FEEDING), TES_READY); } void rt_export_unsubscribe(struct rt_export_request *r) { - ASSERT_DIE(r->exporter) + rt_feeder_unsubscribe(&r->feeder); if (r->cur) rt_export_release(r->cur); diff --git a/nest/rt-show.c b/nest/rt-show.c index 06ca7bf7..54d8d37b 100644 --- a/nest/rt-show.c +++ b/nest/rt-show.c @@ -429,11 +429,13 @@ rt_show_prepare_tables(struct rt_show_data *d) /* Open the export request */ tab->req = (struct rt_export_request) { - .prefilter.addr = d->addr, + .feeder.prefilter = { + .addr = d->addr, + .mode = d->addr_mode, + }, .name = "CLI Show Route", .pool = d->cli->pool, .dump = rt_show_dump_req, - .prefilter.mode = d->addr_mode, }; rt_export_subscribe(&tab->table->export_all, &tab->req);