0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

Prefilter runs before generating feeds

This commit is contained in:
Maria Matejka 2024-06-16 21:36:45 +02:00
parent d6233b4de0
commit a1405a5bc7
4 changed files with 41 additions and 20 deletions

View File

@ -225,7 +225,7 @@ struct rt_exporter {
netindex_hash *netindex; /* Table for net <-> id conversion */ netindex_hash *netindex; /* Table for net <-> id conversion */
void (*stopped)(struct rt_exporter *); /* Callback when exporter can stop */ void (*stopped)(struct rt_exporter *); /* Callback when exporter can stop */
void (*cleanup_done)(struct rt_exporter *, u64 end); /* Callback when cleanup has been done */ void (*cleanup_done)(struct rt_exporter *, u64 end); /* Callback when cleanup has been done */
struct rt_export_feed *(*feed_net)(struct rt_exporter *, struct rcu_unwinder *, u32, const struct rt_export_item *first); struct rt_export_feed *(*feed_net)(struct rt_exporter *, struct rcu_unwinder *, u32, _Bool (*)(struct rt_export_feeder *, const net_addr *), struct rt_export_feeder *, const struct rt_export_item *first);
void (*feed_cleanup)(struct rt_exporter *, struct rt_export_feeder *); void (*feed_cleanup)(struct rt_exporter *, struct rt_export_feeder *);
}; };
@ -313,6 +313,12 @@ static inline int rt_prefilter_net(const struct rt_prefilter *p, const net_addr
static inline _Bool static inline _Bool
rt_net_is_feeding_feeder(struct rt_export_feeder *ref, const net_addr *n) rt_net_is_feeding_feeder(struct rt_export_feeder *ref, const net_addr *n)
{ {
if (!rt_prefilter_net(&ref->prefilter, n))
return 0;
if (!ref->feeding)
return 1;
for (struct rt_feeding_request *rfr = ref->feeding; rfr; rfr = rfr->next) for (struct rt_feeding_request *rfr = ref->feeding; rfr; rfr = rfr->next)
if (rt_prefilter_net(&rfr->prefilter, n)) if (rt_prefilter_net(&rfr->prefilter, n))
return 1; return 1;

View File

@ -149,13 +149,13 @@ rt_export_get(struct rt_export_request *r)
if (r->feeder.domain.rtable) if (r->feeder.domain.rtable)
{ {
LOCK_DOMAIN(rtable, r->feeder.domain); LOCK_DOMAIN(rtable, r->feeder.domain);
feed = e->feed_net(e, NULL, ni->index, update); feed = e->feed_net(e, NULL, ni->index, NULL, NULL, update);
UNLOCK_DOMAIN(rtable, r->feeder.domain); UNLOCK_DOMAIN(rtable, r->feeder.domain);
} }
else else
{ {
RCU_ANCHOR(u); RCU_ANCHOR(u);
feed = e->feed_net(e, u, ni->index, update); feed = e->feed_net(e, u, ni->index, NULL, NULL, update);
} }
bmap_set(&r->feed_map, ni->index); bmap_set(&r->feed_map, ni->index);
@ -263,7 +263,8 @@ rt_export_get_next_feed(struct rt_export_feeder *f, struct rcu_unwinder *u)
return NULL; return NULL;
} }
struct rt_export_feed *feed = e->feed_net(e, u, f->feed_index, NULL); struct rt_export_feed *feed = e->feed_net(e, u, f->feed_index,
rt_net_is_feeding_feeder, f, NULL);
if (feed == &rt_feed_index_out_of_range) if (feed == &rt_feed_index_out_of_range)
{ {
rtex_trace(f, D_ROUTES, "Nothing more to feed", f->feed_index); rtex_trace(f, D_ROUTES, "Nothing more to feed", f->feed_index);
@ -280,13 +281,6 @@ rt_export_get_next_feed(struct rt_export_feeder *f, struct rcu_unwinder *u)
if (!feed) if (!feed)
NOT_THIS_FEED("Nothing found for index %u", f->feed_index); NOT_THIS_FEED("Nothing found for index %u", f->feed_index);
struct netindex *ni = feed->ni;
if (!rt_prefilter_net(&f->prefilter, ni->addr))
NOT_THIS_FEED("Not feeding %N due to prefilter", ni->addr);
if (f->feeding && !rt_net_is_feeding_feeder(f, ni->addr))
NOT_THIS_FEED("Not feeding %N, not requested", ni->addr);
f->feed_index++; f->feed_index++;
return feed; return feed;
} }

View File

@ -2209,7 +2209,7 @@ rt_net_feed_validate_first(
} }
static struct rt_export_feed * static struct rt_export_feed *
rt_net_feed_index(struct rtable_reading *tr, net *n, const struct rt_pending_export *first) rt_net_feed_index(struct rtable_reading *tr, net *n, _Bool (*prefilter)(struct rt_export_feeder *, const net_addr *), struct rt_export_feeder *f, const struct rt_pending_export *first)
{ {
/* Get the feed itself. It may change under our hands tho. */ /* Get the feed itself. It may change under our hands tho. */
struct rt_pending_export *first_in_net, *last_in_net; struct rt_pending_export *first_in_net, *last_in_net;
@ -2230,10 +2230,19 @@ rt_net_feed_index(struct rtable_reading *tr, net *n, const struct rt_pending_exp
ocnt++; ocnt++;
} }
if (ecnt) {
const net_addr *a = (first->it.new ?: first->it.old)->net;
if (prefilter && !prefilter(f, a))
return NULL;
}
struct rt_export_feed *feed = NULL; struct rt_export_feed *feed = NULL;
if (rcnt || ocnt || ecnt) if (rcnt || ocnt || ecnt)
{ {
if (!ecnt && prefilter && !prefilter(f, NET_READ_BEST_ROUTE(tr, n)->rte.net))
return NULL;
feed = rt_alloc_feed(rcnt+ocnt, ecnt); feed = rt_alloc_feed(rcnt+ocnt, ecnt);
if (rcnt) if (rcnt)
@ -2276,13 +2285,13 @@ rt_net_feed_index(struct rtable_reading *tr, net *n, const struct rt_pending_exp
} }
static struct rt_export_feed * static struct rt_export_feed *
rt_net_feed_internal(struct rtable_reading *tr, u32 index, const struct rt_pending_export *first) rt_net_feed_internal(struct rtable_reading *tr, u32 index, _Bool (*prefilter)(struct rt_export_feeder *, const net_addr *), struct rt_export_feeder *f, const struct rt_pending_export *first)
{ {
net *n = rt_net_feed_get_net(tr, index); net *n = rt_net_feed_get_net(tr, index);
if (!n) if (!n)
return &rt_feed_index_out_of_range; return &rt_feed_index_out_of_range;
return rt_net_feed_index(tr, n, first); return rt_net_feed_index(tr, n, prefilter, f, first);
} }
struct rt_export_feed * struct rt_export_feed *
@ -2290,14 +2299,14 @@ rt_net_feed(rtable *t, const net_addr *a, const struct rt_pending_export *first)
{ {
RT_READ(t, tr); RT_READ(t, tr);
const struct netindex *ni = net_find_index(tr->t->netindex, a); const struct netindex *ni = net_find_index(tr->t->netindex, a);
return ni ? rt_net_feed_internal(tr, ni->index, first) : NULL; return ni ? rt_net_feed_internal(tr, ni->index, NULL, NULL, first) : NULL;
} }
static struct rt_export_feed * static struct rt_export_feed *
rt_feed_net_all(struct rt_exporter *e, struct rcu_unwinder *u, u32 index, const struct rt_export_item *_first) rt_feed_net_all(struct rt_exporter *e, struct rcu_unwinder *u, u32 index, _Bool (*prefilter)(struct rt_export_feeder *, const net_addr *), struct rt_export_feeder *f, const struct rt_export_item *_first)
{ {
RT_READ_ANCHORED(SKIP_BACK(rtable, export_all, e), tr, u); RT_READ_ANCHORED(SKIP_BACK(rtable, export_all, e), tr, u);
return rt_net_feed_internal(tr, index, SKIP_BACK(const struct rt_pending_export, it, _first)); return rt_net_feed_internal(tr, index, prefilter, f, SKIP_BACK(const struct rt_pending_export, it, _first));
} }
rte rte
@ -2322,7 +2331,7 @@ rt_net_best(rtable *t, const net_addr *a)
} }
static struct rt_export_feed * static struct rt_export_feed *
rt_feed_net_best(struct rt_exporter *e, struct rcu_unwinder *u, u32 index, const struct rt_export_item *_first) rt_feed_net_best(struct rt_exporter *e, struct rcu_unwinder *u, u32 index, _Bool (*prefilter)(struct rt_export_feeder *, const net_addr *), struct rt_export_feeder *f, const struct rt_export_item *_first)
{ {
SKIP_BACK_DECLARE(rtable, t, export_best, e); SKIP_BACK_DECLARE(rtable, t, export_best, e);
SKIP_BACK_DECLARE(const struct rt_pending_export, first, it, _first); SKIP_BACK_DECLARE(const struct rt_pending_export, first, it, _first);
@ -2344,8 +2353,15 @@ rt_feed_net_best(struct rt_exporter *e, struct rcu_unwinder *u, u32 index, const
rpe = atomic_load_explicit(&rpe->next, memory_order_acquire)) rpe = atomic_load_explicit(&rpe->next, memory_order_acquire))
ecnt++; ecnt++;
if (ecnt) {
const net_addr *a = (first->it.new ?: first->it.old)->net;
if (prefilter && !prefilter(f, a))
return NULL;
}
struct rte_storage *best = NET_READ_BEST_ROUTE(tr, n); struct rte_storage *best = NET_READ_BEST_ROUTE(tr, n);
if (!ecnt && !best)
if (!ecnt && (!best || prefilter && !prefilter(f, best->rte.net)))
return NULL; return NULL;
struct rt_export_feed *feed = rt_alloc_feed(!!best, ecnt); struct rt_export_feed *feed = rt_alloc_feed(!!best, ecnt);

View File

@ -1879,17 +1879,22 @@ bgp_out_item_done(struct lfjour *j, struct lfjour_item *i)
{} {}
static struct rt_export_feed * static struct rt_export_feed *
bgp_out_feed_net(struct rt_exporter *e, struct rcu_unwinder *u, u32 index, const struct rt_export_item *_first) bgp_out_feed_net(struct rt_exporter *e, struct rcu_unwinder *u, u32 index, _Bool (*prefilter)(struct rt_export_feeder *, const net_addr *), struct rt_export_feeder *f, const struct rt_export_item *_first)
{ {
ASSERT_DIE(u == NULL); ASSERT_DIE(u == NULL);
SKIP_BACK_DECLARE(struct bgp_ptx_private, c, exporter, e); SKIP_BACK_DECLARE(struct bgp_ptx_private, c, exporter, e);
ASSERT_DIE(DOMAIN_IS_LOCKED(rtable, c->lock)); ASSERT_DIE(DOMAIN_IS_LOCKED(rtable, c->lock));
struct netindex *ni = net_resolve_index(c->c->c.table->netindex, index); struct netindex *ni = net_resolve_index(c->c->c.table->netindex, index);
if (ni == &net_index_out_of_range) if (ni == &net_index_out_of_range)
return &rt_feed_index_out_of_range; return &rt_feed_index_out_of_range;
if (ni == NULL) if (ni == NULL)
return NULL; return NULL;
if (prefilter && !prefilter(f, ni->addr))
return NULL;
struct rt_export_feed *feed = NULL; struct rt_export_feed *feed = NULL;
uint count = 0; uint count = 0;