add support for setting up routing inside the netns

This commit is contained in:
Robin Appelman 2026-02-23 22:59:31 +01:00
commit 7588b5db00
18 changed files with 272 additions and 53 deletions

View file

@ -1,4 +1,6 @@
use crate::config::{Config, DeviceName, ForwardConfig, NamespaceConfig, NamespaceName};
use crate::config::{
Config, DeviceName, ForwardConfig, NamespaceConfig, NamespaceName, RouteConfig,
};
use crate::link::{LinkError, LinkManager};
use crate::namespace::{
NamespaceEnterError, NamespaceError, NamespaceHandle, NamespaceHandleError, NetNs,
@ -128,6 +130,7 @@ impl State {
let config = config.get_namespace(namespace.name()).unwrap();
namespace.update_proxies(config)?;
namespace.update_devices(config)?;
namespace.update_links(config)?;
}
Ok(())
@ -144,6 +147,7 @@ struct ActiveNamespace {
ns: NetNs,
proxies: Vec<ActiveProxy>,
devices: Vec<DeviceName>,
routes: Vec<RouteConfig>,
}
impl ActiveNamespace {
@ -154,6 +158,7 @@ impl ActiveNamespace {
ns,
proxies: Vec::default(),
devices: Vec::default(),
routes: Vec::default(),
})
}
@ -212,6 +217,52 @@ impl ActiveNamespace {
Ok(())
}
pub fn update_links(&mut self, config: &NamespaceConfig) -> Result<(), DaemonError> {
let removed: Vec<_> = self
.routes
.extract_if(.., |existing| {
!config.routes.iter().any(|new| existing == new)
})
.collect();
let mut added = Vec::new();
for new in &config.routes {
if !self.has_route(new) {
added.push(new.clone());
}
}
self.ns.handle().run_in(|| {
let link_manager = LinkManager::new()?;
for link in link_manager.get_links()?.flatten() {
if let Some(route) = removed
.iter()
.find(|route| route.device == link.name.as_str())
{
info!(namespace = %config.name, %route, "deleting route");
link_manager.delete_route(&link, route.destination)?;
}
}
for link in link_manager.get_links()?.flatten() {
if let Some(route) = added
.iter()
.find(|route| route.device == link.name.as_str())
{
info!(namespace = %config.name, %route, "adding route");
link_manager.add_route(&link, route.destination)?;
}
}
Ok::<_, DaemonError>(())
})??;
for new in added {
self.routes.push(new);
}
Ok(())
}
fn has_forward(&self, config: &ForwardConfig) -> bool {
self.proxies.iter().any(|existing| existing == config)
}
@ -220,6 +271,10 @@ impl ActiveNamespace {
self.devices.iter().any(|existing| existing == name)
}
fn has_route(&self, route: &RouteConfig) -> bool {
self.routes.iter().any(|existing| existing == route)
}
pub fn name(&self) -> &NamespaceName {
self.ns.name()
}