]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Split route table event into separate events
authorMaria Matejka <mq@ucw.cz>
Fri, 22 Oct 2021 19:03:25 +0000 (21:03 +0200)
committerMaria Matejka <mq@ucw.cz>
Mon, 22 Nov 2021 18:05:43 +0000 (19:05 +0100)
The former rt_event is dropped in favour of separate table events.
This allows for selective corking of NHU and prune.

nest/proto.c
nest/protocol.h
nest/route.h
nest/rt-table.c

index ac0fb2322447e988793fa7b80493ec68753a786e..f8e1ba310a19b311ff96ccd8660eb4ae93fd860c 100644 (file)
@@ -658,6 +658,8 @@ channel_aux_stopped(void *data)
   else
     c->in_table = NULL;
 
+  rfree(cat->tab->rp);
+
   mb_free(cat);
   return channel_check_stopped(c);
 }
@@ -666,7 +668,7 @@ static void
 channel_aux_import_stopped(struct rt_import_request *req)
 {
   struct channel_aux_table *cat = SKIP_BACK(struct channel_aux_table, push, req);
-  ASSERT_DIE(cat->stop);
+  ASSERT_DIE(cat->tab->delete_event);
 }
 
 static void
@@ -675,25 +677,23 @@ channel_aux_export_stopped(struct rt_export_request *req)
   struct channel_aux_table *cat = SKIP_BACK(struct channel_aux_table, get, req);
   req->hook = NULL;
 
-  if (cat->refeed_pending && !cat->stop)
+  if (cat->refeed_pending && !cat->tab->delete_event)
   {
     cat->refeed_pending = 0;
     rt_request_export(cat->tab, req);
   }
   else
-    ASSERT_DIE(cat->stop);
+    ASSERT_DIE(cat->tab->delete_event);
 }
 
 static void
 channel_aux_stop(struct channel_aux_table *cat)
 {
-  cat->stop = 1;
-
   rt_stop_import(&cat->push, channel_aux_import_stopped);
   rt_stop_export(&cat->get, channel_aux_export_stopped);
 
-  cat->tab->deleted = channel_aux_stopped;
-  cat->tab->del_data = cat;
+  cat->tab->delete_event = ev_new_init(cat->tab->rp, channel_aux_stopped, cat);
+
   rt_unlock_table(cat->tab);
 }
 
@@ -886,7 +886,6 @@ channel_setup_in_table(struct channel *c, int best)
 
   c->in_table->c = c;
   c->in_table->tab = rt_setup(c->proto->pool, &cat->tab_cf);
-  self_link(&c->in_table->tab->n);
   rt_lock_table(c->in_table->tab);
 
   rt_request_import(c->in_table->tab, &c->in_table->push);
@@ -929,7 +928,6 @@ channel_setup_out_table(struct channel *c)
 
   c->out_table->c = c;
   c->out_table->tab = rt_setup(c->proto->pool, &cat->tab_cf);
-  self_link(&c->out_table->tab->n);
   rt_lock_table(c->out_table->tab);
 
   rt_request_import(c->out_table->tab, &c->out_table->push);
index 2fbd607c1b31b5f959e8389b9b72f88568f776e2..981ca96abf0f89ee6b4b2b647852df1cdca333c9 100644 (file)
@@ -568,7 +568,7 @@ struct channel_aux_table {
   struct rt_import_request push;
   struct rt_export_request get;
   rtable *tab;
-  u8 stop;
+  event *stop;
   u8 refeed_pending;
 };
 
