hypha: more work on IPv6 support

This commit is contained in:
Alex Zenla 2024-02-11 07:06:01 +00:00
parent 102cab32c3
commit 6773640a39
No known key found for this signature in database
GPG Key ID: 067B238899B51269
3 changed files with 97 additions and 46 deletions

View File

@ -9,7 +9,7 @@ use oci_spec::image::{Config, ImageConfiguration};
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::fs; use std::fs;
use std::fs::{File, OpenOptions, Permissions}; use std::fs::{File, OpenOptions, Permissions};
use std::net::Ipv4Addr; use std::net::{Ipv4Addr, Ipv6Addr};
use std::os::fd::AsRawFd; use std::os::fd::AsRawFd;
use std::os::linux::fs::MetadataExt; use std::os::linux::fs::MetadataExt;
use std::os::unix::fs::{chroot, PermissionsExt}; use std::os::unix::fs::{chroot, PermissionsExt};
@ -283,52 +283,83 @@ impl ContainerInit {
} }
async fn network_setup(&mut self, network: &LaunchNetwork) -> Result<()> { async fn network_setup(&mut self, network: &LaunchNetwork) -> Result<()> {
trace!( trace!("setting up network for link");
"setting up network for link {} with ipv4 address {} and gateway {}",
network.link,
network.ipv4.address,
network.ipv4.gateway,
);
let (connection, handle, _) = rtnetlink::new_connection()?;
tokio::spawn(connection);
let ipnet: IpNetwork = network.ipv4.address.parse()?;
let gateway: Ipv4Addr = network.ipv4.gateway.parse()?;
let mut links = handle
.link()
.get()
.match_name(network.link.clone())
.execute();
if let Some(link) = links.try_next().await? {
handle
.address()
.add(link.header.index, ipnet.ip(), ipnet.prefix())
.execute()
.await?;
handle.link().set(link.header.index).up().execute().await?;
handle
.route()
.add()
.v4()
.destination_prefix(Ipv4Addr::new(0, 0, 0, 0), 0)
.output_interface(link.header.index)
.gateway(gateway)
.execute()
.await?;
} else {
warn!("unable to find link named {}", network.link);
}
let etc = PathBuf::from_str("/etc")?; let etc = PathBuf::from_str("/etc")?;
if !etc.exists() { if !etc.exists() {
fs::create_dir(etc)?; fs::create_dir(etc)?;
} }
let resolv = PathBuf::from_str("/etc/resolv.conf")?; let resolv = PathBuf::from_str("/etc/resolv.conf")?;
fs::write(resolv, "nameserver 1.1.1.1\n")?; let mut lines = vec!["# hypha resolver configuration".to_string()];
for nameserver in &network.resolver.nameservers {
lines.push(format!("nameserver {}", nameserver));
}
let mut conf = lines.join("\n");
conf.push('\n');
fs::write(resolv, conf)?;
let (connection, handle, _) = rtnetlink::new_connection()?;
tokio::spawn(connection);
let ipv4_network: IpNetwork = network.ipv4.address.parse()?;
let ipv4_gateway: Ipv4Addr = network.ipv4.gateway.parse()?;
let ipv6_network: IpNetwork = network.ipv6.address.parse()?;
let ipv6_gateway: Ipv6Addr = network.ipv6.gateway.parse()?;
let mut links = handle
.link()
.get()
.match_name(network.link.clone())
.execute();
let Some(link) = links.try_next().await? else {
warn!("unable to find link named {}", network.link);
return Ok(());
};
handle
.address()
.add(link.header.index, ipv4_network.ip(), ipv4_network.prefix())
.execute()
.await?;
let ipv6_result = handle
.address()
.add(link.header.index, ipv6_network.ip(), ipv6_network.prefix())
.execute()
.await;
let ipv6_ready = match ipv6_result {
Ok(()) => true,
Err(error) => {
warn!("unable to setup ipv6 network: {}", error);
false
}
};
handle.link().set(link.header.index).up().execute().await?;
handle
.route()
.add()
.v4()
.destination_prefix(Ipv4Addr::UNSPECIFIED, 0)
.output_interface(link.header.index)
.gateway(ipv4_gateway)
.execute()
.await?;
if ipv6_ready {
handle
.route()
.add()
.v6()
.destination_prefix(Ipv6Addr::UNSPECIFIED, 0)
.output_interface(link.header.index)
.gateway(ipv6_gateway)
.execute()
.await?;
}
Ok(()) Ok(())
} }

