@@ -197,6 +197,14 @@ impl<M: GuestAddressSpace, S: QueueStateT> Queue<M, S> {
197197 self . state . avail_idx ( self . mem . memory ( ) . deref ( ) , order)
198198 }
199199
200+ /// Reads the `idx` field from the used ring.
201+ ///
202+ /// # Arguments
203+ /// * `order` - the memory ordering used to access the `idx` field from memory.
204+ pub fn used_idx ( & self , order : Ordering ) -> Result < Wrapping < u16 > , Error > {
205+ self . state . used_idx ( self . mem . memory ( ) . deref ( ) , order)
206+ }
207+
200208 /// Put a used descriptor head into the used ring.
201209 ///
202210 /// # Arguments
@@ -236,13 +244,26 @@ impl<M: GuestAddressSpace, S: QueueStateT> Queue<M, S> {
236244 self . state . next_avail ( )
237245 }
238246
247+ /// Returns the index for the next descriptor in the used ring.
248+ pub fn next_used ( & self ) -> u16 {
249+ self . state . next_used ( )
250+ }
251+
239252 /// Set the index of the next entry in the available ring.
240253 ///
241254 /// # Arguments
242255 /// * `next_avail` - the index of the next available ring entry.
243256 pub fn set_next_avail ( & mut self , next_avail : u16 ) {
244257 self . state . set_next_avail ( next_avail) ;
245258 }
259+
260+ /// Sets the index for the next descriptor in the used ring.
261+ ///
262+ /// # Arguments
263+ /// * `next_used` - the index of the next used ring entry.
264+ pub fn set_next_used ( & mut self , next_used : u16 ) {
265+ self . state . set_next_used ( next_used) ;
266+ }
246267}
247268
248269impl < M : GuestAddressSpace > Queue < M , QueueState > {
@@ -257,7 +278,7 @@ mod tests {
257278 use super :: * ;
258279 use crate :: defs:: {
259280 DEFAULT_AVAIL_RING_ADDR , DEFAULT_DESC_TABLE_ADDR , DEFAULT_USED_RING_ADDR ,
260- VIRTQ_DESC_F_NEXT , VIRTQ_USED_F_NO_NOTIFY ,
281+ VIRTQ_DESC_F_NEXT , VIRTQ_DESC_F_WRITE , VIRTQ_USED_F_NO_NOTIFY ,
261282 } ;
262283 use crate :: mock:: MockSplitQueue ;
263284 use crate :: Descriptor ;
@@ -348,6 +369,7 @@ mod tests {
348369 let vq = MockSplitQueue :: new ( m, 16 ) ;
349370 let mut q = vq. create_queue ( m) ;
350371
372+ assert_eq ! ( q. used_idx( Ordering :: Acquire ) . unwrap( ) , Wrapping ( 0 ) ) ;
351373 assert_eq ! ( u16 :: from_le( vq. used( ) . idx( ) . load( ) ) , 0 ) ;
352374
353375 // index too large
@@ -357,6 +379,7 @@ mod tests {
357379 // should be ok
358380 q. add_used ( 1 , 0x1000 ) . unwrap ( ) ;
359381 assert_eq ! ( q. state. next_used, Wrapping ( 1 ) ) ;
382+ assert_eq ! ( q. used_idx( Ordering :: Acquire ) . unwrap( ) , Wrapping ( 1 ) ) ;
360383 assert_eq ! ( u16 :: from_le( vq. used( ) . idx( ) . load( ) ) , 1 ) ;
361384
362385 let x = vq. used ( ) . ring ( ) . ref_at ( 0 ) . load ( ) ;
@@ -377,7 +400,7 @@ mod tests {
377400 // Same for `event_idx_enabled`, `next_avail` `next_used` and `signalled_used`.
378401 q. set_event_idx ( true ) ;
379402 q. set_next_avail ( 2 ) ;
380- q. add_used ( 1 , 200 ) . unwrap ( ) ;
403+ q. set_next_used ( 4 ) ;
381404 q. state . signalled_used = Some ( Wrapping ( 15 ) ) ;
382405 assert_eq ! ( q. state. size, 8 ) ;
383406 // `create_queue` also marks the queue as ready.
@@ -533,10 +556,17 @@ mod tests {
533556 i += 1 ;
534557 q. disable_notification ( ) . unwrap ( ) ;
535558
536- while let Some ( _chain) = q. iter ( ) . unwrap ( ) . next ( ) {
537- // Here the device would consume entries from the available ring, add an entry in
538- // the used ring and optionally notify the driver. For the purpose of this test, we
539- // don't need to do anything with the chain, only consume it.
559+ while let Some ( chain) = q. iter ( ) . unwrap ( ) . next ( ) {
560+ // Process the descriptor chain, and then add entries to the
561+ // used ring.
562+ let head_index = chain. head_index ( ) ;
563+ let mut desc_len = 0 ;
564+ chain. for_each ( |d| {
565+ if d. flags ( ) & VIRTQ_DESC_F_WRITE == VIRTQ_DESC_F_WRITE {
566+ desc_len += d. len ( ) ;
567+ }
568+ } ) ;
569+ q. add_used ( head_index, desc_len) . unwrap ( ) ;
540570 }
541571 if !q. enable_notification ( ) . unwrap ( ) {
542572 break ;
@@ -547,6 +577,7 @@ mod tests {
547577 assert_eq ! ( i, 1 ) ;
548578 // The next chain that can be consumed should have index 2.
549579 assert_eq ! ( q. next_avail( ) , 2 ) ;
580+ assert_eq ! ( q. next_used( ) , 2 ) ;
550581 // Let the device know it can consume one more chain.
551582 vq. avail ( ) . idx ( ) . store ( u16:: to_le ( 3 ) ) ;
552583 i = 0 ;
@@ -555,8 +586,17 @@ mod tests {
555586 i += 1 ;
556587 q. disable_notification ( ) . unwrap ( ) ;
557588
558- while let Some ( _chain) = q. iter ( ) . unwrap ( ) . next ( ) {
559- // In a real use case, we would do something with the chain here.
589+ while let Some ( chain) = q. iter ( ) . unwrap ( ) . next ( ) {
590+ // Process the descriptor chain, and then add entries to the
591+ // used ring.
592+ let head_index = chain. head_index ( ) ;
593+ let mut desc_len = 0 ;
594+ chain. for_each ( |d| {
595+ if d. flags ( ) & VIRTQ_DESC_F_WRITE == VIRTQ_DESC_F_WRITE {
596+ desc_len += d. len ( ) ;
597+ }
598+ } ) ;
599+ q. add_used ( head_index, desc_len) . unwrap ( ) ;
560600 }
561601
562602 // For the simplicity of the test we are updating here the `idx` value of the available
@@ -571,21 +611,32 @@ mod tests {
571611 assert_eq ! ( i, 2 ) ;
572612 // The next chain that can be consumed should have index 4.
573613 assert_eq ! ( q. next_avail( ) , 4 ) ;
614+ assert_eq ! ( q. next_used( ) , 4 ) ;
574615
575616 // Set an `idx` that is bigger than the number of entries added in the ring.
576617 // This is an allowed scenario, but the indexes of the chain will have unexpected values.
577618 vq. avail ( ) . idx ( ) . store ( u16:: to_le ( 7 ) ) ;
578619 loop {
579620 q. disable_notification ( ) . unwrap ( ) ;
580621
581- while let Some ( _chain) = q. iter ( ) . unwrap ( ) . next ( ) {
582- // In a real use case, we would do something with the chain here.
622+ while let Some ( chain) = q. iter ( ) . unwrap ( ) . next ( ) {
623+ // Process the descriptor chain, and then add entries to the
624+ // used ring.
625+ let head_index = chain. head_index ( ) ;
626+ let mut desc_len = 0 ;
627+ chain. for_each ( |d| {
628+ if d. flags ( ) & VIRTQ_DESC_F_WRITE == VIRTQ_DESC_F_WRITE {
629+ desc_len += d. len ( ) ;
630+ }
631+ } ) ;
632+ q. add_used ( head_index, desc_len) . unwrap ( ) ;
583633 }
584634 if !q. enable_notification ( ) . unwrap ( ) {
585635 break ;
586636 }
587637 }
588638 assert_eq ! ( q. next_avail( ) , 7 ) ;
639+ assert_eq ! ( q. next_used( ) , 7 ) ;
589640 }
590641
591642 #[ test]
@@ -619,14 +670,22 @@ mod tests {
619670 vq. avail ( ) . idx ( ) . store ( u16:: to_le ( 3 ) ) ;
620671 // No descriptor chains are consumed at this point.
621672 assert_eq ! ( q. next_avail( ) , 0 ) ;
673+ assert_eq ! ( q. next_used( ) , 0 ) ;
622674
623675 loop {
624676 q. disable_notification ( ) . unwrap ( ) ;
625677
626- while let Some ( _chain) = q. iter ( ) . unwrap ( ) . next ( ) {
627- // Here the device would consume entries from the available ring, add an entry in
628- // the used ring and optionally notify the driver. For the purpose of this test, we
629- // don't need to do anything with the chain, only consume it.
678+ while let Some ( chain) = q. iter ( ) . unwrap ( ) . next ( ) {
679+ // Process the descriptor chain, and then add entries to the
680+ // used ring.
681+ let head_index = chain. head_index ( ) ;
682+ let mut desc_len = 0 ;
683+ chain. for_each ( |d| {
684+ if d. flags ( ) & VIRTQ_DESC_F_WRITE == VIRTQ_DESC_F_WRITE {
685+ desc_len += d. len ( ) ;
686+ }
687+ } ) ;
688+ q. add_used ( head_index, desc_len) . unwrap ( ) ;
630689 }
631690 if !q. enable_notification ( ) . unwrap ( ) {
632691 break ;
@@ -635,6 +694,8 @@ mod tests {
635694 // The next chain that can be consumed should have index 3.
636695 assert_eq ! ( q. next_avail( ) , 3 ) ;
637696 assert_eq ! ( q. avail_idx( Ordering :: Acquire ) . unwrap( ) , Wrapping ( 3 ) ) ;
697+ assert_eq ! ( q. next_used( ) , 3 ) ;
698+ assert_eq ! ( q. used_idx( Ordering :: Acquire ) . unwrap( ) , Wrapping ( 3 ) ) ;
638699 assert ! ( q. lock( ) . ready( ) ) ;
639700
640701 // Decrement `idx` which should be forbidden. We don't enforce this thing, but we should
0 commit comments