]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Prefilter runs before generating feeds
authorMaria Matejka <mq@ucw.cz>
Sun, 16 Jun 2024 19:36:45 +0000 (21:36 +0200)
committerMaria Matejka <mq@ucw.cz>
Sun, 16 Jun 2024 19:36:45 +0000 (21:36 +0200)
nest/route.h
nest/rt-export.c
nest/rt-table.c
proto/bgp/attrs.c

index 329eefa69043b0e59cdad65323d32af87fd8742a..74f2d84ad0263ad89fb45ae06ab6d34181729a69 100644 (file)
@@ -225,7 +225,7 @@ struct rt_exporter {
   netindex_hash *netindex;                     /* Table for net <-> id conversion */
   void (*stopped)(struct rt_exporter *);       /* Callback when exporter can stop */
   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 *);
 };
 
@@ -313,6 +313,12 @@ static inline int rt_prefilter_net(const struct rt_prefilter *p, const net_addr
 static inline _Bool
 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)
     if (rt_prefilter_net(&rfr->prefilter, n))
       return 1;
index f421a63b80eabe5986165f193ccaaf9346f1e7d9..1dd536a5c80be55f81eafbb6917bb0498ffff3f1 100644 (file)
@@ -149,13 +149,13 @@ rt_export_get(struct rt_export_request *r)
       if (r->feeder.domain.rtable)
       {
        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);
       }
       else
       {
        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);
@@ -263,7 +263,8 @@ rt_export_get_next_feed(struct rt_export_feeder *f, struct rcu_unwinder *u)
       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)
     {
       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)
       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++;
     return feed;
   }
index cc2111635f9311fca59271eed4b1e0018971438f..c14692d584b2521bfa92a974dd056798a3ca6571 100644 (file)
@@ -2209,7 +2209,7 @@ rt_net_feed_validate_first(
 }
 
 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. */
   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++;
   }
 
+  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;
 
   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);
 
     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 *
-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);
   if (!n)
     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 *
@@ -2290,14 +2299,14 @@ rt_net_feed(rtable *t, const net_addr *a, const struct rt_pending_export *first)
 {
   RT_READ(t, tr);
   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 *
-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);
-  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
@@ -2322,7 +2331,7 @@ rt_net_best(rtable *t, const net_addr *a)
 }
 
 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(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))
     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);
-  if (!ecnt && !best)
+
+  if (!ecnt && (!best || prefilter && !prefilter(f, best->rte.net)))
     return NULL;
 
   struct rt_export_feed *feed = rt_alloc_feed(!!best, ecnt);
index 5ea97ac58a2b970ae3b6ce70d2a2fa8a174ae17e..2450f657a5feee1dd87c783291aa2c7440758914 100644 (file)
@@ -1879,17 +1879,22 @@ bgp_out_item_done(struct lfjour *j, struct lfjour_item *i)
 {}
 
 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);
   SKIP_BACK_DECLARE(struct bgp_ptx_private, c, exporter, e);
   ASSERT_DIE(DOMAIN_IS_LOCKED(rtable, c->lock));
+
   struct netindex *ni = net_resolve_index(c->c->c.table->netindex, index);
   if (ni == &net_index_out_of_range)
     return &rt_feed_index_out_of_range;
+
   if (ni == NULL)
     return NULL;
 
+  if (prefilter && !prefilter(f, ni->addr))
+    return NULL;
+
   struct rt_export_feed *feed = NULL;
 
   uint count = 0;