From de0b2c35b1cf891241501b77ac7f7d14a0cdabfa Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Tue, 13 Feb 2024 10:03:28 +0000 Subject: [PATCH] network: auto-retry backend startup --- network/src/autonet.rs | 4 ++++ network/src/backend.rs | 17 ++++++++-------- network/src/lib.rs | 44 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/network/src/autonet.rs b/network/src/autonet.rs index ef0bf83..3250f95 100644 --- a/network/src/autonet.rs +++ b/network/src/autonet.rs @@ -178,4 +178,8 @@ impl AutoNetworkCollector { Ok(AutoNetworkChangeset { added, removed }) } + + pub fn mark_unknown(&mut self, uuid: Uuid) -> Result { + Ok(self.known.remove(&uuid).is_some()) + } } diff --git a/network/src/backend.rs b/network/src/backend.rs index a10fb89..5021487 100644 --- a/network/src/backend.rs +++ b/network/src/backend.rs @@ -60,15 +60,16 @@ impl NetworkStack<'_> { trace!("failed to send guest packet to bridge: {}", error); } - let slice = SlicedPacket::from_ethernet(packet)?; - let packet = RecvPacket::new(packet, &slice)?; - if let Err(error) = self.router.process(&packet).await { - debug!("router failed to process packet: {}", error); - } + if let Ok(slice) = SlicedPacket::from_ethernet(packet) { + let packet = RecvPacket::new(packet, &slice)?; + if let Err(error) = self.router.process(&packet).await { + debug!("router failed to process packet: {}", error); + } - self.udev.rx = Some(packet.raw.into()); - self.interface - .poll(Instant::now(), &mut self.udev, &mut self.sockets); + self.udev.rx = Some(packet.raw.into()); + self.interface + .poll(Instant::now(), &mut self.udev, &mut self.sockets); + } } NetworkStackSelect::Send(Some(packet)) => self.kdev.write_all(&packet).await?, diff --git a/network/src/lib.rs b/network/src/lib.rs index e9eea23..032d02a 100644 --- a/network/src/lib.rs +++ b/network/src/lib.rs @@ -2,7 +2,10 @@ use std::time::Duration; use anyhow::Result; use autonet::{AutoNetworkChangeset, AutoNetworkCollector, NetworkMetadata}; +use futures::{future::join_all, TryFutureExt}; +use log::warn; use tokio::time::sleep; +use uuid::Uuid; use vbridge::VirtualBridge; use crate::backend::NetworkBackend; @@ -34,25 +37,50 @@ impl NetworkService { let mut collector = AutoNetworkCollector::new()?; loop { let changeset = collector.read_changes()?; - self.process_network_changeset(changeset)?; + self.process_network_changeset(&mut collector, changeset)?; sleep(Duration::from_secs(2)).await; } } - fn process_network_changeset(&mut self, changeset: AutoNetworkChangeset) -> Result<()> { - for metadata in &changeset.added { - futures::executor::block_on(async { - self.add_network_backend(metadata.clone()).await - })?; + fn process_network_changeset( + &mut self, + collector: &mut AutoNetworkCollector, + changeset: AutoNetworkChangeset, + ) -> Result<()> { + let futures = changeset + .added + .iter() + .map(|metadata| { + self.add_network_backend(metadata.clone()) + .map_err(|x| (metadata.clone(), x)) + }) + .collect::>(); + + let failed = futures::executor::block_on(async move { + let mut failed: Vec = Vec::new(); + let results = join_all(futures).await; + for result in results { + if let Err((metadata, error)) = result { + warn!( + "failed to launch network backend for hypha guest {}: {}", + metadata.uuid, error + ); + failed.push(metadata.uuid); + } + } + failed + }); + + for uuid in failed { + collector.mark_unknown(uuid)?; } Ok(()) } - async fn add_network_backend(&mut self, metadata: NetworkMetadata) -> Result<()> { + async fn add_network_backend(&self, metadata: NetworkMetadata) -> Result<()> { let mut network = NetworkBackend::new(metadata, self.bridge.clone())?; network.init().await?; - tokio::time::sleep(Duration::from_secs(1)).await; network.launch().await?; Ok(()) }