diff options
author | Maria Matejka <mq@ucw.cz> | 2020-03-09 15:31:10 +0100 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2021-11-09 19:20:41 +0100 |
commit | 8f3942a97e16370f5c22e9c39ddbfe63b38bd5ce (patch) | |
tree | 991563705788b01b2bcb4ef83f53f40229b08109 /nest | |
parent | c56752e4367733c03a05e65ba62ccd2e54f7aadd (diff) |
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.
Diffstat (limited to 'nest')
-rw-r--r-- | nest/proto.c | 3 | ||||
-rw-r--r-- | nest/protocol.h | 3 | ||||
-rw-r--r-- | 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<count; i++) |