-/* $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>
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 *);
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;
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. */
struct rdomain *rd;
struct rde_peer *peer;
struct filter_head *fh;
+ struct rib_context *ctx;
u_int16_t rid;
int reload = 0;
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)
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;
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);
}
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)