]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Higher export settle times when route refresh is running.
authorMaria Matejka <mq@ucw.cz>
Mon, 26 Sep 2022 10:09:14 +0000 (12:09 +0200)
committerMaria Matejka <mq@ucw.cz>
Mon, 26 Sep 2022 10:09:14 +0000 (12:09 +0200)
This helps the route refresh procedures to finish or at least
do more work before the exporters jump in and steal all the CPU time
for themselves.

doc/bird.sgml
nest/config.Y
nest/rt-table.c
nest/rt.h

index 9399137cf98e93f6d18a04a74b4969a16e40fc9d..0cfe19c4e180be865ad7706bc2ea993054016c06 100644 (file)
@@ -706,6 +706,14 @@ to set options.
        steadily, BIRD isn't waiting forever; at most the maximum time.
        Default values: <cf/1 ms 100 ms/. You have to always provide both values.
 
+       <tag><label id="rtable-route-refresh-export-settle-time">route refresh export settle time <m/time/ <m/time/</tag>
+       Minimum and maximum settle times, respectively, for export announcements
+       (the same as above), valid when any channel is currently doing a route refresh.
+       This serves a purpose of even more aggresive change bundling, knowing that there
+       is some active process generating changes in a fast pace. If you don't want
+       this feature, set this to the same values as <ref id="rtable-export-settle-time" name="export settle time">.
+       Default values: <cf/100 ms 3 s/.
+
        <tag><label id="rtable-debug">debug all|off|{ states|routes|events [, <m/.../] }</tag>
        Set table debugging options. Each table can write some trace messages
        into log with category <cf/trace/. You can request <cf/all/ trace messages
index a8e48cfedc965c118a2050c3523f2553b5c6375b..f2904882123f11ab5dd4fcb2be60d9f706a6e2dd 100644 (file)
@@ -125,7 +125,7 @@ CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, ROUTE, PROTOCOL, BASE, LOG, S, MS, US)
 CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, AS)
 CF_KEYWORDS(MIN, IDLE, RX, TX, INTERVAL, MULTIPLIER, PASSIVE)
 CF_KEYWORDS(CHECK, LINK)
-CF_KEYWORDS(CORK, SORTED, TRIE, MIN, MAX, ROA, SETTLE, TIME, GC, THRESHOLD, PERIOD)
+CF_KEYWORDS(CORK, SORTED, TRIE, MIN, MAX, ROA, ROUTE, REFRESH, SETTLE, TIME, GC, THRESHOLD, PERIOD)
 
 /* For r_args_channel */
 CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, IPV6_SADR, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC)
@@ -233,6 +233,8 @@ table_opt:
      if ($3 > $4) cf_error("Cork low threshold must be lower than the high threshold.");
      this_table->cork_threshold.low = $3;
      this_table->cork_threshold.high = $4; }
+ | EXPORT SETTLE TIME settle { this_table->export_settle = $4; }
+ | ROUTE REFRESH EXPORT SETTLE TIME settle { this_table->export_rr_settle = $6; }
  | DEBUG bool { this_table->debug = $2; }
  ;
 
index 7a21dc394d669cfc1ebffe521a471ba8b657c9ee..36d69d92b778d13eb69187345d51b75d864ab61e 100644 (file)
@@ -1439,6 +1439,13 @@ rt_announce_exports(struct settle *s)
     }
 }
 
+static void
+rt_kick_export_settle(struct rtable_private *tab)
+{
+  tab->export_settle.cf = tab->rr_counter ? tab->config->export_rr_settle : tab->config->export_settle;
+  settle_kick(&tab->export_settle, tab->loop);
+}
+
 static void
 rt_import_announce_exports(void *_hook)
 {
@@ -2039,6 +2046,13 @@ rt_stop_import(struct rt_import_request *req, void (*stopped)(struct rt_import_r
     rt_schedule_prune(tab);
     rt_set_import_state(hook, TIS_STOP);
     hook->stopped = stopped;
+
+    if (hook->stale_set != hook->stale_pruned)
+      tab->rr_counter -= (hook->stale_set - hook->stale_pruned - 1);
+    else
+      tab->rr_counter++;
+
+    hook->stale_set = hook->stale_pruned = hook->stale_pruning = hook->stale_valid = 0;
   }
 }
 
@@ -2301,6 +2315,7 @@ rt_refresh_begin(struct rt_import_request *req)
            e->rte.stale_cycle = 0;
       }
     FIB_WALK_END;
+    tab->rr_counter -= (hook->stale_set - hook->stale_pruned - 1);
     hook->stale_set = 1;
     hook->stale_valid = 0;
     hook->stale_pruned = 0;
