1use alloc::{boxed::Box, sync::Arc, vec, vec::Vec};
2use core::ptr::NonNull;
3
4use spin::Mutex;
5
6use crate::{DevError, DevResult};
7
8pub struct NetBufPtr {
10 raw_ptr: NonNull<u8>,
12 buf_ptr: NonNull<u8>,
14 len: usize,
15}
16
17impl NetBufPtr {
18 pub fn new(raw_ptr: NonNull<u8>, buf_ptr: NonNull<u8>, len: usize) -> Self {
20 Self {
21 raw_ptr,
22 buf_ptr,
23 len,
24 }
25 }
26
27 pub fn raw_ptr<T>(&self) -> *mut T {
29 self.raw_ptr.as_ptr() as *mut T
30 }
31
32 pub fn packet_len(&self) -> usize {
34 self.len
35 }
36
37 pub fn packet(&self) -> &[u8] {
39 unsafe { core::slice::from_raw_parts(self.buf_ptr.as_ptr() as *const u8, self.len) }
40 }
41
42 pub fn packet_mut(&mut self) -> &mut [u8] {
44 unsafe { core::slice::from_raw_parts_mut(self.buf_ptr.as_ptr(), self.len) }
45 }
46}
47
48const MIN_BUFFER_LEN: usize = 1526;
49const MAX_BUFFER_LEN: usize = 65535;
50
51pub type NetBufBox = Box<NetBuf>;
53
54pub struct NetBuf {
72 header_len: usize,
73 packet_len: usize,
74 capacity: usize,
75 buf_ptr: NonNull<u8>,
76 pool_offset: usize,
77 pool: Arc<NetBufPool>,
78}
79
80unsafe impl Send for NetBuf {}
81unsafe impl Sync for NetBuf {}
82
83impl NetBuf {
84 const unsafe fn get_slice(&self, start: usize, len: usize) -> &[u8] {
85 unsafe { core::slice::from_raw_parts(self.buf_ptr.as_ptr().add(start), len) }
86 }
87
88 const unsafe fn get_slice_mut(&mut self, start: usize, len: usize) -> &mut [u8] {
89 unsafe { core::slice::from_raw_parts_mut(self.buf_ptr.as_ptr().add(start), len) }
90 }
91
92 pub const fn capacity(&self) -> usize {
94 self.capacity
95 }
96
97 pub const fn header_len(&self) -> usize {
99 self.header_len
100 }
101
102 pub const fn header(&self) -> &[u8] {
104 unsafe { self.get_slice(0, self.header_len) }
105 }
106
107 pub const fn packet(&self) -> &[u8] {
109 unsafe { self.get_slice(self.header_len, self.packet_len) }
110 }
111
112 pub const fn packet_mut(&mut self) -> &mut [u8] {
114 unsafe { self.get_slice_mut(self.header_len, self.packet_len) }
115 }
116
117 pub const fn packet_with_header(&self) -> &[u8] {
119 unsafe { self.get_slice(0, self.header_len + self.packet_len) }
120 }
121
122 pub const fn raw_buf(&self) -> &[u8] {
124 unsafe { self.get_slice(0, self.capacity) }
125 }
126
127 pub const fn raw_buf_mut(&mut self) -> &mut [u8] {
129 unsafe { self.get_slice_mut(0, self.capacity) }
130 }
131
132 pub fn set_header_len(&mut self, header_len: usize) {
134 debug_assert!(header_len + self.packet_len <= self.capacity);
135 self.header_len = header_len;
136 }
137
138 pub fn set_packet_len(&mut self, packet_len: usize) {
140 debug_assert!(self.header_len + packet_len <= self.capacity);
141 self.packet_len = packet_len;
142 }
143
144 pub fn into_buf_ptr(mut self: Box<Self>) -> NetBufPtr {
146 let buf_ptr = self.packet_mut().as_mut_ptr();
147 let len = self.packet_len;
148 NetBufPtr::new(
149 NonNull::new(Box::into_raw(self) as *mut u8).unwrap(),
150 NonNull::new(buf_ptr).unwrap(),
151 len,
152 )
153 }
154
155 pub unsafe fn from_buf_ptr(ptr: NetBufPtr) -> Box<Self> {
162 unsafe { Box::from_raw(ptr.raw_ptr::<Self>()) }
163 }
164}
165
166impl Drop for NetBuf {
167 fn drop(&mut self) {
169 self.pool.dealloc(self.pool_offset);
170 }
171}
172
173pub struct NetBufPool {
177 capacity: usize,
178 buf_len: usize,
179 pool: Vec<u8>,
180 free_list: Mutex<Vec<usize>>,
181}
182
183impl NetBufPool {
184 pub fn new(capacity: usize, buf_len: usize) -> DevResult<Arc<Self>> {
187 if capacity == 0 {
188 return Err(DevError::InvalidParam);
189 }
190 if !(MIN_BUFFER_LEN..=MAX_BUFFER_LEN).contains(&buf_len) {
191 return Err(DevError::InvalidParam);
192 }
193
194 let pool = vec![0; capacity * buf_len];
195 let mut free_list = Vec::with_capacity(capacity);
196 for i in 0..capacity {
197 free_list.push(i * buf_len);
198 }
199 Ok(Arc::new(Self {
200 capacity,
201 buf_len,
202 pool,
203 free_list: Mutex::new(free_list),
204 }))
205 }
206
207 pub const fn capacity(&self) -> usize {
209 self.capacity
210 }
211
212 pub const fn buffer_len(&self) -> usize {
214 self.buf_len
215 }
216
217 pub fn alloc(self: &Arc<Self>) -> Option<NetBuf> {
221 let pool_offset = self.free_list.lock().pop()?;
222 let buf_ptr =
223 unsafe { NonNull::new(self.pool.as_ptr().add(pool_offset) as *mut u8).unwrap() };
224 Some(NetBuf {
225 header_len: 0,
226 packet_len: 0,
227 capacity: self.buf_len,
228 buf_ptr,
229 pool_offset,
230 pool: Arc::clone(self),
231 })
232 }
233
234 pub fn alloc_boxed(self: &Arc<Self>) -> Option<NetBufBox> {
238 Some(Box::new(self.alloc()?))
239 }
240
241 fn dealloc(&self, pool_offset: usize) {
245 debug_assert_eq!(pool_offset % self.buf_len, 0);
246 self.free_list.lock().push(pool_offset);
247 }
248}