watchdog_warning,
watchdog_timeout,
gr_wait,
- hostname
+ hostname,
+ shutdown
);
#undef COPY
u32 latency_limit; /* Events with longer duration are logged (us) */
u32 watchdog_warning; /* I/O loop watchdog limit for warning (us) */
u32 watchdog_timeout; /* Watchdog timeout (in seconds, 0 = disabled) */
+
+ int shutdown; /* Shutdown in progress */
};
+#define SHUTTING_DOWN atomic_load_explicit(&global_runtime, memory_order_acquire)->shutdown
+
extern struct global_runtime * _Atomic global_runtime;
/* Please don't use these variables in protocols. Use proto_config->global instead. */
protos_commit_request.phase--;
/* If something is pending, the next round will be called asynchronously from proto_rethink_goal(). */
- if (!proto_rethink_goal_pending)
+ if (new->shutdown || !proto_rethink_goal_pending)
protos_do_commit(new, old, type);
}
proto_start(p);
done:
- if (goal_pending && !--proto_rethink_goal_pending)
+ if (goal_pending && !--proto_rethink_goal_pending && protos_commit_request.new)
protos_do_commit(
protos_commit_request.new,
protos_commit_request.old,
static void
aggregator_rt_notify(struct proto *P, struct channel *src_ch, const net_addr *net, rte *new, const rte *old)
{
+ /* Ignore everything on shutdown */
+ if (SHUTTING_DOWN)
+ return;
+
SKIP_BACK_DECLARE(struct aggregator_proto, p, p, P);
ASSERT_DIE(src_ch == p->src);
struct aggregator_bucket *new_bucket = NULL, *old_bucket = NULL;
static int
aggregator_preexport(struct channel *C, struct rte *new)
{
+ /* Reject everything on shutdown */
+ if (SHUTTING_DOWN)
+ return -1;
+
SKIP_BACK_DECLARE(struct aggregator_proto, p, p, C->proto);
/* Reject our own routes */
if (new->sender == p->dst->in_req.hook)
static int
babel_preexport(struct channel *C, struct rte *new)
{
+ if (SHUTTING_DOWN)
+ return -1;
+
if (new->src->owner != &C->proto->sources)
return 0;
struct babel_proto *p = (void *) P;
struct babel_entry *e;
+ /* Ignore everything on shutdown */
+ if (SHUTTING_DOWN)
+ return;
+
if (new)
{
/* Update */
struct bgp_proto *src = bgp_rte_proto(e);
struct bgp_channel *c = (struct bgp_channel *) C;
+ /* Reject everything on shutdown */
+ if (SHUTTING_DOWN)
+ return -1;
+
/* Ignore non-BGP channels */
if (C->class != &channel_bgp)
return -1;
struct bgp_bucket *buck;
struct rte_src *path;
+ /* Reject everything on shutdown */
+ if (SHUTTING_DOWN)
+ return;
+
/* Ignore non-BGP channels */
if (C->class != &channel_bgp)
return;
static void
l3vpn_rt_notify(struct proto *P, struct channel *c0, const net_addr *n0, rte *new, const rte *old UNUSED)
{
+ if (SHUTTING_DOWN)
+ return;
+
struct l3vpn_proto *p = (void *) P;
struct rte_src *src = NULL;
struct channel *dst = NULL;
static int
l3vpn_preexport(struct channel *C, rte *e)
{
+ /* Reject everything on shutdown */
+ if (SHUTTING_DOWN)
+ return -1;
+
struct l3vpn_proto *p = (void *) C->proto;
if (&C->in_req == e->sender->req)
static int
ospf_preexport(struct channel *C, rte *e)
{
+ /* Reject everything on shutdown */
+ if (SHUTTING_DOWN)
+ return -1;
+
struct ospf_proto *p = (struct ospf_proto *) C->proto;
struct ospf_area *oa = ospf_main_area(p);
struct ospf_area *oa = NULL; /* non-NULL for NSSA-LSA */
ort *nf;
+ /* Reject everything on shutdown */
+ if (SHUTTING_DOWN)
+ return;
+
/*
* There are several posibilities:
* 1) router in regular area - originate external LSA with global scope
struct pipe_proto *p = (void *) P;
struct channel *dst = (src_ch == p->pri) ? p->sec : p->pri;
+ /* Reject everything on shutdown */
+ if (SHUTTING_DOWN)
+ return;
+
if (!new && !old)
return;
{
struct pipe_proto *p = (void *) C->proto;
+ /* Reject everything on shutdown */
+ if (SHUTTING_DOWN)
+ return -1;
+
/* Avoid direct loopbacks */
if (e->sender == C->in_req.hook)
return -1;
rip_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *net, struct rte *new,
const struct rte *old UNUSED)
{
+ if (SHUTTING_DOWN)
+ return;
+
struct rip_proto *p = (struct rip_proto *) P;
struct rip_entry *en;
int old_metric;