summaryrefslogtreecommitdiff
path: root/src/vhost_user/message.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/vhost_user/message.rs')
-rw-r--r--src/vhost_user/message.rs210
1 files changed, 201 insertions, 9 deletions
diff --git a/src/vhost_user/message.rs b/src/vhost_user/message.rs
index 32b2f8c..fc33e1b 100644
--- a/src/vhost_user/message.rs
+++ b/src/vhost_user/message.rs
@@ -7,6 +7,7 @@
#![allow(dead_code)]
#![allow(non_camel_case_types)]
+#![allow(clippy::upper_case_acronyms)]
use std::fmt::Debug;
use std::marker::PhantomData;
@@ -140,9 +141,9 @@ pub enum MasterReq {
MAX_CMD = 41,
}
-impl Into<u32> for MasterReq {
- fn into(self) -> u32 {
- self as u32
+impl From<MasterReq> for u32 {
+ fn from(req: MasterReq) -> u32 {
+ req as u32
}
}
@@ -180,9 +181,9 @@ pub enum SlaveReq {
MAX_CMD = 10,
}
-impl Into<u32> for SlaveReq {
- fn into(self) -> u32 {
- self as u32
+impl From<SlaveReq> for u32 {
+ fn from(req: SlaveReq) -> u32 {
+ req as u32
}
}
@@ -222,9 +223,8 @@ bitflags! {
/// Common message header for vhost-user requests and replies.
/// A vhost-user message consists of 3 header fields and an optional payload. All numbers are in the
/// machine native byte order.
-#[allow(safe_packed_borrows)]
#[repr(packed)]
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Copy)]
pub(super) struct VhostUserMsgHeader<R: Req> {
request: u32,
flags: u32,
@@ -232,6 +232,28 @@ pub(super) struct VhostUserMsgHeader<R: Req> {
_r: PhantomData<R>,
}
+impl<R: Req> Debug for VhostUserMsgHeader<R> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("Point")
+ .field("request", &{ self.request })
+ .field("flags", &{ self.flags })
+ .field("size", &{ self.size })
+ .finish()
+ }
+}
+
+impl<R: Req> Clone for VhostUserMsgHeader<R> {
+ fn clone(&self) -> VhostUserMsgHeader<R> {
+ *self
+ }
+}
+
+impl<R: Req> PartialEq for VhostUserMsgHeader<R> {
+ fn eq(&self, other: &Self) -> bool {
+ self.request == other.request && self.flags == other.flags && self.size == other.size
+ }
+}
+
impl<R: Req> VhostUserMsgHeader<R> {
/// Create a new instance of `VhostUserMsgHeader`.
pub fn new(request: R, flags: u32, size: u32) -> Self {
@@ -248,7 +270,7 @@ impl<R: Req> VhostUserMsgHeader<R> {
/// Get message type.
pub fn get_code(&self) -> R {
// It's safe because R is marked as repr(u32).
- unsafe { std::mem::transmute_copy::<u32, R>(&self.request) }
+ unsafe { std::mem::transmute_copy::<u32, R>(&{ self.request }) }
}
/// Set message type.
@@ -673,6 +695,42 @@ impl VhostUserMsgValidator for VhostUserConfig {
/// Payload for the VhostUserConfig message.
pub type VhostUserConfigPayload = Vec<u8>;
+/// Single memory region descriptor as payload for ADD_MEM_REG and REM_MEM_REG
+/// requests.
+#[repr(C)]
+#[derive(Default, Clone)]
+pub struct VhostUserInflight {
+ /// Size of the area to track inflight I/O.
+ pub mmap_size: u64,
+ /// Offset of this area from the start of the supplied file descriptor.
+ pub mmap_offset: u64,
+ /// Number of virtqueues.
+ pub num_queues: u16,
+ /// Size of virtqueues.
+ pub queue_size: u16,
+}
+
+impl VhostUserInflight {
+ /// Create a new instance.
+ pub fn new(mmap_size: u64, mmap_offset: u64, num_queues: u16, queue_size: u16) -> Self {
+ VhostUserInflight {
+ mmap_size,
+ mmap_offset,
+ num_queues,
+ queue_size,
+ }
+ }
+}
+
+impl VhostUserMsgValidator for VhostUserInflight {
+ fn is_valid(&self) -> bool {
+ if self.num_queues == 0 || self.queue_size == 0 {
+ return false;
+ }
+ true
+ }
+}
+
/*
* TODO: support dirty log, live migration and IOTLB operations.
#[repr(packed)]
@@ -744,6 +802,137 @@ impl VhostUserMsgValidator for VhostUserFSSlaveMsg {
}
}
+/// Inflight I/O descriptor state for split virtqueues
+#[repr(packed)]
+#[derive(Clone, Copy, Default)]
+pub struct DescStateSplit {
+ /// Indicate whether this descriptor (only head) is inflight or not.
+ pub inflight: u8,
+ /// Padding
+ padding: [u8; 5],
+ /// List of last batch of used descriptors, only when batching is used for submitting
+ pub next: u16,
+ /// Preserve order of fetching available descriptors, only for head descriptor
+ pub counter: u64,
+}
+
+impl DescStateSplit {
+ /// New instance of DescStateSplit struct
+ pub fn new() -> Self {
+ Self::default()
+ }
+}
+
+/// Inflight I/O queue region for split virtqueues
+#[repr(packed)]
+pub struct QueueRegionSplit {
+ /// Features flags of this region
+ pub features: u64,
+ /// Version of this region
+ pub version: u16,
+ /// Number of DescStateSplit entries
+ pub desc_num: u16,
+ /// List to track last batch of used descriptors
+ pub last_batch_head: u16,
+ /// Idx value of used ring
+ pub used_idx: u16,
+ /// Pointer to an array of DescStateSplit entries
+ pub desc: u64,
+}
+
+impl QueueRegionSplit {
+ /// New instance of QueueRegionSplit struct
+ pub fn new(features: u64, queue_size: u16) -> Self {
+ QueueRegionSplit {
+ features,
+ version: 1,
+ desc_num: queue_size,
+ last_batch_head: 0,
+ used_idx: 0,
+ desc: 0,
+ }
+ }
+}
+
+/// Inflight I/O descriptor state for packed virtqueues
+#[repr(packed)]
+#[derive(Clone, Copy, Default)]
+pub struct DescStatePacked {
+ /// Indicate whether this descriptor (only head) is inflight or not.
+ pub inflight: u8,
+ /// Padding
+ padding: u8,
+ /// Link to next free entry
+ pub next: u16,
+ /// Link to last entry of descriptor list, only for head
+ pub last: u16,
+ /// Length of descriptor list, only for head
+ pub num: u16,
+ /// Preserve order of fetching avail descriptors, only for head
+ pub counter: u64,
+ /// Buffer ID
+ pub id: u16,
+ /// Descriptor flags
+ pub flags: u16,
+ /// Buffer length
+ pub len: u32,
+ /// Buffer address
+ pub addr: u64,
+}
+
+impl DescStatePacked {
+ /// New instance of DescStatePacked struct
+ pub fn new() -> Self {
+ Self::default()
+ }
+}
+
+/// Inflight I/O queue region for packed virtqueues
+#[repr(packed)]
+pub struct QueueRegionPacked {
+ /// Features flags of this region
+ pub features: u64,
+ /// version of this region
+ pub version: u16,
+ /// size of descriptor state array
+ pub desc_num: u16,
+ /// head of free DescStatePacked entry list
+ pub free_head: u16,
+ /// old head of free DescStatePacked entry list
+ pub old_free_head: u16,
+ /// used idx of descriptor ring
+ pub used_idx: u16,
+ /// old used idx of descriptor ring
+ pub old_used_idx: u16,
+ /// device ring wrap counter
+ pub used_wrap_counter: u8,
+ /// old device ring wrap counter
+ pub old_used_wrap_counter: u8,
+ /// Padding
+ padding: [u8; 7],
+ /// Pointer to array tracking state of each descriptor from descriptor ring
+ pub desc: u64,
+}
+
+impl QueueRegionPacked {
+ /// New instance of QueueRegionPacked struct
+ pub fn new(features: u64, queue_size: u16) -> Self {
+ QueueRegionPacked {
+ features,
+ version: 1,
+ desc_num: queue_size,
+ free_head: 0,
+ old_free_head: 0,
+ used_idx: 0,
+ old_used_idx: 0,
+ used_wrap_counter: 0,
+ old_used_wrap_counter: 0,
+ padding: [0; 7],
+ desc: 0,
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -824,7 +1013,10 @@ mod tests {
hdr.set_version(0x1);
assert!(hdr.is_valid());
+ // Test Debug, Clone, PartiaEq trait
assert_eq!(hdr, hdr.clone());
+ assert_eq!(hdr.clone().get_code(), hdr.get_code());
+ assert_eq!(format!("{:?}", hdr.clone()), format!("{:?}", hdr));
}
#[test]