1use alloc::collections::VecDeque;
18use alloc::vec::Vec;
19
20use bytes::Bytes;
21use smallvec::SmallVec;
22
23use super::*;
24
25#[derive(Debug)]
33pub enum UsedChain {
34 Ack(Token),
36 Data(Token, Segments),
42}
43
44impl UsedChain {
45 pub fn token(&self) -> Token {
47 match self {
48 Self::Ack(token) | Self::Data(token, _) => *token,
49 }
50 }
51
52 pub fn to_bytes(&self) -> Option<Bytes> {
54 match self {
55 Self::Ack(_) => None,
56 Self::Data(_, segments) => Some(segments.to_bytes()),
57 }
58 }
59
60 pub fn segments(&self) -> Option<&Segments> {
62 match self {
63 Self::Ack(_) => None,
64 Self::Data(_, segments) => Some(segments),
65 }
66 }
67
68 pub fn into_bytes(self) -> Option<Bytes> {
70 match self {
71 Self::Ack(_) => None,
72 Self::Data(_, segments) => Some(segments.into_bytes()),
73 }
74 }
75
76 pub fn into_segments(self) -> Option<Segments> {
78 match self {
79 Self::Ack(_) => None,
80 Self::Data(_, segments) => Some(segments),
81 }
82 }
83}
84
85#[derive(Debug)]
91pub(crate) struct Inflight {
92 token: Token,
93 chain: BufferChain,
94}
95
96pub struct VirtqProducer<M, N, P> {
129 inner: RingProducer<M>,
130 notifier: N,
131 pool: P,
132 next_token: u32,
133 inflight: Vec<Option<Inflight>>,
134 pending: VecDeque<UsedChain>,
135}
136
137impl<M, N, P> VirtqProducer<M, N, P>
138where
139 M: MemOps + Clone,
140 N: Notifier,
141 P: BufferProvider + Clone,
142{
143 pub fn new(layout: Layout, mem: M, notifier: N, pool: P) -> Self {
152 let inner = RingProducer::new(layout, mem);
153 let ring_len = inner.len();
154
155 Self {
156 inner,
157 pool,
158 notifier,
159 next_token: 0,
160 inflight: (0..ring_len).map(|_| None).collect(),
161 pending: VecDeque::with_capacity(ring_len),
162 }
163 }
164
165 fn dealloc_elems(
166 &self,
167 elems: impl IntoIterator<Item = BufferElement>,
168 ) -> Result<(), VirtqError> {
169 let mut first_err = None;
170 for elem in elems {
171 if let Err(err) = self.pool.dealloc(elem.addr)
172 && first_err.is_none()
173 {
174 first_err = Some(VirtqError::Alloc(err));
175 }
176 }
177
178 if let Some(err) = first_err {
179 return Err(err);
180 }
181
182 Ok(())
183 }
184
185 pub fn chain(&self) -> ChainBuilder<M, P> {
189 ChainBuilder::new(self.inner.mem().clone(), self.pool.clone())
190 }
191
192 pub fn batch(&mut self) -> SubmitBatch<'_, M, N, P> {
199 SubmitBatch::new(self)
200 }
201
202 pub fn submit(&mut self, chain: SendChain<M, P>) -> Result<Token, VirtqError> {
215 let cursor_before = self.inner.avail_cursor();
216 let token = self.publish(chain)?;
217 self.notify_since(cursor_before)?;
218 Ok(token)
219 }
220
221 fn publish(&mut self, send: SendChain<M, P>) -> Result<Token, VirtqError> {
222 let token_id = self.next_token;
223 let id = self.inner.submit_available(send.chain())?;
224 let token = Token { seq: token_id, id };
225
226 if self.inflight[id as usize].is_some() {
228 return Err(VirtqError::InvalidState);
229 }
230
231 let inf = send.into_inflight(token);
232 self.inflight[id as usize] = Some(inf);
233 self.next_token = self.next_token.wrapping_add(1);
234
235 Ok(token)
236 }
237
238 fn notify_since(&mut self, cursor: RingCursor) -> Result<bool, VirtqError> {
239 let should_notify = self.inner.should_notify_since(cursor)?;
240 if should_notify {
241 self.notify_now();
242 }
243 Ok(should_notify)
244 }
245
246 fn notify_now(&self) {
247 self.notifier.notify(QueueStats {
248 num_free: self.inner.num_free(),
249 num_inflight: self.inner.num_inflight(),
250 });
251 }
252
253 #[inline]
258 pub fn notify_backpressure(&self) {
259 self.notify_now();
260 }
261
262 #[inline]
266 pub fn used_cursor(&self) -> RingCursor {
267 self.inner.used_cursor()
268 }
269
270 #[inline]
272 pub fn num_free(&self) -> usize {
273 self.inner.num_free()
274 }
275
276 pub fn set_used_suppression(&mut self, kind: SuppressionKind) -> Result<(), VirtqError> {
296 match kind {
297 SuppressionKind::Enable => self.inner.enable_used_notifications()?,
298 SuppressionKind::Disable => self.inner.disable_used_notifications()?,
299 SuppressionKind::Descriptor(cursor) => self
300 .inner
301 .enable_used_notifications_desc(cursor.head(), cursor.wrap())?,
302 }
303 Ok(())
304 }
305
306 pub unsafe fn reset(&mut self) {
317 self.inflight.iter_mut().for_each(|slot| *slot = None);
318 self.pending.clear();
319 self.inner.reset();
320 self.pool.reset();
321 }
322
323 pub unsafe fn reset_with_pool(&mut self, pool: P) {
332 self.pending.clear();
333 self.inflight.iter_mut().for_each(|slot| *slot = None);
334 self.inner.reset();
335 self.pool = pool;
336 self.pool.reset();
337 }
338}
339
340impl<M, N, P> VirtqProducer<M, N, P>
341where
342 M: MemOps + Clone + Send + 'static,
343 N: Notifier,
344 P: BufferProvider + Clone + Send + 'static,
345{
346 pub fn poll(&mut self) -> Result<Option<UsedChain>, VirtqError> {
364 if let Some(chain) = self.pending.pop_front() {
365 return Ok(Some(chain));
366 }
367 self.poll_ring()
368 }
369
370 pub fn reclaim(&mut self) -> Result<usize, VirtqError> {
381 let mut count = 0;
382 while let Some(chain) = self.poll_ring()? {
383 if matches!(chain, UsedChain::Data(_, _)) {
384 debug_assert!(self.pending.len() < self.inner.len());
385 self.pending.push_back(chain);
386 }
387 count += 1;
388 }
389 Ok(count)
390 }
391
392 fn poll_ring(&mut self) -> Result<Option<UsedChain>, VirtqError> {
394 let used = match self.inner.poll_used() {
395 Ok(u) => u,
396 Err(RingError::WouldBlock) => return Ok(None),
397 Err(e) => return Err(e.into()),
398 };
399
400 let inf = self
401 .inflight
402 .get_mut(used.id as usize)
403 .and_then(Option::take)
404 .ok_or(VirtqError::InvalidState)?;
405
406 let written = used.len as usize;
407 let Inflight { token, chain } = inf;
408
409 self.dealloc_elems(chain.readables().iter().copied())?;
410
411 let used = if chain.writables().is_empty() {
412 UsedChain::Ack(token)
413 } else {
414 UsedChain::Data(token, self.recv_segments(chain.writables(), written)?)
415 };
416
417 Ok(Some(used))
418 }
419
420 fn recv_segments(
421 &self,
422 writables: &[BufferElement],
423 written: usize,
424 ) -> Result<Segments, VirtqError> {
425 let mut owned = SmallVec::<[(BufferElement, usize); 4]>::new();
426 let mut free = SmallVec::<[BufferElement; 4]>::new();
427 let mut remaining = written;
428
429 for &alloc in writables {
430 if remaining == 0 {
431 free.push(alloc);
432 continue;
433 }
434
435 let len = remaining.min(alloc.len as usize);
436 owned.push((alloc, len));
437 remaining -= len;
438 }
439
440 if remaining != 0 {
441 let elems = owned.iter().map(|(elem, _)| *elem).chain(free);
442 self.dealloc_elems(elems)?;
443 return Err(VirtqError::InvalidState);
444 }
445
446 for (elem, len) in &owned {
447 if unsafe { self.inner.mem().as_slice(elem.addr, *len) }.is_err() {
448 let elems = owned.iter().map(|(elem, _)| *elem).chain(free);
449 let _ = self.dealloc_elems(elems);
450 return Err(VirtqError::MemoryReadError);
451 }
452 }
453
454 let mut sgs = SmallVec::<[Bytes; 4]>::new();
455 for (elem, written) in owned {
456 let alloc = OwnedAlloc::new(
457 self.pool.clone(),
458 Allocation {
459 addr: elem.addr,
460 len: elem.len as usize,
461 },
462 );
463 let mem = self.inner.mem().clone();
464 let owner = BufferOwner {
465 alloc,
466 mem,
467 written,
468 };
469 sgs.push(Bytes::from_owner(owner));
470 }
471
472 self.dealloc_elems(free)?;
473
474 Ok(Segments::from_smallvec(sgs))
475 }
476
477 pub fn drain(&mut self, mut f: impl FnMut(UsedChain)) -> Result<(), VirtqError> {
494 while let Some(chain) = self.poll()? {
495 f(chain);
496 }
497
498 Ok(())
499 }
500}
501
502#[must_use = "call finish to notify the consumer about batched submissions"]
508pub struct SubmitBatch<'a, M, N, P> {
509 producer: &'a mut VirtqProducer<M, N, P>,
510 notify_from: Option<RingCursor>,
511}
512
513impl<'a, M, N, P> SubmitBatch<'a, M, N, P>
514where
515 M: MemOps + Clone,
516 N: Notifier,
517 P: BufferProvider + Clone,
518{
519 fn new(producer: &'a mut VirtqProducer<M, N, P>) -> Self {
520 Self {
521 producer,
522 notify_from: None,
523 }
524 }
525
526 pub fn chain(&self) -> ChainBuilder<M, P> {
528 self.producer.chain()
529 }
530
531 pub fn submit(&mut self, chain: SendChain<M, P>) -> Result<Token, VirtqError> {
533 let cursor_before = self.producer.inner.avail_cursor();
534 let token = self.producer.publish(chain)?;
535
536 if self.notify_from.is_none() {
537 self.notify_from = Some(cursor_before);
538 }
539 Ok(token)
540 }
541
542 pub fn finish(mut self) -> Result<bool, VirtqError> {
547 let Some(notify_from) = self.notify_from.take() else {
548 return Ok(false);
549 };
550
551 self.producer.notify_since(notify_from)
552 }
553}
554
555#[must_use = "call .build() to create a SendChain"]
560pub struct ChainBuilder<M: MemOps, P: BufferProvider + Clone> {
561 mem: M,
562 pool: P,
563 rd_caps: SmallVec<[usize; 4]>,
564 wr_caps: SmallVec<[usize; 4]>,
565}
566
567impl<M: MemOps, P: BufferProvider + Clone> ChainBuilder<M, P> {
568 fn new(mem: M, pool: P) -> Self {
569 Self {
570 mem,
571 pool,
572 rd_caps: SmallVec::new(),
573 wr_caps: SmallVec::new(),
574 }
575 }
576
577 pub fn readable(mut self, cap: usize) -> Self {
583 self.rd_caps.push(cap);
584 self
585 }
586
587 pub fn writable(mut self, cap: usize) -> Self {
596 self.wr_caps.push(cap);
597 self
598 }
599
600 pub fn build(self) -> Result<SendChain<M, P>, VirtqError> {
607 if self.rd_caps.is_empty() && self.wr_caps.is_empty() {
608 return Err(VirtqError::InvalidState);
609 }
610
611 let mut rollback = Rollback::new(&self.pool);
612 let mut rd_caps = SmallVec::<[usize; 4]>::new();
613 let mut rd_elems = SmallVec::<[BufferElement; 4]>::new();
614 let mut wr_elems = SmallVec::<[BufferElement; 4]>::new();
615
616 for &cap in &self.rd_caps {
620 let sgs = self.pool.alloc_sg(cap)?;
621 let mut remaining = cap;
622
623 for alloc in sgs {
624 let _ = checked_descriptor_len(alloc.len)?;
625 let seg_cap = remaining.min(alloc.len);
626
627 rd_caps.push(seg_cap);
628 rd_elems.push(BufferElement {
629 addr: alloc.addr,
630 len: 0,
631 writable: false,
632 });
633 remaining -= seg_cap;
634 rollback.allocs.push(alloc);
635 }
636
637 if remaining != 0 {
638 return Err(VirtqError::InvalidState);
639 }
640 }
641
642 for &cap in &self.wr_caps {
646 let sgs = self.pool.alloc_sg(cap)?;
647 for alloc in sgs {
648 let len = checked_descriptor_len(alloc.len)?;
649 wr_elems.push(BufferElement {
650 addr: alloc.addr,
651 len,
652 writable: true,
653 });
654 rollback.allocs.push(alloc);
655 }
656 }
657
658 let chain = BufferChainBuilder::new()
659 .readables(rd_elems)
660 .writables(wr_elems)
661 .build()?;
662
663 rollback.release();
664
665 Ok(SendChain {
666 mem: self.mem,
667 pool: self.pool,
668 chain: Some(chain),
669 rd_caps,
670 rd_capacity: self.rd_caps.iter().sum(),
671 rd_written: 0,
672 write_mode: WriteMode::Unset,
673 })
674 }
675}
676
677struct Rollback<'a, P: BufferProvider> {
678 pool: &'a P,
679 allocs: SmallVec<[Allocation; 8]>,
680}
681
682impl<'a, P: BufferProvider> Rollback<'a, P> {
683 fn new(pool: &'a P) -> Self {
684 Self {
685 pool,
686 allocs: SmallVec::new(),
687 }
688 }
689
690 fn release(mut self) {
691 self.allocs.clear();
692 }
693}
694
695impl<P: BufferProvider> Drop for Rollback<'_, P> {
696 fn drop(&mut self) {
697 for alloc in self.allocs.drain(..) {
698 let result = self.pool.dealloc(alloc.addr);
699 debug_assert!(result.is_ok(), "rollback dealloc failed: {result:?}");
700 }
701 }
702}
703
704#[derive(Debug, Clone, Copy, PartialEq, Eq)]
712enum WriteMode {
713 Unset,
714 Append,
715 Direct,
716}
717
718#[must_use = "dropping without submitting deallocates the buffers"]
740pub struct SendChain<M: MemOps, P: BufferProvider> {
741 mem: M,
742 pool: P,
743 chain: Option<BufferChain>,
744 rd_caps: SmallVec<[usize; 4]>,
745 rd_capacity: usize,
746 rd_written: usize,
747 write_mode: WriteMode,
748}
749
750#[allow(clippy::expect_used)]
754impl<M: MemOps, P: BufferProvider> SendChain<M, P> {
755 fn chain(&self) -> &BufferChain {
756 self.chain.as_ref().expect("SendChain missing BufferChain")
757 }
758
759 fn chain_mut(&mut self) -> &mut BufferChain {
760 self.chain.as_mut().expect("SendChain missing BufferChain")
761 }
762
763 fn note_write_mode(&mut self, mode: WriteMode) {
766 debug_assert!(
767 self.write_mode == WriteMode::Unset || self.write_mode == mode,
768 "SendChain mixes copy writes (write/write_all) with direct writes (write_seg/with_seg)"
769 );
770 self.write_mode = mode;
771 }
772
773 fn into_inflight(mut self, token: Token) -> Inflight {
774 let chain = self.chain.take().expect("SendChain missing BufferChain");
775 Inflight { token, chain }
776 }
777
778 pub fn segment_count(&self) -> usize {
780 self.chain().readables().len()
781 }
782
783 pub fn capacity(&self) -> usize {
785 self.rd_capacity
786 }
787
788 pub fn written(&self) -> usize {
790 self.rd_written
791 }
792
793 pub fn remaining(&self) -> usize {
795 self.capacity() - self.written()
796 }
797
798 pub fn write(&mut self, buf: &[u8]) -> Result<usize, VirtqError> {
810 if self.segment_count() == 0 {
811 return Err(VirtqError::NoPayloadSegment);
812 }
813
814 self.note_write_mode(WriteMode::Append);
815
816 let mut remaining = &buf[..buf.len().min(self.remaining())];
817 let mut written = 0;
818
819 let SendChain {
820 mem,
821 chain,
822 rd_caps,
823 ..
824 } = self;
825
826 let readables = chain
827 .as_mut()
828 .expect("SendChain missing BufferChain")
829 .readables_mut();
830
831 for (readable, &cap) in readables.iter_mut().zip(rd_caps.iter()) {
832 if remaining.is_empty() {
833 break;
834 }
835
836 let written_len = readable.len as usize;
837 let free = cap - written_len;
838 if free == 0 {
839 continue;
840 }
841
842 let n = free.min(remaining.len());
843 let addr = readable.addr + written_len as u64;
844 mem.write(addr, &remaining[..n])
845 .map_err(|_| VirtqError::MemoryWriteError)?;
846
847 readable.len += n as u32;
848 written += n;
849 remaining = &remaining[n..];
850 }
851
852 self.rd_written += written;
853 Ok(written)
854 }
855
856 pub fn write_all(&mut self, buf: &[u8]) -> Result<&mut Self, VirtqError> {
868 if self.segment_count() == 0 {
869 return Err(VirtqError::NoPayloadSegment);
870 }
871
872 if buf.len() > self.remaining() {
873 return Err(VirtqError::PayloadTooLarge {
874 recv: buf.len(),
875 limit: self.remaining(),
876 });
877 }
878
879 let written = self.write(buf)?;
880 debug_assert_eq!(written, buf.len());
881 Ok(self)
882 }
883
884 pub fn write_seg(&mut self, index: usize, buf: &[u8]) -> Result<&mut Self, VirtqError> {
895 self.note_write_mode(WriteMode::Direct);
896
897 let cap = *self
898 .rd_caps
899 .get(index)
900 .ok_or(VirtqError::NoPayloadSegment)?;
901
902 if buf.len() > cap {
903 return Err(VirtqError::PayloadTooLarge {
904 recv: buf.len(),
905 limit: cap,
906 });
907 }
908
909 let addr = self
910 .chain()
911 .readables()
912 .get(index)
913 .ok_or(VirtqError::NoPayloadSegment)?
914 .addr;
915
916 self.mem
917 .write(addr, buf)
918 .map_err(|_| VirtqError::MemoryWriteError)?;
919
920 let previous = self.chain().readables()[index].len as usize;
921 self.chain_mut().readables_mut()[index].len = checked_descriptor_len(buf.len())?;
922 self.rd_written = self.rd_written - previous + buf.len();
923 Ok(self)
924 }
925
926 pub fn with_seg<E>(
937 &mut self,
938 index: usize,
939 f: impl FnOnce(&mut [u8]) -> Result<usize, E>,
940 ) -> Result<&mut Self, E>
941 where
942 E: From<VirtqError>,
943 {
944 self.note_write_mode(WriteMode::Direct);
945
946 let cap = *self
947 .rd_caps
948 .get(index)
949 .ok_or_else(|| E::from(VirtqError::NoPayloadSegment))?;
950
951 let addr = self
952 .chain()
953 .readables()
954 .get(index)
955 .ok_or_else(|| E::from(VirtqError::NoPayloadSegment))?
956 .addr;
957
958 let buf = unsafe {
959 self.mem
960 .as_mut_slice(addr, cap)
961 .map_err(|_| E::from(VirtqError::MemoryWriteError))?
962 };
963
964 let written = f(buf)?;
965 if written > buf.len() {
966 return Err(E::from(VirtqError::PayloadTooLarge {
967 recv: written,
968 limit: buf.len(),
969 }));
970 }
971
972 let previous = self.chain().readables()[index].len as usize;
973 self.chain_mut().readables_mut()[index].len =
975 checked_descriptor_len(written).map_err(E::from)?;
976 self.rd_written = self.rd_written - previous + written;
977
978 Ok(self)
979 }
980}
981
982impl<M: MemOps, P: BufferProvider> Drop for SendChain<M, P> {
983 fn drop(&mut self) {
984 if let Some(chain) = self.chain.take() {
985 for elem in chain.elems() {
986 let result = self.pool.dealloc(elem.addr);
987 debug_assert!(result.is_ok(), "SendChain drop dealloc failed: {result:?}");
988 }
989 }
990 }
991}
992
993fn checked_descriptor_len(len: usize) -> Result<u32, VirtqError> {
994 if len > u32::MAX as usize {
995 return Err(VirtqError::PayloadTooLarge {
996 recv: len,
997 limit: u32::MAX as usize,
998 });
999 }
1000 Ok(len as u32)
1001}
1002
1003#[cfg(test)]
1004mod tests {
1005 use super::*;
1006 use crate::virtq::ring::tests::{TestMem, make_ring};
1007 use crate::virtq::test_utils::*;
1008
1009 fn poll_received<M: MemOps + Clone, N: Notifier>(
1010 consumer: &mut VirtqConsumer<M, N>,
1011 ) -> (RecvChain, ReplyChain<M>) {
1012 consumer.poll(1024).unwrap().unwrap()
1013 }
1014
1015 #[derive(Clone)]
1016 struct NoDirectSliceMem(TestMem);
1017
1018 unsafe impl MemOps for NoDirectSliceMem {
1021 type Error = ();
1022
1023 fn read(&self, addr: u64, dst: &mut [u8]) -> Result<(), Self::Error> {
1024 self.0.read(addr, dst).map_err(|e| match e {})
1025 }
1026
1027 fn write(&self, addr: u64, src: &[u8]) -> Result<(), Self::Error> {
1028 self.0.write(addr, src).map_err(|e| match e {})
1029 }
1030
1031 fn load_acquire(&self, addr: u64) -> Result<u16, Self::Error> {
1032 self.0.load_acquire(addr).map_err(|e| match e {})
1033 }
1034
1035 fn store_release(&self, addr: u64, val: u16) -> Result<(), Self::Error> {
1036 self.0.store_release(addr, val).map_err(|e| match e {})
1037 }
1038
1039 unsafe fn as_slice(&self, _addr: u64, _len: usize) -> Result<&[u8], Self::Error> {
1040 Err(())
1041 }
1042
1043 unsafe fn as_mut_slice(&self, _addr: u64, _len: usize) -> Result<&mut [u8], Self::Error> {
1044 Err(())
1045 }
1046 }
1047
1048 #[test]
1049 fn test_chain_readwrite_build() {
1050 let ring = make_ring(16);
1051 let (producer, _consumer, _notifier) = make_test_producer(&ring);
1052
1053 let se = producer.chain().readable(64).writable(128).build().unwrap();
1054 assert_eq!(se.capacity(), 64);
1055 assert_eq!(se.written(), 0);
1056 assert_eq!(se.remaining(), 64);
1057 }
1058
1059 #[test]
1060 fn test_chain_readable_writable_names_build() {
1061 let ring = make_ring(16);
1062 let (producer, _consumer, _notifier) = make_test_producer(&ring);
1063
1064 let se = producer.chain().readable(16).writable(32).build().unwrap();
1065 assert_eq!(se.segment_count(), 1);
1066 assert_eq!(se.capacity(), 16);
1067 }
1068
1069 #[test]
1070 fn test_chain_multi_readable_write_all_scatters() {
1071 let ring = make_ring(16);
1072 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1073
1074 let mut se = producer
1075 .chain()
1076 .readable(5)
1077 .readable(6)
1078 .writable(32)
1079 .build()
1080 .unwrap();
1081 se.write_all(b"hello world").unwrap();
1082
1083 assert_eq!(se.written(), 11);
1084
1085 let token = producer.submit(se).unwrap();
1086 let (recv, reply) = poll_received(&mut consumer);
1087 assert_eq!(recv.token(), token);
1088 assert_eq!(recv.to_bytes().as_ref(), b"hello world");
1089 assert_eq!(recv.segments().segment_count(), 2);
1090 assert_eq!(recv.segments().as_slice()[0].as_ref(), b"hello");
1091 assert_eq!(recv.segments().as_slice()[1].as_ref(), b" world");
1092 consumer.complete(reply).unwrap();
1093 }
1094
1095 #[test]
1096 fn test_chain_readable_splits_logical_capacity() {
1097 let ring = make_ring(16);
1098 let layout = ring.layout();
1099 let mem = ring.mem();
1100 let pool_base = mem.base_addr() + Layout::query_size(ring.len()) as u64 + 0x100;
1101 let pool = TestPool::new_with_max_alloc_len(pool_base, 0x8000, 4);
1102 let notifier = TestNotifier::new();
1103 let mut producer = VirtqProducer::new(layout, mem.clone(), notifier.clone(), pool);
1104 let mut consumer = VirtqConsumer::new(layout, mem, notifier);
1105
1106 let mut se = producer.chain().readable(10).writable(32).build().unwrap();
1107
1108 assert_eq!(se.segment_count(), 3);
1109 assert_eq!(se.capacity(), 10);
1110
1111 se.write_all(b"abcdefghij").unwrap();
1112 assert_eq!(se.written(), 10);
1113
1114 let token = producer.submit(se).unwrap();
1115 let (recv, reply) = poll_received(&mut consumer);
1116 assert_eq!(recv.token(), token);
1117 assert_eq!(recv.to_bytes().as_ref(), b"abcdefghij");
1118 assert_eq!(recv.segments().segment_count(), 3);
1119 assert_eq!(recv.segments().as_slice()[0].as_ref(), b"abcd");
1120 assert_eq!(recv.segments().as_slice()[1].as_ref(), b"efgh");
1121 assert_eq!(recv.segments().as_slice()[2].as_ref(), b"ij");
1122 consumer.complete(reply).unwrap();
1123 }
1124
1125 #[test]
1126 fn test_chain_readable_rejects_zero_capacity_on_build() {
1127 let ring = make_ring(16);
1128 let (producer, _consumer, _notifier) = make_test_producer(&ring);
1129
1130 assert!(matches!(
1131 producer.chain().readable(0).build(),
1132 Err(VirtqError::Alloc(AllocError::InvalidArg))
1133 ));
1134 }
1135
1136 #[test]
1137 fn test_chain_writable_splits_logical_capacity() {
1138 let ring = make_ring(16);
1139 let layout = ring.layout();
1140 let mem = ring.mem();
1141 let pool_base = mem.base_addr() + Layout::query_size(ring.len()) as u64 + 0x100;
1142 let pool = TestPool::new_with_max_alloc_len(pool_base, 0x8000, 4);
1143 let notifier = TestNotifier::new();
1144 let mut producer = VirtqProducer::new(layout, mem.clone(), notifier.clone(), pool);
1145 let mut consumer = VirtqConsumer::new(layout, mem, notifier);
1146
1147 let se = producer.chain().writable(10).build().unwrap();
1148 let token = producer.submit(se).unwrap();
1149
1150 let (_recv, reply) = poll_received(&mut consumer);
1151 let ReplyChain::Writable(mut wc) = reply else {
1152 panic!("expected writable reply");
1153 };
1154 assert_eq!(wc.capacity(), 10);
1155
1156 wc.write_all(b"abcdefghij").unwrap();
1157 consumer.complete(wc).unwrap();
1158
1159 let used = producer.poll().unwrap().unwrap();
1160 assert_eq!(used.token(), token);
1161 let segments = used.segments().unwrap();
1162 assert_eq!(segments.segment_count(), 3);
1163 assert_eq!(segments.as_slice()[0].as_ref(), b"abcd");
1164 assert_eq!(segments.as_slice()[1].as_ref(), b"efgh");
1165 assert_eq!(segments.as_slice()[2].as_ref(), b"ij");
1166 }
1167
1168 #[test]
1169 fn test_chain_writable_rejects_zero_capacity_on_build() {
1170 let ring = make_ring(16);
1171 let (producer, _consumer, _notifier) = make_test_producer(&ring);
1172
1173 assert!(matches!(
1174 producer.chain().writable(0).build(),
1175 Err(VirtqError::Alloc(AllocError::InvalidArg))
1176 ));
1177 }
1178
1179 #[test]
1180 fn test_chain_multi_readable_write_all_preserves_segments() {
1181 let ring = make_ring(16);
1182 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1183
1184 let mut se = producer.chain().readable(4).readable(4).build().unwrap();
1185 se.write_all(b"headbody").unwrap();
1186
1187 producer.submit(se).unwrap();
1188 let (recv, reply) = poll_received(&mut consumer);
1189 assert_eq!(recv.to_bytes().as_ref(), b"headbody");
1190 consumer.complete(reply).unwrap();
1191 }
1192
1193 #[test]
1194 fn test_chain_payload_segment_writer_serializes_directly() {
1195 let ring = make_ring(16);
1196 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1197
1198 let mut se = producer.chain().readable(4).readable(4).build().unwrap();
1199 se.with_seg(0, |segment| {
1200 segment.copy_from_slice(b"head");
1201 Ok::<usize, VirtqError>(4)
1202 })
1203 .unwrap();
1204 se.with_seg(1, |segment| {
1205 segment.copy_from_slice(b"body");
1206 Ok::<usize, VirtqError>(4)
1207 })
1208 .unwrap();
1209
1210 producer.submit(se).unwrap();
1211 let (recv, reply) = poll_received(&mut consumer);
1212 assert_eq!(recv.to_bytes().as_ref(), b"headbody");
1213 assert_eq!(recv.segments().segment_count(), 2);
1214 consumer.complete(reply).unwrap();
1215 }
1216
1217 #[test]
1218 fn test_chain_payload_segment_write_copies_directly() {
1219 let ring = make_ring(16);
1220 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1221
1222 let mut se = producer.chain().readable(4).readable(4).build().unwrap();
1223 se.write_seg(0, b"head").unwrap();
1224 se.write_seg(1, b"body").unwrap();
1225
1226 producer.submit(se).unwrap();
1227 let (recv, reply) = poll_received(&mut consumer);
1228 assert_eq!(recv.to_bytes().as_ref(), b"headbody");
1229 assert_eq!(recv.segments().segment_count(), 2);
1230 consumer.complete(reply).unwrap();
1231 }
1232
1233 #[test]
1234 fn test_chain_multi_writable_used_returns_segments() {
1235 let ring = make_ring(16);
1236 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1237
1238 let se = producer.chain().writable(5).writable(6).build().unwrap();
1239 let token = producer.submit(se).unwrap();
1240
1241 let (_recv, reply) = poll_received(&mut consumer);
1242 let ReplyChain::Writable(mut wc) = reply else {
1243 panic!("expected writable reply");
1244 };
1245 assert_eq!(wc.capacity(), 11);
1246
1247 wc.write_all(b"hello world").unwrap();
1248 consumer.complete(wc).unwrap();
1249
1250 let used = producer.poll().unwrap().unwrap();
1251 assert_eq!(used.token(), token);
1252 let segments = used.segments().unwrap();
1253 assert_eq!(segments.segment_count(), 2);
1254 assert_eq!(segments.as_slice()[0].as_ref(), b"hello");
1255 assert_eq!(segments.as_slice()[1].as_ref(), b" world");
1256 assert_eq!(segments.to_bytes().as_ref(), b"hello world");
1257 }
1258
1259 #[test]
1260 fn test_chain_multi_writable_short_used_truncates_last_segment() {
1261 let ring = make_ring(16);
1262 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1263
1264 let se = producer.chain().writable(5).writable(6).build().unwrap();
1265 producer.submit(se).unwrap();
1266
1267 let (_recv, reply) = poll_received(&mut consumer);
1268 let ReplyChain::Writable(mut wc) = reply else {
1269 panic!("expected writable reply");
1270 };
1271
1272 wc.write_all(b"hello wo").unwrap();
1273 consumer.complete(wc).unwrap();
1274
1275 let used = producer.poll().unwrap().unwrap();
1276 let segments = used.segments().unwrap();
1277 assert_eq!(segments.segment_count(), 2);
1278 assert_eq!(segments.as_slice()[0].as_ref(), b"hello");
1279 assert_eq!(segments.as_slice()[1].as_ref(), b" wo");
1280 assert_eq!(segments.to_bytes().as_ref(), b"hello wo");
1281 }
1282
1283 #[test]
1284 fn test_chain_multi_writable_zero_used_returns_empty_segments() {
1285 let ring = make_ring(16);
1286 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1287
1288 let se = producer.chain().writable(5).writable(6).build().unwrap();
1289 producer.submit(se).unwrap();
1290
1291 let (_recv, reply) = poll_received(&mut consumer);
1292 consumer.complete(reply).unwrap();
1293
1294 let used = producer.poll().unwrap().unwrap();
1295 let segments = used.segments().unwrap();
1296 assert_eq!(segments.segment_count(), 0);
1297 assert!(segments.is_empty());
1298 assert!(segments.to_bytes().is_empty());
1299 }
1300
1301 #[test]
1302 fn test_chain_readable_only_build() {
1303 let ring = make_ring(16);
1304 let (producer, _consumer, _notifier) = make_test_producer(&ring);
1305
1306 let se = producer.chain().readable(32).build().unwrap();
1307 assert_eq!(se.capacity(), 32);
1308 }
1309
1310 #[test]
1311 fn test_chain_writable_only_build() {
1312 let ring = make_ring(16);
1313 let (producer, _consumer, _notifier) = make_test_producer(&ring);
1314
1315 let se = producer.chain().writable(64).build().unwrap();
1316 assert_eq!(se.capacity(), 0);
1317 }
1318
1319 #[test]
1320 fn test_chain_empty_build_fails() {
1321 let ring = make_ring(16);
1322 let (producer, _consumer, _notifier) = make_test_producer(&ring);
1323
1324 let result = producer.chain().build();
1325 assert!(matches!(result, Err(VirtqError::InvalidState)));
1326 }
1327
1328 #[test]
1329 fn test_send_chain_write_all_and_submit() {
1330 let ring = make_ring(16);
1331 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1332
1333 let mut se = producer.chain().readable(64).writable(128).build().unwrap();
1334
1335 se.write_all(b"hello")
1336 .unwrap()
1337 .write_all(b" world")
1338 .unwrap();
1339 assert_eq!(se.written(), 11);
1340 assert_eq!(se.remaining(), 53);
1341 let tok = producer.submit(se).unwrap();
1342
1343 let (recv, reply) = poll_received(&mut consumer);
1344 assert_eq!(recv.token(), tok);
1345 assert_eq!(recv.to_bytes().as_ref(), b"hello world");
1346 consumer.complete(reply).unwrap();
1347 }
1348
1349 #[test]
1350 fn test_send_payload_write_all_fluent() {
1351 let ring = make_ring(16);
1352 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1353
1354 let mut se = producer.chain().readable(64).writable(128).build().unwrap();
1355 se.write_all(b"hello")
1356 .unwrap()
1357 .write_all(b" world")
1358 .unwrap();
1359 assert_eq!(se.written(), 11);
1360 assert_eq!(se.remaining(), 53);
1361 let tok = producer.submit(se).unwrap();
1362
1363 let (recv, reply) = poll_received(&mut consumer);
1364 assert_eq!(recv.token(), tok);
1365 assert_eq!(recv.to_bytes().as_ref(), b"hello world");
1366 consumer.complete(reply).unwrap();
1367 }
1368
1369 #[test]
1370 fn test_send_payload_partial_write() {
1371 let ring = make_ring(16);
1372 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1373
1374 let mut se = producer.chain().readable(8).build().unwrap();
1375 let written = se.write(b"hello world").unwrap();
1376 assert_eq!(written, 8);
1377 assert_eq!(se.remaining(), 0);
1378
1379 producer.submit(se).unwrap();
1380 let (recv, reply) = poll_received(&mut consumer);
1381 assert_eq!(recv.to_bytes().as_ref(), b"hello wo");
1382 consumer.complete(reply).unwrap();
1383 }
1384
1385 #[test]
1386 fn test_send_payload_write_with_serializes_directly() {
1387 let ring = make_ring(16);
1388 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1389
1390 let mut se = producer.chain().readable(64).writable(128).build().unwrap();
1391 se.with_seg(0, |buf| {
1392 buf[..5].copy_from_slice(b"hello");
1393 Ok::<usize, VirtqError>(5)
1394 })
1395 .unwrap();
1396
1397 let _tok = producer.submit(se).unwrap();
1398
1399 let (recv, reply) = poll_received(&mut consumer);
1400 assert_eq!(recv.to_bytes().as_ref(), b"hello");
1401 consumer.complete(reply).unwrap();
1402 }
1403
1404 #[test]
1405 fn test_send_chain_single_segment_writer_serializes_directly() {
1406 let ring = make_ring(16);
1407 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1408
1409 let mut se = producer.chain().readable(64).writable(128).build().unwrap();
1410 se.with_seg(0, |segment| {
1411 assert_eq!(segment.len(), 64);
1412 segment[..5].copy_from_slice(b"hello");
1413 Ok::<usize, VirtqError>(5)
1414 })
1415 .unwrap();
1416
1417 let _tok = producer.submit(se).unwrap();
1418
1419 let (recv, reply) = poll_received(&mut consumer);
1420 assert_eq!(recv.to_bytes().as_ref(), b"hello");
1421 consumer.complete(reply).unwrap();
1422 }
1423
1424 #[test]
1425 fn test_send_chain_single_segment_writer_rejects_multi_segment() {
1426 let ring = make_ring(16);
1427 let (producer, _consumer, _notifier) = make_test_producer(&ring);
1428
1429 let mut se = producer.chain().readable(4).readable(4).build().unwrap();
1430 assert!(matches!(
1431 se.with_seg(2, |_| Ok::<usize, VirtqError>(0)),
1432 Err(VirtqError::NoPayloadSegment)
1433 ));
1434 }
1435
1436 #[test]
1437 fn test_send_chain_single_segment_writer_rejects_auto_split_chain() {
1438 let ring = make_ring(16);
1439 let layout = ring.layout();
1440 let mem = ring.mem();
1441 let pool_base = mem.base_addr() + Layout::query_size(ring.len()) as u64 + 0x100;
1442 let pool = TestPool::new_with_max_alloc_len(pool_base, 0x8000, 4);
1443 let notifier = TestNotifier::new();
1444 let producer = VirtqProducer::new(layout, mem, notifier, pool);
1445
1446 let mut se = producer.chain().readable(8).build().unwrap();
1447 assert_eq!(se.segment_count(), 2);
1448 assert!(matches!(
1449 se.with_seg(2, |_| Ok::<usize, VirtqError>(0)),
1450 Err(VirtqError::NoPayloadSegment)
1451 ));
1452 }
1453
1454 #[test]
1455 fn test_send_payload_segment_set_written_too_large() {
1456 let ring = make_ring(16);
1457 let (producer, _consumer, _notifier) = make_test_producer(&ring);
1458
1459 let mut se = producer.chain().readable(32).writable(64).build().unwrap();
1460 let err = se
1461 .with_seg(0, |_| Ok::<usize, VirtqError>(64))
1462 .err()
1463 .unwrap();
1464 assert!(matches!(
1465 err,
1466 VirtqError::PayloadTooLarge {
1467 recv: 64,
1468 limit: 32
1469 }
1470 ));
1471 }
1472
1473 #[test]
1474 fn test_send_chain_write_too_large() {
1475 let ring = make_ring(16);
1476 let (producer, _consumer, _notifier) = make_test_producer(&ring);
1477
1478 let mut se = producer.chain().readable(4).build().unwrap();
1479 let err = se.write_all(b"too long").err().unwrap();
1480 assert!(matches!(
1481 err,
1482 VirtqError::PayloadTooLarge { recv: 8, limit: 4 }
1483 ));
1484 }
1485
1486 #[test]
1487 fn test_writeonly_has_no_readable_buffer() {
1488 let ring = make_ring(16);
1489 let (producer, _consumer, _notifier) = make_test_producer(&ring);
1490
1491 let mut se = producer.chain().writable(32).build().unwrap();
1492 let err = se.write_all(b"data").err().unwrap();
1493 assert!(matches!(err, VirtqError::NoPayloadSegment));
1494 }
1495
1496 #[test]
1497 fn test_drop_chain_builder_deallocs() {
1498 let ring = make_ring(16);
1499 let (mut producer, _consumer, _notifier) = make_test_producer(&ring);
1500
1501 {
1502 let _builder = producer.chain().readable(64).writable(128);
1503 }
1505
1506 let se = producer.chain().readable(64).writable(128).build().unwrap();
1508 let tok = producer.submit(se).unwrap();
1509 assert!(tok.id < 16);
1510 }
1511
1512 #[test]
1513 fn test_drop_send_chain_deallocs() {
1514 let ring = make_ring(16);
1515 let (mut producer, _consumer, _notifier) = make_test_producer(&ring);
1516
1517 {
1518 let _se = producer.chain().readable(64).writable(128).build().unwrap();
1519 }
1521
1522 let se = producer.chain().readable(64).writable(128).build().unwrap();
1524 let tok = producer.submit(se).unwrap();
1525 assert!(tok.id < 16);
1526 }
1527
1528 #[test]
1529 fn test_submit_notifies() {
1530 let ring = make_ring(16);
1531 let (mut producer, _consumer, notifier) = make_test_producer(&ring);
1532
1533 let initial_count = notifier.notification_count();
1534
1535 let mut se = producer.chain().readable(64).writable(128).build().unwrap();
1536 se.write_all(b"hello").unwrap();
1537 producer.submit(se).unwrap();
1538
1539 assert!(notifier.notification_count() > initial_count);
1540 }
1541
1542 #[test]
1543 fn test_submit_read_only_notifies_by_default() {
1544 let ring = make_ring(16);
1545 let (mut producer, _consumer, notifier) = make_test_producer(&ring);
1546
1547 let initial_count = notifier.notification_count();
1548
1549 let mut se = producer.chain().readable(64).build().unwrap();
1550 se.write_all(b"fire-and-forget").unwrap();
1551 producer.submit(se).unwrap();
1552
1553 assert!(notifier.notification_count() > initial_count);
1554 }
1555
1556 #[test]
1557 fn test_submit_write_only_notifies_by_default() {
1558 let ring = make_ring(16);
1559 let (mut producer, _consumer, notifier) = make_test_producer(&ring);
1560
1561 let initial_count = notifier.notification_count();
1562
1563 let se = producer.chain().writable(128).build().unwrap();
1564 producer.submit(se).unwrap();
1565
1566 assert!(notifier.notification_count() > initial_count);
1567 }
1568
1569 #[test]
1570 fn test_batch_notifies_once_on_finish() {
1571 let ring = make_ring(16);
1572 let (mut producer, mut consumer, notifier) = make_test_producer(&ring);
1573
1574 let initial_count = notifier.notification_count();
1575
1576 let mut batch = producer.batch();
1577
1578 let mut first = batch.chain().readable(64).build().unwrap();
1579 first.write_all(b"first").unwrap();
1580 batch.submit(first).unwrap();
1581
1582 let mut second = batch.chain().readable(64).build().unwrap();
1583 second.write_all(b"second").unwrap();
1584 batch.submit(second).unwrap();
1585
1586 assert_eq!(notifier.notification_count(), initial_count);
1587 assert!(batch.finish().unwrap());
1588 assert_eq!(notifier.notification_count(), initial_count + 1);
1589
1590 let (recv, reply) = poll_received(&mut consumer);
1591 assert_eq!(recv.to_bytes().as_ref(), b"first");
1592 consumer.complete(reply).unwrap();
1593
1594 let (recv, reply) = poll_received(&mut consumer);
1595 assert_eq!(recv.to_bytes().as_ref(), b"second");
1596 consumer.complete(reply).unwrap();
1597 }
1598
1599 #[test]
1600 fn test_batch_finish_notifies_from_batch_start_cursor() {
1601 let ring = make_ring(16);
1602 let (mut producer, mut consumer, notifier) = make_test_producer(&ring);
1603
1604 let cursor = consumer.avail_cursor();
1605 consumer
1606 .set_avail_suppression(SuppressionKind::Descriptor(cursor))
1607 .unwrap();
1608
1609 let mut batch = producer.batch();
1610
1611 let mut first = batch.chain().readable(64).build().unwrap();
1612 first.write_all(b"first").unwrap();
1613 batch.submit(first).unwrap();
1614 assert_eq!(notifier.notification_count(), 0);
1615
1616 let mut second = batch.chain().readable(64).writable(64).build().unwrap();
1617 second.write_all(b"second").unwrap();
1618 batch.submit(second).unwrap();
1619
1620 assert!(batch.finish().unwrap());
1621
1622 assert_eq!(notifier.notification_count(), 1);
1623 }
1624
1625 #[test]
1626 fn test_empty_batch_finish_does_not_notify() {
1627 let ring = make_ring(16);
1628 let (mut producer, _consumer, notifier) = make_test_producer(&ring);
1629
1630 let batch = producer.batch();
1631 assert!(!batch.finish().unwrap());
1632 assert_eq!(notifier.notification_count(), 0);
1633 }
1634
1635 #[test]
1636 fn test_write_only_round_trip() {
1637 let ring = make_ring(16);
1638 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1639
1640 let se = producer.chain().writable(32).build().unwrap();
1641 let token = producer.submit(se).unwrap();
1642
1643 let (recv, reply) = poll_received(&mut consumer);
1644 assert_eq!(recv.token(), token);
1645 assert!(recv.to_bytes().is_empty());
1646
1647 if let ReplyChain::Writable(mut wc) = reply {
1648 wc.write_all(b"filled-by-consumer").unwrap();
1649 consumer.complete(wc).unwrap();
1650 } else {
1651 panic!("expected Writable");
1652 }
1653
1654 let used = producer.poll().unwrap().unwrap();
1655 assert_eq!(used.token(), token);
1656 assert_eq!(used.to_bytes().unwrap().len(), b"filled-by-consumer".len());
1657 assert_eq!(used.to_bytes().unwrap().as_ref(), b"filled-by-consumer");
1658 }
1659
1660 #[test]
1661 fn test_read_only_round_trip() {
1662 let ring = make_ring(16);
1663 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1664
1665 let mut se = producer.chain().readable(32).build().unwrap();
1666 se.write_all(b"fire-and-forget").unwrap();
1667 let token = producer.submit(se).unwrap();
1668
1669 let (recv, reply) = poll_received(&mut consumer);
1670 assert_eq!(recv.token(), token);
1671 assert_eq!(recv.to_bytes().as_ref(), b"fire-and-forget");
1672 assert!(matches!(reply, ReplyChain::Ack(_)));
1673 consumer.complete(reply).unwrap();
1674
1675 let used = producer.poll().unwrap().unwrap();
1676 assert!(matches!(used, UsedChain::Ack(t) if t == token));
1677 }
1678
1679 #[test]
1680 fn test_readwrite_round_trip() {
1681 let ring = make_ring(16);
1682 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1683
1684 let mut se = producer.chain().readable(64).writable(128).build().unwrap();
1685 se.write_all(b"request data").unwrap();
1686 let token = producer.submit(se).unwrap();
1687
1688 let (recv, reply) = poll_received(&mut consumer);
1689 assert_eq!(recv.to_bytes().as_ref(), b"request data");
1690 if let ReplyChain::Writable(mut wc) = reply {
1691 wc.write_all(b"response data").unwrap();
1692 consumer.complete(wc).unwrap();
1693 } else {
1694 panic!("expected Writable");
1695 }
1696
1697 let used = producer.poll().unwrap().unwrap();
1698 assert_eq!(used.token(), token);
1699 assert_eq!(used.to_bytes().unwrap().as_ref(), b"response data");
1700 }
1701
1702 #[test]
1703 fn test_poll_used_requires_direct_slice() {
1704 let ring = make_ring(16);
1705 let layout = ring.layout();
1706 let test_mem = ring.mem();
1707 let pool_base = test_mem.base_addr() + Layout::query_size(ring.len()) as u64 + 0x100;
1708 let pool = TestPool::new(pool_base, 0x8000);
1709 let notifier = TestNotifier::new();
1710 let mem = NoDirectSliceMem(test_mem);
1711 let mut producer = VirtqProducer::new(layout, mem.clone(), notifier.clone(), pool);
1712 let mut consumer = VirtqConsumer::new(layout, mem, notifier);
1713
1714 let mut se = producer.chain().readable(64).writable(128).build().unwrap();
1715 se.write_all(b"request data").unwrap();
1716 producer.submit(se).unwrap();
1717
1718 let (_recv, reply) = poll_received(&mut consumer);
1719 if let ReplyChain::Writable(mut wc) = reply {
1720 wc.write_all(b"response data").unwrap();
1721 consumer.complete(wc).unwrap();
1722 } else {
1723 panic!("expected Writable");
1724 }
1725
1726 assert!(matches!(producer.poll(), Err(VirtqError::MemoryReadError)));
1727 }
1728
1729 #[test]
1730 fn test_virtq_producer_reset() {
1731 let ring = make_ring(16);
1732 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
1733
1734 let mut se = producer.chain().readable(32).writable(64).build().unwrap();
1736 se.write_all(b"hello").unwrap();
1737 producer.submit(se).unwrap();
1738
1739 let (recv, reply) = poll_received(&mut consumer);
1740 assert_eq!(recv.to_bytes().as_ref(), b"hello");
1741 consumer.complete(reply).unwrap();
1742 let _ = producer.poll().unwrap().unwrap();
1743
1744 unsafe {
1748 producer.reset();
1749 }
1750
1751 assert_eq!(producer.inner.num_inflight(), 0);
1753 assert_eq!(producer.inner.num_free(), producer.inner.len());
1755 }
1756
1757 #[test]
1758 fn test_virtq_producer_reset_clears_inflight() {
1759 let ring = make_ring(16);
1760 let (mut producer, _consumer, _notifier) = make_test_producer(&ring);
1761
1762 let se = producer.chain().writable(64).build().unwrap();
1764 producer.submit(se).unwrap();
1765
1766 assert_eq!(producer.inner.num_inflight(), 1);
1767
1768 unsafe {
1770 producer.reset();
1771 }
1772
1773 assert_eq!(producer.inner.num_inflight(), 0);
1774 assert_eq!(producer.inner.num_free(), producer.inner.len());
1775 }
1776}