From: Maria Matejka Date: Mon, 10 Mar 2025 19:20:32 +0000 (+0100) Subject: Table export: ignoring invalid routes before marking them in export maps X-Git-Tag: v3.1.1~23^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=40cb435971c12f4553f981c760c42ffcf38f5006;p=thirdparty%2Fbird.git Table export: ignoring invalid routes before marking them in export maps Fast subsequent updates on filtered routes made the code crash because no flags were set while ignoring them. And if these routes flapped, the squashed export update crashed on a consistency check. We ignore them unconditionally so we don't have to mark them at all and we can convert them to NULL even before export maps are touched. --- diff --git a/nest/rt-table.c b/nest/rt-table.c index b604596a9..5b438aa7f 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -1165,24 +1165,6 @@ rt_notify_basic(struct channel *c, const rte *new, const rte *old) { const rte *trte = new ?: old; - /* Have we exported the old route? */ - if (old && !bmap_test(&c->export_accepted_map, old->id)) - old = NULL; - - /* Ignore invalid routes */ - if (!rte_is_valid(new)) - new = NULL; - - if (!rte_is_valid(old)) - old = NULL; - - if (!new && !old) - { - channel_rte_trace_out(D_ROUTES, c, trte, "idempotent withdraw (filtered on import)"); - c->export_stats.withdraws_ignored++; - return; - } - /* Have we exported the old route? */ if (old) { @@ -1598,6 +1580,18 @@ channel_notify_basic(void *_channel) rt_export_processed(&c->out_req, rpe->it.seq); } + /* Have we exported the old route? */ + if (old && !bmap_test(&c->export_accepted_map, old->id)) + old = NULL; + + /* Ignore invalid routes */ + if (!rte_is_valid(new)) + new = NULL; + + if (!rte_is_valid(old)) + old = NULL; + + /* Update status map flags for id-only updates */ if (new && old && rte_same(new, old)) { channel_rte_trace_out(D_ROUTES, c, new, "already exported"); @@ -1620,7 +1614,7 @@ channel_notify_basic(void *_channel) } else if (!new && !old) { - channel_rte_trace_out(D_ROUTES, c, u->update->new, "idempotent withdraw (squash)"); + channel_rte_trace_out(D_ROUTES, c, u->update->new, "idempotent withdraw"); c->export_stats.withdraws_ignored++; } else