summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2018-08-08 13:08:55 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2018-08-08 13:08:55 +0000
commit8af63106b213787e38e9ec66b470b5f64ec0b831 (patch)
tree0c16a3a6199e83af1f9ca285b4a682a8f5dc21e7 /usr.sbin
parent952191b0775597902b4e5691d3364d647a419cbb (diff)
Update the RIB after a config reload in the background. This moves the
heavy bits into the background and so the RDE is able to process new messages more or less instantly after a configuration reload. Not all cases are covered yet but the bulk is. While the backgorund process is running no new config can be loaded. Tested by and OK benno@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bgpd/rde.c116
-rw-r--r--usr.sbin/bgpd/rde.h4
2 files changed, 105 insertions, 15 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 79cf5a42545..8ee91c291fb 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.412 2018/08/08 06:54:50 benno Exp $ */
+/* $OpenBSD: rde.c,v 1.413 2018/08/08 13:08:54 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -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. */
@@ -2715,6 +2722,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;
@@ -2835,14 +2843,55 @@ rde_reload_done(void)
filterlist_free(ribs[rid].in_rules_tmp);
ribs[rid].in_rules_tmp = NULL;
}
+ log_info("RDE reconfigured");
+
+ 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;
- if (reload > 0)
- rib_dump(&ribs[RIB_ADJ_IN].rib, rde_softreconfig_in, NULL,
- AID_UNSPEC);
+ /* 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)
@@ -2852,18 +2901,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;
@@ -2876,7 +2960,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);
}
@@ -2900,6 +2984,10 @@ rde_softreconfig_in(struct rib_entry *re, void *bula)
asp = prefix_aspath(p);
peer = prefix_peer(p);
+ /* skip announced networks, they are never filtered */
+ if (asp->flags & F_PREFIX_ANNOUNCED)
+ continue;
+
for (i = RIB_LOC_START; i < rib_size; i++) {
rib = &ribs[i];
if (rib->state != RECONF_RELOAD)
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index 0e30e476559..6049bdaa60f 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.185 2018/08/08 06:54:50 benno Exp $ */
+/* $OpenBSD: rde.h,v 1.186 2018/08/08 13:08:54 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -287,9 +287,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