rust_rsm/net_ext/
pktbuf.rs

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///pkt_buf_handle_t, packet Buffer Handle
15#[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
105///pkt_global_cb_t:全局packet buffer分配控制块
106struct 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    //分配一个Buffer
119    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    ///释放Buf
144    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
193///外部接口,初始化Packet Buffer
194pub 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}
230///allocate_pkt_buf 申请一个pkt_buf,尺寸固定,buf_type参见PktBufType常量
231pub 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
240///free_pkt_buf 释放一个pkt_buf,尺寸固定
241fn 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}