Forráskód Böngészése

Support indirect descriptors in fake queue for tests.

Andrew Walbran 1 éve
szülő
commit
f22e068534
1 módosított fájl, 76 hozzáadás és 23 törlés
  1. 76 23
      src/queue.rs

+ 76 - 23
src/queue.rs

@@ -796,6 +796,7 @@ pub(crate) fn fake_read_write_queue<const QUEUE_SIZE: usize>(
     handler: impl FnOnce(Vec<u8>) -> Vec<u8>,
 ) {
     use core::{ops::Deref, slice};
+    use zerocopy::LayoutVerified;
 
     let available_ring = queue_driver_area as *const AvailRing<QUEUE_SIZE>;
     let used_ring = queue_device_area as *mut UsedRing<QUEUE_SIZE>;
@@ -811,47 +812,99 @@ pub(crate) fn fake_read_write_queue<const QUEUE_SIZE: usize>(
         let head_descriptor_index = (*available_ring).ring[next_slot as usize];
         let mut descriptor = &(*descriptors)[head_descriptor_index as usize];
 
-        // Loop through all input descriptors in the chain, reading data from them.
-        let mut input = Vec::new();
-        while !descriptor.flags.contains(DescFlags::WRITE) {
-            input.extend_from_slice(slice::from_raw_parts(
-                descriptor.addr as *const u8,
-                descriptor.len as usize,
-            ));
+        let input_length;
+        let output;
+        if descriptor.flags.contains(DescFlags::INDIRECT) {
+            // The descriptor shouldn't have any other flags if it is indirect.
+            assert_eq!(descriptor.flags, DescFlags::INDIRECT);
+
+            // Loop through all input descriptors in the indirect descriptor list, reading data from
+            // them.
+            let indirect_descriptor_list: &[Descriptor] = LayoutVerified::new_slice(
+                slice::from_raw_parts(descriptor.addr as *const u8, descriptor.len as usize),
+            )
+            .unwrap()
+            .into_slice();
+            let mut input = Vec::new();
+            let mut indirect_descriptor_index = 0;
+            while indirect_descriptor_index < indirect_descriptor_list.len() {
+                let indirect_descriptor = &indirect_descriptor_list[indirect_descriptor_index];
+                if indirect_descriptor.flags.contains(DescFlags::WRITE) {
+                    break;
+                }
 
-            if let Some(next) = descriptor.next() {
-                descriptor = &(*descriptors)[next as usize];
-            } else {
-                break;
+                input.extend_from_slice(slice::from_raw_parts(
+                    indirect_descriptor.addr as *const u8,
+                    indirect_descriptor.len as usize,
+                ));
+
+                indirect_descriptor_index += 1;
             }
-        }
-        let input_length = input.len();
+            input_length = input.len();
 
-        // Let the test handle the request.
-        let output = handler(input);
+            // Let the test handle the request.
+            output = handler(input);
 
-        // Write the response to the remaining descriptors.
-        let mut remaining_output = output.deref();
-        if descriptor.flags.contains(DescFlags::WRITE) {
-            loop {
-                assert!(descriptor.flags.contains(DescFlags::WRITE));
+            // Write the response to the remaining descriptors.
+            let mut remaining_output = output.deref();
+            while indirect_descriptor_index < indirect_descriptor_list.len() {
+                let indirect_descriptor = &indirect_descriptor_list[indirect_descriptor_index];
+                assert!(indirect_descriptor.flags.contains(DescFlags::WRITE));
 
-                let length_to_write = min(remaining_output.len(), descriptor.len as usize);
+                let length_to_write = min(remaining_output.len(), indirect_descriptor.len as usize);
                 ptr::copy(
                     remaining_output.as_ptr(),
-                    descriptor.addr as *mut u8,
+                    indirect_descriptor.addr as *mut u8,
                     length_to_write,
                 );
                 remaining_output = &remaining_output[length_to_write..];
 
+                indirect_descriptor_index += 1;
+            }
+            assert_eq!(remaining_output.len(), 0);
+        } else {
+            // Loop through all input descriptors in the chain, reading data from them.
+            let mut input = Vec::new();
+            while !descriptor.flags.contains(DescFlags::WRITE) {
+                input.extend_from_slice(slice::from_raw_parts(
+                    descriptor.addr as *const u8,
+                    descriptor.len as usize,
+                ));
+
                 if let Some(next) = descriptor.next() {
                     descriptor = &(*descriptors)[next as usize];
                 } else {
                     break;
                 }
             }
+            input_length = input.len();
+
+            // Let the test handle the request.
+            output = handler(input);
+
+            // Write the response to the remaining descriptors.
+            let mut remaining_output = output.deref();
+            if descriptor.flags.contains(DescFlags::WRITE) {
+                loop {
+                    assert!(descriptor.flags.contains(DescFlags::WRITE));
+
+                    let length_to_write = min(remaining_output.len(), descriptor.len as usize);
+                    ptr::copy(
+                        remaining_output.as_ptr(),
+                        descriptor.addr as *mut u8,
+                        length_to_write,
+                    );
+                    remaining_output = &remaining_output[length_to_write..];
+
+                    if let Some(next) = descriptor.next() {
+                        descriptor = &(*descriptors)[next as usize];
+                    } else {
+                        break;
+                    }
+                }
+            }
+            assert_eq!(remaining_output.len(), 0);
         }
-        assert_eq!(remaining_output.len(), 0);
 
         // Mark the buffer as used.
         (*used_ring).ring[next_slot as usize].id = head_descriptor_index as u32;