@@ -2311,6 +2326,7 @@ rt_refresh_begin(struct rt_import_request *req)
     /* Let's reserve the stale_cycle zero value for always-invalid routes */
     hook->stale_set = 1;
     hook->stale_valid = 0;
+    tab->rr_counter++;
   }
 
   if (req->trace_routes & D_STATES)
@@ -2514,7 +2530,7 @@ rt_flag_handler(struct birdloop_flag_handler *fh, u32 flags)
       rt_next_hop_update(tab);
 
     if (flags & RTF_EXPORT)
-      settle_kick(&tab->export_settle, tab->loop);
+      rt_kick_export_settle(tab);
 
     if (flags & RTF_CLEANUP)
     {
@@ -2947,7 +2963,7 @@ again:
   FIB_ITERATE_END;
 
   rt_trace(tab, D_EVENTS, "Prune done, scheduling export timer");
-  settle_kick(&tab->export_settle, tab->loop);
+  rt_kick_export_settle(tab);
 
 #ifdef DEBUGGING
   fib_check(&tab->fib);
@@ -2997,9 +3013,11 @@ again:
       ih->flush_seq = tab->exporter.next_seq;
       rt_set_import_state(ih, TIS_WAITING);
       flushed_channels++;
+      tab->rr_counter--;
     }
     else if (ih->stale_pruning != ih->stale_pruned)
     {
+      tab->rr_counter -= (ih->stale_pruned - ih->stale_pruning);
       ih->stale_pruned = ih->stale_pruning;
       if (ih->req->trace_routes & D_STATES)
        log(L_TRACE "%s: table prune after refresh end [%u]", ih->req->name, ih->stale_pruned);
@@ -3809,7 +3827,7 @@ rt_next_hop_update(struct rtable_private *tab)
     rt_trace(tab, D_STATES, "Next hop updater corked");
     if ((tab->nhu_state & NHU_RUNNING)
        && !EMPTY_LIST(tab->exporter.pending))
-      settle_kick(&tab->export_settle, tab->loop);
+      rt_kick_export_settle(tab);
 
     tab->nhu_corked = tab->nhu_state;
     tab->nhu_state = 0;
@@ -3847,7 +3865,7 @@ rt_next_hop_update(struct rtable_private *tab)
 
   /* Finished NHU, cleanup */
   rt_trace(tab, D_EVENTS, "NHU done, scheduling export timer");
-  settle_kick(&tab->export_settle, tab->loop);
+  rt_kick_export_settle(tab);
 
   /* State change:
    *   NHU_DIRTY   -> NHU_SCHEDULED
@@ -3903,6 +3921,10 @@ rt_new_table(struct symbol *s, uint addr_type)
     .min = 1 MS,
     .max = 100 MS,
   };
+  c->export_rr_settle = (struct settle_config) {
+    .min = 100 MS,
+    .max = 3 S,
+  };
   c->debug = new_config->table_debug;
 
   add_tail(&new_config->tables, &c->n);
@@ -4014,8 +4036,6 @@ rt_reconfigure(struct rtable_private *tab, struct rtable_config *new, struct rta
   tab->name = new->name;
   tab->config = new;
 
-  tab->export_settle.cf = new->export_settle;
-
   if (tab->hostcache)
     tab->hostcache->req.trace_routes = new->debug;
 
index d53f54e15f0072ef7e6552900869af3e7f64f2a8..6ee2ce9be1d5f2cb668593187330c3a9951e26d9 100644 (file)
--- a/nest/rt.h
+++ b/nest/rt.h
@@ -65,6 +65,8 @@ struct rtable_config {
   byte debug;                          /* Whether to log */
   struct rt_cork_threshold cork_threshold;     /* Cork threshold values */
   struct settle_config export_settle;  /* Export announcement settler */
+  struct settle_config export_rr_settle;/* Export announcement settler config valid when any
+                                          route refresh is running */
 };
 
 struct rt_export_hook;
@@ -136,6 +138,9 @@ struct rtable_private {
   btime last_rt_change;                        /* Last time when route changed */
   btime gc_time;                       /* Time of last GC */
   uint gc_counter;                     /* Number of operations since last GC */
+  uint rr_counter;                     /* Number of currently running route refreshes,
+                                          in fact sum of (stale_set - stale_pruned) over all importers
+                                          + one for each TIS_FLUSHING importer */
   byte prune_state;                    /* Table prune state, 1 -> scheduled, 2-> running */
   byte prune_trie;                     /* Prune prefix trie during next table prune */
   byte nhu_state;                      /* Next Hop Update state */