mirror of
https://gitlab.labs.nic.cz/labs/bird.git
synced 2024-05-11 16:54:54 +00:00
Fixes responsiveness for protocol shutdown.
When a protocol went down, all its routes were flushed in one step, that may block BIRD for too much time. The patch fixes that by limiting maximum number of routes flushed in one step.
This commit is contained in:
118
nest/proto.c
118
nest/proto.c
@@ -38,7 +38,7 @@ static event *proto_flush_event;
|
||||
static char *p_states[] = { "DOWN", "START", "UP", "STOP" };
|
||||
static char *c_states[] = { "HUNGRY", "FEEDING", "HAPPY", "FLUSHING" };
|
||||
|
||||
static void proto_flush_all(void *);
|
||||
static void proto_flush_loop(void *);
|
||||
static void proto_rethink_goal(struct proto *p);
|
||||
static char *proto_state_name(struct proto *p);
|
||||
|
||||
@@ -635,7 +635,7 @@ protos_build(void)
|
||||
#endif
|
||||
proto_pool = rp_new(&root_pool, "Protocols");
|
||||
proto_flush_event = ev_new(proto_pool);
|
||||
proto_flush_event->hook = proto_flush_all;
|
||||
proto_flush_event->hook = proto_flush_loop;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -691,20 +691,6 @@ proto_feed_initial(void *P)
|
||||
proto_feed_more(P);
|
||||
}
|
||||
|
||||
static void
|
||||
proto_schedule_flush(struct proto *p)
|
||||
{
|
||||
/* Need to abort feeding */
|
||||
if (p->core_state == FS_FEEDING)
|
||||
rt_feed_baby_abort(p);
|
||||
|
||||
DBG("%s: Scheduling flush\n", p->name);
|
||||
p->core_state = FS_FLUSHING;
|
||||
proto_relink(p);
|
||||
proto_flush_hooks(p);
|
||||
ev_schedule(proto_flush_event);
|
||||
}
|
||||
|
||||
static void
|
||||
proto_schedule_feed(struct proto *p, int initial)
|
||||
{
|
||||
@@ -721,6 +707,85 @@ proto_schedule_feed(struct proto *p, int initial)
|
||||
ev_schedule(p->attn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flushing loop is responsible for flushing routes and protocols
|
||||
* after they went down. It runs in proto_flush_event. At the start of
|
||||
* one round, protocols waiting to flush are marked in
|
||||
* proto_schedule_flush_loop(). At the end of the round (when routing
|
||||
* table flush is complete), marked protocols are flushed and a next
|
||||
* round may start.
|
||||
*/
|
||||
|
||||
static int flush_loop_state; /* 1 -> running */
|
||||
|
||||
static void
|
||||
proto_schedule_flush_loop(void)
|
||||
{
|
||||
struct proto *p;
|
||||
|
||||
if (flush_loop_state)
|
||||
return;
|
||||
flush_loop_state = 1;
|
||||
|
||||
rt_schedule_prune_all();
|
||||
WALK_LIST(p, flush_proto_list)
|
||||
p->flushing = 1;
|
||||
|
||||
ev_schedule(proto_flush_event);
|
||||
}
|
||||
|
||||
static void
|
||||
proto_flush_loop(void *unused UNUSED)
|
||||
{
|
||||
struct proto *p;
|
||||
|
||||
if (! rt_prune_loop())
|
||||
{
|
||||
/* Rtable pruning is not finished */
|
||||
ev_schedule(proto_flush_event);
|
||||
return;
|
||||
}
|
||||
|
||||
again:
|
||||
WALK_LIST(p, flush_proto_list)
|
||||
if (p->flushing)
|
||||
{
|
||||
/* This will flush interfaces in the same manner
|
||||
like rt_prune_all() flushes routes */
|
||||
if (p->proto == &proto_unix_iface)
|
||||
if_flush_ifaces(p);
|
||||
|
||||
DBG("Flushing protocol %s\n", p->name);
|
||||
p->flushing = 0;
|
||||
p->core_state = FS_HUNGRY;
|
||||
proto_relink(p);
|
||||
if (p->proto_state == PS_DOWN)
|
||||
proto_fell_down(p);
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* This round finished, perhaps there will be another one */
|
||||
flush_loop_state = 0;
|
||||
if (!EMPTY_LIST(flush_proto_list))
|
||||
proto_schedule_flush_loop();
|
||||
}
|
||||
|
||||
static void
|
||||
proto_schedule_flush(struct proto *p)
|
||||
{
|
||||
/* Need to abort feeding */
|
||||
if (p->core_state == FS_FEEDING)
|
||||
rt_feed_baby_abort(p);
|
||||
|
||||
DBG("%s: Scheduling flush\n", p->name);
|
||||
p->core_state = FS_FLUSHING;
|
||||
proto_relink(p);
|
||||
proto_flush_hooks(p);
|
||||
proto_schedule_flush_loop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* proto_request_feeding - request feeding routes to the protocol
|
||||
* @p: given protocol
|
||||
@@ -810,27 +875,6 @@ proto_notify_state(struct proto *p, unsigned ps)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
proto_flush_all(void *unused UNUSED)
|
||||
{
|
||||
struct proto *p;
|
||||
|
||||
rt_prune_all();
|
||||
while ((p = HEAD(flush_proto_list))->n.next)
|
||||
{
|
||||
/* This will flush interfaces in the same manner
|
||||
like rt_prune_all() flushes routes */
|
||||
if (p->proto == &proto_unix_iface)
|
||||
if_flush_ifaces(p);
|
||||
|
||||
DBG("Flushing protocol %s\n", p->name);
|
||||
p->core_state = FS_HUNGRY;
|
||||
proto_relink(p);
|
||||
if (p->proto_state == PS_DOWN)
|
||||
proto_fell_down(p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CLI Commands
|
||||
*/
|
||||
|
Reference in New Issue
Block a user