runtime-rs: Support VhostUserEndpoint

This commit introduces VhostUserEndpoint and supports relative to
vhost-user-net devices for device manager. For now, Dragonball is able to
attach vhost-user-net devices.

Fixes: #8625

Signed-off-by: Xuewei Niu <niuxuewei.nxw@antgroup.com>
This commit is contained in:
Xuewei Niu
2023-12-11 16:44:46 +08:00
parent 374c2f01aa
commit 54df832407
10 changed files with 242 additions and 8 deletions

View File

@@ -44,6 +44,12 @@ pub struct TapEndpointState {
pub if_name: String,
}
#[derive(Serialize, Deserialize, Clone, Default)]
pub struct VhostUserEndpointState {
pub if_name: String,
pub socket_path: String,
}
#[derive(Serialize, Deserialize, Clone, Default)]
pub struct EndpointState {
pub physical_endpoint: Option<PhysicalEndpointState>,
@@ -52,5 +58,6 @@ pub struct EndpointState {
pub macvlan_endpoint: Option<MacvlanEndpointState>,
pub vlan_endpoint: Option<VlanEndpointState>,
pub tap_endpoint: Option<TapEndpointState>,
pub vhost_user_endpoint: Option<VhostUserEndpointState>,
// TODO : other endpoint
}

View File

@@ -18,6 +18,8 @@ pub mod endpoint_persist;
mod endpoints_test;
mod tap_endpoint;
pub use tap_endpoint::TapEndpoint;
mod vhost_user_endpoint;
pub use vhost_user_endpoint::VhostUserEndpoint;
use anyhow::Result;
use async_trait::async_trait;

View File

@@ -0,0 +1,114 @@
// Copyright (C) 2019-2023 Ant Group. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
use std::path::Path;
use std::sync::Arc;
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use hypervisor::device::device_manager::{do_handle_device, DeviceManager};
use hypervisor::device::{DeviceConfig, DeviceType};
use hypervisor::{Hypervisor, VhostUserConfig, VhostUserNetDevice, VhostUserType};
use tokio::sync::RwLock;
use super::endpoint_persist::VhostUserEndpointState;
use super::Endpoint;
use crate::network::EndpointState;
/// VhostUserEndpoint uses vhost-user-net device, which supports DPDK, etc.
#[derive(Debug)]
pub struct VhostUserEndpoint {
// Endpoint index
#[allow(dead_code)]
index: u32,
// Name of virt interface
name: String,
// Hardware address of virt interface
guest_mac: String,
// Vhost-user-net device's socket path
socket_path: String,
// Device manager
dev_mgr: Arc<RwLock<DeviceManager>>,
// Virtio queue num
queue_num: usize,
// Virtio queue size
queue_size: usize,
}
impl VhostUserEndpoint {
pub async fn new(
dev_mgr: &Arc<RwLock<DeviceManager>>,
index: u32,
name: &str,
guest_mac: &str,
socket_path: &str,
queue_num: usize,
queue_size: usize,
) -> Result<Self> {
let sk_path = Path::new(socket_path);
if sk_path.exists() {
return Err(anyhow!("vhost-user-net socket path {} exists", socket_path));
}
Ok(VhostUserEndpoint {
index,
name: name.to_string(),
guest_mac: guest_mac.to_string(),
socket_path: socket_path.to_string(),
dev_mgr: dev_mgr.clone(),
queue_num,
queue_size,
})
}
fn get_network_config(&self) -> VhostUserConfig {
VhostUserConfig {
socket_path: self.socket_path.clone(),
mac_address: self.guest_mac.clone(),
device_type: VhostUserType::Net,
queue_size: self.queue_size as u32,
num_queues: self.queue_num,
..Default::default()
}
}
}
#[async_trait]
impl Endpoint for VhostUserEndpoint {
async fn name(&self) -> String {
self.name.clone()
}
async fn hardware_addr(&self) -> String {
self.guest_mac.clone()
}
async fn attach(&self) -> Result<()> {
let config = self.get_network_config();
do_handle_device(&self.dev_mgr, &DeviceConfig::VhostUserNetworkCfg(config))
.await
.context("handle device")?;
Ok(())
}
async fn detach(&self, h: &dyn Hypervisor) -> Result<()> {
let config = self.get_network_config();
h.remove_device(DeviceType::VhostUserNetwork(VhostUserNetDevice {
config,
..Default::default()
}))
.await
.context("remove device")?;
Ok(())
}
async fn save(&self) -> Option<EndpointState> {
Some(EndpointState {
vhost_user_endpoint: Some(VhostUserEndpointState {
if_name: self.name.clone(),
socket_path: self.socket_path.clone(),
}),
..Default::default()
})
}
}