Skip to content

Commit 68a7131

Browse files
virtio: move testing utilities in separate module
Signed-off-by: Cihodaru Alexandru <[email protected]>
1 parent 7965439 commit 68a7131

File tree

4 files changed

+328
-261
lines changed

4 files changed

+328
-261
lines changed

src/devices/src/virtio/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ mod mmio;
1616
pub mod net;
1717
pub mod persist;
1818
mod queue;
19+
pub mod test_utils;
1920
pub mod vsock;
2021

2122
pub use self::balloon::*;

src/devices/src/virtio/persist.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,11 @@ impl Persist<'_> for MmioTransport {
196196
#[cfg(test)]
197197
mod tests {
198198
use super::*;
199-
use crate::virtio::block::device::tests::default_mem;
200199
use crate::virtio::mmio::tests::DummyDevice;
201-
use crate::virtio::{Block, Net, Vsock, VsockUnixBackend};
200+
use crate::virtio::{net, Block, Net, Vsock, VsockUnixBackend};
202201

202+
use crate::virtio::block::test_utils::default_block_with_path;
203+
use crate::virtio::test_utils::default_mem;
203204
use utils::tempfile::TempFile;
204205

205206
const DEFAULT_QUEUE_MAX_SIZE: u16 = 256;
@@ -362,7 +363,6 @@ mod tests {
362363
}
363364

364365
fn default_block() -> (MmioTransport, GuestMemoryMmap, Arc<Mutex<Block>>) {
365-
use crate::virtio::block::device::tests::default_block_with_path;
366366
let mem = default_mem();
367367

368368
// Create backing file.
@@ -377,7 +377,7 @@ mod tests {
377377

378378
fn default_net() -> (MmioTransport, GuestMemoryMmap, Arc<Mutex<Net>>) {
379379
let mem = default_mem();
380-
let net = Arc::new(Mutex::new(Net::default_net()));
380+
let net = Arc::new(Mutex::new(net::test_utils::default_net()));
381381
let mmio_transport = MmioTransport::new(mem.clone(), net.clone());
382382

383383
(mmio_transport, mem, net)

src/devices/src/virtio/queue.rs

Lines changed: 3 additions & 257 deletions
Original file line numberDiff line numberDiff line change
@@ -389,266 +389,12 @@ impl Queue {
389389

390390
#[cfg(test)]
391391
pub(crate) mod tests {
392-
use std::marker::PhantomData;
393-
use std::mem;
394392

395393
pub use super::*;
396-
use crate::virtio::QueueError::{DescIndexOutOfBounds, UsedRing};
397-
use vm_memory::{Bytes, GuestAddress, GuestMemoryMmap};
398-
399-
// Represents a location in GuestMemoryMmap which holds a given type.
400-
pub struct SomeplaceInMemory<'a, T> {
401-
pub location: GuestAddress,
402-
mem: &'a GuestMemoryMmap,
403-
phantom: PhantomData<*const T>,
404-
}
405-
406-
// The ByteValued trait is required to use mem.read_obj_from_addr and write_obj_at_addr.
407-
impl<'a, T> SomeplaceInMemory<'a, T>
408-
where
409-
T: vm_memory::ByteValued,
410-
{
411-
fn new(location: GuestAddress, mem: &'a GuestMemoryMmap) -> Self {
412-
SomeplaceInMemory {
413-
location,
414-
mem,
415-
phantom: PhantomData,
416-
}
417-
}
418-
419-
// Reads from the actual memory location.
420-
pub fn get(&self) -> T {
421-
self.mem.read_obj(self.location).unwrap()
422-
}
423-
424-
// Writes to the actual memory location.
425-
pub fn set(&self, val: T) {
426-
self.mem.write_obj(val, self.location).unwrap()
427-
}
428-
429-
// This function returns a place in memory which holds a value of type U, and starts
430-
// offset bytes after the current location.
431-
fn map_offset<U>(&self, offset: usize) -> SomeplaceInMemory<'a, U> {
432-
SomeplaceInMemory {
433-
location: self.location.checked_add(offset as u64).unwrap(),
434-
mem: self.mem,
435-
phantom: PhantomData,
436-
}
437-
}
438-
439-
// This function returns a place in memory which holds a value of type U, and starts
440-
// immediately after the end of self (which is location + sizeof(T)).
441-
fn next_place<U>(&self) -> SomeplaceInMemory<'a, U> {
442-
self.map_offset::<U>(mem::size_of::<T>())
443-
}
444-
445-
fn end(&self) -> GuestAddress {
446-
self.location
447-
.checked_add(mem::size_of::<T>() as u64)
448-
.unwrap()
449-
}
450-
}
451-
452-
// Represents a virtio descriptor in guest memory.
453-
pub struct VirtqDesc<'a> {
454-
pub addr: SomeplaceInMemory<'a, u64>,
455-
pub len: SomeplaceInMemory<'a, u32>,
456-
pub flags: SomeplaceInMemory<'a, u16>,
457-
pub next: SomeplaceInMemory<'a, u16>,
458-
}
459-
460-
impl<'a> VirtqDesc<'a> {
461-
pub const ALIGNMENT: u64 = 16;
462-
463-
fn new(start: GuestAddress, mem: &'a GuestMemoryMmap) -> Self {
464-
assert_eq!(start.0 & (Self::ALIGNMENT - 1), 0);
465-
466-
let addr = SomeplaceInMemory::new(start, mem);
467-
let len = addr.next_place();
468-
let flags = len.next_place();
469-
let next = flags.next_place();
470-
471-
VirtqDesc {
472-
addr,
473-
len,
474-
flags,
475-
next,
476-
}
477-
}
478-
479-
fn start(&self) -> GuestAddress {
480-
self.addr.location
481-
}
482-
483-
fn end(&self) -> GuestAddress {
484-
self.next.end()
485-
}
486-
487-
pub fn set(&self, addr: u64, len: u32, flags: u16, next: u16) {
488-
self.addr.set(addr);
489-
self.len.set(len);
490-
self.flags.set(flags);
491-
self.next.set(next);
492-
}
493-
494-
pub fn check_data(&self, expected_data: &[u8]) {
495-
assert!(self.len.get() as usize >= expected_data.len());
496-
let mem = self.addr.mem;
497-
let mut buf = vec![0; expected_data.len() as usize];
498-
assert!(mem
499-
.read_slice(&mut buf, GuestAddress::new(self.addr.get()))
500-
.is_ok());
501-
assert_eq!(buf.as_slice(), expected_data);
502-
}
503-
}
504-
505-
// Represents a virtio queue ring. The only difference between the used and available rings,
506-
// is the ring element type.
507-
pub struct VirtqRing<'a, T> {
508-
pub flags: SomeplaceInMemory<'a, u16>,
509-
pub idx: SomeplaceInMemory<'a, u16>,
510-
pub ring: Vec<SomeplaceInMemory<'a, T>>,
511-
pub event: SomeplaceInMemory<'a, u16>,
512-
}
513-
514-
impl<'a, T> VirtqRing<'a, T>
515-
where
516-
T: vm_memory::ByteValued,
517-
{
518-
fn new(
519-
start: GuestAddress,
520-
mem: &'a GuestMemoryMmap,
521-
qsize: u16,
522-
alignment: usize,
523-
) -> Self {
524-
assert_eq!(start.0 & (alignment as u64 - 1), 0);
525-
526-
let flags = SomeplaceInMemory::new(start, mem);
527-
let idx = flags.next_place();
528-
529-
let mut ring = Vec::with_capacity(qsize as usize);
530-
531-
ring.push(idx.next_place());
532-
533-
for _ in 1..qsize as usize {
534-
let x = ring.last().unwrap().next_place();
535-
ring.push(x)
536-
}
537-
538-
let event = ring.last().unwrap().next_place();
539-
540-
flags.set(0);
541-
idx.set(0);
542-
event.set(0);
543394

544-
VirtqRing {
545-
flags,
546-
idx,
547-
ring,
548-
event,
549-
}
550-
}
551-
552-
pub fn end(&self) -> GuestAddress {
553-
self.event.end()
554-
}
555-
}
556-
557-
#[repr(C)]
558-
#[derive(Clone, Copy, Default)]
559-
pub struct VirtqUsedElem {
560-
pub id: u32,
561-
pub len: u32,
562-
}
563-
564-
unsafe impl vm_memory::ByteValued for VirtqUsedElem {}
565-
566-
pub type VirtqAvail<'a> = VirtqRing<'a, u16>;
567-
pub type VirtqUsed<'a> = VirtqRing<'a, VirtqUsedElem>;
568-
569-
pub struct VirtQueue<'a> {
570-
pub dtable: Vec<VirtqDesc<'a>>,
571-
pub avail: VirtqAvail<'a>,
572-
pub used: VirtqUsed<'a>,
573-
}
574-
575-
impl<'a> VirtQueue<'a> {
576-
// We try to make sure things are aligned properly :-s
577-
pub fn new(start: GuestAddress, mem: &'a GuestMemoryMmap, qsize: u16) -> Self {
578-
// power of 2?
579-
assert!(qsize > 0 && qsize & (qsize - 1) == 0);
580-
581-
let mut dtable = Vec::with_capacity(qsize as usize);
582-
583-
let mut end = start;
584-
585-
for _ in 0..qsize {
586-
let d = VirtqDesc::new(end, mem);
587-
end = d.end();
588-
dtable.push(d);
589-
}
590-
591-
const AVAIL_ALIGN: usize = 2;
592-
593-
let avail = VirtqAvail::new(end, mem, qsize, AVAIL_ALIGN);
594-
595-
const USED_ALIGN: u64 = 4;
596-
597-
let mut x = avail.end().0;
598-
x = (x + USED_ALIGN - 1) & !(USED_ALIGN - 1);
599-
600-
let used = VirtqUsed::new(GuestAddress(x), mem, qsize, USED_ALIGN as usize);
601-
602-
VirtQueue {
603-
dtable,
604-
avail,
605-
used,
606-
}
607-
}
608-
609-
pub fn size(&self) -> u16 {
610-
self.dtable.len() as u16
611-
}
612-
613-
fn dtable_start(&self) -> GuestAddress {
614-
self.dtable.first().unwrap().start()
615-
}
616-
617-
fn avail_start(&self) -> GuestAddress {
618-
self.avail.flags.location
619-
}
620-
621-
fn used_start(&self) -> GuestAddress {
622-
self.used.flags.location
623-
}
624-
625-
// Creates a new Queue, using the underlying memory regions represented by the VirtQueue.
626-
pub fn create_queue(&self) -> Queue {
627-
let mut q = Queue::new(self.size());
628-
629-
q.size = self.size();
630-
q.ready = true;
631-
q.desc_table = self.dtable_start();
632-
q.avail_ring = self.avail_start();
633-
q.used_ring = self.used_start();
634-
635-
q
636-
}
637-
638-
pub fn start(&self) -> GuestAddress {
639-
self.dtable_start()
640-
}
641-
642-
pub fn end(&self) -> GuestAddress {
643-
self.used.end()
644-
}
645-
646-
pub fn check_used_elem(&self, used_index: u16, expected_id: u16, expected_len: u32) {
647-
let used_elem = self.used.ring[used_index as usize].get();
648-
assert_eq!(used_elem.id, expected_id as u32);
649-
assert_eq!(used_elem.len, expected_len);
650-
}
651-
}
395+
use crate::virtio::test_utils::VirtQueue;
396+
use crate::virtio::QueueError::{DescIndexOutOfBounds, UsedRing};
397+
use vm_memory::{GuestAddress, GuestMemoryMmap};
652398

653399
#[test]
654400
fn test_checked_new_descriptor_chain() {

0 commit comments

Comments
 (0)