1use alloc::vec;
18
19use bytes::Bytes;
20use fixedbitset::FixedBitSet;
21use smallvec::SmallVec;
22
23use super::*;
24
25type WritableElems = SmallVec<[BufferElement; 2]>;
26
27#[derive(Debug, Clone)]
34pub struct RecvChain {
35 token: Token,
36 segments: Segments,
37}
38
39impl RecvChain {
40 pub fn token(&self) -> Token {
42 self.token
43 }
44
45 pub fn segments(&self) -> &Segments {
47 &self.segments
48 }
49
50 pub fn into_segments(self) -> Segments {
52 self.segments
53 }
54
55 pub fn to_bytes(&self) -> Bytes {
59 self.segments.to_bytes()
60 }
61
62 pub fn into_bytes(self) -> Bytes {
64 self.segments.into_bytes()
65 }
66}
67
68#[must_use = "dropping without completing leaks the descriptor"]
73pub enum ReplyChain<M: MemOps> {
74 Writable(WritableChain<M>),
78 Ack(AckChain),
81}
82
83impl<M: MemOps> ReplyChain<M> {
84 pub fn token(&self) -> Token {
86 match self {
87 ReplyChain::Writable(wc) => wc.token(),
88 ReplyChain::Ack(ack) => ack.token(),
89 }
90 }
91
92 pub fn written(&self) -> usize {
94 match self {
95 ReplyChain::Writable(wc) => wc.written,
96 ReplyChain::Ack(_) => 0,
97 }
98 }
99
100 pub fn into_writable(self) -> Result<WritableChain<M>, AckChain> {
105 match self {
106 ReplyChain::Writable(wc) => Ok(wc),
107 ReplyChain::Ack(ack) => Err(ack),
108 }
109 }
110}
111
112#[must_use = "dropping without completing leaks the descriptor"]
123pub struct WritableChain<M: MemOps> {
124 mem: M,
125 token: Token,
126 elems: WritableElems,
127 capacity: usize,
128 written: usize,
129}
130
131impl<M: MemOps> WritableChain<M> {
132 fn new(mem: M, token: Token, elems: WritableElems) -> Self {
133 let capacity = elems.iter().map(|elem| elem.len as usize).sum();
134 Self {
135 mem,
136 token,
137 elems,
138 capacity,
139 written: 0,
140 }
141 }
142
143 pub fn token(&self) -> Token {
145 self.token
146 }
147
148 pub fn capacity(&self) -> usize {
150 self.capacity
151 }
152
153 pub fn written(&self) -> usize {
155 self.written
156 }
157
158 pub fn remaining(&self) -> usize {
160 self.capacity() - self.written()
161 }
162
163 pub fn write(&mut self, buf: &[u8]) -> Result<usize, VirtqError> {
174 let written = write_elements(&self.mem, &self.elems, self.written, buf)
175 .map_err(|_| VirtqError::MemoryWriteError)?;
176 self.written += written;
177 Ok(written)
178 }
179
180 pub fn write_all(&mut self, buf: &[u8]) -> Result<&mut Self, VirtqError> {
187 if buf.len() > self.remaining() {
188 return Err(VirtqError::ReplyTooLarge);
189 }
190
191 let written = self.write(buf)?;
192 debug_assert_eq!(written, buf.len());
193 Ok(self)
194 }
195
196 pub fn rewind(&mut self) {
201 self.written = 0;
202 }
203}
204
205#[must_use = "dropping without completing leaks the descriptor"]
212pub struct AckChain {
213 token: Token,
214}
215
216impl AckChain {
217 fn new(token: Token) -> Self {
218 Self { token }
219 }
220
221 pub fn token(&self) -> Token {
222 self.token
223 }
224}
225
226pub struct VirtqConsumer<M, N> {
263 inner: RingConsumer<M>,
264 notifier: N,
265 inflight: FixedBitSet,
266 next_token: u32,
267}
268
269impl<M: MemOps + Clone, N: Notifier> VirtqConsumer<M, N> {
270 pub fn new(layout: Layout, mem: M, notifier: N) -> Self {
278 let inner = RingConsumer::new(layout, mem);
279 let inflight = FixedBitSet::with_capacity(inner.len());
280
281 Self {
282 inner,
283 notifier,
284 inflight,
285 next_token: 0,
286 }
287 }
288
289 pub fn poll(
311 &mut self,
312 max_recv_len: usize,
313 ) -> Result<Option<(RecvChain, ReplyChain<M>)>, VirtqError> {
314 let (id, chain) = match self.inner.poll_available() {
315 Ok(x) => x,
316 Err(RingError::WouldBlock) => return Ok(None),
317 Err(e) => return Err(e.into()),
318 };
319
320 let readables = chain.readables();
321 let writables = chain.writables();
322 if readables.is_empty() && writables.is_empty() {
323 return Err(self.abort_chain(id, VirtqError::BadChain));
324 }
325
326 let recv_len = readables
327 .iter()
328 .fold(0usize, |acc, elem| acc.saturating_add(elem.len as usize));
329
330 let id_idx = id as usize;
332 if id_idx >= self.inflight.len() {
333 return Err(VirtqError::InvalidState);
334 }
335
336 if self.inflight.contains(id_idx) {
337 return Err(VirtqError::InvalidState);
338 }
339
340 self.inflight.insert(id_idx);
341 let token = Token {
342 seq: self.next_token,
343 id,
344 };
345 self.next_token = self.next_token.wrapping_add(1);
346
347 if recv_len > max_recv_len {
348 return Err(self.abort_chain(
349 id,
350 VirtqError::PayloadTooLarge {
351 recv: recv_len,
352 limit: max_recv_len,
353 },
354 ));
355 }
356
357 let data = match self.read_elements(readables) {
359 Ok(d) => d,
360 Err(e) => return Err(self.abort_chain(id, e)),
361 };
362
363 let chain = RecvChain {
364 token,
365 segments: data,
366 };
367
368 let reply = if !writables.is_empty() {
369 let mem = self.inner.mem().clone();
370 let writable = WritableChain::new(mem, token, writables.iter().copied().collect());
371 ReplyChain::Writable(writable)
372 } else {
373 let ack = AckChain::new(token);
374 ReplyChain::Ack(ack)
375 };
376
377 Ok(Some((chain, reply)))
378 }
379
380 pub fn complete(&mut self, reply: impl Into<ReplyChain<M>>) -> Result<(), VirtqError> {
387 let reply = reply.into();
388 let id = reply.token().id;
389 let written = u32::try_from(reply.written()).map_err(|_| VirtqError::ReplyTooLarge)?;
390
391 let id_idx = id as usize;
392 let slot_set = id_idx < self.inflight.len() && self.inflight.contains(id_idx);
393 if !slot_set {
394 return Err(VirtqError::InvalidState);
395 }
396
397 self.inflight.set(id_idx, false);
398
399 if self.inner.submit_used_with_notify(id, written)? {
400 self.notifier.notify(QueueStats {
401 num_free: self.inner.num_free(),
402 num_inflight: self.inner.num_inflight(),
403 });
404 }
405
406 Ok(())
407 }
408
409 fn abort_chain(&mut self, id: u16, err: VirtqError) -> VirtqError {
414 let id_idx = id as usize;
415 if id_idx < self.inflight.len() {
416 self.inflight.set(id_idx, false);
417 }
418
419 if let Ok(true) = self.inner.submit_used_with_notify(id, 0) {
422 self.notifier.notify(QueueStats {
423 num_free: self.inner.num_free(),
424 num_inflight: self.inner.num_inflight(),
425 });
426 }
427
428 err
429 }
430
431 #[inline]
436 pub fn avail_cursor(&self) -> RingCursor {
437 self.inner.avail_cursor()
438 }
439
440 #[inline]
445 pub fn used_cursor(&self) -> RingCursor {
446 self.inner.used_cursor()
447 }
448
449 pub fn set_avail_suppression(&mut self, kind: SuppressionKind) -> Result<(), VirtqError> {
468 match kind {
469 SuppressionKind::Enable => self.inner.enable_avail_notifications()?,
470 SuppressionKind::Disable => self.inner.disable_avail_notifications()?,
471 SuppressionKind::Descriptor(cursor) => self
472 .inner
473 .enable_avail_notifications_desc(cursor.head(), cursor.wrap())?,
474 }
475 Ok(())
476 }
477
478 fn read_elements(&self, elems: &[BufferElement]) -> Result<Segments, VirtqError> {
480 let mut segments = SmallVec::<[Bytes; 4]>::new();
481
482 for elem in elems {
483 let mut buf = vec![0u8; elem.len as usize];
484 self.inner
485 .mem()
486 .read(elem.addr, &mut buf)
487 .map_err(|_| VirtqError::MemoryReadError)?;
488 segments.push(Bytes::from(buf));
489 }
490
491 Ok(Segments::from_smallvec(segments))
492 }
493
494 pub fn reset(&mut self) {
496 self.inner.reset();
497 self.inflight.clear();
498 }
499}
500
501fn write_elements<M: MemOps>(
502 mem: &M,
503 elems: &[BufferElement],
504 offset: usize,
505 buf: &[u8],
506) -> Result<usize, M::Error> {
507 let capacity: usize = elems.iter().map(|elem| elem.len as usize).sum();
508 let mut src = &buf[..buf.len().min(capacity.saturating_sub(offset))];
509 let mut written = 0;
510 let mut skip = offset;
511
512 for elem in elems {
513 if src.is_empty() {
514 break;
515 }
516
517 let elem_len = elem.len as usize;
518 if skip >= elem_len {
519 skip -= elem_len;
520 continue;
521 }
522
523 let elem_offset = skip;
524 skip = 0;
525 let n = (elem_len - elem_offset).min(src.len());
526 let addr = elem.addr + elem_offset as u64;
527
528 mem.write(addr, &src[..n])?;
529
530 written += n;
531 src = &src[n..];
532 }
533
534 Ok(written)
535}
536
537impl<M: MemOps> From<WritableChain<M>> for ReplyChain<M> {
538 fn from(wc: WritableChain<M>) -> Self {
539 ReplyChain::Writable(wc)
540 }
541}
542
543impl<M: MemOps> From<AckChain> for ReplyChain<M> {
544 fn from(ack: AckChain) -> Self {
545 ReplyChain::Ack(ack)
546 }
547}
548
549#[cfg(test)]
550mod tests {
551 use super::*;
552 use crate::virtq::ring::tests::{make_producer, make_ring};
553 use crate::virtq::test_utils::*;
554
555 fn poll_data(
556 consumer: &mut VirtqConsumer<crate::virtq::ring::tests::TestMem, TestNotifier>,
557 ) -> (RecvChain, ReplyChain<crate::virtq::ring::tests::TestMem>) {
558 consumer.poll(1024).unwrap().unwrap()
559 }
560
561 #[test]
562 fn test_write_only_recv_is_empty() {
563 let ring = make_ring(16);
564 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
565
566 let se = producer.chain().writable(16).build().unwrap();
567 producer.submit(se).unwrap();
568
569 let (recv, reply) = poll_data(&mut consumer);
570 assert!(recv.to_bytes().is_empty());
571 assert!(matches!(reply, ReplyChain::Writable(_)));
572
573 if let ReplyChain::Writable(mut wc) = reply {
574 wc.write_all(b"response").unwrap();
575 consumer.complete(wc).unwrap();
576 }
577 }
578
579 #[test]
580 fn test_read_only_ack_reply() {
581 let ring = make_ring(16);
582 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
583
584 let mut se = producer.chain().readable(16).build().unwrap();
585 se.write_all(b"hello").unwrap();
586 producer.submit(se).unwrap();
587
588 let (recv, reply) = poll_data(&mut consumer);
589 assert_eq!(recv.to_bytes().as_ref(), b"hello");
590 assert!(matches!(reply, ReplyChain::Ack(_)));
591
592 consumer.complete(reply).unwrap();
593 }
594
595 #[test]
596 fn test_readwrite_round_trip() {
597 let ring = make_ring(16);
598 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
599
600 let mut se = producer.chain().readable(32).writable(64).build().unwrap();
601 se.write_all(b"hello world").unwrap();
602 producer.submit(se).unwrap();
603
604 let (recv, reply) = poll_data(&mut consumer);
605 assert_eq!(recv.to_bytes().as_ref(), b"hello world");
606
607 if let ReplyChain::Writable(mut wc) = reply {
608 assert_eq!(wc.capacity(), 64);
609 assert_eq!(wc.written(), 0);
610 assert_eq!(wc.remaining(), 64);
611 wc.write_all(b"response").unwrap();
612 assert_eq!(wc.written(), 8);
613 assert_eq!(wc.remaining(), 56);
614 consumer.complete(wc).unwrap();
615 } else {
616 panic!("expected Writable reply for recv+reply chain");
617 }
618 }
619
620 #[test]
621 fn test_writable_partial_write() {
622 let ring = make_ring(16);
623 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
624
625 let se = producer.chain().writable(8).build().unwrap();
626 producer.submit(se).unwrap();
627
628 let (_recv, reply) = poll_data(&mut consumer);
629
630 if let ReplyChain::Writable(mut wc) = reply {
631 let n = wc.write(b"hello world!").unwrap();
632 assert_eq!(n, 8);
633 assert_eq!(wc.remaining(), 0);
634 consumer.complete(wc).unwrap();
635 } else {
636 panic!("expected Writable");
637 }
638 }
639
640 #[test]
641 fn test_writable_write_all_too_large() {
642 let ring = make_ring(16);
643 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
644
645 let se = producer.chain().writable(4).build().unwrap();
646 producer.submit(se).unwrap();
647 let (_recv, reply) = poll_data(&mut consumer);
648
649 if let ReplyChain::Writable(mut wc) = reply {
650 let err = wc.write_all(b"too long").err().unwrap();
651 assert!(matches!(err, VirtqError::ReplyTooLarge));
652 } else {
653 panic!("expected Writable");
654 }
655 }
656
657 #[test]
658 fn test_poll_too_large_returns_payload_error() {
659 let ring = make_ring(16);
660 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
661
662 let mut se = producer.chain().readable(8).writable(16).build().unwrap();
663 se.write_all(b"too much").unwrap();
664 producer.submit(se).unwrap();
665
666 assert!(matches!(
667 consumer.poll(4),
668 Err(VirtqError::PayloadTooLarge { recv: 8, limit: 4 })
669 ));
670 }
671
672 #[test]
673 fn test_poll_too_large_returns_descriptor() {
674 let ring = make_ring(16);
675 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
676
677 let mut se = producer.chain().readable(8).writable(16).build().unwrap();
678 se.write_all(b"too much").unwrap();
679 let token = producer.submit(se).unwrap();
680
681 assert!(matches!(
684 consumer.poll(4),
685 Err(VirtqError::PayloadTooLarge { recv: 8, limit: 4 })
686 ));
687
688 let used = producer.poll().unwrap().unwrap();
690 assert_eq!(used.token(), token);
691
692 let se2 = producer.chain().writable(16).build().unwrap();
694 producer.submit(se2).unwrap();
695 let (_recv, reply) = poll_data(&mut consumer);
696 consumer.complete(reply).unwrap();
697 assert!(producer.poll().unwrap().is_some());
698 }
699
700 #[test]
701 fn test_writable_chain_writes_single_segment() {
702 let ring = make_ring(16);
703 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
704
705 let se = producer.chain().writable(16).build().unwrap();
706 producer.submit(se).unwrap();
707 let (_recv, reply) = poll_data(&mut consumer);
708
709 let ReplyChain::Writable(mut wc) = reply else {
710 panic!("expected Writable");
711 };
712 wc.write_all(b"hello").unwrap();
713 consumer.complete(wc).unwrap();
714
715 let used = producer.poll().unwrap().unwrap();
716 assert_eq!(used.to_bytes().unwrap().as_ref(), b"hello");
717 }
718
719 #[test]
720 fn test_writable_rewind() {
721 let ring = make_ring(16);
722 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
723
724 let se = producer.chain().writable(16).build().unwrap();
725 producer.submit(se).unwrap();
726
727 let (_recv, reply) = poll_data(&mut consumer);
728
729 if let ReplyChain::Writable(mut wc) = reply {
730 wc.write_all(b"first").unwrap();
731 assert_eq!(wc.written(), 5);
732 wc.rewind();
733 assert_eq!(wc.written(), 0);
734 assert_eq!(wc.remaining(), 16);
735 wc.write_all(b"second").unwrap();
736 assert_eq!(wc.written(), 6);
737 consumer.complete(wc).unwrap();
738 } else {
739 panic!("expected Writable");
740 }
741 }
742
743 #[test]
744 fn test_writable_reply_scatters_across_segments() {
745 let ring = make_ring(16);
746 let mem = ring.mem();
747 let mut ring_producer = make_producer(&ring);
748 let mut consumer = VirtqConsumer::new(ring.layout(), mem.clone(), TestNotifier::new());
749
750 let base = mem.base_addr() + Layout::query_size(ring.len()) as u64 + 0x100;
751 let chain = BufferChainBuilder::new()
752 .writable(base, 4)
753 .writable(base + 4, 4)
754 .build()
755 .unwrap();
756 let id = ring_producer.submit_available(&chain).unwrap();
757
758 let (recv, reply) = poll_data(&mut consumer);
759 assert!(recv.to_bytes().is_empty());
760
761 let ReplyChain::Writable(mut wc) = reply else {
762 panic!("expected Writable");
763 };
764 assert_eq!(wc.capacity(), 8);
765 wc.write_all(b"abcdefgh").unwrap();
766 assert_eq!(wc.written(), 8);
767 consumer.complete(wc).unwrap();
768
769 let mut first = [0u8; 4];
770 let mut second = [0u8; 4];
771 mem.read(base, &mut first).unwrap();
772 mem.read(base + 4, &mut second).unwrap();
773 assert_eq!(&first, b"abcd");
774 assert_eq!(&second, b"efgh");
775
776 let used = ring_producer.poll_used().unwrap();
777 assert_eq!(used.id, id);
778 assert_eq!(used.len, 8);
779 }
780
781 #[test]
782 fn test_multiple_pending_replies() {
783 let ring = make_ring(16);
784 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
785
786 let se1 = producer.chain().writable(16).build().unwrap();
787 producer.submit(se1).unwrap();
788 let se2 = producer.chain().writable(16).build().unwrap();
789 producer.submit(se2).unwrap();
790
791 let (_e1, c1) = poll_data(&mut consumer);
792 let (_e2, c2) = poll_data(&mut consumer);
793
794 consumer.complete(c2).unwrap();
796 consumer.complete(c1).unwrap();
797 }
798
799 #[test]
800 fn test_recv_into_bytes() {
801 let ring = make_ring(16);
802 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
803
804 let mut se = producer.chain().readable(16).build().unwrap();
805 se.write_all(b"abc").unwrap();
806 producer.submit(se).unwrap();
807
808 let (recv, reply) = poll_data(&mut consumer);
809 let data = recv.into_bytes();
810 assert_eq!(data.as_ref(), b"abc");
811 consumer.complete(reply).unwrap();
812 }
813
814 #[test]
815 fn test_virtq_consumer_reset() {
816 let ring = make_ring(16);
817 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
818
819 let se = producer.chain().writable(16).build().unwrap();
821 producer.submit(se).unwrap();
822
823 let (_recv, reply) = poll_data(&mut consumer);
824 assert!(consumer.inflight.count_ones(..) > 0);
825
826 consumer.complete(reply).unwrap();
828
829 consumer.reset();
830
831 assert_eq!(consumer.inflight.count_ones(..), 0);
832 assert_eq!(consumer.inner.num_inflight(), 0);
833 }
834
835 #[test]
836 fn test_virtq_consumer_reset_clears_inflight() {
837 let ring = make_ring(16);
838 let (mut producer, mut consumer, _notifier) = make_test_producer(&ring);
839
840 let se1 = producer.chain().writable(16).build().unwrap();
842 producer.submit(se1).unwrap();
843 let se2 = producer.chain().writable(16).build().unwrap();
844 producer.submit(se2).unwrap();
845
846 let (_e1, c1) = poll_data(&mut consumer);
847 let (_e2, c2) = poll_data(&mut consumer);
848 consumer.complete(c1).unwrap();
850 consumer.complete(c2).unwrap();
851
852 consumer.reset();
853
854 assert_eq!(consumer.inflight.count_ones(..), 0);
855 assert_eq!(consumer.inner.num_inflight(), 0);
856 }
857}