ev_send(proto_event_list(c->proto), &c->reimport_event);
}
+static inline bool channel_reload(struct channel *c, struct rt_feeding_request *rfr)
+{
+ if ((c->in_keep & RIK_PREFILTER) == RIK_PREFILTER)
+ {
+ channel_reimport(c, rfr);
+ return true;
+ }
+ else
+ return c->proto->reload_routes(c, rfr);
+}
+
+static inline void channel_reload_roa(struct channel *c, struct rt_feeding_request *rfr)
+{
+ ASSERT_DIE(channel_reload(c, rfr));
+}
+
static inline void channel_refeed(struct channel *c, struct rt_feeding_request *rfr)
{
CALL(c->proto->refeed_begin, c, rfr);
static inline int channel_is_active(struct channel *c)
{ return (c->channel_state != CS_DOWN); }
-static inline int channel_reloadable(struct channel *c)
+static inline enum channel_reloadable channel_reloadable(struct channel *c)
{
- return c->reloadable && c->proto->reload_routes
- || ((c->in_keep & RIK_PREFILTER) == RIK_PREFILTER);
+ /* Import table always reloads locally */
+ if ((c->in_keep & RIK_PREFILTER) == RIK_PREFILTER)
+ return CHANNEL_RELOADABLE_LOCALLY;
+
+ /* The protocol should indicate how the reload actually works */
+ if (c->proto->reload_routes)
+ return c->reloadable;
+
+ /* No reload possible */
+ return CHANNEL_RELOADABLE_NEVER;
}
static inline void
c->channel_state = CS_DOWN;
c->last_state_change = current_time();
- c->reloadable = 1;
+ c->reloadable = CHANNEL_RELOADABLE_LOCALLY;
init_list(&c->roa_subscriptions);
static inline void (*channel_roa_reload_hook(int dir))(struct channel *, struct rt_feeding_request *)
{
- return dir ? channel_reimport : channel_refeed;
+ return dir ? channel_reload_roa : channel_refeed;
}
static int
return;
/* No automatic reload for non-reloadable channels */
- if (dir && !channel_reloadable(c))
+ if (dir && (channel_reloadable(c) != CHANNEL_RELOADABLE_LOCALLY))
valid = 0;
struct filter_iterator fit;
else
CD(c, "Full import reload requested");
- if ((c->in_keep & RIK_PREFILTER) == RIK_PREFILTER)
- channel_reimport(c, cir);
- else if (! c->proto->reload_routes(c, cir))
- cli_msg(-15, "%s.%s: partial reload refused, please run full reload instead", c->proto->name, c->name);
+ if (!channel_reload(c, cir))
+ if (cir && cir->prefilter.mode)
+ cli_msg(-15, "%s.%s: partial reload refused, please run full reload instead", c->proto->name, c->name);
+ else
+ bug("%s.%s: full reload refused");
}
const struct channel_class channel_basic = {
u8 stale; /* Used in reconfiguration */
u8 channel_state;
- u8 reloadable; /* Hook reload_routes() is allowed on the channel */
+ PACKED enum channel_reloadable {
+ CHANNEL_RELOADABLE_NEVER = 0, /* Never reload */
+ CHANNEL_RELOADABLE_REMOTELY = 1, /* Hook reload_routes() causes remote actions */
+ CHANNEL_RELOADABLE_LOCALLY = 2, /* Hook reload_routes() reloads routes locally */
+ } reloadable;
+
OBSREF(struct graceful_recovery_context) gr_lock; /* Graceful restart mechanism should wait for this channel */
u8 gr_wait; /* Route export to channel is postponed until graceful restart */