]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Fix minor issue in pipe route propagation
authorOndrej Zajicek <santiago@crfreenet.org>
Sat, 16 May 2015 18:17:59 +0000 (20:17 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Sat, 16 May 2015 18:17:59 +0000 (20:17 +0200)
In some circumstances during reconfiguration, routes propagated by pipes
to other tables may hang there even after the primary routes are removed.

There is already a workaround for this issue in the code which removes
these stale routes by flush process when source protocols are shut down.

This patch is a cleaner fix and allows to simplify the flush process

nest/rt-table.c

index dbe0c50dfc4f484df588cf5d7942c96ccba9086d..a8fe137c2ba6450ca3335d4cf4c8b4a68941210c 100644 (file)
@@ -347,11 +347,13 @@ do_rt_notify(struct announce_hook *ah, net *net, rte *new, rte *old, ea_list *tm
 }
 
 static void
-rt_notify_basic(struct announce_hook *ah, net *net, rte *new, rte *old, ea_list *tmpa, int refeed)
+rt_notify_basic(struct announce_hook *ah, net *net, rte *new0, rte *old0, ea_list *tmpa, int refeed)
 {
-  // struct proto *p = ah->proto;
+  struct proto *p = ah->proto;
   struct proto_stats *stats = ah->stats;
 
+  rte *new = new0;
+  rte *old = old0;
   rte *new_free = NULL;
   rte *old_free = NULL;
 
@@ -369,7 +371,7 @@ rt_notify_basic(struct announce_hook *ah, net *net, rte *new, rte *old, ea_list
    * 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 
+   * even try to run the filter on an old route, This may lead to
    * 'spurious withdraws' but ensure that there are no 'missing
    * withdraws'.
    *
@@ -386,9 +388,26 @@ rt_notify_basic(struct announce_hook *ah, net *net, rte *new, rte *old, ea_list
   if (old && !refeed)
     old = export_filter(ah, old, &old_free, NULL, 1);
 
-  /* FIXME - This is broken because of incorrect 'old' value (see above) */
   if (!new && !old)
+  {
+    /*
+     * As mentioned above, 'old' value may be incorrect in some race conditions.
+     * We generally ignore it with the exception of withdraw to pipe protocol.
+     * In that case we rather propagate unfiltered withdraws regardless of
+     * export filters to ensure that when a protocol is flushed, its routes are
+     * removed from all tables. Possible spurious unfiltered withdraws are not
+     * problem here as they are ignored if there is no corresponding route at
+     * the other end of the pipe. We directly call rt_notify() hook instead of
+     * do_rt_notify() to avoid logging and stat counters.
+     */
+
+#ifdef CONFIG_PIPE
+    if ((p->proto == &proto_pipe) && !new0 && (p != old0->sender->proto))
+      p->rt_notify(p, ah->table, net, NULL, old0, NULL);
+#endif
+
     return;
+  }
 
   do_rt_notify(ah, net, new, old, tmpa, refeed);