diff --git a/dpdk/src/dev.rs b/dpdk/src/dev.rs index 7febf61d..901cf335 100644 --- a/dpdk/src/dev.rs +++ b/dpdk/src/dev.rs @@ -99,13 +99,13 @@ impl DevIndex { return Err(DevInfoError::InvalidArgument); } val => { - let unknown = match StandardErrno::parse_i32(val) { + let _unknown = match StandardErrno::parse_i32(val) { Ok(standard) => { return Err(DevInfoError::UnknownStandard(standard)); } Err(unknown) => unknown, }; - let unknown = match NegStandardErrno::parse_i32(val) { + let _unknown = match NegStandardErrno::parse_i32(val) { Ok(standard) => { return Err(DevInfoError::UnknownNegStandard(standard)); } @@ -779,9 +779,9 @@ pub struct StartedDev { pub info: DevInfo, /// The configuration of the device. pub config: DevConfig, - pub(crate) rx_queues: Vec, - pub(crate) tx_queues: Vec, - pub(crate) hairpin_queues: Vec, + pub rx_queues: Vec, + pub tx_queues: Vec, + pub hairpin_queues: Vec, } impl Dev { diff --git a/dpdk/src/flow/mod.rs b/dpdk/src/flow/mod.rs index ee67e4d0..4d3c6277 100644 --- a/dpdk/src/flow/mod.rs +++ b/dpdk/src/flow/mod.rs @@ -7,7 +7,6 @@ use crate::queue::tx::TxQueueIndex; use alloc::vec::Vec; use core::fmt::Debug; use core::marker::PhantomData; -use core::net::Ipv4Addr; use core::ptr::NonNull; use dpdk_sys::*; use net; @@ -28,8 +27,8 @@ pub struct FlowRule { _phantom: PhantomData, } -const MAX_PATTERN_NUM: usize = 16; -const MAX_ACTION_NUM: usize = 16; +pub const MAX_PATTERN_NUM: usize = 16; +pub const MAX_ACTION_NUM: usize = 16; /// TODO: convert numbers to constant references to `rte_flow_item_type` #[derive(Debug)] @@ -244,7 +243,7 @@ pub enum FlowMatch { #[derive(Debug, Clone, Copy)] pub struct MatchTag { /// NOTE: can't be more than 2^24 - 1 - data: u32, + pub data: u32, } /// A metadata value to match on. @@ -261,7 +260,7 @@ pub struct Vni(pub u32); // TODO: expose remaining fields pub struct VxlanHeader { - vni: Vni, + pub vni: Vni, } pub struct UdpPort(pub u16); @@ -269,26 +268,26 @@ pub struct TcpPort(pub u16); // TODO: expose remaining fields pub struct TcpHeader { - src_port: TcpPort, - dst_port: TcpPort, + pub src_port: TcpPort, + pub dst_port: TcpPort, } // TODO: expose remaining fields pub struct UdpHeader { - src_port: UdpPort, - dst_port: UdpPort, + pub src_port: UdpPort, + pub dst_port: UdpPort, } // TODO: expose remaining fields pub struct Ipv6Header { - src: core::net::Ipv6Addr, - dst: core::net::Ipv6Addr, + pub src: core::net::Ipv6Addr, + pub dst: core::net::Ipv6Addr, } // TODO: expose remaining fields pub struct Ipv4Header { - src: Ipv4Addr, - dst: Ipv4Addr, + pub src: core::net::Ipv4Addr, + pub dst: core::net::Ipv4Addr, } pub struct FlowSpec { @@ -359,9 +358,9 @@ impl From for rte_flow_item_eth { pub struct VlanTci(pub u16); pub struct VlanHeader { - ether_type: EtherType, - tci: VlanTci, - inner_ether_type: EtherType, + pub ether_type: EtherType, + pub tci: VlanTci, + pub inner_ether_type: EtherType, // TODO: figure out why DPDK lets you spec TCI twice } @@ -688,13 +687,19 @@ pub enum FlowAction { // Nat64, } +/// Modify a field #[repr(u32)] pub enum FieldModificationOperation { + /// Set a field Set = rte_flow_modify_op::RTE_FLOW_MODIFY_SET, + /// Add to a field Add = rte_flow_modify_op::RTE_FLOW_MODIFY_ADD, + /// Subtract from a field Subtract = rte_flow_modify_op::RTE_FLOW_MODIFY_SUB, } +/// A wrapper around a `rte_flow_action_modify_field` that specifies the +/// field to modify and its new value. #[repr(u32)] pub enum FlowFieldId { /// Start of a packet. @@ -803,41 +808,71 @@ pub enum FlowFieldId { VxlanLastReserved = rte_flow_field_id::RTE_FLOW_FIELD_VXLAN_LAST_RSVD, } +/// A wrapper around a `rte_flow_action_modify_field` that specifies the +/// field to modify and its new value. #[derive(Debug, Clone, Copy)] pub enum SetFlowField { + /// Dest mac MacDst(MacAddr), + /// Source mac MacSrc(MacAddr), + /// Vlan ethertype VlanType(EtherType), + /// Vlan VID VlanVid(net::vlan::Vid), + /// Ethertype EtherType(EtherType), + /// IPv4 DSCP Ipv4Dscp(u8), + /// IPv4 TTL Ipv4Ttl(u8), - Ipv4Src(Ipv4Addr), - Ipv4Dst(Ipv4Addr), + /// Ipv4 source + Ipv4Src(core::net::Ipv4Addr), + /// Ipv4 dest + Ipv4Dst(core::net::Ipv4Addr), + /// Ipv6 DSCP Ipv6Dscp(u8), + /// Ipv6 hop limit (ttl) Ipv6HopLimit(u8), + /// Ipv6 source Ipv6Src(core::net::Ipv6Addr), + /// Ipv6 dest Ipv6Dst(core::net::Ipv6Addr), + /// TCP source port TcpPortSrc(u16), + /// TCP dest port TcpPortDst(u16), + /// TCP seq number TcpSeqNum(u32), + /// TCP ack num TcpAckNum(u32), + /// TCP flags TcpFlags(u16), + /// UDP source port UdpPortSrc(u16), + /// UDP dest port UdpPortDst(u16), + /// VXLAN vni VxlanVni(net::vxlan::Vni), + /// Tag Tag(MatchTag), + /// Metadata Meta(MatchMeta), + /// Ipv4 ECN IpV4Ecn(u8), + /// IPv6 ECN IpV6Ecn(u8), } +/// A wrapper around a `rte_flow_action_modify_field` that specifies the +/// field to modify and its new value. pub struct SetFieldAction { - rule: SetFlowField, - conf: rte_flow_action_modify_field, + pub rule: SetFlowField, + pub conf: rte_flow_action_modify_field, } impl SetFlowField { + /// Converts the `SetFlowField` into a `SetFieldAction`. pub fn to_flow_rule(&self) -> SetFieldAction { let conf = match self { SetFlowField::MacDst(mac_addr) => { @@ -895,11 +930,13 @@ impl Sealed for u32 {} impl Sealed for u64 {} impl Sealed for u128 {} +/// A wrapper around unsigned numbers that specifies they are in big endian order. #[repr(transparent)] pub struct BigEndian(T) where T: UnsignedNum; +/// An unsigned number (e.g. u8 or u32) pub trait UnsignedNum: Sealed {} impl UnsignedNum for T where T: Sealed {} @@ -943,7 +980,3 @@ impl From for BigEndian { BigEndian(x.to_be()) } } - -pub struct JumpAction { - group: u32, -} diff --git a/dpdk/src/lib.rs b/dpdk/src/lib.rs index 9988b140..c2c7d8c7 100644 --- a/dpdk/src/lib.rs +++ b/dpdk/src/lib.rs @@ -26,10 +26,7 @@ //! encourage this practice. #![cfg_attr(not(test), no_std)] #![warn( - missing_docs, clippy::all, - clippy::missing_panics_doc, - clippy::missing_safety_doc )] #![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic)] #![allow(private_bounds)] diff --git a/dpdk/src/mem.rs b/dpdk/src/mem.rs index 0cb672ab..d065f1dd 100644 --- a/dpdk/src/mem.rs +++ b/dpdk/src/mem.rs @@ -345,6 +345,9 @@ impl Drop for PoolInner { } } +/// A DPDK Mbuf (memory buffer) +/// +/// Usually used to hold an ethernet frame. #[repr(transparent)] pub struct Mbuf { pub(crate) raw: NonNull, @@ -376,7 +379,6 @@ impl Mbuf { #[tracing::instrument(level = "trace")] pub(crate) fn new_from_raw(raw: *mut rte_mbuf) -> Option { let raw = match NonNull::new(raw) { - #[cold] None => { warn!("Attempted to create Mbuf from null pointer"); return None; @@ -390,6 +392,7 @@ impl Mbuf { }) } + /// Get an immutable ref to the raw data of an Mbuf pub fn raw_data(&self) -> &[u8] { let pkt_data_start = unsafe { (self.raw.as_ref().buf_addr as *const u8) @@ -403,6 +406,7 @@ impl Mbuf { } } + /// Get a mutable ref to the raw data of an Mbuf pub fn raw_data_mut(&mut self) -> &mut [u8] { unsafe { let data_start = self diff --git a/dpdk/src/queue/hairpin.rs b/dpdk/src/queue/hairpin.rs index 931d99a5..89b51cbd 100644 --- a/dpdk/src/queue/hairpin.rs +++ b/dpdk/src/queue/hairpin.rs @@ -1,6 +1,6 @@ //! Hairpin queue configuration and management. use super::{rx, tx}; -use crate::dev::{Dev, DevConfig, DevInfo}; +use crate::dev::{Dev, DevInfo}; use crate::queue::rx::RxQueue; use crate::queue::tx::{TxQueue}; use dpdk_sys::*; @@ -99,7 +99,7 @@ impl HairpinQueue { Ok(HairpinQueue { rx, tx, peering }) } - pub(crate) fn start(self) -> HairpinQueue { + pub fn start(self) -> HairpinQueue { let rx = match self.rx.start() { Ok(rx) => rx, Err(_) => todo!(), diff --git a/dpdk/src/queue/mod.rs b/dpdk/src/queue/mod.rs index 610f183e..9eb685ba 100644 --- a/dpdk/src/queue/mod.rs +++ b/dpdk/src/queue/mod.rs @@ -3,10 +3,14 @@ pub mod rx; pub mod tx; pub mod hairpin; +/// The possible states of a DPDK queue #[derive(Debug)] pub enum QueueState { + /// An unconfigured queue Unconfigured, + /// A stopped queue Stopped, + /// A started queue Started, } diff --git a/dpdk/src/queue/rx.rs b/dpdk/src/queue/rx.rs index ba1559ef..7e9e0a5a 100644 --- a/dpdk/src/queue/rx.rs +++ b/dpdk/src/queue/rx.rs @@ -4,11 +4,8 @@ use crate::dev::DevIndex; use crate::mem::Mbuf; use crate::socket::SocketId; use crate::{dev, mem, socket}; -use core::marker::PhantomData; -use core::ptr::NonNull; -use etherparse::LinkSlice::Ethernet2; use dpdk_sys::*; -use tracing::{debug, info, trace, warn}; +use tracing::{trace, warn}; #[repr(transparent)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -55,12 +52,6 @@ pub struct RxQueueConfig { pub pool: mem::PoolHandle, } -/// Error type for receive queue configuration failures. -#[derive(Debug)] -pub struct ConfigError { - err: errno::Errno, -} - /// Error type for receive queue configuration failures. #[derive(Debug)] pub enum ConfigFailure { @@ -76,6 +67,7 @@ pub enum ConfigFailure { InvalidSocket(errno::Errno), } +/// DPDK rx queue #[derive(Debug)] pub struct RxQueue { pub(crate) config: RxQueueConfig, @@ -93,7 +85,7 @@ impl RxQueue { /// associated with the device. pub(crate) fn configure(dev: &dev::Dev, config: RxQueueConfig) -> Result { let socket_id = SocketId::try_from(config.socket_preference) - .map_err(|err| ConfigFailure::InvalidSocket(errno::Errno(errno::NEG_EINVAL)))?; + .map_err(|_| ConfigFailure::InvalidSocket(errno::Errno(errno::NEG_EINVAL)))?; let rx_conf = rte_eth_rxconf { offloads: dev.info.inner.rx_queue_offload_capa, @@ -233,25 +225,3 @@ pub enum RxQueueState { /// TODO Started, } - - - -fn test_burst(queue: RxQueue) { - let mut queue = queue; - let pkts = queue.receive(); - for pkt in pkts { - let parsed_packet = etherparse::SlicedPacket::from_ethernet(pkt.raw_data()).expect("Failed to parse packet"); - match parsed_packet.link { - None => { - debug!("Failed to parse packet link header"); - } - Some(Ethernet2(pkt)) => { - pkt.ether_type(); - } - pkt => { - debug!("Unsupported packet type {pkt:?}"); - } - } - // info!("Received packet: {:?}", pkt); - } -} \ No newline at end of file diff --git a/net/src/lib.rs b/net/src/lib.rs index a6fa5984..beaf3c56 100644 --- a/net/src/lib.rs +++ b/net/src/lib.rs @@ -7,8 +7,6 @@ extern crate alloc; -use alloc::vec::Vec; - #[cfg(all(kani, feature = "_fake_kani"))] compile_error!("kani should not be used with internal _fake_kani feature."); diff --git a/scratch/src/main.rs b/scratch/src/main.rs index 18fc5583..c94c4d16 100644 --- a/scratch/src/main.rs +++ b/scratch/src/main.rs @@ -1,11 +1,10 @@ use dpdk::dev::TxOffloadConfig; -use dpdk::queue::rx::RxQueue; use dpdk::{dev, eal, mem, queue, socket}; use dpdk_sys::*; use std::ffi::{c_uint, CStr, CString}; use std::fmt::{Debug, Display}; use std::io; -use std::net::{IpAddr, Ipv4Addr}; +use std::net::Ipv4Addr; use std::time::Instant; use tracing::{debug, error, info, trace, warn}; @@ -49,7 +48,6 @@ pub fn fatal_error>(message: T) -> ! { unsafe { rte_exit(1, message_cstring.as_ptr()) } } - const MAX_PATTERN_NUM: usize = 8; #[tracing::instrument(level = "debug")] @@ -231,6 +229,7 @@ fn init_port2(port_id: u16, mbuf_pool: &mut rte_mempool) { }; let mut txq_conf: rte_eth_txconf; + #[allow(unused)] let mut rxq_conf: rte_eth_rxconf = unsafe { std::mem::zeroed() }; let mut dev_info: rte_eth_dev_info = unsafe { std::mem::zeroed() }; @@ -598,28 +597,6 @@ fn generate_ct_flow2(port_id: u16, rx_q: u16, err: &mut rte_flow_error) -> RteFl RteFlow::new(port_id, flow) } -fn meter_stuff(port_id: u16) { - let mut caps = rte_mtr_capabilities::default(); - let mut err = rte_mtr_error::default(); - let ret = unsafe { rte_mtr_capabilities_get(port_id, &mut caps, &mut err) }; - - if ret != 0 || !err.message.is_null() { - let io_error_msg = io::Error::from_raw_os_error(ret).to_string(); - let err_msg = if err.message.is_null() { - format!("Failed to get meter capabilities: {io_error_msg}",) - } else { - let err_str = unsafe { CStr::from_ptr(err.message) }; - format!( - "Failed to get meter capabilities: {err_str}; {io_error_msg}", - err_str = err_str.to_str().unwrap() - ) - }; - fatal_error(err_msg.as_str()); - } - - info!("Meter capabilities: {caps:?}"); -} - fn main() { eal_main(); } @@ -752,34 +729,32 @@ fn eal_main() { my_dev.start().unwrap(); let mut start = Instant::now(); - - let flows: Vec<_> = (0..50_000_000) - .map(|i: u32| { - if i % 100_000 == 0 { - let stop = Instant::now(); - let elapsed = stop.duration_since(start); - warn!( - "{i} rules installed, rate: {rate:.1}k / second", - rate = 100.0 / elapsed.as_secs_f64() - ); - start = Instant::now(); - } - let src = Ipv4Addr::from(i); - let dst = Ipv4Addr::from(rand::random::()); - let mut err = rte_flow_error::default(); - generate_modify_field_flow( - i, - my_dev.info.index().0, - 0, - src, - Ipv4Addr::new(255, 255, 255, 255), - dst, - Ipv4Addr::new(255, 255, 255, 255), - &mut err, - ) - }) - .collect(); - + + for i in 0..50_000_000 { + if i % 100_000 == 0 { + let stop = Instant::now(); + let elapsed = stop.duration_since(start); + warn!( + "{i} rules installed, rate: {rate:.1}k / second", + rate = 100.0 / elapsed.as_secs_f64() + ); + start = Instant::now(); + } + let src = Ipv4Addr::from(i); + let dst = Ipv4Addr::from(rand::random::()); + let mut err = rte_flow_error::default(); + generate_modify_field_flow( + i, + my_dev.info.index().0, + 0, + src, + Ipv4Addr::new(255, 255, 255, 255), + dst, + Ipv4Addr::new(255, 255, 255, 255), + &mut err, + ); + } + warn!("Flows created"); // for i in 0..2000 { @@ -814,6 +789,7 @@ fn eal_main() { }); } +#[allow(clippy::too_many_arguments)] #[tracing::instrument(level = "debug")] fn generate_modify_field_flow( i: u32, @@ -825,9 +801,11 @@ fn generate_modify_field_flow( dest_mask: Ipv4Addr, err: &mut rte_flow_error, ) -> RteFlow { - let mut attr: rte_flow_attr = Default::default(); - attr.group = 99u32; - attr.priority = 9; + let mut attr: rte_flow_attr = rte_flow_attr { + group: 99u32, + priority: 9, + ..Default::default() + }; attr.set_ingress(1); let mut pattern: [rte_flow_item; MAX_PATTERN_NUM] = Default::default(); let mut action: [rte_flow_action; MAX_PATTERN_NUM] = Default::default(); @@ -836,6 +814,7 @@ fn generate_modify_field_flow( pattern[0].type_ = rte_flow_item_type::RTE_FLOW_ITEM_TYPE_ETH; let mut eth_spec = rte_flow_item_eth::default(); + #[allow(unused_unsafe)] unsafe { eth_spec.annon1.hdr.dst_addr = rte_ether_addr { addr_bytes: [ @@ -848,6 +827,7 @@ fn generate_modify_field_flow( ], }; } + #[allow(unused_unsafe)] unsafe { eth_spec.annon1.hdr.src_addr = rte_ether_addr { addr_bytes: [ @@ -863,6 +843,7 @@ fn generate_modify_field_flow( let mut eth_mask = rte_flow_item_eth::default(); + #[allow(unused_unsafe)] unsafe { eth_mask.annon1.hdr.dst_addr = rte_ether_addr { addr_bytes: [0xff; 6], @@ -920,25 +901,6 @@ fn generate_modify_field_flow( let mut ip_dst_value = [0u8; 16]; ip_dst_value[0..4].copy_from_slice(&new_dst_ip.to_bits().to_be_bytes()); - let new_eth_src = [ - rand::random::(), - rand::random::(), - rand::random::(), - rand::random::(), - rand::random::(), - rand::random::(), - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ]; - let new_eth_dst = [ rand::random::(), rand::random::(),