]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Implements route re-feed.
authorOndrej Zajicek <santiago@crfreenet.org>
Wed, 2 Dec 2009 21:19:47 +0000 (22:19 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Wed, 2 Dec 2009 21:19:47 +0000 (22:19 +0100)
This can be used to re-feed routes to protocol after soft change in
export filters.

nest/proto.c
nest/protocol.h
nest/rt-table.c

index c531d869c6b5e3b059029e0f28c4a6a13aa8128b..bdac4bf65223c34c233558e0fc6e8048411abbe7 100644 (file)
@@ -585,6 +585,7 @@ proto_schedule_feed(struct proto *p, int initial)
 {
   DBG("%s: Scheduling meal\n", p->name);
   p->core_state = FS_FEEDING;
+  p->refeeding = !initial;
   proto_relink(p);
   p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
   ev_schedule(p->attn);
index 66e6c43db3389acce943f9a053dd8e599a891d83..e1adc525c97e42cefca08525186a8705b899ab42 100644 (file)
@@ -134,6 +134,7 @@ struct proto {
   unsigned core_state;                 /* Core state machine (see below) */
   unsigned core_goal;                  /* State we want to reach (see below) */
   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 */
   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 */
index a8d0fee5e528a11d799db5a8e826110c2c609615..8efc0a618dd0ccd6b973849c132c4f412ec564eb 100644 (file)
@@ -158,7 +158,7 @@ rte_trace_out(unsigned int flag, struct proto *p, rte *e, char *msg)
 }
 
 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;
   rte *new0 = new;
@@ -199,15 +199,27 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
   else
     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.
-     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 */
-
-  if (old)
+  /*
+   * This is a tricky part - we don't know whether route 'old' was
+   * exported to protocol 'p' or was filtered by the export filter.
+   * 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).
+   */
+
+  if (old && !refeed)
     {
       if (p->out_filter == FILTER_REJECT)
        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);
       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();
   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();
 }