Implements route re-feed.
This can be used to re-feed routes to protocol after soft change in export filters.
This commit is contained in:
parent
11787b8473
commit
11361a1015
3 changed files with 25 additions and 11 deletions
|
@ -585,6 +585,7 @@ proto_schedule_feed(struct proto *p, int initial)
|
||||||
{
|
{
|
||||||
DBG("%s: Scheduling meal\n", p->name);
|
DBG("%s: Scheduling meal\n", p->name);
|
||||||
p->core_state = FS_FEEDING;
|
p->core_state = FS_FEEDING;
|
||||||
|
p->refeeding = !initial;
|
||||||
proto_relink(p);
|
proto_relink(p);
|
||||||
p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
|
p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
|
||||||
ev_schedule(p->attn);
|
ev_schedule(p->attn);
|
||||||
|
|
|
@ -134,6 +134,7 @@ struct proto {
|
||||||
unsigned core_state; /* Core state machine (see below) */
|
unsigned core_state; /* Core state machine (see below) */
|
||||||
unsigned core_goal; /* State we want to reach (see below) */
|
unsigned core_goal; /* State we want to reach (see below) */
|
||||||
unsigned reconfiguring; /* We're shutting down due to reconfiguration */
|
unsigned reconfiguring; /* We're shutting down due to reconfiguration */
|
||||||
|
unsigned refeeding; /* We are refeeding (valid only if core_state == FS_FEEDING) */
|
||||||
u32 hash_key; /* Random key used for hashing of neighbors */
|
u32 hash_key; /* Random key used for hashing of neighbors */
|
||||||
bird_clock_t last_state_change; /* Time of last state transition */
|
bird_clock_t last_state_change; /* Time of last state transition */
|
||||||
char *last_state_name_announced; /* Last state name we've announced to the user */
|
char *last_state_name_announced; /* Last state name we've announced to the user */
|
||||||
|
|
|
@ -158,7 +158,7 @@ rte_trace_out(unsigned int flag, struct proto *p, rte *e, char *msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old, ea_list *tmpa, int class)
|
do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old, ea_list *tmpa, int class, int refeed)
|
||||||
{
|
{
|
||||||
struct proto *p = a->proto;
|
struct proto *p = a->proto;
|
||||||
rte *new0 = new;
|
rte *new0 = new;
|
||||||
|
@ -199,15 +199,27 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
|
||||||
else
|
else
|
||||||
p->stats.exp_withdraws_received++;
|
p->stats.exp_withdraws_received++;
|
||||||
|
|
||||||
/* This is a tricky part - we don't know whether route 'old' was
|
/*
|
||||||
exported to protocol 'p' or was filtered by the export filter.
|
* This is a tricky part - we don't know whether route 'old' was
|
||||||
We try tu run the export filter to know this to have a correct
|
* exported to protocol 'p' or was filtered by the export filter.
|
||||||
value in 'old' argument of rt_update (and proper filter value)
|
* We try tu run the export filter to know this to have a correct
|
||||||
|
* value in 'old' argument of rt_update (and proper filter value)
|
||||||
|
*
|
||||||
|
* FIXME - this is broken because 'configure soft' may change
|
||||||
|
* filters but keep routes. Refeed is expected to be called after
|
||||||
|
* change of the filters and with old == new, therefore we do not
|
||||||
|
* even try to run the filter on an old route, This may lead to
|
||||||
|
* 'spurious withdraws' but ensure that there are no 'missing
|
||||||
|
* withdraws'.
|
||||||
|
*
|
||||||
|
* This is not completely safe as there is a window between
|
||||||
|
* reconfiguration and the end of refeed - if a newly filtered
|
||||||
|
* route disappears during this period, proper withdraw is not
|
||||||
|
* sent (because old would be also filtered) and the route is
|
||||||
|
* not refeeded (because it disappeared before that).
|
||||||
|
*/
|
||||||
|
|
||||||
FIXME - this is broken because 'configure soft' may change
|
if (old && !refeed)
|
||||||
filters but keep routes */
|
|
||||||
|
|
||||||
if (old)
|
|
||||||
{
|
{
|
||||||
if (p->out_filter == FILTER_REJECT)
|
if (p->out_filter == FILTER_REJECT)
|
||||||
old = NULL;
|
old = NULL;
|
||||||
|
@ -313,7 +325,7 @@ rte_announce(rtable *tab, int type, net *net, rte *new, rte *old, ea_list *tmpa)
|
||||||
{
|
{
|
||||||
ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
|
ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
|
||||||
if (a->proto->accept_ra_types == type)
|
if (a->proto->accept_ra_types == type)
|
||||||
do_rte_announce(a, type, net, new, old, tmpa, class);
|
do_rte_announce(a, type, net, new, old, tmpa, class, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -973,7 +985,7 @@ do_feed_baby(struct proto *p, int type, struct announce_hook *h, net *n, rte *e)
|
||||||
|
|
||||||
rte_update_lock();
|
rte_update_lock();
|
||||||
tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL;
|
tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL;
|
||||||
do_rte_announce(h, type, n, e, NULL, tmpa, ipa_classify(n->n.prefix));
|
do_rte_announce(h, type, n, e, p->refeeding ? e : NULL, tmpa, ipa_classify(n->n.prefix), p->refeeding);
|
||||||
rte_update_unlock();
|
rte_update_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue