1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3#![allow(non_upper_case_globals)]
4
5use crate::common::{tsidallocator::TsIdAllocator,errcode,spin_lock::spin_lock_t};
6use std::fmt;
7use std::alloc;
8use super::*;
9
10pub mod PktBufType {
11 pub const BufTypeRecv:u16 = 0;
12 pub const BufTypeSend:u16 = 1;
13}
14#[derive(Debug)]
16pub struct pkt_buf_handle_t {
17 buf_id:i32,
18 buf_capacity:u16,
19 buf_type:u16,
20 buf_len:u16,
21 buf_ptr:*mut u8,
22}
23impl pkt_buf_handle_t {
24 pub fn new_zero()->pkt_buf_handle_t {
25 return pkt_buf_handle_t {
26 buf_id:TsIdAllocator::INVALID_ID,
27 buf_capacity:0,
28 buf_type:0,
29 buf_len:0,
30 buf_ptr:std::ptr::null_mut(),
31 }
32 }
33 pub fn len(&self)->usize {
34 return self.buf_len as usize;
35 }
36 pub fn capacity(&self)->usize {
37 return self.buf_capacity as usize;
38 }
39
40 pub fn as_mut_ptr(&mut self)->*mut u8 {
41 return self.buf_ptr
42 }
43 pub fn as_ptr(&self)->*const u8 {
44 return self.buf_ptr
45 }
46 pub fn as_slice(&self)->&[u8] {
47 unsafe {
48 return & (*(self.buf_ptr as *const [u8;MAX_PKT_BUF_SIZE as usize]))[0..self.buf_len as usize]
49 }
50 }
51 pub fn as_mut_slice(&mut self)->&mut [u8] {
52 unsafe {
53 return &mut (*(self.buf_ptr as *mut [u8;MAX_PKT_BUF_SIZE as usize]))[0..self.buf_len as usize]
54 }
55 }
56 pub fn set_len(&mut self,len:usize) {
57 self.buf_len = std::cmp::min(len as u16,self.buf_capacity)
58 }
59
60 pub fn extend_from_slice(&mut self,buf:&[u8]) {
61 if self.buf_len+buf.len() as u16 >self.buf_capacity {
62 return;
63 }
64 unsafe {
65 std::ptr::copy_nonoverlapping(buf.as_ptr(), (self.buf_ptr as usize+self.buf_len as usize) as *mut u8, buf.len());
66 }
67 self.buf_len+=buf.len() as u16;
68 }
69 pub fn is_valid_buffer(&self)->bool {
70 return self.buf_id!=TsIdAllocator::INVALID_ID && self.buf_capacity>0
71 }
72}
73impl fmt::Display for pkt_buf_handle_t {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 write!(f,"id:{},capacity:{},len={},ptr:{:?}",self.buf_id,self.buf_capacity,self.buf_len,self.buf_ptr)
76 }
77}
78
79impl Clone for pkt_buf_handle_t {
80 fn clone(&self)->Self {
81 let mut new_pkt = allocate_pkt_buf(self.buf_type);
82 if !new_pkt.is_valid_buffer() {
83 return Self::new_zero()
84 }
85 new_pkt.buf_len = self.buf_len;
86 unsafe {
87 std::ptr::copy_nonoverlapping(self.buf_ptr, new_pkt.buf_ptr, self.buf_len as usize);
88 }
89
90 return new_pkt;
91 }
92}
93
94impl Drop for pkt_buf_handle_t {
95 fn drop(&mut self) {
96 if self.buf_id==TsIdAllocator::INVALID_ID {
97 return
98 }
99 let res = free_pkt_buf(self.buf_type,self.buf_id as usize);
100 assert_eq!(res,errcode::RESULT_SUCCESS);
101 }
102}
103const MAX_PKT_BUF_COUNT:usize = 65536;
104
105struct pkt_global_cb_t {
107 ids:TsIdAllocator,
108 packet_bufs:*mut [*mut u8;MAX_PKT_BUF_COUNT],
109 buf_used:[bool;MAX_PKT_BUF_COUNT],
110 lock:spin_lock_t,
111 buf_type:u16,
112 capacity:usize,
113 alloc_count:u64,
114 free_count:u64,
115}
116
117impl pkt_global_cb_t {
118 pub fn allocate_pkt_buf(&mut self)->pkt_buf_handle_t {
120 self.lock.lock();
121 let id =self.ids.allocate_id();
122
123 if id==TsIdAllocator::INVALID_ID {
124 self.lock.unlock();
125 return pkt_buf_handle_t::new_zero()
126 }
127 let idx = (id-1) as usize;
128 self.buf_used[idx]=true;
129 self.alloc_count+=1;
130 self.lock.unlock();
131 let handle = pkt_buf_handle_t {
132 buf_id:id,
133 buf_capacity:MAX_PKT_BUF_SIZE,
134 buf_type:self.buf_type,
135 buf_len:0,
136 buf_ptr:unsafe { (&*self.packet_bufs)[idx] },
137 };
138
139
140 return handle
141 }
142
143 fn free_pkt_buf(&mut self,buf_id:usize)->errcode::RESULT {
145 let idx = buf_id-1;
146 self.lock.lock();
147 if self.ids.release_id(buf_id as i32) != errcode::RESULT_SUCCESS {
148 assert!(buf_id>0 && buf_id<self.capacity);
149 self.lock.unlock();
150 return errcode::ERROR_NOT_FOUND;
151 }
152
153 self.buf_used[idx]=false;
154 self.free_count+=1;
155 self.lock.unlock();
156 errcode::RESULT_SUCCESS
157 }
158}
159static mut GlobalRecvPktBufs:Option<pkt_global_cb_t>=None;
160static mut GlobalSendPktBufs:Option<pkt_global_cb_t>=None;
161
162fn get_one_buf_cb(buf_count:usize,buf_type:u16)->Option<pkt_global_cb_t> {
163 let capacity = std::cmp::min(buf_count, MAX_PKT_BUF_COUNT);
164
165 let buf_ptr = unsafe {
166 alloc::alloc_zeroed(alloc::Layout::from_size_align_unchecked(MAX_PKT_BUF_SIZE as usize *capacity, 1))
167 };
168
169 if buf_ptr==std::ptr::null_mut() {
170 return None;
171 }
172 let blocks = unsafe {
173 alloc::alloc_zeroed(alloc::Layout::from_size_align_unchecked(std::mem::size_of::<* mut u8>()*capacity, 1)) as *mut [*mut u8;MAX_PKT_BUF_COUNT]
174 };
175 for i in 0..capacity {
176 unsafe {
177 (&mut *blocks)[i]=(buf_ptr as usize+i*MAX_PKT_BUF_SIZE as usize) as *mut u8;
178 }
179 }
180 let buf_cb = pkt_global_cb_t {
181 ids:TsIdAllocator::new(1,capacity as i32),
182 packet_bufs:blocks,
183 buf_used:[false;MAX_PKT_BUF_COUNT],
184 lock:spin_lock_t::new(),
185 buf_type:buf_type,
186 capacity:capacity,
187 alloc_count:0,
188 free_count:0,
189 };
190 return Some(buf_cb);
191}
192
193pub fn init_pkt_buf(buf_count:usize)->errcode::RESULT {
195
196 let buf_cb1= match get_one_buf_cb(buf_count,PktBufType::BufTypeRecv) {
197 Some(cb)=>cb,
198 None=>return errcode::ERROR_OUTOF_MEM,
199 };
200 let buf_cb2=match get_one_buf_cb(buf_count,PktBufType::BufTypeSend) {
201 Some(cb)=>cb,
202 None=>return errcode::ERROR_OUTOF_MEM,
203 };
204 unsafe {
205 GlobalRecvPktBufs=Some(buf_cb1);
206 GlobalSendPktBufs=Some(buf_cb2);
207 }
208 errcode::RESULT_SUCCESS
209}
210
211fn get_gbuf_ref(buf_type:u16)->Option<&'static mut pkt_global_cb_t> {
212 let cb_ptr = match buf_type {
213 PktBufType::BufTypeRecv=> {
214 match unsafe { &mut GlobalRecvPktBufs } {
215 None=>return None,
216 Some(cb)=>cb,
217 }
218 },
219 PktBufType::BufTypeSend=> {
220 match unsafe { &mut GlobalSendPktBufs } {
221 None=>return None,
222 Some(cb)=>cb,
223 }
224 },
225 _=>return None,
226 };
227
228 return Some(cb_ptr);
229}
230pub fn allocate_pkt_buf(buf_type:u16)->pkt_buf_handle_t {
232 let gbuf = match get_gbuf_ref(buf_type) {
233 None=>return pkt_buf_handle_t::new_zero(),
234 Some(bufs)=>bufs,
235 };
236
237 return gbuf.allocate_pkt_buf()
238}
239
240fn free_pkt_buf(buf_type:u16,buf_id:usize)->errcode::RESULT {
242 let gbuf = match get_gbuf_ref(buf_type) {
243 None=> {
244 assert!(false);
245 return errcode::ERROR_NOT_INITIALIZED;
246 },
247 Some(bufs)=>bufs,
248 };
249 return gbuf.free_pkt_buf(buf_id);
250}
251
252pub fn get_dbg_string()->String {
253 let gbuf = match get_gbuf_ref(PktBufType::BufTypeRecv) {
254 None=>return String::new(),
255 Some(bufs)=>bufs,
256 };
257 let recv_str = format!("Global Recv Packet Buffer, Capacity={},used={},alloc_call={},free_call={}",
258 gbuf.ids.capacity(),gbuf.ids.used_count(),gbuf.alloc_count,gbuf.free_count);
259
260 let sbuf = match get_gbuf_ref(PktBufType::BufTypeSend) {
261 None=> return String::new(),
262 Some(bufs)=>bufs,
263 };
264
265 format!("{},Global Send Packet Buffer, Capacity={},used={},alloc_call={},free_call={}",
266 recv_str,sbuf.ids.capacity(),sbuf.ids.used_count(),sbuf.alloc_count,sbuf.free_count)
267
268}
269pub fn print_stats() {
270 println!("{}",get_dbg_string());
271}