mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-18 09:08:42 +00:00
Route table import-to-export announcement indirection to reduce pipe traffic
This commit is contained in:
parent
794a4eefa1
commit
dc160e11e1
@ -468,6 +468,7 @@ channel_start_import(struct channel *c)
|
|||||||
|
|
||||||
c->in_req = (struct rt_import_request) {
|
c->in_req = (struct rt_import_request) {
|
||||||
.name = rn,
|
.name = rn,
|
||||||
|
.list = proto_work_list(c->proto),
|
||||||
.trace_routes = c->debug | c->proto->debug,
|
.trace_routes = c->debug | c->proto->debug,
|
||||||
.dump_req = channel_dump_import_req,
|
.dump_req = channel_dump_import_req,
|
||||||
.log_state_change = channel_import_log_state_change,
|
.log_state_change = channel_import_log_state_change,
|
||||||
@ -886,6 +887,7 @@ channel_setup_in_table(struct channel *c, int best)
|
|||||||
c->in_table = &cat->cat;
|
c->in_table = &cat->cat;
|
||||||
c->in_table->push = (struct rt_import_request) {
|
c->in_table->push = (struct rt_import_request) {
|
||||||
.name = cat->name,
|
.name = cat->name,
|
||||||
|
.list = proto_work_list(c->proto),
|
||||||
.trace_routes = c->debug | c->proto->debug,
|
.trace_routes = c->debug | c->proto->debug,
|
||||||
.dump_req = channel_in_push_dump_req,
|
.dump_req = channel_in_push_dump_req,
|
||||||
.log_state_change = channel_push_log_state_change,
|
.log_state_change = channel_push_log_state_change,
|
||||||
@ -928,6 +930,7 @@ channel_setup_out_table(struct channel *c)
|
|||||||
c->out_table = &cat->cat;
|
c->out_table = &cat->cat;
|
||||||
c->out_table->push = (struct rt_import_request) {
|
c->out_table->push = (struct rt_import_request) {
|
||||||
.name = cat->name,
|
.name = cat->name,
|
||||||
|
.list = proto_work_list(c->proto),
|
||||||
.trace_routes = c->debug | c->proto->debug,
|
.trace_routes = c->debug | c->proto->debug,
|
||||||
.dump_req = channel_out_push_dump_req,
|
.dump_req = channel_out_push_dump_req,
|
||||||
.log_state_change = channel_push_log_state_change,
|
.log_state_change = channel_push_log_state_change,
|
||||||
|
@ -170,6 +170,7 @@ typedef struct rtable_private {
|
|||||||
struct hmap id_map;
|
struct hmap id_map;
|
||||||
struct hostcache *hostcache;
|
struct hostcache *hostcache;
|
||||||
struct event *prune_event; /* Event to prune abandoned routes */
|
struct event *prune_event; /* Event to prune abandoned routes */
|
||||||
|
struct event *announce_event; /* Event to announce pending exports */
|
||||||
struct event *ec_event; /* Event to prune finished exports */
|
struct event *ec_event; /* Event to prune finished exports */
|
||||||
struct event *hcu_event; /* Event to update host cache */
|
struct event *hcu_event; /* Event to update host cache */
|
||||||
struct event *delete_event; /* Event to delete the table */
|
struct event *delete_event; /* Event to delete the table */
|
||||||
@ -191,8 +192,6 @@ typedef struct rtable_private {
|
|||||||
struct timer *settle_timer; /* Settle time for notifications */
|
struct timer *settle_timer; /* Settle time for notifications */
|
||||||
|
|
||||||
list pending_exports; /* List of packed struct rt_pending_export */
|
list pending_exports; /* List of packed struct rt_pending_export */
|
||||||
btime base_export_time; /* When first pending export was announced */
|
|
||||||
struct timer *export_timer;
|
|
||||||
|
|
||||||
struct rt_pending_export *first_export; /* First export to announce */
|
struct rt_pending_export *first_export; /* First export to announce */
|
||||||
u64 next_export_seq; /* The next export will have this ID */
|
u64 next_export_seq; /* The next export will have this ID */
|
||||||
@ -221,7 +220,6 @@ struct rtable_config {
|
|||||||
byte sorted; /* Routes of network are sorted according to rte_better() */
|
byte sorted; /* Routes of network are sorted according to rte_better() */
|
||||||
btime min_settle_time; /* Minimum settle time for notifications */
|
btime min_settle_time; /* Minimum settle time for notifications */
|
||||||
btime max_settle_time; /* Maximum settle time for notifications */
|
btime max_settle_time; /* Maximum settle time for notifications */
|
||||||
btime export_settle_time; /* Delay before exports are announced */
|
|
||||||
uint cork_limit; /* Amount of routes to be pending on export to cork imports */
|
uint cork_limit; /* Amount of routes to be pending on export to cork imports */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -309,6 +307,8 @@ struct rt_import_request {
|
|||||||
char *name;
|
char *name;
|
||||||
u8 trace_routes;
|
u8 trace_routes;
|
||||||
|
|
||||||
|
event_list *list; /* Where to schedule import events */
|
||||||
|
|
||||||
void (*dump_req)(struct rt_import_request *req);
|
void (*dump_req)(struct rt_import_request *req);
|
||||||
void (*log_state_change)(struct rt_import_request *req, u8 state);
|
void (*log_state_change)(struct rt_import_request *req, u8 state);
|
||||||
/* Preimport is called when the @new route is just-to-be inserted, replacing @old.
|
/* Preimport is called when the @new route is just-to-be inserted, replacing @old.
|
||||||
@ -339,6 +339,7 @@ struct rt_import_hook {
|
|||||||
u8 stale_pruned; /* Last prune finished when this value was set at stale_valid */
|
u8 stale_pruned; /* Last prune finished when this value was set at stale_valid */
|
||||||
u8 stale_pruning; /* Last prune started when this value was set at stale_valid */
|
u8 stale_pruning; /* Last prune started when this value was set at stale_valid */
|
||||||
|
|
||||||
|
struct event *export_announce_event; /* Event to run to announce new exports */
|
||||||
struct event *stopped; /* Event to run when import is stopped */
|
struct event *stopped; /* Event to run when import is stopped */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1023,8 +1023,6 @@ rte_announce(rtable_private *tab, net *net, struct rte_storage *new, struct rte_
|
|||||||
rt_notify_hostcache(tab, net);
|
rt_notify_hostcache(tab, net);
|
||||||
}
|
}
|
||||||
|
|
||||||
rt_schedule_notify(tab);
|
|
||||||
|
|
||||||
if (EMPTY_LIST(tab->exports) && EMPTY_LIST(tab->pending_exports))
|
if (EMPTY_LIST(tab->exports) && EMPTY_LIST(tab->pending_exports))
|
||||||
{
|
{
|
||||||
/* 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. */
|
||||||
@ -1105,10 +1103,7 @@ rte_announce(rtable_private *tab, net *net, struct rte_storage *new, struct rte_
|
|||||||
{
|
{
|
||||||
ev_cork(&rt_cork);
|
ev_cork(&rt_cork);
|
||||||
tab->cork_active = 1;
|
tab->cork_active = 1;
|
||||||
tm_start_in(tab->export_timer, 0, tab->loop);
|
|
||||||
}
|
}
|
||||||
else if (!tm_active(tab->export_timer))
|
|
||||||
tm_start_in(tab->export_timer, tab->config->export_settle_time, tab->loop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct rt_pending_export *
|
static struct rt_pending_export *
|
||||||
@ -1158,11 +1153,13 @@ rt_send_export_event(struct rt_export_hook *hook)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rt_announce_exports(timer *tm)
|
rt_announce_exports(void *data)
|
||||||
{
|
{
|
||||||
rtable_private *tab = tm->data;
|
rtable_private *tab = data;
|
||||||
ASSERT_DIE(birdloop_inside(tab->loop));
|
ASSERT_DIE(birdloop_inside(tab->loop));
|
||||||
|
|
||||||
|
rt_schedule_notify(tab);
|
||||||
|
|
||||||
struct rt_export_hook *c; node *n;
|
struct rt_export_hook *c; node *n;
|
||||||
WALK_LIST2(c, n, tab->exports, n)
|
WALK_LIST2(c, n, tab->exports, n)
|
||||||
{
|
{
|
||||||
@ -1173,6 +1170,26 @@ rt_announce_exports(timer *tm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rt_import_announce_exports(void *data)
|
||||||
|
{
|
||||||
|
struct rt_import_hook *hook = data;
|
||||||
|
RT_LOCKED(hook->table, tab)
|
||||||
|
{
|
||||||
|
if (hook->import_state == TIS_CLEARED)
|
||||||
|
{
|
||||||
|
rfree(hook->export_announce_event);
|
||||||
|
|
||||||
|
ev_send(hook->stopped->list, hook->stopped);
|
||||||
|
rem_node(&hook->n);
|
||||||
|
mb_free(hook);
|
||||||
|
rt_unlock_table(tab);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ev_send_loop(tab->loop, tab->announce_event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct rt_pending_export *
|
static struct rt_pending_export *
|
||||||
rt_last_export(rtable_private *tab)
|
rt_last_export(rtable_private *tab)
|
||||||
{
|
{
|
||||||
@ -1471,6 +1488,8 @@ rte_recalculate(rtable_private *table, struct rt_import_hook *c, net *net, rte *
|
|||||||
rte_announce(table, net, new_stored, old_stored,
|
rte_announce(table, net, new_stored, old_stored,
|
||||||
net->routes, old_best_stored);
|
net->routes, old_best_stored);
|
||||||
|
|
||||||
|
ev_send(req->list, c->export_announce_event);
|
||||||
|
|
||||||
if (!net->routes &&
|
if (!net->routes &&
|
||||||
(table->gc_counter++ >= table->config->gc_max_ops) &&
|
(table->gc_counter++ >= table->config->gc_max_ops) &&
|
||||||
(table->gc_time + table->config->gc_min_time <= current_time()))
|
(table->gc_time + table->config->gc_min_time <= current_time()))
|
||||||
@ -1709,6 +1728,8 @@ rt_request_import(rtable *t, struct rt_import_request *req)
|
|||||||
hook->req = req;
|
hook->req = req;
|
||||||
hook->table = t;
|
hook->table = t;
|
||||||
|
|
||||||
|
hook->export_announce_event = ev_new_init(tab->rp, rt_import_announce_exports, hook);
|
||||||
|
|
||||||
if (!hook->stale_set)
|
if (!hook->stale_set)
|
||||||
hook->stale_set = hook->stale_valid = hook->stale_pruning = hook->stale_pruned = 1;
|
hook->stale_set = hook->stale_valid = hook->stale_pruning = hook->stale_pruned = 1;
|
||||||
|
|
||||||
@ -1727,11 +1748,12 @@ rt_stop_import(struct rt_import_request *req, event *stopped)
|
|||||||
struct rt_import_hook *hook = req->hook;
|
struct rt_import_hook *hook = req->hook;
|
||||||
|
|
||||||
RT_LOCK(hook->table);
|
RT_LOCK(hook->table);
|
||||||
|
|
||||||
rt_schedule_prune(RT_PRIV(hook->table));
|
rt_schedule_prune(RT_PRIV(hook->table));
|
||||||
|
|
||||||
rt_set_import_state(hook, TIS_STOP);
|
rt_set_import_state(hook, TIS_STOP);
|
||||||
|
|
||||||
hook->stopped = stopped;
|
hook->stopped = stopped;
|
||||||
|
|
||||||
RT_UNLOCK(hook->table);
|
RT_UNLOCK(hook->table);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2158,6 +2180,7 @@ rt_setup(pool *pp, struct rtable_config *cf)
|
|||||||
|
|
||||||
t->loop = birdloop_new(p, DOMAIN_ORDER(rtable), nb);
|
t->loop = birdloop_new(p, DOMAIN_ORDER(rtable), nb);
|
||||||
|
|
||||||
|
t->announce_event = ev_new_init(p, rt_announce_exports, t);
|
||||||
t->ec_event = ev_new_init(p, rt_export_cleanup, t);
|
t->ec_event = ev_new_init(p, rt_export_cleanup, t);
|
||||||
t->prune_event = ev_new_init(p, rt_prune_table, t);
|
t->prune_event = ev_new_init(p, rt_prune_table, t);
|
||||||
t->hcu_event = ev_new_init(p, rt_update_hostcache, t);
|
t->hcu_event = ev_new_init(p, rt_update_hostcache, t);
|
||||||
@ -2166,7 +2189,6 @@ rt_setup(pool *pp, struct rtable_config *cf)
|
|||||||
t->nhu_event->cork = &rt_cork;
|
t->nhu_event->cork = &rt_cork;
|
||||||
t->prune_event->cork = &rt_cork;
|
t->prune_event->cork = &rt_cork;
|
||||||
|
|
||||||
t->export_timer = tm_new_init(p, rt_announce_exports, t, 0, 0);
|
|
||||||
t->last_rt_change = t->gc_time = current_time();
|
t->last_rt_change = t->gc_time = current_time();
|
||||||
t->next_export_seq = 1;
|
t->next_export_seq = 1;
|
||||||
|
|
||||||
@ -2472,15 +2494,11 @@ done:;
|
|||||||
if (!first_export || (first_export->seq >= ih->flush_seq))
|
if (!first_export || (first_export->seq >= ih->flush_seq))
|
||||||
{
|
{
|
||||||
ih->import_state = TIS_CLEARED;
|
ih->import_state = TIS_CLEARED;
|
||||||
ev_send(ih->stopped->list, ih->stopped);
|
ev_send(ih->req->list, ih->export_announce_event);
|
||||||
rem_node(&ih->n);
|
|
||||||
mb_free(ih);
|
|
||||||
rt_unlock_table(tab);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (EMPTY_LIST(tab->pending_exports) && ev_active(tab->announce_event))
|
||||||
if (EMPTY_LIST(tab->pending_exports) && tm_active(tab->export_timer))
|
ev_postpone(tab->announce_event);
|
||||||
tm_stop(tab->export_timer);
|
|
||||||
|
|
||||||
/* If reduced to at most one export block pending */
|
/* If reduced to at most one export block pending */
|
||||||
if (tab->cork_active &&
|
if (tab->cork_active &&
|
||||||
@ -2753,6 +2771,8 @@ rt_next_hop_update(void *data)
|
|||||||
if (atomic_fetch_and_explicit(&tab->nhu_state, NHU_SCHEDULED, memory_order_acq_rel) != NHU_RUNNING)
|
if (atomic_fetch_and_explicit(&tab->nhu_state, NHU_SCHEDULED, memory_order_acq_rel) != NHU_RUNNING)
|
||||||
ev_send_loop(tab->loop, tab->nhu_event);
|
ev_send_loop(tab->loop, tab->nhu_event);
|
||||||
|
|
||||||
|
ev_send_loop(tab->loop, tab->announce_event);
|
||||||
|
|
||||||
rt_unlock_table(tab);
|
rt_unlock_table(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2809,6 +2829,7 @@ rt_loop_stopped(void *data)
|
|||||||
r->loop = NULL;
|
r->loop = NULL;
|
||||||
r->prune_event->list = r->ec_event->list = NULL;
|
r->prune_event->list = r->ec_event->list = NULL;
|
||||||
r->nhu_event->list = r->hcu_event->list = NULL;
|
r->nhu_event->list = r->hcu_event->list = NULL;
|
||||||
|
r->announce_event->list = NULL;
|
||||||
ev_send(r->delete_event->list, r->delete_event);
|
ev_send(r->delete_event->list, r->delete_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user