1#![allow(unsafe_code)]
34
35use crate::descriptor::XdpDesc;
36use crate::error::{Result, RingError};
37use std::sync::atomic::{AtomicU32, Ordering};
38
39pub const XDP_RING_NEED_WAKEUP: u32 = 0x1;
48
49pub const MAX_SIMULATED_CAPACITY: u32 = 1 << 20;
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub enum RingType {
59 Fill,
61 Rx,
63 Tx,
65 Completion,
67}
68
69#[derive(Debug, Clone, Copy)]
78pub struct RingOffsets {
79 pub producer: u64,
81 pub consumer: u64,
83 pub desc: u64,
85 pub flags: u64,
87 pub len: u64,
89}
90
91pub struct XskRing {
101 ring_type: RingType,
103 capacity: u32,
105 mask: u32,
107 storage: RingStorage,
109}
110
111enum RingStorage {
117 Simulated {
119 producer_idx: AtomicU32,
121 consumer_idx: AtomicU32,
123 descriptors: Vec<XdpDesc>,
125 },
126 Kernel(KernelRing),
128}
129
130struct KernelRing {
134 mmap_base: *mut u8,
136 mmap_len: usize,
138 producer: *mut AtomicU32,
140 consumer: *mut AtomicU32,
142 descs: *mut XdpDesc,
144 flags: Option<*const AtomicU32>,
146}
147
148impl Drop for KernelRing {
149 fn drop(&mut self) {
150 unsafe {
153 libc::munmap(self.mmap_base as *mut libc::c_void, self.mmap_len);
154 }
155 }
156}
157
158impl std::fmt::Debug for XskRing {
159 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
160 f.debug_struct("XskRing")
161 .field("ring_type", &self.ring_type)
162 .field("capacity", &self.capacity)
163 .field("producer_idx", &self.producer_index())
164 .field("consumer_idx", &self.consumer_index())
165 .field("kernel_mode", &self.is_kernel_mode())
166 .finish()
167 }
168}
169
170unsafe impl Send for XskRing {}
179unsafe impl Sync for XskRing {}
180
181impl XskRing {
182 pub fn new(ring_type: RingType, capacity: u32) -> Result<Self> {
202 if capacity == 0 {
203 return Err(RingError::InvalidOffsets(
204 "ring capacity 必须 > 0".to_string(),
205 )
206 .into());
207 }
208 let actual_capacity = capacity
209 .max(16)
210 .checked_next_power_of_two()
211 .ok_or_else(|| {
212 RingError::InvalidOffsets(format!(
213 "ring capacity {capacity} 超出最大可表示容量 2^31"
214 ))
215 })?;
216 if actual_capacity > MAX_SIMULATED_CAPACITY {
217 return Err(RingError::InvalidOffsets(format!(
218 "ring capacity {actual_capacity} 超出模拟模式上限 {MAX_SIMULATED_CAPACITY}"
219 ))
220 .into());
221 }
222 let mask = actual_capacity - 1;
223
224 Ok(Self {
225 ring_type,
226 capacity: actual_capacity,
227 mask,
228 storage: RingStorage::Simulated {
229 producer_idx: AtomicU32::new(0),
230 consumer_idx: AtomicU32::new(0),
231 descriptors: vec![XdpDesc::zero(); actual_capacity as usize],
232 },
233 })
234 }
235
236 pub unsafe fn with_kernel_ring(
257 ring_type: RingType,
258 mmap_base: *mut u8,
259 offsets: RingOffsets,
260 ) -> Result<Self> {
261 if mmap_base.is_null() {
263 return Err(RingError::InvalidOffsets("mmap_base 为空指针".to_string()).into());
264 }
265 let desc_area = offsets.len.checked_sub(offsets.desc).ok_or_else(|| {
267 RingError::InvalidOffsets(format!(
268 "desc 偏移 {} 超出 ring 长度 {}",
269 offsets.desc, offsets.len
270 ))
271 })?;
272 let desc_size = std::mem::size_of::<XdpDesc>() as u64;
273 let capacity_u64 = desc_area / desc_size;
274 if capacity_u64 == 0 || capacity_u64 > u64::from(u32::MAX) {
275 return Err(RingError::InvalidOffsets(format!(
276 "描述符容量 {capacity_u64} 非法"
277 ))
278 .into());
279 }
280 let capacity = capacity_u64 as u32;
281 if !capacity.is_power_of_two() {
284 return Err(RingError::InvalidOffsets(format!(
285 "容量 {capacity} 不是 2 的幂"
286 ))
287 .into());
288 }
289 let word = std::mem::size_of::<u32>() as u64;
291 for (name, off) in [
292 ("producer", offsets.producer),
293 ("consumer", offsets.consumer),
294 ] {
295 if off >= offsets.len || offsets.len - off < word {
296 return Err(RingError::InvalidOffsets(format!(
297 "{name} 偏移 {off} 越界(len={})",
298 offsets.len
299 ))
300 .into());
301 }
302 }
303 if offsets.flags > 0 && (offsets.flags >= offsets.len || offsets.len - offsets.flags < word)
304 {
305 return Err(RingError::InvalidOffsets(format!(
306 "flags 偏移 {} 越界(len={})",
307 offsets.flags, offsets.len
308 ))
309 .into());
310 }
311
312 let kernel = KernelRing {
316 mmap_base,
317 mmap_len: offsets.len as usize,
318 producer: unsafe { mmap_base.add(offsets.producer as usize) as *mut AtomicU32 },
319 consumer: unsafe { mmap_base.add(offsets.consumer as usize) as *mut AtomicU32 },
320 descs: unsafe { mmap_base.add(offsets.desc as usize) as *mut XdpDesc },
321 flags: if offsets.flags > 0 {
322 Some(unsafe { mmap_base.add(offsets.flags as usize) as *const AtomicU32 })
323 } else {
324 None
325 },
326 };
327
328 Ok(Self {
329 ring_type,
330 capacity,
331 mask: capacity - 1,
332 storage: RingStorage::Kernel(kernel),
333 })
334 }
335
336 #[inline]
342 fn ring_slot(base: u32, offset: u32, mask: u32) -> u32 {
343 base.wrapping_add(offset) & mask
344 }
345
346 #[inline]
348 fn producer_atomic(&self) -> &AtomicU32 {
349 match &self.storage {
350 RingStorage::Simulated { producer_idx, .. } => producer_idx,
351 RingStorage::Kernel(k) => unsafe { &*k.producer },
354 }
355 }
356
357 #[inline]
359 fn consumer_atomic(&self) -> &AtomicU32 {
360 match &self.storage {
361 RingStorage::Simulated { consumer_idx, .. } => consumer_idx,
362 RingStorage::Kernel(k) => unsafe { &*k.consumer },
364 }
365 }
366
367 #[inline]
369 fn read_desc(&self, slot: u32) -> XdpDesc {
370 match &self.storage {
371 RingStorage::Simulated { descriptors, .. } => descriptors[slot as usize],
372 RingStorage::Kernel(k) => unsafe { k.descs.add(slot as usize).read() },
376 }
377 }
378
379 #[inline]
381 fn write_desc(&mut self, slot: u32, desc: XdpDesc) {
382 match &mut self.storage {
383 RingStorage::Simulated { descriptors, .. } => descriptors[slot as usize] = desc,
384 RingStorage::Kernel(k) => unsafe { k.descs.add(slot as usize).write(desc) },
387 }
388 }
389
390 #[inline]
392 pub fn available_space(&self) -> u32 {
393 let producer = self.producer_atomic().load(Ordering::Relaxed);
394 let consumer = self.consumer_atomic().load(Ordering::Acquire);
395 self.capacity - (producer.wrapping_sub(consumer))
397 }
398
399 #[inline]
401 pub fn available_data(&self) -> u32 {
402 let producer = self.producer_atomic().load(Ordering::Acquire);
403 let consumer = self.consumer_atomic().load(Ordering::Relaxed);
404 producer.wrapping_sub(consumer)
405 }
406
407 pub fn enqueue_batch(&mut self, descriptors: &[XdpDesc]) -> Result<u32> {
415 if descriptors.is_empty() {
416 return Ok(0);
417 }
418
419 let available = self.available_space();
420 let to_enqueue = descriptors.len() as u32;
421
422 if to_enqueue > available {
423 return Err(RingError::BatchSizeExceeded {
424 requested: to_enqueue,
425 maximum: available,
426 }
427 .into());
428 }
429
430 let start_idx = self.producer_atomic().load(Ordering::Relaxed);
431
432 for (i, desc) in descriptors.iter().enumerate() {
433 let slot = Self::ring_slot(start_idx, i as u32, self.mask);
434 self.write_desc(slot, *desc);
435 }
436
437 self.producer_atomic()
440 .store(start_idx.wrapping_add(to_enqueue), Ordering::Release);
441
442 Ok(to_enqueue)
443 }
444
445 pub fn dequeue_batch(&mut self, max_batch: u32) -> Result<Vec<XdpDesc>> {
453 let available = self.available_data();
454 let to_dequeue = available.min(max_batch);
455
456 if to_dequeue == 0 {
457 return Ok(Vec::new());
458 }
459
460 let consumer = self.consumer_atomic().load(Ordering::Relaxed);
461 let mut result = Vec::with_capacity(to_dequeue as usize);
462
463 for i in 0..to_dequeue {
464 let slot = Self::ring_slot(consumer, i, self.mask);
465 result.push(self.read_desc(slot));
466 }
467
468 self.consumer_atomic()
470 .store(consumer.wrapping_add(to_dequeue), Ordering::Release);
471
472 Ok(result)
473 }
474
475 pub fn dequeue_batch_to(&mut self, buffer: &mut [XdpDesc]) -> Result<u32> {
483 let available = self.available_data();
484 let max = buffer.len() as u32;
485 let to_dequeue = available.min(max);
486
487 if to_dequeue == 0 {
488 return Ok(0);
489 }
490
491 let consumer = self.consumer_atomic().load(Ordering::Relaxed);
492
493 for (i, slot) in buffer.iter_mut().enumerate().take(to_dequeue as usize) {
494 let idx = Self::ring_slot(consumer, i as u32, self.mask);
495 *slot = self.read_desc(idx);
496 }
497
498 self.consumer_atomic()
499 .store(consumer.wrapping_add(to_dequeue), Ordering::Release);
500
501 Ok(to_dequeue)
502 }
503
504 pub fn enqueue_batch_from(&mut self, descriptors: &[XdpDesc]) -> Result<u32> {
512 self.enqueue_batch(descriptors)
513 }
514
515 pub fn revert_consumer(&mut self, count: u32) {
519 debug_assert!(
520 count <= self.consumer_index(),
521 "回退计数 {count} 超过当前消费者索引 {}",
522 self.consumer_index()
523 );
524 self.consumer_atomic().fetch_sub(count, Ordering::Release);
525 }
526
527 pub fn revert_producer(&mut self, count: u32) {
531 debug_assert!(
532 count <= self.producer_index(),
533 "回退计数 {count} 超过当前生产者索引 {}",
534 self.producer_index()
535 );
536 self.producer_atomic().fetch_sub(count, Ordering::Release);
537 }
538
539 #[inline]
541 pub fn capacity(&self) -> u32 {
542 self.capacity
543 }
544
545 #[inline]
547 pub fn ring_type(&self) -> RingType {
548 self.ring_type
549 }
550
551 #[inline]
553 pub fn producer_index(&self) -> u32 {
554 self.producer_atomic().load(Ordering::Relaxed)
555 }
556
557 #[inline]
559 pub fn consumer_index(&self) -> u32 {
560 self.consumer_atomic().load(Ordering::Relaxed)
561 }
562
563 #[inline]
565 pub fn is_kernel_mode(&self) -> bool {
566 matches!(self.storage, RingStorage::Kernel(_))
567 }
568
569 #[inline]
577 pub fn need_wakeup(&self) -> bool {
578 match &self.storage {
579 RingStorage::Kernel(k) => match k.flags {
580 Some(ptr) => unsafe {
583 let flags = (*ptr).load(Ordering::Acquire);
584 (flags & XDP_RING_NEED_WAKEUP) != 0
585 },
586 None => false,
587 },
588 RingStorage::Simulated { .. } => false,
589 }
590 }
591}
592
593#[cfg(test)]
594mod tests {
595 use super::*;
596
597 fn make_desc(addr: u64, len: u32) -> XdpDesc {
598 XdpDesc {
599 addr,
600 len,
601 options: 0,
602 }
603 }
604
605 #[test]
606 fn test_ring_creation() {
607 let ring = XskRing::new(RingType::Fill, 64).unwrap();
608 assert_eq!(ring.capacity(), 64);
609 assert_eq!(ring.ring_type(), RingType::Fill);
610 assert_eq!(ring.available_data(), 0);
611 assert_eq!(ring.available_space(), 64);
612 assert!(!ring.is_kernel_mode());
613 }
614
615 #[test]
616 fn test_ring_capacity_power_of_two() {
617 let ring = XskRing::new(RingType::Rx, 10).unwrap();
618 assert_eq!(ring.capacity(), 16);
619 }
620
621 #[test]
622 fn test_ring_enqueue_dequeue() {
623 let mut ring = XskRing::new(RingType::Tx, 16).unwrap();
624
625 let descs = [
626 make_desc(0, 64),
627 make_desc(4096, 128),
628 make_desc(8192, 256),
629 make_desc(12288, 512),
630 make_desc(16384, 1024),
631 ];
632 let enqueued = ring.enqueue_batch(&descs).unwrap();
633 assert_eq!(enqueued, 5);
634 assert_eq!(ring.available_data(), 5);
635 assert_eq!(ring.available_space(), 11);
636
637 let dequeued = ring.dequeue_batch(3).unwrap();
638 assert_eq!(dequeued.len(), 3);
639 assert_eq!(dequeued[0].addr, 0);
640 assert_eq!(dequeued[1].addr, 4096);
641 assert_eq!(dequeued[2].addr, 8192);
642 assert_eq!(ring.available_data(), 2);
643
644 let dequeued = ring.dequeue_batch(10).unwrap();
645 assert_eq!(dequeued.len(), 2);
646 assert_eq!(ring.available_data(), 0);
647 }
648
649 #[test]
650 fn test_ring_full() {
651 let mut ring = XskRing::new(RingType::Completion, 16).unwrap();
652 let descs: Vec<XdpDesc> = (0..17).map(|i| make_desc(i * 4096, 0)).collect();
653 let result = ring.enqueue_batch(&descs);
654 assert!(result.is_err());
655 }
656
657 #[test]
658 fn test_ring_wrapping() {
659 let mut ring = XskRing::new(RingType::Fill, 16).unwrap();
660
661 let descs: Vec<XdpDesc> = (0..16).map(|i| make_desc(i * 4096, 0)).collect();
662 ring.enqueue_batch(&descs).unwrap();
663 ring.dequeue_batch(16).unwrap();
664
665 assert_eq!(ring.available_data(), 0);
666 assert_eq!(ring.available_space(), 16);
667
668 ring.enqueue_batch(&[make_desc(65536, 0), make_desc(69632, 0)]).unwrap();
669 assert_eq!(ring.available_data(), 2);
670 }
671
672 #[test]
673 fn test_ring_dequeue_to_buffer() {
674 let mut ring = XskRing::new(RingType::Rx, 8).unwrap();
675 let descs = [make_desc(1024, 100), make_desc(2048, 200), make_desc(3072, 300), make_desc(4096, 400)];
676 ring.enqueue_batch(&descs).unwrap();
677
678 let mut buffer = [XdpDesc::zero(); 3];
679 let count = ring.dequeue_batch_to(&mut buffer).unwrap();
680 assert_eq!(count, 3);
681 assert_eq!(buffer[0].addr, 1024);
682 assert_eq!(buffer[1].addr, 2048);
683 assert_eq!(buffer[2].addr, 3072);
684 }
685
686 #[test]
687 fn test_ring_revert() {
688 let mut ring = XskRing::new(RingType::Tx, 16).unwrap();
689
690 ring.enqueue_batch(&[make_desc(0, 0), make_desc(4096, 0), make_desc(8192, 0)])
691 .unwrap();
692 assert_eq!(ring.available_data(), 3);
693
694 ring.revert_producer(2);
695 assert_eq!(ring.available_data(), 1);
696
697 ring.dequeue_batch(1).unwrap();
698 assert_eq!(ring.available_data(), 0);
699
700 ring.revert_consumer(1);
701 assert_eq!(ring.available_data(), 1);
702 }
703
704 #[test]
705 fn test_ring_empty_dequeue() {
706 let mut ring = XskRing::new(RingType::Rx, 16).unwrap();
707 let result = ring.dequeue_batch(10).unwrap();
708 assert!(result.is_empty());
709 }
710
711 #[test]
712 fn test_ring_zero_length() {
713 let mut ring = XskRing::new(RingType::Fill, 16).unwrap();
714 let result = ring.enqueue_batch(&[]).unwrap();
715 assert_eq!(result, 0);
716 }
717
718 #[test]
719 fn test_ring_capacity_minimum_16() {
720 let ring = XskRing::new(RingType::Rx, 1).unwrap();
721 assert_eq!(ring.capacity(), 16);
722 assert!(ring.capacity().is_power_of_two());
723 }
724
725 #[test]
726 fn test_ring_capacity_exact_power_of_two() {
727 for cap in [16, 32, 64, 128, 256, 512, 1024, 2048, 4096] {
728 let ring = XskRing::new(RingType::Tx, cap).unwrap();
729 assert_eq!(ring.capacity(), cap);
730 assert!(ring.capacity().is_power_of_two());
731 }
732 }
733
734 #[test]
735 fn test_ring_capacity_rounds_up() {
736 let test_cases = vec![
737 (17, 32),
738 (33, 64),
739 (100, 128),
740 (255, 256),
741 (1000, 1024),
742 ];
743 for (input, expected) in test_cases {
744 let ring = XskRing::new(RingType::Completion, input).unwrap();
745 assert_eq!(
746 ring.capacity(),
747 expected,
748 "Input {} should round up to {}",
749 input,
750 expected
751 );
752 assert!(ring.capacity().is_power_of_two());
753 }
754 }
755
756 #[test]
757 fn test_ring_new_fail_closed_on_invalid_capacity() {
758 assert!(XskRing::new(RingType::Rx, 0).is_err());
760 assert!(XskRing::new(RingType::Rx, u32::MAX).is_err());
763 assert!(XskRing::new(RingType::Rx, (1u32 << 31) + 1).is_err());
764 assert!(XskRing::new(RingType::Rx, 1u32 << 31).is_err());
768 assert!(XskRing::new(RingType::Rx, MAX_SIMULATED_CAPACITY + 1).is_err());
769 assert!(XskRing::new(RingType::Rx, MAX_SIMULATED_CAPACITY).is_ok());
771 }
772
773 #[test]
774 fn test_ring_empty_boundary() {
775 let mut ring = XskRing::new(RingType::Rx, 32).unwrap();
776 assert_eq!(ring.available_data(), 0);
777 assert_eq!(ring.available_space(), 32);
778
779 let result = ring.dequeue_batch(10).unwrap();
780 assert!(result.is_empty());
781 assert_eq!(ring.consumer_index(), 0);
782 }
783
784 #[test]
785 fn test_ring_full_boundary() {
786 let mut ring = XskRing::new(RingType::Tx, 16).unwrap();
787 let descs: Vec<XdpDesc> = (0..16).map(|i| make_desc(i * 4096, 64)).collect();
788
789 let enqueued = ring.enqueue_batch(&descs).unwrap();
790 assert_eq!(enqueued, 16);
791 assert_eq!(ring.available_data(), 16);
792 assert_eq!(ring.available_space(), 0);
793
794 let overflow = ring.enqueue_batch(&[make_desc(65536, 0)]);
795 assert!(overflow.is_err());
796 }
797
798 #[test]
799 fn test_ring_full_then_partial_consume() {
800 let mut ring = XskRing::new(RingType::Rx, 16).unwrap();
801 let descs: Vec<XdpDesc> = (0..16).map(|i| make_desc(i * 4096, 64)).collect();
802 ring.enqueue_batch(&descs).unwrap();
803 assert_eq!(ring.available_space(), 0);
804
805 let consumed = ring.dequeue_batch(5).unwrap();
806 assert_eq!(consumed.len(), 5);
807 assert_eq!(ring.available_space(), 5);
808 assert_eq!(ring.available_data(), 11);
809 }
810
811 #[test]
812 fn test_ring_index_wrapping_producer() {
813 let mut ring = XskRing::new(RingType::Fill, 16).unwrap();
814
815 for i in 0..16 {
816 ring.enqueue_batch(&[make_desc(i * 4096, 0)]).unwrap();
817 }
818 assert_eq!(ring.producer_index(), 16);
819
820 ring.dequeue_batch(8).unwrap();
821 assert_eq!(ring.consumer_index(), 8);
822
823 for i in 16..24 {
824 ring.enqueue_batch(&[make_desc(i * 4096, 0)]).unwrap();
825 }
826 assert_eq!(ring.producer_index(), 24);
827 assert_eq!(ring.available_data(), 16);
828 }
829
830 #[test]
831 fn test_ring_index_wrapping_consumer() {
832 let mut ring = XskRing::new(RingType::Rx, 16).unwrap();
833
834 for _ in 0..3 {
835 let descs: Vec<XdpDesc> = (0..16).map(|i| make_desc(i * 4096, 0)).collect();
836 ring.enqueue_batch(&descs).unwrap();
837 let consumed = ring.dequeue_batch(16).unwrap();
838 assert_eq!(consumed.len(), 16);
839 }
840
841 assert_eq!(ring.producer_index(), 48);
842 assert_eq!(ring.consumer_index(), 48);
843 assert_eq!(ring.available_data(), 0);
844 }
845
846 #[test]
847 fn test_ring_batch_exceeds_available_space() {
848 let mut ring = XskRing::new(RingType::Tx, 32).unwrap();
849 let descs: Vec<XdpDesc> = (0..10).map(|i| make_desc(i * 4096, 0)).collect();
850 ring.enqueue_batch(&descs).unwrap();
851
852 assert_eq!(ring.available_space(), 22);
853
854 let too_many: Vec<XdpDesc> = (0..30).map(|i| make_desc(i * 4096, 0)).collect();
855 let result = ring.enqueue_batch(&too_many);
856 assert!(result.is_err());
857 }
858
859 #[test]
860 fn test_ring_dequeue_batch_to_empty_buffer() {
861 let mut ring = XskRing::new(RingType::Rx, 16).unwrap();
862 let descs = [make_desc(1024, 100)];
863 ring.enqueue_batch(&descs).unwrap();
864
865 let mut buffer = [];
866 let count = ring.dequeue_batch_to(&mut buffer).unwrap();
867 assert_eq!(count, 0);
868 }
869
870 #[test]
871 fn test_ring_enqueue_batch_from_alias() {
872 let mut ring = XskRing::new(RingType::Fill, 16).unwrap();
873 let descs = [make_desc(4096, 128), make_desc(8192, 256)];
874 let count = ring.enqueue_batch_from(&descs).unwrap();
875 assert_eq!(count, 2);
876 assert_eq!(ring.available_data(), 2);
877 }
878
879 #[test]
880 fn test_ring_revert_producer_zero() {
881 let mut ring = XskRing::new(RingType::Tx, 16).unwrap();
882 ring.revert_producer(0);
883 assert_eq!(ring.producer_index(), 0);
884 assert_eq!(ring.available_data(), 0);
885 }
886
887 #[test]
888 fn test_ring_revert_consumer_zero() {
889 let mut ring = XskRing::new(RingType::Rx, 16).unwrap();
890 ring.revert_consumer(0);
891 assert_eq!(ring.consumer_index(), 0);
892 assert_eq!(ring.available_data(), 0);
893 }
894
895 #[test]
896 fn test_ring_types_all_work() {
897 let types = vec![
898 RingType::Fill,
899 RingType::Rx,
900 RingType::Tx,
901 RingType::Completion,
902 ];
903 for ring_type in types {
904 let mut ring = XskRing::new(ring_type, 16).unwrap();
905 assert_eq!(ring.ring_type(), ring_type);
906 let desc = make_desc(0, 0);
907 ring.enqueue_batch(&[desc]).unwrap();
908 let result = ring.dequeue_batch(1).unwrap();
909 assert_eq!(result.len(), 1);
910 }
911 }
912
913 #[test]
914 fn test_ring_fifo_order() {
915 let mut ring = XskRing::new(RingType::Rx, 32).unwrap();
916 let descs: Vec<XdpDesc> = (0..10u32).map(|i| make_desc(i as u64 * 4096, i * 100)).collect();
917
918 ring.enqueue_batch(&descs).unwrap();
919 let dequeued = ring.dequeue_batch(10).unwrap();
920
921 for (i, desc) in dequeued.iter().enumerate() {
922 assert_eq!(desc.addr, i as u64 * 4096);
923 assert_eq!(desc.len, i as u32 * 100);
924 }
925 }
926
927 #[test]
928 fn test_need_wakeup_simulated_mode() {
929 let ring = XskRing::new(RingType::Tx, 64).unwrap();
931 assert!(!ring.need_wakeup());
932
933 let fill_ring = XskRing::new(RingType::Fill, 64).unwrap();
934 assert!(!fill_ring.need_wakeup());
935 }
936
937 #[test]
938 fn test_xdp_ring_need_wakeup_constant() {
939 assert_eq!(XDP_RING_NEED_WAKEUP, 0x1);
941 }
942
943 #[test]
944 fn test_ring_slot_wrapping_pure_logic() {
945 assert_eq!(XskRing::ring_slot(0, 0, 15), 0);
947 assert_eq!(XskRing::ring_slot(u32::MAX, 1, 15), 0); assert_eq!(XskRing::ring_slot(u32::MAX - 1, 3, 15), 1); assert_eq!(XskRing::ring_slot(u32::MAX - 2, 4, 15), 1); assert_eq!(XskRing::ring_slot(5, 3, 15), 8);
951 for base in [0u32, 1, 15, 16, u32::MAX - 7, u32::MAX] {
953 for off in [0u32, 1, 7, 16, 100] {
954 assert!(XskRing::ring_slot(base, off, 15) < 16);
955 }
956 }
957 }
958
959 #[test]
960 fn test_simulated_ring_index_wrap_at_u32_max() {
961 let mut ring = XskRing::new(RingType::Tx, 16).unwrap();
963 if let RingStorage::Simulated {
964 producer_idx,
965 consumer_idx,
966 ..
967 } = &ring.storage
968 {
969 producer_idx.store(u32::MAX - 2, Ordering::SeqCst);
970 consumer_idx.store(u32::MAX - 2, Ordering::SeqCst);
971 } else {
972 panic!("new() 必须是模拟模式");
973 }
974
975 let descs: Vec<XdpDesc> = (0..4u32).map(|i| make_desc(u64::from(i) * 4096, i)).collect();
976 assert_eq!(ring.enqueue_batch(&descs).unwrap(), 4);
977 assert_eq!(ring.available_data(), 4);
978 assert_eq!(ring.producer_index(), 1);
980
981 let out = ring.dequeue_batch(4).unwrap();
982 assert_eq!(out.len(), 4);
983 for (i, d) in out.iter().enumerate() {
984 assert_eq!(d.addr, (i as u64) * 4096);
985 }
986 assert_eq!(ring.consumer_index(), 1);
987 assert_eq!(ring.available_data(), 0);
988 assert_eq!(ring.available_space(), 16);
989 }
990
991 fn fake_kernel_ring_layout(ring_size: u32, flags_value: u32) -> (*mut u8, RingOffsets) {
996 let desc_off = 64u64;
997 let len = desc_off + u64::from(ring_size) * std::mem::size_of::<XdpDesc>() as u64;
998 let map_len = len as usize;
999 let base = unsafe {
1001 libc::mmap(
1002 std::ptr::null_mut(),
1003 map_len,
1004 libc::PROT_READ | libc::PROT_WRITE,
1005 libc::MAP_SHARED | libc::MAP_ANONYMOUS,
1006 -1,
1007 0,
1008 )
1009 };
1010 assert_ne!(base, libc::MAP_FAILED, "匿名 mmap 失败");
1011 let base = base as *mut u8;
1012 unsafe {
1014 (base.add(16) as *mut u32).write(flags_value);
1015 }
1016 (
1017 base,
1018 RingOffsets {
1019 producer: 0,
1020 consumer: 8,
1021 desc: desc_off,
1022 flags: 16,
1023 len,
1024 },
1025 )
1026 }
1027
1028 #[test]
1029 fn test_kernel_mode_ring_enqueue_dequeue_via_mmap() {
1030 let (base, offsets) = fake_kernel_ring_layout(4, 0);
1031 let mut ring = unsafe { XskRing::with_kernel_ring(RingType::Tx, base, offsets) }
1034 .expect("合法偏移必须成功");
1035
1036 assert!(ring.is_kernel_mode());
1037 assert_eq!(ring.capacity(), 4);
1038 assert_eq!(ring.available_space(), 4);
1039
1040 let descs = [make_desc(4096, 64), make_desc(8192, 128)];
1041 assert_eq!(ring.enqueue_batch(&descs).unwrap(), 2);
1042
1043 unsafe {
1046 assert_eq!((base as *const u32).read(), 2, "producer 索引应写入共享区");
1047 let d0 = (base.add(64) as *const XdpDesc).read();
1048 assert_eq!(d0.addr, 4096);
1049 assert_eq!(d0.len, 64);
1050 let d1 = (base.add(64 + 16) as *const XdpDesc).read();
1051 assert_eq!(d1.addr, 8192);
1052 }
1053
1054 let out = ring.dequeue_batch(4).unwrap();
1055 assert_eq!(out.len(), 2);
1056 assert_eq!(out[0].addr, 4096);
1057 assert_eq!(out[1].addr, 8192);
1058 unsafe {
1060 assert_eq!((base.add(8) as *const u32).read(), 2, "consumer 索引应写入共享区");
1061 }
1062 }
1064
1065 #[test]
1066 fn test_kernel_mode_ring_need_wakeup_flag() {
1067 let (base, offsets) = fake_kernel_ring_layout(4, XDP_RING_NEED_WAKEUP);
1068 let ring = unsafe { XskRing::with_kernel_ring(RingType::Fill, base, offsets) }
1070 .expect("合法偏移必须成功");
1071 assert!(ring.need_wakeup(), "flags 置位时 need_wakeup 必须为 true");
1072
1073 unsafe {
1076 (base.add(16) as *mut u32).write(0u32);
1077 }
1078 assert!(!ring.need_wakeup());
1079 }
1080
1081 #[test]
1082 fn test_kernel_mode_ring_no_flags_field() {
1083 let (base, mut offsets) = fake_kernel_ring_layout(4, 0);
1085 offsets.flags = 0;
1086 let ring = unsafe { XskRing::with_kernel_ring(RingType::Rx, base, offsets) }
1088 .expect("合法偏移必须成功");
1089 assert!(!ring.need_wakeup());
1090 }
1091
1092 #[test]
1093 fn test_kernel_mode_ring_rejects_invalid_offsets() {
1094 let (base, offsets) = fake_kernel_ring_layout(4, 0);
1095
1096 let r = unsafe { XskRing::with_kernel_ring(RingType::Rx, std::ptr::null_mut(), offsets) };
1098 assert!(r.is_err(), "空 mmap_base 必须拒绝");
1099
1100 let bad = RingOffsets { desc: 4096, ..offsets };
1102 let r = unsafe { XskRing::with_kernel_ring(RingType::Rx, base, bad) };
1103 assert!(r.is_err(), "desc > len 必须拒绝");
1104
1105 let bad = RingOffsets { len: offsets.desc + 3 * 16, ..offsets };
1107 let r = unsafe { XskRing::with_kernel_ring(RingType::Rx, base, bad) };
1108 assert!(r.is_err(), "非 2 的幂容量必须拒绝");
1109
1110 let bad = RingOffsets { producer: offsets.len, ..offsets };
1112 let r = unsafe { XskRing::with_kernel_ring(RingType::Rx, base, bad) };
1113 assert!(r.is_err(), "producer 越界必须拒绝");
1114
1115 let bad = RingOffsets { flags: offsets.len + 4, ..offsets };
1117 let r = unsafe { XskRing::with_kernel_ring(RingType::Rx, base, bad) };
1118 assert!(r.is_err(), "flags 越界必须拒绝");
1119
1120 unsafe {
1123 libc::munmap(base as *mut libc::c_void, offsets.len as usize);
1124 }
1125 }
1126
1127 #[test]
1128 fn test_kernel_mode_ring_wrap_across_u32_max() {
1129 let (base, offsets) = fake_kernel_ring_layout(16, 0);
1130 let mut ring = unsafe { XskRing::with_kernel_ring(RingType::Completion, base, offsets) }
1132 .expect("合法偏移必须成功");
1133
1134 unsafe {
1137 (base as *mut u32).write(u32::MAX - 1);
1138 (base.add(8) as *mut u32).write(u32::MAX - 1);
1139 }
1140 assert_eq!(ring.available_data(), 0);
1141 assert_eq!(ring.available_space(), 16);
1142
1143 let descs: Vec<XdpDesc> = (0..4u32).map(|i| make_desc(u64::from(i) * 4096, i)).collect();
1144 assert_eq!(ring.enqueue_batch(&descs).unwrap(), 4);
1145 assert_eq!(ring.producer_index(), 2);
1147 assert_eq!(ring.available_data(), 4);
1148
1149 let out = ring.dequeue_batch(4).unwrap();
1150 assert_eq!(out.len(), 4);
1151 for (i, d) in out.iter().enumerate() {
1152 assert_eq!(d.addr, (i as u64) * 4096, "跨回绕边界 FIFO 顺序必须保持");
1153 }
1154 assert_eq!(ring.consumer_index(), 2);
1155 }
1156}