1use alloc::vec;
5
6use bytes::Bytes;
7use fixedbitset::FixedBitSet;
8use smallvec::SmallVec;
9
10use super::*;
11
12type WritableElems = SmallVec<[BufferElement; 2]>;
13
14#[derive(Debug, Clone)]
21pub struct RecvChain {
22 token: Token,
23 segments: Segments,
24}
25
26impl RecvChain {
27 pub fn token(&self) -> Token {
29 self.token
30 }
31
32 pub fn segments(&self) -> &Segments {
34 &self.segments
35 }
36
37 pub fn into_segments(self) -> Segments {
39 self.segments
40 }
41
42 pub fn to_bytes(&self) -> Bytes {
46 self.segments.to_bytes()
47 }
48
49 pub fn into_bytes(self) -> Bytes {
51 self.segments.into_bytes()
52 }
53}
54
55#[must_use = "dropping without completing leaks the descriptor"]
60pub enum ReplyChain<M: MemOps> {
61 Writable(WritableChain<M>),
65 Ack(AckChain),
68}
69
70impl<M: MemOps> ReplyChain<M> {
71 pub fn token(&self) -> Token {
73 match self {
74 ReplyChain::Writable(wc) => wc.token(),
75 ReplyChain::Ack(ack) => ack.token(),
76 }
77 }
78
79 pub fn written(&self) -> usize {
81 match self {
82 ReplyChain::Writable(wc) => wc.written,
83 ReplyChain::Ack(_) => 0,
84 }
85 }
86
87 pub fn into_writable(self) -> Result<WritableChain<M>, AckChain> {
92 match self {
93 ReplyChain::Writable(wc) => Ok(wc),
94 ReplyChain::Ack(ack) => Err(ack),
95 }
96 }
97}
98
99#[must_use = "dropping without completing leaks the descriptor"]
110pub struct WritableChain<M: MemOps> {
111 mem: M,
112 token: Token,
113 elems: WritableElems,
114 capacity: usize,
115 written: usize,
116}
117
118impl<M: MemOps> WritableChain<M> {
119 fn new(mem: M, token: Token, elems: WritableElems) -> Self {
120 let capacity = elems.iter().map(|elem| elem.len as usize).sum();
121 Self {
122 mem,
123 token,
124 elems,
125 capacity,
126 written: 0,
127 }
128 }
129
130 pub fn token(&self) -> Token {
132 self.token
133 }
134
135 pub fn capacity(&self) -> usize {
137 self.capacity
138 }
139
140 pub fn written(&self) -> usize {
142 self.written
143 }
144
145 pub fn remaining(&self) -> usize {
147 self.capacity() - self.written()
148 }
149
150 pub fn write(&mut self, buf: &[u8]) -> Result<usize, VirtqError> {
161 let written = write_elements(&self.mem, &self.elems, self.written, buf)
162 .map_err(|_| VirtqError::MemoryWriteError)?;
163 self.written += written;
164 Ok(written)
165 }
166
167 pub fn write_all(&mut self, buf: &[u8]) -> Result<&mut Self, VirtqError> {
174 if buf.len() > self.remaining() {
175 return Err(VirtqError::ReplyTooLarge);
176 }
177
178 let written = self.write(buf)?;
179 debug_assert_eq!(written, buf.len());
180 Ok(self)
181 }
182
183 pub fn rewind(&mut self) {
188 self.written = 0;
189 }
190}
191
192#[must_use = "dropping without completing leaks the descriptor"]
199pub struct AckChain {
200 token: Token,
201}
202
203impl AckChain {
204 fn new(token: Token) -> Self {
205 Self { token }
206 }
207
208 pub fn token(&self) -> Token {
209 self.token
210 }
211}
212
213pub struct VirtqConsumer<M, N> {
250 inner: RingConsumer<M>,
251 notifier: N,
252 inflight: FixedBitSet,
253 next_token: u32,
254}
255
256impl<M: MemOps + Clone, N: Notifier> VirtqConsumer<M, N> {
257 pub fn new(layout: Layout, mem: M, notifier: N) -> Self {
265 let inner = RingConsumer::new(layout, mem);
266 let inflight = FixedBitSet::with_capacity(inner.len());
267
268 Self {
269 inner,
270 notifier,
271 inflight,
272 next_token: 0,
273 }
274 }
275
276 pub fn poll(
298 &mut self,
299 max_recv_len: usize,
300 ) -> Result<Option<(RecvChain, ReplyChain<M>)>, VirtqError> {
301 let (id, chain) = match self.inner.poll_available() {
302 Ok(x) => x,
303 Err(RingError::WouldBlock) => return Ok(None),
304 Err(e) => return Err(e.into()),
305 };
306
307 let readables = chain.readables();
308 let writables = chain.writables();
309 if readables.is_empty() && writables.is_empty() {
310 return Err(self.abort_chain(id, VirtqError::BadChain));
311 }
312
313 let recv_len = readables
314 .iter()
315 .fold(0usize, |acc, elem| acc.saturating_add(elem.len as usize));
316
317 let id_idx = id as usize;
319 if id_idx >= self.inflight.len() {
320 return Err(VirtqError::InvalidState);
321 }
322
323 if self.inflight.contains(id_idx) {
324 return Err(VirtqError::InvalidState);
325 }
326
327 self.inflight.insert(id_idx);
328 let token = Token {
329 seq: self.next_token,
330 id,
331 };
332 self.next_token = self.next_token.wrapping_add(1);
333
334 if recv_len > max_recv_len {
335 return Err(self.abort_chain(
336 id,
337 VirtqError::PayloadTooLarge {
338 recv: recv_len,
339 limit: max_recv_len,
340 },
341 ));
342 }
343
344 let data = match self.read_elements(readables) {
346 Ok(d) => d,
347 Err(e) => return Err(self.abort_chain(id, e)),
348 };
349
350 let chain = RecvChain {
351 token,
352 segments: data,
353 };
354
355 let reply = if !writables.is_empty() {
356 let mem = self.inner.mem().clone();
357 let writable = WritableChain::new(mem, token, writables.iter().copied().collect());
358 ReplyChain::Writable(writable)
359 } else {
360 let ack = AckChain::new(token);
361 ReplyChain::Ack(ack)
362 };
363
364 Ok(Some((chain, reply)))
365 }
366
367 pub fn complete(&mut self, reply: impl Into<ReplyChain<M>>) -> Result<(), VirtqError> {
374 let reply = reply.into();
375 let id = reply.token().id;
376 let written = u32::try_from(reply.written()).map_err(|_| VirtqError::ReplyTooLarge)?;
377
378 let id_idx = id as usize;
379 let slot_set = id_idx < self.inflight.len() && self.inflight.contains(id_idx);
380 if !slot_set {
381 return Err(VirtqError::InvalidState);
382 }
383
384 self.inflight.set(id_idx, false);
385
386 if self.inner.submit_used_with_notify(id, written)? {
387 self.notifier.notify(QueueStats {
388 num_free: self.inner.num_free(),
389 num_inflight: self.inner.num_inflight(),
390 });
391 }
392
393 Ok(())
394 }
395
396 fn abort_chain(&mut self, id: u16, err: VirtqError) -> VirtqError {
401 let id_idx = id as usize;
402 if id_idx < self.inflight.len() {
403 self.inflight.set(id_idx, false);
404 }
405
406 if let Ok(true) = self.inner.submit_used_with_notify(id, 0) {
409 self.notifier.notify(QueueStats {
410 num_free: self.inner.num_free(),
411 num_inflight: self.inner.num_inflight(),
412 });
413 }
414
415 err
416 }
417
418 #[inline]
423 pub fn avail_cursor(&self) -> RingCursor {
424 self.inner.avail_cursor()
425 }
426
427 #[inline]
432 pub fn used_cursor(&self) -> RingCursor {
433 self.inner.used_cursor()
434 }
435
436 pub fn set_avail_suppression(&mut self, kind: SuppressionKind) -> Result<(), VirtqError> {
455 match kind {
456 SuppressionKind::Enable => self.inner.enable_avail_notifications()?,
457 SuppressionKind::Disable => self.inner.disable_avail_notifications()?,
458 SuppressionKind::Descriptor(cursor) => self
459 .inner
460 .enable_avail_notifications_desc(cursor.head(), cursor.wrap())?,
461 }
462 Ok(())
463 }
464
465 fn read_elements(&self, elems: &[BufferElement]) -> Result<Segments, VirtqError> {
467 let mut segments = SmallVec::<[Bytes; 4]>::new();
468
469 for elem in elems {
470 let mut buf = vec![0u8; elem.len as usize];
471 self.inner
472 .mem()
473 .read(elem.addr, &mut buf)
474 .map_err(|_| VirtqError::MemoryReadError)?;
475 segments.push(Bytes::from(buf));
476 }
477
478 Ok(Segments::from_smallvec(segments))
479 }
480
481 pub fn reset(&mut self) {
483 self.inner.reset();
484 self.inflight.clear();
485 }
486}
487
488fn write_elements<M: MemOps>(
489 mem: &M,
490 elems: &[BufferElement],
491 offset: usize,
492 buf: &[u8],
493) -> Result<usize, M::Error> {
494 let capacity: usize = elems.iter().map(|elem| elem.len as usize).sum();
495 let mut src = &buf[..buf.len().min(capacity.saturating_sub(offset))];
496 let mut written = 0;
497 let mut skip = offset;
498
499 for elem in elems {
500 if src.is_empty() {
501 break;
502 }
503
504 let elem_len = elem.len as usize;
505 if skip >= elem_len {
506 skip -= elem_len;
507 continue;
508 }
509
510 let elem_offset = skip;
511 skip = 0;
512 let n = (elem_len - elem_offset).min(src.len());
513 let addr = elem.addr + elem_offset as u64;
514
515 mem.write(addr, &src[..n])?;
516
517 written += n;
518 src = &src[n..];
519 }
520
521 Ok(written)
522}
523
524impl<M: MemOps> From<WritableChain<M>> for ReplyChain<M> {
525 fn from(wc: WritableChain<M>) -> Self {
526 ReplyChain::Writable(wc)
527 }
528}
529
530impl<M: MemOps> From<AckChain> for ReplyChain<M> {
531 fn from(ack: AckChain) -> Self {
532 ReplyChain::Ack(ack)
533 }
534}
535
536#[cfg(test)]
537mod tests {
538 use super::*;
539 use crate::virtq::ring::tests::{make_producer, make_ring};
540 use crate::virtq::test_utils::*;
541
542 fn poll_data(
543 consumer: &mut VirtqConsumer<crate::virtq::ring::tests::TestMem, TestNotifier>,
544 ) -> (RecvChain, ReplyChain<crate::virtq::ring::tests::TestMem>) {
545 consumer.poll(1024).unwrap().unwrap()
546 }
547
548 #[test]
549 fn test_write_only_recv_is_empty() {
550 let ring = make_ring(16);
551 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
552
553 let se = producer.chain().writable(16).build().unwrap();
554 producer.submit(se).unwrap();
555
556 let (recv, reply) = poll_data(&mut consumer);
557 assert!(recv.to_bytes().is_empty());
558 assert!(matches!(reply, ReplyChain::Writable(_)));
559
560 if let ReplyChain::Writable(mut wc) = reply {
561 wc.write_all(b"response").unwrap();
562 consumer.complete(wc).unwrap();
563 }
564 }
565
566 #[test]
567 fn test_read_only_ack_reply() {
568 let ring = make_ring(16);
569 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
570
571 let mut se = producer.chain().readable(16).build().unwrap();
572 se.write_all(b"hello").unwrap();
573 producer.submit(se).unwrap();
574
575 let (recv, reply) = poll_data(&mut consumer);
576 assert_eq!(recv.to_bytes().as_ref(), b"hello");
577 assert!(matches!(reply, ReplyChain::Ack(_)));
578
579 consumer.complete(reply).unwrap();
580 }
581
582 #[test]
583 fn test_readwrite_round_trip() {
584 let ring = make_ring(16);
585 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
586
587 let mut se = producer.chain().readable(32).writable(64).build().unwrap();
588 se.write_all(b"hello world").unwrap();
589 producer.submit(se).unwrap();
590
591 let (recv, reply) = poll_data(&mut consumer);
592 assert_eq!(recv.to_bytes().as_ref(), b"hello world");
593
594 if let ReplyChain::Writable(mut wc) = reply {
595 assert_eq!(wc.capacity(), 64);
596 assert_eq!(wc.written(), 0);
597 assert_eq!(wc.remaining(), 64);
598 wc.write_all(b"response").unwrap();
599 assert_eq!(wc.written(), 8);
600 assert_eq!(wc.remaining(), 56);
601 consumer.complete(wc).unwrap();
602 } else {
603 panic!("expected Writable reply for recv+reply chain");
604 }
605 }
606
607 #[test]
608 fn test_writable_partial_write() {
609 let ring = make_ring(16);
610 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
611
612 let se = producer.chain().writable(8).build().unwrap();
613 producer.submit(se).unwrap();
614
615 let (_recv, reply) = poll_data(&mut consumer);
616
617 if let ReplyChain::Writable(mut wc) = reply {
618 let n = wc.write(b"hello world!").unwrap();
619 assert_eq!(n, 8);
620 assert_eq!(wc.remaining(), 0);
621 consumer.complete(wc).unwrap();
622 } else {
623 panic!("expected Writable");
624 }
625 }
626
627 #[test]
628 fn test_writable_write_all_too_large() {
629 let ring = make_ring(16);
630 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
631
632 let se = producer.chain().writable(4).build().unwrap();
633 producer.submit(se).unwrap();
634 let (_recv, reply) = poll_data(&mut consumer);
635
636 if let ReplyChain::Writable(mut wc) = reply {
637 let err = wc.write_all(b"too long").err().unwrap();
638 assert!(matches!(err, VirtqError::ReplyTooLarge));
639 } else {
640 panic!("expected Writable");
641 }
642 }
643
644 #[test]
645 fn test_poll_too_large_returns_payload_error() {
646 let ring = make_ring(16);
647 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
648
649 let mut se = producer.chain().readable(8).writable(16).build().unwrap();
650 se.write_all(b"too much").unwrap();
651 producer.submit(se).unwrap();
652
653 assert!(matches!(
654 consumer.poll(4),
655 Err(VirtqError::PayloadTooLarge { recv: 8, limit: 4 })
656 ));
657 }
658
659 #[test]
660 fn test_poll_too_large_returns_descriptor() {
661 let ring = make_ring(16);
662 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
663
664 let mut se = producer.chain().readable(8).writable(16).build().unwrap();
665 se.write_all(b"too much").unwrap();
666 let token = producer.submit(se).unwrap();
667
668 assert!(matches!(
671 consumer.poll(4),
672 Err(VirtqError::PayloadTooLarge { recv: 8, limit: 4 })
673 ));
674
675 let used = producer.poll().unwrap().unwrap();
677 assert_eq!(used.token(), token);
678
679 let se2 = producer.chain().writable(16).build().unwrap();
681 producer.submit(se2).unwrap();
682 let (_recv, reply) = poll_data(&mut consumer);
683 consumer.complete(reply).unwrap();
684 assert!(producer.poll().unwrap().is_some());
685 }
686
687 #[test]
688 fn test_villain_indirect_descriptor_does_not_mark_high_level_inflight() {
689 let ring = make_ring(16);
690 let mem = ring.mem();
691 let mut consumer = VirtqConsumer::new(ring.layout(), mem, TestNotifier::new());
692
693 let mut desc = Descriptor::new(0x1000, 16, 0, DescFlags::INDIRECT);
694 desc.mark_avail(true);
695 ring.write_desc(0, desc);
696
697 assert!(matches!(
698 consumer.poll(1024),
699 Err(VirtqError::RingError(RingError::BadChain))
700 ));
701 assert_eq!(consumer.inflight.count_ones(..), 0);
702 assert_eq!(consumer.inner.num_inflight(), 0);
703 }
704
705 #[test]
706 fn test_villain_bad_chain_does_not_mark_high_level_inflight() {
707 let ring = make_ring(16);
708 let mem = ring.mem();
709 let mut consumer = VirtqConsumer::new(ring.layout(), mem, TestNotifier::new());
710
711 let mut first = Descriptor::new(0x1000, 16, 0, DescFlags::NEXT | DescFlags::WRITE);
712 first.mark_avail(true);
713 ring.write_desc(0, first);
714
715 let mut second = Descriptor::new(0x2000, 16, 0, DescFlags::empty());
716 second.mark_avail(true);
717 ring.write_desc(1, second);
718
719 assert!(matches!(
720 consumer.poll(1024),
721 Err(VirtqError::RingError(RingError::BadChain))
722 ));
723 assert_eq!(consumer.inflight.count_ones(..), 0);
724 assert_eq!(consumer.inner.num_inflight(), 0);
725 }
726
727 #[test]
728 fn test_writable_chain_writes_single_segment() {
729 let ring = make_ring(16);
730 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
731
732 let se = producer.chain().writable(16).build().unwrap();
733 producer.submit(se).unwrap();
734 let (_recv, reply) = poll_data(&mut consumer);
735
736 let ReplyChain::Writable(mut wc) = reply else {
737 panic!("expected Writable");
738 };
739 wc.write_all(b"hello").unwrap();
740 consumer.complete(wc).unwrap();
741
742 let used = producer.poll().unwrap().unwrap();
743 assert_eq!(used.to_bytes().unwrap().as_ref(), b"hello");
744 }
745
746 #[test]
747 fn test_writable_rewind() {
748 let ring = make_ring(16);
749 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
750
751 let se = producer.chain().writable(16).build().unwrap();
752 producer.submit(se).unwrap();
753
754 let (_recv, reply) = poll_data(&mut consumer);
755
756 if let ReplyChain::Writable(mut wc) = reply {
757 wc.write_all(b"first").unwrap();
758 assert_eq!(wc.written(), 5);
759 wc.rewind();
760 assert_eq!(wc.written(), 0);
761 assert_eq!(wc.remaining(), 16);
762 wc.write_all(b"second").unwrap();
763 assert_eq!(wc.written(), 6);
764 consumer.complete(wc).unwrap();
765 } else {
766 panic!("expected Writable");
767 }
768 }
769
770 #[test]
771 fn test_writable_reply_scatters_across_segments() {
772 let ring = make_ring(16);
773 let mem = ring.mem();
774 let mut ring_producer = make_producer(&ring);
775 let mut consumer = VirtqConsumer::new(ring.layout(), mem.clone(), TestNotifier::new());
776
777 let base = mem.base_addr() + Layout::query_size(ring.len()) as u64 + 0x100;
778 let chain = BufferChainBuilder::new()
779 .writable(base, 4)
780 .writable(base + 4, 4)
781 .build()
782 .unwrap();
783 let id = ring_producer.submit_available(&chain).unwrap();
784
785 let (recv, reply) = poll_data(&mut consumer);
786 assert!(recv.to_bytes().is_empty());
787
788 let ReplyChain::Writable(mut wc) = reply else {
789 panic!("expected Writable");
790 };
791 assert_eq!(wc.capacity(), 8);
792 wc.write_all(b"abcdefgh").unwrap();
793 assert_eq!(wc.written(), 8);
794 consumer.complete(wc).unwrap();
795
796 let mut first = [0u8; 4];
797 let mut second = [0u8; 4];
798 mem.read(base, &mut first).unwrap();
799 mem.read(base + 4, &mut second).unwrap();
800 assert_eq!(&first, b"abcd");
801 assert_eq!(&second, b"efgh");
802
803 let used = ring_producer.poll_used().unwrap();
804 assert_eq!(used.id, id);
805 assert_eq!(used.len, 8);
806 }
807
808 #[test]
809 fn test_multiple_pending_replies() {
810 let ring = make_ring(16);
811 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
812
813 let se1 = producer.chain().writable(16).build().unwrap();
814 producer.submit(se1).unwrap();
815 let se2 = producer.chain().writable(16).build().unwrap();
816 producer.submit(se2).unwrap();
817
818 let (_e1, c1) = poll_data(&mut consumer);
819 let (_e2, c2) = poll_data(&mut consumer);
820
821 consumer.complete(c2).unwrap();
823 consumer.complete(c1).unwrap();
824 }
825
826 #[test]
827 fn test_recv_into_bytes() {
828 let ring = make_ring(16);
829 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
830
831 let mut se = producer.chain().readable(16).build().unwrap();
832 se.write_all(b"abc").unwrap();
833 producer.submit(se).unwrap();
834
835 let (recv, reply) = poll_data(&mut consumer);
836 let data = recv.into_bytes();
837 assert_eq!(data.as_ref(), b"abc");
838 consumer.complete(reply).unwrap();
839 }
840
841 #[test]
842 fn test_virtq_consumer_reset() {
843 let ring = make_ring(16);
844 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
845
846 let se = producer.chain().writable(16).build().unwrap();
848 producer.submit(se).unwrap();
849
850 let (_recv, reply) = poll_data(&mut consumer);
851 assert!(consumer.inflight.count_ones(..) > 0);
852
853 consumer.complete(reply).unwrap();
855
856 consumer.reset();
857
858 assert_eq!(consumer.inflight.count_ones(..), 0);
859 assert_eq!(consumer.inner.num_inflight(), 0);
860 }
861
862 #[test]
863 fn test_virtq_consumer_reset_clears_inflight() {
864 let ring = make_ring(16);
865 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
866
867 let se1 = producer.chain().writable(16).build().unwrap();
869 producer.submit(se1).unwrap();
870 let se2 = producer.chain().writable(16).build().unwrap();
871 producer.submit(se2).unwrap();
872
873 let (_e1, c1) = poll_data(&mut consumer);
874 let (_e2, c2) = poll_data(&mut consumer);
875 consumer.complete(c1).unwrap();
877 consumer.complete(c2).unwrap();
878
879 consumer.reset();
880
881 assert_eq!(consumer.inflight.count_ones(..), 0);
882 assert_eq!(consumer.inner.num_inflight(), 0);
883 }
884}