Kernel: read what the table has before letting kept routes go

Once every peer had sent all its routes, the kernel task let go of the
routes kept from the earlier run that the table did not have, at once.
But "the table has" and "the kernel task has read" are not the same
moment: a route a peer sent just before its End-of-RIB could still be
unread in the table's journal, in which case it was taken out of the
kernel and put back a moment later. The interop lab saw this now and
then as "N routes were taken out of the kernel over the restart".

The task now reads the table to the end before it decides what is
unconfirmed; follow() says whether the reader is caught up.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Rayhaan JaufeerallyandClaude Fable 5.1 committed 2026-10-06 11:21:53 +02:00
1 parent 175a13d506
commit 724bb99f11
1 file changed
+11 -4
+11 -4
View File
@@ -746,11 +746,12 @@ impl Task {
}
/// Takes the next changes of best route from the routing table and
/// hands over what brings the kernel in step with them.
async fn follow(&mut self, reader: &mut Reader) -> Result<(), FibError> {
/// hands over what brings the kernel in step with them. Returns whether
/// the reader has read everything the table has for it.
async fn follow(&mut self, reader: &mut Reader) -> Result<bool, FibError> {
let mut news = Vec::with_capacity(BATCH);
// Only what is needed is taken while the table is held.
reader.poll(BATCH, |event| {
let progress = reader.poll(BATCH, |event| {
news.push(match event {
Event::Reset => News::Reset,
Event::Synced => News::Synced,
@@ -822,7 +823,8 @@ impl Task {
News::Withdrawn(prefix) => ops.extend(self.plan.withdrawn(prefix)),
}
}
self.send(ops, whole_table).await
self.send(ops, whole_table).await?;
Ok(progress.caught_up)
}
/// Takes in what the writer says became of what it was given.
@@ -1130,6 +1132,11 @@ pub(crate) async fn run(
}
}, if release_at.is_some() => {
release_at = None;
// What the table has by now, the kernel is to have before
// anything is let go of: a route a peer sent just before
// its End-of-RIB may not have been read yet, and would be
// taken out only to be put back.
while !task.follow(&mut reader).await? {}
task.keeping = false;
let stale = task.plan.release();
info!(