Skip to content

Commit 976cda7

Browse files
committed
Support indirect descriptors in fake queue for tests.
1 parent 87aebbb commit 976cda7

File tree

1 file changed

+76
-23
lines changed

1 file changed

+76
-23
lines changed

src/queue.rs

Lines changed: 76 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ pub(crate) fn fake_read_write_queue<const QUEUE_SIZE: usize>(
785785
handler: impl FnOnce(Vec<u8>) -> Vec<u8>,
786786
) {
787787
use core::{ops::Deref, slice};
788+
use zerocopy::LayoutVerified;
788789

789790
let available_ring = queue_driver_area as *const AvailRing<QUEUE_SIZE>;
790791
let used_ring = queue_device_area as *mut UsedRing<QUEUE_SIZE>;
@@ -800,47 +801,99 @@ pub(crate) fn fake_read_write_queue<const QUEUE_SIZE: usize>(
800801
let head_descriptor_index = (*available_ring).ring[next_slot as usize];
801802
let mut descriptor = &(*descriptors)[head_descriptor_index as usize];
802803

803-
// Loop through all input descriptors in the chain, reading data from them.
804-
let mut input = Vec::new();
805-
while !descriptor.flags.contains(DescFlags::WRITE) {
806-
input.extend_from_slice(slice::from_raw_parts(
807-
descriptor.addr as *const u8,
808-
descriptor.len as usize,
809-
));
804+
let input_length;
805+
let output;
806+
if descriptor.flags.contains(DescFlags::INDIRECT) {
807+
// The descriptor shouldn't have any other flags if it is indirect.
808+
assert_eq!(descriptor.flags, DescFlags::INDIRECT);
809+
810+
// Loop through all input descriptors in the indirect descriptor list, reading data from
811+
// them.
812+
let indirect_descriptor_list: &[Descriptor] = LayoutVerified::new_slice(
813+
slice::from_raw_parts(descriptor.addr as *const u8, descriptor.len as usize),
814+
)
815+
.unwrap()
816+
.into_slice();
817+
let mut input = Vec::new();
818+
let mut indirect_descriptor_index = 0;
819+
while indirect_descriptor_index < indirect_descriptor_list.len() {
820+
let indirect_descriptor = &indirect_descriptor_list[indirect_descriptor_index];
821+
if indirect_descriptor.flags.contains(DescFlags::WRITE) {
822+
break;
823+
}
810824

811-
if let Some(next) = descriptor.next() {
812-
descriptor = &(*descriptors)[next as usize];
813-
} else {
814-
break;
825+
input.extend_from_slice(slice::from_raw_parts(
826+
indirect_descriptor.addr as *const u8,
827+
indirect_descriptor.len as usize,
828+
));
829+
830+
indirect_descriptor_index += 1;
815831
}
816-
}
817-
let input_length = input.len();
832+
input_length = input.len();
818833

819-
// Let the test handle the request.
820-
let output = handler(input);
834+
// Let the test handle the request.
835+
output = handler(input);
821836

822-
// Write the response to the remaining descriptors.
823-
let mut remaining_output = output.deref();
824-
if descriptor.flags.contains(DescFlags::WRITE) {
825-
loop {
826-
assert!(descriptor.flags.contains(DescFlags::WRITE));
837+
// Write the response to the remaining descriptors.
838+
let mut remaining_output = output.deref();
839+
while indirect_descriptor_index < indirect_descriptor_list.len() {
840+
let indirect_descriptor = &indirect_descriptor_list[indirect_descriptor_index];
841+
assert!(indirect_descriptor.flags.contains(DescFlags::WRITE));
827842

828-
let length_to_write = min(remaining_output.len(), descriptor.len as usize);
843+
let length_to_write = min(remaining_output.len(), indirect_descriptor.len as usize);
829844
ptr::copy(
830845
remaining_output.as_ptr(),
831-
descriptor.addr as *mut u8,
846+
indirect_descriptor.addr as *mut u8,
832847
length_to_write,
833848
);
834849
remaining_output = &remaining_output[length_to_write..];
835850

851+
indirect_descriptor_index += 1;
852+
}
853+
assert_eq!(remaining_output.len(), 0);
854+
} else {
855+
// Loop through all input descriptors in the chain, reading data from them.
856+
let mut input = Vec::new();
857+
while !descriptor.flags.contains(DescFlags::WRITE) {
858+
input.extend_from_slice(slice::from_raw_parts(
859+
descriptor.addr as *const u8,
860+
descriptor.len as usize,
861+
));
862+
836863
if let Some(next) = descriptor.next() {
837864
descriptor = &(*descriptors)[next as usize];
838865
} else {
839866
break;
840867
}
841868
}
869+
input_length = input.len();
870+
871+
// Let the test handle the request.
872+
output = handler(input);
873+
874+
// Write the response to the remaining descriptors.
875+
let mut remaining_output = output.deref();
876+
if descriptor.flags.contains(DescFlags::WRITE) {
877+
loop {
878+
assert!(descriptor.flags.contains(DescFlags::WRITE));
879+
880+
let length_to_write = min(remaining_output.len(), descriptor.len as usize);
881+
ptr::copy(
882+
remaining_output.as_ptr(),
883+
descriptor.addr as *mut u8,
884+
length_to_write,
885+
);
886+
remaining_output = &remaining_output[length_to_write..];
887+
888+
if let Some(next) = descriptor.next() {
889+
descriptor = &(*descriptors)[next as usize];
890+
} else {
891+
break;
892+
}
893+
}
894+
}
895+
assert_eq!(remaining_output.len(), 0);
842896
}
843-
assert_eq!(remaining_output.len(), 0);
844897

845898
// Mark the buffer as used.
846899
(*used_ring).ring[next_slot as usize].id = head_descriptor_index as u32;

0 commit comments

Comments
 (0)