mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-28 19:54:35 +00:00
runtime-rs: Enhancing Device Manager for network endpoints.
Currently, network endpoints are separate from the device manager and need to be included for proper management. In order to do so, we need to refactor the implementation of the network endpoints. The first step is to restructure the NetworkConfig and NetworkDevice structures. Next, we will implement the virtio-net driver and add the Network device to the Device Manager. Finally, we'll unify entries with do_handle_device for each endpoint. Fixes: #7215 Signed-off-by: alex.lyn <alex.lyn@antgroup.com>
This commit is contained in:
parent
d01762dc35
commit
283f809dda
118
src/libs/Cargo.lock
generated
118
src/libs/Cargo.lock
generated
@ -34,6 +34,17 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
@ -130,7 +141,7 @@ dependencies = [
|
||||
"js-sys",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
"time 0.1.43",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
@ -172,6 +183,27 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
@ -559,6 +591,7 @@ dependencies = [
|
||||
"slog-async",
|
||||
"slog-json",
|
||||
"slog-scope",
|
||||
"slog-term",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
@ -681,6 +714,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oci"
|
||||
version = "0.1.0"
|
||||
@ -950,13 +992,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.10"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.6.0"
|
||||
@ -983,6 +1036,12 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.9"
|
||||
@ -1113,6 +1172,19 @@ dependencies = [
|
||||
"slog",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slog-term"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87d29185c55b7b258b4f120eab00f48557d4d9bc814f41713f449d35b0f8977c"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"slog",
|
||||
"term",
|
||||
"thread_local",
|
||||
"time 0.3.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.8.0"
|
||||
@ -1170,6 +1242,17 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
|
||||
dependencies = [
|
||||
"dirs-next",
|
||||
"rustversion",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-utils"
|
||||
version = "0.1.0"
|
||||
@ -1216,6 +1299,35 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"libc",
|
||||
"num_threads",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
|
||||
dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.17.0"
|
||||
|
@ -11,8 +11,9 @@ use kata_sys_util::rand::RandomBytes;
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
|
||||
use crate::{
|
||||
device::VhostUserBlkDevice, BlockConfig, BlockDevice, Hypervisor, VfioDevice, VhostUserConfig,
|
||||
KATA_BLK_DEV_TYPE, KATA_MMIO_BLK_DEV_TYPE, VIRTIO_BLOCK_MMIO, VIRTIO_BLOCK_PCI,
|
||||
device::VhostUserBlkDevice, BlockConfig, BlockDevice, Hypervisor, NetworkDevice, VfioDevice,
|
||||
VhostUserConfig, KATA_BLK_DEV_TYPE, KATA_MMIO_BLK_DEV_TYPE, VIRTIO_BLOCK_MMIO,
|
||||
VIRTIO_BLOCK_PCI,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -193,6 +194,11 @@ impl DeviceManager {
|
||||
return Some(device_id.to_string());
|
||||
}
|
||||
}
|
||||
DeviceType::Network(device) => {
|
||||
if device.config.host_dev_name == host_path {
|
||||
return Some(device_id.to_string());
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// TODO: support find other device type
|
||||
continue;
|
||||
@ -267,6 +273,21 @@ impl DeviceManager {
|
||||
.await
|
||||
.context("failed to create vhost blk device")?
|
||||
}
|
||||
DeviceConfig::NetworkCfg(config) => {
|
||||
// try to find the device, found and just return id.
|
||||
if let Some(dev_id_matched) = self.find_device(config.host_dev_name.clone()).await {
|
||||
info!(
|
||||
sl!(),
|
||||
"network device with path:{:?} found. return network device id: {:?}",
|
||||
config.host_dev_name.clone(),
|
||||
dev_id_matched
|
||||
);
|
||||
|
||||
return Ok(dev_id_matched);
|
||||
}
|
||||
|
||||
Arc::new(Mutex::new(NetworkDevice::new(device_id.clone(), config)))
|
||||
}
|
||||
_ => {
|
||||
return Err(anyhow!("invliad device type"));
|
||||
}
|
||||
|
@ -6,6 +6,14 @@
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::{
|
||||
device::{Device, DeviceType},
|
||||
Hypervisor as hypervisor,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Address(pub [u8; 6]);
|
||||
|
||||
@ -20,20 +28,71 @@ impl fmt::Debug for Address {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct NetworkConfig {
|
||||
/// for detach, now it's default value 0.
|
||||
pub index: u64,
|
||||
|
||||
/// Host level path for the guest network interface.
|
||||
pub host_dev_name: String,
|
||||
|
||||
/// Guest iface name for the guest network interface.
|
||||
pub virt_iface_name: String,
|
||||
|
||||
/// Guest MAC address.
|
||||
pub guest_mac: Option<Address>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct NetworkDevice {
|
||||
/// Unique identifier of the device
|
||||
pub id: String,
|
||||
pub device_id: String,
|
||||
|
||||
/// Network Device config info
|
||||
pub config: NetworkConfig,
|
||||
}
|
||||
|
||||
impl NetworkDevice {
|
||||
// new creates a NetworkDevice
|
||||
pub fn new(device_id: String, config: &NetworkConfig) -> Self {
|
||||
Self {
|
||||
device_id,
|
||||
config: config.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Device for NetworkDevice {
|
||||
async fn attach(&mut self, h: &dyn hypervisor) -> Result<()> {
|
||||
h.add_device(DeviceType::Network(self.clone()))
|
||||
.await
|
||||
.context("add network device.")?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
async fn detach(&mut self, h: &dyn hypervisor) -> Result<Option<u64>> {
|
||||
h.remove_device(DeviceType::Network(self.clone()))
|
||||
.await
|
||||
.context("remove network device.")?;
|
||||
|
||||
Ok(Some(self.config.index))
|
||||
}
|
||||
|
||||
async fn get_device_info(&self) -> DeviceType {
|
||||
DeviceType::Network(self.clone())
|
||||
}
|
||||
|
||||
async fn increase_attach_count(&mut self) -> Result<bool> {
|
||||
// network devices will not be attached multiple times, Just return Ok(false)
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
async fn decrease_attach_count(&mut self) -> Result<bool> {
|
||||
// network devices will not be detached multiple times, Just return Ok(false)
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ impl DragonballInner {
|
||||
info!(sl!(), "dragonball add device {:?}", &device);
|
||||
match device {
|
||||
DeviceType::Network(network) => self
|
||||
.add_net_device(&network.config, network.id)
|
||||
.add_net_device(&network.config)
|
||||
.context("add net device"),
|
||||
DeviceType::Vfio(hostdev) => self.add_vfio_device(&hostdev).context("add vfio device"),
|
||||
DeviceType::Block(block) => self
|
||||
@ -84,6 +84,15 @@ impl DragonballInner {
|
||||
info!(sl!(), "remove device {} ", device);
|
||||
|
||||
match device {
|
||||
DeviceType::Network(network) => {
|
||||
// Dragonball doesn't support remove network device, just print message.
|
||||
info!(
|
||||
sl!(),
|
||||
"dragonball remove network device: {:?}.", network.config.virt_iface_name
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
DeviceType::Block(block) => {
|
||||
let drive_id = drive_index_to_id(block.config.index);
|
||||
self.remove_block_drive(drive_id.as_str())
|
||||
@ -197,9 +206,9 @@ impl DragonballInner {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_net_device(&mut self, config: &NetworkConfig, device_id: String) -> Result<()> {
|
||||
fn add_net_device(&mut self, config: &NetworkConfig) -> Result<()> {
|
||||
let iface_cfg = VirtioNetDeviceConfigInfo {
|
||||
iface_id: device_id,
|
||||
iface_id: config.virt_iface_name.clone(),
|
||||
host_dev_name: config.host_dev_name.clone(),
|
||||
guest_mac: match &config.guest_mac {
|
||||
Some(mac) => MacAddr::from_bytes(&mac.0).ok(),
|
||||
|
@ -141,15 +141,13 @@ impl ResourceManagerInner {
|
||||
// but it is not in netns. So, the previous thread would still remain in the pod netns.
|
||||
// The solution is to block the future on the current thread, it is enabled by spawn an os thread, create a
|
||||
// tokio runtime, and block the task on it.
|
||||
let hypervisor = self.hypervisor.clone();
|
||||
let device_manager = self.device_manager.clone();
|
||||
let network = thread::spawn(move || -> Result<Arc<dyn Network>> {
|
||||
let rt = runtime::Builder::new_current_thread().enable_io().build()?;
|
||||
let d = rt
|
||||
.block_on(network::new(&network_config, device_manager))
|
||||
.context("new network")?;
|
||||
rt.block_on(d.setup(hypervisor.as_ref()))
|
||||
.context("setup network")?;
|
||||
rt.block_on(d.setup()).context("setup network")?;
|
||||
Ok(d)
|
||||
})
|
||||
.join()
|
||||
|
@ -6,11 +6,12 @@
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use anyhow::Context;
|
||||
use std::{fs, path::Path, sync::Arc};
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use netlink_packet_route::MACVLAN_MODE_PRIVATE;
|
||||
use scopeguard::defer;
|
||||
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::network::{
|
||||
endpoint::{IPVlanEndpoint, MacVlanEndpoint, VlanEndpoint},
|
||||
@ -22,6 +23,41 @@ mod tests {
|
||||
network_pair::{NetworkInterface, NetworkPair, TapInterface},
|
||||
utils::link::net_test_utils::delete_link,
|
||||
};
|
||||
use hypervisor::{device::device_manager::DeviceManager, qemu::Qemu};
|
||||
use kata_types::config::{QemuConfig, TomlConfig};
|
||||
|
||||
async fn get_device_manager() -> Result<Arc<RwLock<DeviceManager>>> {
|
||||
let path = env!("CARGO_MANIFEST_DIR");
|
||||
let path = Path::new(path)
|
||||
.join("../../../libs/kata-types/tests/texture/configuration-anno-0.toml");
|
||||
|
||||
let content = fs::read_to_string(path).context("read configuration failed")?;
|
||||
// just for test, use x/kata-types/tests/texture/configuration-anno-0.toml as
|
||||
// the test configuration.toml which is for qemu.
|
||||
let hypervisor_name: &str = "qemu";
|
||||
|
||||
let qemu = QemuConfig::new();
|
||||
qemu.register();
|
||||
|
||||
let toml_config = TomlConfig::load(&content).context("load toml config failed")?;
|
||||
let hypervisor_config = toml_config
|
||||
.hypervisor
|
||||
.get(hypervisor_name)
|
||||
.ok_or_else(|| anyhow!("failed to get hypervisor for {}", &hypervisor_name))?;
|
||||
|
||||
let mut hypervisor = Qemu::new();
|
||||
hypervisor
|
||||
.set_hypervisor_config(hypervisor_config.clone())
|
||||
.await;
|
||||
|
||||
let dm = Arc::new(RwLock::new(
|
||||
DeviceManager::new(Arc::new(hypervisor))
|
||||
.await
|
||||
.context("device manager")?,
|
||||
));
|
||||
|
||||
Ok(dm)
|
||||
}
|
||||
|
||||
// this unit test tests the integrity of MacVlanEndpoint::new()
|
||||
#[actix_rt::test]
|
||||
@ -33,6 +69,10 @@ mod tests {
|
||||
let dummy_name = format!("dummy{}", idx);
|
||||
let vlanid = 123;
|
||||
|
||||
let dm = get_device_manager().await;
|
||||
assert!(dm.is_ok());
|
||||
let d = dm.unwrap();
|
||||
|
||||
if let Ok((conn, handle, _)) =
|
||||
rtnetlink::new_connection().context("failed to create netlink connection")
|
||||
{
|
||||
@ -63,11 +103,12 @@ mod tests {
|
||||
.await
|
||||
.context("failed to create manual veth pair")
|
||||
{
|
||||
if let Ok(mut result) = VlanEndpoint::new(&handle, "", idx, 5)
|
||||
if let Ok(mut result) = VlanEndpoint::new(&d, &handle, "", idx, 5)
|
||||
.await
|
||||
.context("failed to create new ipvlan endpoint")
|
||||
{
|
||||
let manual = VlanEndpoint {
|
||||
d,
|
||||
net_pair: NetworkPair {
|
||||
tap: TapInterface {
|
||||
id: String::from("uniqueTestID_kata"),
|
||||
@ -144,6 +185,9 @@ mod tests {
|
||||
let tap_iface_name = format!("tap{}_kata", idx); // create by NetworkPair::new()
|
||||
let model_str = TC_FILTER_NET_MODEL_STR;
|
||||
let dummy_name = format!("dummy{}", idx);
|
||||
let dm = get_device_manager().await;
|
||||
assert!(dm.is_ok());
|
||||
let d = dm.unwrap();
|
||||
|
||||
if let Ok((conn, handle, _)) =
|
||||
rtnetlink::new_connection().context("failed to create netlink connection")
|
||||
@ -180,6 +224,7 @@ mod tests {
|
||||
{
|
||||
// model here does not matter, could be any of supported models
|
||||
if let Ok(mut result) = MacVlanEndpoint::new(
|
||||
&d,
|
||||
&handle,
|
||||
manual_macvlan_iface_name.clone().as_str(),
|
||||
idx,
|
||||
@ -190,6 +235,7 @@ mod tests {
|
||||
.context("failed to create new macvlan endpoint")
|
||||
{
|
||||
let manual = MacVlanEndpoint {
|
||||
d,
|
||||
net_pair: NetworkPair {
|
||||
tap: TapInterface {
|
||||
id: String::from("uniqueTestID_kata"),
|
||||
@ -267,6 +313,9 @@ mod tests {
|
||||
let mac_addr = String::from("02:00:CA:FE:00:04");
|
||||
let manual_virt_iface_name = format!("eth{}", idx);
|
||||
let tap_iface_name = format!("tap{}_kata", idx); // create by kata
|
||||
let dm = get_device_manager().await;
|
||||
assert!(dm.is_ok());
|
||||
let d = dm.unwrap();
|
||||
|
||||
if let Ok((conn, handle, _)) =
|
||||
rtnetlink::new_connection().context("failed to create netlink connection")
|
||||
@ -286,11 +335,12 @@ mod tests {
|
||||
.await
|
||||
.context("failed to create manual veth pair")
|
||||
{
|
||||
if let Ok(mut result) = IPVlanEndpoint::new(&handle, "", idx, 5)
|
||||
if let Ok(mut result) = IPVlanEndpoint::new(&d, &handle, "", idx, 5)
|
||||
.await
|
||||
.context("failed to create new ipvlan endpoint")
|
||||
{
|
||||
let manual = IPVlanEndpoint {
|
||||
d,
|
||||
net_pair: NetworkPair {
|
||||
tap: TapInterface {
|
||||
id: String::from("uniqueTestID_kata"),
|
||||
|
@ -4,37 +4,54 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::io::{self, Error};
|
||||
use std::{
|
||||
io::{self, Error},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use super::endpoint_persist::{EndpointState, IpVlanEndpointState};
|
||||
use anyhow::{Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use hypervisor::device::DeviceType;
|
||||
use hypervisor::NetworkDevice;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use super::Endpoint;
|
||||
use crate::network::network_model::TC_FILTER_NET_MODEL_STR;
|
||||
use crate::network::{utils, NetworkPair};
|
||||
use hypervisor::{device::driver::NetworkConfig, Hypervisor};
|
||||
use hypervisor::{
|
||||
device::{
|
||||
device_manager::{do_handle_device, DeviceManager},
|
||||
driver::NetworkConfig,
|
||||
DeviceConfig, DeviceType,
|
||||
},
|
||||
Hypervisor, NetworkDevice,
|
||||
};
|
||||
|
||||
use super::{
|
||||
endpoint_persist::{EndpointState, IpVlanEndpointState},
|
||||
Endpoint,
|
||||
};
|
||||
use crate::network::{network_model::TC_FILTER_NET_MODEL_STR, utils, NetworkPair};
|
||||
|
||||
// IPVlanEndpoint is the endpoint bridged to VM
|
||||
#[derive(Debug)]
|
||||
pub struct IPVlanEndpoint {
|
||||
pub(crate) net_pair: NetworkPair,
|
||||
pub(crate) d: Arc<RwLock<DeviceManager>>,
|
||||
}
|
||||
|
||||
impl IPVlanEndpoint {
|
||||
pub async fn new(
|
||||
d: &Arc<RwLock<DeviceManager>>,
|
||||
handle: &rtnetlink::Handle,
|
||||
name: &str,
|
||||
idx: u32,
|
||||
queues: usize,
|
||||
) -> Result<Self> {
|
||||
// tc filter network model is the only one works for ipvlan
|
||||
// tc filter network model is the only for ipvlan
|
||||
let net_pair = NetworkPair::new(handle, idx, name, TC_FILTER_NET_MODEL_STR, queues)
|
||||
.await
|
||||
.context("error creating new NetworkPair")?;
|
||||
Ok(IPVlanEndpoint { net_pair })
|
||||
|
||||
Ok(IPVlanEndpoint {
|
||||
net_pair,
|
||||
d: d.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn get_network_config(&self) -> Result<NetworkConfig> {
|
||||
@ -45,9 +62,12 @@ impl IPVlanEndpoint {
|
||||
format!("hard_addr {}", &iface.hard_addr),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(NetworkConfig {
|
||||
host_dev_name: iface.name.clone(),
|
||||
virt_iface_name: self.net_pair.virt_iface.name.clone(),
|
||||
guest_mac: Some(guest_mac),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -62,18 +82,16 @@ impl Endpoint for IPVlanEndpoint {
|
||||
self.net_pair.tap.tap_iface.hard_addr.clone()
|
||||
}
|
||||
|
||||
async fn attach(&self, h: &dyn Hypervisor) -> Result<()> {
|
||||
async fn attach(&self) -> Result<()> {
|
||||
self.net_pair
|
||||
.add_network_model()
|
||||
.await
|
||||
.context("error adding network model")?;
|
||||
|
||||
let config = self.get_network_config().context("get network config")?;
|
||||
h.add_device(DeviceType::Network(NetworkDevice {
|
||||
id: self.net_pair.virt_iface.name.clone(),
|
||||
config,
|
||||
}))
|
||||
.await
|
||||
.context("error adding device by hypervisor")?;
|
||||
do_handle_device(&self.d, &DeviceConfig::NetworkCfg(config))
|
||||
.await
|
||||
.context("do handle network IPVlan endpoint device failed.")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -86,12 +104,13 @@ impl Endpoint for IPVlanEndpoint {
|
||||
let config = self
|
||||
.get_network_config()
|
||||
.context("error getting network config")?;
|
||||
|
||||
h.remove_device(DeviceType::Network(NetworkDevice {
|
||||
id: self.net_pair.virt_iface.name.clone(),
|
||||
config,
|
||||
..Default::default()
|
||||
}))
|
||||
.await
|
||||
.context("error removing device by hypervisor")?;
|
||||
.context("remove IPVlan endpoint device by hypervisor failed.")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -4,24 +4,39 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::io::{self, Error};
|
||||
use std::{
|
||||
io::{self, Error},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use super::endpoint_persist::{EndpointState, MacvlanEndpointState};
|
||||
use super::Endpoint;
|
||||
use crate::network::{utils, NetworkPair};
|
||||
use anyhow::{Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use hypervisor::device::DeviceType;
|
||||
use hypervisor::NetworkDevice;
|
||||
use hypervisor::{device::driver::NetworkConfig, Hypervisor};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use hypervisor::{
|
||||
device::{
|
||||
device_manager::{do_handle_device, DeviceManager},
|
||||
driver::NetworkConfig,
|
||||
DeviceConfig, DeviceType,
|
||||
},
|
||||
Hypervisor, NetworkDevice,
|
||||
};
|
||||
|
||||
use super::{
|
||||
endpoint_persist::{EndpointState, MacvlanEndpointState},
|
||||
Endpoint,
|
||||
};
|
||||
use crate::network::{utils, NetworkPair};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MacVlanEndpoint {
|
||||
pub(crate) net_pair: NetworkPair,
|
||||
pub(crate) d: Arc<RwLock<DeviceManager>>,
|
||||
}
|
||||
|
||||
impl MacVlanEndpoint {
|
||||
pub async fn new(
|
||||
d: &Arc<RwLock<DeviceManager>>,
|
||||
handle: &rtnetlink::Handle,
|
||||
name: &str,
|
||||
idx: u32,
|
||||
@ -31,7 +46,11 @@ impl MacVlanEndpoint {
|
||||
let net_pair = NetworkPair::new(handle, idx, name, model, queues)
|
||||
.await
|
||||
.context("error creating new networkInterfacePair")?;
|
||||
Ok(MacVlanEndpoint { net_pair })
|
||||
|
||||
Ok(MacVlanEndpoint {
|
||||
net_pair,
|
||||
d: d.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn get_network_config(&self) -> Result<NetworkConfig> {
|
||||
@ -42,9 +61,12 @@ impl MacVlanEndpoint {
|
||||
format!("hard_addr {}", &iface.hard_addr),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(NetworkConfig {
|
||||
host_dev_name: iface.name.clone(),
|
||||
virt_iface_name: self.net_pair.virt_iface.name.clone(),
|
||||
guest_mac: Some(guest_mac),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -59,18 +81,16 @@ impl Endpoint for MacVlanEndpoint {
|
||||
self.net_pair.tap.tap_iface.hard_addr.clone()
|
||||
}
|
||||
|
||||
async fn attach(&self, h: &dyn Hypervisor) -> Result<()> {
|
||||
async fn attach(&self) -> Result<()> {
|
||||
self.net_pair
|
||||
.add_network_model()
|
||||
.await
|
||||
.context("add network model")?;
|
||||
|
||||
let config = self.get_network_config().context("get network config")?;
|
||||
h.add_device(DeviceType::Network(NetworkDevice {
|
||||
id: self.net_pair.virt_iface.name.clone(),
|
||||
config,
|
||||
}))
|
||||
.await
|
||||
.context("error adding device by hypervisor")?;
|
||||
do_handle_device(&self.d, &DeviceConfig::NetworkCfg(config))
|
||||
.await
|
||||
.context("do handle network MacVlan endpoint device failed.")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -80,13 +100,14 @@ impl Endpoint for MacVlanEndpoint {
|
||||
.del_network_model()
|
||||
.await
|
||||
.context("del network model")?;
|
||||
|
||||
let config = self.get_network_config().context("get network config")?;
|
||||
h.remove_device(DeviceType::Network(NetworkDevice {
|
||||
id: self.net_pair.virt_iface.name.clone(),
|
||||
config,
|
||||
..Default::default()
|
||||
}))
|
||||
.await
|
||||
.context("error removing device by hypervisor")?;
|
||||
.context("remove MacVlan endpoint device by hypervisor failed.")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ use super::EndpointState;
|
||||
pub trait Endpoint: std::fmt::Debug + Send + Sync {
|
||||
async fn name(&self) -> String;
|
||||
async fn hardware_addr(&self) -> String;
|
||||
async fn attach(&self, hypervisor: &dyn Hypervisor) -> Result<()>;
|
||||
async fn attach(&self) -> Result<()>;
|
||||
async fn detach(&self, hypervisor: &dyn Hypervisor) -> Result<()>;
|
||||
async fn save(&self) -> Option<EndpointState>;
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ impl Endpoint for PhysicalEndpoint {
|
||||
self.hard_addr.clone()
|
||||
}
|
||||
|
||||
async fn attach(&self, _hypervisor: &dyn Hypervisor) -> Result<()> {
|
||||
async fn attach(&self) -> Result<()> {
|
||||
// bind physical interface from host driver and bind to vfio
|
||||
driver::bind_device_to_vfio(
|
||||
&self.bdf,
|
||||
|
@ -4,24 +4,39 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::io::{self, Error};
|
||||
use std::{
|
||||
io::{self, Error},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use super::endpoint_persist::{EndpointState, VethEndpointState};
|
||||
use super::Endpoint;
|
||||
use crate::network::{utils, NetworkPair};
|
||||
use anyhow::{Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use hypervisor::device::DeviceType;
|
||||
use hypervisor::NetworkDevice;
|
||||
use hypervisor::{device::driver::NetworkConfig, Hypervisor};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use hypervisor::{
|
||||
device::{
|
||||
device_manager::{do_handle_device, DeviceManager},
|
||||
driver::NetworkConfig,
|
||||
DeviceConfig, DeviceType,
|
||||
},
|
||||
Hypervisor, NetworkDevice,
|
||||
};
|
||||
|
||||
use super::{
|
||||
endpoint_persist::{EndpointState, VethEndpointState},
|
||||
Endpoint,
|
||||
};
|
||||
use crate::network::{utils, NetworkPair};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VethEndpoint {
|
||||
net_pair: NetworkPair,
|
||||
pub(crate) net_pair: NetworkPair,
|
||||
pub(crate) d: Arc<RwLock<DeviceManager>>,
|
||||
}
|
||||
|
||||
impl VethEndpoint {
|
||||
pub async fn new(
|
||||
d: &Arc<RwLock<DeviceManager>>,
|
||||
handle: &rtnetlink::Handle,
|
||||
name: &str,
|
||||
idx: u32,
|
||||
@ -30,8 +45,12 @@ impl VethEndpoint {
|
||||
) -> Result<Self> {
|
||||
let net_pair = NetworkPair::new(handle, idx, name, model, queues)
|
||||
.await
|
||||
.context("new networkInterfacePair")?;
|
||||
Ok(VethEndpoint { net_pair })
|
||||
.context("new network interface pair failed.")?;
|
||||
|
||||
Ok(VethEndpoint {
|
||||
net_pair,
|
||||
d: d.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn get_network_config(&self) -> Result<NetworkConfig> {
|
||||
@ -42,9 +61,12 @@ impl VethEndpoint {
|
||||
format!("hard_addr {}", &iface.hard_addr),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(NetworkConfig {
|
||||
host_dev_name: iface.name.clone(),
|
||||
virt_iface_name: self.net_pair.virt_iface.name.clone(),
|
||||
guest_mac: Some(guest_mac),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -59,18 +81,17 @@ impl Endpoint for VethEndpoint {
|
||||
self.net_pair.tap.tap_iface.hard_addr.clone()
|
||||
}
|
||||
|
||||
async fn attach(&self, h: &dyn Hypervisor) -> Result<()> {
|
||||
async fn attach(&self) -> Result<()> {
|
||||
self.net_pair
|
||||
.add_network_model()
|
||||
.await
|
||||
.context("add network model")?;
|
||||
|
||||
let config = self.get_network_config().context("get network config")?;
|
||||
h.add_device(DeviceType::Network(NetworkDevice {
|
||||
id: self.net_pair.virt_iface.name.clone(),
|
||||
config,
|
||||
}))
|
||||
.await
|
||||
.context("error adding device by hypervisor")?;
|
||||
do_handle_device(&self.d, &DeviceConfig::NetworkCfg(config))
|
||||
.await
|
||||
.context("do handle network Veth endpoint device failed.")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -78,16 +99,19 @@ impl Endpoint for VethEndpoint {
|
||||
self.net_pair
|
||||
.del_network_model()
|
||||
.await
|
||||
.context("del network model")?;
|
||||
.context("del network model failed.")?;
|
||||
|
||||
let config = self.get_network_config().context("get network config")?;
|
||||
h.remove_device(DeviceType::Network(NetworkDevice {
|
||||
id: self.net_pair.virt_iface.name.clone(),
|
||||
config,
|
||||
..Default::default()
|
||||
}))
|
||||
.await
|
||||
.context("error removing device by hypervisor")?;
|
||||
.context("remove Veth endpoint device by hypervisor failed.")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn save(&self) -> Option<EndpointState> {
|
||||
Some(EndpointState {
|
||||
veth_endpoint: Some(VethEndpointState {
|
||||
|
@ -4,25 +4,39 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::io::{self, Error};
|
||||
use std::{
|
||||
io::{self, Error},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use hypervisor::device::DeviceType;
|
||||
use hypervisor::NetworkDevice;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use hypervisor::{
|
||||
device::{
|
||||
device_manager::{do_handle_device, DeviceManager},
|
||||
driver::NetworkConfig,
|
||||
DeviceConfig, DeviceType,
|
||||
},
|
||||
Hypervisor, NetworkDevice,
|
||||
};
|
||||
|
||||
use super::{
|
||||
endpoint_persist::{EndpointState, VlanEndpointState},
|
||||
Endpoint,
|
||||
};
|
||||
use crate::network::{network_model::TC_FILTER_NET_MODEL_STR, utils, NetworkPair};
|
||||
|
||||
use super::endpoint_persist::{EndpointState, VlanEndpointState};
|
||||
use super::Endpoint;
|
||||
use crate::network::network_model::TC_FILTER_NET_MODEL_STR;
|
||||
use crate::network::{utils, NetworkPair};
|
||||
use hypervisor::{device::driver::NetworkConfig, Hypervisor};
|
||||
#[derive(Debug)]
|
||||
pub struct VlanEndpoint {
|
||||
pub(crate) net_pair: NetworkPair,
|
||||
pub(crate) d: Arc<RwLock<DeviceManager>>,
|
||||
}
|
||||
|
||||
impl VlanEndpoint {
|
||||
pub async fn new(
|
||||
d: &Arc<RwLock<DeviceManager>>,
|
||||
handle: &rtnetlink::Handle,
|
||||
name: &str,
|
||||
idx: u32,
|
||||
@ -30,8 +44,12 @@ impl VlanEndpoint {
|
||||
) -> Result<Self> {
|
||||
let net_pair = NetworkPair::new(handle, idx, name, TC_FILTER_NET_MODEL_STR, queues)
|
||||
.await
|
||||
.context("error creating networkInterfacePair")?;
|
||||
Ok(VlanEndpoint { net_pair })
|
||||
.context("new network interface pair failed.")?;
|
||||
|
||||
Ok(VlanEndpoint {
|
||||
net_pair,
|
||||
d: d.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn get_network_config(&self) -> Result<NetworkConfig> {
|
||||
@ -42,9 +60,12 @@ impl VlanEndpoint {
|
||||
format!("hard_addr {}", &iface.hard_addr),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(NetworkConfig {
|
||||
host_dev_name: iface.name.clone(),
|
||||
virt_iface_name: self.net_pair.virt_iface.name.clone(),
|
||||
guest_mac: Some(guest_mac),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -59,18 +80,16 @@ impl Endpoint for VlanEndpoint {
|
||||
self.net_pair.tap.tap_iface.hard_addr.clone()
|
||||
}
|
||||
|
||||
async fn attach(&self, h: &dyn Hypervisor) -> Result<()> {
|
||||
async fn attach(&self) -> Result<()> {
|
||||
self.net_pair
|
||||
.add_network_model()
|
||||
.await
|
||||
.context("error adding network model")?;
|
||||
.context("add network model failed.")?;
|
||||
|
||||
let config = self.get_network_config().context("get network config")?;
|
||||
h.add_device(DeviceType::Network(NetworkDevice {
|
||||
id: self.net_pair.virt_iface.name.clone(),
|
||||
config,
|
||||
}))
|
||||
.await
|
||||
.context("error adding device by hypervisor")?;
|
||||
do_handle_device(&self.d, &DeviceConfig::NetworkCfg(config))
|
||||
.await
|
||||
.context("do handle network Vlan endpoint device failed.")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -79,16 +98,17 @@ impl Endpoint for VlanEndpoint {
|
||||
self.net_pair
|
||||
.del_network_model()
|
||||
.await
|
||||
.context("error deleting network model")?;
|
||||
.context("delete network model failed.")?;
|
||||
|
||||
let config = self
|
||||
.get_network_config()
|
||||
.context("error getting network config")?;
|
||||
.context("get network config failed.")?;
|
||||
h.remove_device(DeviceType::Network(NetworkDevice {
|
||||
id: self.net_pair.virt_iface.name.clone(),
|
||||
config,
|
||||
..Default::default()
|
||||
}))
|
||||
.await
|
||||
.context("error removing device by hypervisor")?;
|
||||
.context("remove Vlan endpoint device by hypervisor failed.")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ pub enum NetworkConfig {
|
||||
|
||||
#[async_trait]
|
||||
pub trait Network: Send + Sync {
|
||||
async fn setup(&self, h: &dyn Hypervisor) -> Result<()>;
|
||||
async fn setup(&self) -> Result<()>;
|
||||
async fn interfaces(&self) -> Result<Vec<agent::Interface>>;
|
||||
async fn routes(&self) -> Result<Vec<agent::Route>>;
|
||||
async fn neighs(&self) -> Result<Vec<agent::ARPNeighbor>>;
|
||||
|
@ -39,6 +39,7 @@ pub struct NetworkPair {
|
||||
pub model: Arc<dyn network_model::NetworkModel>,
|
||||
pub network_qos: bool,
|
||||
}
|
||||
|
||||
impl NetworkPair {
|
||||
pub(crate) async fn new(
|
||||
handle: &rtnetlink::Handle,
|
||||
|
@ -82,11 +82,11 @@ impl NetworkWithNetns {
|
||||
|
||||
#[async_trait]
|
||||
impl Network for NetworkWithNetns {
|
||||
async fn setup(&self, h: &dyn Hypervisor) -> Result<()> {
|
||||
async fn setup(&self) -> Result<()> {
|
||||
let inner = self.inner.read().await;
|
||||
let _netns_guard = netns::NetnsGuard::new(&inner.netns_path).context("net netns guard")?;
|
||||
for e in &inner.entity_list {
|
||||
e.endpoint.attach(h).await.context("attach")?;
|
||||
e.endpoint.attach().await.context("attach")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -225,6 +225,7 @@ async fn create_endpoint(
|
||||
match link_type {
|
||||
"veth" => {
|
||||
let ret = VethEndpoint::new(
|
||||
&d,
|
||||
handle,
|
||||
&attrs.name,
|
||||
idx,
|
||||
@ -236,19 +237,20 @@ async fn create_endpoint(
|
||||
Arc::new(ret)
|
||||
}
|
||||
"vlan" => {
|
||||
let ret = VlanEndpoint::new(handle, &attrs.name, idx, config.queues)
|
||||
let ret = VlanEndpoint::new(&d, handle, &attrs.name, idx, config.queues)
|
||||
.await
|
||||
.context("vlan endpoint")?;
|
||||
Arc::new(ret)
|
||||
}
|
||||
"ipvlan" => {
|
||||
let ret = IPVlanEndpoint::new(handle, &attrs.name, idx, config.queues)
|
||||
let ret = IPVlanEndpoint::new(&d, handle, &attrs.name, idx, config.queues)
|
||||
.await
|
||||
.context("ipvlan endpoint")?;
|
||||
Arc::new(ret)
|
||||
}
|
||||
"macvlan" => {
|
||||
let ret = MacVlanEndpoint::new(
|
||||
&d,
|
||||
handle,
|
||||
&attrs.name,
|
||||
idx,
|
||||
|
Loading…
Reference in New Issue
Block a user