Skip to content

Commit

Permalink
vhost: add vhost-user GET_BACKEND_SPECS handling
Browse files Browse the repository at this point in the history
This seems like an awful lot of boilerplate (without even any test) to
implement a single message.

Signed-off-by: Alex Bennée <[email protected]>
  • Loading branch information
stsquad committed Jul 10, 2023
1 parent 3c6b1f1 commit b4313a1
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 3 deletions.
24 changes: 23 additions & 1 deletion crates/vhost-user-backend/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use std::io::Result;
use std::ops::Deref;
use std::sync::{Arc, Mutex, RwLock};

use vhost::vhost_user::message::VhostUserProtocolFeatures;
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserBackendSpecs};
use vhost::vhost_user::Slave;
use vm_memory::bitmap::Bitmap;
use vmm_sys_util::epoll::EventSet;
Expand Down Expand Up @@ -54,6 +54,9 @@ where
/// Get available vhost protocol features.
fn protocol_features(&self) -> VhostUserProtocolFeatures;

/// Get the backends specs
fn specs(&self) -> VhostUserBackendSpecs;

/// Enable or disable the virtio EVENT_IDX feature
fn set_event_idx(&self, enabled: bool);

Expand Down Expand Up @@ -135,6 +138,9 @@ where
/// Get available vhost protocol features.
fn protocol_features(&self) -> VhostUserProtocolFeatures;

/// Get specs
fn specs(&self) -> VhostUserBackendSpecs;

/// Enable or disable the virtio EVENT_IDX feature
fn set_event_idx(&mut self, enabled: bool);

Expand Down Expand Up @@ -220,6 +226,10 @@ where
self.deref().protocol_features()
}

fn specs(&self) -> VhostUserBackendSpecs {
self.deref().specs()
}

fn set_event_idx(&self, enabled: bool) {
self.deref().set_event_idx(enabled)
}
Expand Down Expand Up @@ -285,6 +295,10 @@ where
self.lock().unwrap().protocol_features()
}

fn specs(&self) -> VhostUserBackendSpecs {
self.lock().unwrap().specs()
}

fn set_event_idx(&self, enabled: bool) {
self.lock().unwrap().set_event_idx(enabled)
}
Expand Down Expand Up @@ -351,6 +365,10 @@ where
self.read().unwrap().protocol_features()
}

fn specs(&self) -> VhostUserBackendSpecs {
self.read().unwrap().specs()
}

fn set_event_idx(&self, enabled: bool) {
self.write().unwrap().set_event_idx(enabled)
}
Expand Down Expand Up @@ -436,6 +454,10 @@ pub mod tests {
VhostUserProtocolFeatures::all()
}

fn specs(&self) -> VhostUserBackendSpecs {
VhostUserBackendSpecs::new(2, 32, 4, 8)
}

fn set_event_idx(&mut self, enabled: bool) {
self.event_idx = enabled;
}
Expand Down
4 changes: 4 additions & 0 deletions crates/vhost-user-backend/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,10 @@ where
Ok(())
}

fn specs(&self) -> VhostUserResult<vhost::vhost_user::message::VhostUserBackendSpecs> {
Ok(self.backend.specs())
}

fn get_queue_num(&mut self) -> VhostUserResult<u64> {
Ok(self.num_queues as u64)
}
Expand Down
6 changes: 5 additions & 1 deletion crates/vhost-user-backend/tests/vhost-user-server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::sync::{Arc, Barrier, Mutex};
use std::thread;

use vhost::vhost_user::message::{
VhostUserConfigFlags, VhostUserHeaderFlag, VhostUserInflight, VhostUserProtocolFeatures,
VhostUserConfigFlags, VhostUserHeaderFlag, VhostUserInflight, VhostUserProtocolFeatures, VhostUserBackendSpecs,
};
use vhost::vhost_user::{Listener, Master, Slave, VhostUserMaster};
use vhost::{VhostBackend, VhostUserMemoryRegionInfo, VringConfigData};
Expand Down Expand Up @@ -56,6 +56,10 @@ impl VhostUserBackendMut<VringRwLock, ()> for MockVhostBackend {
VhostUserProtocolFeatures::all()
}

fn specs(&self) -> VhostUserBackendSpecs {
VhostUserBackendSpecs::new(1, 32, 4, 8)
}

fn set_event_idx(&mut self, enabled: bool) {
self.event_idx = enabled;
}
Expand Down
5 changes: 5 additions & 0 deletions crates/vhost/src/vhost_user/dummy_slave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ impl VhostUserSlaveReqHandlerMut for DummySlaveReqHandler {
Ok(())
}

