mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 17:51:53 +00:00
Partial import reload
This commit is contained in:
parent
a532146886
commit
10bf227de7
125
nest/proto.c
125
nest/proto.c
@ -52,6 +52,7 @@ static void channel_init_limit(struct channel *c, struct limit *l, int dir, stru
|
||||
static void channel_update_limit(struct channel *c, struct limit *l, int dir, struct channel_limit *cf);
|
||||
static void channel_reset_limit(struct channel *c, struct limit *l, int dir);
|
||||
static int channel_refeed_prefilter(const struct rt_prefilter *p, const net_addr *n);
|
||||
static int channel_import_prefilter(const struct rt_prefilter *p, const net_addr *n);
|
||||
static void channel_feed_end(struct channel *c);
|
||||
static void channel_stop_export(struct channel *c);
|
||||
static void channel_export_stopped(struct rt_export_request *req);
|
||||
@ -557,6 +558,10 @@ channel_start_import(struct channel *c)
|
||||
.dump_req = channel_dump_import_req,
|
||||
.log_state_change = channel_import_log_state_change,
|
||||
.preimport = channel_preimport,
|
||||
.prefilter = {
|
||||
.mode = c->out_subprefix ? TE_ADDR_IN : TE_ADDR_NONE,
|
||||
.addr = c->out_subprefix,
|
||||
},
|
||||
};
|
||||
|
||||
ASSERT(c->channel_state == CS_UP);
|
||||
@ -752,11 +757,30 @@ channel_refeed_prefilter(const struct rt_prefilter *p, const net_addr *n)
|
||||
|
||||
for (struct channel_feeding_request *cfr = c->refeeding; cfr; cfr = cfr->next)
|
||||
if (!cfr->trie || trie_match_net(cfr->trie, n))
|
||||
{
|
||||
log(L_TRACE "Export this one");
|
||||
return 1;
|
||||
|
||||
}
|
||||
log(L_TRACE "%N filtered out of export", n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
channel_import_prefilter(const struct rt_prefilter *p, const net_addr *n)
|
||||
{
|
||||
const struct channel *c =
|
||||
SKIP_BACK(struct channel, reload_req,
|
||||
SKIP_BACK(struct rt_export_request, prefilter, p)
|
||||
);
|
||||
for (struct channel_import_request *cir = c->importing; cir; cir = cir->next)
|
||||
if (!cir->trie || trie_match_net(cir->trie, n))
|
||||
{
|
||||
log(L_TRACE "Export this one");
|
||||
return 1;
|
||||
}
|
||||
log(L_TRACE "%N filtered out of import", n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
channel_feed_end(struct channel *c)
|
||||
@ -808,18 +832,44 @@ channel_feed_end(struct channel *c)
|
||||
|
||||
/* Called by protocol for reload from in_table */
|
||||
void
|
||||
channel_schedule_reload(struct channel *c)
|
||||
channel_schedule_reload(struct channel *c, struct channel_import_request *cir)
|
||||
{
|
||||
log(L_TRACE "channel_schedule_reload %i %i",cir, (cir && cir->trie));
|
||||
ASSERT(c->in_req.hook);
|
||||
|
||||
int no_trie = 0;
|
||||
if (cir)
|
||||
{
|
||||
struct channel_import_request* last = c->import_pending;
|
||||
while (last)
|
||||
{
|
||||
if (!last->trie)
|
||||
no_trie = 1;
|
||||
last = last->next;
|
||||
}
|
||||
last = cir;
|
||||
no_trie = !last->trie;
|
||||
}
|
||||
if (c->reload_req.hook)
|
||||
{
|
||||
CD(c, "Reload triggered before the previous one has finished");
|
||||
c->reload_pending = 1;
|
||||
return;
|
||||
}
|
||||
c->importing = c->import_pending;
|
||||
c->import_pending = NULL;
|
||||
|
||||
if (no_trie)
|
||||
{
|
||||
c->reload_req.prefilter.mode = TE_ADDR_NONE;
|
||||
c->reload_req.prefilter.hook = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
CD(c, "Import with trie");
|
||||
c->reload_req.prefilter.mode = TE_ADDR_HOOK;
|
||||
c->reload_req.prefilter.hook = channel_import_prefilter;
|
||||
}
|
||||
|
||||
rt_refresh_begin(&c->in_req);
|
||||
rt_request_export(c->table, &c->reload_req);
|
||||
}
|
||||
|
||||
@ -1081,12 +1131,32 @@ channel_request_reload(struct channel *c)
|
||||
|
||||
CD(c, "Reload requested");
|
||||
|
||||
if ((c->in_keep & RIK_PREFILTER) == RIK_PREFILTER)
|
||||
channel_schedule_reload(c);
|
||||
if ((c->in_keep & RIK_PREFILTER) == RIK_PREFILTER) {
|
||||
struct channel_import_request* cir = mb_alloc(c->proto->pool, sizeof *cir);;
|
||||
cir->trie = NULL;
|
||||
channel_schedule_reload(c, cir);
|
||||
}
|
||||
else
|
||||
c->proto->reload_routes(c);
|
||||
}
|
||||
|
||||
static void
|
||||
channel_request_partial_reload(struct channel *c, struct channel_import_request *cir)
|
||||
{
|
||||
ASSERT(c->in_req.hook);
|
||||
ASSERT(channel_reloadable(c));
|
||||
|
||||
CD(c, "Partial import reload requested");
|
||||
|
||||
if ((c->in_keep & RIK_PREFILTER) == RIK_PREFILTER)
|
||||
channel_schedule_reload(c, cir);
|
||||
/* TODO*/
|
||||
else
|
||||
CD(c, "Partial import reload requested, but with ric cosi");
|
||||
/*c->proto->reload_routes(c);
|
||||
*/
|
||||
}
|
||||
|
||||
const struct channel_class channel_basic = {
|
||||
.channel_size = sizeof(struct channel),
|
||||
.config_size = sizeof(struct channel_config)
|
||||
@ -2681,6 +2751,11 @@ struct channel_cmd_reload_feeding_request {
|
||||
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_main(void *_prr)
|
||||
{
|
||||
@ -2698,6 +2773,14 @@ channel_reload_out_done(struct channel_feeding_request *cfr)
|
||||
ev_send_loop(&main_birdloop, &ccrfr->prr->ev);
|
||||
}
|
||||
|
||||
static void
|
||||
channel_reload_in_done(struct channel_import_request *cir)
|
||||
{
|
||||
struct channel_cmd_reload_import_request *ccrir = SKIP_BACK(struct channel_cmd_reload_import_request, cir, cir);
|
||||
if (atomic_fetch_sub_explicit(&ccrir->prr->counter, 1, memory_order_acq_rel) == 1)
|
||||
ev_send_loop(&main_birdloop, &ccrir->prr->ev);
|
||||
}
|
||||
|
||||
void
|
||||
proto_cmd_reload(struct proto *p, uintptr_t _prr, int cnt UNUSED)
|
||||
{
|
||||
@ -2729,7 +2812,37 @@ proto_cmd_reload(struct proto *p, uintptr_t _prr, int cnt UNUSED)
|
||||
if (prr->dir != CMD_RELOAD_OUT)
|
||||
WALK_LIST(c, p->channels)
|
||||
if (c->channel_state == CS_UP)
|
||||
{
|
||||
if (prr->trie)
|
||||
{
|
||||
/* Increase the refeed counter */
|
||||
if (atomic_fetch_add_explicit(&prr->counter, 1, memory_order_relaxed) == 0)
|
||||
{
|
||||
/* First occurence */
|
||||
ASSERT_DIE(this_cli->parser_pool == prr->trie->lp);
|
||||
rmove(this_cli->parser_pool, &root_pool);
|
||||
this_cli->parser_pool = lp_new(this_cli->pool);
|
||||
prr->ev = (event) {
|
||||
.hook = channel_reload_out_done_main,
|
||||
.data = prr,
|
||||
};
|
||||
}
|
||||
else
|
||||
ASSERT_DIE(this_cli->parser_pool != prr->trie->lp);
|
||||
|
||||
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_IN)
|
||||
|
@ -581,6 +581,8 @@ struct channel {
|
||||
struct f_trie *refeed_trie; /* Auxiliary refeed trie */
|
||||
struct channel_feeding_request *refeeding; /* Refeeding the channel */
|
||||
struct channel_feeding_request *refeed_pending; /* Scheduled refeeds */
|
||||
struct channel_import_request *importing; /* Importing the channel */
|
||||
struct channel_import_request *import_pending; /* Scheduled imports */
|
||||
|
||||
uint feed_block_size; /* How many routes to feed at once */
|
||||
|
||||
@ -677,7 +679,7 @@ struct channel *proto_add_channel(struct proto *p, struct channel_config *cf);
|
||||
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);
|
||||
void channel_schedule_reload(struct channel *c, struct channel_import_request *cir);
|
||||
|
||||
static inline void channel_init(struct channel *c) { channel_set_state(c, CS_START); }
|
||||
static inline void channel_open(struct channel *c) { channel_set_state(c, CS_UP); }
|
||||
@ -698,6 +700,12 @@ struct channel_feeding_request {
|
||||
} state;
|
||||
};
|
||||
|
||||
struct channel_import_request {
|
||||
struct channel_import_request *next; /* Next in request chain */
|
||||
void (*done)(struct channel_import_request *); /* Called when import finishes */
|
||||
const struct f_trie *trie; /* Reload only matching nets */
|
||||
};
|
||||
|
||||
struct channel *channel_from_export_request(struct rt_export_request *req);
|
||||
void channel_request_feeding(struct channel *c, struct channel_feeding_request *);
|
||||
void channel_request_feeding_dynamic(struct channel *c, enum channel_feeding_request_type);
|
||||
|
@ -2212,7 +2212,7 @@ rt_table_export_start_feed(struct rtable_private *tab, struct rt_table_export_ho
|
||||
{
|
||||
struct rt_exporter *re = &tab->exporter.e;
|
||||
struct rt_export_request *req = hook->h.req;
|
||||
|
||||
log("Hook is %x", hook);
|
||||
/* stats zeroed by mb_allocz */
|
||||
switch (req->prefilter.mode)
|
||||
{
|
||||
@ -2230,6 +2230,7 @@ rt_table_export_start_feed(struct rtable_private *tab, struct rt_table_export_ho
|
||||
case TE_ADDR_NONE:
|
||||
case TE_ADDR_TRIE:
|
||||
case TE_ADDR_HOOK:
|
||||
log(L_TRACE "hook - we will feed by fib, not trie?");
|
||||
FIB_ITERATE_INIT(&hook->feed_fit, &tab->fib);
|
||||
hook->h.event.hook = rt_feed_by_fib;
|
||||
break;
|
||||
@ -4403,6 +4404,7 @@ rt_process_feed(struct rt_table_export_hook *c, rt_feed_block *b)
|
||||
static void
|
||||
rt_feed_by_fib(void *data)
|
||||
{
|
||||
log(L_TRACE "rt_feed_by_fib_function - here filtering starts");
|
||||
struct rt_table_export_hook *c = data;
|
||||
struct fib_iterator *fit = &c->feed_fit;
|
||||
rt_feed_block block = {};
|
||||
@ -4546,6 +4548,7 @@ void channel_reload_export_bulk(struct rt_export_request *req, const net_addr *n
|
||||
while (new.attrs->next)
|
||||
new.attrs = new.attrs->next;
|
||||
|
||||
log(L_TRACE "chanel_reload_export_bulk %N", net);
|
||||
/* And reload the route */
|
||||
rte_update(c, net, &new, new.src);
|
||||
}
|
||||
|
35
nest/rt.h
35
nest/rt.h
@ -253,10 +253,28 @@ struct rte_storage {
|
||||
|
||||
/* Table-channel connections */
|
||||
|
||||
struct rt_prefilter {
|
||||
union {
|
||||
const struct f_trie *trie;
|
||||
const net_addr *addr; /* Network prefilter address */
|
||||
int (*hook)(const struct rt_prefilter *, const net_addr *);
|
||||
};
|
||||
/* Network prefilter mode (TE_ADDR_*) */
|
||||
enum {
|
||||
TE_ADDR_NONE = 0, /* No address matching */
|
||||
TE_ADDR_EQUAL, /* Exact query - show route <addr> */
|
||||
TE_ADDR_FOR, /* Longest prefix match - show route for <addr> */
|
||||
TE_ADDR_IN, /* Interval query - show route in <addr> */
|
||||
TE_ADDR_TRIE, /* Query defined by trie */
|
||||
TE_ADDR_HOOK, /* Query processed by supplied custom hook */
|
||||
} mode;
|
||||
} PACKED;
|
||||
|
||||
struct rt_import_request {
|
||||
struct rt_import_hook *hook; /* The table part of importer */
|
||||
char *name;
|
||||
u8 trace_routes;
|
||||
struct rt_prefilter prefilter;
|
||||
|
||||
event_list *list; /* Where to schedule announce events */
|
||||
|
||||
@ -300,23 +318,6 @@ struct rt_pending_export {
|
||||
u64 seq; /* Sequential ID (table-local) of the pending export */
|
||||
};
|
||||
|
||||
struct rt_prefilter {
|
||||
union {
|
||||
const struct f_trie *trie;
|
||||
const net_addr *addr; /* Network prefilter address */
|
||||
int (*hook)(const struct rt_prefilter *, const net_addr *);
|
||||
};
|
||||
/* Network prefilter mode (TE_ADDR_*) */
|
||||
enum {
|
||||
TE_ADDR_NONE = 0, /* No address matching */
|
||||
TE_ADDR_EQUAL, /* Exact query - show route <addr> */
|
||||
TE_ADDR_FOR, /* Longest prefix match - show route for <addr> */
|
||||
TE_ADDR_IN, /* Interval query - show route in <addr> */
|
||||
TE_ADDR_TRIE, /* Query defined by trie */
|
||||
TE_ADDR_HOOK, /* Query processed by supplied custom hook */
|
||||
} mode;
|
||||
} PACKED;
|
||||
|
||||
struct rt_export_request {
|
||||
struct rt_export_hook *hook; /* Table part of the export */
|
||||
char *name; /* Network prefilter address */
|
||||
|
Loading…
Reference in New Issue
Block a user