]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Table export generalized to allow for exporting from non-tables
authorMaria Matejka <mq@ucw.cz>
Mon, 20 Jun 2022 19:29:10 +0000 (21:29 +0200)
committerMaria Matejka <mq@ucw.cz>
Fri, 24 Jun 2022 13:49:08 +0000 (15:49 +0200)
nest/proto.c
nest/rt-table.c
nest/rt.h

index 5e67d940f8733dc4e04afceddf02d65a8e2622a7..8513b9cba50bf9475627ff945b7404b251e0bbf0 100644 (file)
@@ -498,7 +498,7 @@ channel_start_export(struct channel *c)
   }
 
   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);
+  rt_request_export(&c->table->exporter, &c->out_req);
 }
 
 static void
@@ -552,7 +552,7 @@ channel_export_stopped(struct rt_export_request *req)
   {
     c->refeeding = 1;
     c->refeed_pending = 0;
-    rt_request_export(c->table, req);
+    rt_request_export(&c->table->exporter, req);
     return;
   }
 
@@ -600,7 +600,7 @@ channel_schedule_reload(struct channel *c)
 {
   ASSERT(c->in_req.hook);
 
-  rt_request_export(c->table, &c->reload_req);
+  rt_request_export(&c->table->exporter, &c->reload_req);
 }
 
 static void
