switch (c->channel_state)
{
case CS_STOP:
- if (!EMPTY_LIST(c->roa_subscriptions) || c->out_req.hook || c->refeed_req.hook || c->in_req.hook || c->reload_req.hook)
+ if (c->obstacles || !EMPTY_LIST(c->roa_subscriptions) || c->out_req.hook || c->refeed_req.hook || c->in_req.hook || c->reload_req.hook)
return;
channel_set_state(c, CS_DOWN);
break;
case CS_PAUSE:
- if (!EMPTY_LIST(c->roa_subscriptions) || c->out_req.hook || c->refeed_req.hook || c->reload_req.hook)
+ if (c->obstacles || !EMPTY_LIST(c->roa_subscriptions) || c->out_req.hook || c->refeed_req.hook || c->reload_req.hook)
return;
channel_set_state(c, CS_START);
DBG("%s.%s: Channel requests/hooks stopped (in state %s)\n", c->proto->name, c->name, c_states[c->channel_state]);
}
+void
+channel_add_obstacle(struct channel *c)
+{
+ c->obstacles++;
+}
+
+void
+channel_del_obstacle(struct channel *c)
+{
+ if (!--c->obstacles)
+ channel_check_stopped(c);
+}
+
void
channel_import_stopped(struct rt_import_request *req)
{
u8 gr_lock; /* Graceful restart mechanism should wait for this channel */
u8 gr_wait; /* Route export to channel is postponed until graceful restart */
+ u32 obstacles; /* External obstacles remaining before cleanup */
+
btime last_state_change; /* Time of last state transition */
struct rt_export_request reload_req; /* Feeder for import reload */
void channel_schedule_reload(struct channel *c, struct channel_import_request *cir);
int channel_import_request_prefilter(struct channel_import_request *cir_head, const net_addr *n);
+void channel_add_obstacle(struct channel *c);
+void channel_del_obstacle(struct channel *c);
+
static inline void channel_init(struct channel *c) { channel_set_state(c, CS_START); }
static inline void channel_open(struct channel *c) { channel_set_state(c, CS_UP); }
static inline void channel_close(struct channel *c) { channel_set_state(c, CS_STOP); }