1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub enum IpFragmentFamily {
6 Ipv4,
8 Ipv6,
10}
11
12impl IpFragmentFamily {
13 pub const fn version(self) -> u8 {
15 match self {
16 Self::Ipv4 => 4,
17 Self::Ipv6 => 6,
18 }
19 }
20
21 pub const fn label(self) -> &'static str {
23 match self {
24 Self::Ipv4 => "ipv4",
25 Self::Ipv6 => "ipv6",
26 }
27 }
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
32pub struct IpFragmentRange {
33 start: u32,
34 end: u32,
35}
36
37impl IpFragmentRange {
38 pub const fn new(start: u32, end: u32) -> Self {
40 Self { start, end }
41 }
42
43 pub const fn start(self) -> u32 {
45 self.start
46 }
47
48 pub const fn end(self) -> u32 {
50 self.end
51 }
52
53 pub const fn len(self) -> u32 {
55 self.end.saturating_sub(self.start)
56 }
57
58 pub const fn is_empty(self) -> bool {
60 self.len() == 0
61 }
62}
63
64#[derive(Debug, Clone, PartialEq, Eq, Hash)]
66pub enum IpFragmentReason {
67 Fragmented,
69 AlreadyFits,
71 DontFragment,
73 Unsupported,
75 Other(String),
77}
78
79#[derive(Debug, Clone, PartialEq, Eq, Hash)]
81pub struct IpFragmentMetadata {
82 family: IpFragmentFamily,
83 mtu: usize,
84 identification: u32,
85 fragment_offset: u16,
86 more_fragments: bool,
87 fragment_count: usize,
88 emitted_index: usize,
89 byte_range: IpFragmentRange,
90 original_len: Option<u32>,
91 reason: Option<IpFragmentReason>,
92}
93
94impl IpFragmentMetadata {
95 #[allow(clippy::too_many_arguments)]
97 pub const fn new(
98 family: IpFragmentFamily,
99 mtu: usize,
100 identification: u32,
101 fragment_offset: u16,
102 more_fragments: bool,
103 fragment_count: usize,
104 emitted_index: usize,
105 byte_range: IpFragmentRange,
106 ) -> Self {
107 Self {
108 family,
109 mtu,
110 identification,
111 fragment_offset,
112 more_fragments,
113 fragment_count,
114 emitted_index,
115 byte_range,
116 original_len: None,
117 reason: None,
118 }
119 }
120
121 pub const fn family(&self) -> IpFragmentFamily {
123 self.family
124 }
125
126 pub const fn mtu(&self) -> usize {
128 self.mtu
129 }
130
131 pub const fn identification(&self) -> u32 {
133 self.identification
134 }
135
136 pub const fn fragment_offset(&self) -> u16 {
138 self.fragment_offset
139 }
140
141 pub const fn fragment_offset_bytes(&self) -> u32 {
143 (self.fragment_offset as u32) * 8
144 }
145
146 pub const fn more_fragments(&self) -> bool {
148 self.more_fragments
149 }
150
151 pub const fn fragment_count(&self) -> usize {
153 self.fragment_count
154 }
155
156 pub const fn emitted_index(&self) -> usize {
158 self.emitted_index
159 }
160
161 pub const fn fragment_index(&self) -> usize {
163 self.emitted_index()
164 }
165
166 pub const fn byte_range(&self) -> IpFragmentRange {
168 self.byte_range
169 }
170
171 pub const fn original_len(&self) -> Option<u32> {
173 self.original_len
174 }
175
176 pub const fn reason(&self) -> Option<&IpFragmentReason> {
178 self.reason.as_ref()
179 }
180
181 pub const fn with_original_len(mut self, original_len: u32) -> Self {
183 self.original_len = Some(original_len);
184 self
185 }
186
187 pub fn with_reason(mut self, reason: IpFragmentReason) -> Self {
189 self.reason = Some(reason);
190 self
191 }
192}
193
194#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
196pub enum IpDefragOverlapStatus {
197 None,
199 NonConflicting,
201 Conflicting,
203}
204
205impl IpDefragOverlapStatus {
206 pub const fn has_overlap(self) -> bool {
208 !matches!(self, Self::None)
209 }
210
211 pub const fn has_conflict(self) -> bool {
213 matches!(self, Self::Conflicting)
214 }
215}
216
217#[derive(Debug, Clone, PartialEq, Eq, Hash)]
219pub enum IpDefragEvictionReason {
220 Timeout,
222 DatagramLimit,
224 ByteLimit,
226 Conflict,
228 Other(String),
230}
231
232#[derive(Debug, Clone, PartialEq, Eq, Hash)]
234pub struct IpDefragMetadata {
235 family: IpFragmentFamily,
236 identification: u32,
237 datagram_key: Option<String>,
238 fragment_count: usize,
239 duplicate_count: usize,
240 overlap_status: IpDefragOverlapStatus,
241 byte_ranges: Vec<IpFragmentRange>,
242 total_len: Option<u32>,
243 eviction_reason: Option<IpDefragEvictionReason>,
244}
245
246impl IpDefragMetadata {
247 pub const fn new(family: IpFragmentFamily, identification: u32) -> Self {
249 Self {
250 family,
251 identification,
252 datagram_key: None,
253 fragment_count: 0,
254 duplicate_count: 0,
255 overlap_status: IpDefragOverlapStatus::None,
256 byte_ranges: Vec::new(),
257 total_len: None,
258 eviction_reason: None,
259 }
260 }
261
262 pub const fn family(&self) -> IpFragmentFamily {
264 self.family
265 }
266
267 pub const fn identification(&self) -> u32 {
269 self.identification
270 }
271
272 pub fn datagram_key(&self) -> Option<&str> {
274 self.datagram_key.as_deref()
275 }
276
277 pub const fn fragment_count(&self) -> usize {
279 self.fragment_count
280 }
281
282 pub const fn duplicate_count(&self) -> usize {
284 self.duplicate_count
285 }
286
287 pub const fn overlap_status(&self) -> IpDefragOverlapStatus {
289 self.overlap_status
290 }
291
292 pub const fn has_conflict(&self) -> bool {
294 self.overlap_status.has_conflict()
295 }
296
297 pub fn byte_ranges(&self) -> &[IpFragmentRange] {
299 &self.byte_ranges
300 }
301
302 pub const fn total_len(&self) -> Option<u32> {
304 self.total_len
305 }
306
307 pub const fn eviction_reason(&self) -> Option<&IpDefragEvictionReason> {
309 self.eviction_reason.as_ref()
310 }
311
312 pub const fn timed_out(&self) -> bool {
314 matches!(self.eviction_reason, Some(IpDefragEvictionReason::Timeout))
315 }
316
317 pub fn with_datagram_key(mut self, datagram_key: impl Into<String>) -> Self {
319 self.datagram_key = Some(datagram_key.into());
320 self
321 }
322
323 pub const fn with_fragment_count(mut self, fragment_count: usize) -> Self {
325 self.fragment_count = fragment_count;
326 self
327 }
328
329 pub const fn with_duplicate_count(mut self, duplicate_count: usize) -> Self {
331 self.duplicate_count = duplicate_count;
332 self
333 }
334
335 pub const fn with_overlap_status(mut self, overlap_status: IpDefragOverlapStatus) -> Self {
337 self.overlap_status = overlap_status;
338 self
339 }
340
341 pub fn with_byte_range(mut self, byte_range: IpFragmentRange) -> Self {
343 self.byte_ranges.push(byte_range);
344 self
345 }
346
347 pub fn with_byte_ranges(
349 mut self,
350 byte_ranges: impl IntoIterator<Item = IpFragmentRange>,
351 ) -> Self {
352 self.byte_ranges = byte_ranges.into_iter().collect();
353 self
354 }
355
356 pub const fn with_total_len(mut self, total_len: u32) -> Self {
358 self.total_len = Some(total_len);
359 self
360 }
361
362 pub fn with_eviction_reason(mut self, eviction_reason: IpDefragEvictionReason) -> Self {
364 self.eviction_reason = Some(eviction_reason);
365 self
366 }
367}