summaryrefslogtreecommitdiff
path: root/nest/rt-table.c
diff options
context:
space:
mode:
Diffstat (limited to 'nest/rt-table.c')
-rw-r--r--nest/rt-table.c27
1 files changed, 23 insertions, 4 deletions
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);