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
16pub 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 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 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 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 match self.inner.receive_packets(0, RECV_BATCH_SIZE, f) {
108 Ok(recv_nums) => {
109 if recv_nums == 0 {
110 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 let mut buf = ManuallyDrop::new(buf);
145 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
156fn 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}