So the reshuffling made it possible to simply run the reconfigure
of the RIBs in the background and no longer lock up the RDE for
extended times. In short this means that during 'bgpctl reload'
other bgpctl calls no longer block and that also UPDATE from neighbors
are fully processed.

This does not really spead up anything (apart from maybe some cache
related speedups) but it makes it look faster :)
-- 
:wq Claudio

Index: rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
retrieving revision 1.407
diff -u -p -r1.407 rde.c
--- rde.c       3 Aug 2018 14:10:39 -0000       1.407
+++ rde.c       3 Aug 2018 14:18:42 -0000
@@ -90,7 +90,10 @@ void          rde_rib_free(struct rib_desc *);
 
 int             rde_rdomain_import(struct rde_aspath *, struct rdomain *);
 void            rde_reload_done(void);
-static void     rde_softreconfig_done(void *);
+static void     rde_reload_runner(void);
+static void     rde_softreconfig_in_done(void *);
+static void     rde_softreconfig_out_done(void *);
+static void     rde_softreconfig_done(void);
 static void     rde_softreconfig_out(struct rib_entry *, void *);
 static void     rde_softreconfig_in(struct rib_entry *, void *);
 static void     rde_softreconfig_unload_peer(struct rib_entry *, void *);
@@ -132,6 +135,7 @@ struct imsgbuf              *ibuf_se;
 struct imsgbuf         *ibuf_se_ctl;
 struct imsgbuf         *ibuf_main;
 struct rde_memstats     rdemem;
+int                     softreconfig;
 
 struct rde_dump_ctx {
        LIST_ENTRY(rde_dump_ctx)        entry;
@@ -322,6 +326,9 @@ rde_main(int debug, int verbose)
                if (rde_dump_pending() &&
                    ibuf_se_ctl && ibuf_se_ctl->w.queued <= 10)
                        rde_dump_runner();
+               if (softreconfig) {
+                       rde_reload_runner();
+               }
        }
 
        /* do not clean up on shutdown on production, it takes ages. */
@@ -2697,6 +2704,7 @@ rde_reload_done(void)
        struct rdomain          *rd;
        struct rde_peer         *peer;
        struct filter_head      *fh;
+       struct rib_context      *ctx;
        u_int16_t                rid;
        int                      reload = 0;
 
@@ -2817,14 +2825,55 @@ rde_reload_done(void)
                filterlist_free(ribs[rid].in_rules_tmp);
                ribs[rid].in_rules_tmp = NULL;
        }
+       log_info("RDE reconfigured");
 
