1use 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 fn new_ref(mbuf: &Mbuf) -> Mbuf {
49 unsafe {
50 dpdk::rte_mbuf_refcnt_update(mbuf.raw.as_ptr(), 1);
51 }
52 Mbuf::new_unchecked(mbuf.raw.as_ptr())
53 }
54
55 pub(crate) fn from_bytes(data: &[u8], mp: *mut dpdk::rte_mempool) -> Result<Mbuf> {
57 let mut mbuf = unsafe { Mbuf::new(dpdk::rte_pktmbuf_alloc(mp))? };
58 if data.len() <= mbuf.raw().get_buf_len() {
59 let current_data_len = mbuf.raw().get_data_len();
60 mbuf.raw_mut()
61 .set_data_len(current_data_len + data.len() as u16);
62
63 let current_pkt_len = mbuf.raw().get_pkt_len();
64 mbuf.raw_mut()
65 .set_pkt_len(current_pkt_len + data.len() as u32);
66
67 unsafe {
68 let src = data.as_ptr();
69 let dst = mbuf.get_data_address(0) as *mut u8;
70 std::ptr::copy_nonoverlapping(src, dst, data.len());
71 }
72 } else {
73 bail!(MbufError::WritePastBuffer);
74 }
75 Ok(mbuf)
76 }
77
78 pub(crate) fn raw(&self) -> &dpdk::rte_mbuf {
80 unsafe { self.raw.as_ref() }
81 }
82
83 fn raw_mut(&mut self) -> &mut dpdk::rte_mbuf {
85 unsafe { self.raw.as_mut() }
86 }
87
88 #[allow(dead_code)]
90 pub(crate) fn timestamp(&self) -> usize {
91 unimplemented!();
92 }
93
94 pub fn data_len(&self) -> usize {
96 self.raw().get_data_len() as usize
97 }
98
99 pub fn data(&self) -> &[u8] {
101 let ptr = self.get_data_address(0);
102 unsafe { slice::from_raw_parts(ptr, self.data_len()) as &[u8] }
103 }
104
105 pub fn get_data_slice(&self, offset: usize, count: usize) -> Result<&[u8]> {
110 if offset < self.data_len() {
111 if offset + count <= self.data_len() {
112 let ptr = self.get_data_address(offset);
113 unsafe { Ok(slice::from_raw_parts(ptr, count) as &[u8]) }
114 } else {
115 bail!(MbufError::ReadPastBuffer)
116 }
117 } else {
118 bail!(MbufError::BadOffset)
119 }
120 }
121
122 pub(crate) fn get_data<T: PacketHeader>(&self, offset: usize) -> Result<*const T> {
126 if offset < self.data_len() {
127 if offset + T::size_of() <= self.data_len() {
128 Ok(self.get_data_address(offset) as *const T)
129 } else {
130 bail!(MbufError::ReadPastBuffer)
131 }
132 } else {
133 bail!(MbufError::BadOffset)
134 }
135 }
136
137 fn get_data_address(&self, offset: usize) -> *const u8 {
139 let raw = self.raw();
140 unsafe { (raw.buf_addr as *const u8).offset(raw.get_data_off() as isize + offset as isize) }
141 }
142
143 #[allow(dead_code)]
145 pub(crate) fn rss_hash(&self) -> u32 {
146 self.raw().get_rss_hash()
147 }
148
149 #[allow(dead_code)]
151 pub(crate) fn mark(&self) -> u32 {
152 self.raw().get_mark()
153 }
154
155 #[allow(dead_code)]
156 pub(crate) fn add_mark(&mut self, mark: u32) {
157 self.raw_mut().set_mark(mark);
158 }
159
160 #[allow(dead_code)]
162 pub fn has_mark(&mut self, _mark: u32) -> bool {
163 true
165 }
166}
167
168impl<'a> Packet<'a> for Mbuf {
169 fn mbuf(&self) -> &Mbuf {
170 self
171 }
172
173 fn header_len(&self) -> usize {
174 0
175 }
176
177 fn next_header_offset(&self) -> usize {
178 0
179 }
180
181 fn next_header(&self) -> Option<usize> {
182 None
183 }
184
185 fn parse_from(_outer: &'a impl Packet<'a>) -> Result<Self>
186 where
187 Self: Sized,
188 {
189 bail!(PacketParseError::InvalidProtocol)
191 }
192}
193
194impl Drop for Mbuf {
195 fn drop(&mut self) {
196 unsafe { dpdk::rte_pktmbuf_free(self.raw()) };
204 }
205}
206
207impl fmt::Debug for Mbuf {
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 let raw = self.raw();
210 f.debug_struct("Mbuf")
211 .field("buf_addr", &raw.buf_addr)
212 .field("buf_len", &raw.get_buf_len())
213 .field("pkt_len", &raw.get_pkt_len())
214 .field("data_len", &raw.get_data_len())
215 .field("data_off", &raw.get_data_off())
216 .finish()
217 }
218}
219
220impl fmt::Display for Mbuf {
222 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
223 for byte in 0..self.raw().get_data_len() {
224 write!(
225 f,
226 "{:02x} ",
227 self.get_data_slice(byte as usize, 1).unwrap()[0]
228 )?;
229 if byte % 16 == 15 {
230 writeln!(f,)?;
231 }
232 }
233 Ok(())
234 }
235}
236
237#[derive(Error, Debug)]
238pub(crate) enum MbufError {
239 #[error("Offset exceeds Mbuf segment buffer length")]
240 BadOffset,
241
242 #[error("Data read exceeds Mbuf segment buffer")]
243 ReadPastBuffer,
244
245 #[error("Data write exceeds Mbuf segment buffer")]
246 WritePastBuffer,
247}