Coverage Report

Created: 2026-02-14 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/virtio-queue-0.16.0/src/state.rs
Line
Count
Source
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
39
0
    fn try_from(q_state: QueueState) -> Result<Self, Self::Error> {
40
0
        let mut q = Queue::new(q_state.max_size)?;
41
42
0
        q.set_next_avail(q_state.next_avail);
43
0
        q.set_next_used(q_state.next_used);
44
0
        q.set_event_idx(q_state.event_idx_enabled);
45
0
        q.try_set_size(q_state.size)?;
46
0
        q.set_ready(q_state.ready);
47
0
        q.try_set_desc_table_address(GuestAddress(q_state.desc_table))?;
48
0
        q.try_set_avail_ring_address(GuestAddress(q_state.avail_ring))?;
49
0
        q.try_set_used_ring_address(GuestAddress(q_state.used_ring))?;
50
51
0
        Ok(q)
52
0
    }
53
}
54
55
#[cfg(test)]
56
mod tests {
57
    use super::*;
58
59
    fn create_valid_queue_state() -> QueueState {
60
        let queue = Queue::new(16).unwrap();
61
        queue.state()
62
    }
63
64
    #[test]
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]
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
}