1use crate::error::{DpdkError, DpdkResult};
2use std::ffi::CString;
3
4pub struct Eal;
5
6impl Eal {
7 pub fn init(args: &[&str]) -> DpdkResult<Self> {
8 let c_args: Result<Vec<CString>, _> = args.iter().map(|s| CString::new(*s)).collect();
9 let c_args = c_args.map_err(|_| DpdkError::EalInitFailed(-1))?;
10 let mut argv: Vec<*mut i8> = c_args.iter().map(|s| s.as_ptr() as *mut i8).collect();
11
12 let result = unsafe {
13 dpdk_sys::rte_eal_init(argv.len() as i32, argv.as_mut_ptr())
14 };
15
16 if result < 0 {
17 return Err(DpdkError::EalInitFailed(result));
18 }
19
20 Ok(Self)
21 }
22}
23
24impl Drop for Eal {
25 fn drop(&mut self) {
26 unsafe {
27 dpdk_sys::rte_eal_cleanup();
28 }
29 }
30}
31
32#[cfg(test)]
33mod tests {
34 use super::*;
35 use serial_test::serial;
36
37 #[test]
38 #[serial(eal)]
39 fn test_eal_init_and_cleanup_lifecycle() {
40 dpdk_sys::stub_eal_reset();
41
42 let eal = Eal::init(&["test-app", "-l", "0", "-n", "4"])
43 .expect("Eal::init should succeed");
44
45 assert!(
46 dpdk_sys::stub_eal_is_initialized(),
47 "EAL should be initialized after Eal::init()"
48 );
49
50 drop(eal);
51
52 assert!(
53 dpdk_sys::stub_eal_is_cleaned_up(),
54 "EAL should be in cleaned-up state after Eal is dropped"
55 );
56
57 dpdk_sys::stub_eal_reset();
58 }
59
60 #[test]
61 #[serial(eal)]
62 fn test_eal_must_be_alive_for_mempool_creation() {
63 dpdk_sys::stub_eal_reset();
64
65 let _eal = Eal::init(&["test-app", "-l", "0", "-n", "4"])
66 .expect("Eal::init should succeed");
67 assert!(dpdk_sys::stub_eal_is_initialized());
68
69 let pool_name = std::ffi::CString::new("test_pool").unwrap();
70 let ptr = unsafe {
71 dpdk_sys::rte_pktmbuf_pool_create(
72 pool_name.as_ptr(),
73 1024,
74 256,
75 0,
76 dpdk_sys::RTE_MBUF_DEFAULT_BUF_SIZE,
77 0,
78 )
79 };
80 assert!(!ptr.is_null(), "Mempool creation should succeed while EAL is alive");
81 unsafe { dpdk_sys::rte_mempool_free(ptr) };
82
83 drop(_eal);
84 dpdk_sys::stub_eal_reset();
85 }
86
87 #[test]
88 #[serial(eal)]
89 fn test_mempool_create_fails_after_eal_cleanup() {
90 dpdk_sys::stub_eal_reset();
91
92 {
95 let _eal = Eal::init(&["test-app", "-l", "0", "-n", "4"])
96 .expect("Eal::init should succeed");
97 }
98
99 assert!(
100 dpdk_sys::stub_eal_is_cleaned_up(),
101 "EAL should be in cleaned-up state after Eal is dropped"
102 );
103
104 let pool_name = std::ffi::CString::new("orphan_pool").unwrap();
107 let ptr = unsafe {
108 dpdk_sys::rte_pktmbuf_pool_create(
109 pool_name.as_ptr(),
110 1024,
111 256,
112 0,
113 dpdk_sys::RTE_MBUF_DEFAULT_BUF_SIZE,
114 0,
115 )
116 };
117 assert!(
118 ptr.is_null(),
119 "Mempool creation should fail (return NULL) when EAL is cleaned up — \
120 with real DPDK this segfaults because rte_config->mem_config is NULL"
121 );
122
123 dpdk_sys::stub_eal_reset();
124 }
125}