1use core::fmt;
65use core::marker::PhantomData;
66use core::sync::atomic::{Ordering, fence};
67
68use bytemuck::Zeroable;
69use smallvec::SmallVec;
70use thiserror::Error;
71
72use super::desc::{DescFlags, DescTable, Descriptor};
73use super::event::{EventFlags, EventSuppression};
74use super::{Layout, MemOps};
75
76#[derive(Debug, Copy, Clone, Zeroable)]
82pub struct BufferElement {
83 pub addr: u64,
85 pub len: u32,
87 pub writable: bool,
89}
90
91#[derive(Debug, Copy, Clone)]
97pub struct UsedBuffer {
98 pub id: u16,
100 pub len: u32,
103}
104
105#[derive(Debug, Copy, Clone)]
110pub struct SubmitResult {
111 pub id: u16,
114 pub notify: bool,
117}
118
119#[derive(Debug, Copy, Clone, PartialEq, Eq)]
121pub enum MemOp {
122 ReadDesc,
124 WriteDesc,
126 ReadEvent,
128 WriteEvent,
130}
131
132impl fmt::Display for MemOp {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 match self {
135 Self::ReadDesc => f.write_str("reading descriptor"),
136 Self::WriteDesc => f.write_str("writing descriptor"),
137 Self::ReadEvent => f.write_str("reading event suppression"),
138 Self::WriteEvent => f.write_str("writing event suppression"),
139 }
140 }
141}
142
143#[derive(Error, Debug)]
144pub enum RingError {
145 #[error("Buffer chain is empty")]
146 EmptyChain,
147 #[error("Buffer chain is malformed")]
148 BadChain,
149 #[error("Operation would block")]
150 WouldBlock,
151 #[error("Out of memory")]
152 OutOfMemory,
153 #[error("Invalid state")]
154 InvalidState,
155 #[error("Invalid memory layout")]
156 InvalidLayout,
157 #[error("Backend memory error while {op} at address 0x{addr:x}, len {len}")]
158 MemError {
159 op: MemOp,
161 addr: u64,
163 len: usize,
165 },
166}
167
168impl RingError {
169 #[inline]
170 fn mem_err(op: MemOp, addr: u64) -> Self {
171 let len = match op {
172 MemOp::ReadDesc | MemOp::WriteDesc => Descriptor::SIZE,
173 MemOp::ReadEvent | MemOp::WriteEvent => EventSuppression::SIZE,
174 };
175
176 Self::MemError { op, addr, len }
177 }
178}
179
180pub struct Readable;
182
183pub struct Writable;
185
186#[derive(Debug, Default)]
194pub struct BufferChainBuilder<T> {
195 elems: SmallVec<[BufferElement; 16]>,
196 split: usize,
197 marker: PhantomData<T>,
198}
199
200impl BufferChainBuilder<Readable> {
201 pub fn new() -> Self {
203 Self {
204 elems: Default::default(),
205 split: 0,
206 marker: PhantomData,
207 }
208 }
209
210 pub fn readable(mut self, addr: u64, len: u32) -> Self {
212 self.elems.push(BufferElement {
213 addr,
214 len,
215 writable: false,
216 });
217 self.split += 1;
218 self
219 }
220
221 pub fn readables(
223 mut self,
224 elements: impl IntoIterator<Item = impl Into<BufferElement>>,
225 ) -> Self {
226 for elem in elements {
227 let mut elem = elem.into();
228 elem.writable = false;
229 self.elems.push(elem);
230 self.split += 1;
231 }
232
233 self
234 }
235
236 pub fn writable(mut self, addr: u64, len: u32) -> BufferChainBuilder<Writable> {
240 self.elems.push(BufferElement {
241 addr,
242 len,
243 writable: true,
244 });
245
246 BufferChainBuilder {
247 elems: self.elems,
248 split: self.split,
249 marker: PhantomData,
250 }
251 }
252
253 pub fn writables(
257 mut self,
258 elements: impl IntoIterator<Item = impl Into<BufferElement>>,
259 ) -> BufferChainBuilder<Writable> {
260 for elem in elements {
261 let mut elem = elem.into();
262 elem.writable = true;
263 self.elems.push(elem);
264 }
265
266 BufferChainBuilder {
267 elems: self.elems,
268 split: self.split,
269 marker: PhantomData,
270 }
271 }
272
273 pub fn build(self) -> Result<BufferChain, RingError> {
277 if self.elems.is_empty() {
278 return Err(RingError::EmptyChain);
279 }
280
281 Ok(BufferChain {
282 elems: self.elems,
283 split: self.split,
284 })
285 }
286}
287
288impl BufferChainBuilder<Writable> {
289 pub fn writable(mut self, addr: u64, len: u32) -> Self {
291 self.elems.push(BufferElement {
292 addr,
293 len,
294 writable: true,
295 });
296 self
297 }
298
299 pub fn writables(
301 mut self,
302 elements: impl IntoIterator<Item = impl Into<BufferElement>>,
303 ) -> Self {
304 for elem in elements {
305 let mut elem = elem.into();
306 elem.writable = true;
307 self.elems.push(elem);
308 }
309 self
310 }
311
312 pub fn build(self) -> Result<BufferChain, RingError> {
316 if self.elems.is_empty() {
317 return Err(RingError::EmptyChain);
318 }
319
320 Ok(BufferChain {
321 elems: self.elems,
322 split: self.split,
323 })
324 }
325}
326
327#[derive(Debug, Clone)]
332pub struct BufferChain {
333 elems: SmallVec<[BufferElement; 16]>,
335 split: usize,
337}
338
339impl BufferChain {
340 pub fn elems(&self) -> &[BufferElement] {
342 self.elems.as_slice()
343 }
344
345 pub fn readables(&self) -> &[BufferElement] {
347 &self.elems[..self.split]
348 }
349
350 pub(crate) fn readables_mut(&mut self) -> &mut [BufferElement] {
352 &mut self.elems[..self.split]
353 }
354
355 pub fn writables(&self) -> &[BufferElement] {
357 &self.elems[self.split..]
358 }
359
360 #[allow(clippy::len_without_is_empty)]
363 pub fn len(&self) -> usize {
364 self.elems.len()
365 }
366}
367
368#[derive(Debug, Copy, Clone, PartialEq, Eq)]
373pub struct RingCursor {
374 head: u16,
375 size: u16,
376 wrap: bool,
377}
378
379impl RingCursor {
380 pub(crate) fn new(size: usize) -> Self {
381 Self {
382 head: 0,
383 size: size as u16,
384 wrap: true,
385 }
386 }
387
388 #[inline]
390 fn advance(&mut self) {
391 debug_assert!(self.head.checked_add(1).is_some());
392 self.head += 1;
393 if self.head >= self.size {
394 self.head = 0;
395 self.wrap = !self.wrap;
396 }
397 }
398
399 #[inline]
401 fn advance_by(&mut self, n: u16) {
402 debug_assert!(self.head.checked_add(n).is_some());
403 let new = self.head + n;
404 let wraps = new / self.size;
405 self.head = new % self.size;
406 if !wraps.is_multiple_of(2) {
407 self.wrap = !self.wrap;
408 }
409 }
410
411 #[inline]
413 pub fn head(&self) -> u16 {
414 self.head
415 }
416
417 #[inline]
419 pub fn wrap(&self) -> bool {
420 self.wrap
421 }
422
423 #[inline]
425 pub fn reset(&mut self) {
426 self.head = 0;
427 self.wrap = true;
428 }
429}
430
431#[derive(Debug)]
444pub struct RingProducer<M> {
445 mem: M,
447 avail_cursor: RingCursor,
449 used_cursor: RingCursor,
451 num_free: usize,
453 desc_table: DescTable,
455 event_flags_shadow: EventFlags,
457 drv_evt_addr: u64,
459 dev_evt_addr: u64,
461 id_free: SmallVec<[u16; DescTable::DEFAULT_LEN]>,
463 id_num: SmallVec<[u16; DescTable::DEFAULT_LEN]>,
465}
466
467impl<M: MemOps> RingProducer<M> {
468 pub fn new(layout: Layout, mem: M) -> Self {
470 let size = layout.desc_table_len() as usize;
471 let raw = layout.desc_table_addr();
472
473 let table = unsafe { DescTable::from_raw_parts(raw, size) };
475 let cursor = RingCursor::new(size);
476
477 const DEFAULT_LEN: usize = DescTable::default_len();
478 let id_free = (0..size as u16).collect::<SmallVec<[_; DEFAULT_LEN]>>();
479 let id_num = SmallVec::<[_; DEFAULT_LEN]>::from_elem(0, size);
480
481 let event_flags_shadow = EventFlags::ENABLE;
483
484 Self {
485 mem,
486 avail_cursor: cursor,
487 used_cursor: cursor,
488 num_free: size,
489 desc_table: table,
490 id_free,
491 id_num,
492 event_flags_shadow,
493 drv_evt_addr: layout.drv_evt_addr(),
494 dev_evt_addr: layout.dev_evt_addr(),
495 }
496 }
497
498 pub fn submit_one(&mut self, addr: u64, len: u32, writable: bool) -> Result<u16, RingError> {
520 if self.num_free < 1 {
521 return Err(RingError::WouldBlock);
522 }
523
524 let id = self.id_free.pop().ok_or(RingError::OutOfMemory)?;
526
527 if self.id_num[id as usize] != 0 {
529 return Err(RingError::InvalidState);
530 }
531
532 self.id_num[id as usize] = 1;
534
535 let head_idx = self.avail_cursor.head();
537 let head_wrap = self.avail_cursor.wrap();
538
539 let mut flags = DescFlags::empty();
540 flags.set(DescFlags::WRITE, writable);
541 let mut desc = Descriptor::new(addr, len, id, flags);
542 desc.mark_avail(head_wrap);
543
544 let addr = self
545 .desc_table
546 .desc_addr(head_idx)
547 .ok_or(RingError::InvalidState)?;
548
549 desc.write_release(&self.mem, addr)
551 .map_err(|_| RingError::mem_err(MemOp::WriteDesc, addr))?;
552
553 self.avail_cursor.advance();
555 self.num_free -= 1;
556
557 Ok(id)
558 }
559
560 pub fn submit_available_with_notify(
562 &mut self,
563 chain: &BufferChain,
564 ) -> Result<SubmitResult, RingError> {
565 let old = self.avail_cursor;
566 let id = self.submit_available(chain)?;
567 let new = self.avail_cursor;
568 let notify = self.should_notify_device(old, new)?;
569
570 Ok(SubmitResult { id, notify })
571 }
572
573 pub fn submit_one_with_notify(
575 &mut self,
576 addr: u64,
577 len: u32,
578 writable: bool,
579 ) -> Result<SubmitResult, RingError> {
580 let old = self.avail_cursor;
581 let id = self.submit_one(addr, len, writable)?;
582 let new = self.avail_cursor;
583 let notify = self.should_notify_device(old, new)?;
584 Ok(SubmitResult { id, notify })
585 }
586
587 pub fn submit_available(&mut self, chain: &BufferChain) -> Result<u16, RingError> {
610 let total_descs = chain.len();
611 if total_descs == 0 {
612 return Err(RingError::EmptyChain);
613 }
614
615 if self.num_free < total_descs {
616 return Err(RingError::WouldBlock);
617 }
618
619 if total_descs == 1 {
620 let elem = chain.elems()[0];
621 return self.submit_one(elem.addr, elem.len, elem.writable);
622 }
623
624 let head_idx = self.avail_cursor.head();
625 let head_wrap = self.avail_cursor.wrap();
626
627 let id = self.id_free.pop().ok_or(RingError::OutOfMemory)?;
628
629 if self.id_num[id as usize] != 0 {
631 return Err(RingError::InvalidState);
632 }
633
634 self.id_num[id as usize] = total_descs as u16;
636
637 let mut pos = self.avail_cursor;
639 pos.advance();
640
641 for (i, elem) in chain.elems().iter().enumerate().skip(1) {
642 let is_next = i + 1 < total_descs;
643 let mut flags = DescFlags::empty();
644
645 flags.set(DescFlags::NEXT, is_next);
646 flags.set(DescFlags::WRITE, elem.writable);
647
648 let mut desc = Descriptor::new(elem.addr, elem.len, id, flags);
649 desc.mark_avail(pos.wrap());
650
651 let addr = self
652 .desc_table
653 .desc_addr(pos.head())
654 .ok_or(RingError::InvalidState)?;
655
656 self.mem
657 .write_val(addr, desc)
658 .map_err(|_| RingError::mem_err(MemOp::WriteDesc, addr))?;
659 pos.advance();
660 }
661
662 let head_elem = chain.elems()[0];
664 let mut head_flags = DescFlags::empty();
666 head_flags.set(DescFlags::NEXT, total_descs > 1);
667 head_flags.set(DescFlags::WRITE, head_elem.writable);
668
669 let mut head_desc = Descriptor::new(head_elem.addr, head_elem.len, id, head_flags);
670 head_desc.mark_avail(head_wrap);
671
672 let head_addr = self
673 .desc_table
674 .desc_addr(head_idx)
675 .ok_or(RingError::InvalidState)?;
676
677 head_desc
679 .write_release(&self.mem, head_addr)
680 .map_err(|_| RingError::mem_err(MemOp::WriteDesc, head_addr))?;
681
682 self.num_free -= total_descs;
683 self.avail_cursor = pos;
684
685 Ok(id)
686 }
687
688 pub fn poll_used(&mut self) -> Result<UsedBuffer, RingError> {
698 let idx = self.used_cursor.head();
699 let wrap = self.used_cursor.wrap();
700
701 let addr = self
703 .desc_table
704 .desc_addr(idx)
705 .ok_or(RingError::InvalidState)?;
706
707 let flags = Descriptor::read_flags_acquire(&self.mem, addr)
709 .map_err(|_| RingError::mem_err(MemOp::ReadDesc, addr))?;
710
711 if !flags.is_used(wrap) {
712 return Err(RingError::WouldBlock);
713 }
714
715 let desc = Descriptor::read_body(&self.mem, addr, flags)
716 .map_err(|_| RingError::mem_err(MemOp::ReadDesc, addr))?;
717
718 let id = desc.id;
719 let count = *self
720 .id_num
721 .get(id as usize)
722 .ok_or(RingError::InvalidState)?;
723
724 if count == 0 {
725 return Err(RingError::InvalidState);
726 }
727
728 self.used_cursor.advance_by(count);
730 self.num_free += count as usize;
732 self.id_num[id as usize] = 0;
734 self.id_free.push(id);
736
737 Ok(UsedBuffer { id, len: desc.len })
738 }
739
740 #[inline]
742 pub fn num_free(&self) -> usize {
743 self.num_free
744 }
745
746 #[inline]
748 pub fn num_inflight(&self) -> usize {
749 self.desc_table.len() - self.num_free
750 }
751
752 #[inline]
754 pub fn is_full(&self) -> bool {
755 self.num_free == 0
756 }
757
758 #[inline]
760 #[allow(clippy::len_without_is_empty)]
761 pub fn len(&self) -> usize {
762 self.desc_table.len()
763 }
764
765 #[inline]
767 pub fn mem(&self) -> &M {
768 &self.mem
769 }
770
771 #[inline]
773 pub fn desc_table(&self) -> &DescTable {
774 &self.desc_table
775 }
776
777 #[inline]
782 pub fn avail_cursor(&self) -> RingCursor {
783 self.avail_cursor
784 }
785
786 #[inline]
790 pub fn used_cursor(&self) -> RingCursor {
791 self.used_cursor
792 }
793
794 pub fn should_notify_since(&self, old: RingCursor) -> Result<bool, RingError> {
802 self.should_notify_device(old, self.avail_cursor)
803 }
804
805 pub fn disable_used_notifications(&mut self) -> Result<(), RingError> {
807 if self.event_flags_shadow == EventFlags::DISABLE {
809 return Ok(());
810 }
811
812 let mut evt = self
813 .mem
814 .read_val::<EventSuppression>(self.drv_evt_addr)
815 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.drv_evt_addr))?;
816
817 evt.set_flags(EventFlags::DISABLE);
818
819 evt.write_release(&self.mem, self.drv_evt_addr)
820 .map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.drv_evt_addr))?;
821 self.event_flags_shadow = EventFlags::DISABLE;
822 Ok(())
823 }
824
825 pub fn enable_used_notifications(&mut self) -> Result<(), RingError> {
827 if self.event_flags_shadow == EventFlags::ENABLE {
828 return Ok(());
829 }
830
831 let mut evt = self
832 .mem
833 .read_val::<EventSuppression>(self.drv_evt_addr)
834 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.drv_evt_addr))?;
835
836 evt.set_flags(EventFlags::ENABLE);
837 evt.write_release(&self.mem, self.drv_evt_addr)
838 .map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.drv_evt_addr))?;
839
840 self.event_flags_shadow = EventFlags::ENABLE;
841 Ok(())
842 }
843
844 pub fn enable_used_notifications_desc(
851 &mut self,
852 off: u16,
853 wrap: bool,
854 ) -> Result<(), RingError> {
855 let mut evt = self
856 .mem
857 .read_val::<EventSuppression>(self.drv_evt_addr)
858 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.drv_evt_addr))?;
859
860 evt.set_desc_event(off, wrap);
861 evt.set_flags(EventFlags::DESC);
862
863 evt.write_release(&self.mem, self.drv_evt_addr)
865 .map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.drv_evt_addr))?;
866 self.event_flags_shadow = EventFlags::DESC;
868 Ok(())
869 }
870
871 pub fn enable_used_notifications_for_next(&mut self) -> Result<(), RingError> {
873 let off = self.used_cursor.head();
874 let wrap = self.used_cursor.wrap();
875
876 self.enable_used_notifications_desc(off, wrap)
877 }
878
879 fn should_notify_device(&self, old: RingCursor, new: RingCursor) -> Result<bool, RingError> {
881 fence(Ordering::SeqCst);
891
892 should_notify_evt(&self.mem, self.dev_evt_addr, self.len() as u16, old, new)
893 }
894
895 pub fn reset(&mut self) {
897 let size = self.desc_table.len();
898 self.avail_cursor.reset();
899 self.used_cursor.reset();
900 self.num_free = size;
901 self.id_free.clear();
902 self.id_free.extend(0..size as u16);
903 self.id_num.iter_mut().for_each(|n| *n = 0);
904 self.event_flags_shadow = EventFlags::ENABLE;
905 }
906
907 pub fn reset_prefilled(&mut self, ids: &[u16]) {
912 let size = self.desc_table.len();
913 let count = ids.len();
914 assert!(count <= size);
915
916 let wrapped = count >= size;
917 self.avail_cursor.head = if wrapped { 0 } else { count as u16 };
918 self.avail_cursor.wrap = !wrapped;
919
920 self.used_cursor.head = 0;
921 self.used_cursor.wrap = true;
922
923 self.id_num.iter_mut().for_each(|n| *n = 0);
924 for &id in ids {
925 assert!((id as usize) < size);
926 assert_eq!(self.id_num[id as usize], 0);
927 self.id_num[id as usize] = 1;
928 }
929
930 self.num_free = size - count;
931 self.id_free.clear();
932 self.id_free
933 .extend((0..size as u16).filter(|id| self.id_num[*id as usize] == 0));
934 }
935}
936
937#[derive(Debug)]
950pub struct RingConsumer<M> {
951 mem: M,
953 avail_cursor: RingCursor,
955 used_cursor: RingCursor,
957 desc_table: DescTable,
959 id_num: SmallVec<[u16; DescTable::DEFAULT_LEN]>,
961 num_inflight: usize,
963 event_flags_shadow: EventFlags,
965 drv_evt_addr: u64,
967 dev_evt_addr: u64,
969}
970
971impl<M: MemOps> RingConsumer<M> {
972 pub fn new(layout: Layout, mem: M) -> Self {
973 let size = layout.desc_table_len() as usize;
974 let raw = layout.desc_table_addr();
975
976 let table = unsafe { DescTable::from_raw_parts(raw, size) };
978 let cursor = RingCursor::new(size);
979 let id_chain_len = SmallVec::<[u16; DescTable::DEFAULT_LEN]>::from_elem(0, size);
980
981 let event_flags_shadow = EventFlags::ENABLE;
983
984 Self {
985 mem,
986 avail_cursor: cursor,
987 used_cursor: cursor,
988 desc_table: table,
989 id_num: id_chain_len,
990 num_inflight: 0,
991 event_flags_shadow,
992 drv_evt_addr: layout.drv_evt_addr(),
993 dev_evt_addr: layout.dev_evt_addr(),
994 }
995 }
996
997 pub fn poll_available(&mut self) -> Result<(u16, BufferChain), RingError> {
1009 let idx = self.avail_cursor.head();
1010 let wrap = self.avail_cursor.wrap();
1011
1012 let head_addr = self
1013 .desc_table
1014 .desc_addr(idx)
1015 .ok_or(RingError::InvalidState)?;
1016
1017 let flags = Descriptor::read_flags_acquire(&self.mem, head_addr)
1019 .map_err(|_| RingError::mem_err(MemOp::ReadDesc, head_addr))?;
1020
1021 if !flags.is_avail(wrap) {
1023 return Err(RingError::WouldBlock);
1024 }
1025
1026 let head_desc = Descriptor::read_body(&self.mem, head_addr, flags)
1027 .map_err(|_| RingError::mem_err(MemOp::ReadDesc, head_addr))?;
1028
1029 if flags.contains(DescFlags::INDIRECT) {
1030 return Err(RingError::BadChain);
1031 }
1032
1033 let mut elements = SmallVec::<[BufferElement; 16]>::new();
1035 let mut pos = self.avail_cursor;
1036 let mut chain_len: u16 = 1;
1037
1038 let mut steps = 1;
1039 let mut has_next = head_desc.is_next();
1040
1041 let max_steps = self.desc_table.len();
1042
1043 let head_elem = BufferElement::from(&head_desc);
1044 let mut seen_writable = head_elem.writable;
1045 let mut writables: usize = if seen_writable { 1 } else { 0 };
1046 elements.push(head_elem);
1047 pos.advance();
1048
1049 while has_next && steps < max_steps {
1050 let addr = self
1051 .desc_table
1052 .desc_addr(pos.head())
1053 .ok_or(RingError::InvalidState)?;
1054
1055 let desc: Descriptor = self
1057 .mem
1058 .read_val(addr)
1059 .map_err(|_| RingError::mem_err(MemOp::ReadDesc, addr))?;
1060 if desc.flags().contains(DescFlags::INDIRECT) {
1061 return Err(RingError::BadChain);
1062 }
1063
1064 let elem = BufferElement::from(&desc);
1065
1066 if elem.writable {
1067 seen_writable = true;
1068 writables += 1;
1069 } else if seen_writable {
1070 return Err(RingError::BadChain);
1071 }
1072
1073 elements.push(elem);
1074
1075 chain_len += 1;
1076 steps += 1;
1077
1078 has_next = desc.is_next();
1079 pos.advance();
1080 }
1081
1082 if steps >= max_steps && has_next {
1084 return Err(RingError::BadChain);
1085 }
1086
1087 if self.num_inflight + chain_len as usize > self.desc_table.len() {
1090 return Err(RingError::InvalidState);
1091 }
1092
1093 let readables = elements.len() - writables;
1094
1095 let id = head_desc.id;
1097 let id_num = self
1098 .id_num
1099 .get_mut(id as usize)
1100 .ok_or(RingError::InvalidState)?;
1101 if *id_num != 0 {
1102 return Err(RingError::InvalidState);
1103 }
1104
1105 *id_num = chain_len;
1107 self.avail_cursor = pos;
1109 self.num_inflight += chain_len as usize;
1111
1112 Ok((
1113 id,
1114 BufferChain {
1115 elems: elements,
1116 split: readables,
1117 },
1118 ))
1119 }
1120
1121 pub fn submit_used(&mut self, id: u16, written_len: u32) -> Result<(), RingError> {
1133 let chain_len = *self
1135 .id_num
1136 .get(id as usize)
1137 .ok_or(RingError::InvalidState)?;
1138
1139 if chain_len == 0 || chain_len > self.desc_table.len() as u16 {
1140 return Err(RingError::InvalidState);
1141 }
1142
1143 let idx = self.used_cursor.head();
1144 let wrap = self.used_cursor.wrap();
1145
1146 let mut used_desc = Descriptor::new(0, written_len, id, DescFlags::empty());
1148 used_desc.mark_used(wrap);
1149
1150 let addr = self
1151 .desc_table
1152 .desc_addr(idx)
1153 .ok_or(RingError::InvalidState)?;
1154
1155 used_desc
1157 .write_release(&self.mem, addr)
1158 .map_err(|_| RingError::mem_err(MemOp::WriteDesc, addr))?;
1159
1160 self.used_cursor.advance_by(chain_len);
1162 self.id_num[id as usize] = 0;
1163
1164 self.num_inflight -= chain_len as usize;
1165 Ok(())
1166 }
1167
1168 pub fn peek_available(&self) -> Result<bool, RingError> {
1170 let Some(addr) = self.desc_table.desc_addr(self.avail_cursor.head()) else {
1171 return Err(RingError::InvalidState);
1172 };
1173
1174 let flags = Descriptor::read_flags_acquire(&self.mem, addr)
1175 .map_err(|_| RingError::mem_err(MemOp::ReadDesc, addr))?;
1176
1177 Ok(flags.is_avail(self.avail_cursor.wrap()))
1178 }
1179
1180 pub fn submit_used_with_notify(
1182 &mut self,
1183 id: u16,
1184 written_len: u32,
1185 ) -> Result<bool, RingError> {
1186 let old = self.used_cursor;
1187 self.submit_used(id, written_len)?;
1188 let new = self.used_cursor;
1189 self.should_notify_driver(old, new)
1190 }
1191
1192 pub fn num_free(&self) -> usize {
1194 self.desc_table.len() - self.num_inflight
1195 }
1196
1197 pub fn num_inflight(&self) -> usize {
1199 self.num_inflight
1200 }
1201
1202 pub fn is_full(&self) -> bool {
1204 self.num_inflight == self.desc_table.len()
1205 }
1206
1207 #[allow(clippy::len_without_is_empty)]
1209 pub fn len(&self) -> usize {
1210 self.desc_table.len()
1211 }
1212
1213 pub fn mem(&self) -> &M {
1215 &self.mem
1216 }
1217
1218 #[inline]
1220 pub fn avail_cursor(&self) -> RingCursor {
1221 self.avail_cursor
1222 }
1223
1224 #[inline]
1226 pub fn used_cursor(&self) -> RingCursor {
1227 self.used_cursor
1228 }
1229
1230 pub fn disable_avail_notifications(&mut self) -> Result<(), RingError> {
1234 if self.event_flags_shadow == EventFlags::DISABLE {
1235 return Ok(());
1236 }
1237
1238 let mut evt = self
1239 .mem
1240 .read_val::<EventSuppression>(self.dev_evt_addr)
1241 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.dev_evt_addr))?;
1242
1243 evt.set_flags(EventFlags::DISABLE);
1244 evt.write_release(&self.mem, self.dev_evt_addr)
1245 .map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.dev_evt_addr))?;
1246
1247 self.event_flags_shadow = EventFlags::DISABLE;
1248 Ok(())
1249 }
1250
1251 pub fn enable_avail_notifications(&mut self) -> Result<(), RingError> {
1253 if self.event_flags_shadow == EventFlags::ENABLE {
1254 return Ok(());
1255 }
1256
1257 let mut evt = self
1258 .mem
1259 .read_val::<EventSuppression>(self.dev_evt_addr)
1260 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.dev_evt_addr))?;
1261
1262 evt.set_flags(EventFlags::ENABLE);
1263 evt.write_release(&self.mem, self.dev_evt_addr)
1264 .map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.dev_evt_addr))?;
1265
1266 self.event_flags_shadow = EventFlags::ENABLE;
1267 Ok(())
1268 }
1269
1270 pub fn enable_avail_notifications_desc(
1274 &mut self,
1275 off: u16,
1276 wrap: bool,
1277 ) -> Result<(), RingError> {
1278 let mut evt = self
1280 .mem
1281 .read_val::<EventSuppression>(self.dev_evt_addr)
1282 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.dev_evt_addr))?;
1283
1284 evt.set_desc_event(off, wrap);
1285 evt.set_flags(EventFlags::DESC);
1286
1287 evt.write_release(&self.mem, self.dev_evt_addr)
1289 .map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.dev_evt_addr))?;
1290
1291 self.event_flags_shadow = EventFlags::DESC;
1292 Ok(())
1293 }
1294
1295 pub fn enable_avail_notifications_for_next(&mut self) -> Result<(), RingError> {
1298 let off = self.avail_cursor.head();
1299 let wrap = self.avail_cursor.wrap();
1300 self.enable_avail_notifications_desc(off, wrap)
1301 }
1302
1303 fn should_notify_driver(&self, old: RingCursor, new: RingCursor) -> Result<bool, RingError> {
1305 fence(Ordering::SeqCst);
1308
1309 should_notify_evt(&self.mem, self.drv_evt_addr, self.len() as u16, old, new)
1310 }
1311
1312 pub fn reset(&mut self) {
1315 self.avail_cursor.reset();
1316 self.used_cursor.reset();
1317 self.id_num.iter_mut().for_each(|n| *n = 0);
1318 self.num_inflight = 0;
1319 self.event_flags_shadow = EventFlags::ENABLE;
1320 }
1321}
1322
1323fn should_notify_evt<M: MemOps>(
1325 mem: &M,
1326 evt_addr: u64,
1327 ring_len: u16,
1328 old: RingCursor,
1329 new: RingCursor,
1330) -> Result<bool, RingError> {
1331 let flags = EventSuppression::read_flags_acquire(mem, evt_addr)
1332 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, evt_addr))?;
1333
1334 let evt = if flags == EventFlags::DESC {
1335 EventSuppression::read_body(mem, evt_addr, flags)
1336 .map_err(|_| RingError::mem_err(MemOp::ReadEvent, evt_addr))?
1337 } else {
1338 EventSuppression::new(0, flags)
1339 };
1340
1341 Ok(should_notify(evt, ring_len, old, new))
1342}
1343
1344#[inline]
1351fn should_notify(evt: EventSuppression, ring_len: u16, old: RingCursor, new: RingCursor) -> bool {
1352 match evt.flags() {
1353 EventFlags::DISABLE => false,
1354 EventFlags::ENABLE => true,
1355 EventFlags::DESC => {
1356 let mut off = evt.desc_event_off();
1357 if off >= ring_len {
1358 return false;
1359 }
1360
1361 let wrap = evt.desc_event_wrap();
1362
1363 if wrap != new.wrap() {
1364 off = off.wrapping_sub(ring_len);
1365 }
1366
1367 ring_need_event(off, new.head(), old.head())
1368 }
1369 _ => false,
1371 }
1372}
1373
1374#[inline(always)]
1375fn ring_need_event(event_idx: u16, new: u16, old: u16) -> bool {
1376 new.wrapping_sub(event_idx).wrapping_sub(1) < new.wrapping_sub(old)
1377}
1378
1379impl From<&Descriptor> for BufferElement {
1380 fn from(desc: &Descriptor) -> Self {
1381 BufferElement {
1382 addr: desc.addr,
1383 len: desc.len,
1384 writable: desc.is_writable(),
1385 }
1386 }
1387}
1388
1389#[cfg(test)]
1390pub(crate) mod tests {
1391 use alloc::sync::Arc;
1392 use core::cell::UnsafeCell;
1393 use core::num::NonZeroU16;
1394 use core::ptr;
1395 use core::sync::atomic::{AtomicU16, Ordering};
1396
1397 use bytemuck::{Pod, Zeroable};
1398
1399 use super::super::align_up;
1400 use super::*;
1401 use crate::virtq::event::EventSuppression;
1402
1403 #[derive(Clone)]
1409 pub struct TestMem {
1410 inner: Arc<TestMemInner>,
1411 }
1412
1413 struct TestMemInner {
1414 storage: UnsafeCell<Vec<u8>>,
1416 base_addr: u64,
1418 }
1419
1420 unsafe impl Send for TestMemInner {}
1423 unsafe impl Sync for TestMemInner {}
1424
1425 impl TestMem {
1426 pub fn new(size: usize) -> Self {
1427 let storage = vec![0u8; size];
1428 let base_addr = storage.as_ptr() as u64;
1429 Self {
1430 inner: Arc::new(TestMemInner {
1431 storage: UnsafeCell::new(storage),
1432 base_addr,
1433 }),
1434 }
1435 }
1436
1437 fn ptr_for_addr(&self, addr: u64) -> *mut u8 {
1439 let storage = unsafe { &mut *self.inner.storage.get() };
1440 let base_ptr = storage.as_mut_ptr();
1441 let offset = (addr - self.inner.base_addr) as usize;
1442 base_ptr.wrapping_add(offset)
1444 }
1445
1446 pub fn base_addr(&self) -> u64 {
1447 self.inner.base_addr
1448 }
1449 }
1450
1451 unsafe impl MemOps for TestMem {
1454 type Error = core::convert::Infallible;
1455
1456 fn read(&self, addr: u64, dst: &mut [u8]) -> Result<(), Self::Error> {
1457 let src = self.ptr_for_addr(addr);
1458 unsafe {
1459 ptr::copy_nonoverlapping(src, dst.as_mut_ptr(), dst.len());
1460 }
1461 Ok(())
1462 }
1463
1464 fn write(&self, addr: u64, src: &[u8]) -> Result<(), Self::Error> {
1465 let dst = self.ptr_for_addr(addr);
1466 unsafe {
1467 ptr::copy_nonoverlapping(src.as_ptr(), dst, src.len());
1468 }
1469 Ok(())
1470 }
1471
1472 fn read_val<T: Pod>(&self, addr: u64) -> Result<T, Self::Error> {
1473 let ptr = self.ptr_for_addr(addr).cast::<T>();
1474 Ok(unsafe { ptr::read_volatile(ptr) })
1475 }
1476
1477 fn write_val<T: Pod>(&self, addr: u64, val: T) -> Result<(), Self::Error> {
1478 let ptr = self.ptr_for_addr(addr).cast::<T>();
1479 unsafe { ptr::write_volatile(ptr, val) };
1480 Ok(())
1481 }
1482
1483 fn load_acquire(&self, addr: u64) -> Result<u16, Self::Error> {
1484 let ptr = self.ptr_for_addr(addr).cast::<AtomicU16>();
1485 Ok(unsafe { (*ptr).load(Ordering::Acquire) })
1486 }
1487
1488 fn store_release(&self, addr: u64, val: u16) -> Result<(), Self::Error> {
1489 let ptr = self.ptr_for_addr(addr).cast::<AtomicU16>();
1490 unsafe { (*ptr).store(val, Ordering::Release) };
1491 Ok(())
1492 }
1493
1494 unsafe fn as_slice(&self, addr: u64, len: usize) -> Result<&[u8], Self::Error> {
1495 let ptr = self.ptr_for_addr(addr);
1496 Ok(unsafe { core::slice::from_raw_parts(ptr, len) })
1497 }
1498
1499 unsafe fn as_mut_slice(&self, addr: u64, len: usize) -> Result<&mut [u8], Self::Error> {
1500 let ptr = self.ptr_for_addr(addr);
1501 Ok(unsafe { core::slice::from_raw_parts_mut(ptr, len) })
1502 }
1503 }
1504
1505 pub struct OwnedRing {
1507 mem: TestMem,
1508 layout: Layout,
1509 }
1510
1511 impl OwnedRing {
1512 pub fn new(size: usize) -> Self {
1513 let num_descs = NonZeroU16::new(size as u16).unwrap();
1514 let needed = Layout::query_size(size);
1515
1516 let padding = Descriptor::ALIGN;
1520 let pool_headroom = 0x100 + 0x8000;
1521 let mem = TestMem::new(needed + padding + pool_headroom);
1522
1523 let aligned_base = align_up(mem.base_addr() as usize, Descriptor::ALIGN) as u64;
1525 let layout = unsafe { Layout::from_base(aligned_base, num_descs).unwrap() };
1526
1527 Self { mem, layout }
1528 }
1529
1530 pub fn layout(&self) -> Layout {
1531 self.layout
1532 }
1533
1534 pub fn mem(&self) -> TestMem {
1535 self.mem.clone()
1536 }
1537
1538 pub fn desc_addr(&self, idx: u16) -> u64 {
1540 self.layout.desc_table_addr() + (idx as u64 * Descriptor::SIZE as u64)
1541 }
1542
1543 pub fn read_desc(&self, idx: u16) -> Descriptor {
1545 self.mem.read_val(self.desc_addr(idx)).unwrap()
1546 }
1547
1548 pub fn write_desc(&self, idx: u16, desc: Descriptor) {
1550 self.mem.write_val(self.desc_addr(idx), desc).unwrap()
1551 }
1552
1553 pub fn read_driver_event(&self) -> EventSuppression {
1555 self.mem.read_val(self.layout.drv_evt_addr()).unwrap()
1556 }
1557
1558 pub fn read_device_event(&self) -> EventSuppression {
1560 self.mem.read_val(self.layout.dev_evt_addr()).unwrap()
1561 }
1562
1563 pub fn len(&self) -> usize {
1564 self.layout.desc_table_len() as usize
1565 }
1566 }
1567
1568 pub(crate) fn make_ring(size: usize) -> OwnedRing {
1570 OwnedRing::new(size)
1571 }
1572
1573 pub(crate) fn make_producer(ring: &OwnedRing) -> RingProducer<TestMem> {
1574 RingProducer::new(ring.layout(), ring.mem())
1575 }
1576
1577 pub(crate) fn make_consumer(ring: &OwnedRing) -> RingConsumer<TestMem> {
1578 RingConsumer::new(ring.layout(), ring.mem())
1579 }
1580
1581 fn assert_invariants(ring: &OwnedRing, prod: &RingProducer<TestMem>) {
1582 let outstanding: u16 = prod.id_num.iter().copied().sum();
1583 assert_eq!(outstanding as usize + prod.num_free, ring.len());
1584
1585 for id in prod.id_free.iter() {
1586 assert_eq!(prod.id_num[*id as usize], 0);
1587 }
1588
1589 for (id, &n) in prod.id_num.iter().enumerate() {
1590 if n > 0 {
1591 assert!(!prod.id_free.contains(&(id as u16)));
1592 }
1593 }
1594 }
1595
1596 #[test]
1597 fn test_initialization() {
1598 let ring = make_ring(8);
1599 let producer = make_producer(&ring);
1600
1601 for i in 0..8u16 {
1603 let desc = ring.read_desc(i);
1604 assert_eq!(desc, Descriptor::zeroed());
1605 assert_eq!(desc.flags, 0);
1606 assert_eq!(desc.addr, 0);
1607 assert_eq!(desc.len, 0);
1608 assert_eq!(desc.id, 0);
1609 }
1610
1611 assert_eq!(producer.avail_cursor.head(), 0);
1613 assert!(producer.avail_cursor.wrap());
1614 assert_eq!(producer.used_cursor.head(), 0);
1615 assert!(producer.used_cursor.wrap());
1616
1617 assert_eq!(producer.id_free.len(), 8);
1619 assert_eq!(producer.num_free, 8);
1620 for i in 0..8 {
1621 assert_eq!(producer.id_num[i], 0);
1622 }
1623 }
1624
1625 #[test]
1626 fn test_buffer_chain_builder_normalizes_element_direction() {
1627 let readable_as_writable = BufferElement {
1628 addr: 0x1000,
1629 len: 16,
1630 writable: true,
1631 };
1632 let writable_as_readable = BufferElement {
1633 addr: 0x2000,
1634 len: 32,
1635 writable: false,
1636 };
1637 let second_writable_as_readable = BufferElement {
1638 addr: 0x3000,
1639 len: 64,
1640 writable: false,
1641 };
1642
1643 let chain = BufferChainBuilder::new()
1644 .readables([readable_as_writable])
1645 .writables([writable_as_readable])
1646 .writables([second_writable_as_readable])
1647 .build()
1648 .unwrap();
1649
1650 assert!(!chain.readables()[0].writable);
1651 assert!(chain.writables().iter().all(|elem| elem.writable));
1652 }
1653
1654 #[test]
1655 fn test_submit_one_descriptor() {
1656 let ring = make_ring(8);
1657 let mut producer = make_producer(&ring);
1658
1659 let addr = 0x1000;
1660 let len = 512;
1661 let writable = false;
1662
1663 let id = producer.submit_one(addr, len, writable).unwrap();
1664
1665 let desc = ring.read_desc(0);
1667
1668 assert_eq!(desc.addr, addr);
1669 assert_eq!(desc.len, len);
1670 assert_eq!(desc.id, id);
1671
1672 let flags = desc.flags();
1674 assert!(flags.contains(DescFlags::AVAIL));
1675 assert!(!flags.contains(DescFlags::USED));
1676 assert!(!flags.contains(DescFlags::WRITE));
1677 assert!(!flags.contains(DescFlags::NEXT));
1678
1679 assert_eq!(producer.num_free, 7);
1681
1682 assert_eq!(producer.avail_cursor.head(), 1);
1684 assert!(producer.avail_cursor.wrap());
1685
1686 assert_eq!(producer.id_num[id as usize], 1);
1688 assert_eq!(producer.id_free.len(), 7);
1689 }
1690
1691 #[test]
1692 fn test_single_descriptor_wrap_toggle() {
1693 let ring = make_ring(4);
1694 let mut producer = make_producer(&ring);
1695
1696 producer.avail_cursor.head = 3;
1698 producer.avail_cursor.wrap = true;
1699 producer.num_free = 1;
1700 producer.id_free.clear();
1701 producer.id_free.push(0);
1702
1703 let _id = producer.submit_one(0x1000, 512, false).unwrap();
1704
1705 assert_eq!(producer.avail_cursor.head(), 0);
1707 assert!(!producer.avail_cursor.wrap());
1708
1709 let desc = ring.read_desc(3);
1711 let flags = desc.flags();
1712 assert!(flags.contains(DescFlags::AVAIL));
1713 assert!(!flags.contains(DescFlags::USED));
1714 }
1715
1716 #[test]
1717 fn test_multi_descriptor_no_wrap() {
1718 let ring = make_ring(8);
1719 let mut producer = make_producer(&ring);
1720
1721 let chain = BufferChainBuilder::new()
1722 .readable(0x1000, 256)
1723 .readable(0x2000, 256)
1724 .writable(0x3000, 512)
1725 .build()
1726 .unwrap();
1727
1728 let id = producer.submit_available(&chain).unwrap();
1729
1730 let head_desc = ring.read_desc(0);
1732 assert_eq!(head_desc.addr, 0x1000);
1733 assert_eq!(head_desc.len, 256);
1734 assert_eq!(head_desc.id, id);
1735
1736 let head_flags = head_desc.flags();
1737 assert!(head_flags.contains(DescFlags::NEXT));
1738 assert!(!head_flags.contains(DescFlags::WRITE));
1739 assert!(head_flags.contains(DescFlags::AVAIL));
1740 assert!(!head_flags.contains(DescFlags::USED));
1741
1742 let mid_desc = ring.read_desc(1);
1744 assert_eq!(mid_desc.addr, 0x2000);
1745 assert_eq!(mid_desc.len, 256);
1746 assert_eq!(mid_desc.id, id);
1747
1748 let mid_flags = mid_desc.flags();
1749 assert!(mid_flags.contains(DescFlags::NEXT));
1750 assert!(!mid_flags.contains(DescFlags::WRITE));
1751
1752 let tail_desc = ring.read_desc(2);
1754 assert_eq!(tail_desc.addr, 0x3000);
1755 assert_eq!(tail_desc.len, 512);
1756 assert_eq!(tail_desc.id, id);
1757
1758 let tail_flags = tail_desc.flags();
1759 assert!(!tail_flags.contains(DescFlags::NEXT));
1760 assert!(tail_flags.contains(DescFlags::WRITE));
1761
1762 assert_eq!(head_desc.id, mid_desc.id);
1764 assert_eq!(mid_desc.id, tail_desc.id);
1765
1766 assert_eq!(producer.num_free, 5);
1768 assert_eq!(producer.avail_cursor.head(), 3);
1769 assert_eq!(producer.id_num[id as usize], 3);
1770 }
1771
1772 #[test]
1773 fn test_multi_descriptor_with_wrap() {
1774 let ring = make_ring(4);
1775 let mut producer = make_producer(&ring);
1776
1777 producer.avail_cursor.head = 2;
1779 producer.avail_cursor.wrap = true;
1780
1781 let chain = BufferChainBuilder::new()
1782 .readable(0x1000, 256)
1783 .readable(0x2000, 256)
1784 .readable(0x3000, 256)
1785 .build()
1786 .unwrap();
1787
1788 let _id = producer.submit_available(&chain).unwrap();
1789
1790 let head_desc = ring.read_desc(2);
1792 let head_flags = head_desc.flags();
1793 assert!(head_flags.contains(DescFlags::AVAIL));
1794 assert!(!head_flags.contains(DescFlags::USED));
1795
1796 let mid_desc = ring.read_desc(3);
1798 let mid_flags = mid_desc.flags();
1799 assert!(mid_flags.contains(DescFlags::AVAIL));
1800 assert!(!mid_flags.contains(DescFlags::USED));
1801
1802 let tail_desc = ring.read_desc(0);
1804 let tail_flags = tail_desc.flags();
1805 assert!(!tail_flags.contains(DescFlags::AVAIL));
1806 assert!(tail_flags.contains(DescFlags::USED));
1807
1808 assert_eq!(producer.avail_cursor.head(), 1);
1810 assert!(!producer.avail_cursor.wrap());
1811 }
1812
1813 #[test]
1814 fn test_ring_full() {
1815 let ring = make_ring(4);
1816 let mut producer = make_producer(&ring);
1817
1818 for _ in 0..4 {
1820 producer.submit_one(0x1000, 256, false).unwrap();
1821 }
1822
1823 assert_eq!(producer.num_free, 0);
1824
1825 let result = producer.submit_one(0x5000, 256, false);
1827 assert!(matches!(result, Err(RingError::WouldBlock)));
1828 }
1829
1830 #[test]
1831 fn test_poll_and_reclaim() {
1832 let ring = make_ring(8);
1833 let mut producer = make_producer(&ring);
1834
1835 let id = producer.submit_one(0x1000, 512, false).unwrap();
1836
1837 let mut desc = ring.read_desc(0);
1839 desc.mark_used(true);
1840 desc.len = 256;
1841 ring.write_desc(0, desc);
1842
1843 let used = producer.poll_used().unwrap();
1845 assert_eq!(used.id, id);
1846 assert_eq!(used.len, 256);
1847
1848 assert_eq!(producer.num_free, 8);
1850 assert_eq!(producer.used_cursor.head(), 1);
1851 assert_eq!(producer.id_num[id as usize], 0);
1852 assert!(producer.id_free.contains(&id));
1853 }
1854
1855 #[test]
1856 fn test_poll_multi_descriptor_chain() {
1857 let ring = make_ring(8);
1858 let mut producer = make_producer(&ring);
1859
1860 let chain = BufferChainBuilder::new()
1861 .readable(0x1000, 256)
1862 .readable(0x2000, 256)
1863 .writable(0x3000, 512)
1864 .build()
1865 .unwrap();
1866
1867 let id = producer.submit_available(&chain).unwrap();
1868
1869 let mut head_desc = ring.read_desc(0);
1871 head_desc.mark_used(true);
1872 head_desc.len = 512;
1873 ring.write_desc(0, head_desc);
1874
1875 let used = producer.poll_used().unwrap();
1877 assert_eq!(used.id, id);
1878 assert_eq!(used.len, 512);
1879
1880 assert_eq!(producer.used_cursor.head(), 3);
1882 assert_eq!(producer.num_free, 8);
1883 }
1884
1885 #[test]
1886 fn test_id_reuse() {
1887 let ring = make_ring(4);
1888 let mut producer = make_producer(&ring);
1889
1890 let id1 = producer.submit_one(0x1000, 256, false).unwrap();
1892
1893 let mut desc = ring.read_desc(0);
1894 desc.mark_used(true);
1895 ring.write_desc(0, desc);
1896
1897 producer.poll_used().unwrap();
1898
1899 let id2 = producer.submit_one(0x2000, 256, false).unwrap();
1901
1902 assert_eq!(id2, id1);
1904 assert_eq!(producer.id_num[id2 as usize], 1);
1905 }
1906
1907 #[test]
1908 fn test_available_descriptor_flags() {
1909 let ring = make_ring(4);
1910 let mut producer = make_producer(&ring);
1911
1912 producer.submit_one(0x1000, 256, false).unwrap();
1913
1914 let desc = ring.read_desc(0);
1915
1916 let flags = desc.flags();
1918 assert_ne!(
1919 flags.contains(DescFlags::AVAIL),
1920 flags.contains(DescFlags::USED)
1921 );
1922
1923 assert!(flags.contains(DescFlags::AVAIL));
1925 assert!(!flags.contains(DescFlags::USED));
1926 }
1927
1928 #[test]
1929 fn test_used_descriptor_flags() {
1930 let ring = make_ring(4);
1931 let mut producer = make_producer(&ring);
1932
1933 producer.submit_one(0x1000, 256, false).unwrap();
1934
1935 let mut desc = ring.read_desc(0);
1936 desc.mark_used(true);
1937 ring.write_desc(0, desc);
1938
1939 let desc = ring.read_desc(0);
1940 let flags = desc.flags();
1941
1942 assert_eq!(
1944 flags.contains(DescFlags::AVAIL),
1945 flags.contains(DescFlags::USED)
1946 );
1947 }
1948
1949 #[test]
1950 fn test_poll_empty_ring() {
1951 let ring = make_ring(4);
1952 let mut producer = make_producer(&ring);
1953
1954 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
1956 }
1957
1958 #[test]
1959 fn test_submit_when_full() {
1960 let ring = make_ring(2);
1961 let mut producer = make_producer(&ring);
1962
1963 producer.submit_one(0x1000, 256, false).unwrap();
1964 producer.submit_one(0x2000, 256, false).unwrap();
1965
1966 assert!(matches!(
1968 producer.submit_one(0x3000, 256, false),
1969 Err(RingError::WouldBlock)
1970 ));
1971 }
1972
1973 #[test]
1974 fn test_wrap_stress() {
1975 let ring = make_ring(4);
1976 let mut producer = make_producer(&ring);
1977 let mut consumer = make_consumer(&ring);
1978
1979 for lap in 0..3 {
1981 let expected_wrap = lap % 2 == 0;
1982
1983 for _ in 0..4 {
1984 let id = producer.submit_one(0x1000, 256, false).unwrap();
1985
1986 let (dev_id, _) = consumer.poll_available().unwrap();
1987 assert_eq!(dev_id, id);
1988
1989 consumer.submit_used(dev_id, 256).unwrap();
1990
1991 producer.poll_used().unwrap();
1992 }
1993
1994 assert_eq!(producer.avail_cursor.wrap(), !expected_wrap);
1996 }
1997 assert_invariants(&ring, &producer);
1998 }
1999
2000 #[test]
2001 fn test_next_flag_termination() {
2002 let ring = make_ring(8);
2003 let mut producer = make_producer(&ring);
2004
2005 let chain = BufferChainBuilder::new()
2006 .readable(0x1000, 256)
2007 .readable(0x2000, 256)
2008 .readable(0x3000, 256)
2009 .build()
2010 .unwrap();
2011
2012 producer.submit_available(&chain).unwrap();
2013
2014 for i in 0..2 {
2016 let desc = ring.read_desc(i);
2017 assert!(desc.flags().contains(DescFlags::NEXT));
2018 }
2019
2020 let tail_desc = ring.read_desc(2);
2022 assert!(!tail_desc.flags().contains(DescFlags::NEXT));
2023 }
2024
2025 #[test]
2026 fn test_consumer_initialization() {
2027 let ring = make_ring(8);
2028 let consumer = make_consumer(&ring);
2029
2030 assert_eq!(consumer.avail_cursor.head(), 0);
2031 assert!(consumer.avail_cursor.wrap());
2032 assert_eq!(consumer.used_cursor.head(), 0);
2033 assert!(consumer.used_cursor.wrap());
2034
2035 for i in 0..8 {
2036 assert_eq!(consumer.id_num[i], 0);
2037 }
2038 }
2039
2040 #[test]
2041 fn test_consumer_poll_available_single() {
2042 let ring = make_ring(8);
2043 let mut producer = make_producer(&ring);
2044 let mut consumer = make_consumer(&ring);
2045
2046 let id = producer.submit_one(0x1000, 512, false).unwrap();
2047
2048 let (polled_id, chain) = consumer.poll_available().unwrap();
2049
2050 assert_eq!(polled_id, id);
2051 assert_eq!(chain.len(), 1);
2052 assert_eq!(chain.elems()[0].addr, 0x1000);
2053 assert_eq!(chain.elems()[0].len, 512);
2054 assert!(!chain.elems()[0].writable);
2055
2056 assert_eq!(consumer.id_num[id as usize], 1);
2058 assert_eq!(consumer.avail_cursor.head(), 1);
2059 }
2060
2061 #[test]
2062 fn test_consumer_poll_available_chain() {
2063 let ring = make_ring(8);
2064 let mut producer = make_producer(&ring);
2065 let mut consumer = make_consumer(&ring);
2066
2067 let chain = BufferChainBuilder::new()
2068 .readable(0x1000, 256)
2069 .readable(0x2000, 256)
2070 .writable(0x3000, 512)
2071 .build()
2072 .unwrap();
2073
2074 let id = producer.submit_available(&chain).unwrap();
2075
2076 let (polled_id, polled_chain) = consumer.poll_available().unwrap();
2077
2078 assert_eq!(polled_id, id);
2079 assert_eq!(polled_chain.len(), 3);
2080
2081 assert_eq!(polled_chain.elems()[0].addr, 0x1000);
2082 assert!(!polled_chain.elems()[0].writable);
2083
2084 assert_eq!(polled_chain.elems()[1].addr, 0x2000);
2085 assert!(!polled_chain.elems()[1].writable);
2086
2087 assert_eq!(polled_chain.elems()[2].addr, 0x3000);
2088 assert!(polled_chain.elems()[2].writable);
2089
2090 assert_eq!(consumer.id_num[id as usize], 3);
2091 }
2092
2093 #[test]
2094 fn test_consumer_rejects_duplicate_inflight_id() {
2095 let ring = make_ring(8);
2096 let mut producer = make_producer(&ring);
2097 let mut consumer = make_consumer(&ring);
2098
2099 let id = producer.submit_one(0x1000, 512, false).unwrap();
2100 let (polled_id, _) = consumer.poll_available().unwrap();
2101 assert_eq!(polled_id, id);
2102
2103 let mut desc = Descriptor::new(0x2000, 256, id, DescFlags::empty());
2104 desc.mark_avail(consumer.avail_cursor.wrap());
2105 ring.write_desc(consumer.avail_cursor.head(), desc);
2106
2107 assert!(matches!(
2108 consumer.poll_available(),
2109 Err(RingError::InvalidState)
2110 ));
2111 }
2112
2113 #[test]
2114 fn test_consumer_submit_used() {
2115 let ring = make_ring(8);
2116 let mut producer = make_producer(&ring);
2117 let mut consumer = make_consumer(&ring);
2118
2119 let id = producer.submit_one(0x1000, 512, true).unwrap();
2120
2121 let (polled_id, _) = consumer.poll_available().unwrap();
2122
2123 consumer.submit_used(polled_id, 256).unwrap();
2125
2126 let desc = ring.read_desc(0);
2128
2129 assert_eq!(desc.id, id);
2130 assert_eq!(desc.len, 256);
2131 assert!(desc.is_used(true));
2132
2133 assert_eq!(consumer.used_cursor.head(), 1);
2135 assert_eq!(consumer.id_num[id as usize], 0);
2136 }
2137
2138 #[test]
2139 fn test_consumer_submit_used_multi_descriptor() {
2140 let ring = make_ring(8);
2141 let mut producer = make_producer(&ring);
2142 let mut consumer = make_consumer(&ring);
2143
2144 let chain = BufferChainBuilder::new()
2145 .readable(0x1000, 256)
2146 .writable(0x2000, 512)
2147 .writable(0x3000, 512)
2148 .build()
2149 .unwrap();
2150
2151 producer.submit_available(&chain).unwrap();
2152
2153 let (id, _) = consumer.poll_available().unwrap();
2154
2155 consumer.submit_used(id, 1024).unwrap();
2156
2157 let head_desc = ring.read_desc(0);
2159 assert!(head_desc.is_used(true));
2160 assert_eq!(head_desc.len, 1024);
2161
2162 assert_eq!(consumer.used_cursor.head(), 3);
2164 assert_eq!(consumer.id_num[id as usize], 0);
2165 }
2166
2167 #[test]
2168 fn test_consumer_poll_empty() {
2169 let ring = make_ring(4);
2170 let mut consumer = make_consumer(&ring);
2171
2172 assert!(matches!(
2173 consumer.poll_available(),
2174 Err(RingError::WouldBlock)
2175 ));
2176 }
2177
2178 #[test]
2179 fn test_consumer_peek() {
2180 let ring = make_ring(8);
2181 let mut producer = make_producer(&ring);
2182 let consumer = make_consumer(&ring);
2183
2184 producer.submit_one(0x1000, 512, false).unwrap();
2185 assert!(consumer.peek_available().unwrap());
2186
2187 let empty_ring = make_ring(4);
2188 let empty_consumer = make_consumer(&empty_ring);
2189 assert!(!empty_consumer.peek_available().unwrap());
2190 }
2191
2192 #[test]
2193 fn test_full_roundtrip() {
2194 let ring = make_ring(8);
2195 let mut producer = make_producer(&ring);
2196 let mut consumer = make_consumer(&ring);
2197
2198 let chain = BufferChainBuilder::new()
2199 .readable(0x1000, 256)
2200 .writable(0x2000, 512)
2201 .build()
2202 .unwrap();
2203
2204 let id = producer.submit_available(&chain).unwrap();
2205
2206 let (consumer_id, consumer_chain) = consumer.poll_available().unwrap();
2207
2208 assert_eq!(consumer_id, id);
2209 assert_eq!(consumer_chain.len(), 2);
2210
2211 consumer.submit_used(consumer_id, 512).unwrap();
2212
2213 let used = producer.poll_used().unwrap();
2214 assert_eq!(used.id, id);
2215 assert_eq!(used.len, 512);
2216 }
2217
2218 #[test]
2219 fn ring_initial_poll_used_blocks() {
2220 let ring = make_ring(8);
2221 let mut producer = make_producer(&ring);
2222 for _ in 0..8 {
2224 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
2225 }
2226 assert_eq!(producer.num_free, ring.len());
2228 }
2229
2230 #[test]
2231 fn ring_consumer_blocks_until_submit() {
2232 let ring = make_ring(8);
2233 let mut producer = make_producer(&ring);
2234 let mut consumer = make_consumer(&ring);
2235
2236 assert!(matches!(
2237 consumer.poll_available(),
2238 Err(RingError::WouldBlock)
2239 ));
2240
2241 let chain = BufferChainBuilder::new()
2242 .readable(0x1000, 32)
2243 .readable(0x2000, 16)
2244 .build()
2245 .unwrap();
2246
2247 let id = producer.submit_available(&chain).unwrap();
2248
2249 let (cid, polled) = consumer.poll_available().unwrap();
2250 assert_eq!(cid, id);
2251 assert_eq!(polled.len(), chain.len());
2252 }
2253
2254 #[test]
2255 fn test_out_of_order_completion_stream() {
2256 let ring = make_ring(8);
2257 let mut producer = make_producer(&ring);
2258 let mut consumer = make_consumer(&ring);
2259
2260 let id_a = producer.submit_one(0x1000, 256, true).unwrap();
2262 let id_b = producer.submit_one(0x2000, 256, true).unwrap();
2263
2264 let (dev_id_a, chain_a) = consumer.poll_available().unwrap();
2266 assert_eq!(dev_id_a, id_a);
2267 assert_eq!(chain_a.len(), 1);
2268
2269 let (dev_id_b, chain_b) = consumer.poll_available().unwrap();
2270 assert_eq!(dev_id_b, id_b);
2271 assert_eq!(chain_b.len(), 1);
2272
2273 consumer.submit_used(dev_id_b, 128).unwrap();
2275 consumer.submit_used(dev_id_a, 256).unwrap();
2276
2277 let used_b = producer.poll_used().unwrap();
2279 assert_eq!(used_b.id, id_b);
2280 assert_eq!(used_b.len, 128);
2281
2282 let used_a = producer.poll_used().unwrap();
2284 assert_eq!(used_a.id, id_a);
2285 assert_eq!(used_a.len, 256);
2286
2287 assert!(producer.id_free.contains(&id_a));
2289 assert!(producer.id_free.contains(&id_b));
2290 }
2291
2292 #[test]
2293 fn test_mixed_chain_sizes_out_of_order_completion() {
2294 let ring = make_ring(16);
2295 let mut producer = make_producer(&ring);
2296 let mut consumer = make_consumer(&ring);
2297
2298 let chains = vec![
2299 BufferChainBuilder::new()
2300 .readable(0x1000, 10)
2301 .writable(0x2000, 5)
2302 .build()
2303 .unwrap(),
2304 BufferChainBuilder::new()
2305 .readable(0x3000, 8)
2306 .readable(0x3010, 8)
2307 .writable(0x3020, 16)
2308 .build()
2309 .unwrap(),
2310 BufferChainBuilder::new()
2311 .readable(0x4000, 4)
2312 .build()
2313 .unwrap(),
2314 BufferChainBuilder::new()
2315 .readable(0x5000, 4)
2316 .readable(0x5010, 4)
2317 .readable(0x5020, 4)
2318 .writable(0x5030, 4)
2319 .build()
2320 .unwrap(),
2321 ];
2322
2323 for c in &chains {
2324 producer.submit_available(c).unwrap();
2325 }
2326
2327 let mut dev_chain_lens = Vec::new();
2328 for _ in &chains {
2329 let (id, chain) = consumer.poll_available().unwrap();
2330 dev_chain_lens.push((id, chain.len() as u32));
2331 }
2332
2333 let order = [1, 3, 0, 2];
2334 let mut completion = Vec::new();
2335
2336 for &idx in &order {
2337 let (id, len) = dev_chain_lens[idx];
2338 consumer.submit_used(id, len).unwrap();
2339 completion.push((id, len));
2340 }
2341
2342 for (expected_id, expected_len) in &completion {
2343 let used = producer.poll_used().unwrap();
2344 assert_eq!(used.id, *expected_id);
2345 assert_eq!(used.len, *expected_len);
2346 assert_eq!(producer.id_num[*expected_id as usize], 0);
2347 assert!(producer.id_free.contains(expected_id));
2348 }
2349
2350 assert_invariants(&ring, &producer);
2351 }
2352
2353 #[test]
2355 fn test_used_stream_wrap_crossing() {
2356 let ring = make_ring(8);
2357 let mut producer = make_producer(&ring);
2358 let mut consumer = make_consumer(&ring);
2359
2360 let mut ids = Vec::new();
2362 for i in 0..8 {
2363 ids.push(producer.submit_one(0x1000 + i as u64, 1, false).unwrap());
2364 }
2365
2366 for _ in 0..8 {
2368 consumer.poll_available().unwrap();
2369 }
2370
2371 for &id in ids.iter().rev() {
2373 consumer.submit_used(id, 1).unwrap();
2374 }
2375
2376 for _ in 0..8 {
2378 producer.poll_used().unwrap();
2379 }
2380 assert_eq!(producer.used_cursor.head(), 0);
2381 assert!(!producer.used_cursor.wrap()); assert_invariants(&ring, &producer);
2383 }
2384
2385 #[test]
2387 fn test_interleaved_submit_completion() {
2388 let ring = make_ring(8);
2389 let mut producer = make_producer(&ring);
2390 let mut consumer = make_consumer(&ring);
2391
2392 let chain_a = BufferChainBuilder::new()
2394 .readable(0x1000, 8)
2395 .writable(0x2000, 8)
2396 .build()
2397 .unwrap();
2398 let id_a = producer.submit_available(&chain_a).unwrap();
2399
2400 let (dev_id_a, _) = consumer.poll_available().unwrap();
2402 assert_eq!(dev_id_a, id_a);
2403
2404 consumer.submit_used(dev_id_a, 8).unwrap();
2406
2407 let chain_b = BufferChainBuilder::new()
2409 .readable(0x3000, 4)
2410 .readable(0x3010, 4)
2411 .writable(0x3020, 4)
2412 .build()
2413 .unwrap();
2414 let id_b = producer.submit_available(&chain_b).unwrap();
2415
2416 let (dev_id_b, _) = consumer.poll_available().unwrap();
2418 assert_eq!(dev_id_b, id_b);
2419
2420 let used_a = producer.poll_used().unwrap();
2422 assert_eq!(used_a.id, id_a);
2423
2424 consumer.submit_used(dev_id_b, 12).unwrap();
2426
2427 let used_b = producer.poll_used().unwrap();
2429 assert_eq!(used_b.id, id_b);
2430
2431 assert_invariants(&ring, &producer);
2432 }
2433
2434 #[test]
2436 fn test_partial_publish_safety() {
2437 let ring = make_ring(8);
2438 let mut consumer = make_consumer(&ring);
2439 let mut producer = make_producer(&ring);
2440
2441 let chain = BufferChainBuilder::new()
2443 .readable(0x1000, 4)
2444 .readable(0x2000, 4)
2445 .writable(0x3000, 4)
2446 .build()
2447 .unwrap();
2448
2449 let id = producer.id_free.pop().unwrap();
2451 producer.id_num[id as usize] = chain.len() as u16;
2452
2453 let head_idx = producer.avail_cursor.head();
2455 let wrap_start = producer.avail_cursor.wrap();
2456 let mut pos = producer.avail_cursor;
2457 pos.advance();
2458
2459 for (i, elem) in chain.elems().iter().enumerate().skip(1) {
2460 let is_next = i + 1 < chain.len();
2461 let mut flags = DescFlags::empty();
2462 flags.set(DescFlags::NEXT, is_next);
2463 flags.set(DescFlags::WRITE, elem.writable);
2464 let mut d = Descriptor::new(elem.addr, elem.len, id, flags);
2465 d.mark_avail(pos.wrap());
2466 ring.write_desc(pos.head(), d);
2467 pos.advance();
2468 }
2469
2470 assert!(matches!(
2472 consumer.poll_available(),
2473 Err(RingError::WouldBlock)
2474 ));
2475
2476 let head_elem = chain.elems()[0];
2478 let mut head_flags = DescFlags::empty();
2479 head_flags.set(DescFlags::NEXT, true);
2480 head_flags.set(DescFlags::WRITE, head_elem.writable);
2481 let mut head_desc = Descriptor::new(head_elem.addr, head_elem.len, id, head_flags);
2482 head_desc.mark_avail(wrap_start);
2483 ring.write_desc(head_idx, head_desc);
2484 producer.avail_cursor = pos;
2485 producer.num_free -= chain.len();
2486
2487 let (dev_id, dev_chain) = consumer.poll_available().unwrap();
2489 assert_eq!(dev_id, id);
2490 assert_eq!(dev_chain.len(), chain.len());
2491 assert_invariants(&ring, &producer);
2492 }
2493
2494 #[test]
2496 fn test_tail_marked_used_ignored() {
2497 let ring = make_ring(8);
2498 let mut producer = make_producer(&ring);
2499
2500 let chain = BufferChainBuilder::new()
2501 .readable(0x1000, 4)
2502 .readable(0x2000, 4)
2503 .build()
2504 .unwrap();
2505 let id = producer.submit_available(&chain).unwrap();
2506
2507 let mut tail_desc = ring.read_desc(1);
2509 tail_desc.mark_used(producer.used_cursor.wrap());
2510 ring.write_desc(1, tail_desc);
2511
2512 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
2514
2515 let mut head_desc = ring.read_desc(0);
2517 head_desc.mark_used(producer.used_cursor.wrap());
2518 ring.write_desc(0, head_desc);
2519
2520 let used = producer.poll_used().unwrap();
2522 assert_eq!(used.id, id);
2523 assert_invariants(&ring, &producer);
2524 }
2525
2526 #[test]
2528 fn test_max_chain_len_rejected() {
2529 let ring = make_ring(8);
2530 let mut producer = make_producer(&ring);
2531
2532 let elems = (0..9).map(|i| BufferElement {
2534 addr: 0x1000 + i as u64,
2535 len: 42,
2536 writable: false,
2537 });
2538
2539 let chain = BufferChainBuilder::new().readables(elems).build().unwrap();
2540
2541 assert!(matches!(
2543 producer.submit_available(&chain),
2544 Err(RingError::WouldBlock)
2545 ));
2546 }
2547
2548 #[test]
2550 fn test_descriptor_state_monotonicity() {
2551 let ring = make_ring(8);
2552 let mut producer = make_producer(&ring);
2553 let mut consumer = make_consumer(&ring);
2554
2555 let mut states = vec![0u8; 8];
2557
2558 for _ in 0..5 {
2559 for state in states.iter_mut() {
2560 let id = producer.submit_one(0x1000, 4, false).unwrap();
2561 *state = (*state).max(1);
2563
2564 let (dev_id, _) = consumer.poll_available().unwrap();
2566 consumer.submit_used(dev_id, 4).unwrap();
2567 *state = (*state).max(2);
2568
2569 let used = producer.poll_used().unwrap();
2570 assert_eq!(used.id, id);
2571 *state = (*state).max(3);
2572 }
2573
2574 assert_invariants(&ring, &producer);
2575 }
2576
2577 for s in states {
2579 assert!(s >= 3);
2580 }
2581 }
2582
2583 #[test]
2585 fn test_random_stress_small() {
2586 use rand::RngExt;
2587 use rand::seq::SliceRandom;
2588
2589 let ring = make_ring(16);
2590 let mut producer = make_producer(&ring);
2591 let mut consumer = make_consumer(&ring);
2592 let mut rng = rand::rng();
2593
2594 let mut active_ids = Vec::new();
2596 for _ in 0..8 {
2597 let len = rng.random_range(1..=4);
2598 let mut b = BufferChainBuilder::new().readable(0x1000, 4);
2599 for i in 1..len {
2600 b = b.readable(0x1000 + i as u64 * 0x10, 4);
2601 }
2602 let chain = b.build().unwrap();
2603 if let Ok(id) = producer.submit_available(&chain) {
2604 active_ids.push(id);
2605 }
2606 }
2607
2608 let mut dev_ids = Vec::new();
2609 while let Ok((id, _)) = consumer.poll_available() {
2610 dev_ids.push(id);
2611 }
2612
2613 dev_ids.shuffle(&mut rng);
2615 for id in &dev_ids {
2616 let chain_len = consumer.id_num[*id as usize];
2617 consumer.submit_used(*id, chain_len as u32 * 4).unwrap();
2618 }
2619 for _ in &dev_ids {
2621 if producer.poll_used().is_ok() {}
2622 }
2623
2624 assert_invariants(&ring, &producer);
2625 }
2626
2627 #[test]
2629 fn test_out_of_order_multi_length() {
2630 let ring = make_ring(16);
2631 let mut producer = make_producer(&ring);
2632 let mut consumer = make_consumer(&ring);
2633
2634 let chain_a = BufferChainBuilder::new()
2635 .readable(0x1000, 4)
2636 .writable(0x2000, 4)
2637 .build()
2638 .unwrap();
2639 let chain_b = BufferChainBuilder::new()
2640 .readable(0x3000, 4)
2641 .readable(0x3010, 4)
2642 .writable(0x3020, 4)
2643 .build()
2644 .unwrap();
2645 let chain_c = BufferChainBuilder::new()
2646 .readable(0x4000, 4)
2647 .build()
2648 .unwrap();
2649
2650 let id_a = producer.submit_available(&chain_a).unwrap();
2651 let id_b = producer.submit_available(&chain_b).unwrap();
2652 let id_c = producer.submit_available(&chain_c).unwrap();
2653
2654 let (d_a, _) = consumer.poll_available().unwrap();
2655 let (d_b, _) = consumer.poll_available().unwrap();
2656 let (d_c, _) = consumer.poll_available().unwrap();
2657 assert_eq!(d_a, id_a);
2658 assert_eq!(d_b, id_b);
2659 assert_eq!(d_c, id_c);
2660
2661 consumer.submit_used(d_b, 12).unwrap();
2663 consumer.submit_used(d_c, 4).unwrap();
2664 consumer.submit_used(d_a, 8).unwrap();
2665
2666 let u_b = producer.poll_used().unwrap();
2667 assert_eq!(u_b.id, id_b);
2668 let u_c = producer.poll_used().unwrap();
2669 assert_eq!(u_c.id, id_c);
2670 let u_a = producer.poll_used().unwrap();
2671 assert_eq!(u_a.id, id_a);
2672
2673 assert_invariants(&ring, &producer);
2674 }
2675
2676 #[test]
2677 fn interleave_submit_and_completion() {
2678 let ring = make_ring(16);
2679 let mut producer = make_producer(&ring);
2680 let mut consumer = make_consumer(&ring);
2681
2682 let chain_a = BufferChainBuilder::new()
2684 .readable(0x1000, 4)
2685 .writable(0x2000, 4)
2686 .build()
2687 .unwrap();
2688 let id_a = producer.submit_available(&chain_a).unwrap();
2689
2690 let (d_a, _) = consumer.poll_available().unwrap();
2692 assert_eq!(d_a, id_a);
2693
2694 consumer.submit_used(d_a, 8).unwrap();
2696
2697 let chain_b = BufferChainBuilder::new()
2699 .readable(0x3000, 4)
2700 .readable(0x3010, 4)
2701 .writable(0x3020, 4)
2702 .build()
2703 .unwrap();
2704 let id_b = producer.submit_available(&chain_b).unwrap();
2705
2706 let u_a = producer.poll_used().unwrap();
2708 assert_eq!(u_a.id, id_a);
2709 assert_eq!(u_a.len, 8);
2710
2711 let (d_b, _) = consumer.poll_available().unwrap();
2713 assert_eq!(d_b, id_b);
2714 consumer.submit_used(d_b, 12).unwrap();
2715
2716 let id_c = producer.submit_one(0x4000, 4, false).unwrap();
2718
2719 let (d_c, _) = consumer.poll_available().unwrap();
2721 assert_eq!(d_c, id_c);
2722 consumer.submit_used(d_c, 4).unwrap();
2723
2724 let u_b = producer.poll_used().unwrap();
2726 assert_eq!(u_b.id, id_b);
2727 assert_eq!(u_b.len, 12);
2728
2729 let u_c = producer.poll_used().unwrap();
2730 assert_eq!(u_c.id, id_c);
2731 assert_eq!(u_c.len, 4);
2732
2733 assert_invariants(&ring, &producer);
2734 }
2735
2736 #[test]
2738 fn producer_disable_used_notifications_writes_driver_disable() {
2739 let ring = make_ring(8);
2740 let mut producer = make_producer(&ring);
2741
2742 assert_eq!(ring.read_driver_event().flags(), EventFlags::ENABLE);
2743 producer.disable_used_notifications().unwrap();
2744 assert_eq!(ring.read_driver_event().flags(), EventFlags::DISABLE);
2745 }
2746
2747 #[test]
2748 fn producer_enable_used_notifications_writes_driver_enable() {
2749 let ring = make_ring(8);
2750 let mut producer = make_producer(&ring);
2751
2752 producer.disable_used_notifications().unwrap();
2753 assert_eq!(ring.read_driver_event().flags(), EventFlags::DISABLE);
2754
2755 producer.enable_used_notifications().unwrap();
2756 assert_eq!(ring.read_driver_event().flags(), EventFlags::ENABLE);
2757 }
2758
2759 #[test]
2760 fn producer_enable_used_notifications_desc_sets_off_wrap_and_flags() {
2761 let ring = make_ring(8);
2762 let mut producer = make_producer(&ring);
2763
2764 producer.enable_used_notifications_desc(5, true).unwrap();
2765
2766 let evt = ring.read_driver_event();
2767 assert_eq!(evt.flags(), EventFlags::DESC);
2768 assert_eq!(evt.desc_event_off(), 5);
2769 assert!(evt.desc_event_wrap());
2770 }
2771
2772 #[test]
2773 fn producer_enable_used_notifications_for_next_programs_used_cursor() {
2774 let ring = make_ring(8);
2775 let mut producer = make_producer(&ring);
2776
2777 producer.enable_used_notifications_for_next().unwrap();
2779
2780 let evt = ring.read_driver_event();
2781 assert_eq!(evt.flags(), EventFlags::DESC);
2782 assert_eq!(evt.desc_event_off(), 0);
2783 assert!(evt.desc_event_wrap());
2784 }
2785
2786 #[test]
2787 fn consumer_disable_avail_notifications_writes_device_disable() {
2788 let ring = make_ring(8);
2789 let mut consumer = make_consumer(&ring);
2790
2791 assert_eq!(ring.read_device_event().flags(), EventFlags::ENABLE);
2792 consumer.disable_avail_notifications().unwrap();
2793 assert_eq!(ring.read_device_event().flags(), EventFlags::DISABLE);
2794 }
2795
2796 #[test]
2797 fn consumer_enable_avail_notifications_writes_device_enable() {
2798 let ring = make_ring(8);
2799 let mut consumer = make_consumer(&ring);
2800
2801 consumer.disable_avail_notifications().unwrap();
2802 assert_eq!(ring.read_device_event().flags(), EventFlags::DISABLE);
2803
2804 consumer.enable_avail_notifications().unwrap();
2805 assert_eq!(ring.read_device_event().flags(), EventFlags::ENABLE);
2806 }
2807
2808 #[test]
2809 fn consumer_enable_avail_notifications_desc_sets_off_wrap_and_flags() {
2810 let ring = make_ring(8);
2811 let mut consumer = make_consumer(&ring);
2812
2813 consumer.enable_avail_notifications_desc(7, false).unwrap();
2814
2815 let evt = ring.read_device_event();
2816 assert_eq!(evt.flags(), EventFlags::DESC);
2817 assert_eq!(evt.desc_event_off(), 7);
2818 assert!(!evt.desc_event_wrap());
2819 }
2820
2821 #[test]
2822 fn consumer_enable_avail_notifications_for_next_programs_avail_cursor() {
2823 let ring = make_ring(8);
2824 let mut consumer = make_consumer(&ring);
2825
2826 consumer.enable_avail_notifications_for_next().unwrap();
2828
2829 let evt = ring.read_device_event();
2830 assert_eq!(evt.flags(), EventFlags::DESC);
2831 assert_eq!(evt.desc_event_off(), 0);
2832 assert!(evt.desc_event_wrap());
2833 }
2834
2835 #[test]
2836 fn producer_does_not_write_device_event_when_toggling_used_notifications() {
2837 let ring = make_ring(8);
2838 let mut producer = make_producer(&ring);
2839
2840 let dev_before = ring.read_device_event();
2841 producer.disable_used_notifications().unwrap();
2842 let dev_after = ring.read_device_event();
2843
2844 assert_eq!(dev_after, dev_before);
2845 }
2846
2847 #[test]
2848 fn consumer_does_not_write_driver_event_when_toggling_avail_notifications() {
2849 let ring = make_ring(8);
2850 let mut consumer = make_consumer(&ring);
2851
2852 let drv_before = ring.read_driver_event();
2853 consumer.disable_avail_notifications().unwrap();
2854 let drv_after = ring.read_driver_event();
2855
2856 assert_eq!(drv_after, drv_before);
2857 }
2858
2859 #[test]
2860 fn should_notify_flags_enable_disable() {
2861 let ring_len = 8;
2862
2863 let old = RingCursor {
2864 head: 0,
2865 size: ring_len,
2866 wrap: true,
2867 };
2868 let new = RingCursor {
2869 head: 1,
2870 size: ring_len,
2871 wrap: true,
2872 };
2873
2874 let evt = EventSuppression::new(0, EventFlags::DISABLE);
2876 assert!(!should_notify(evt, ring_len, old, new));
2877
2878 let evt = EventSuppression::new(0, EventFlags::ENABLE);
2880 assert!(should_notify(evt, ring_len, old, new));
2881 }
2882
2883 #[test]
2884 fn should_notify_desc_no_crossing() {
2885 let ring_len = 8;
2886
2887 let old = RingCursor {
2888 head: 2,
2889 size: ring_len,
2890 wrap: true,
2891 };
2892 let new = RingCursor {
2893 head: 3,
2894 size: ring_len,
2895 wrap: true,
2896 };
2897
2898 let mut evt = EventSuppression::zeroed();
2900 evt.set_desc_event(6, true);
2901 evt.set_flags(EventFlags::DESC);
2902
2903 assert!(!should_notify(evt, ring_len, old, new));
2904 }
2905
2906 #[test]
2907 fn should_notify_desc_wrap_mismatch_adjusts_event_idx() {
2908 let ring_len = 8;
2909
2910 let old = RingCursor {
2911 head: 7,
2912 size: ring_len,
2913 wrap: true,
2914 };
2915 let new = RingCursor {
2916 head: 1,
2917 size: ring_len,
2918 wrap: false,
2919 };
2920
2921 let mut evt = EventSuppression::zeroed();
2922 evt.set_desc_event(7, true);
2923 evt.set_flags(EventFlags::DESC);
2924
2925 assert!(should_notify(evt, ring_len, old, new));
2926 }
2927
2928 #[test]
2929 fn ring_need_event_basic_cases() {
2930 assert!(ring_need_event(4, 5, 2));
2932 assert!(!ring_need_event(4, 5, 5));
2934
2935 let old = 0xFFFE;
2937 let new = 1;
2938 assert!(ring_need_event(0xFFFF, new, old));
2940 }
2941
2942 #[test]
2944 fn bad_device_marks_tail_used() {
2945 let ring = make_ring(8);
2946 let mut producer = make_producer(&ring);
2947
2948 let chain = BufferChainBuilder::new()
2949 .readable(0x1000, 4)
2950 .readable(0x2000, 4)
2951 .build()
2952 .unwrap();
2953 let id = producer.submit_available(&chain).unwrap();
2954
2955 let mut tail = ring.read_desc(1);
2957 tail.mark_used(producer.used_cursor.wrap());
2958 ring.write_desc(1, tail);
2959
2960 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
2962
2963 let mut head = ring.read_desc(0);
2965 head.mark_used(producer.used_cursor.wrap());
2966 ring.write_desc(0, head);
2967
2968 let used = producer.poll_used().unwrap();
2969 assert_eq!(used.id, id);
2970 }
2971
2972 #[test]
2973 fn bad_device_wrong_used_bits() {
2974 let ring = make_ring(4);
2975 let mut producer = make_producer(&ring);
2976
2977 let id = producer.submit_one(0x1000, 8, true).unwrap();
2978
2979 let mut d = ring.read_desc(0);
2981 d.mark_avail(producer.used_cursor.wrap());
2983 d.len = 8;
2984 ring.write_desc(0, d);
2985
2986 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
2987
2988 let mut d2 = ring.read_desc(0);
2989 d2.mark_used(producer.used_cursor.wrap());
2990 ring.write_desc(0, d2);
2991
2992 let u = producer.poll_used().unwrap();
2993 assert_eq!(u.id, id);
2994 }
2995
2996 #[test]
2997 fn bad_driver_next_never_clears() {
2998 let ring = make_ring(8);
2999 let mut consumer = make_consumer(&ring);
3000 let mut producer = make_producer(&ring);
3001
3002 let id = producer.id_free.pop().unwrap();
3004 producer.id_num[id as usize] = 8;
3005
3006 let mut pos = producer.avail_cursor;
3007 let wrap_start = pos.wrap();
3008
3009 for _ in 0..8 {
3011 let idx = pos.head();
3012 let mut flags = DescFlags::empty();
3013 flags.set(DescFlags::NEXT, true); let mut desc = Descriptor::new(0x1000 + idx as u64 * 0x10, 4, id, flags);
3015 desc.mark_avail(pos.wrap());
3016 ring.write_desc(idx, desc);
3017 pos.advance();
3018 }
3019
3020 let head_idx = producer.avail_cursor.head();
3022 let mut head_flags = DescFlags::empty();
3023 head_flags.set(DescFlags::NEXT, true);
3024 let mut head_desc = Descriptor::new(0x42, 4, id, head_flags);
3025 head_desc.mark_avail(wrap_start);
3026 ring.write_desc(head_idx, head_desc);
3027
3028 assert!(matches!(
3030 consumer.poll_available(),
3031 Err(RingError::BadChain)
3032 ));
3033 }
3034
3035 #[test]
3036 fn bad_driver_interleaved_readables_and_writables() {
3037 let ring = make_ring(8);
3038 let mut consumer = make_consumer(&ring);
3039 let mut producer = make_producer(&ring);
3040
3041 let chain = BufferChainBuilder::new()
3042 .readable(0x1000, 4)
3043 .readable(0x2000, 4)
3044 .writable(0x2000, 4)
3045 .build()
3046 .unwrap();
3047
3048 let _id = producer.submit_available(&chain).unwrap();
3049
3050 let mut first = ring.read_desc(0);
3052 first.flags |= DescFlags::WRITE.bits();
3053 ring.write_desc(0, first);
3054
3055 assert!(matches!(
3056 consumer.poll_available(),
3057 Err(RingError::BadChain)
3058 ));
3059 }
3060
3061 #[test]
3062 fn bad_device_marks_multiple_used_in_chain() {
3063 let ring = make_ring(8);
3064 let mut producer = make_producer(&ring);
3065
3066 let chain = BufferChainBuilder::new()
3067 .readable(0x1000, 4)
3068 .readable(0x2000, 4)
3069 .build()
3070 .unwrap();
3071 let id = producer.submit_available(&chain).unwrap();
3072
3073 let mut head = ring.read_desc(0);
3075 head.mark_used(producer.used_cursor.wrap());
3076 ring.write_desc(0, head);
3077
3078 let mut tail = ring.read_desc(1);
3079 tail.mark_used(producer.used_cursor.wrap());
3080 ring.write_desc(1, tail);
3081
3082 let u = producer.poll_used().unwrap();
3084 assert_eq!(u.id, id);
3085
3086 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
3088 }
3089
3090 #[test]
3091 fn bad_device_writes_used_at_wrong_slot() {
3092 let ring = make_ring(8);
3093 let mut producer = make_producer(&ring);
3094
3095 let _id = producer.submit_one(0x1000, 4, true).unwrap();
3096
3097 let mut d = ring.read_desc(3);
3099 d.mark_used(producer.used_cursor.wrap());
3100 ring.write_desc(3, d);
3101
3102 assert!(matches!(producer.poll_used(), Err(RingError::WouldBlock)));
3104
3105 let mut d0 = ring.read_desc(0);
3107 d0.mark_used(producer.used_cursor.wrap());
3108 ring.write_desc(0, d0);
3109 let _u = producer.poll_used().unwrap();
3110 }
3111
3112 #[test]
3113 fn bad_driver_reuses_id_while_outstanding() {
3114 let ring = make_ring(8);
3115 let mut producer = make_producer(&ring);
3116
3117 let id = producer.submit_one(0x1000, 4, false).unwrap();
3119 assert_eq!(producer.id_num[id as usize], 1);
3120
3121 producer.id_free.push(id);
3123
3124 let res = producer.submit_one(0x2000, 4, false);
3126 assert!(matches!(res, Err(RingError::InvalidState)));
3127 }
3128
3129 #[test]
3130 fn test_avail_cursor_accessor() {
3131 let ring = make_ring(8);
3132 let mut producer = make_producer(&ring);
3133
3134 let cursor = producer.avail_cursor();
3136 assert_eq!(cursor.head(), 0);
3137 assert!(cursor.wrap());
3138
3139 producer.submit_one(0x1000, 512, false).unwrap();
3141 let cursor = producer.avail_cursor();
3142 assert_eq!(cursor.head(), 1);
3143 assert!(cursor.wrap());
3144 }
3145
3146 #[test]
3147 fn test_should_notify_since() {
3148 let ring = make_ring(8);
3149 let mut producer = make_producer(&ring);
3150
3151 let before = producer.avail_cursor();
3152 producer.submit_one(0x1000, 512, false).unwrap();
3153
3154 let should_notify = producer.should_notify_since(before).unwrap();
3156 assert!(should_notify);
3157 }
3158
3159 #[test]
3160 fn test_batch_notification_single_check() {
3161 let ring = make_ring(8);
3162 let mut producer = make_producer(&ring);
3163 let mut consumer = make_consumer(&ring);
3164
3165 let before = producer.avail_cursor();
3166
3167 producer.submit_one(0x1000, 512, false).unwrap();
3169 producer.submit_one(0x2000, 512, false).unwrap();
3170 producer.submit_one(0x3000, 512, false).unwrap();
3171
3172 let should_notify = producer.should_notify_since(before).unwrap();
3174 assert!(should_notify);
3175
3176 for _ in 0..3 {
3178 let (_, _) = consumer.poll_available().unwrap();
3179 }
3180 }
3181
3182 #[test]
3183 fn test_ring_cursor_reset() {
3184 let mut cursor = RingCursor::new(16);
3185 cursor.advance_by(5);
3186 assert_eq!(cursor.head(), 5);
3187
3188 cursor.reset();
3189 assert_eq!(cursor, RingCursor::new(16));
3190 assert_eq!(cursor.head(), 0);
3191 assert!(cursor.wrap());
3192 }
3193
3194 #[test]
3195 fn test_ring_cursor_reset_after_wrap() {
3196 let mut cursor = RingCursor::new(4);
3197 cursor.advance_by(5);
3199 assert_eq!(cursor.head(), 1);
3200 assert!(!cursor.wrap());
3201
3202 cursor.reset();
3203 assert_eq!(cursor.head(), 0);
3204 assert!(cursor.wrap());
3205 }
3206
3207 #[test]
3208 fn test_ring_producer_reset_matches_new() {
3209 let ring = make_ring(8);
3210 let fresh = make_producer(&ring);
3211
3212 let mut used = make_producer(&ring);
3213 used.submit_one(0x1000, 64, false).unwrap();
3215 used.submit_one(0x2000, 128, true).unwrap();
3216
3217 used.reset();
3218
3219 assert_eq!(used.avail_cursor, fresh.avail_cursor);
3220 assert_eq!(used.used_cursor, fresh.used_cursor);
3221 assert_eq!(used.num_free, fresh.num_free);
3222 assert_eq!(used.id_free.len(), fresh.id_free.len());
3223 assert_eq!(used.id_num.as_slice(), fresh.id_num.as_slice());
3224 assert_eq!(used.event_flags_shadow, fresh.event_flags_shadow);
3225 }
3226
3227 #[test]
3228 fn test_ring_producer_reset_id_free_complete() {
3229 let ring = make_ring(8);
3230 let mut producer = make_producer(&ring);
3231
3232 for i in 0..4u64 {
3234 producer.submit_one(0x1000 + i * 0x100, 64, false).unwrap();
3235 }
3236 assert_eq!(producer.num_free, 4);
3237
3238 producer.reset();
3239
3240 assert_eq!(producer.num_free, 8);
3241 assert_eq!(producer.id_free.len(), 8);
3242 for id in 0..8u16 {
3244 assert!(producer.id_free.contains(&id));
3245 }
3246 }
3247
3248 #[test]
3249 fn test_ring_consumer_reset_matches_new() {
3250 let ring = make_ring(8);
3251 let fresh = make_consumer(&ring);
3252
3253 let mut used = make_consumer(&ring);
3254
3255 let mut producer = make_producer(&ring);
3257 producer.submit_one(0x1000, 64, false).unwrap();
3258
3259 let (id, _chain) = used.poll_available().unwrap();
3261 used.submit_used(id, 64).unwrap();
3262
3263 used.reset();
3264
3265 assert_eq!(used.avail_cursor, fresh.avail_cursor);
3266 assert_eq!(used.used_cursor, fresh.used_cursor);
3267 assert_eq!(used.id_num.as_slice(), fresh.id_num.as_slice());
3268 assert_eq!(used.num_inflight, fresh.num_inflight);
3269 assert_eq!(used.event_flags_shadow, fresh.event_flags_shadow);
3270 }
3271
3272 #[test]
3273 fn test_ring_consumer_reset_clears_inflight() {
3274 let ring = make_ring(8);
3275 let mut producer = make_producer(&ring);
3276 let mut consumer = make_consumer(&ring);
3277
3278 producer.submit_one(0x1000, 64, false).unwrap();
3280 producer.submit_one(0x2000, 64, false).unwrap();
3281 let _ = consumer.poll_available().unwrap();
3282 let _ = consumer.poll_available().unwrap();
3283 assert_eq!(consumer.num_inflight, 2);
3284
3285 consumer.reset();
3286 assert_eq!(consumer.num_inflight, 0);
3287 }
3288
3289 #[test]
3290 fn test_reset_prefilled_sets_cursors() {
3291 let ring = make_ring(8);
3292 let mut producer = make_producer(&ring);
3293 let ids: Vec<u16> = (0..8).collect();
3294 producer.reset_prefilled(&ids);
3295
3296 assert_eq!(producer.avail_cursor.head(), 0);
3298 assert!(!producer.avail_cursor.wrap());
3299 assert_eq!(producer.used_cursor.head(), 0);
3301 assert!(producer.used_cursor.wrap());
3302 }
3303
3304 #[test]
3305 fn test_reset_prefilled_all_ids_inflight() {
3306 let ring = make_ring(8);
3307 let mut producer = make_producer(&ring);
3308 let ids: Vec<u16> = (0..8).collect();
3309 producer.reset_prefilled(&ids);
3310
3311 assert_eq!(producer.num_free, 0);
3312 assert!(producer.id_free.is_empty());
3313 assert!(producer.id_num.iter().all(|&n| n == 1));
3314 }
3315
3316 #[test]
3317 fn test_reset_prefilled_partial() {
3318 let ring = make_ring(8);
3319 let mut producer = make_producer(&ring);
3320 producer.reset_prefilled(&[5, 6, 7, 3]);
3321
3322 assert_eq!(producer.avail_cursor.head(), 4);
3324 assert!(producer.avail_cursor.wrap());
3325 assert_eq!(producer.used_cursor.head(), 0);
3327 assert!(producer.used_cursor.wrap());
3328
3329 assert_eq!(producer.num_free, 4);
3330 assert_eq!(producer.id_free.len(), 4);
3331 for &id in &[0, 1, 2, 4] {
3332 assert!(producer.id_free.contains(&id));
3333 }
3334 for &id in &[5, 6, 7, 3] {
3336 assert_eq!(producer.id_num[id as usize], 1);
3337 }
3338 for &id in &[0, 1, 2, 4] {
3339 assert_eq!(producer.id_num[id as usize], 0);
3340 }
3341 }
3342
3343 #[test]
3344 fn test_reset_prefilled_partial_then_submit() {
3345 let ring = make_ring(8);
3346 let mut producer = make_producer(&ring);
3347 producer.reset_prefilled(&[4, 5, 6, 7]);
3348
3349 let id = producer.submit_one(0x8000, 128, false).unwrap();
3350
3351 assert!([0, 1, 2, 3].contains(&id));
3352 assert_eq!(producer.num_free, 3);
3353 assert_eq!(producer.id_num[id as usize], 1);
3354 }
3355
3356 #[test]
3357 fn test_reset_prefilled_then_poll_used() {
3358 let ring = make_ring(4);
3359 let mut producer = make_producer(&ring);
3360
3361 for i in 0..4u64 {
3363 producer.submit_one(0x1000 + i * 4096, 4096, true).unwrap();
3364 }
3365
3366 let mut consumer = make_consumer(&ring);
3368 let (id, _chain) = consumer.poll_available().unwrap();
3369 consumer.submit_used(id, 64).unwrap();
3370
3371 let mut restored = make_producer(&ring);
3373 restored.reset_prefilled(&[0, 1, 2, 3]);
3374
3375 let used = restored.poll_used().unwrap();
3377 assert_eq!(used.id, id);
3378 }
3379
3380 #[test]
3381 fn test_desc_table_read_after_submit() {
3382 let ring = make_ring(8);
3383 let mut writer = make_producer(&ring);
3384 writer.submit_one(0x1000, 4096, true).unwrap();
3385
3386 let reader = make_producer(&ring);
3387 let addr = reader.desc_table().desc_addr(0).unwrap();
3388 let flags = Descriptor::read_flags_acquire(reader.mem(), addr).unwrap();
3389 let desc = Descriptor::read_body(reader.mem(), addr, flags).unwrap();
3390 assert_eq!(desc.addr, 0x1000);
3391 assert_eq!(desc.len, 4096);
3392 assert!(desc.is_writable());
3393 assert!(desc.is_avail(true));
3394 assert!(!desc.is_used(true));
3395 }
3396
3397 #[test]
3398 fn test_desc_table_out_of_bounds() {
3399 let ring = make_ring(8);
3400 let reader = make_producer(&ring);
3401 assert!(reader.desc_table().desc_addr(8).is_none());
3402 }
3403
3404 #[test]
3405 fn test_desc_table_read_used_descriptor() {
3406 let ring = make_ring(8);
3407 let mut writer = make_producer(&ring);
3408 writer.submit_one(0x1000, 4096, true).unwrap();
3409
3410 let mut consumer = make_consumer(&ring);
3411 let (id, _chain) = consumer.poll_available().unwrap();
3412 consumer.submit_used(id, 128).unwrap();
3413
3414 let reader = make_producer(&ring);
3415 let addr = reader.desc_table().desc_addr(0).unwrap();
3416 let flags = Descriptor::read_flags_acquire(reader.mem(), addr).unwrap();
3417 let desc = Descriptor::read_body(reader.mem(), addr, flags).unwrap();
3418 assert!(desc.is_used(true));
3419 assert!(!desc.is_avail(true));
3420 }
3421}
3422
3423#[cfg(test)]
3425mod virtio_villain {
3426 use super::tests::{OwnedRing, make_consumer, make_producer, make_ring};
3427 use super::*;
3428
3429 fn raw_desc(id: u16, len: u32, flags: DescFlags) -> Descriptor {
3430 Descriptor::new(0x1000 + u64::from(id) * 0x10, len, id, flags)
3431 }
3432
3433 fn avail_desc(id: u16, len: u32, flags: DescFlags) -> Descriptor {
3434 let mut desc = raw_desc(id, len, flags);
3435 desc.mark_avail(true);
3436 desc
3437 }
3438
3439 fn write_avail(ring: &OwnedRing, idx: u16, id: u16, flags: DescFlags) {
3440 write_avail_len(ring, idx, id, 16, flags);
3441 }
3442
3443 fn write_avail_len(ring: &OwnedRing, idx: u16, id: u16, len: u32, flags: DescFlags) {
3444 ring.write_desc(idx, avail_desc(id, len, flags));
3445 }
3446
3447 fn write_driver_event(ring: &OwnedRing, off_wrap: u16, flags: u16) {
3448 write_event(ring, ring.layout().drv_evt_addr(), off_wrap, flags);
3449 }
3450
3451 fn write_device_event(ring: &OwnedRing, off_wrap: u16, flags: u16) {
3452 write_event(ring, ring.layout().dev_evt_addr(), off_wrap, flags);
3453 }
3454
3455 fn write_event(ring: &OwnedRing, addr: u64, off_wrap: u16, flags: u16) {
3456 ring.mem()
3457 .write(
3458 addr,
3459 &[
3460 (off_wrap & 0xff) as u8,
3461 (off_wrap >> 8) as u8,
3462 (flags & 0xff) as u8,
3463 (flags >> 8) as u8,
3464 ],
3465 )
3466 .unwrap();
3467 }
3468
3469 #[test]
3470 fn p0003_chain_with_next_past_ring_is_rejected() {
3471 let ring = make_ring(4);
3472 let mut consumer = make_consumer(&ring);
3473
3474 for idx in 0..ring.len() as u16 {
3475 write_avail(&ring, idx, 0, DescFlags::NEXT);
3476 }
3477
3478 assert!(matches!(
3479 consumer.poll_available(),
3480 Err(RingError::BadChain)
3481 ));
3482 }
3483
3484 #[test]
3485 fn p0005_indirect_without_feature_is_rejected() {
3486 let ring = make_ring(8);
3487 let mut consumer = make_consumer(&ring);
3488
3489 write_avail(&ring, 0, 0, DescFlags::INDIRECT);
3490
3491 assert!(matches!(
3492 consumer.poll_available(),
3493 Err(RingError::BadChain)
3494 ));
3495 }
3496
3497 #[test]
3498 fn p0006_indirect_with_bad_flags_is_rejected() {
3499 let ring = make_ring(8);
3500 let mut consumer = make_consumer(&ring);
3501
3502 write_avail(&ring, 0, 0, DescFlags::INDIRECT | DescFlags::WRITE);
3503
3504 assert!(matches!(
3505 consumer.poll_available(),
3506 Err(RingError::BadChain)
3507 ));
3508 }
3509
3510 #[test]
3511 fn p0007_indirect_tail_in_mixed_chain_is_rejected() {
3512 let ring = make_ring(8);
3513 let mut consumer = make_consumer(&ring);
3514
3515 write_avail(&ring, 0, 0, DescFlags::NEXT);
3516 write_avail(&ring, 1, 0, DescFlags::INDIRECT | DescFlags::WRITE);
3517
3518 assert!(matches!(
3519 consumer.poll_available(),
3520 Err(RingError::BadChain)
3521 ));
3522 }
3523
3524 #[test]
3525 fn p0008_long_chain_is_consumable_at_ring_layer() {
3526 let ring = make_ring(16);
3527 let mut consumer = make_consumer(&ring);
3528
3529 for idx in 0..12u16 {
3530 let flags = if idx == 11 {
3531 DescFlags::WRITE
3532 } else {
3533 DescFlags::NEXT | DescFlags::WRITE
3534 };
3535 write_avail(&ring, idx, 0, flags);
3536 }
3537
3538 let (id, chain) = consumer.poll_available().unwrap();
3539 assert_eq!(id, 0);
3540 assert_eq!(chain.len(), 12);
3541 }
3542
3543 #[test]
3544 fn p0009_unaligned_descriptor_address_is_preserved() {
3545 let ring = make_ring(8);
3546 let mut consumer = make_consumer(&ring);
3547
3548 let mut desc = Descriptor::new(0x1003, 16, 0, DescFlags::empty());
3549 desc.mark_avail(true);
3550 ring.write_desc(0, desc);
3551
3552 let (_, chain) = consumer.poll_available().unwrap();
3553 assert_eq!(chain.elems()[0].addr, 0x1003);
3554 }
3555
3556 #[test]
3557 fn p0010_writable_before_readable_is_rejected() {
3558 let ring = make_ring(8);
3559 let mut consumer = make_consumer(&ring);
3560
3561 write_avail(&ring, 0, 0, DescFlags::NEXT);
3562 write_avail(&ring, 1, 0, DescFlags::NEXT | DescFlags::WRITE);
3563 write_avail(&ring, 2, 0, DescFlags::NEXT);
3564 write_avail(&ring, 3, 0, DescFlags::WRITE);
3565
3566 assert!(matches!(
3567 consumer.poll_available(),
3568 Err(RingError::BadChain)
3569 ));
3570 }
3571
3572 #[test]
3573 fn p0011_stale_wrap_descriptor_is_ignored() {
3574 let ring = make_ring(8);
3575 let mut consumer = make_consumer(&ring);
3576
3577 let mut desc = raw_desc(0, 16, DescFlags::empty());
3578 desc.mark_avail(false);
3579 ring.write_desc(0, desc);
3580
3581 assert!(matches!(
3582 consumer.poll_available(),
3583 Err(RingError::WouldBlock)
3584 ));
3585 }
3586
3587 #[test]
3588 fn p0012_multidescriptor_oob_id_is_rejected() {
3589 let ring = make_ring(8);
3590 let mut consumer = make_consumer(&ring);
3591 let bad_id = ring.len() as u16;
3592
3593 write_avail(&ring, 0, bad_id, DescFlags::NEXT);
3594 write_avail(&ring, 1, bad_id, DescFlags::WRITE);
3595
3596 assert!(matches!(
3597 consumer.poll_available(),
3598 Err(RingError::InvalidState)
3599 ));
3600 }
3601
3602 #[test]
3603 fn p0013_duplicate_inflight_buffer_id_is_rejected() {
3604 let ring = make_ring(8);
3605 let mut consumer = make_consumer(&ring);
3606
3607 write_avail(&ring, 0, 0, DescFlags::NEXT);
3608 write_avail(&ring, 1, 0, DescFlags::WRITE);
3609 write_avail(&ring, 2, 0, DescFlags::NEXT);
3610 write_avail(&ring, 3, 0, DescFlags::WRITE);
3611
3612 let (first_id, first_chain) = consumer.poll_available().unwrap();
3613 assert_eq!(first_id, 0);
3614 assert_eq!(first_chain.len(), 2);
3615
3616 assert!(matches!(
3617 consumer.poll_available(),
3618 Err(RingError::InvalidState)
3619 ));
3620 }
3621
3622 #[test]
3623 fn p0014_reserved_driver_event_flags_do_not_block_processing() {
3624 let ring = make_ring(8);
3625 let mut consumer = make_consumer(&ring);
3626
3627 write_driver_event(&ring, 0, 3);
3628 write_avail(&ring, 0, 0, DescFlags::empty());
3629
3630 let (id, chain) = consumer.poll_available().unwrap();
3631 assert_eq!(id, 0);
3632 assert_eq!(chain.len(), 1);
3633 }
3634
3635 #[test]
3636 fn p0015_wrap_at_zero_is_consumed_correctly() {
3637 let ring = make_ring(2);
3638 let mut producer = make_producer(&ring);
3639 let mut consumer = make_consumer(&ring);
3640
3641 producer.submit_one(0x1000, 16, false).unwrap();
3642 producer.submit_one(0x2000, 16, false).unwrap();
3643
3644 assert_eq!(producer.avail_cursor().head(), 0);
3645 assert!(!producer.avail_cursor().wrap());
3646
3647 assert_eq!(consumer.poll_available().unwrap().1.elems()[0].addr, 0x1000);
3648 assert_eq!(consumer.poll_available().unwrap().1.elems()[0].addr, 0x2000);
3649 assert_eq!(consumer.avail_cursor().head(), 0);
3650 assert!(!consumer.avail_cursor().wrap());
3651 }
3652
3653 #[test]
3654 fn p0016_queue_size_one_next_chain_is_rejected() {
3655 let ring = make_ring(1);
3656 let mut consumer = make_consumer(&ring);
3657
3658 write_avail(&ring, 0, 0, DescFlags::NEXT);
3659
3660 assert!(matches!(
3661 consumer.poll_available(),
3662 Err(RingError::BadChain)
3663 ));
3664 }
3665
3666 #[test]
3667 fn p0017_stale_driver_event_wrap_suppresses_notification() {
3668 let ring = make_ring(8);
3669 let mut consumer = make_consumer(&ring);
3670
3671 write_driver_event(&ring, 0, EventFlags::DESC.bits());
3672 write_avail(&ring, 0, 0, DescFlags::empty());
3673
3674 let (id, _) = consumer.poll_available().unwrap();
3675
3676 assert!(!consumer.submit_used_with_notify(id, 0).unwrap());
3677 }
3678
3679 #[test]
3680 fn p0018_pre_used_descriptor_is_ignored() {
3681 let ring = make_ring(8);
3682 let mut consumer = make_consumer(&ring);
3683
3684 let mut desc = raw_desc(0, 16, DescFlags::empty());
3685 desc.mark_used(true);
3686 ring.write_desc(0, desc);
3687
3688 assert!(matches!(
3689 consumer.poll_available(),
3690 Err(RingError::WouldBlock)
3691 ));
3692 }
3693
3694 #[test]
3695 fn p0019_driver_event_wrap_mismatch_suppresses_notification() {
3696 let ring = make_ring(8);
3697 let mut consumer = make_consumer(&ring);
3698
3699 write_driver_event(&ring, 1, EventFlags::DESC.bits());
3700 write_avail(&ring, 0, 0, DescFlags::empty());
3701
3702 let (id, _) = consumer.poll_available().unwrap();
3703
3704 assert!(!consumer.submit_used_with_notify(id, 0).unwrap());
3705 }
3706
3707 #[test]
3708 fn p0020_ring_full_reports_backpressure() {
3709 let ring = make_ring(4);
3710 let mut producer = make_producer(&ring);
3711
3712 for idx in 0..4 {
3713 producer.submit_one(0x1000 + idx * 0x10, 16, false).unwrap();
3714 }
3715
3716 assert!(matches!(
3717 producer.submit_one(0x2000, 16, false),
3718 Err(RingError::WouldBlock)
3719 ));
3720 }
3721
3722 #[test]
3723 fn p0022_indirect_reused_id_is_rejected_before_id_reuse() {
3724 let ring = make_ring(8);
3725 let mut consumer = make_consumer(&ring);
3726
3727 write_avail(&ring, 0, 0, DescFlags::INDIRECT);
3728 write_avail(&ring, 1, 0, DescFlags::empty());
3729
3730 assert!(matches!(
3731 consumer.poll_available(),
3732 Err(RingError::BadChain)
3733 ));
3734 }
3735
3736 #[test]
3737 fn p0023_desc_event_mode_suppresses_before_later_slot() {
3738 let ring = make_ring(8);
3739 let mut consumer = make_consumer(&ring);
3740
3741 write_driver_event(&ring, 0x8001, EventFlags::DESC.bits());
3742 write_avail(&ring, 0, 0, DescFlags::empty());
3743
3744 let (id, _) = consumer.poll_available().unwrap();
3745
3746 assert!(!consumer.submit_used_with_notify(id, 0).unwrap());
3747 }
3748
3749 #[test]
3750 fn p0024_single_slot_indirect_is_rejected() {
3751 let ring = make_ring(1);
3752 let mut consumer = make_consumer(&ring);
3753
3754 write_avail(&ring, 0, 0, DescFlags::INDIRECT);
3755
3756 assert!(matches!(
3757 consumer.poll_available(),
3758 Err(RingError::BadChain)
3759 ));
3760 }
3761
3762 #[test]
3763 fn p0025_used_completions_can_arrive_out_of_order() {
3764 let ring = make_ring(8);
3765 let mut producer = make_producer(&ring);
3766 let mut consumer = make_consumer(&ring);
3767
3768 let id0 = producer.submit_one(0x1000, 16, true).unwrap();
3769 let id1 = producer.submit_one(0x2000, 16, true).unwrap();
3770 let id2 = producer.submit_one(0x3000, 16, true).unwrap();
3771
3772 let (dev0, _) = consumer.poll_available().unwrap();
3773 let (dev1, _) = consumer.poll_available().unwrap();
3774 let (dev2, _) = consumer.poll_available().unwrap();
3775
3776 consumer.submit_used(dev2, 32).unwrap();
3777 consumer.submit_used(dev0, 16).unwrap();
3778 consumer.submit_used(dev1, 24).unwrap();
3779
3780 assert_eq!(producer.poll_used().unwrap().id, id2);
3781 assert_eq!(producer.poll_used().unwrap().id, id0);
3782 assert_eq!(producer.poll_used().unwrap().id, id1);
3783 }
3784
3785 #[test]
3786 fn p0026_all_descriptor_flags_set_is_not_available() {
3787 let ring = make_ring(8);
3788 let mut consumer = make_consumer(&ring);
3789
3790 ring.write_desc(0, raw_desc(0, 16, DescFlags::from_bits_truncate(u16::MAX)));
3791
3792 assert!(matches!(
3793 consumer.poll_available(),
3794 Err(RingError::WouldBlock)
3795 ));
3796 }
3797
3798 #[test]
3799 fn p0028_multi_wrap_round_trip_remains_ordered() {
3800 let ring = make_ring(2);
3801 let mut producer = make_producer(&ring);
3802 let mut consumer = make_consumer(&ring);
3803
3804 for idx in 0..8u64 {
3805 let id = producer.submit_one(0x1000 + idx * 0x10, 16, false).unwrap();
3806 let (dev_id, _) = consumer.poll_available().unwrap();
3807 assert_eq!(dev_id, id);
3808 consumer.submit_used(dev_id, idx as u32).unwrap();
3809 assert_eq!(producer.poll_used().unwrap().id, id);
3810 }
3811 }
3812
3813 #[test]
3814 fn p0029_desc_event_idx_zero_notifies() {
3815 let ring = make_ring(8);
3816 let mut consumer = make_consumer(&ring);
3817
3818 write_driver_event(&ring, 0x8000, EventFlags::DESC.bits());
3819 write_avail(&ring, 0, 0, DescFlags::empty());
3820
3821 let (id, _) = consumer.poll_available().unwrap();
3822
3823 assert!(consumer.submit_used_with_notify(id, 0).unwrap());
3824 }
3825
3826 #[test]
3827 fn p0031_reserved_driver_event_flags_suppress_notification() {
3828 let ring = make_ring(8);
3829 let mut consumer = make_consumer(&ring);
3830
3831 write_driver_event(&ring, 0, 3);
3832 write_avail(&ring, 0, 0, DescFlags::empty());
3833
3834 let (id, _) = consumer.poll_available().unwrap();
3835
3836 assert!(!consumer.submit_used_with_notify(id, 0).unwrap());
3837 }
3838
3839 #[test]
3840 fn p0032_unaligned_indirect_descriptor_is_rejected() {
3841 let ring = make_ring(8);
3842 let mut consumer = make_consumer(&ring);
3843
3844 let mut desc = Descriptor::new(0x1003, 16, 0, DescFlags::INDIRECT);
3845 desc.mark_avail(true);
3846 ring.write_desc(0, desc);
3847
3848 assert!(matches!(
3849 consumer.poll_available(),
3850 Err(RingError::BadChain)
3851 ));
3852 }
3853
3854 #[test]
3855 fn p0033_scatter_gather_chain_is_preserved() {
3856 let ring = make_ring(16);
3857 let mut consumer = make_consumer(&ring);
3858
3859 for idx in 0..8u16 {
3860 let flags = if idx == 7 {
3861 DescFlags::WRITE
3862 } else {
3863 DescFlags::NEXT
3864 };
3865 write_avail(&ring, idx, 0, flags);
3866 }
3867
3868 let (_, chain) = consumer.poll_available().unwrap();
3869 assert_eq!(chain.len(), 8);
3870 assert_eq!(chain.readables().len(), 7);
3871 assert_eq!(chain.writables().len(), 1);
3872 }
3873
3874 #[test]
3875 fn p0034_page_boundary_indirect_descriptor_is_rejected() {
3876 let ring = make_ring(8);
3877 let mut consumer = make_consumer(&ring);
3878
3879 let mut desc = Descriptor::new(0x1ff0, 16, 0, DescFlags::INDIRECT);
3880 desc.mark_avail(true);
3881 ring.write_desc(0, desc);
3882
3883 assert!(matches!(
3884 consumer.poll_available(),
3885 Err(RingError::BadChain)
3886 ));
3887 }
3888
3889 #[test]
3890 fn p0035_both_avail_and_used_clear_is_ignored() {
3891 let ring = make_ring(8);
3892 let mut consumer = make_consumer(&ring);
3893
3894 ring.write_desc(0, raw_desc(0, 16, DescFlags::empty()));
3895
3896 assert!(matches!(
3897 consumer.poll_available(),
3898 Err(RingError::WouldBlock)
3899 ));
3900 }
3901
3902 #[test]
3903 fn p0037_event_flags_can_cycle_between_batches() {
3904 let ring = make_ring(8);
3905 let mut consumer = make_consumer(&ring);
3906
3907 for (idx, (flags, expect_notify)) in [
3908 (EventFlags::ENABLE.bits(), true),
3909 (EventFlags::DISABLE.bits(), false),
3910 (EventFlags::ENABLE.bits(), true),
3911 ]
3912 .into_iter()
3913 .enumerate()
3914 {
3915 write_driver_event(&ring, 0, flags);
3916 write_avail(&ring, idx as u16, idx as u16, DescFlags::empty());
3917 let (id, _) = consumer.poll_available().unwrap();
3918 assert_eq!(
3919 consumer.submit_used_with_notify(id, 0).unwrap(),
3920 expect_notify
3921 );
3922 }
3923 }
3924
3925 #[test]
3926 fn p0038_many_wraps_on_minimum_queue_size() {
3927 let ring = make_ring(1);
3928 let mut producer = make_producer(&ring);
3929 let mut consumer = make_consumer(&ring);
3930
3931 for idx in 0..8u64 {
3932 let id = producer.submit_one(0x1000 + idx * 0x10, 16, false).unwrap();
3933 let (dev_id, _) = consumer.poll_available().unwrap();
3934 assert_eq!(dev_id, id);
3935 consumer.submit_used(dev_id, 0).unwrap();
3936 assert_eq!(producer.poll_used().unwrap().id, id);
3937 }
3938 }
3939
3940 #[test]
3941 fn p0039_reserved_device_event_flags_suppress_avail_notification() {
3942 let ring = make_ring(8);
3943 let mut producer = make_producer(&ring);
3944
3945 write_device_event(&ring, 0, 3);
3946
3947 assert!(
3948 !producer
3949 .submit_one_with_notify(0x1000, 16, false)
3950 .unwrap()
3951 .notify
3952 );
3953 }
3954
3955 #[test]
3956 fn p0040_indirect_with_next_is_rejected() {
3957 let ring = make_ring(8);
3958 let mut consumer = make_consumer(&ring);
3959
3960 write_avail(&ring, 0, 0, DescFlags::INDIRECT | DescFlags::NEXT);
3961
3962 assert!(matches!(
3963 consumer.poll_available(),
3964 Err(RingError::BadChain)
3965 ));
3966 }
3967
3968 #[test]
3969 fn p0041_driver_event_offset_at_queue_size_suppresses_notification() {
3970 let ring = make_ring(8);
3971 let mut consumer = make_consumer(&ring);
3972
3973 write_driver_event(&ring, ring.len() as u16, EventFlags::DESC.bits());
3974 write_avail(&ring, 0, 0, DescFlags::empty());
3975
3976 let (id, _) = consumer.poll_available().unwrap();
3977
3978 assert!(!consumer.submit_used_with_notify(id, 0).unwrap());
3979 }
3980
3981 #[test]
3982 fn p0042_empty_ring_has_no_available_work() {
3983 let ring = make_ring(8);
3984 let mut consumer = make_consumer(&ring);
3985
3986 assert!(matches!(
3987 consumer.poll_available(),
3988 Err(RingError::WouldBlock)
3989 ));
3990 }
3991
3992 #[test]
3993 fn p0043_id_equal_to_queue_size_is_rejected() {
3994 let ring = make_ring(8);
3995 let mut consumer = make_consumer(&ring);
3996
3997 write_avail(&ring, 0, ring.len() as u16, DescFlags::empty());
3998
3999 assert!(matches!(
4000 consumer.poll_available(),
4001 Err(RingError::InvalidState)
4002 ));
4003 }
4004
4005 #[test]
4006 fn p0044_avail_and_used_set_is_not_available() {
4007 let ring = make_ring(8);
4008 let mut consumer = make_consumer(&ring);
4009
4010 ring.write_desc(0, raw_desc(0, 16, DescFlags::AVAIL | DescFlags::USED));
4011
4012 assert!(!consumer.peek_available().unwrap());
4013 assert!(matches!(
4014 consumer.poll_available(),
4015 Err(RingError::WouldBlock)
4016 ));
4017 }
4018
4019 #[test]
4020 fn p0045_zero_length_descriptor_is_consumable() {
4021 let ring = make_ring(8);
4022 let mut consumer = make_consumer(&ring);
4023
4024 write_avail_len(&ring, 0, 0, 0, DescFlags::WRITE);
4025
4026 let (id, chain) = consumer.poll_available().unwrap();
4027 assert_eq!(id, 0);
4028 assert_eq!(chain.writables()[0].len, 0);
4029 }
4030
4031 #[test]
4032 fn p0046_max_length_descriptor_is_consumable_at_ring_layer() {
4033 let ring = make_ring(8);
4034 let mut consumer = make_consumer(&ring);
4035
4036 write_avail_len(&ring, 0, 0, u32::MAX, DescFlags::WRITE);
4037
4038 let (id, chain) = consumer.poll_available().unwrap();
4039 assert_eq!(id, 0);
4040 assert_eq!(chain.writables()[0].len, u32::MAX);
4041 }
4042
4043 #[test]
4044 fn p0047_zero_descriptor_address_is_preserved_at_ring_layer() {
4045 let ring = make_ring(8);
4046 let mut consumer = make_consumer(&ring);
4047
4048 let mut desc = Descriptor::new(0, 16, 0, DescFlags::WRITE);
4049 desc.mark_avail(true);
4050 ring.write_desc(0, desc);
4051
4052 let (id, chain) = consumer.poll_available().unwrap();
4053 assert_eq!(id, 0);
4054 assert_eq!(chain.writables()[0].addr, 0);
4055 }
4056
4057 #[test]
4058 fn p0049_indirect_entry_with_phase_bits_is_rejected() {
4059 let ring = make_ring(8);
4060 let mut consumer = make_consumer(&ring);
4061
4062 ring.write_desc(
4063 0,
4064 raw_desc(
4065 0,
4066 16,
4067 DescFlags::INDIRECT | DescFlags::AVAIL | DescFlags::USED,
4068 ),
4069 );
4070
4071 assert!(matches!(
4072 consumer.poll_available(),
4073 Err(RingError::WouldBlock)
4074 ));
4075 }
4076
4077 #[test]
4078 fn p0050_nested_indirect_is_rejected_at_head() {
4079 let ring = make_ring(8);
4080 let mut consumer = make_consumer(&ring);
4081
4082 write_avail(&ring, 0, 0, DescFlags::INDIRECT);
4083
4084 assert!(matches!(
4085 consumer.poll_available(),
4086 Err(RingError::BadChain)
4087 ));
4088 }
4089
4090 #[test]
4091 fn p0051_write_flag_controls_readable_writable_split() {
4092 let ring = make_ring(8);
4093 let mut consumer = make_consumer(&ring);
4094
4095 write_avail(&ring, 0, 0, DescFlags::NEXT);
4096 write_avail(&ring, 1, 0, DescFlags::WRITE);
4097
4098 let (_, chain) = consumer.poll_available().unwrap();
4099 assert_eq!(chain.readables().len(), 1);
4100 assert_eq!(chain.writables().len(), 1);
4101 }
4102
4103 #[test]
4104 fn p0052_batch_completion_signals_each_chain_head() {
4105 let ring = make_ring(8);
4106 let mut producer = make_producer(&ring);
4107 let mut consumer = make_consumer(&ring);
4108
4109 let id0 = producer.submit_one(0x1000, 16, true).unwrap();
4110 let id1 = producer.submit_one(0x2000, 16, true).unwrap();
4111
4112 let (dev0, _) = consumer.poll_available().unwrap();
4113 let (dev1, _) = consumer.poll_available().unwrap();
4114 consumer.submit_used(dev0, 16).unwrap();
4115 consumer.submit_used(dev1, 32).unwrap();
4116
4117 assert_eq!(producer.poll_used().unwrap().id, id0);
4118 assert_eq!(producer.poll_used().unwrap().id, id1);
4119 }
4120
4121 #[test]
4122 fn p0053_descriptor_without_avail_bit_is_ignored() {
4123 let ring = make_ring(8);
4124 let mut consumer = make_consumer(&ring);
4125
4126 ring.write_desc(0, raw_desc(0, 16, DescFlags::WRITE));
4127
4128 assert!(!consumer.peek_available().unwrap());
4129 assert!(matches!(
4130 consumer.poll_available(),
4131 Err(RingError::WouldBlock)
4132 ));
4133 }
4134
4135 #[test]
4136 fn p0054_event_suppression_struct_layout_matches_packed_ring() {
4137 assert_eq!(EventSuppression::SIZE, 4);
4138 assert_eq!(EventSuppression::WRAP_OFFSET, 0);
4139 assert_eq!(EventSuppression::FLAGS_OFFSET, 2);
4140 }
4141
4142 #[test]
4143 fn p0055_descriptor_after_chain_tail_is_ignored() {
4144 let ring = make_ring(8);
4145 let mut consumer = make_consumer(&ring);
4146
4147 write_avail(&ring, 0, 0, DescFlags::empty());
4148 write_avail(&ring, 1, 1, DescFlags::WRITE);
4149
4150 let (id, chain) = consumer.poll_available().unwrap();
4151 assert_eq!(id, 0);
4152 assert_eq!(chain.len(), 1);
4153 }
4154
4155 #[test]
4156 fn p0056_next_chain_order_is_preserved() {
4157 let ring = make_ring(8);
4158 let mut consumer = make_consumer(&ring);
4159
4160 for idx in 0..3u16 {
4161 let mut desc = Descriptor::new(
4162 0x1000 + u64::from(idx) * 0x100,
4163 16,
4164 0,
4165 if idx == 2 {
4166 DescFlags::WRITE
4167 } else {
4168 DescFlags::NEXT
4169 },
4170 );
4171 desc.mark_avail(true);
4172 ring.write_desc(idx, desc);
4173 }
4174
4175 let (_, chain) = consumer.poll_available().unwrap();
4176 assert_eq!(chain.elems()[0].addr, 0x1000);
4177 assert_eq!(chain.elems()[1].addr, 0x1100);
4178 assert_eq!(chain.elems()[2].addr, 0x1200);
4179 }
4180
4181 #[test]
4182 fn p0057_device_event_enable_requests_avail_notification() {
4183 let ring = make_ring(8);
4184 let mut producer = make_producer(&ring);
4185
4186 write_device_event(&ring, 0, EventFlags::ENABLE.bits());
4187
4188 assert!(
4189 producer
4190 .submit_one_with_notify(0x1000, 16, false)
4191 .unwrap()
4192 .notify
4193 );
4194 }
4195
4196 #[test]
4197 fn p0058_used_descriptor_carries_id_and_len() {
4198 let ring = make_ring(8);
4199 let mut producer = make_producer(&ring);
4200 let mut consumer = make_consumer(&ring);
4201
4202 let id = producer.submit_one(0x1000, 16, true).unwrap();
4203 let (dev_id, _) = consumer.poll_available().unwrap();
4204 consumer.submit_used(dev_id, 42).unwrap();
4205
4206 let used = producer.poll_used().unwrap();
4207 assert_eq!(used.id, id);
4208 assert_eq!(used.len, 42);
4209 }
4210}
4211
4212#[cfg(test)]
4213mod fuzz {
4214 use quickcheck::{Arbitrary, Gen, QuickCheck};
4215
4216 use super::tests::{OwnedRing, make_consumer, make_producer};
4217 use super::*;
4218
4219 const MAX_RING: usize = 64;
4220 const MAX_OPS: usize = 128;
4221 const MAX_CHAIN_LEN: usize = 8;
4222
4223 #[allow(clippy::large_enum_variant)]
4224 #[derive(Clone, Debug)]
4225 enum Op {
4226 Submit(BufferChain),
4228 PollAvail(u8),
4230 PollUsed(u8),
4232 CompleteOne,
4234 }
4235
4236 impl Arbitrary for Op {
4237 fn arbitrary(g: &mut Gen) -> Self {
4238 let choice = u8::arbitrary(g) % 4;
4239 match choice {
4240 0 => Op::Submit(BufferChain::arbitrary(g)),
4241 1 => Op::PollAvail(u8::arbitrary(g) % 8 + 1),
4242 2 => Op::PollUsed(u8::arbitrary(g) % 8 + 1),
4243 3 => Op::CompleteOne,
4244 _ => unreachable!(),
4245 }
4246 }
4247 }
4248
4249 #[derive(Clone, Debug)]
4250 struct Scenario {
4251 table_size: usize,
4252 ops: Vec<Op>,
4253 }
4254
4255 impl Arbitrary for Scenario {
4256 fn arbitrary(g: &mut Gen) -> Self {
4257 let table_size = (usize::arbitrary(g) % MAX_RING + 1).next_power_of_two();
4258 let num_ops = usize::arbitrary(g) % MAX_OPS + 1;
4259
4260 let ops = (0..num_ops).map(|_| Op::arbitrary(g)).collect();
4261 Scenario { table_size, ops }
4262 }
4263 }
4264
4265 impl Arbitrary for BufferElement {
4266 fn arbitrary(g: &mut Gen) -> Self {
4267 let addr = u64::arbitrary(g);
4268 let len = u32::arbitrary(g);
4269 let writable = bool::arbitrary(g);
4270
4271 BufferElement {
4272 addr,
4273 len,
4274 writable,
4275 }
4276 }
4277 }
4278
4279 impl Arbitrary for BufferChain {
4280 fn arbitrary(g: &mut Gen) -> Self {
4281 let chain_len = usize::arbitrary(g) % MAX_CHAIN_LEN + 1;
4282
4283 let mut elems = vec![BufferElement::zeroed(); chain_len];
4284 let mut readables = 0;
4285 let mut writables = 0;
4286
4287 for _ in 0..chain_len {
4288 let elem = BufferElement::arbitrary(g);
4289 if elem.writable {
4290 elems[chain_len - 1 - writables] = elem;
4291 writables += 1;
4292 } else {
4293 elems[readables] = elem;
4294 readables += 1;
4295 }
4296 }
4297
4298 BufferChain {
4299 elems: elems.into(),
4300 split: readables,
4301 }
4302 }
4303 }
4304
4305 fn run_scenario(s: Scenario) -> bool {
4306 let ring = OwnedRing::new(s.table_size);
4307 let mut producer = make_producer(&ring);
4308 let mut consumer = make_consumer(&ring);
4309
4310 let mut dev_order: Vec<u16> = Vec::new();
4312 let mut drv_order: Vec<u16> = Vec::new();
4313
4314 let mut dev_ready: Vec<(u16, u32)> = Vec::new();
4316
4317 for op in &s.ops {
4318 match op {
4319 Op::Submit(chain) => {
4320 let _ = producer.submit_available(chain);
4322 }
4323 Op::PollAvail(n) => {
4324 for _ in 0..*n {
4325 if let Ok((id, chain)) = consumer.poll_available() {
4326 dev_ready.push((id, chain.len() as u32));
4327 } else {
4328 break;
4329 }
4330 }
4331 }
4332 Op::PollUsed(n) => {
4333 for _ in 0..*n {
4334 match producer.poll_used() {
4335 Ok(u) => {
4336 drv_order.push(u.id);
4337 if producer.id_num[u.id as usize] != 0 {
4338 return false;
4339 }
4340 if !producer.id_free.contains(&u.id) {
4341 return false;
4342 }
4343 }
4344 Err(RingError::WouldBlock) => break,
4345 Err(_) => return false,
4346 }
4347 }
4348 }
4349 Op::CompleteOne => {
4350 if let Some((id, len)) = dev_ready.pop() {
4351 if consumer.submit_used(id, len).is_err() {
4352 return false;
4353 }
4354
4355 dev_order.push(id);
4356 }
4357 }
4358 }
4359
4360 let outstanding: u16 = producer.id_num.iter().copied().sum();
4362 if outstanding as usize + producer.num_free != ring.len() {
4363 return false;
4364 }
4365
4366 for id in producer.id_free.iter() {
4367 if producer.id_num[*id as usize] != 0 {
4368 return false;
4369 }
4370 }
4371 }
4372
4373 while let Some((id, len)) = dev_ready.pop() {
4375 if consumer.submit_used(id, len).is_err() {
4376 return false;
4377 }
4378 }
4379
4380 loop {
4381 match producer.poll_used() {
4382 Ok(u) => drv_order.push(u.id),
4383 Err(RingError::WouldBlock) => break,
4384 Err(_) => return false,
4385 }
4386 }
4387
4388 true
4389 }
4390
4391 #[test]
4392 fn prop_interleaved_with_order_verification() {
4393 #[cfg(miri)]
4394 let tests = 1;
4395 #[cfg(not(miri))]
4396 let tests = 100;
4397
4398 QuickCheck::new()
4399 .tests(tests)
4400 .quickcheck(run_scenario as fn(Scenario) -> bool);
4401 }
4402}