mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-23 02:01:55 +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->export_state = ES_DOWN;
|
||||||
c->stats.exp_routes = 0;
|
c->stats.exp_routes = 0;
|
||||||
bmap_reset(&c->export_map, 1024);
|
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);
|
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_map, c->proto->pool, 1024);
|
||||||
|
bmap_init(&c->export_reject_map, c->proto->pool, 1024);
|
||||||
memset(&c->stats, 0, sizeof(struct proto_stats));
|
memset(&c->stats, 0, sizeof(struct proto_stats));
|
||||||
|
|
||||||
channel_reset_limit(&c->rx_limit);
|
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() */
|
/* 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_map);
|
||||||
|
bmap_free(&c->export_reject_map);
|
||||||
c->in_table = NULL;
|
c->in_table = NULL;
|
||||||
c->reload_event = NULL;
|
c->reload_event = NULL;
|
||||||
c->out_table = NULL;
|
c->out_table = NULL;
|
||||||
|
@ -499,7 +499,8 @@ struct channel {
|
|||||||
struct rtable *table;
|
struct rtable *table;
|
||||||
const struct filter *in_filter; /* Input filter */
|
const struct filter *in_filter; /* Input filter */
|
||||||
const struct filter *out_filter; /* Output 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 rx_limit; /* Receive limit (for in_keep_filtered) */
|
||||||
struct channel_limit in_limit; /* Input limit */
|
struct channel_limit in_limit; /* Input limit */
|
||||||
struct channel_limit out_limit; /* Output 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);
|
void *net_route(rtable *tab, const net_addr *n);
|
||||||
int net_roa_check(rtable *tab, const net_addr *n, u32 asn);
|
int net_roa_check(rtable *tab, const net_addr *n, u32 asn);
|
||||||
rte *rte_find(net *net, struct rte_src *src);
|
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);
|
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_begin(rtable *t, struct channel *c);
|
||||||
void rt_refresh_end(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;
|
const struct filter *filter = c->out_filter;
|
||||||
struct proto_stats *stats = &c->stats;
|
struct proto_stats *stats = &c->stats;
|
||||||
rte *rt;
|
rte *rt;
|
||||||
int v;
|
|
||||||
|
|
||||||
rt = rt0;
|
rt = rt0;
|
||||||
*rt_free = NULL;
|
*rt_free = NULL;
|
||||||
|
|
||||||
v = p->preexport ? p->preexport(p, &rt, pool) : 0;
|
/* Do nothing if we have already rejected the route */
|
||||||
if (v < 0)
|
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)
|
if (silent)
|
||||||
goto reject;
|
goto reject;
|
||||||
|
|
||||||
stats->exp_updates_rejected++;
|
stats->exp_updates_rejected++;
|
||||||
if (v == RIC_REJECT)
|
if (pv == RIC_REJECT)
|
||||||
rte_trace_out(D_FILTERS, p, rt, "rejected by protocol");
|
rte_trace_out(D_FILTERS, p, rt, "rejected by protocol");
|
||||||
goto reject;
|
goto reject;
|
||||||
}
|
}
|
||||||
if (v > 0)
|
if (pv > 0)
|
||||||
{
|
{
|
||||||
if (!silent)
|
if (!silent)
|
||||||
rte_trace_out(D_FILTERS, p, rt, "forced accept by protocol");
|
rte_trace_out(D_FILTERS, p, rt, "forced accept by protocol");
|
||||||
goto accept;
|
goto accept;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = filter && ((filter == FILTER_REJECT) ||
|
int fv = filter && ((filter == FILTER_REJECT) ||
|
||||||
(f_run(filter, &rt, pool,
|
(f_run(filter, &rt, pool,
|
||||||
(silent ? FF_SILENT : 0)) > F_ACCEPT));
|
(silent ? FF_SILENT : 0)) > F_ACCEPT));
|
||||||
if (v)
|
if (fv)
|
||||||
{
|
{
|
||||||
if (silent)
|
if (silent)
|
||||||
goto reject;
|
goto reject;
|
||||||
@ -471,11 +474,19 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si
|
|||||||
}
|
}
|
||||||
|
|
||||||
accept:
|
accept:
|
||||||
|
/* We have accepted the route */
|
||||||
|
bmap_clear(&c->export_reject_map, rt0->id);
|
||||||
|
|
||||||
|
/* Discard temporary rte */
|
||||||
if (rt != rt0)
|
if (rt != rt0)
|
||||||
*rt_free = rt;
|
*rt_free = rt;
|
||||||
return rt;
|
return rt;
|
||||||
|
|
||||||
reject:
|
reject:
|
||||||
|
/* We have rejected the route by filter */
|
||||||
|
if (pv == 0)
|
||||||
|
bmap_set(&c->export_reject_map, rt0->id);
|
||||||
|
|
||||||
/* Discard temporary rte */
|
/* Discard temporary rte */
|
||||||
if (rt != rt0)
|
if (rt != rt0)
|
||||||
rte_free(rt);
|
rte_free(rt);
|
||||||
@ -829,7 +840,16 @@ rte_announce(rtable *tab, uint type, net *net, rte *new, rte *old,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (type && (type != c->ra_mode))
|
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;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
struct rte_export_internal e = {
|
struct rte_export_internal e = {
|
||||||
.pub = {
|
.pub = {
|
||||||
@ -880,6 +900,11 @@ next_channel:
|
|||||||
/* Discard temporary rte */
|
/* Discard temporary rte */
|
||||||
if (e.rt_free)
|
if (e.rt_free)
|
||||||
rte_free(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();
|
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
|
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;
|
rte *rt = n ? n->routes : NULL;
|
||||||
|
|
||||||
if (!rte_is_valid(rt))
|
if (!rte_is_valid(rt))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (bmap_test(&c->export_reject_map, rt->id))
|
||||||
|
return 0;
|
||||||
|
|
||||||
rte_update_lock();
|
rte_update_lock();
|
||||||
|
|
||||||
|
struct proto *p = c->proto;
|
||||||
/* Rest is stripped down export_filter() */
|
/* Rest is stripped down export_filter() */
|
||||||
int v = p->preexport ? p->preexport(p, &rt, rte_update_pool) : 0;
|
int v = p->preexport ? p->preexport(p, &rt, rte_update_pool) : 0;
|
||||||
if (v == RIC_PROCESS)
|
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 */
|
/* Discard temporary rte */
|
||||||
if (rt != n->routes)
|
if (rt != n->routes)
|
||||||
|
@ -555,7 +555,7 @@ radv_check_active(struct radv_proto *p)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
struct channel *c = p->p.main_channel;
|
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
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user