From ce4b0a8397359e7ea472e778698cd771ccb4ce10 Mon Sep 17 00:00:00 2001 From: Ric Li Date: Wed, 20 Dec 2023 16:48:41 +0800 Subject: [PATCH] rust: wrap the init parameters (#658) Signed-off-by: Ric Li --- rust/Cargo.toml | 3 + rust/examples/init.rs | 28 +++++ rust/examples/version.rs | 4 +- rust/src/imtl/lib.rs | 4 +- rust/src/imtl/mtl.rs | 227 ++++++++++++++++++++++++++++++++++ rust/src/imtl/netdev.rs | 99 +++++++++++++++ rust/src/imtl/pipeline/mod.rs | 2 +- 7 files changed, 363 insertions(+), 4 deletions(-) create mode 100644 rust/examples/init.rs create mode 100644 rust/src/imtl/mtl.rs create mode 100644 rust/src/imtl/netdev.rs diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 735b93ed1..70f3b5f96 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -13,6 +13,9 @@ path = "src/imtl/lib.rs" path = "imtl-sys" version = "^0.1.0" +[dependencies.bitflags] +version = "2.4.1" + [features] convert = ["imtl-sys/convert"] pipeline = ["imtl-sys/pipeline"] diff --git a/rust/examples/init.rs b/rust/examples/init.rs new file mode 100644 index 000000000..46b641643 --- /dev/null +++ b/rust/examples/init.rs @@ -0,0 +1,28 @@ +use imtl::mtl::{Mtl, MtlFlags, MtlInitParams, MtlLogLevel}; +use imtl::netdev::*; + +fn main() { + let mut params = MtlInitParams::new(); + + let mut flags = MtlFlags::empty(); + flags.insert(MtlFlags::MTL_FLAG_BIND_NUMA); + params.set_flags(flags); + + let net_dev = MtlNetDev::new( + "0000:4b:01.0".to_string(), + MtlNetProto::Static, + MtlPmdType::DpdkPmd, + "192.168.96.111".parse().ok(), + "255.255.255.0".parse().ok(), + "0.0.0.0".parse().ok(), + 1, + 1, + 1, + ); + params.add_netdev(net_dev); + + params.set_log_level(MtlLogLevel::Debug); + + let _mtl = Mtl::new(¶ms); + std::thread::sleep(std::time::Duration::from_secs(3)); +} diff --git a/rust/examples/version.rs b/rust/examples/version.rs index 8a7cf81a2..604537da8 100644 --- a/rust/examples/version.rs +++ b/rust/examples/version.rs @@ -1,6 +1,6 @@ use imtl::version; -fn main () { +fn main() { let v = version::version(); println!("current imtl version is {}", v); -} \ No newline at end of file +} diff --git a/rust/src/imtl/lib.rs b/rust/src/imtl/lib.rs index 290de8e3b..854ab878e 100644 --- a/rust/src/imtl/lib.rs +++ b/rust/src/imtl/lib.rs @@ -3,10 +3,12 @@ pub extern crate imtl_sys as sys; +pub mod mtl; +pub mod netdev; pub mod version; // modules #[cfg(feature = "convert")] pub mod convert; #[cfg(feature = "pipeline")] -pub mod pipeline; \ No newline at end of file +pub mod pipeline; diff --git a/rust/src/imtl/mtl.rs b/rust/src/imtl/mtl.rs new file mode 100644 index 000000000..0ff5f8dca --- /dev/null +++ b/rust/src/imtl/mtl.rs @@ -0,0 +1,227 @@ +use bitflags::bitflags; +use std::mem::MaybeUninit; +use std::ptr::null_mut; + +use crate::netdev::MtlNetDev; +use crate::sys; + +#[derive(Copy, Clone)] +pub enum MtlLogLevel { + Debug = 0, + Info, + Notice, + Warning, + Error, +} + +#[derive(Copy, Clone)] +pub enum MtlRssMode { + None = 0, + L3, + L3L4, +} + +#[derive(Copy, Clone)] +pub enum MtlIovaMode { + Auto = 0, + Va, + Pa, +} + +bitflags! { + pub struct MtlFlags: u64 { + const MTL_FLAG_BIND_NUMA = + sys::mtl_init_flag_MTL_FLAG_BIND_NUMA; + const MTL_FLAG_PTP_ENABLE = + sys::mtl_init_flag_MTL_FLAG_PTP_ENABLE; + const MTL_FLAG_RX_SEPARATE_VIDEO_LCORE = + sys::mtl_init_flag_MTL_FLAG_RX_SEPARATE_VIDEO_LCORE; + const MTL_FLAG_TX_VIDEO_MIGRATE = + sys::mtl_init_flag_MTL_FLAG_TX_VIDEO_MIGRATE; + const MTL_FLAG_RX_VIDEO_MIGRATE = + sys::mtl_init_flag_MTL_FLAG_RX_VIDEO_MIGRATE; + const MTL_FLAG_TASKLET_THREAD = + sys::mtl_init_flag_MTL_FLAG_TASKLET_THREAD; + const MTL_FLAG_TASKLET_SLEEP = + sys::mtl_init_flag_MTL_FLAG_TASKLET_SLEEP; + const MTL_FLAG_RXTX_SIMD_512 = + sys::mtl_init_flag_MTL_FLAG_RXTX_SIMD_512; + const MTL_FLAG_PTP_PI = + sys::mtl_init_flag_MTL_FLAG_PTP_PI; + const MTL_FLAG_UDP_LCORE = + sys::mtl_init_flag_MTL_FLAG_UDP_LCORE; + const MTL_FLAG_RANDOM_SRC_PORT = + sys::mtl_init_flag_MTL_FLAG_RANDOM_SRC_PORT; + const MTL_FLAG_MULTI_SRC_PORT = + sys::mtl_init_flag_MTL_FLAG_MULTI_SRC_PORT; + const MTL_FLAG_SHARED_TX_QUEUE = + sys::mtl_init_flag_MTL_FLAG_SHARED_TX_QUEUE; + const MTL_FLAG_SHARED_RX_QUEUE = + sys::mtl_init_flag_MTL_FLAG_SHARED_RX_QUEUE; + const MTL_FLAG_PHC2SYS_ENABLE = + sys::mtl_init_flag_MTL_FLAG_PHC2SYS_ENABLE; + const MTL_FLAG_VIRTIO_USER = + sys::mtl_init_flag_MTL_FLAG_VIRTIO_USER; + const MTL_FLAG_DEV_AUTO_START_STOP = + sys::mtl_init_flag_MTL_FLAG_DEV_AUTO_START_STOP; + const MTL_FLAG_CNI_THREAD = + sys::mtl_init_flag_MTL_FLAG_CNI_THREAD; + const MTL_FLAG_ENABLE_HW_TIMESTAMP = + sys::mtl_init_flag_MTL_FLAG_ENABLE_HW_TIMESTAMP; + const MTL_FLAG_NIC_RX_PROMISCUOUS = + sys::mtl_init_flag_MTL_FLAG_NIC_RX_PROMISCUOUS; + const MTL_FLAG_PTP_UNICAST_ADDR = + sys::mtl_init_flag_MTL_FLAG_PTP_UNICAST_ADDR; + const MTL_FLAG_RX_MONO_POOL = + sys::mtl_init_flag_MTL_FLAG_RX_MONO_POOL; + const MTL_FLAG_TASKLET_TIME_MEASURE = + sys::mtl_init_flag_MTL_FLAG_TASKLET_TIME_MEASURE; + const MTL_FLAG_AF_XDP_ZC_DISABLE = + sys::mtl_init_flag_MTL_FLAG_AF_XDP_ZC_DISABLE; + const MTL_FLAG_TX_MONO_POOL = + sys::mtl_init_flag_MTL_FLAG_TX_MONO_POOL; + const MTL_FLAG_DISABLE_SYSTEM_RX_QUEUES = + sys::mtl_init_flag_MTL_FLAG_DISABLE_SYSTEM_RX_QUEUES; + const MTL_FLAG_PTP_SOURCE_TSC = + sys::mtl_init_flag_MTL_FLAG_PTP_SOURCE_TSC; + const MTL_FLAG_TX_NO_CHAIN = + sys::mtl_init_flag_MTL_FLAG_TX_NO_CHAIN; + const MTL_FLAG_TX_NO_BURST_CHK = + sys::mtl_init_flag_MTL_FLAG_TX_NO_BURST_CHK; + const MTL_FLAG_RX_USE_CNI = + sys::mtl_init_flag_MTL_FLAG_RX_USE_CNI; + const MTL_FLAG_RX_UDP_PORT_ONLY = + sys::mtl_init_flag_MTL_FLAG_RX_UDP_PORT_ONLY; + } +} + +pub struct MtlInitParams { + net_devs: Vec, + dma_devs: Vec, + lcores: Option, + log_level: MtlLogLevel, + rss_mode: MtlRssMode, + iova_mode: MtlIovaMode, + flags: MtlFlags, +} + +impl MtlInitParams { + pub fn new() -> MtlInitParams { + MtlInitParams { + net_devs: Vec::new(), + dma_devs: Vec::new(), + lcores: None, + log_level: MtlLogLevel::Info, + rss_mode: MtlRssMode::None, + iova_mode: MtlIovaMode::Auto, + flags: MtlFlags::empty(), + } + } + pub fn add_netdev(&mut self, netdev: MtlNetDev) { + self.net_devs.push(netdev); + } + pub fn add_dma_dev(&mut self, dma_dev: String) { + self.dma_devs.push(dma_dev); + } + pub fn set_lcores(&mut self, lcores: String) { + self.lcores = Some(lcores); + } + pub fn set_log_level(&mut self, log_level: MtlLogLevel) { + self.log_level = log_level; + } + pub fn set_rss_mode(&mut self, rss_mode: MtlRssMode) { + self.rss_mode = rss_mode; + } + pub fn set_iova_mode(&mut self, iova_mode: MtlIovaMode) { + self.iova_mode = iova_mode; + } + pub fn set_flags(&mut self, flags: MtlFlags) { + self.flags = flags; + } +} + +pub struct Mtl { + handle: sys::mtl_handle, +} + +impl Mtl { + pub fn new(params: &MtlInitParams) -> Result { + let num_ports = params.net_devs.len(); + if num_ports > 8 || num_ports == 0 { + return Err("Invalid number of netdevs"); + } + + // Create an uninitialized instance of mtl_init_params and zero out the memory + let mut c_param: MaybeUninit = MaybeUninit::uninit(); + unsafe { + std::ptr::write_bytes(c_param.as_mut_ptr(), 0, 1); + } + + // Fill the params + unsafe { + let c_param = &mut *c_param.as_mut_ptr(); + c_param.num_ports = num_ports as _; + for (i, net_dev) in params.net_devs.iter().enumerate() { + let port_bytes: Vec = net_dev + .get_port() + .as_bytes() + .iter() + .cloned() + .map(|b| b as i8) // Convert u8 to i8 + .chain(std::iter::repeat(0)) // Pad with zeros if needed + .take(64) // Take only up to 64 elements + .collect(); + c_param.port[i].copy_from_slice(&port_bytes); + + c_param.pmd[i] = net_dev.get_pmd() as _; + c_param.net_proto[i] = net_dev.get_net_proto() as _; + if let Some(ip) = net_dev.get_sip_addr() { + c_param.sip_addr[i] = ip.octets(); + } + if let Some(ip) = net_dev.get_netmask() { + c_param.netmask[i] = ip.octets(); + } + if let Some(ip) = net_dev.get_gateway() { + c_param.gateway[i] = ip.octets(); + } + } + for (i, dma_dev) in params.dma_devs.iter().enumerate() { + let port_bytes: Vec = dma_dev + .as_bytes() + .iter() + .cloned() + .map(|b| b as i8) // Convert u8 to i8 + .chain(std::iter::repeat(0)) // Pad with zeros if needed + .take(64) // Take only up to 64 elements + .collect(); + c_param.dma_dev_port[i].copy_from_slice(&port_bytes); + c_param.num_dma_dev_port += 1; + } + + c_param.log_level = params.log_level as _; + c_param.rss_mode = params.rss_mode as _; + c_param.iova_mode = params.iova_mode as _; + if let Some(lcores) = ¶ms.lcores { + c_param.lcores = lcores.as_ptr() as _; + } + c_param.flags = params.flags.bits(); + } + + let mut c_param = unsafe { c_param.assume_init() }; + + let handle = unsafe { sys::mtl_init(&mut c_param as *mut _) }; + if handle == null_mut() { + Err("Failed to initialize MTL") + } else { + Ok(Mtl { handle }) + } + } +} + +impl Drop for Mtl { + fn drop(&mut self) { + unsafe { + sys::mtl_uninit(self.handle); + } + } +} diff --git a/rust/src/imtl/netdev.rs b/rust/src/imtl/netdev.rs new file mode 100644 index 000000000..21e5758a6 --- /dev/null +++ b/rust/src/imtl/netdev.rs @@ -0,0 +1,99 @@ +use std::net::Ipv4Addr; + +#[derive(Copy, Clone)] +pub enum MtlNetProto { + Static = 0, + Dhcp, +} + +#[derive(Copy, Clone)] +pub enum MtlPmdType { + DpdkPmd = 0, + DpdkAfXdp, + DpdkAfPacket, + KernelSocket, + AfXdp, +} + +pub struct MtlNetDev { + port: String, + net_proto: MtlNetProto, + pmd: MtlPmdType, + sip_addr: Option, + netmask: Option, + gateway: Option, + tx_queues_cnt: u16, + rx_queues_cnt: u16, + xdp_start_queue: u8, +} + +impl MtlNetDev { + pub fn new( + port: String, + net_proto: MtlNetProto, + pmd: MtlPmdType, + sip_addr: Option, + netmask: Option, + gateway: Option, + tx_queues_cnt: u16, + rx_queues_cnt: u16, + xdp_start_queue: u8, + ) -> MtlNetDev { + MtlNetDev { + port: port, + net_proto: net_proto, + pmd: pmd, + sip_addr: sip_addr, + netmask: netmask, + gateway: gateway, + tx_queues_cnt: tx_queues_cnt, + rx_queues_cnt: rx_queues_cnt, + xdp_start_queue: xdp_start_queue, + } + } + + pub fn get_port(&self) -> &str { + &self.port + } + + pub fn get_net_proto(&self) -> MtlNetProto { + self.net_proto + } + + pub fn get_pmd(&self) -> MtlPmdType { + self.pmd + } + + pub fn get_sip_addr(&self) -> Option { + self.sip_addr + } + + pub fn get_netmask(&self) -> Option { + self.netmask + } + pub fn get_gateway(&self) -> Option { + self.gateway + } + + pub fn get_tx_queues_cnt(&self) -> u16 { + self.tx_queues_cnt + } + + pub fn get_rx_queues_cnt(&self) -> u16 { + self.rx_queues_cnt + } + + pub fn get_xdp_start_queue(&self) -> u8 { + self.xdp_start_queue + } + + pub fn bind_pmd(&self) -> Result<(), String> { + // TODO + Ok(()) + } + + pub fn bind_kernel(&self) -> Result<(), String> { + // TODO + Ok(()) + } +} diff --git a/rust/src/imtl/pipeline/mod.rs b/rust/src/imtl/pipeline/mod.rs index 9b3e21c1f..d7a15800f 100644 --- a/rust/src/imtl/pipeline/mod.rs +++ b/rust/src/imtl/pipeline/mod.rs @@ -1,2 +1,2 @@ use sys; -use sys::pipeline; \ No newline at end of file +use sys::pipeline;