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:
Ondrej Zajicek 2009-12-02 22:19:47 +01:00
parent 11787b8473
commit 11361a1015
3 changed files with 25 additions and 11 deletions

View file

@ -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);

View file

@ -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 */

View file

@ -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();
} }