Skip to main content

axdriver_net/
ixgbe.rs

1use alloc::{collections::VecDeque, sync::Arc};
2use core::{convert::From, mem::ManuallyDrop, ptr::NonNull};
3
4use axdriver_base::{BaseDriverOps, DevError, DevResult, DeviceType};
5pub use ixgbe_driver::{INTEL_82599, INTEL_VEND, IxgbeHal, PhysAddr};
6use ixgbe_driver::{IxgbeDevice, IxgbeError, IxgbeNetBuf, MemPool, NicDevice};
7use log::*;
8
9use crate::{EthernetAddress, NetBufPtr, NetDriverOps};
10
11const RECV_BATCH_SIZE: usize = 64;
12const RX_BUFFER_SIZE: usize = 1024;
13const MEM_POOL: usize = 4096;
14const MEM_POOL_ENTRY_SIZE: usize = 2048;
15
16/// The ixgbe NIC device driver.
17///
18/// `QS` is the ixgbe queue size, `QN` is the ixgbe queue num.
19pub struct IxgbeNic<H: IxgbeHal, const QS: usize, const QN: u16> {
20    inner: IxgbeDevice<H, QS>,
21    mem_pool: Arc<MemPool>,
22    rx_buffer_queue: VecDeque<NetBufPtr>,
23}
24
25unsafe impl<H: IxgbeHal, const QS: usize, const QN: u16> Sync for IxgbeNic<H, QS, QN> {}
26unsafe impl<H: IxgbeHal, const QS: usize, const QN: u16> Send for IxgbeNic<H, QS, QN> {}
27
28impl<H: IxgbeHal, const QS: usize, const QN: u16> IxgbeNic<H, QS, QN> {
29    /// Creates a net ixgbe NIC instance and initialize, or returns a error if
30    /// any step fails.
31    pub fn init(base: usize, len: usize) -> DevResult<Self> {
32        let mem_pool = MemPool::allocate::<H>(MEM_POOL, MEM_POOL_ENTRY_SIZE)
33            .map_err(|_| DevError::NoMemory)?;
34        let inner = IxgbeDevice::<H, QS>::init(base, len, QN, QN, &mem_pool).map_err(|err| {
35            error!("Failed to initialize ixgbe device: {err:?}");
36            DevError::BadState
37        })?;
38
39        let rx_buffer_queue = VecDeque::with_capacity(RX_BUFFER_SIZE);
40        Ok(Self {
41            inner,
42            mem_pool,
43            rx_buffer_queue,
44        })
45    }
46}
47
48impl<H: IxgbeHal, const QS: usize, const QN: u16> BaseDriverOps for IxgbeNic<H, QS, QN> {
49    fn device_name(&self) -> &str {
50        self.inner.get_driver_name()
51    }
52
53    fn device_type(&self) -> DeviceType {
54        DeviceType::Net
55    }
56}
57
58impl<H: IxgbeHal, const QS: usize, const QN: u16> NetDriverOps for IxgbeNic<H, QS, QN> {
59    fn mac_address(&self) -> EthernetAddress {
60        EthernetAddress(self.inner.get_mac_addr())
61    }
62
63    fn rx_queue_size(&self) -> usize {
64        QS
65    }
66
67    fn tx_queue_size(&self) -> usize {
68        QS
69    }
70
71    fn can_receive(&self) -> bool {
72        !self.rx_buffer_queue.is_empty() || self.inner.can_receive(0).unwrap()
73    }
74
75    fn can_transmit(&self) -> bool {
76        // Default implementation is return true forever.
77        self.inner.can_send(0).unwrap()
78    }
79
80    fn recycle_rx_buffer(&mut self, rx_buf: NetBufPtr) -> DevResult {
81        let rx_buf = ixgbe_ptr_to_buf(rx_buf, &self.mem_pool)?;
82        drop(rx_buf);
83        Ok(())
84    }
85
86    fn recycle_tx_buffers(&mut self) -> DevResult {
87        self.inner
88            .recycle_tx_buffers(0)
89            .map_err(|_| DevError::BadState)?;
90        Ok(())
91    }
92
93    fn receive(&mut self) -> DevResult<NetBufPtr> {
94        if !self.can_receive() {
95            return Err(DevError::Again);
96        }
97        if !self.rx_buffer_queue.is_empty() {
98            // RX buffer have received packets.
99            Ok(self.rx_buffer_queue.pop_front().unwrap())
100        } else {
101            let f = |rx_buf| {
102                let rx_buf = NetBufPtr::from(rx_buf);
103                self.rx_buffer_queue.push_back(rx_buf);
104            };
105
106            // RX queue is empty, receive from ixgbe NIC.
107            match self.inner.receive_packets(0, RECV_BATCH_SIZE, f) {
108                Ok(recv_nums) => {
109                    if recv_nums == 0 {
110                        // No packet is received, it is impossible things.
111                        panic!("Error: No receive packets.")
112                    } else {
113                        Ok(self.rx_buffer_queue.pop_front().unwrap())
114                    }
115                }
116                Err(e) => match e {
117                    IxgbeError::NotReady => Err(DevError::Again),
118                    _ => Err(DevError::BadState),
119                },
120            }
121        }
122    }
123
124    fn transmit(&mut self, tx_buf: NetBufPtr) -> DevResult {
125        let tx_buf = ixgbe_ptr_to_buf(tx_buf, &self.mem_pool)?;
126        match self.inner.send(0, tx_buf) {
127            Ok(_) => Ok(()),
128            Err(err) => match err {
129                IxgbeError::QueueFull => Err(DevError::Again),
130                _ => panic!("Unexpected err: {:?}", err),
131            },
132        }
133    }
134
135    fn alloc_tx_buffer(&mut self, size: usize) -> DevResult<NetBufPtr> {
136        let tx_buf = IxgbeNetBuf::alloc(&self.mem_pool, size).map_err(|_| DevError::NoMemory)?;
137        Ok(NetBufPtr::from(tx_buf))
138    }
139}
140
141impl From<IxgbeNetBuf> for NetBufPtr {
142    fn from(buf: IxgbeNetBuf) -> Self {
143        // Use `ManuallyDrop` to avoid drop `tx_buf`.
144        let mut buf = ManuallyDrop::new(buf);
145        // In ixgbe, `raw_ptr` is the pool entry, `buf_ptr` is the packet ptr, `len` is
146        // packet len to avoid too many dynamic memory allocation.
147        let buf_ptr = buf.packet_mut().as_mut_ptr();
148        Self::new(
149            NonNull::new(buf.pool_entry() as *mut u8).unwrap(),
150            NonNull::new(buf_ptr).unwrap(),
151            buf.packet_len(),
152        )
153    }
154}
155
156// Converts a `NetBufPtr` to `IxgbeNetBuf`.
157fn ixgbe_ptr_to_buf(ptr: NetBufPtr, pool: &Arc<MemPool>) -> DevResult<IxgbeNetBuf> {
158    IxgbeNetBuf::construct(ptr.raw_ptr::<()>().addr(), pool, ptr.packet_len())
159        .map_err(|_| DevError::BadState)
160}