diff --git a/crates/fib/src/kernel.rs b/crates/fib/src/kernel.rs index 614eb46..3275e4d 100644 --- a/crates/fib/src/kernel.rs +++ b/crates/fib/src/kernel.rs @@ -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 { 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!(