Commit 86f567e1 authored by Ondrej Zajicek's avatar Ondrej Zajicek
Browse files

Fix minor issue in pipe route propagation

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
parent 38e835de
Loading
Loading
Loading
Loading
+23 −4
Original line number Diff line number Diff line
@@ -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;

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