netstack3_tcp/
seq_ranges.rs1use alloc::collections::VecDeque;
6use core::ops::Range;
7
8use derivative::Derivative;
9use netstack3_base::SeqNum;
10
11#[derive(Debug, Derivative)]
15#[derivative(Default(bound = ""))]
16#[cfg_attr(test, derive(PartialEq, Eq))]
17pub(crate) struct SeqRanges<M> {
18 blocks: VecDeque<SeqRange<M>>,
19}
20
21impl<M> SeqRanges<M> {
22 pub(crate) fn is_empty(&self) -> bool {
23 self.blocks.is_empty()
24 }
25
26 pub(crate) fn pop_front_if<F: FnOnce(&SeqRange<M>) -> bool>(
27 &mut self,
28 f: F,
29 ) -> Option<SeqRange<M>> {
30 let front = self.blocks.front()?;
31 if f(front) {
32 self.blocks.pop_front()
33 } else {
34 None
35 }
36 }
37
38 fn find_first_after(blocks: &mut VecDeque<SeqRange<M>>, start: SeqNum) -> usize {
39 match blocks.binary_search_by(|block| {
40 if block.start() == start {
41 return core::cmp::Ordering::Equal;
42 }
43 if block.start().before(start) {
44 core::cmp::Ordering::Less
45 } else {
46 core::cmp::Ordering::Greater
47 }
48 }) {
49 Ok(r) => {
50 r + 1
53 }
54 Err(e) => {
55 e
59 }
60 }
61 }
62
63 pub(crate) fn insert(&mut self, range: Range<SeqNum>, meta: M) -> bool
73 where
74 M: Clone,
75 {
76 let Some(range) = SeqRange::new(range, meta) else {
77 return false;
78 };
79 self.insert_seq_range(range)
80 }
81
82 fn insert_seq_range(&mut self, mut range: SeqRange<M>) -> bool
83 where
84 M: Clone,
85 {
86 let Self { blocks } = self;
87
88 if blocks.is_empty() {
89 blocks.push_back(range);
90 return true;
91 }
92
93 let first_after = Self::find_first_after(blocks, range.start());
95
96 let mut merge_right = 0;
97 for block in blocks.range(first_after..blocks.len()) {
98 match range.merge_right(block) {
99 MergeRightResult::Before => break,
100 MergeRightResult::After { merged } => {
101 merge_right += 1;
102 if merged {
103 break;
104 }
105 }
106 }
107 }
108
109 let merge_left = match first_after
112 .checked_sub(1)
113 .and_then(|first_before| blocks.get_mut(first_before))
114 {
115 Some(block) => {
116 match block.merge_right(&range) {
117 MergeRightResult::Before => 0,
118 MergeRightResult::After { merged } => {
119 if merged {
120 range.clone_range_from(&block);
121 1
122 } else {
123 block.set_meta(range.into_meta());
126 return false;
127 }
128 }
129 }
130 }
131 None => 0,
132 };
133
134 if merge_left == 0 && merge_right == 0 {
135 blocks.insert(first_after, range);
138 } else {
139 let left_edge = first_after - merge_left;
142 let right_edge = first_after + merge_right;
143 blocks[left_edge] = range;
144 for i in right_edge..blocks.len() {
145 blocks[i - merge_left - merge_right + 1] = blocks[i].clone();
146 }
147 blocks.truncate(blocks.len() - merge_left - merge_right + 1);
148 }
149
150 true
151 }
152
153 pub(crate) fn iter(&self) -> impl Iterator<Item = &SeqRange<M>> + '_ {
154 self.blocks.iter()
155 }
156
157 pub(crate) fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut SeqRange<M>> + '_ {
160 self.blocks.iter_mut()
161 }
162
163 pub(crate) fn discard_starting_at_or_before(&mut self, value: SeqNum) {
165 let Self { blocks } = self;
166 let first_after = Self::find_first_after(blocks, value);
167 let _drain = blocks.drain(0..first_after);
169 }
170}
171
172impl<M: Clone> FromIterator<SeqRange<M>> for SeqRanges<M> {
173 fn from_iter<T: IntoIterator<Item = SeqRange<M>>>(iter: T) -> Self {
174 let mut ranges = SeqRanges::default();
175 for range in iter {
176 let _: bool = ranges.insert_seq_range(range);
177 }
178 ranges
179 }
180}
181
182mod range {
183 use netstack3_base::SackBlock;
184
185 use super::*;
186
187 #[derive(Debug, Clone)]
189 #[cfg_attr(test, derive(PartialEq, Eq))]
190 pub(crate) struct SeqRange<M> {
191 range: Range<SeqNum>,
192 meta: M,
193 }
194
195 impl<M> SeqRange<M> {
196 pub(crate) fn new(range: Range<SeqNum>, meta: M) -> Option<Self> {
197 range.end.after(range.start).then(|| Self { range, meta })
198 }
199
200 pub(crate) fn start(&self) -> SeqNum {
201 self.range.start
202 }
203
204 pub(crate) fn end(&self) -> SeqNum {
205 self.range.end
206 }
207
208 pub(crate) fn set_meta(&mut self, meta: M) {
209 self.meta = meta;
210 }
211
212 pub(crate) fn meta(&self) -> &M {
213 &self.meta
214 }
215
216 pub(crate) fn into_meta(self) -> M {
217 self.meta
218 }
219
220 pub(super) fn clone_range_from(&mut self, other: &Self) {
221 let Self { range, meta: _ } = self;
222 *range = other.range.clone();
223 }
224
225 pub(crate) fn len(&self) -> u32 {
226 let Self { range: Range { start, end }, meta: _ } = self;
227 let len = *end - *start;
228 debug_assert!(len >= 0);
230 len as u32
231 }
232
233 pub(crate) fn cap_right(self, seq: SeqNum) -> Option<Self> {
234 let Self { range: Range { start, end }, meta } = self;
235 seq.after(start).then(|| Self { range: Range { start, end: end.earliest(seq) }, meta })
236 }
237
238 pub(crate) fn to_sack_block(&self) -> SackBlock {
239 let Self { range: Range { start, end }, meta: _ } = self;
240 unsafe { SackBlock::new_unchecked(*start, *end) }
243 }
244
245 pub(super) fn merge_right(&mut self, other: &Self) -> MergeRightResult {
246 if self.range.end.before(other.range.start) {
247 return MergeRightResult::Before;
248 }
249
250 let merged = self.range.end.before(other.range.end);
251 if merged {
252 self.range.end = other.range.end;
253 }
254
255 MergeRightResult::After { merged }
256 }
257 }
258
259 pub(super) enum MergeRightResult {
260 Before,
261 After { merged: bool },
262 }
263}
264use range::MergeRightResult;
265pub(crate) use range::SeqRange;
266
267#[cfg(test)]
268mod test {
269 use super::*;
270
271 use alloc::vec::Vec;
272 use alloc::{format, vec};
273
274 use netstack3_base::{SackBlock, WindowSize};
275 use proptest::strategy::{Just, Strategy};
276 use proptest::test_runner::Config;
277 use proptest::{prop_assert, prop_assert_eq, proptest};
278 use proptest_support::failed_seeds_no_std;
279 use test_case::test_case;
280
281 impl SeqRanges<()> {
282 fn insert_u32(&mut self, range: Range<u32>) -> bool {
283 let Range { start, end } = range;
284 self.insert(SeqNum::new(start)..SeqNum::new(end), ())
285 }
286 }
287
288 impl FromIterator<Range<u32>> for SeqRanges<()> {
289 fn from_iter<T: IntoIterator<Item = Range<u32>>>(iter: T) -> Self {
290 let mut ranges = SeqRanges::default();
291 for range in iter {
292 let _: bool = ranges.insert_u32(range);
293 }
294 ranges
295 }
296 }
297
298 proptest! {
299 #![proptest_config(Config {
300 failure_persistence: failed_seeds_no_std!(
302 "cc f621ca7d3a2b108e0dc41f7169ad028f4329b79e90e73d5f68042519a9f63999",
303 "cc c449aebed201b4ec4f137f3c224f20325f4cfee0b7fd596d9285176b6d811aa9"
304 ),
305 ..Config::default()
306 })]
307
308 #[test]
309 fn seq_ranges_insert(insertions in proptest::collection::vec(insertions(), 200)) {
310 let mut seq_ranges = SeqRanges::<()>::default();
311 let mut num_insertions_performed = 0;
312 let mut min_seq = SeqNum::new(WindowSize::MAX.into());
313 let mut max_seq = SeqNum::new(0);
314 for Range { start, end } in insertions {
315 if min_seq.after(start) {
316 min_seq = start;
317 }
318 if max_seq.before(end) {
319 max_seq = end;
320 }
321 prop_assert!(seq_ranges.blocks.len() <= num_insertions_performed);
324 let _: bool = seq_ranges.insert(start..end, ());
325 num_insertions_performed += 1;
326
327 for i in 1..seq_ranges.blocks.len() {
330 prop_assert!(
331 seq_ranges.blocks[i-1].end().before(seq_ranges.blocks[i].start())
332 );
333 }
334 }
335 prop_assert_eq!(seq_ranges.blocks.front().unwrap().start(), min_seq);
336 prop_assert_eq!(seq_ranges.blocks.back().unwrap().end(), max_seq);
337 }
338
339 #[test]
342 fn seq_range_to_sack_block((start, end) in sequence_numbers()) {
343 prop_assert_eq!(
344 SeqRange::new(start..end, ()).map(|sr| sr.to_sack_block()),
345 SackBlock::try_new(start, end).ok()
346 );
347 }
348
349 }
350
351 fn insertions() -> impl Strategy<Value = Range<SeqNum>> {
352 (0..u32::from(WindowSize::MAX)).prop_flat_map(|start| {
353 (start + 1..=u32::from(WindowSize::MAX)).prop_flat_map(move |end| {
354 Just(Range { start: SeqNum::new(start), end: SeqNum::new(end) })
355 })
356 })
357 }
358
359 fn sequence_numbers() -> impl Strategy<Value = (SeqNum, SeqNum)> {
360 (0u32..5).prop_flat_map(|start| {
361 (0u32..5).prop_flat_map(move |end| Just((SeqNum::new(start), SeqNum::new(end))))
362 })
363 }
364
365 #[test]
366 fn insert_return() {
367 let mut sr = SeqRanges::default();
368 assert!(sr.insert_u32(10..20));
369
370 assert!(!sr.insert_u32(10..20));
371 assert!(!sr.insert_u32(11..20));
372 assert!(!sr.insert_u32(11..12));
373 assert!(!sr.insert_u32(19..20));
374
375 assert!(sr.insert_u32(0..5));
376 assert!(sr.insert_u32(25..35));
377 assert!(sr.insert_u32(5..7));
378 assert!(sr.insert_u32(22..25));
379
380 assert!(sr.insert_u32(7..22));
381 assert!(!sr.insert_u32(0..35));
382 }
383
384 #[test_case(&[], 0 => Vec::<Range<u32>>::new(); "empty")]
385 #[test_case(&[10..20], 0 => vec![10..20]; "before 1")]
386 #[test_case(&[10..20, 30..40], 0 => vec![10..20, 30..40]; "before 2")]
387 #[test_case(&[10..20], 10 => Vec::<Range<u32>>::new(); "same 1")]
388 #[test_case(&[10..20, 30..40], 10 => vec![30..40]; "same 2")]
389 #[test_case(&[10..20], 20 => Vec::<Range<u32>>::new(); "after 1")]
390 #[test_case(&[10..20, 30..40], 20 => vec![30..40]; "after 2")]
391 #[test_case(&[10..20, 30..40], 30 => Vec::<Range<u32>>::new(); "after 3")]
392 #[test_case(&[10..20, 30..40], 15 => vec![30..40]; "mid 1")]
393 #[test_case(&[10..20, 30..40], 35 => Vec::<Range<u32>>::new(); "mid 2")]
394 fn discard_starting_at_or_before(ranges: &[Range<u32>], discard: u32) -> Vec<Range<u32>> {
395 let mut sr = ranges.into_iter().cloned().collect::<SeqRanges<()>>();
396 sr.discard_starting_at_or_before(SeqNum::new(discard));
397 sr.iter()
398 .map(|seq_range| u32::from(seq_range.start())..u32::from(seq_range.end()))
399 .collect()
400 }
401}