]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Higher settle times when route refresh in the source table is running
authorMaria Matejka <mq@ucw.cz>
Tue, 16 Nov 2021 11:23:24 +0000 (12:23 +0100)
committerMaria Matejka <mq@ucw.cz>
Mon, 22 Nov 2021 18:05:44 +0000 (19:05 +0100)
nest/route.h
nest/rt-table.c

index 531e004be46bbce60dfe0fd70e62cd135fb70b7b..b5d44040f9c15dcd1aee26da0761ab3261d49906 100644 (file)
@@ -163,6 +163,7 @@ typedef struct rtable_private {
   struct fib fib;
   int use_count;                       /* Number of protocols using this table */
   u32 rt_count;                                /* Number of routes in the table */
+  u32 rr_count;                                /* Number of running route refresh requests */
 
   list imports;                                /* Registered route importers */
   list exports;                                /* Registered route exporters */
@@ -220,6 +221,8 @@ struct rtable_config {
   byte sorted;                         /* Routes of network are sorted according to rte_better() */
   btime min_settle_time;               /* Minimum settle time for notifications */
   btime max_settle_time;               /* Maximum settle time for notifications */
+  btime min_rr_settle_time;            /* Minimum settle time for notifications when route refresh is running */
+  btime max_rr_settle_time;            /* Maximum settle time for notifications when route refresh is running */
   uint cork_limit;                     /* Amount of routes to be pending on export to cork imports */
 };
 
index a2f62df7b8c24bd38b51044ed678397ab40c5dcf..d09abbef713682db9b47e553f15eebaa1e3f179e 100644 (file)
@@ -1752,14 +1752,18 @@ rt_stop_import(struct rt_import_request *req, event *stopped)
   ASSERT_DIE(req->hook);
   struct rt_import_hook *hook = req->hook;
 
-  RT_LOCK(hook->table);
+  rtable_private *tab = RT_LOCK(hook->table);
 
-  rt_schedule_prune(RT_PRIV(hook->table));
+  rt_schedule_prune(tab);
 
   rt_set_import_state(hook, TIS_STOP);
   hook->stopped = stopped;
 
-  RT_UNLOCK(hook->table);
+  if (hook->stale_set < hook->stale_valid)
+    if (!--tab->rr_count)
+      rt_schedule_notify(tab);
+
+  RT_UNLOCK(tab);
 }
 
 void
@@ -1864,6 +1868,8 @@ rt_refresh_begin(struct rt_import_request *req)
     hook->stale_valid = 0;
   }
 
+  tab->rr_count++;
+
   if (req->trace_routes & D_STATES)
     log(L_TRACE "%s: route refresh begin [%u]", req->name, hook->stale_set);
 
@@ -1884,16 +1890,19 @@ rt_refresh_end(struct rt_import_request *req)
   struct rt_import_hook *hook = req->hook;
   ASSERT_DIE(hook);
 
-  RT_LOCK(hook->table);
+  rtable_private *tab = RT_LOCK(hook->table);
   hook->stale_valid++;
   ASSERT_DIE(hook->stale_set == hook->stale_valid);
 
-  rt_schedule_prune(RT_PRIV(hook->table));
+  rt_schedule_prune(tab);
 
   if (req->trace_routes & D_STATES)
     log(L_TRACE "%s: route refresh end [%u]", req->name, hook->stale_valid);
 
-  RT_UNLOCK(hook->table);
+  if (!--tab->rr_count)
+    rt_schedule_notify(tab);
+
+  RT_UNLOCK(tab);
 }
 
 /**
@@ -2032,8 +2041,17 @@ rt_settled_time(rtable_private *tab)
 {
   ASSUME(tab->base_settle_time != 0);
 
-  return MIN(tab->last_rt_change + tab->config->min_settle_time,
-            tab->base_settle_time + tab->config->max_settle_time);
+  btime min_settle_time = tab->rr_count ? tab->config->min_rr_settle_time : tab->config->min_settle_time;
+  btime max_settle_time = tab->rr_count ? tab->config->max_rr_settle_time : tab->config->max_settle_time;
+
+  DBG("settled time computed from %t %t %t %t as %t / %t, now is %t\n",
+      tab->name, tab->last_rt_change, min_settle_time,
+            tab->base_settle_time, max_settle_time,
+            tab->last_rt_change + min_settle_time,
+            tab->base_settle_time + max_settle_time, current_time());
+
+  return MIN(tab->last_rt_change + min_settle_time,
+            tab->base_settle_time + max_settle_time);
 }
 
 static void
@@ -2794,6 +2812,8 @@ 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->min_rr_settle_time = 30 S;
+  c->max_rr_settle_time = 90 S;
   c->cork_limit = 4 * page_size / sizeof(struct rt_pending_export);
   c->config = new_config;