1use crate::error::{DescriptorError, Result};
26use std::sync::atomic::{AtomicU64, Ordering};
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum DescriptorType {
31 DataFrame,
33 ControlMessage,
35 Reserved,
37}
38
39#[repr(C, align(8))]
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub struct XdpDesc {
45 pub addr: u64,
47 pub len: u32,
49 pub options: u32,
51}
52
53const _: () = assert!(
56 core::mem::size_of::<XdpDesc>() == 16,
57 "XdpDesc 必须与内核 xdp_desc 同为 16 字节"
58);
59
60impl XdpDesc {
61 #[inline]
63 pub const fn zero() -> Self {
64 Self {
65 addr: 0,
66 len: 0,
67 options: 0,
68 }
69 }
70
71 #[inline]
76 pub fn is_zero(&self) -> bool {
77 self.addr == 0 && self.len == 0 && self.options == 0
78 }
79
80 #[inline]
82 pub fn as_u64_slice(&self) -> [u64; 2] {
83 [self.addr, (self.len as u64) | ((self.options as u64) << 32)]
86 }
87
88 #[inline]
90 pub fn from_u64_slice(raw: [u64; 2]) -> Self {
91 Self {
92 addr: raw[0],
93 len: (raw[1] as u32),
94 options: (raw[1] >> 32) as u32,
95 }
96 }
97}
98
99impl Default for XdpDesc {
100 fn default() -> Self {
101 Self::zero()
102 }
103}
104
105#[derive(Debug, Clone, Copy, PartialEq, Eq)]
113pub struct Descriptor {
114 xdp: XdpDesc,
116 index: u32,
118 generation: u16,
120 owner: u16,
122 desc_type: DescriptorType,
124}
125
126pub const MAX_FRAME_INDEX: u64 = (1 << 20) - 1;
132
133impl Descriptor {
134 #[inline]
136 pub fn new(
137 xdp: XdpDesc,
138 index: u32,
139 owner: u16,
140 generation: u16,
141 desc_type: DescriptorType,
142 ) -> Self {
143 Self {
144 xdp,
145 index,
146 owner,
147 generation,
148 desc_type,
149 }
150 }
151
152 #[inline]
164 pub fn from_xdp(xdp: XdpDesc, owner: u16, generation: u16, frame_shift: u32) -> Result<Self> {
165 let raw_index = xdp.addr >> frame_shift;
166 if raw_index > MAX_FRAME_INDEX {
167 return Err(DescriptorError::OutOfRange {
168 descriptor: xdp.addr,
169 max_valid: MAX_FRAME_INDEX,
170 }
171 .into());
172 }
173 let index = u32::try_from(raw_index).map_err(|_| DescriptorError::OutOfRange {
175 descriptor: xdp.addr,
176 max_valid: MAX_FRAME_INDEX,
177 })?;
178 Ok(Self {
179 xdp,
180 index,
181 owner,
182 generation,
183 desc_type: DescriptorType::DataFrame,
184 })
185 }
186
187 #[inline]
189 pub fn xdp_desc(&self) -> &XdpDesc {
190 &self.xdp
191 }
192
193 #[inline]
195 pub fn addr(&self) -> u64 {
196 self.xdp.addr
197 }
198
199 #[inline]
201 pub fn len(&self) -> u32 {
202 self.xdp.len
203 }
204
205 #[inline]
207 pub fn is_empty(&self) -> bool {
208 self.xdp.len == 0
209 }
210
211 #[inline]
213 pub fn options(&self) -> u32 {
214 self.xdp.options
215 }
216
217 #[inline]
219 pub fn index(&self) -> u32 {
220 self.index
221 }
222
223 #[inline]
225 pub fn owner(&self) -> u16 {
226 self.owner
227 }
228
229 #[inline]
231 pub fn generation(&self) -> u16 {
232 self.generation
233 }
234
235 #[inline]
237 pub fn descriptor_type(&self) -> DescriptorType {
238 self.desc_type
239 }
240
241 #[inline]
243 pub fn set_owner(&mut self, new_owner: u16) {
244 self.owner = new_owner;
245 }
246
247 #[inline]
249 pub fn set_generation(&mut self, new_generation: u16) {
250 self.generation = new_generation;
251 }
252
253 #[inline]
255 pub fn is_zero(&self) -> bool {
256 self.xdp.is_zero()
257 }
258
259 #[inline]
261 pub fn to_raw(&self) -> [u64; 2] {
262 self.xdp.as_u64_slice()
263 }
264}
265
266impl Default for Descriptor {
267 fn default() -> Self {
268 Self {
269 xdp: XdpDesc::zero(),
270 index: 0,
271 generation: 0,
272 owner: 0,
273 desc_type: DescriptorType::Reserved,
274 }
275 }
276}
277
278pub struct DescriptorEngine {
290 max_frame_index: u64,
292 frame_shift: u32,
294 current_generation: AtomicU64,
296 allocated_count: AtomicU64,
298 freed_count: AtomicU64,
300 active_bitmap: Vec<AtomicU64>,
302}
303
304impl std::fmt::Debug for DescriptorEngine {
305 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
306 f.debug_struct("DescriptorEngine")
307 .field("max_frame_index", &self.max_frame_index)
308 .field("current_generation", &self.current_generation)
309 .field("allocated_count", &self.allocated_count)
310 .field("freed_count", &self.freed_count)
311 .finish()
312 }
313}
314
315impl DescriptorEngine {
316 pub fn new(max_frames: u64) -> Result<Self> {
326 Self::with_frame_shift(max_frames, 12)
328 }
329
330 pub fn with_frame_shift(max_frames: u64, frame_shift: u32) -> Result<Self> {
346 if !(11..=15).contains(&frame_shift) {
347 return Err(DescriptorError::InvalidFrameShift(frame_shift).into());
348 }
349 if max_frames > MAX_FRAME_INDEX + 1 {
350 return Err(DescriptorError::InvalidCapacity(max_frames).into());
351 }
352 Ok(Self::new_unchecked(max_frames, frame_shift))
353 }
354
355 fn new_unchecked(max_frames: u64, frame_shift: u32) -> Self {
358 let bitmap_words = max_frames.div_ceil(64);
359 let active_bitmap = (0..bitmap_words)
360 .map(|_| AtomicU64::new(0))
361 .collect();
362
363 Self {
364 max_frame_index: max_frames.saturating_sub(1),
365 frame_shift,
366 current_generation: AtomicU64::new(1),
367 allocated_count: AtomicU64::new(0),
368 freed_count: AtomicU64::new(0),
369 active_bitmap,
370 }
371 }
372
373 #[inline]
375 pub fn frame_shift(&self) -> u32 {
376 self.frame_shift
377 }
378
379 pub fn allocate(&self, frame_index: u32, owner: u16) -> Result<Descriptor> {
388 if u64::from(frame_index) > self.max_frame_index {
391 return Err(DescriptorError::OutOfRange {
392 descriptor: u64::from(frame_index) << self.frame_shift,
393 max_valid: self.max_frame_index,
394 }
395 .into());
396 }
397
398 if self.get_bitmap(frame_index) {
401 return Err(DescriptorError::AlreadyAllocated(u64::from(frame_index)).into());
402 }
403
404 let generation = self.current_generation.load(Ordering::Relaxed) as u16;
405
406 self.set_bitmap(frame_index, true);
408
409 self.allocated_count.fetch_add(1, Ordering::Relaxed);
410
411 let xdp = XdpDesc {
413 addr: u64::from(frame_index) << self.frame_shift,
414 len: 0,
415 options: 0,
416 };
417
418 Ok(Descriptor::new(
419 xdp,
420 frame_index,
421 owner,
422 generation,
423 DescriptorType::DataFrame,
424 ))
425 }
426
427 pub fn release(&self, desc: &Descriptor) -> Result<()> {
435 let index = desc.index();
436 if !self.get_bitmap(index) {
437 return Err(DescriptorError::AlreadyFreed(desc.addr()).into());
438 }
439
440 self.set_bitmap(index, false);
441 self.freed_count.fetch_add(1, Ordering::Relaxed);
442
443 Ok(())
444 }
445
446 pub fn rollback_allocate(&self, frame_index: u32) -> bool {
458 if u64::from(frame_index) > self.max_frame_index {
459 return false;
460 }
461 if !self.get_bitmap(frame_index) {
462 return false;
463 }
464 self.set_bitmap(frame_index, false);
465 let _ = self.allocated_count.fetch_sub(1, Ordering::Relaxed);
467 true
468 }
469
470 pub fn verify(&self, desc: &Descriptor, expected_owner: u16) -> Result<()> {
482 let index = desc.index();
483 if (index as u64) > self.max_frame_index {
484 return Err(DescriptorError::OutOfRange {
485 descriptor: desc.addr(),
486 max_valid: self.max_frame_index,
487 }
488 .into());
489 }
490
491 if !self.get_bitmap(index) {
493 return Err(DescriptorError::AlreadyFreed(desc.addr()).into());
494 }
495
496 if desc.owner() != expected_owner {
497 return Err(DescriptorError::OwnershipMismatch {
498 expected: expected_owner as u32,
499 actual: desc.owner() as u32,
500 }
501 .into());
502 }
503
504 Ok(())
505 }
506
507 pub fn transfer_ownership(
519 &self,
520 desc: &Descriptor,
521 old_owner: u16,
522 new_owner: u16,
523 ) -> Result<Descriptor> {
524 self.verify(desc, old_owner)?;
525
526 let next = self.current_generation.fetch_add(1, Ordering::Relaxed).wrapping_add(1);
529 let new_generation = u16::try_from(next).map_err(|_| {
530 DescriptorError::TransactionFailed(format!("代际号 {next} 超出 u16 范围"))
531 })?;
532 let mut new_desc = *desc;
533 new_desc.set_owner(new_owner);
534 new_desc.set_generation(new_generation);
535
536 Ok(new_desc)
537 }
538
539 #[inline]
544 pub fn is_allocated(&self, index: u32) -> bool {
545 self.get_bitmap(index)
546 }
547
548 #[inline]
558 pub fn bump_generation(&self) -> Result<u64> {
559 let next = self
560 .current_generation
561 .fetch_add(1, Ordering::Relaxed)
562 .wrapping_add(1);
563 if next > u64::from(u16::MAX) {
564 return Err(DescriptorError::TransactionFailed(format!(
565 "代际号 {next} 超出 u16 范围"
566 ))
567 .into());
568 }
569 Ok(next)
570 }
571
572 #[inline]
574 pub fn conservation_stats(&self) -> (u64, u64) {
575 (
576 self.allocated_count.load(Ordering::Relaxed),
577 self.freed_count.load(Ordering::Relaxed),
578 )
579 }
580
581 pub fn verify_conservation(&self) -> bool {
583 let (allocated, freed) = self.conservation_stats();
584 let active = self.count_active();
585 allocated == freed + active
586 }
587
588 fn count_active(&self) -> u64 {
590 let mut count = 0u64;
591 for word in &self.active_bitmap {
592 count += word.load(Ordering::Relaxed).count_ones() as u64;
593 }
594 count
595 }
596
597 fn set_bitmap(&self, index: u32, value: bool) {
599 let word_idx = (index / 64) as usize;
600 let bit_idx = index % 64;
601 if word_idx < self.active_bitmap.len() {
602 if value {
603 self.active_bitmap[word_idx].fetch_or(1u64 << bit_idx, Ordering::Relaxed);
604 } else {
605 self.active_bitmap[word_idx].fetch_and(!(1u64 << bit_idx), Ordering::Relaxed);
606 }
607 }
608 }
609
610 fn get_bitmap(&self, index: u32) -> bool {
612 let word_idx = (index / 64) as usize;
613 let bit_idx = index % 64;
614 if word_idx < self.active_bitmap.len() {
615 (self.active_bitmap[word_idx].load(Ordering::Relaxed) >> bit_idx) & 1 == 1
616 } else {
617 false
618 }
619 }
620}
621
622#[cfg(test)]
623mod tests {
624 use super::*;
625 use crate::error::LinuxError;
626
627 #[test]
628 fn test_xdp_desc_zero() {
629 let desc = XdpDesc::zero();
630 assert!(desc.is_zero());
631 assert_eq!(desc.addr, 0);
632 assert_eq!(desc.len, 0);
633 assert_eq!(desc.options, 0);
634 }
635
636 #[test]
637 fn test_xdp_desc_roundtrip() {
638 let desc = XdpDesc {
639 addr: 0x1000,
640 len: 1500,
641 options: 0x42,
642 };
643 let raw = desc.as_u64_slice();
644 let recovered = XdpDesc::from_u64_slice(raw);
645 assert_eq!(recovered, desc);
646 }
647
648 #[test]
649 fn test_descriptor_creation() {
650 let xdp = XdpDesc {
651 addr: 4096,
652 len: 1500,
653 options: 0,
654 };
655 let desc = Descriptor::new(xdp, 1, 1, 1, DescriptorType::DataFrame);
656 assert_eq!(desc.index(), 1);
657 assert_eq!(desc.addr(), 4096);
658 assert_eq!(desc.len(), 1500);
659 assert_eq!(desc.owner(), 1);
660 assert_eq!(desc.generation(), 1);
661 assert_eq!(desc.descriptor_type(), DescriptorType::DataFrame);
662 }
663
664 #[test]
665 fn test_descriptor_modify() {
666 let xdp = XdpDesc::zero();
667 let mut desc = Descriptor::new(xdp, 0, 1, 1, DescriptorType::DataFrame);
668 desc.set_owner(2);
669 assert_eq!(desc.owner(), 2);
670 desc.set_generation(5);
671 assert_eq!(desc.generation(), 5);
672 }
673
674 #[test]
675 fn test_descriptor_from_xdp() {
676 let xdp = XdpDesc {
677 addr: 8192, len: 64,
679 options: 0,
680 };
681 let desc = Descriptor::from_xdp(xdp, 3, 42, 12).unwrap();
682 assert_eq!(desc.index(), 2);
683 assert_eq!(desc.addr(), 8192);
684 assert_eq!(desc.owner(), 3);
685 assert_eq!(desc.generation(), 42);
686 }
687
688 #[test]
689 fn test_descriptor_from_xdp_out_of_range_rejected() {
690 let xdp = XdpDesc {
692 addr: (1u64 << 20) << 12,
693 len: 64,
694 options: 0,
695 };
696 let result = Descriptor::from_xdp(xdp, 1, 1, 12);
697 assert!(matches!(
698 result,
699 Err(LinuxError::Descriptor(DescriptorError::OutOfRange { .. }))
700 ));
701 }
702
703 #[test]
704 fn test_descriptor_from_xdp_high_bits_truncation_rejected() {
705 let xdp = XdpDesc {
707 addr: (1u64 << 32) << 12,
708 len: 0,
709 options: 0,
710 };
711 assert!(Descriptor::from_xdp(xdp, 1, 1, 12).is_err());
712 }
713
714 #[test]
715 fn test_descriptor_from_xdp_max_valid_index() {
716 let xdp = XdpDesc {
718 addr: MAX_FRAME_INDEX << 12,
719 len: 0,
720 options: 0,
721 };
722 let desc = Descriptor::from_xdp(xdp, 1, 1, 12).unwrap();
723 assert_eq!(desc.index() as u64, MAX_FRAME_INDEX);
724 }
725
726 #[test]
727 fn test_descriptor_from_xdp_non_default_frame_shift() {
728 let xdp = XdpDesc {
730 addr: 4096, len: 64,
732 options: 0,
733 };
734 let desc = Descriptor::from_xdp(xdp, 1, 1, 11).unwrap();
735 assert_eq!(desc.index(), 2);
736
737 let xdp2 = XdpDesc {
739 addr: 65536,
740 len: 64,
741 options: 0,
742 };
743 let desc2 = Descriptor::from_xdp(xdp2, 1, 1, 15).unwrap();
744 assert_eq!(desc2.index(), 2);
745 }
746
747 #[test]
748 fn test_descriptor_engine_allocate_release() {
749 let engine = DescriptorEngine::new(1024).unwrap();
750
751 let desc = engine.allocate(0, 1).unwrap();
752 assert_eq!(desc.index(), 0);
753 assert_eq!(desc.owner(), 1);
754 assert_eq!(desc.addr(), 0);
755
756 engine.verify(&desc, 1).unwrap();
757 engine.release(&desc).unwrap();
758
759 let result = engine.verify(&desc, 1);
760 assert!(result.is_err());
761 }
762
763 #[test]
764 fn test_descriptor_engine_zero_rejected() {
765 let engine = DescriptorEngine::new(1024).unwrap();
766 let zero = Descriptor::default();
767 let result = engine.verify(&zero, 1);
768 assert!(result.is_err());
769 }
770
771 #[test]
772 fn test_descriptor_ownership_transfer() {
773 let engine = DescriptorEngine::new(1024).unwrap();
774 let desc = engine.allocate(0, 1).unwrap();
775 let new_desc = engine.transfer_ownership(&desc, 1, 2).unwrap();
776 assert_eq!(new_desc.owner(), 2);
777 assert_eq!(new_desc.index(), 0);
778 }
779
780 #[test]
781 fn test_descriptor_conservation() {
782 let engine = DescriptorEngine::new(1024).unwrap();
783 let desc1 = engine.allocate(0, 1).unwrap();
784 let _desc2 = engine.allocate(1, 1).unwrap();
785 engine.release(&desc1).unwrap();
786 assert!(engine.verify_conservation());
787 let (allocated, freed) = engine.conservation_stats();
788 assert_eq!(allocated, 2);
789 assert_eq!(freed, 1);
790 }
791
792 #[test]
793 fn test_descriptor_out_of_range() {
794 let engine = DescriptorEngine::new(100).unwrap();
795 let xdp = XdpDesc {
796 addr: (2000u64) << 12,
797 len: 0,
798 options: 0,
799 };
800 let desc = Descriptor::new(xdp, 2000, 1, 1, DescriptorType::DataFrame);
801 let result = engine.verify(&desc, 1);
802 assert!(result.is_err());
803 }
804
805 #[test]
806 fn test_already_freed_rejected() {
807 let engine = DescriptorEngine::new(1024).unwrap();
808 let desc = engine.allocate(5, 1).unwrap();
809 engine.release(&desc).unwrap();
810 let result = engine.release(&desc);
811 assert!(result.is_err());
812 }
813
814 #[test]
815 fn test_ownership_mismatch() {
816 let engine = DescriptorEngine::new(1024).unwrap();
817 let desc = engine.allocate(10, 2).unwrap();
818 let result = engine.verify(&desc, 1);
819 assert!(result.is_err());
820 }
821
822 #[test]
823 fn test_frame_index_boundary_zero() {
824 let engine = DescriptorEngine::new(1024).unwrap();
825 let desc = engine.allocate(0, 1).unwrap();
826 assert_eq!(desc.index(), 0);
827 assert_eq!(desc.addr(), 0);
828 engine.verify(&desc, 1).unwrap();
829 }
830
831 #[test]
832 fn test_frame_index_boundary_one() {
833 let engine = DescriptorEngine::new(1024).unwrap();
834 let desc = engine.allocate(1, 1).unwrap();
835 assert_eq!(desc.index(), 1);
836 assert_eq!(desc.addr(), 4096);
837 engine.verify(&desc, 1).unwrap();
838 }
839
840 #[test]
841 fn test_frame_index_20bit_max() {
842 let max_frames = 0x100000u64; let engine = DescriptorEngine::new(max_frames).unwrap();
844
845 let max_index = (max_frames - 1) as u32;
846 let desc = engine.allocate(max_index, 1).unwrap();
847 assert_eq!(desc.index(), max_index);
848 assert_eq!(desc.addr(), (max_index as u64) << 12);
849 engine.verify(&desc, 1).unwrap();
850 }
851
852 #[test]
853 fn test_frame_index_out_of_range() {
854 let engine = DescriptorEngine::new(100).unwrap();
855 let xdp = XdpDesc {
856 addr: (200u64) << 12,
857 len: 0,
858 options: 0,
859 };
860 let desc = Descriptor::new(xdp, 200, 1, 1, DescriptorType::DataFrame);
861 let result = engine.verify(&desc, 1);
862 assert!(result.is_err());
863 }
864
865 #[test]
866 fn test_descriptor_default_is_zero() {
867 let desc = Descriptor::default();
868 assert!(desc.is_zero());
869 assert_eq!(desc.index(), 0);
870 assert_eq!(desc.owner(), 0);
871 assert_eq!(desc.generation(), 0);
872 assert_eq!(desc.descriptor_type(), DescriptorType::Reserved);
873 }
874
875 #[test]
876 fn test_xdp_desc_default_is_zero() {
877 let desc = XdpDesc::default();
878 assert!(desc.is_zero());
879 assert_eq!(desc.addr, 0);
880 assert_eq!(desc.len, 0);
881 assert_eq!(desc.options, 0);
882 }
883
884 #[test]
885 fn test_xdp_desc_not_zero_with_addr_only() {
886 let desc = XdpDesc {
887 addr: 4096,
888 len: 0,
889 options: 0,
890 };
891 assert!(!desc.is_zero());
892 }
893
894 #[test]
895 fn test_xdp_desc_not_zero_with_len_only() {
896 let desc = XdpDesc {
897 addr: 0,
898 len: 100,
899 options: 0,
900 };
901 assert!(!desc.is_zero());
902 }
903
904 #[test]
905 fn test_xdp_desc_not_zero_with_options_only() {
906 let desc = XdpDesc {
907 addr: 0,
908 len: 0,
909 options: 1,
910 };
911 assert!(!desc.is_zero());
912 }
913
914 #[test]
915 fn test_descriptor_to_raw_roundtrip() {
916 let xdp = XdpDesc {
917 addr: 0x12345678,
918 len: 1500,
919 options: 0xDEAD,
920 };
921 let desc = Descriptor::new(xdp, 0, 1, 2, DescriptorType::DataFrame);
922 let raw = desc.to_raw();
923 let recovered = XdpDesc::from_u64_slice(raw);
924 assert_eq!(recovered, xdp);
925 }
926
927 #[test]
928 fn test_generation_bump() {
929 let engine = DescriptorEngine::new(1024).unwrap();
930 let initial = engine.bump_generation().unwrap();
931 assert!(initial > 1);
932
933 let next = engine.bump_generation().unwrap();
934 assert_eq!(next, initial + 1);
935 }
936
937 #[test]
938 fn test_generation_bump_overflow_fail_closed() {
939 let engine = DescriptorEngine::new(1024).unwrap();
942 engine
943 .current_generation
944 .store(u64::from(u16::MAX), Ordering::Relaxed);
945 let result = engine.bump_generation();
946 assert!(result.is_err(), "代际号越界必须 Fail-Closed");
947 }
948
949 #[test]
950 fn test_transfer_ownership_increments_generation() {
951 let engine = DescriptorEngine::new(1024).unwrap();
952 let desc = engine.allocate(0, 1).unwrap();
953 let original_gen = desc.generation();
954
955 let new_desc = engine.transfer_ownership(&desc, 1, 2).unwrap();
956 assert_eq!(new_desc.owner(), 2);
957 assert_eq!(new_desc.index(), 0);
958 assert!(new_desc.generation() > original_gen);
959 }
960
961 #[test]
962 fn test_transfer_ownership_wrong_old_owner_fails() {
963 let engine = DescriptorEngine::new(1024).unwrap();
964 let desc = engine.allocate(0, 1).unwrap();
965 let result = engine.transfer_ownership(&desc, 99, 2);
966 assert!(result.is_err());
967 }
968
969 #[test]
970 fn test_transfer_ownership_generation_overflow_fails() {
971 let engine = DescriptorEngine::new(1024).unwrap();
973 let desc = engine.allocate(0, 1).unwrap();
974 engine.current_generation.store(u64::from(u16::MAX), Ordering::Relaxed);
976 let result = engine.transfer_ownership(&desc, 1, 2);
977 assert!(result.is_err(), "代际号越界必须 Fail-Closed");
978 }
979
980 #[test]
981 fn test_multiple_allocations_and_releases() {
982 let engine = DescriptorEngine::new(1024).unwrap();
983 let mut descs = Vec::new();
984
985 for i in 0..100 {
986 let desc = engine.allocate(i, (i % 10) as u16).unwrap();
987 descs.push(desc);
988 }
989
990 assert!(engine.verify_conservation());
991 let (allocated, freed) = engine.conservation_stats();
992 assert_eq!(allocated, 100);
993 assert_eq!(freed, 0);
994
995 for desc in &descs[..50] {
996 engine.release(desc).unwrap();
997 }
998
999 assert!(engine.verify_conservation());
1000 let (allocated, freed) = engine.conservation_stats();
1001 assert_eq!(allocated, 100);
1002 assert_eq!(freed, 50);
1003
1004 for desc in &descs[50..] {
1005 engine.release(desc).unwrap();
1006 }
1007
1008 assert!(engine.verify_conservation());
1009 let (allocated, freed) = engine.conservation_stats();
1010 assert_eq!(allocated, 100);
1011 assert_eq!(freed, 100);
1012 }
1013
1014 #[test]
1015 fn test_already_in_use_check() {
1016 let engine = DescriptorEngine::new(1024).unwrap();
1019 let desc = engine.allocate(42, 1).unwrap();
1020 engine.verify(&desc, 1).unwrap();
1021 assert!(engine.is_allocated(42));
1022
1023 let result = engine.allocate(42, 2);
1024 assert!(
1025 matches!(
1026 result,
1027 Err(LinuxError::Descriptor(DescriptorError::AlreadyAllocated(42)))
1028 ),
1029 "已分配帧重复分配必须返回 AlreadyAllocated,实际 {result:?}"
1030 );
1031 let (allocated, freed) = engine.conservation_stats();
1033 assert_eq!(allocated, 1);
1034 assert_eq!(freed, 0);
1035 assert!(engine.verify_conservation());
1036 }
1037
1038 #[test]
1039 fn test_engine_capacity_fail_closed_over_20bit() {
1040 assert!(DescriptorEngine::new((1u64 << 20) + 1).is_err());
1042 assert!(DescriptorEngine::new(u64::MAX).is_err());
1043 assert!(DescriptorEngine::with_frame_shift((1u64 << 20) + 1, 12).is_err());
1044 assert!(DescriptorEngine::new(1u64 << 20).is_ok());
1046 assert!(DescriptorEngine::with_frame_shift(1024, 16).is_err());
1047 }
1048
1049 #[test]
1050 fn test_descriptor_engine_debug_format() {
1051 let engine = DescriptorEngine::new(256).unwrap();
1052 let debug = format!("{:?}", engine);
1053 assert!(debug.contains("DescriptorEngine"));
1054 assert!(debug.contains("max_frame_index"));
1055 assert!(debug.contains("current_generation"));
1056 }
1057
1058 #[test]
1059 fn test_descriptor_type_variants() {
1060 let types = vec![
1061 DescriptorType::DataFrame,
1062 DescriptorType::ControlMessage,
1063 DescriptorType::Reserved,
1064 ];
1065 for desc_type in types {
1066 let xdp = XdpDesc::zero();
1067 let desc = Descriptor::new(xdp, 0, 0, 0, desc_type);
1068 assert_eq!(desc.descriptor_type(), desc_type);
1069 }
1070 }
1071
1072 #[test]
1073 fn test_large_descriptor_engine() {
1074 let engine = DescriptorEngine::new(65536).unwrap();
1075 let desc = engine.allocate(65535, 1).unwrap();
1076 assert_eq!(desc.index(), 65535);
1077 engine.verify(&desc, 1).unwrap();
1078 engine.release(&desc).unwrap();
1079 assert!(engine.verify_conservation());
1080 }
1081}