From c56752e4367733c03a05e65ba62ccd2e54f7aadd Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Mon, 21 Jun 2021 19:11:42 +0200 Subject: [PATCH 1/2] Protocol stats split to import and export --- nest/proto.c | 45 +++++++++++++------------ nest/protocol.h | 46 +++++++++++++------------ nest/rt-table.c | 86 +++++++++++++++++++++++------------------------ proto/pipe/pipe.c | 24 +++++++------ 4 files changed, 105 insertions(+), 96 deletions(-) diff --git a/nest/proto.c b/nest/proto.c index 7cfb1555..631e4b60 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -284,7 +284,7 @@ channel_feed_loop(void *ptr) if (c->refeeding && (l->state == PLS_BLOCKED) && (c->refeed_count <= l->limit) && - (c->stats.exp_routes <= l->limit)) + (c->export_stats.routes <= l->limit)) { log(L_INFO "Protocol %s resets route export limit (%u)", c->proto->name, l->limit); channel_reset_limit(&c->out_limit); @@ -461,7 +461,7 @@ channel_stop_export(struct channel *c) rt_feed_channel_abort(c); c->export_state = ES_DOWN; - c->stats.exp_routes = 0; + c->export_stats.routes = 0; bmap_reset(&c->export_map, 1024); } @@ -551,7 +551,8 @@ channel_do_start(struct channel *c) c->feed_event = ev_new_init(c->proto->pool, channel_feed_loop, c); bmap_init(&c->export_map, c->proto->pool, 1024); - memset(&c->stats, 0, sizeof(struct proto_stats)); + memset(&c->export_stats, 0, sizeof(struct export_stats)); + memset(&c->import_stats, 0, sizeof(struct import_stats)); channel_reset_limit(&c->rx_limit); channel_reset_limit(&c->in_limit); @@ -600,11 +601,12 @@ channel_do_down(struct channel *c) rt_unlock_table(c->table); c->proto->active_channels--; - if ((c->stats.imp_routes + c->stats.filt_routes) != 0) + if ((c->import_stats.routes + c->import_stats.filtered) != 0) log(L_ERR "%s: Channel %s is down but still has some routes", c->proto->name, c->name); // bmap_free(&c->export_map); - memset(&c->stats, 0, sizeof(struct proto_stats)); + memset(&c->import_stats, 0, sizeof(struct import_stats)); + memset(&c->export_stats, 0, sizeof(struct export_stats)); c->in_table = NULL; c->reload_event = NULL; @@ -1842,19 +1844,19 @@ static void channel_verify_limits(struct channel *c) { struct channel_limit *l; - u32 all_routes = c->stats.imp_routes + c->stats.filt_routes; + u32 all_routes = c->import_stats.routes + c->import_stats.filtered; l = &c->rx_limit; if (l->action && (all_routes > l->limit)) channel_notify_limit(c, l, PLD_RX, all_routes); l = &c->in_limit; - if (l->action && (c->stats.imp_routes > l->limit)) - channel_notify_limit(c, l, PLD_IN, c->stats.imp_routes); + if (l->action && (c->import_stats.routes > l->limit)) + channel_notify_limit(c, l, PLD_IN, c->import_stats.routes); l = &c->out_limit; - if (l->action && (c->stats.exp_routes > l->limit)) - channel_notify_limit(c, l, PLD_OUT, c->stats.exp_routes); + if (l->action && (c->export_stats.routes > l->limit)) + channel_notify_limit(c, l, PLD_OUT, c->export_stats.routes); } static inline void @@ -2009,28 +2011,29 @@ proto_state_name(struct proto *p) static void channel_show_stats(struct channel *c) { - struct proto_stats *s = &c->stats; + struct import_stats *is = &c->import_stats; + struct export_stats *es = &c->export_stats; if (c->in_keep_filtered) cli_msg(-1006, " Routes: %u imported, %u filtered, %u exported, %u preferred", - s->imp_routes, s->filt_routes, s->exp_routes, s->pref_routes); + is->routes, is->filtered, es->routes, is->pref); else cli_msg(-1006, " Routes: %u imported, %u exported, %u preferred", - s->imp_routes, s->exp_routes, s->pref_routes); + is->routes, es->routes, is->pref); cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted"); cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u", - s->imp_updates_received, s->imp_updates_invalid, - s->imp_updates_filtered, s->imp_updates_ignored, - s->imp_updates_accepted); + is->updates_received, is->updates_invalid, + is->updates_filtered, is->updates_ignored, + is->updates_accepted); cli_msg(-1006, " Import withdraws: %10u %10u --- %10u %10u", - s->imp_withdraws_received, s->imp_withdraws_invalid, - s->imp_withdraws_ignored, s->imp_withdraws_accepted); + is->withdraws_received, is->withdraws_invalid, + is->withdraws_ignored, is->withdraws_accepted); cli_msg(-1006, " Export updates: %10u %10u %10u --- %10u", - s->exp_updates_received, s->exp_updates_rejected, - s->exp_updates_filtered, s->exp_updates_accepted); + es->updates_received, es->updates_rejected, + es->updates_filtered, es->updates_accepted); cli_msg(-1006, " Export withdraws: %10u --- --- --- %10u", - s->exp_withdraws_received, s->exp_withdraws_accepted); + es->withdraws_received, es->withdraws_accepted); } void diff --git a/nest/protocol.h b/nest/protocol.h index 80b4509b..9be8e531 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -132,29 +132,31 @@ struct proto_config { }; /* Protocol statistics */ -struct proto_stats { +struct import_stats { /* Import - from protocol to core */ - u32 imp_routes; /* Number of routes successfully imported to the (adjacent) routing table */ - u32 filt_routes; /* Number of routes rejected in import filter but kept in the routing table */ - u32 pref_routes; /* Number of routes selected as best in the (adjacent) routing table */ - u32 imp_updates_received; /* Number of route updates received */ - u32 imp_updates_invalid; /* Number of route updates rejected as invalid */ - u32 imp_updates_filtered; /* Number of route updates rejected by filters */ - u32 imp_updates_ignored; /* Number of route updates rejected as already in route table */ - u32 imp_updates_accepted; /* Number of route updates accepted and imported */ - u32 imp_withdraws_received; /* Number of route withdraws received */ - u32 imp_withdraws_invalid; /* Number of route withdraws rejected as invalid */ - u32 imp_withdraws_ignored; /* Number of route withdraws rejected as already not in route table */ - u32 imp_withdraws_accepted; /* Number of route withdraws accepted and processed */ + u32 routes; /* Number of routes successfully imported to the (adjacent) routing table */ + u32 filtered; /* Number of routes rejected in import filter but kept in the routing table */ + u32 pref; /* Number of routes selected as best in the (adjacent) routing table */ + u32 updates_received; /* Number of route updates received */ + u32 updates_invalid; /* Number of route updates rejected as invalid */ + u32 updates_filtered; /* Number of route updates rejected by filters */ + u32 updates_ignored; /* Number of route updates rejected as already in route table */ + u32 updates_accepted; /* Number of route updates accepted and imported */ + u32 withdraws_received; /* Number of route withdraws received */ + u32 withdraws_invalid; /* Number of route withdraws rejected as invalid */ + u32 withdraws_ignored; /* Number of route withdraws rejected as already not in route table */ + u32 withdraws_accepted; /* Number of route withdraws accepted and processed */ +}; +struct export_stats { /* Export - from core to protocol */ - u32 exp_routes; /* Number of routes successfully exported to the protocol */ - u32 exp_updates_received; /* Number of route updates received */ - u32 exp_updates_rejected; /* Number of route updates rejected by protocol */ - u32 exp_updates_filtered; /* Number of route updates rejected by filters */ - u32 exp_updates_accepted; /* Number of route updates accepted and exported */ - u32 exp_withdraws_received; /* Number of route withdraws received */ - u32 exp_withdraws_accepted; /* Number of route withdraws accepted and processed */ + u32 routes; /* Number of routes successfully exported to the protocol */ + u32 updates_received; /* Number of route updates received */ + u32 updates_rejected; /* Number of route updates rejected by protocol */ + u32 updates_filtered; /* Number of route updates rejected by filters */ + u32 updates_accepted; /* Number of route updates accepted and exported */ + u32 withdraws_received; /* Number of route withdraws received */ + u32 withdraws_accepted; /* Number of route withdraws accepted and processed */ }; struct proto { @@ -516,7 +518,9 @@ struct channel { struct event *feed_event; /* Event responsible for feeding */ struct fib_iterator feed_fit; /* Routing table iterator used during feeding */ - struct proto_stats stats; /* Per-channel protocol statistics */ + struct import_stats import_stats; /* Import statistics */ + struct export_stats export_stats; /* Export statistics */ + u32 refeed_count; /* Number of routes exported during refeed regardless of out_limit */ u8 net_type; /* Routing table network type (NET_*), 0 for undefined */ diff --git a/nest/rt-table.c b/nest/rt-table.c index 6851b4bc..0b6351e9 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -375,7 +375,7 @@ export_filter_(struct channel *c, rte *rt, linpool *pool, int silent) { struct proto *p = c->proto; const struct filter *filter = c->out_filter; - struct proto_stats *stats = &c->stats; + struct export_stats *stats = &c->export_stats; int v; v = p->preexport ? p->preexport(c, rt) : 0; @@ -384,7 +384,7 @@ export_filter_(struct channel *c, rte *rt, linpool *pool, int silent) if (silent) goto reject; - stats->exp_updates_rejected++; + stats->updates_rejected++; if (v == RIC_REJECT) rte_trace_out(D_FILTERS, c, rt, "rejected by protocol"); goto reject; @@ -404,7 +404,7 @@ export_filter_(struct channel *c, rte *rt, linpool *pool, int silent) if (silent) goto reject; - stats->exp_updates_filtered++; + stats->updates_filtered++; rte_trace_out(D_FILTERS, c, rt, "filtered out"); goto reject; } @@ -427,7 +427,7 @@ static void do_rt_notify(struct channel *c, const net_addr *net, rte *new, rte *old, int refeed) { struct proto *p = c->proto; - struct proto_stats *stats = &c->stats; + struct export_stats *stats = &c->export_stats; if (refeed && new) c->refeed_count++; @@ -436,12 +436,12 @@ do_rt_notify(struct channel *c, const net_addr *net, rte *new, rte *old, int ref struct channel_limit *l = &c->out_limit; if (l->action && !old && new) { - if (stats->exp_routes >= l->limit) - channel_notify_limit(c, l, PLD_OUT, stats->exp_routes); + if (stats->routes >= l->limit) + channel_notify_limit(c, l, PLD_OUT, stats->routes); if (l->state == PLS_BLOCKED) { - stats->exp_updates_rejected++; + stats->updates_rejected++; rte_trace_out(D_FILTERS, c, new, "rejected [limit]"); return; } @@ -459,20 +459,20 @@ do_rt_notify(struct channel *c, const net_addr *net, rte *new, rte *old, int ref } if (new) - stats->exp_updates_accepted++; + stats->updates_accepted++; else - stats->exp_withdraws_accepted++; + stats->withdraws_accepted++; if (old) { bmap_clear(&c->export_map, old->id); - stats->exp_routes--; + stats->routes--; } if (new) { bmap_set(&c->export_map, new->id); - stats->exp_routes++; + stats->routes++; } if (p->debug & D_ROUTES) @@ -495,9 +495,9 @@ static void rt_notify_basic(struct channel *c, const net_addr *net, rte *new, rte *old, int refeed) { if (new) - c->stats.exp_updates_received++; + c->export_stats.updates_received++; else - c->stats.exp_withdraws_received++; + c->export_stats.withdraws_received++; if (new) new = export_filter(c, new, 0); @@ -537,9 +537,9 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang */ if (net->routes) - c->stats.exp_updates_received++; + c->export_stats.updates_received++; else - c->stats.exp_withdraws_received++; + c->export_stats.withdraws_received++; /* Find old_best - either old_changed, or route for net->routes */ if (old_changed && bmap_test(&c->export_map, old_changed->id)) @@ -655,9 +655,9 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed return; if (new_best) - c->stats.exp_updates_received++; + c->export_stats.updates_received++; else - c->stats.exp_withdraws_received++; + c->export_stats.withdraws_received++; /* Prepare new merged route */ if (new_best) @@ -735,9 +735,9 @@ rte_announce(rtable *tab, uint type, net *net, struct rte_storage *new, struct r if (new_best != old_best) { if (new_best) - new_best->rte.sender->stats.pref_routes++; + new_best->rte.sender->import_stats.pref++; if (old_best) - old_best->rte.sender->stats.pref_routes--; + old_best->rte.sender->import_stats.pref--; if (tab->hostcache) rt_notify_hostcache(tab, net); @@ -836,7 +836,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) { struct proto *p = c->proto; struct rtable *table = c->table; - struct proto_stats *stats = &c->stats; + struct import_stats *stats = &c->import_stats; struct rte_storage *old_best_stored = net->routes, *old_stored = NULL; rte *old_best = old_best_stored ? &old_best_stored->rte : NULL; rte *old = NULL; @@ -873,7 +873,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) if (!rte_is_filtered(new)) { - stats->imp_updates_ignored++; + stats->updates_ignored++; rte_trace_in(D_ROUTES, c, new, "ignored"); } @@ -887,7 +887,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) if (!old && !new) { - stats->imp_withdraws_ignored++; + stats->withdraws_ignored++; return; } @@ -897,7 +897,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) struct channel_limit *l = &c->rx_limit; if (l->action && !old && new && !c->in_table) { - u32 all_routes = stats->imp_routes + stats->filt_routes; + u32 all_routes = stats->routes + stats->filtered; if (all_routes >= l->limit) channel_notify_limit(c, l, PLD_RX, all_routes); @@ -907,7 +907,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) /* In receive limit the situation is simple, old is NULL so we just free new and exit like nothing happened */ - stats->imp_updates_ignored++; + stats->updates_ignored++; rte_trace_in(D_FILTERS, c, new, "ignored [limit]"); return; } @@ -916,8 +916,8 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) l = &c->in_limit; if (l->action && !old_ok && new_ok) { - if (stats->imp_routes >= l->limit) - channel_notify_limit(c, l, PLD_IN, stats->imp_routes); + if (stats->routes >= l->limit) + channel_notify_limit(c, l, PLD_IN, stats->routes); if (l->state == PLS_BLOCKED) { @@ -928,7 +928,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) if both are NULL as this case is probably assumed to be already handled. */ - stats->imp_updates_ignored++; + stats->updates_ignored++; rte_trace_in(D_FILTERS, c, new, "ignored [limit]"); if (c->in_keep_filtered) @@ -948,11 +948,11 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) } if (new_ok) - stats->imp_updates_accepted++; + stats->updates_accepted++; else if (old_ok) - stats->imp_withdraws_accepted++; + stats->withdraws_accepted++; else - stats->imp_withdraws_ignored++; + stats->withdraws_ignored++; if (old_ok || new_ok) table->last_rt_change = current_time(); @@ -961,9 +961,9 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) struct rte_storage *new_stored = new ? rte_store(new, net, table) : NULL; if (new) - rte_is_filtered(new) ? stats->filt_routes++ : stats->imp_routes++; + rte_is_filtered(new) ? stats->filtered++ : stats->routes++; if (old) - rte_is_filtered(old) ? stats->filt_routes-- : stats->imp_routes--; + rte_is_filtered(old) ? stats->filtered-- : stats->routes--; if (table->config->sorted) { @@ -1128,7 +1128,7 @@ rte_update(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) if (c->in_table && !rte_update_in(c, n, new, src)) return; - struct proto_stats *stats = &c->stats; + struct import_stats *stats = &c->import_stats; const struct filter *filter = c->in_filter; net *nn; @@ -1140,17 +1140,17 @@ rte_update(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) new->net = n; new->sender = c; - stats->imp_updates_received++; + stats->updates_received++; if (!rte_validate(new)) { rte_trace_in(D_FILTERS, c, new, "invalid"); - stats->imp_updates_invalid++; + stats->updates_invalid++; goto drop; } if (filter == FILTER_REJECT) { - stats->imp_updates_filtered++; + stats->updates_filtered++; rte_trace_in(D_FILTERS, c, new, "filtered out"); if (! c->in_keep_filtered) @@ -1164,7 +1164,7 @@ rte_update(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) int fr = f_run(filter, new, rte_update_pool, 0); if (fr > F_ACCEPT) { - stats->imp_updates_filtered++; + stats->updates_filtered++; rte_trace_in(D_FILTERS, c, new, "filtered out"); if (! c->in_keep_filtered) @@ -1180,11 +1180,11 @@ rte_update(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) } else { - stats->imp_withdraws_received++; + stats->withdraws_received++; if (!(nn = net_find(c->table, n)) || !src) { - stats->imp_withdraws_ignored++; + stats->withdraws_ignored++; rte_update_unlock(); return; } @@ -2297,8 +2297,8 @@ rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *sr return 1; drop_update: - c->stats.imp_updates_received++; - c->stats.imp_updates_ignored++; + c->import_stats.updates_received++; + c->import_stats.updates_ignored++; if (!net->routes) fib_delete(&tab->fib, net); @@ -2306,8 +2306,8 @@ drop_update: return 0; drop_withdraw: - c->stats.imp_withdraws_received++; - c->stats.imp_withdraws_ignored++; + c->import_stats.withdraws_received++; + c->import_stats.withdraws_ignored++; return 0; } diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index 7604cc79..55a0b526 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -212,8 +212,10 @@ pipe_get_status(struct proto *P, byte *buf) static void pipe_show_stats(struct pipe_proto *p) { - struct proto_stats *s1 = &p->pri->stats; - struct proto_stats *s2 = &p->sec->stats; + struct import_stats *s1i = &p->pri->import_stats; + struct export_stats *s1e = &p->pri->export_stats; + struct import_stats *s2i = &p->sec->import_stats; + struct export_stats *s2e = &p->sec->export_stats; /* * Pipe stats (as anything related to pipes) are a bit tricky. There @@ -237,20 +239,20 @@ pipe_show_stats(struct pipe_proto *p) */ cli_msg(-1006, " Routes: %u imported, %u exported", - s1->imp_routes, s2->imp_routes); + s1i->routes, s2i->routes); cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted"); cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u", - s2->exp_updates_received, s2->exp_updates_rejected + s1->imp_updates_invalid, - s2->exp_updates_filtered, s1->imp_updates_ignored, s1->imp_updates_accepted); + s2e->updates_received, s2e->updates_rejected + s1i->updates_invalid, + s2e->updates_filtered, s1i->updates_ignored, s1i->updates_accepted); cli_msg(-1006, " Import withdraws: %10u %10u --- %10u %10u", - s2->exp_withdraws_received, s1->imp_withdraws_invalid, - s1->imp_withdraws_ignored, s1->imp_withdraws_accepted); + s2e->withdraws_received, s1i->withdraws_invalid, + s1i->withdraws_ignored, s1i->withdraws_accepted); cli_msg(-1006, " Export updates: %10u %10u %10u %10u %10u", - s1->exp_updates_received, s1->exp_updates_rejected + s2->imp_updates_invalid, - s1->exp_updates_filtered, s2->imp_updates_ignored, s2->imp_updates_accepted); + s1e->updates_received, s1e->updates_rejected + s2i->updates_invalid, + s1e->updates_filtered, s2i->updates_ignored, s2i->updates_accepted); cli_msg(-1006, " Export withdraws: %10u %10u --- %10u %10u", - s1->exp_withdraws_received, s2->imp_withdraws_invalid, - s2->imp_withdraws_ignored, s2->imp_withdraws_accepted); + s1e->withdraws_received, s2i->withdraws_invalid, + s2i->withdraws_ignored, s2i->withdraws_accepted); } static const char *pipe_feed_state[] = { [ES_DOWN] = "down", [ES_FEEDING] = "feed", [ES_READY] = "up" }; From 8f3942a97e16370f5c22e9c39ddbfe63b38bd5ce Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Mon, 9 Mar 2020 15:31:10 +0100 Subject: [PATCH 2/2] Route export: rejected by filter bitmap If a route has been rejected by filter, store that information to avoid repeated export filter runs on rejected routes. --- nest/proto.c | 3 +++ nest/protocol.h | 3 ++- nest/rt-table.c | 51 ++++++++++++++++++++++++++++++------------------- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/nest/proto.c b/nest/proto.c index 631e4b60..c7e25209 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -463,6 +463,7 @@ channel_stop_export(struct channel *c) c->export_state = ES_DOWN; c->export_stats.routes = 0; bmap_reset(&c->export_map, 1024); + bmap_reset(&c->export_reject_map, 1024); } @@ -551,6 +552,7 @@ channel_do_start(struct channel *c) c->feed_event = ev_new_init(c->proto->pool, channel_feed_loop, c); bmap_init(&c->export_map, c->proto->pool, 1024); + bmap_init(&c->export_reject_map, c->proto->pool, 1024); memset(&c->export_stats, 0, sizeof(struct export_stats)); memset(&c->import_stats, 0, sizeof(struct import_stats)); @@ -585,6 +587,7 @@ channel_do_flush(struct channel *c) /* This have to be done in here, as channel pool is freed before channel_do_down() */ bmap_free(&c->export_map); + bmap_free(&c->export_reject_map); c->in_table = NULL; c->reload_event = NULL; c->out_table = NULL; diff --git a/nest/protocol.h b/nest/protocol.h index 9be8e531..4c87c72d 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -511,7 +511,8 @@ struct channel { struct rtable *table; const struct filter *in_filter; /* Input filter */ const struct filter *out_filter; /* Output filter */ - struct bmap export_map; /* Keeps track which routes passed export filter */ + struct bmap export_map; /* Keeps track which routes were really exported */ + struct bmap export_reject_map; /* Keeps track which routes were rejected by export filter */ struct channel_limit rx_limit; /* Receive limit (for in_keep_filtered) */ struct channel_limit in_limit; /* Input limit */ struct channel_limit out_limit; /* Output limit */ diff --git a/nest/rt-table.c b/nest/rt-table.c index 0b6351e9..280551aa 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -376,18 +376,22 @@ export_filter_(struct channel *c, rte *rt, linpool *pool, int silent) struct proto *p = c->proto; const struct filter *filter = c->out_filter; struct export_stats *stats = &c->export_stats; - int v; - v = p->preexport ? p->preexport(c, rt) : 0; + /* Do nothing if we have already rejected the route */ + if (silent && bmap_test(&c->export_reject_map, rt->id)) + goto reject_noset; + + int v = p->preexport ? p->preexport(c, rt) : 0; if (v < 0) { if (silent) - goto reject; + goto reject_noset; stats->updates_rejected++; if (v == RIC_REJECT) rte_trace_out(D_FILTERS, c, rt, "rejected by protocol"); - goto reject; + goto reject_noset; + } if (v > 0) { @@ -410,9 +414,16 @@ export_filter_(struct channel *c, rte *rt, linpool *pool, int silent) } accept: + /* We have accepted the route */ + bmap_clear(&c->export_reject_map, rt->id); return rt; reject: + /* We have rejected the route by filter */ + bmap_set(&c->export_reject_map, rt->id); + +reject_noset: + /* Invalidate the route */ /* Discard temporary rte */ return NULL; } @@ -565,8 +576,14 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang { /* Feed or old_best changed -> find first accepted by filters */ for (struct rte_storage *r = net->routes; r && rte_is_valid(&r->rte); r = r->next) + { + /* Already rejected before */ + if (!refeed && bmap_test(&c->export_reject_map, r->rte.id)) + continue; + if (new_best = export_filter(c, ((nb0 = r->rte), &nb0), 0)) break; + } } else { @@ -677,7 +694,6 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed /** * rte_announce - announce a routing table change * @tab: table the route has been added to - * @type: type of route announcement (RA_UNDEF or RA_ANY) * @net: network in question * @new: the new or changed route * @old: the previous route replaced by the new one @@ -693,13 +709,6 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed * and @new_best and @old_best describes best routes. Other routes are not * affected, but in sorted table the order of other routes might change. * - * Second, There is a bulk change of multiple routes in @net, with shared best - * route selection. In such case separate route changes are described using - * @type of %RA_ANY, with @new and @old specifying the changed route, while - * @new_best and @old_best are NULL. After that, another notification is done - * where @new_best and @old_best are filled (may be the same), but @new and @old - * are NULL. - * * The function announces the change to all associated channels. For each * channel, an appropriate preprocessing is done according to channel &ra_mode. * For example, %RA_OPTIMAL channels receive just changes of best routes. @@ -714,7 +723,7 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed * done outside of scope of rte_announce(). */ static void -rte_announce(rtable *tab, uint type, net *net, struct rte_storage *new, struct rte_storage *old, +rte_announce(rtable *tab, net *net, struct rte_storage *new, struct rte_storage *old, struct rte_storage *new_best, struct rte_storage *old_best) { if (!new || !rte_is_valid(&new->rte)) @@ -751,9 +760,6 @@ rte_announce(rtable *tab, uint type, net *net, struct rte_storage *new, struct r if (c->export_state == ES_DOWN) continue; - if (type && (type != c->ra_mode)) - continue; - rte n0; switch (c->ra_mode) { @@ -775,6 +781,11 @@ rte_announce(rtable *tab, uint type, net *net, struct rte_storage *new, struct r rt_notify_merged(c, net, RTE_OR_NULL(new), RTE_OR_NULL(old), RTE_OR_NULL(new_best), RTE_OR_NULL(old_best), 0); break; } + + /* Drop the old stored rejection if applicable. + * new->id == old->id happens when updating hostentries. */ + if (old && (!new || (new->rte.id != old->rte.id))) + bmap_clear(&c->export_reject_map, old->rte.id); } } @@ -1083,7 +1094,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) } /* Propagate the route change */ - rte_announce(table, RA_UNDEF, net, new_stored, old_stored, + rte_announce(table, net, new_stored, old_stored, net->routes, old_best_stored); if (!net->routes && @@ -1208,11 +1219,11 @@ rte_update(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) /* Independent call to rte_announce(), used from next hop recalculation, outside of rte_update(). new must be non-NULL */ static inline void -rte_announce_i(rtable *tab, uint type, net *net, struct rte_storage *new, struct rte_storage *old, +rte_announce_i(rtable *tab, net *net, struct rte_storage *new, struct rte_storage *old, struct rte_storage *new_best, struct rte_storage *old_best) { rte_update_lock(); - rte_announce(tab, type, net, new, old, new_best, old_best); + rte_announce(tab, net, new, old, new_best, old_best); rte_update_unlock(); } @@ -1938,7 +1949,7 @@ rt_next_hop_update_net(rtable *tab, net *n) _Bool nb = (new == updates[i].new), ob = (old_best == updates[i].old); const char *best_indicator[2][2] = { { "updated", "updated [-best]" }, { "updated [+best]", "updated [best]" } }; rte_trace_in(D_ROUTES, new->rte.sender, &updates[i].new->rte, best_indicator[nb][ob]); - rte_announce_i(tab, RA_UNDEF, n, updates[i].new, updates[i].old, new, old_best); + rte_announce_i(tab, n, updates[i].new, updates[i].old, new, old_best); } for (int i=0; i