Skip to content

Commit

Permalink
Support indirect descriptors in fake queue for tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
qwandor committed Jul 24, 2023
1 parent a480e6a commit f22e068
Showing 1 changed file with 76 additions and 23 deletions.
99 changes: 76 additions & 23 deletions src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand All @@ -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;
Expand Down

0 comments on commit f22e068

Please sign in to comment.