diff --git a/nest/rt-table.c b/nest/rt-table.c index dbe0c50d..a8fe137c 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -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);