index 7c5fd02f622faa22cb11c5d388ff5edc0aa19c0f..88a56073b526432c7bea118fb0dc195e64a90044 100644 (file)
@@ -147,6 +147,7 @@ void fit_copy(struct fib *f, struct fib_iterator *dst, struct fib_iterator *src)
 struct rtable_config {
   node n;
   char *name;
+  struct config *config;
   struct rtable *table;
   struct proto_config *krt_attached;   /* Kernel syncer attached to this table */
   uint addr_type;                      /* Type of address data stored in table (NET_*) */
@@ -175,17 +176,17 @@ typedef struct rtable {
   struct hmap id_map;
   struct hostcache *hostcache;
   struct rtable_config *config;                /* Configuration of this table */
-  void (*deleted)(void *);             /* Table should free itself. Call this when it is done. */
-  void *del_data;
-  struct event *rt_event;              /* Routing table event */
+  struct event *prune_event;           /* Event to prune abandoned routes */
+  struct event *ec_event;              /* Event to prune finished exports */
+  struct event *hcu_event;             /* Event to update host cache */
+  struct event *nhu_event;             /* Event to update next hops */
+  struct event *delete_event;          /* Event to delete the table */
   btime last_rt_change;                        /* Last time when route changed */
   btime base_settle_time;              /* Start time of rtable settling interval */
   btime gc_time;                       /* Time of last GC */
   int gc_counter;                      /* Number of operations since last GC */
   byte prune_state;                    /* Table prune state, 1 -> scheduled, 2-> running */
-  byte hcu_scheduled;                  /* Hostcache update is scheduled */
   byte nhu_state;                      /* Next Hop Update state */
-  byte export_used;                    /* Export journal setup scheduled */
   struct fib_iterator prune_fit;       /* Rtable prune FIB iterator */
   struct fib_iterator nhu_fit;         /* Next Hop Update FIB iterator */
   struct tbf rl_pipe;                  /* Rate limiting token buffer for pipe collisions */
@@ -475,7 +476,6 @@ void rt_unlock_table(rtable *);
 void rt_subscribe(rtable *tab, struct rt_subscription *s);
 void rt_unsubscribe(struct rt_subscription *s);
 rtable *rt_setup(pool *, struct rtable_config *);
-static inline void rt_shutdown(rtable *r) { rfree(r->rp); }
 
 static inline net *net_find(rtable *tab, const net_addr *addr) { return (net *) fib_find(&tab->fib, addr); }
 static inline net *net_find_valid(rtable *tab, const net_addr *addr)
index 9c12ef565ffde2b30628ea425392dcb43d7f6b7c..6dd6587eb7c1a1583657c8b3ad448b5ed0ed3888 100644 (file)
@@ -65,14 +65,14 @@ struct rt_export_block {
 
 static void rt_free_hostcache(rtable *tab);
 static void rt_notify_hostcache(rtable *tab, net *net);
-static void rt_update_hostcache(rtable *tab);
-static void rt_next_hop_update(rtable *tab);
-static inline void rt_prune_table(rtable *tab);
+static void rt_update_hostcache(void *tab);
+static void rt_next_hop_update(void *tab);
+static inline void rt_prune_table(void *tab);
 static inline void rt_schedule_notify(rtable *tab);
 static void rt_feed_channel(void *);
 
 static inline void rt_export_used(rtable *tab);
-static void rt_export_cleanup(rtable *tab);
+static void rt_export_cleanup(void *tab);
 
 static inline void rte_update_lock(void);
 static inline void rte_update_unlock(void);
@@ -1860,7 +1860,7 @@ rte_dump(struct rte_storage *e)
 void
 rt_dump(rtable *t)
 {
-  debug("Dump of routing table <%s>%s\n", t->name, t->deleted ? " (deleted)" : "");
+  debug("Dump of routing table <%s>%s\n", t->name, t->delete_event ? " (deleted)" : "");
 #ifdef DEBUGGING
   fib_check(&t->fib);
 #endif
@@ -1891,9 +1891,9 @@ rt_dump_all(void)
 void
 rt_dump_hooks(rtable *tab)
 {
-  debug("Dump of hooks in routing table <%s>%s\n", tab->name, tab->deleted ? " (deleted)" : "");
+  debug("Dump of hooks in routing table <%s>%s\n", tab->name, tab->delete_event ? " (deleted)" : "");
   debug("  nhu_state=%u hcu_scheduled=%u use_count=%d rt_count=%u\n",
-      tab->nhu_state, tab->hcu_scheduled, tab->use_count, tab->rt_count);
+      tab->nhu_state, ev_active(tab->hcu_event), tab->use_count, tab->rt_count);
   debug("  last_rt_change=%t gc_time=%t gc_counter=%d prune_state=%u\n",
       tab->last_rt_change, tab->gc_time, tab->gc_counter, tab->prune_state);
 
@@ -1930,21 +1930,11 @@ rt_dump_hooks_all(void)
     rt_dump_hooks(t);
 }
 
-static inline void
-rt_schedule_hcu(rtable *tab)
-{
-  if (tab->hcu_scheduled)
-    return;
-
-  tab->hcu_scheduled = 1;
-  ev_schedule(tab->rt_event);
-}
-
 static inline void
 rt_schedule_nhu(rtable *tab)
 {
   if (tab->nhu_state == NHU_CLEAN)
-    ev_schedule(tab->rt_event);
+    ev_schedule(tab->nhu_event);
 
   /* state change:
    *   NHU_CLEAN   -> NHU_SCHEDULED
@@ -1957,7 +1947,7 @@ void
 rt_schedule_prune(rtable *tab)
 {
   if (tab->prune_state == 0)
-    ev_schedule(tab->rt_event);
+    ev_schedule(tab->prune_event);
 
   /* state change 0->1, 2->3 */
   tab->prune_state |= 1;
@@ -1969,36 +1959,9 @@ rt_export_used(rtable *tab)
   if (config->table_debug)
     log(L_TRACE "%s: Export cleanup requested", tab->name);
 
-  if (tab->export_used)
-    return;
-
-  tab->export_used = 1;
-  ev_schedule(tab->rt_event);
+  ev_schedule(tab->ec_event);
 }
 
-static void
-rt_event(void *ptr)
-{
-  rtable *tab = ptr;
-
-  rt_lock_table(tab);
-
-  if (tab->export_used)
-    rt_export_cleanup(tab);
-
-  if (tab->hcu_scheduled)
-    rt_update_hostcache(tab);
-
-  if (tab->nhu_state)
-    rt_next_hop_update(tab);
-
-  if (tab->prune_state)
-    rt_prune_table(tab);
-
-  rt_unlock_table(tab);
-}
-
-
 static inline btime
 rt_settled_time(rtable *tab)
 {
@@ -2078,13 +2041,9 @@ rt_free(resource *_r)
 
   DBG("Deleting routing table %s\n", r->name);
   ASSERT_DIE(r->use_count == 0);
-  ASSERT_DIE(r->deleted);
-
-  r->config->table = NULL;
-  rem_node(&r->n);
-
-  if (r->hostcache)
-    rt_free_hostcache(r);
+  ASSERT_DIE(r->rt_count == 0);
+  ASSERT_DIE(EMPTY_LIST(r->imports));
+  ASSERT_DIE(EMPTY_LIST(r->exports));
 
   /* Freed automagically by the resource pool
   fib_free(&r->fib);
@@ -2142,7 +2101,11 @@ rt_setup(pool *pp, struct rtable_config *cf)
   init_list(&t->pending_exports);
   init_list(&t->subscribers);
 
-  t->rt_event = ev_new_init(p, rt_event, t);
+  t->ec_event = ev_new_init(p, rt_export_cleanup, t);
+  t->prune_event = ev_new_init(p, rt_prune_table, t);
+  t->hcu_event = ev_new_init(p, rt_update_hostcache, t);
+  t->nhu_event = ev_new_init(p, rt_next_hop_update, t);
+
   t->export_timer = tm_new_init(p, rt_announce_exports, t, 0, 0);
   t->last_rt_change = t->gc_time = current_time();
   t->next_export_seq = 1;
@@ -2167,7 +2130,6 @@ rt_init(void)
   init_list(&routing_tables);
 }
 
-
 /**
  * rt_prune_table - prune a routing table
  *
@@ -2183,8 +2145,9 @@ rt_init(void)
  * iteration.
  */
 static void
-rt_prune_table(rtable *tab)
+rt_prune_table(void *data)
 {
+  rtable *tab = data;
   struct fib_iterator *fit = &tab->prune_fit;
   int limit = 512;
 
@@ -2232,7 +2195,7 @@ again:
            if (limit <= 0)
              {
                FIB_ITERATE_PUT(fit);
-               ev_schedule(tab->rt_event);
+               ev_schedule(tab->prune_event);
                return;
              }
 
@@ -2288,9 +2251,9 @@ again:
 }
 
 static void
-rt_export_cleanup(rtable *tab)
+rt_export_cleanup(void *data)
 {
-  tab->export_used = 0;
+  rtable *tab = data;
 
   u64 min_seq = ~((u64) 0);
   struct rt_pending_export *last_export_to_free = NULL;
@@ -2447,9 +2410,6 @@ done:;
        imports_stopped = 1;
       }
 
-  if (tab->export_used)
-    ev_schedule(tab->rt_event);
-
   if (imports_stopped)
   {
     if (config->table_debug)
@@ -2683,8 +2643,9 @@ rt_next_hop_update_net(rtable *tab, net *n)
 }
 
 static void
-rt_next_hop_update(rtable *tab)
+rt_next_hop_update(void *data)
 {
+  rtable *tab = data;
   struct fib_iterator *fit = &tab->nhu_fit;
   int max_feed = 32;
 
@@ -2702,7 +2663,7 @@ rt_next_hop_update(rtable *tab)
       if (max_feed <= 0)
        {
          FIB_ITERATE_PUT(fit);
-         ev_schedule(tab->rt_event);
+         ev_schedule(tab->nhu_event);
          return;
        }
       max_feed -= rt_next_hop_update_net(tab, n);
@@ -2716,7 +2677,7 @@ rt_next_hop_update(rtable *tab)
   tab->nhu_state &= 1;
 
   if (tab->nhu_state != NHU_CLEAN)
-    ev_schedule(tab->rt_event);
+    ev_schedule(tab->nhu_event);
 }
 
 
@@ -2738,6 +2699,7 @@ rt_new_table(struct symbol *s, uint addr_type)
   c->gc_min_time = 5;
   c->min_settle_time = 1 S;
   c->max_settle_time = 20 S;
+  c->config = new_config;
 
   add_tail(&new_config->tables, &c->n);
 
@@ -2773,17 +2735,12 @@ rt_lock_table(rtable *r)
 void
 rt_unlock_table(rtable *r)
 {
-  if (!--r->use_count && r->deleted)
-    {
-      void *del_data = r->del_data;
-      void (*deleted)(void *) = r->deleted;
-
-      /* Delete the routing table by freeing its pool */
-      rt_shutdown(r);
-      deleted(del_data);
-    }
+  if (!--r->use_count && r->delete_event)
+    /* Delete the routing table by freeing its pool */
+    ev_schedule(r->delete_event);
 }
 
+
 static struct rtable_config *
 rt_find_table_config(struct config *cf, char *name)
 {
@@ -2791,7 +2748,23 @@ rt_find_table_config(struct config *cf, char *name)
   return (sym && (sym->class == SYM_TABLE)) ? sym->table : NULL;
 }
 
-static void rt_config_del_obstacle(void *data) { config_del_obstacle(data); }
+static void
+rt_done(void *data)
+{
+  rtable *t = data;
+  struct rtable_config *tc = t->config;
+  struct config *c = tc->config;
+
+  tc->table = NULL;
+  rem_node(&t->n);
+
+  if (t->hostcache)
+    rt_free_hostcache(t);
+
+  rfree(t->rp);
+
+  config_del_obstacle(c);
+}
 
 /**
  * rt_commit - commit new routing table configuration
@@ -2816,7 +2789,7 @@ rt_commit(struct config *new, struct config *old)
       WALK_LIST(o, old->tables)
        {
          rtable *ot = o->table;
-         if (!ot->deleted)
+         if (!ot->delete_event)
            {
              r = rt_find_table_config(new, o->name);
              if (r && (r->addr_type == o->addr_type) && !new->shutdown)
@@ -2832,8 +2805,7 @@ rt_commit(struct config *new, struct config *old)
                {
                  DBG("\t%s: deleted\n", o->name);
                  rt_lock_table(ot);
-                 ot->deleted = rt_config_del_obstacle;
-                 ot->del_data = old;
+                 ot->delete_event = ev_new_init(ot->rp, rt_done, ot);
                  config_add_obstacle(old);
                  rt_unlock_table(ot);
                }
@@ -3060,11 +3032,11 @@ rt_free_hostcache(rtable *tab)
 static void
 rt_notify_hostcache(rtable *tab, net *net)
 {
-  if (tab->hcu_scheduled)
+  if (ev_active(tab->hcu_event))
     return;
 
   if (trie_match_net(tab->hostcache->trie, net->n.addr))
-    rt_schedule_hcu(tab);
+    ev_schedule(tab->hcu_event);
 }
 
 static int
@@ -3161,8 +3133,9 @@ done:
 }
 
 static void
-rt_update_hostcache(rtable *tab)
+rt_update_hostcache(void *data)
 {
+  rtable *tab = data;
   struct hostcache *hc = tab->hostcache;
   struct hostentry *he;
   node *n, *x;
@@ -3183,8 +3156,6 @@ rt_update_hostcache(rtable *tab)
       if (rt_update_hostentry(tab, he))
        rt_schedule_nhu(he->tab);
     }
-
-  tab->hcu_scheduled = 0;
 }
 
 struct hostentry *