-       if (reload > 0)
-               rib_dump(&ribs[RIB_ADJ_IN].rib, rde_softreconfig_in, NULL,
-                   AID_UNSPEC);
+       softreconfig++;
+       if (reload > 0) {
+               ctx = &ribs[RIB_ADJ_IN].ribctx;
+               memset(ctx, 0, sizeof(*ctx));
+               ctx->ctx_rib = &ribs[RIB_ADJ_IN].rib;
+               ctx->ctx_arg = &ribs[RIB_ADJ_IN];
+               ctx->ctx_upcall = rde_softreconfig_in;
+               ctx->ctx_done = rde_softreconfig_in_done;
+               ctx->ctx_aid = AID_UNSPEC;
+               ctx->ctx_count = RDE_RUNNER_ROUNDS;
+               ribs[RIB_ADJ_IN].dumping = 1;
+               log_info("running softreconfig in");
+       } else {
+               rde_softreconfig_in_done(&ribs[RIB_ADJ_IN]);
+       }
+}
+
+static void
+rde_reload_runner(void)
+{
+       u_int16_t       rid;
+
+       for (rid = 0; rid < rib_size; rid++) {
+               if (*ribs[rid].name == '\0')
+                       continue;
+               if (ribs[rid].dumping)
+                       rib_dump_r(&ribs[rid].ribctx);
+       }
+}
+
+static void
+rde_softreconfig_in_done(void *arg)
+{
+       struct rib_desc         *rib = arg;
+       struct rde_peer         *peer;
+       u_int16_t                rid;
+
+       /* Adj-RIB-In run is done */
+       softreconfig--;
+       rib->dumping = 0;
 
        /* now do the Adj-RIB-Out sync */
-       for (rid = 0; rid < rib_size; rid++)
+       for (rid = 0; rid < rib_size; rid++) {
+               if (*ribs[rid].name == '\0')
+                       continue;
                ribs[rid].state = RECONF_NONE;
+       }
 
        LIST_FOREACH(peer, &peerlist, peer_l) {
                if (peer->reconf_out)
@@ -2834,18 +2883,53 @@ rde_reload_done(void)
                        peer_dump(peer->conf.id, AID_UNSPEC);
        }
 
-       for (rid = 0; rid < rib_size; rid++)
-               if (ribs[rid].state == RECONF_RELOAD)
-                       rib_dump(&ribs[rid].rib, rde_softreconfig_out, NULL,
-                           AID_UNSPEC);
+       for (rid = 0; rid < rib_size; rid++) {
+               if (*ribs[rid].name == '\0')
+                       continue;
+               if (ribs[rid].state == RECONF_RELOAD) {
+                       struct rib_context      *ctx;
+
+                       ctx = &ribs[rid].ribctx;
+                       memset(ctx, 0, sizeof(*ctx));
+                       ctx->ctx_rib = &ribs[rid].rib;
+                       ctx->ctx_arg = &ribs[rid];
+                       ctx->ctx_upcall = rde_softreconfig_out;
+                       ctx->ctx_done = rde_softreconfig_out_done;
+                       ctx->ctx_aid = AID_UNSPEC;
+                       ctx->ctx_count = RDE_RUNNER_ROUNDS;
+                       ribs[rid].dumping = 1;
+                       softreconfig++;
+                       log_info("starting softreconfig out for rib %s",
+                           ribs[rid].name);
+               }
+       }
 
-       rde_softreconfig_done(NULL);
+       /* if nothing to do move to last stage */
+       if (softreconfig == 0) 
+               rde_softreconfig_done();
 }
 
 static void
-rde_softreconfig_done(void *arg)
+rde_softreconfig_out_done(void *arg)
 {
-       u_int16_t                rid;
+       struct rib_desc         *rib = arg;
+
+       /* this RIB dump is done */
+       softreconfig--;
+       rib->dumping = 0;
+       log_info("softreconfig out done for %s", rib->name);
+
+       /* but other dumps are still running */
+       if (softreconfig > 0)
+               return;
+
+       rde_softreconfig_done();
+}
+
+static void
+rde_softreconfig_done(void)
+{
+       u_int16_t       rid;
 
        filterlist_free(out_rules_tmp);
        out_rules_tmp = NULL;
@@ -2858,7 +2942,7 @@ rde_softreconfig_done(void *arg)
        free_prefixsets(prefixsets_old);
        prefixsets_old = NULL;
 
-       log_info("RDE reconfigured");
+       log_info("RDE soft reconfiguration done");
        imsg_compose(ibuf_main, IMSG_RECONF_DONE, 0, 0,
            -1, NULL, 0);
 }
Index: rde.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v
retrieving revision 1.182
diff -u -p -r1.182 rde.h
--- rde.h       31 Jul 2018 15:30:04 -0000      1.182
+++ rde.h       3 Aug 2018 14:18:42 -0000
@@ -293,9 +293,11 @@ struct rib {
 struct rib_desc {
        char                    name[PEER_DESCR_LEN];
        struct rib              rib;
+       struct rib_context      ribctx;
        struct filter_head      *in_rules;
        struct filter_head      *in_rules_tmp;
        enum reconf_action      state;
+       u_int8_t                dumping;
 };
 
 #define RIB_ADJ_IN     0

Reply via email to