Skip to content

Commit a4e7406

Browse files
committed
Add packed descriptor
Signed-off-by: Wenyu Huang <[email protected]>
1 parent 52b278c commit a4e7406

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed

virtio-queue/src/desc/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use vm_memory::{ByteValued, Le16, Le32, Le64};
44

55
pub mod split;
6+
pub mod packed;
67

78
/// A virtio descriptor's layout constraints with C representation.
89
/// This is a unified representation of the memory layout order
@@ -29,3 +30,9 @@ impl From<Descriptor> for split::Descriptor {
2930
split::Descriptor::new(desc.0.into(), desc.1.into(), desc.2.into(), desc.3.into())
3031
}
3132
}
33+
34+
impl From<Descriptor> for packed::Descriptor {
35+
fn from(desc: Descriptor) -> packed::Descriptor {
36+
packed::Descriptor::new(desc.0.into(), desc.1.into(), desc.2.into(), desc.3.into())
37+
}
38+
}

virtio-queue/src/desc/packed.rs

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
//! packed descriptor
2+
use virtio_bindings::bindings::virtio_ring::{
3+
VRING_DESC_F_INDIRECT, VRING_DESC_F_NEXT, VRING_DESC_F_WRITE,
4+
};
5+
use vm_memory::{ByteValued, GuestAddress, Le16, Le32, Le64};
6+
7+
/// A virtio packed descriptor constraints with C representation.
8+
#[repr(C)]
9+
#[derive(Default, Clone, Copy, Debug)]
10+
pub struct Descriptor {
11+
/// Guest physical address of device specific data.
12+
addr: Le64,
13+
/// Length of device specific data.
14+
len: Le32,
15+
/// Index of descriptor in the descriptor table.
16+
id: Le16,
17+
/// Includes next, write, and indirect bits.
18+
flags: Le16,
19+
}
20+
21+
impl Descriptor {
22+
/// Return the guest physical address of the descriptor buffer.
23+
pub fn addr(&self) -> GuestAddress {
24+
GuestAddress(self.addr.into())
25+
}
26+
/// Return the length of the descriptor buffer.
27+
pub fn len(&self) -> u32 {
28+
self.len.into()
29+
}
30+
/// Return the flags for this descriptor, including next, write and indirect bits.
31+
pub fn flags(&self) -> u16 {
32+
println!("packed flags");
33+
self.flags.into()
34+
}
35+
/// Return the index of the descriptor in the descriptor table.
36+
pub fn id(&self) -> u16 {
37+
self.id.into()
38+
}
39+
/// Check whether this descriptor refers to a buffer containing an indirect descriptor table.
40+
pub fn refers_to_indirect_table(&self) -> bool {
41+
self.flags() & VRING_DESC_F_INDIRECT as u16 != 0
42+
}
43+
/// Check whether the `VIRTQ_DESC_F_NEXT` is set for the descriptor.
44+
pub fn has_next(&self) -> bool {
45+
self.flags() & VRING_DESC_F_NEXT as u16 != 0
46+
}
47+
/// Check if the driver designated this as a write only descriptor.
48+
///
49+
/// If this is false, this descriptor is read only.
50+
/// Write only means the the emulated device can write and the driver can read.
51+
pub fn is_write_only(&self) -> bool {
52+
self.flags() & VRING_DESC_F_WRITE as u16 != 0
53+
}
54+
}
55+
56+
impl Descriptor {
57+
/// Create a new descriptor.
58+
///
59+
/// # Arguments
60+
/// * `addr` - the guest physical address of the descriptor buffer.
61+
/// * `len` - the length of the descriptor buffer.
62+
/// * `flags` - the `flags` for the descriptor.
63+
/// * `next` - the `next` field of the descriptor.
64+
pub fn new(addr: u64, len: u32, id: u16, flags: u16) -> Self {
65+
Descriptor {
66+
addr: addr.into(),
67+
len: len.into(),
68+
id: id.into(),
69+
flags: flags.into(),
70+
}
71+
}
72+
/// Set the guest physical address of the descriptor buffer.
73+
pub fn set_addr(&mut self, addr: u64) {
74+
self.addr = addr.into();
75+
}
76+
/// Set the length of the descriptor buffer.
77+
pub fn set_len(&mut self, len: u32) {
78+
self.len = len.into();
79+
}
80+
/// Set the flags for this descriptor.
81+
pub fn set_flags(&mut self, flags: u16) {
82+
self.flags = flags.into();
83+
}
84+
/// Set the value stored in the `next` field of the descriptor.
85+
pub fn set_id(&mut self, id: u16) {
86+
self.id = id.into();
87+
}
88+
}
89+
90+
unsafe impl ByteValued for Descriptor {}
91+
92+
/// A packed descriptor event constraints with C representation.
93+
#[repr(C)]
94+
#[derive(Clone, Copy, Debug)]
95+
pub struct PackedDescEvent {
96+
off_wrap: Le16,
97+
flags: Le16,
98+
}
99+
100+
impl PackedDescEvent {
101+
/// Set the value stored in the `off_wrap` field.
102+
pub fn set_off_wrap(&mut self, off_wrap: u16) {
103+
self.off_wrap = off_wrap.into();
104+
}
105+
106+
/// Set the value stored in the `flags` field.
107+
pub fn set_flags(&mut self, flags: u16) {
108+
self.flags = flags.into();
109+
}
110+
111+
/// Get the value stored in the `off_wrap` field
112+
pub fn get_off_wrap(&self) -> u16 {
113+
self.off_wrap.into()
114+
}
115+
116+
/// Get the value stored in the `flags` field.
117+
pub fn get_flags(&self) -> u16 {
118+
self.flags.into()
119+
}
120+
}
121+
122+
unsafe impl ByteValued for PackedDescEvent {}
123+
124+
#[cfg(test)]
125+
mod tests {
126+
use super::*;
127+
use memoffset::offset_of;
128+
use std::mem::{align_of, size_of};
129+
#[test]
130+
fn test_descriptor_offset() {
131+
assert_eq!(size_of::<Descriptor>(), 16);
132+
assert_eq!(offset_of!(Descriptor, addr), 0);
133+
assert_eq!(offset_of!(Descriptor, len), 8);
134+
assert_eq!(offset_of!(Descriptor, id), 12);
135+
assert_eq!(offset_of!(Descriptor, flags), 14);
136+
assert!(align_of::<Descriptor>() <= 16);
137+
}
138+
#[test]
139+
fn test_descriptor_getter_setter() {
140+
let mut desc = Descriptor::new(0, 0, 0, 0);
141+
desc.set_addr(0x1000);
142+
assert_eq!(desc.addr(), GuestAddress(0x1000));
143+
desc.set_len(0x2000);
144+
assert_eq!(desc.len(), 0x2000);
145+
desc.set_flags(VRING_DESC_F_NEXT as u16);
146+
assert_eq!(desc.flags(), VRING_DESC_F_NEXT as u16);
147+
assert!(desc.has_next());
148+
assert!(!desc.is_write_only());
149+
assert!(!desc.refers_to_indirect_table());
150+
desc.set_flags(VRING_DESC_F_WRITE as u16);
151+
assert_eq!(desc.flags(), VRING_DESC_F_WRITE as u16);
152+
assert!(!desc.has_next());
153+
assert!(desc.is_write_only());
154+
assert!(!desc.refers_to_indirect_table());
155+
desc.set_flags(VRING_DESC_F_INDIRECT as u16);
156+
assert_eq!(desc.flags(), VRING_DESC_F_INDIRECT as u16);
157+
assert!(!desc.is_write_only());
158+
assert!(desc.refers_to_indirect_table());
159+
}
160+
#[test]
161+
fn test_descriptor_copy() {
162+
let e1 = Descriptor::new(1, 2, 0, 3);
163+
let mut e2 = Descriptor::default();
164+
e2.as_mut_slice().copy_from_slice(e1.as_slice());
165+
assert_eq!(e1.addr(), e2.addr());
166+
assert_eq!(e1.len(), e2.len());
167+
assert_eq!(e1.id(), e2.id());
168+
assert_eq!(e1.flags(), e2.flags());
169+
}
170+
}

0 commit comments

Comments
 (0)