]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Bugfix
authorIgor Putovny <igor.putovny@nic.cz>
Fri, 28 Feb 2025 17:12:47 +0000 (18:12 +0100)
committerIgor Putovny <igor.putovny@nic.cz>
Mon, 3 Mar 2025 15:23:28 +0000 (16:23 +0100)
This was another bug tricky to find.
It manifested in a following way. After running aggregator with configuration A,
reconfiguring it to B (this works now as it was fixed in the previous commit)
and reconfiguring back to A, no routes from A were exported to the routing
table, despite prefixes being present in the trie.

It was found that aggregator_bucket_update() is correctly called, however, it
returned on the first "if", meaning that bucket was empty. It was found that
there were two different buckets with the same ID. The culprit turned out to
be freeing bucket ID when the bucket becomes empty in rt_notify() due to
reconfiguration. When that happens, freed ID will be used again for new bucket
created during reconfiguration.
However, the bucket pointer in the bucket list was never updated and pointer to
old bucket was still kept there at position [ID]. When the aggregator decided
for creating new route after reconfiguring back to A, it found bucket pointer
by its ID. However, this pointer was actually pointer to an empty bucket.
This triggered early return from aggregator_bucket_update(), which means that
control flow never reached the point where new route could be exported.
Either way, the empty bucket means that rte_update2() would be called with
wrong arguments and route export would still be unsuccessful.

proto/aggregator/aggregator.c

index da61bf183aaef450e8636231d396d1f09692461e..b0e8980b71b99d83bbcc1469020bfa5aec43cf38 100644 (file)
@@ -724,7 +724,6 @@ aggregator_rt_notify(struct proto *P, struct channel *src_ch, net *net, rte *new
   if (old_bucket && (!old_bucket->rte || !old_bucket->count))
   {
     ASSERT_DIE(!old_bucket->rte && !old_bucket->count);
-    hmap_clear(&p->bucket_id_map, old_bucket->id);
     HASH_REMOVE2(p->buckets, AGGR_BUCK, p->p.pool, old_bucket);
   }
 }