index 975da363ea877af2857673e6765612e6648cba4f..14c801387074d81bb056fac2ec5065d7e1e281f6 100644 (file)
@@ -139,7 +139,6 @@ const char *rt_import_state_name_array[TIS_MAX] = {
 
 const char *rt_export_state_name_array[TES_MAX] = {
   [TES_DOWN] = "DOWN",
-  [TES_HUNGRY] = "HUNGRY",
   [TES_FEEDING] = "FEEDING",
   [TES_READY] = "READY",
   [TES_STOP] = "STOP"
@@ -1183,7 +1182,7 @@ rte_announce(rtable *tab, net *net, struct rte_storage *new, struct rte_storage
   }
 
   struct rt_export_hook *eh;
-  WALK_LIST(eh, tab->exports)
+  WALK_LIST(eh, tab->exporter.hooks)
   {
     if (eh->export_state == TES_STOP)
       continue;
@@ -1677,11 +1676,21 @@ rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filte
   return v > 0;
 }
 
+static void
+rt_table_export_done(struct rt_export_hook *hook)
+{
+  struct rt_exporter *re = hook->table;
+  struct rtable *tab = SKIP_BACK(struct rtable, exporter, re);
+
+  rt_unlock_table(tab);
+  DBG("Export hook %p in table %s finished uc=%u\n", hook, tab->name, tab->use_count);
+}
+
 static void
 rt_export_stopped(void *data)
 {
   struct rt_export_hook *hook = data;
-  rtable *tab = hook->table;
+  struct rt_exporter *tab = hook->table;
 
   /* Unlist */
   rem_node(&hook->n);
@@ -1689,14 +1698,13 @@ rt_export_stopped(void *data)
   /* Reporting the channel as stopped. */
   hook->stopped(hook->req);
 
+  /* Reporting the hook as finished. */
+  tab->done(hook);
+
   /* Freeing the hook together with its coroutine. */
   rfree(hook->pool);
-  rt_unlock_table(tab);
-
-  DBG("Export hook %p in table %s finished uc=%u\n", hook, tab->name, tab->use_count);
 }
 
-
 static inline void
 rt_set_import_state(struct rt_import_hook *hook, u8 state)
 {
@@ -1748,54 +1756,73 @@ rt_stop_import(struct rt_import_request *req, void (*stopped)(struct rt_import_r
   hook->stopped = stopped;
 }
 
-void
-rt_request_export(rtable *tab, struct rt_export_request *req)
+static struct rt_export_hook *
+rt_table_export_start(struct rt_exporter *re, struct rt_export_request *req)
 {
+  rtable *tab = SKIP_BACK(rtable, exporter, re);
   rt_lock_table(tab);
 
   pool *p = rp_new(tab->rp, "Export hook");
-  struct rt_export_hook *hook = req->hook = mb_allocz(p, sizeof(struct rt_export_hook));
+  struct rt_export_hook *hook = mb_allocz(p, sizeof(struct rt_export_hook));
   hook->pool = p;
   hook->lp = lp_new_default(p);
-  
-  hook->req = req;
-  hook->table = tab;
 
   /* stats zeroed by mb_allocz */
 
-  rt_set_export_state(hook, TES_HUNGRY);
-
-  hook->n = (node) {};
-  add_tail(&tab->exports, &hook->n);
-
   FIB_ITERATE_INIT(&hook->feed_fit, &tab->fib);
 
   DBG("New export hook %p req %p in table %s uc=%u\n", hook, req, tab->name, tab->use_count);
 
+  hook->event = ev_new_init(p, rt_feed_channel, hook);
+
+  return hook;
+}
+
+void
+rt_request_export(struct rt_exporter *re, struct rt_export_request *req)
+{
+  struct rt_export_hook *hook = req->hook = re->start(re, req);
+
+  hook->req = req;
+  hook->table = re;
+
+  hook->n = (node) {};
+  add_tail(&re->hooks, &hook->n);
+
   rt_set_export_state(hook, TES_FEEDING);
 
-  hook->event = ev_new_init(p, rt_feed_channel, hook);
   ev_schedule_work(hook->event);
 }
 
+static void
+rt_table_export_stop(struct rt_export_hook *hook)
+{
+  rtable *tab = SKIP_BACK(rtable, exporter, hook->table);
+
+  if (hook->export_state == TES_FEEDING)
+    fit_get(&tab->fib, &hook->feed_fit);
+}
+
 void
 rt_stop_export(struct rt_export_request *req, void (*stopped)(struct rt_export_request *))
 {
   ASSERT_DIE(req->hook);
   struct rt_export_hook *hook = req->hook;
 
-  rtable *tab = hook->table;
-
-  /* Stop feeding */
+  /* Cancel the feeder event */
   ev_postpone(hook->event);
 
-  if (hook->export_state == TES_FEEDING)
-    fit_get(&tab->fib, &hook->feed_fit);
+  /* Stop feeding from the exporter */
+  hook->table->stop(hook);
 
+  /* Reset the event as the stopped event */
   hook->event->hook = rt_export_stopped;
   hook->stopped = stopped;
 
+  /* Update export state */
   rt_set_export_state(hook, TES_STOP);
+
+  /* Run the stopped event */
   ev_schedule(hook->event);
 }
 
@@ -1948,7 +1975,7 @@ rt_dump_hooks(rtable *tab)
   }
 
   struct rt_export_hook *eh;
-  WALK_LIST(eh, tab->exports)
+  WALK_LIST(eh, tab->exporter.hooks)
   {
     eh->req->dump_req(eh->req);
     debug("  Export hook %p requested by %p:"
@@ -2252,10 +2279,17 @@ rt_setup(pool *pp, struct rtable_config *cf)
 
   init_list(&t->flowspec_links);
 
+  t->exporter = (struct rt_exporter) {
+    .start = rt_table_export_start,
+    .stop = rt_table_export_stop,
+    .done = rt_table_export_done,
+  };
+  init_list(&t->exporter.hooks);
+
   if (!(t->internal = cf->internal))
   {
     init_list(&t->imports);
-    init_list(&t->exports);
+
     hmap_init(&t->id_map, p, 1024);
     hmap_set(&t->id_map, 0);
 
@@ -3138,7 +3172,9 @@ rt_feed_channel(void *data)
 
   ASSERT(c->export_state == TES_FEEDING);
 
-  FIB_ITERATE_START(&c->table->fib, fit, net, n)
+  rtable *tab = SKIP_BACK(rtable, exporter, c->table);
+
+  FIB_ITERATE_START(&tab->fib, fit, net, n)
     {
       if (max_feed <= 0)
        {
index d5e28cb636fdb2ea7261e4d60862e9988233b2d0..0f5a5ba780ea83cfcffafb213d15ee694439e1ee 100644 (file)
--- a/nest/rt.h
+++ b/nest/rt.h
@@ -56,6 +56,16 @@ struct rtable_config {
   btime max_settle_time;               /* Maximum settle time for notifications */
 };
 
+struct rt_export_hook;
+struct rt_export_request;
+
+struct rt_exporter {
+  list hooks;                          /* Registered route export hooks */
+  struct rt_export_hook *(*start)(struct rt_exporter *, struct rt_export_request *);
+  void (*stop)(struct rt_export_hook *);
+  void (*done)(struct rt_export_hook *);
+};
+
 typedef struct rtable {
   resource r;
   node n;                              /* Node in list of all tables */
@@ -69,7 +79,7 @@ typedef struct rtable {
   u32 rt_count;                                /* Number of routes in the table */
 
   list imports;                                /* Registered route importers */
-  list exports;                                /* Registered route exporters */
+  struct rt_exporter exporter;         /* Exporter API structure */
 
   struct hmap id_map;
   struct hostcache *hostcache;
@@ -221,7 +231,7 @@ struct rt_export_request {
 
 struct rt_export_hook {
   node n;
-  rtable *table;                       /* The connected table */
+  struct rt_exporter *table;           /* The connected table */
 
   pool *pool;
   linpool *lp;
@@ -255,14 +265,13 @@ struct rt_export_hook {
 #define TIS_MAX                6
 
 #define TES_DOWN       0
-#define TES_HUNGRY     1
 #define TES_FEEDING    2
 #define TES_READY      3
 #define TES_STOP       4
 #define TES_MAX                5
 
 void rt_request_import(rtable *tab, struct rt_import_request *req);
-void rt_request_export(rtable *tab, struct rt_export_request *req);
+void rt_request_export(struct rt_exporter *tab, struct rt_export_request *req);
 
 void rt_stop_import(struct rt_import_request *, void (*stopped)(struct rt_import_request *));
 void rt_stop_export(struct rt_export_request *, void (*stopped)(struct rt_export_request *));