fn specs(&self) -> Result<VhostUserBackendSpecs> {
Ok(VhostUserBackendSpecs::new(
1, 2, 3, 4))
}

fn get_queue_num(&mut self) -> Result<u64> {
Ok(MAX_QUEUE_NUM as u64)
}
Expand Down
36 changes: 35 additions & 1 deletion crates/vhost/src/vhost_user/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,10 @@ pub enum MasterReq {
/// Query the backend for its device status as defined in the VIRTIO
/// specification.
GET_STATUS = 40,
/// Query the backend for its emulation specification
GET_BACKEND_SPECS = 41,
/// Upper bound of valid commands.
MAX_CMD = 41,
MAX_CMD = 42,
}

impl From<MasterReq> for u32 {
Expand Down Expand Up @@ -429,6 +431,8 @@ bitflags! {
const STATUS = 0x0001_0000;
/// Support Xen mmap.
const XEN_MMAP = 0x0002_0000;
/// Support GET_BACKEND_SPECS;
const STANDALONE = 0x0004_0000;
}
}

Expand Down Expand Up @@ -667,6 +671,36 @@ impl VhostUserSingleMemoryRegion {
unsafe impl ByteValued for VhostUserSingleMemoryRegion {}
impl VhostUserMsgValidator for VhostUserSingleMemoryRegion {}

/// Supported specs of the backend.
#[repr(C)]
#[derive(Default, Clone, Copy)]
pub struct VhostUserBackendSpecs {
/// VirtIO device ID
device_id: u32,
/// Size of config space
config_size: u32,
/// Minimum number of VQs
min_vqs: u32,
/// Maximum number of VQs
max_vqs: u32,
}

impl VhostUserBackendSpecs {
/// Create a new instance.
pub fn new(device_id: u32, config_size: u32,
min_vqs: u32, max_vqs: u32) -> Self {
VhostUserBackendSpecs {
device_id,
config_size,
min_vqs,
max_vqs,
}
}
}

// SAFETY: Safe because all fields of VhostUserBackendSpecs are POD
unsafe impl ByteValued for VhostUserBackendSpecs {}

/// Vring state descriptor.
#[repr(packed)]
#[derive(Copy, Clone, Default)]
Expand Down
11 changes: 11 additions & 0 deletions crates/vhost/src/vhost_user/slave_req_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub trait VhostUserSlaveReqHandler {

fn get_protocol_features(&self) -> Result<VhostUserProtocolFeatures>;
fn set_protocol_features(&self, features: u64) -> Result<()>;
fn specs(&self) -> Result<VhostUserBackendSpecs>;
fn get_queue_num(&self) -> Result<u64>;
fn set_vring_enable(&self, index: u32, enable: bool) -> Result<()>;
fn get_config(&self, offset: u32, size: u32, flags: VhostUserConfigFlags) -> Result<Vec<u8>>;
Expand Down Expand Up @@ -103,6 +104,7 @@ pub trait VhostUserSlaveReqHandlerMut {

fn get_protocol_features(&mut self) -> Result<VhostUserProtocolFeatures>;
fn set_protocol_features(&mut self, features: u64) -> Result<()>;
fn specs(&self) -> Result<VhostUserBackendSpecs>;
fn get_queue_num(&mut self) -> Result<u64>;
fn set_vring_enable(&mut self, index: u32, enable: bool) -> Result<()>;
fn get_config(
Expand Down Expand Up @@ -192,6 +194,10 @@ impl<T: VhostUserSlaveReqHandlerMut> VhostUserSlaveReqHandler for Mutex<T> {
self.lock().unwrap().set_protocol_features(features)
}

fn specs(&self) -> Result<VhostUserBackendSpecs> {
self.lock().unwrap().specs()
}

fn get_queue_num(&self) -> Result<u64> {
self.lock().unwrap().get_queue_num()
}
Expand Down Expand Up @@ -545,6 +551,11 @@ impl<S: VhostUserSlaveReqHandler> SlaveReqHandler<S> {
let msg = VhostUserU64::new(num.into());
self.send_reply_message(&hdr, &msg)?;
}
Ok(MasterReq::GET_BACKEND_SPECS) => {
self.check_proto_feature(VhostUserProtocolFeatures::STANDALONE)?;
let msg = self.backend.specs()?;
self.send_reply_message(&hdr, &msg)?;
}
_ => {
return Err(Error::InvalidMessage);
}
Expand Down

0 comments on commit b4313a1

Please sign in to comment.