]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Added an indirection to the export announcement routine
authorMaria Matejka <mq@ucw.cz>
Thu, 1 Sep 2022 09:17:35 +0000 (11:17 +0200)
committerMaria Matejka <mq@ucw.cz>
Thu, 1 Sep 2022 20:22:31 +0000 (22:22 +0200)
There are performance reasons for this, mostly that we don't want to
ping the table service routine with every import.

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

index f4615c2f25911231f63c1408791bca5da92b869a..783672ecb821b6a2baccc0383c8d9b32db83adb6 100644 (file)
@@ -511,6 +511,7 @@ channel_start_import(struct channel *c)
   c->in_req = (struct rt_import_request) {
     .name = mb_sprintf(c->proto->pool, "%s.%s", c->proto->name, c->name),
     .trace_routes = c->debug | c->proto->debug,
+    .list = proto_work_list(c->proto),
     .dump_req = channel_dump_import_req,
     .log_state_change = channel_import_log_state_change,
     .preimport = channel_preimport,
index 2fa736e20b97039e6d4cdf985c0b6088556721cd..3188ddf87462e6e34bd815a831c6c88040502b8e 100644 (file)
@@ -1354,9 +1354,6 @@ rte_announce(rtable *tab, net *net, struct rte_storage *new, struct rte_storage
     tab->exporter.first = rpe;
 
   rt_check_cork_high(tab);
-
-  if (!tm_active(tab->exporter.export_timer))
-    tm_start(tab->exporter.export_timer, tab->config->export_settle_time);
 }
 
 static struct rt_pending_export *
@@ -1410,6 +1407,9 @@ rt_announce_exports(timer *tm)
 {
   rtable *tab = tm->data;
 
+  if (EMPTY_LIST(tab->exporter.pending))
+    return;
+
   struct rt_export_hook *c; node *n;
   WALK_LIST2(c, n, tab->exporter.hooks, n)
   {
@@ -1420,6 +1420,28 @@ rt_announce_exports(timer *tm)
   }
 }
 
+static void
+rt_import_announce_exports(void *_hook)
+{
+  struct rt_import_hook *hook = _hook;
+  rtable *tab = hook->table;
+
+
+  if (hook->import_state == TIS_CLEARED)
+  {
+    rt_trace(tab, D_EVENTS, "Hook %s stopped", hook->req->name);
+    hook->stopped(hook->req);
+    rem_node(&hook->n);
+    mb_free(hook);
+    rt_unlock_table(tab);
+  }
+
+  rt_trace(tab, D_EVENTS, "Announcing exports after imports from %s", hook->req->name);
+
+  if (!tm_active(tab->exporter.export_timer))
+    tm_start(tab->exporter.export_timer, tab->config->export_settle_time);
+}
+
 static struct rt_pending_export *
 rt_last_export(struct rt_exporter *tab)
 {
@@ -1535,7 +1557,7 @@ rte_same(rte *x, rte *y)
 
 static inline int rte_is_ok(rte *e) { return e && !rte_is_filtered(e); }
 
-static void
+static int
 rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *src)
 {
   struct rt_import_request *req = c->req;
@@ -1588,7 +1610,7 @@ rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *sr
 
              /* We need to free the already stored route here before returning */
              rte_free(new_stored);
-             return;
+             return 0;
          }
 
        *before_old = (*before_old)->next;
@@ -1598,7 +1620,7 @@ rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *sr
   if (!old && !new)
     {
       stats->withdraws_ignored++;
-      return;
+      return 0;
     }
 
   /* If rejected by import limit, we need to pretend there is no route */
@@ -1734,14 +1756,7 @@ rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *sr
   rte_announce(table, net, new_stored, old_stored,
       net->routes, old_best_stored);
 
-#if 0
-  /* Enable and reimplement these callbacks if anybody wants to use them */
-  if (old_ok && p->rte_remove)
-    p->rte_remove(net, old);
-  if (new_ok && p->rte_insert)
-    p->rte_insert(net, &new_stored->rte);
-#endif
-
+  return 1;
 }
 
 int
