mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-03 21:21:32 +00:00
network: inter-container networking support
This commit is contained in:
@ -1,14 +1,13 @@
|
||||
use advmac::MacAddr6;
|
||||
use anyhow::Result;
|
||||
use futures::TryStreamExt;
|
||||
use log::{error, info, warn};
|
||||
use netlink_packet_route::link::LinkAttribute;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use autonet::{AutoNetworkChangeset, AutoNetworkCollector, NetworkMetadata};
|
||||
use tokio::time::sleep;
|
||||
use vbridge::VirtualBridge;
|
||||
|
||||
use crate::backend::NetworkBackend;
|
||||
|
||||
pub mod autonet;
|
||||
pub mod backend;
|
||||
pub mod chandev;
|
||||
pub mod icmp;
|
||||
@ -16,99 +15,45 @@ pub mod nat;
|
||||
pub mod pkt;
|
||||
pub mod proxynat;
|
||||
pub mod raw_socket;
|
||||
pub mod vbridge;
|
||||
|
||||
pub struct NetworkService {
|
||||
pub ipv4: String,
|
||||
pub ipv6: String,
|
||||
pub force_mac_address: Option<MacAddr6>,
|
||||
pub bridge: VirtualBridge,
|
||||
}
|
||||
|
||||
impl NetworkService {
|
||||
pub fn new(
|
||||
ipv4: String,
|
||||
ipv6: String,
|
||||
force_mac_address: Option<MacAddr6>,
|
||||
) -> Result<NetworkService> {
|
||||
pub fn new() -> Result<NetworkService> {
|
||||
Ok(NetworkService {
|
||||
ipv4,
|
||||
ipv6,
|
||||
force_mac_address,
|
||||
bridge: VirtualBridge::new()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkService {
|
||||
pub async fn watch(&mut self) -> Result<()> {
|
||||
let spawned: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(Vec::new()));
|
||||
let (connection, handle, _) = rtnetlink::new_connection()?;
|
||||
tokio::spawn(connection);
|
||||
let mut collector = AutoNetworkCollector::new()?;
|
||||
loop {
|
||||
let mut stream = handle.link().get().execute();
|
||||
while let Some(message) = stream.try_next().await? {
|
||||
let mut name: Option<String> = None;
|
||||
for attribute in &message.attributes {
|
||||
if let LinkAttribute::IfName(if_name) = attribute {
|
||||
name = Some(if_name.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if name.is_none() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = name.unwrap();
|
||||
if !name.starts_with("vif") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Ok(spawns) = spawned.lock() {
|
||||
if spawns.contains(&name) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(error) = self.add_network_backend(&name, spawned.clone()).await {
|
||||
warn!(
|
||||
"failed to initialize network backend for interface {}: {}",
|
||||
name, error
|
||||
);
|
||||
}
|
||||
|
||||
if let Ok(mut spawns) = spawned.lock() {
|
||||
spawns.push(name.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let changeset = collector.read_changes()?;
|
||||
self.process_network_changeset(changeset)?;
|
||||
sleep(Duration::from_secs(2)).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn add_network_backend(
|
||||
&mut self,
|
||||
interface: &str,
|
||||
spawned: Arc<Mutex<Vec<String>>>,
|
||||
) -> Result<()> {
|
||||
let interface = interface.to_string();
|
||||
let mut network =
|
||||
NetworkBackend::new(&self.ipv4, &self.ipv6, &self.force_mac_address, &interface)?;
|
||||
info!("initializing network backend for interface {}", interface);
|
||||
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
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn add_network_backend(&mut self, metadata: NetworkMetadata) -> Result<()> {
|
||||
let mut network = NetworkBackend::new(metadata, self.bridge.clone())?;
|
||||
network.init().await?;
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
info!("spawning network backend for interface {}", interface);
|
||||
tokio::spawn(async move {
|
||||
if let Err(error) = network.run().await {
|
||||
error!(
|
||||
"network backend for interface {} has been stopped: {}",
|
||||
interface, error
|
||||
);
|
||||
}
|
||||
|
||||
if let Ok(mut spawns) = spawned.lock() {
|
||||
if let Some(position) = spawns.iter().position(|x| *x == interface) {
|
||||
spawns.remove(position);
|
||||
}
|
||||
}
|
||||
});
|
||||
network.launch().await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user