mirror of
https://gitlab.labs.nic.cz/labs/bird.git
synced 2024-05-11 16:54:54 +00:00
Gotten to rt-table.c again
This commit is contained in:
209
nest/proto.c
209
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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
30
nest/route.h
30
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)
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user