@@ -1869,8 +1884,9 @@ rte_import(struct rt_import_request *req, const net_addr *n, rte *new, struct rt
       return;
     }
 
-  /* And recalculate the best route */
-  rte_recalculate(hook, nn, new, src);
+  /* Recalculate the best route */
+  if (rte_recalculate(hook, nn, new, src))
+    ev_send(req->list, &hook->announce_event);
 }
 
 /* Check rtable for best route to given net whether it would be exported do p */
@@ -1951,14 +1967,14 @@ rt_request_import(rtable *tab, struct rt_import_request *req)
 
   struct rt_import_hook *hook = req->hook = mb_allocz(tab->rp, sizeof(struct rt_import_hook));
 
+  hook->announce_event = (event) { .hook = rt_import_announce_exports, .data = hook };
+
   DBG("Lock table %s for import %p req=%p uc=%u\n", tab->name, hook, req, tab->use_count);
 
   hook->req = req;
   hook->table = tab;
 
   rt_set_import_state(hook, TIS_UP);
-
-  hook->n = (node) {};
   add_tail(&tab->imports, &hook->n);
 }
 
@@ -2313,7 +2329,13 @@ rt_event(void *ptr)
   if (tab->nhu_corked || tab->nhu_state && rt_cork_check(tab->uncork_event))
   {
     if (!tab->nhu_corked)
+    {
       rt_trace(tab, D_STATES, "Next hop updater corked");
+      if ((tab->nhu_state & NHU_RUNNING)
+         && !EMPTY_LIST(tab->exporter.pending)
+         && !tm_active(tab->exporter.export_timer))
+       tm_start(tab->exporter.export_timer, tab->config->export_settle_time);
+    }
 
     tab->nhu_corked |= tab->nhu_state;
     tab->nhu_state = 0;
@@ -2699,6 +2721,10 @@ again:
     }
   FIB_ITERATE_END;
 
+  rt_trace(tab, D_EVENTS, "Prune done, scheduling export timer");
+  if (!tm_active(tab->exporter.export_timer))
+    tm_start(tab->exporter.export_timer, tab->config->export_settle_time);
+
 #ifdef DEBUGGING
   fib_check(&tab->fib);
 #endif
@@ -2912,10 +2938,7 @@ done:;
       if (!first || (first->seq >= ih->flush_seq))
       {
        ih->import_state = TIS_CLEARED;
-       ih->stopped(ih->req);
-       rem_node(&ih->n);
-       mb_free(ih);
-       rt_unlock_table(tab);
+       ev_send(ih->req->list, &ih->announce_event);
       }
 
   if ((tab->gc_counter += want_prune) >= tab->config->gc_threshold)
@@ -3497,6 +3520,11 @@ rt_next_hop_update(rtable *tab)
     }
   FIB_ITERATE_END;
 
+  rt_trace(tab, D_EVENTS, "NHU done, scheduling export timer");
+
+  if (!tm_active(tab->exporter.export_timer))
+    tm_start(tab->exporter.export_timer, tab->config->export_settle_time);
+
   /* State change:
    *   NHU_DIRTY   -> NHU_SCHEDULED
    *   NHU_RUNNING -> NHU_CLEAN
index c5948512a86407922eccfda9f30d6caf894d0b59..78585c794234cf6a01fa3033384837e26acb3893 100644 (file)
--- a/nest/rt.h
+++ b/nest/rt.h
@@ -187,6 +187,8 @@ struct rt_import_request {
   char *name;
   u8 trace_routes;
 
+  event_list *list;                    /* Where to schedule announce events */
+
   void (*dump_req)(struct rt_import_request *req);
   void (*log_state_change)(struct rt_import_request *req, u8 state);
   /* Preimport is called when the @new route is just-to-be inserted, replacing @old.
@@ -218,6 +220,7 @@ struct rt_import_hook {
   u8 stale_pruning;                    /* Last prune started when this value was set at stale_valid */
 
   void (*stopped)(struct rt_import_request *); /* Stored callback when import is stopped */
+  event announce_event;                        /* This event announces table updates */
 };
 
 struct rt_pending_export {