View File

@ -7,7 +7,9 @@ use crate::image::name::ImageName;
use crate::image::{ImageCompiler, ImageInfo}; use crate::image::{ImageCompiler, ImageInfo};
use advmac::MacAddr6; use advmac::MacAddr6;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use hypha::{LaunchInfo, LaunchNetwork, LaunchNetworkIpv4}; use hypha::{
LaunchInfo, LaunchNetwork, LaunchNetworkIpv4, LaunchNetworkIpv6, LaunchNetworkResolver,
};
use ipnetwork::Ipv4Network; use ipnetwork::Ipv4Network;
use loopdev::LoopControl; use loopdev::LoopControl;
use std::io::{Read, Write}; use std::io::{Read, Write};
@ -81,7 +83,10 @@ impl Controller {
let name = format!("hypha-{uuid}"); let name = format!("hypha-{uuid}");
let image_info = self.compile(image)?; let image_info = self.compile(image)?;
let mut mac = MacAddr6::random();
mac.set_local(true);
let ipv4 = self.allocate_ipv4()?; let ipv4 = self.allocate_ipv4()?;
let ipv6 = mac.to_link_local_ipv6();
let launch_config = LaunchInfo { let launch_config = LaunchInfo {
network: Some(LaunchNetwork { network: Some(LaunchNetwork {
link: "eth0".to_string(), link: "eth0".to_string(),
@ -89,7 +94,18 @@ impl Controller {
address: format!("{}/24", ipv4), address: format!("{}/24", ipv4),
gateway: "192.168.42.1".to_string(), gateway: "192.168.42.1".to_string(),
}, },
ipv6: None, ipv6: LaunchNetworkIpv6 {
address: format!("{}/10", ipv6),
gateway: "fe80::1".to_string(),
},
resolver: LaunchNetworkResolver {
nameservers: vec![
"1.1.1.1".to_string(),
"1.0.0.1".to_string(),
"2606:4700:4700::1111".to_string(),
"2606:4700:4700::1001".to_string(),
],
},
}), }),
env, env,
run, run,
@ -118,8 +134,6 @@ impl Controller {
let cmdline_options = [if debug { "debug" } else { "quiet" }, "elevator=noop"]; let cmdline_options = [if debug { "debug" } else { "quiet" }, "elevator=noop"];
let cmdline = cmdline_options.join(" "); let cmdline = cmdline_options.join(" ");
let mut mac = MacAddr6::random();
mac.set_local(true);
let mac = mac.to_string().replace('-', ":"); let mac = mac.to_string().replace('-', ":");
let config = DomainConfig { let config = DomainConfig {
backend_domid: 0, backend_domid: 0,

View File

@ -12,11 +12,17 @@ pub struct LaunchNetworkIpv6 {
pub gateway: String, pub gateway: String,
} }
#[derive(Serialize, Deserialize, Debug)]
pub struct LaunchNetworkResolver {
pub nameservers: Vec<String>,
}
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct LaunchNetwork { pub struct LaunchNetwork {
pub link: String, pub link: String,
pub ipv4: LaunchNetworkIpv4, pub ipv4: LaunchNetworkIpv4,
pub ipv6: Option<LaunchNetworkIpv6>, pub ipv6: LaunchNetworkIpv6,
pub resolver: LaunchNetworkResolver,
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]