mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
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.
This commit is contained in:
parent
f2e9c7b285
commit
e64fd37675
@ -299,6 +299,7 @@ channel_stop_export(struct channel *c)
|
||||
c->export_state = ES_DOWN;
|
||||
c->stats.exp_routes = 0;
|
||||
bmap_reset(&c->export_map, 1024);
|
||||
bmap_reset(&c->export_reject_map, 1024);
|
||||
}
|
||||
|
||||
|
||||
@ -378,6 +379,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->stats, 0, sizeof(struct proto_stats));
|
||||
|
||||
channel_reset_limit(&c->rx_limit);
|
||||
@ -400,6 +402,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;
|
||||
|
@ -499,7 +499,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 */
|
||||
|
@ -320,7 +320,7 @@ static inline net *net_get(rtable *tab, const net_addr *addr) { return (net *) f
|
||||
void *net_route(rtable *tab, const net_addr *n);
|
||||
int net_roa_check(rtable *tab, const net_addr *n, u32 asn);
|
||||
rte *rte_find(net *net, struct rte_src *src);
|
||||
int rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter);
|
||||
int rt_examine(struct channel *c, net_addr *a);
|
||||
rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent);
|
||||
void rt_refresh_begin(rtable *t, struct channel *c);
|
||||
void rt_refresh_end(rtable *t, struct channel *c);
|
||||
|
@ -434,33 +434,36 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si
|
||||
const struct filter *filter = c->out_filter;
|
||||
struct proto_stats *stats = &c->stats;
|
||||
rte *rt;
|
||||
int v;
|
||||
|
||||
rt = rt0;
|
||||
*rt_free = NULL;
|
||||
|
||||
v = p->preexport ? p->preexport(p, &rt, pool) : 0;
|
||||
if (v < 0)
|
||||
/* Do nothing if we have already rejected the route */
|
||||
if (silent && bmap_test(&c->export_reject_map, rt0->id))
|
||||
return NULL;
|
||||
|
||||
int pv = p->preexport ? p->preexport(p, &rt, pool) : 0;
|
||||
if (pv < 0)
|
||||
{
|
||||
if (silent)
|
||||
goto reject;
|
||||
|
||||
stats->exp_updates_rejected++;
|
||||
if (v == RIC_REJECT)
|
||||
if (pv == RIC_REJECT)
|
||||
rte_trace_out(D_FILTERS, p, rt, "rejected by protocol");
|
||||
goto reject;
|
||||
}
|
||||
if (v > 0)
|
||||
if (pv > 0)
|
||||
{
|
||||
if (!silent)
|
||||
rte_trace_out(D_FILTERS, p, rt, "forced accept by protocol");
|
||||
goto accept;
|
||||
}
|
||||
|
||||
v = filter && ((filter == FILTER_REJECT) ||
|
||||
int fv = filter && ((filter == FILTER_REJECT) ||
|
||||
(f_run(filter, &rt, pool,
|
||||
(silent ? FF_SILENT : 0)) > F_ACCEPT));
|
||||
if (v)
|
||||
if (fv)
|
||||
{
|
||||
if (silent)
|
||||
goto reject;
|
||||
@ -471,11 +474,19 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si
|
||||
}
|
||||
|
||||
accept:
|
||||
/* We have accepted the route */
|
||||
bmap_clear(&c->export_reject_map, rt0->id);
|
||||
|
||||
/* Discard temporary rte */
|
||||
if (rt != rt0)
|
||||
*rt_free = rt;
|
||||
return rt;
|
||||
|
||||
reject:
|
||||
/* We have rejected the route by filter */
|
||||
if (pv == 0)
|
||||
bmap_set(&c->export_reject_map, rt0->id);
|
||||
|
||||
/* Discard temporary rte */
|
||||
if (rt != rt0)
|
||||
rte_free(rt);
|
||||
@ -829,7 +840,16 @@ rte_announce(rtable *tab, uint type, net *net, rte *new, rte *old,
|
||||
continue;
|
||||
|
||||
if (type && (type != c->ra_mode))
|
||||
{
|
||||
/* If skipping other means of announcement,
|
||||
* drop the rejection bit anyway
|
||||
* as we won't get this route as old any more.
|
||||
* This happens when updating hostentries. */
|
||||
if (old)
|
||||
bmap_clear(&c->export_reject_map, old->id);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
struct rte_export_internal e = {
|
||||
.pub = {
|
||||
@ -880,6 +900,11 @@ next_channel:
|
||||
/* Discard temporary rte */
|
||||
if (e.rt_free)
|
||||
rte_free(e.rt_free);
|
||||
|
||||
/* Drop the old stored rejection if applicable.
|
||||
* new->id == old->id happens when updating hostentries. */
|
||||
if (old && (!new || (new->id != old->id)))
|
||||
bmap_clear(&c->export_reject_map, old->id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1383,22 +1408,26 @@ rte_modify(rte *old)
|
||||
rte_update_unlock();
|
||||
}
|
||||
|
||||
/* Check rtable for best route to given net whether it would be exported do p */
|
||||
/* Check channel for best route to given net whether it would be exported */
|
||||
int
|
||||
rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter)
|
||||
rt_examine(struct channel *c, net_addr *a)
|
||||
{
|
||||
net *n = net_find(t, a);
|
||||
net *n = net_find(c->table, a);
|
||||
rte *rt = n ? n->routes : NULL;
|
||||
|
||||
if (!rte_is_valid(rt))
|
||||
return 0;
|
||||
|
||||
if (bmap_test(&c->export_reject_map, rt->id))
|
||||
return 0;
|
||||
|
||||
rte_update_lock();
|
||||
|
||||
struct proto *p = c->proto;
|
||||
/* Rest is stripped down export_filter() */
|
||||
int v = p->preexport ? p->preexport(p, &rt, rte_update_pool) : 0;
|
||||
if (v == RIC_PROCESS)
|
||||
v = (f_run(filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT);
|
||||
v = (f_run(c->out_filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT);
|
||||
|
||||
/* Discard temporary rte */
|
||||
if (rt != n->routes)
|
||||
|
@ -555,7 +555,7 @@ radv_check_active(struct radv_proto *p)
|
||||
return 1;
|
||||
|
||||
struct channel *c = p->p.main_channel;
|
||||
return rt_examine(c->table, &cf->trigger, &p->p, c->out_filter);
|
||||
return rt_examine(c, &cf->trigger);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user