1 use crate::{Error, Queue, QueueT}; 2 use vm_memory::GuestAddress; 3 4 /// Representation of the `Queue` state. 5 /// 6 /// The `QueueState` represents the pure state of the `queue` without tracking any implementation 7 /// details of the queue. The goal with this design is to minimize the changes required to the 8 /// state, and thus the required transitions between states when upgrading or downgrading. 9 /// 10 /// In practice this means that the `QueueState` consists solely of POD (Plain Old Data). 11 /// 12 /// As this structure has all the fields public it is consider to be untrusted. A validated 13 /// queue can be created from the state by calling the associated `try_from` function. 14 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] 15 pub struct QueueState { 16 /// The maximum size in elements offered by the device. 17 pub max_size: u16, 18 /// Tail position of the available ring. 19 pub next_avail: u16, 20 /// Head position of the used ring. 21 pub next_used: u16, 22 /// VIRTIO_F_RING_EVENT_IDX negotiated. 23 pub event_idx_enabled: bool, 24 /// The queue size in elements the driver selected. 25 pub size: u16, 26 /// Indicates if the queue is finished with configuration. 27 pub ready: bool, 28 /// Guest physical address of the descriptor table. 29 pub desc_table: u64, 30 /// Guest physical address of the available ring. 31 pub avail_ring: u64, 32 /// Guest physical address of the used ring. 33 pub used_ring: u64, 34 } 35 36 impl TryFrom<QueueState> for Queue { 37 type Error = Error; 38 try_from(q_state: QueueState) -> Result<Self, Self::Error>39 fn try_from(q_state: QueueState) -> Result<Self, Self::Error> { 40 let mut q = Queue::new(q_state.max_size)?; 41 42 q.set_next_avail(q_state.next_avail); 43 q.set_next_used(q_state.next_used); 44 q.set_event_idx(q_state.event_idx_enabled); 45 q.try_set_size(q_state.size)?; 46 q.set_ready(q_state.ready); 47 q.try_set_desc_table_address(GuestAddress(q_state.desc_table))?; 48 q.try_set_avail_ring_address(GuestAddress(q_state.avail_ring))?; 49 q.try_set_used_ring_address(GuestAddress(q_state.used_ring))?; 50 51 Ok(q) 52 } 53 } 54 55 #[cfg(test)] 56 mod tests { 57 use super::*; 58 create_valid_queue_state() -> QueueState59 fn create_valid_queue_state() -> QueueState { 60 let queue = Queue::new(16).unwrap(); 61 queue.state() 62 } 63 64 #[test] test_empty_queue_state()65 fn test_empty_queue_state() { 66 let max_size = 16; 67 let queue = Queue::new(max_size).unwrap(); 68 69 // Saving the state of a queue on which we didn't do any operation is ok. 70 // Same for restore. 71 let queue_state = queue.state(); 72 let restored_q = Queue::try_from(queue_state).unwrap(); 73 assert_eq!(queue, restored_q); 74 } 75 76 #[test] test_invalid_queue_state()77 fn test_invalid_queue_state() { 78 // Let's generate a state that we know is valid so we can just alter one field at a time. 79 let mut q_state = create_valid_queue_state(); 80 81 // Test invalid max_size. 82 // Size too small. 83 q_state.max_size = 0; 84 assert!(Queue::try_from(q_state).is_err()); 85 // Size too big. 86 q_state.max_size = u16::MAX; 87 assert!(Queue::try_from(q_state).is_err()); 88 // Size not a power of 2. 89 q_state.max_size = 15; 90 assert!(Queue::try_from(q_state).is_err()); 91 92 // Test invalid size. 93 let mut q_state = create_valid_queue_state(); 94 // Size too small. 95 q_state.size = 0; 96 assert!(Queue::try_from(q_state).is_err()); 97 // Size too big. 98 q_state.size = u16::MAX; 99 assert!(Queue::try_from(q_state).is_err()); 100 // Size not a power of 2. 101 q_state.size = 15; 102 assert!(Queue::try_from(q_state).is_err()); 103 104 // Test invalid desc_table. 105 let mut q_state = create_valid_queue_state(); 106 q_state.desc_table = 0xf; 107 assert!(Queue::try_from(q_state).is_err()); 108 109 // Test invalid avail_ring. 110 let mut q_state = create_valid_queue_state(); 111 q_state.avail_ring = 0x1; 112 assert!(Queue::try_from(q_state).is_err()); 113 114 // Test invalid used_ring. 115 let mut q_state = create_valid_queue_state(); 116 q_state.used_ring = 0x3; 117 assert!(Queue::try_from(q_state).is_err()); 118 } 119 } 120