retina_core/memory/
mbuf.rs1use crate::dpdk;
13use crate::memory::mempool::MempoolError;
14use crate::protocols::packet::{Packet, PacketHeader, PacketParseError};
15
16use std::fmt;
17use std::ptr::NonNull;
18use std::slice;
19
20use anyhow::{bail, Result};
21use thiserror::Error;
22
23#[derive(Clone)]
24pub struct Mbuf {
28 raw: NonNull<dpdk::rte_mbuf>,
29}
30
31impl Mbuf {
32 pub(crate) fn new_unchecked(mbuf: *mut dpdk::rte_mbuf) -> Mbuf {
34 unsafe {
35 Mbuf {
36 raw: NonNull::new_unchecked(mbuf),
37 }
38 }
39 }
40
41 pub(crate) fn new(mbuf: *mut dpdk::rte_mbuf) -> Result<Mbuf> {
43 Ok(Mbuf {
44 raw: NonNull::new(mbuf).ok_or(MempoolError::Exhausted)?,
45 })
46 }
47
48 pub(crate) fn from_bytes(data: &[u8], mp: *mut dpdk::rte_mempool) -> Result<Mbuf> {
50 let mut mbuf = unsafe { Mbuf::new(dpdk::rte_pktmbuf_alloc(mp))? };
51 if data.len() <= mbuf.raw().buf_len.into() {
52 mbuf.raw_mut().data_len += data.len() as u16;
53 mbuf.raw_mut().pkt_len += data.len() as u32;
54 unsafe {
55 let src = data.as_ptr();
56 let dst = mbuf.get_data_address(0) as *mut u8;
57 std::ptr::copy_nonoverlapping(src, dst, data.len());
58 }
59 } else {
60 bail!(MbufError::WritePastBuffer);
61 }
62 Ok(mbuf)
63 }
64
65 pub(crate) fn raw(&self) -> &dpdk::rte_mbuf {
67 unsafe { self.raw.as_ref() }
68 }
69
70 fn raw_mut(&mut self) -> &mut dpdk::rte_mbuf {
72 unsafe { self.raw.as_mut() }
73 }
74
75 #[allow(dead_code)]
77 pub(crate) fn timestamp(&self) -> usize {
78 unimplemented!();
79 }
80
81 pub fn data_len(&self) -> usize {
83 self.raw().data_len as usize
84 }
85
86 pub fn data(&self) -> &[u8] {
88 let ptr = self.get_data_address(0);
89 unsafe { slice::from_raw_parts(ptr, self.data_len()) as &[u8] }
90 }
91
92 pub fn get_data_slice(&self, offset: usize, count: usize) -> Result<&[u8]> {
97 if offset < self.data_len() {
98 if offset + count <= self.data_len() {
99 let ptr = self.get_data_address(offset);
100 unsafe { Ok(slice::from_raw_parts(ptr, count) as &[u8]) }
101 } else {
102 bail!(MbufError::ReadPastBuffer)
103 }
104 } else {
105 bail!(MbufError::BadOffset)
106 }
107 }
108
109 pub(crate) fn get_data<T: PacketHeader>(&self, offset: usize) -> Result<*const T> {
113 if offset < self.data_len() {
114 if offset + T::size_of() <= self.data_len() {
115 Ok(self.get_data_address(offset) as *const T)
116 } else {
117 bail!(MbufError::ReadPastBuffer)
118 }
119 } else {
120 bail!(MbufError::BadOffset)
121 }
122 }
123
124 fn get_data_address(&self, offset: usize) -> *const u8 {
126 let raw = self.raw();
127 unsafe { (raw.buf_addr as *const u8).offset(raw.data_off as isize + offset as isize) }
128 }
129
130 #[allow(dead_code)]
132 pub(crate) fn rss_hash(&self) -> u32 {
133 unsafe { self.raw().__bindgen_anon_2.hash.rss }
134 }
135
136 #[allow(dead_code)]
138 pub(crate) fn mark(&self) -> u32 {
139 unsafe { self.raw().__bindgen_anon_2.hash.fdir.hi }
140 }
141}
142
143impl<'a> Packet<'a> for Mbuf {
144 fn mbuf(&self) -> &Mbuf {
145 self
146 }
147
148 fn header_len(&self) -> usize {
149 0
150 }
151
152 fn next_header_offset(&self) -> usize {
153 0
154 }
155
156 fn next_header(&self) -> Option<usize> {
157 None
158 }
159
160 fn parse_from(_outer: &'a impl Packet<'a>) -> Result<Self>
161 where
162 Self: Sized,
163 {
164 bail!(PacketParseError::InvalidProtocol)
166 }
167}
168
169impl Drop for Mbuf {
170 fn drop(&mut self) {
171 unsafe { dpdk::rte_pktmbuf_free(self.raw()) };
173 }
174}
175
176impl fmt::Debug for Mbuf {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 let raw = self.raw();
179 f.debug_struct("Mbuf")
180 .field("buf_addr", &raw.buf_addr)
181 .field("buf_len", &raw.buf_len)
182 .field("pkt_len", &raw.pkt_len)
183 .field("data_len", &raw.data_len)
184 .field("data_off", &raw.data_off)
185 .finish()
186 }
187}
188
189impl fmt::Display for Mbuf {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 for byte in 0..self.raw().data_len {
193 write!(
194 f,
195 "{:02x} ",
196 self.get_data_slice(byte as usize, 1).unwrap()[0]
197 )?;
198 if byte % 16 == 15 {
199 writeln!(f,)?;
200 }
201 }
202 Ok(())
203 }
204}
205
206#[derive(Error, Debug)]
207pub(crate) enum MbufError {
208 #[error("Offset exceeds Mbuf segment buffer length")]
209 BadOffset,
210
211 #[error("Data read exceeds Mbuf segment buffer")]
212 ReadPastBuffer,
213
214 #[error("Data write exceeds Mbuf segment buffer")]
215 WritePastBuffer,
216}