]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Prefiltering routes by net and custom hook for partial reloads
authorMaria Matejka <mq@ucw.cz>
Wed, 4 Oct 2023 09:03:29 +0000 (11:03 +0200)
committerMaria Matejka <mq@ucw.cz>
Thu, 2 Nov 2023 13:37:27 +0000 (14:37 +0100)
nest/proto.c
nest/rt-table.c
nest/rt.h

index 9eebb1107cd6a6a2bd984cde41a8884b63a437bf..767395565dd0e3001697dc709f77d00511f2b427 100644 (file)
@@ -51,6 +51,7 @@ static char *proto_state_name(struct proto *p);
 static void channel_init_limit(struct channel *c, struct limit *l, int dir, struct channel_limit *cf);
 static void channel_update_limit(struct channel *c, struct limit *l, int dir, struct channel_limit *cf);
 static void channel_reset_limit(struct channel *c, struct limit *l, int dir);
+static int channel_refeed_prefilter(const struct rt_prefilter *p, const net_addr *n);
 static void channel_feed_end(struct channel *c);
 static void channel_stop_export(struct channel *c);
 static void channel_export_stopped(struct rt_export_request *req);
@@ -622,6 +623,7 @@ channel_start_export(struct channel *c)
   c->refeed_req.dump_req = channel_dump_refeed_req;
   c->refeed_req.log_state_change = channel_refeed_log_state_change;
   c->refeed_req.mark_seen = channel_rpe_mark_seen_refeed;
+  c->refeed_req.prefilter.hook = channel_refeed_prefilter;
 
   DBG("%s.%s: Channel start export req=%p\n", c->proto->name, c->name, &c->out_req);
   rt_request_export(c->table, &c->out_req);
@@ -719,9 +721,26 @@ channel_init_feeding(struct channel *c)
   c->refeeding = c->refeed_pending;
   c->refeed_pending = NULL;
   c->refeed_trie = f_new_trie(lp_new(c->proto->pool), 0);
+
   rt_request_export(c->table, &c->refeed_req);
 }
 
+static int
+channel_refeed_prefilter(const struct rt_prefilter *p, const net_addr *n)
+{
+  const struct channel *c =
+    SKIP_BACK(struct channel, refeed_req,
+       SKIP_BACK(struct rt_export_request, prefilter, p)
+       );
+
+  for (struct channel_feeding_request *cfr = c->refeeding; cfr; cfr = cfr->next)
+    if (!cfr->trie || trie_match_net(cfr->trie, n))
+      return 1;
+
+  return 0;
+}
+
+
 static void
 channel_feed_end(struct channel *c)
 {
index d0b4f11730b69c33e97f61ee98d1c5873f78c3c9..160d24b1dbe19f8fd18b20e83e64f2e6b2c4845a 100644 (file)
@@ -2229,6 +2229,7 @@ rt_table_export_start_feed(struct rtable_private *tab, struct rt_table_export_ho
       /* fall through */
     case TE_ADDR_NONE:
     case TE_ADDR_TRIE:
+    case TE_ADDR_HOOK:
       FIB_ITERATE_INIT(&hook->feed_fit, &tab->fib);
       hook->h.event.hook = rt_feed_by_fib;
       break;
@@ -2327,6 +2328,7 @@ rt_table_export_stop_locked(struct rt_export_hook *hh)
          }
          /* fall through */
        case TE_ADDR_NONE:
+       case TE_ADDR_HOOK:
        case TE_ADDR_TRIE:
          fit_get(&tab->fib, &hook->feed_fit);
          break;
@@ -4423,6 +4425,8 @@ rt_feed_by_fib(void *data)
          return;
        }
       }
+      else
+       req_trace(c->h.req, D_ROUTES, "Feeding %N rejected by prefilter", n->n.addr);
     }
   FIB_ITERATE_END;
   }
index 5070fcc582a3eab691d992d9c1356c14ad45c76a..bd9f9363eaa34dd85fb0eb9090662d595b03e4c8 100644 (file)
--- a/nest/rt.h
+++ b/nest/rt.h
@@ -304,6 +304,7 @@ struct rt_prefilter {
   union {
     const struct f_trie *trie;
     const net_addr *addr;      /* Network prefilter address */
+    int (*hook)(const struct rt_prefilter *, const net_addr *);
   };
                                /* Network prefilter mode (TE_ADDR_*) */
   enum {
@@ -312,6 +313,7 @@ struct rt_prefilter {
     TE_ADDR_FOR,               /* Longest prefix match - show route for <addr> */
     TE_ADDR_IN,                        /* Interval query - show route in <addr> */
     TE_ADDR_TRIE,              /* Query defined by trie */
+    TE_ADDR_HOOK,              /* Query processed by supplied custom hook */
   } mode;
 } PACKED;
 
@@ -352,6 +354,7 @@ static inline int rt_prefilter_net(const struct rt_prefilter *p, const net_addr
     case TE_ADDR_EQUAL:        return net_equal(n, p->addr);
     case TE_ADDR_FOR:  return net_in_netX(p->addr, n);
     case TE_ADDR_TRIE: return trie_match_net(p->trie, n);
+    case TE_ADDR_HOOK: return p->hook(p, n);
   }
 
   bug("Crazy prefilter application attempt failed wildly.");