1#![allow(dead_code)]
9
10#[cfg(feature = "alloc")]
11use alloc::vec::Vec;
12
13#[inline]
20pub fn seq_lt(a: u32, b: u32) -> bool {
21 (a.wrapping_sub(b) as i32) < 0
22}
23
24#[inline]
26pub fn seq_le(a: u32, b: u32) -> bool {
27 (a.wrapping_sub(b) as i32) <= 0
28}
29
30#[inline]
32pub fn seq_gt(a: u32, b: u32) -> bool {
33 (a.wrapping_sub(b) as i32) > 0
34}
35
36#[inline]
38pub fn seq_ge(a: u32, b: u32) -> bool {
39 (a.wrapping_sub(b) as i32) >= 0
40}
41
42pub const TCP_OPT_SACK_PERMITTED: u8 = 4;
48
49pub const TCP_OPT_SACK_PERMITTED_LEN: u8 = 2;
51
52pub const TCP_OPT_SACK: u8 = 5;
54
55pub const MAX_SACK_BLOCKS: usize = 4;
58
59const SACK_BLOCK_SIZE: usize = 8;
61
62const TCP_OPT_EOL: u8 = 0;
64
65const TCP_OPT_NOP: u8 = 1;
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77pub struct SackBlock {
78 pub left_edge: u32,
79 pub right_edge: u32,
80}
81
82impl SackBlock {
83 pub const fn new(left_edge: u32, right_edge: u32) -> Self {
85 Self {
86 left_edge,
87 right_edge,
88 }
89 }
90
91 pub fn contains(&self, seq: u32) -> bool {
93 seq_ge(seq, self.left_edge) && seq_lt(seq, self.right_edge)
94 }
95
96 pub fn len(&self) -> u32 {
98 self.right_edge.wrapping_sub(self.left_edge)
99 }
100
101 pub fn is_empty(&self) -> bool {
103 self.left_edge == self.right_edge
104 }
105
106 pub fn overlaps_or_adjacent(&self, other: &SackBlock) -> bool {
108 seq_le(self.left_edge, other.right_edge) && seq_le(other.left_edge, self.right_edge)
111 }
112
113 pub fn merge(&mut self, other: &SackBlock) {
116 if seq_lt(other.left_edge, self.left_edge) {
117 self.left_edge = other.left_edge;
118 }
119 if seq_gt(other.right_edge, self.right_edge) {
120 self.right_edge = other.right_edge;
121 }
122 }
123}
124
125#[cfg(feature = "alloc")]
134pub fn parse_sack_blocks(options: &[u8]) -> Vec<SackBlock> {
135 let mut blocks = Vec::new();
136 let mut i = 0;
137
138 while i < options.len() {
139 match options[i] {
140 TCP_OPT_EOL => break,
141 TCP_OPT_NOP => {
142 i += 1;
143 }
144 TCP_OPT_SACK => {
145 if i + 1 >= options.len() {
147 break;
148 }
149 let opt_len = options[i + 1] as usize;
150 if opt_len < 2 || i + opt_len > options.len() {
151 break;
152 }
153 let num_blocks = (opt_len - 2) / SACK_BLOCK_SIZE;
155 let mut offset = i + 2;
156 for _ in 0..num_blocks.min(MAX_SACK_BLOCKS) {
157 if offset + SACK_BLOCK_SIZE > i + opt_len {
158 break;
159 }
160 let left = u32::from_be_bytes([
161 options[offset],
162 options[offset + 1],
163 options[offset + 2],
164 options[offset + 3],
165 ]);
166 let right = u32::from_be_bytes([
167 options[offset + 4],
168 options[offset + 5],
169 options[offset + 6],
170 options[offset + 7],
171 ]);
172 blocks.push(SackBlock::new(left, right));
173 offset += SACK_BLOCK_SIZE;
174 }
175 i += opt_len;
176 }
177 _ => {
178 if i + 1 >= options.len() {
180 break;
181 }
182 let opt_len = options[i + 1] as usize;
183 if opt_len < 2 {
184 break;
185 }
186 i += opt_len;
187 }
188 }
189 }
190
191 blocks
192}
193
194pub fn has_sack_permitted(options: &[u8]) -> bool {
196 let mut i = 0;
197
198 while i < options.len() {
199 match options[i] {
200 TCP_OPT_EOL => break,
201 TCP_OPT_NOP => {
202 i += 1;
203 }
204 TCP_OPT_SACK_PERMITTED => {
205 if i + 1 < options.len() && options[i + 1] == TCP_OPT_SACK_PERMITTED_LEN {
206 return true;
207 }
208 if i + 1 < options.len() {
210 let opt_len = options[i + 1] as usize;
211 i += if opt_len >= 2 { opt_len } else { 2 };
212 } else {
213 break;
214 }
215 }
216 _ => {
217 if i + 1 >= options.len() {
218 break;
219 }
220 let opt_len = options[i + 1] as usize;
221 if opt_len < 2 {
222 break;
223 }
224 i += opt_len;
225 }
226 }
227 }
228
229 false
230}
231
232#[cfg(feature = "alloc")]
234pub fn serialize_sack_permitted() -> Vec<u8> {
235 alloc::vec![TCP_OPT_SACK_PERMITTED, TCP_OPT_SACK_PERMITTED_LEN]
236}
237
238#[cfg(feature = "alloc")]
243pub fn serialize_sack_blocks(blocks: &[SackBlock]) -> Vec<u8> {
244 if blocks.is_empty() {
245 return Vec::new();
246 }
247
248 let count = blocks.len().min(MAX_SACK_BLOCKS);
249 let opt_len = 2 + count * SACK_BLOCK_SIZE;
250 let mut out = Vec::with_capacity(opt_len);
251
252 out.push(TCP_OPT_SACK);
253 out.push(opt_len as u8);
254
255 for block in blocks.iter().take(count) {
256 out.extend_from_slice(&block.left_edge.to_be_bytes());
257 out.extend_from_slice(&block.right_edge.to_be_bytes());
258 }
259
260 out
261}
262
263#[cfg(feature = "alloc")]
272pub struct SackScoreboard {
273 blocks: Vec<SackBlock>,
276}
277
278#[cfg(feature = "alloc")]
279impl Default for SackScoreboard {
280 fn default() -> Self {
281 Self::new()
282 }
283}
284
285#[cfg(feature = "alloc")]
286impl SackScoreboard {
287 pub fn new() -> Self {
289 Self { blocks: Vec::new() }
290 }
291
292 pub fn block_count(&self) -> usize {
294 self.blocks.len()
295 }
296
297 pub fn blocks(&self) -> &[SackBlock] {
299 &self.blocks
300 }
301
302 pub fn is_sacked(&self, seq: u32) -> bool {
304 self.blocks.iter().any(|b| b.contains(seq))
305 }
306
307 pub fn mark_sacked(&mut self, left: u32, right: u32) {
312 if seq_ge(left, right) {
313 return; }
315
316 let mut new_block = SackBlock::new(left, right);
317
318 let mut merge_indices = Vec::new();
320 for (i, block) in self.blocks.iter().enumerate() {
321 if new_block.overlaps_or_adjacent(block) {
322 merge_indices.push(i);
323 }
324 }
325
326 for &i in merge_indices.iter() {
328 new_block.merge(&self.blocks[i]);
329 }
330
331 for &i in merge_indices.iter().rev() {
333 self.blocks.remove(i);
334 }
335
336 let insert_pos = self
338 .blocks
339 .iter()
340 .position(|b| seq_gt(b.left_edge, new_block.left_edge))
341 .unwrap_or(self.blocks.len());
342
343 self.blocks.insert(insert_pos, new_block);
344 }
345
346 pub fn clear_below(&mut self, ack: u32) {
351 self.blocks.retain_mut(|block| {
352 if seq_le(block.right_edge, ack) {
353 false
355 } else if seq_lt(block.left_edge, ack) {
356 block.left_edge = ack;
358 true
359 } else {
360 true
361 }
362 });
363 }
364
365 pub fn highest_sacked(&self) -> Option<u32> {
367 self.blocks.last().map(|b| b.right_edge)
368 }
369
370 pub fn next_retransmit(&self, snd_una: u32) -> Option<(u32, u32)> {
375 if self.blocks.is_empty() {
376 return None;
377 }
378
379 let first = &self.blocks[0];
381 if seq_lt(snd_una, first.left_edge) {
382 let hole_len = first.left_edge.wrapping_sub(snd_una);
383 return Some((snd_una, hole_len));
384 }
385
386 for window in self.blocks.windows(2) {
388 let gap_start = window[0].right_edge;
389 let gap_end = window[1].left_edge;
390 if seq_lt(gap_start, gap_end) {
391 let hole_len = gap_end.wrapping_sub(gap_start);
392 return Some((gap_start, hole_len));
393 }
394 }
395
396 None
397 }
398
399 pub fn holes(&self, snd_una: u32) -> Vec<(u32, u32)> {
403 let mut result = Vec::new();
404
405 if self.blocks.is_empty() {
406 return result;
407 }
408
409 let first = &self.blocks[0];
411 if seq_lt(snd_una, first.left_edge) {
412 let hole_len = first.left_edge.wrapping_sub(snd_una);
413 result.push((snd_una, hole_len));
414 }
415
416 for window in self.blocks.windows(2) {
418 let gap_start = window[0].right_edge;
419 let gap_end = window[1].left_edge;
420 if seq_lt(gap_start, gap_end) {
421 let hole_len = gap_end.wrapping_sub(gap_start);
422 result.push((gap_start, hole_len));
423 }
424 }
425
426 result
427 }
428}
429
430#[cfg(test)]
435mod tests {
436 #[allow(unused_imports)]
437 use alloc::vec;
438
439 use super::*;
440
441 #[test]
444 fn test_seq_lt_normal() {
445 assert!(seq_lt(100, 200));
446 assert!(!seq_lt(200, 100));
447 assert!(!seq_lt(100, 100));
448 }
449
450 #[test]
451 fn test_seq_lt_wrapping() {
452 let a = u32::MAX - 10;
454 let b = 10u32; assert!(seq_lt(a, b));
456 assert!(!seq_lt(b, a));
457 }
458
459 #[test]
460 fn test_seq_le_ge() {
461 assert!(seq_le(100, 100));
462 assert!(seq_le(100, 200));
463 assert!(seq_ge(200, 100));
464 assert!(seq_ge(100, 100));
465 assert!(!seq_ge(100, 200));
466 }
467
468 #[test]
469 fn test_seq_gt_wrapping() {
470 let a = 5u32;
471 let b = u32::MAX - 5;
472 assert!(seq_gt(a, b)); }
474
475 #[test]
478 fn test_sack_block_contains() {
479 let block = SackBlock::new(1000, 2000);
480 assert!(block.contains(1000));
481 assert!(block.contains(1500));
482 assert!(block.contains(1999));
483 assert!(!block.contains(2000));
484 assert!(!block.contains(999));
485 }
486
487 #[test]
488 fn test_sack_block_len() {
489 let block = SackBlock::new(1000, 2000);
490 assert_eq!(block.len(), 1000);
491
492 let empty = SackBlock::new(500, 500);
493 assert!(empty.is_empty());
494 }
495
496 #[test]
497 fn test_sack_block_overlap_and_merge() {
498 let mut a = SackBlock::new(100, 200);
499 let b = SackBlock::new(150, 300);
500 assert!(a.overlaps_or_adjacent(&b));
501 a.merge(&b);
502 assert_eq!(a.left_edge, 100);
503 assert_eq!(a.right_edge, 300);
504 }
505
506 #[test]
509 fn test_parse_sack_blocks() {
510 let mut opts = vec![TCP_OPT_SACK, 18]; opts.extend_from_slice(&1000u32.to_be_bytes());
513 opts.extend_from_slice(&2000u32.to_be_bytes());
514 opts.extend_from_slice(&3000u32.to_be_bytes());
515 opts.extend_from_slice(&4000u32.to_be_bytes());
516
517 let blocks = parse_sack_blocks(&opts);
518 assert_eq!(blocks.len(), 2);
519 assert_eq!(blocks[0], SackBlock::new(1000, 2000));
520 assert_eq!(blocks[1], SackBlock::new(3000, 4000));
521 }
522
523 #[test]
524 fn test_has_sack_permitted() {
525 let opts = vec![
526 TCP_OPT_NOP,
527 TCP_OPT_SACK_PERMITTED,
528 TCP_OPT_SACK_PERMITTED_LEN,
529 ];
530 assert!(has_sack_permitted(&opts));
531
532 let no_sack = vec![TCP_OPT_NOP, TCP_OPT_EOL];
533 assert!(!has_sack_permitted(&no_sack));
534 }
535
536 #[test]
537 fn test_serialize_sack_blocks() {
538 let blocks = vec![SackBlock::new(1000, 2000), SackBlock::new(3000, 4000)];
539 let serialized = serialize_sack_blocks(&blocks);
540 assert_eq!(serialized[0], TCP_OPT_SACK);
541 assert_eq!(serialized[1], 18); let parsed = parse_sack_blocks(&serialized);
543 assert_eq!(parsed, blocks);
544 }
545
546 #[test]
547 fn test_serialize_sack_permitted() {
548 let opt = serialize_sack_permitted();
549 assert_eq!(opt.len(), 2);
550 assert!(has_sack_permitted(&opt));
551 }
552
553 #[test]
556 fn test_scoreboard_mark_and_query() {
557 let mut sb = SackScoreboard::new();
558 sb.mark_sacked(1000, 2000);
559 sb.mark_sacked(3000, 4000);
560
561 assert!(sb.is_sacked(1500));
562 assert!(sb.is_sacked(3500));
563 assert!(!sb.is_sacked(2500));
564 assert_eq!(sb.block_count(), 2);
565 }
566
567 #[test]
568 fn test_scoreboard_merge_overlapping() {
569 let mut sb = SackScoreboard::new();
570 sb.mark_sacked(1000, 2000);
571 sb.mark_sacked(1500, 3000);
572
573 assert_eq!(sb.block_count(), 1);
574 assert_eq!(sb.blocks()[0], SackBlock::new(1000, 3000));
575 }
576
577 #[test]
578 fn test_scoreboard_merge_adjacent() {
579 let mut sb = SackScoreboard::new();
580 sb.mark_sacked(1000, 2000);
581 sb.mark_sacked(2000, 3000);
582
583 assert_eq!(sb.block_count(), 1);
584 assert_eq!(sb.blocks()[0], SackBlock::new(1000, 3000));
585 }
586
587 #[test]
588 fn test_scoreboard_merge_multiple() {
589 let mut sb = SackScoreboard::new();
590 sb.mark_sacked(1000, 2000);
591 sb.mark_sacked(3000, 4000);
592 sb.mark_sacked(5000, 6000);
593 sb.mark_sacked(1500, 5500);
595
596 assert_eq!(sb.block_count(), 1);
597 assert_eq!(sb.blocks()[0], SackBlock::new(1000, 6000));
598 }
599
600 #[test]
601 fn test_scoreboard_clear_below() {
602 let mut sb = SackScoreboard::new();
603 sb.mark_sacked(1000, 2000);
604 sb.mark_sacked(3000, 4000);
605
606 sb.clear_below(1500);
608 assert_eq!(sb.block_count(), 2);
609 assert_eq!(sb.blocks()[0].left_edge, 1500);
610
611 sb.clear_below(2500);
613 assert_eq!(sb.block_count(), 1);
614 assert_eq!(sb.blocks()[0], SackBlock::new(3000, 4000));
615 }
616
617 #[test]
618 fn test_scoreboard_highest_sacked() {
619 let mut sb = SackScoreboard::new();
620 assert_eq!(sb.highest_sacked(), None);
621
622 sb.mark_sacked(1000, 2000);
623 assert_eq!(sb.highest_sacked(), Some(2000));
624
625 sb.mark_sacked(5000, 6000);
626 assert_eq!(sb.highest_sacked(), Some(6000));
627 }
628
629 #[test]
630 fn test_scoreboard_holes() {
631 let mut sb = SackScoreboard::new();
632 sb.mark_sacked(2000, 3000);
633 sb.mark_sacked(4000, 5000);
634
635 let holes = sb.holes(1000);
636 assert_eq!(holes.len(), 2);
637 assert_eq!(holes[0], (1000, 1000)); assert_eq!(holes[1], (3000, 1000)); }
640
641 #[test]
642 fn test_scoreboard_next_retransmit() {
643 let mut sb = SackScoreboard::new();
644 sb.mark_sacked(2000, 3000);
645 sb.mark_sacked(4000, 5000);
646
647 let next = sb.next_retransmit(1000);
649 assert_eq!(next, Some((1000, 1000)));
650
651 let next = sb.next_retransmit(3000);
653 assert_eq!(next, Some((3000, 1000)));
654 }
655
656 #[test]
657 fn test_scoreboard_no_holes() {
658 let mut sb = SackScoreboard::new();
659 sb.mark_sacked(1000, 3000);
660
661 let next = sb.next_retransmit(1000);
663 assert_eq!(next, None);
664
665 let holes = sb.holes(1000);
666 assert!(holes.is_empty());
667 }
668
669 #[test]
670 fn test_scoreboard_wrapping_sequence() {
671 let mut sb = SackScoreboard::new();
672 let near_max = u32::MAX - 500;
674 let past_wrap = 500u32;
675
676 sb.mark_sacked(near_max, u32::MAX);
677 sb.mark_sacked(0, past_wrap);
678
679 assert_eq!(sb.block_count(), 2);
686
687 assert!(sb.is_sacked(near_max + 100));
689 assert!(sb.is_sacked(200));
690 }
691}