mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-22 11:22:26 +00:00
virtio-devices: vhost_user: Factorize features negotiation
Factorize the virtio features and vhost-user protocol features negotiation through a common function that blk, fs and net implementations can directly rely on. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
cdaa4d3ad7
commit
f36b5f3e3c
@ -46,6 +46,9 @@ impl Blk {
|
|||||||
pub fn new(id: String, vu_cfg: VhostUserConfig) -> Result<Blk> {
|
pub fn new(id: String, vu_cfg: VhostUserConfig) -> Result<Blk> {
|
||||||
let num_queues = vu_cfg.num_queues;
|
let num_queues = vu_cfg.num_queues;
|
||||||
|
|
||||||
|
let mut vhost_user_blk = Master::connect(&vu_cfg.socket, num_queues as u64)
|
||||||
|
.map_err(Error::VhostUserCreateMaster)?;
|
||||||
|
|
||||||
// Filling device and vring features VMM supports.
|
// Filling device and vring features VMM supports.
|
||||||
let mut avail_features = 1 << VIRTIO_BLK_F_SEG_MAX
|
let mut avail_features = 1 << VIRTIO_BLK_F_SEG_MAX
|
||||||
| 1 << VIRTIO_BLK_F_RO
|
| 1 << VIRTIO_BLK_F_RO
|
||||||
@ -61,46 +64,16 @@ impl Blk {
|
|||||||
avail_features |= 1 << VIRTIO_BLK_F_MQ;
|
avail_features |= 1 << VIRTIO_BLK_F_MQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut vhost_user_blk = Master::connect(&vu_cfg.socket, num_queues as u64)
|
|
||||||
.map_err(Error::VhostUserCreateMaster)?;
|
|
||||||
|
|
||||||
// Set vhost-user owner.
|
|
||||||
vhost_user_blk
|
|
||||||
.set_owner()
|
|
||||||
.map_err(Error::VhostUserSetOwner)?;
|
|
||||||
|
|
||||||
// Get features from backend, do negotiation to get a feature collection which
|
|
||||||
// both VMM and backend support.
|
|
||||||
let backend_features = vhost_user_blk
|
|
||||||
.get_features()
|
|
||||||
.map_err(Error::VhostUserGetFeatures)?;
|
|
||||||
let acked_features = avail_features & backend_features;
|
|
||||||
// Set features back is required by the vhost crate mechanism, since the
|
|
||||||
// later vhost call will check if features is filled in master before execution.
|
|
||||||
vhost_user_blk
|
|
||||||
.set_features(acked_features)
|
|
||||||
.map_err(Error::VhostUserSetFeatures)?;
|
|
||||||
|
|
||||||
let avail_protocol_features = VhostUserProtocolFeatures::CONFIG
|
let avail_protocol_features = VhostUserProtocolFeatures::CONFIG
|
||||||
| VhostUserProtocolFeatures::MQ
|
| VhostUserProtocolFeatures::MQ
|
||||||
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
||||||
| VhostUserProtocolFeatures::REPLY_ACK;
|
| VhostUserProtocolFeatures::REPLY_ACK;
|
||||||
let acked_protocol_features =
|
|
||||||
if acked_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() != 0 {
|
|
||||||
let backend_protocol_features = vhost_user_blk
|
|
||||||
.get_protocol_features()
|
|
||||||
.map_err(Error::VhostUserGetProtocolFeatures)?;
|
|
||||||
|
|
||||||
let acked_protocol_features = avail_protocol_features & backend_protocol_features;
|
let (acked_features, acked_protocol_features) = negotiate_features_vhost_user(
|
||||||
|
&mut vhost_user_blk,
|
||||||
vhost_user_blk
|
avail_features,
|
||||||
.set_protocol_features(acked_protocol_features)
|
avail_protocol_features,
|
||||||
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
)?;
|
||||||
|
|
||||||
acked_protocol_features.bits()
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
let backend_num_queues =
|
let backend_num_queues =
|
||||||
if acked_protocol_features & VhostUserProtocolFeatures::MQ.bits() != 0 {
|
if acked_protocol_features & VhostUserProtocolFeatures::MQ.bits() != 0 {
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use super::vu_common_ctrl::{
|
use super::vu_common_ctrl::{
|
||||||
add_memory_region, reset_vhost_user, setup_vhost_user, update_mem_table,
|
add_memory_region, negotiate_features_vhost_user, reset_vhost_user, setup_vhost_user,
|
||||||
|
update_mem_table,
|
||||||
};
|
};
|
||||||
use super::{Error, Result};
|
use super::{Error, Result};
|
||||||
use crate::seccomp_filters::{get_seccomp_filter, Thread};
|
use crate::seccomp_filters::{get_seccomp_filter, Thread};
|
||||||
@ -26,7 +27,6 @@ use vhost::vhost_user::message::{
|
|||||||
use vhost::vhost_user::{
|
use vhost::vhost_user::{
|
||||||
HandlerResult, Master, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler,
|
HandlerResult, Master, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler,
|
||||||
};
|
};
|
||||||
use vhost::VhostBackend;
|
|
||||||
use virtio_bindings::bindings::virtio_ring::{
|
use virtio_bindings::bindings::virtio_ring::{
|
||||||
VIRTIO_RING_F_EVENT_IDX, VIRTIO_RING_F_INDIRECT_DESC,
|
VIRTIO_RING_F_EVENT_IDX, VIRTIO_RING_F_INDIRECT_DESC,
|
||||||
};
|
};
|
||||||
@ -312,23 +312,6 @@ impl Fs {
|
|||||||
| 1 << VIRTIO_RING_F_INDIRECT_DESC
|
| 1 << VIRTIO_RING_F_INDIRECT_DESC
|
||||||
| VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
|
| VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
|
||||||
|
|
||||||
// Set vhost-user owner.
|
|
||||||
vhost_user_fs
|
|
||||||
.set_owner()
|
|
||||||
.map_err(Error::VhostUserSetOwner)?;
|
|
||||||
|
|
||||||
// Get features from backend, do negotiation to get a feature collection which
|
|
||||||
// both VMM and backend support.
|
|
||||||
let backend_features = vhost_user_fs
|
|
||||||
.get_features()
|
|
||||||
.map_err(Error::VhostUserGetFeatures)?;
|
|
||||||
let acked_features = avail_features & backend_features;
|
|
||||||
// Set features back is required by the vhost crate mechanism, since the
|
|
||||||
// later vhost call will check if features is filled in master before execution.
|
|
||||||
vhost_user_fs
|
|
||||||
.set_features(acked_features)
|
|
||||||
.map_err(Error::VhostUserSetFeatures)?;
|
|
||||||
|
|
||||||
let mut avail_protocol_features = VhostUserProtocolFeatures::MQ
|
let mut avail_protocol_features = VhostUserProtocolFeatures::MQ
|
||||||
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
||||||
| VhostUserProtocolFeatures::REPLY_ACK;
|
| VhostUserProtocolFeatures::REPLY_ACK;
|
||||||
@ -338,22 +321,11 @@ impl Fs {
|
|||||||
avail_protocol_features |= slave_protocol_features;
|
avail_protocol_features |= slave_protocol_features;
|
||||||
}
|
}
|
||||||
|
|
||||||
let acked_protocol_features =
|
let (acked_features, acked_protocol_features) = negotiate_features_vhost_user(
|
||||||
if acked_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() != 0 {
|
&mut vhost_user_fs,
|
||||||
let backend_protocol_features = vhost_user_fs
|
avail_features,
|
||||||
.get_protocol_features()
|
avail_protocol_features,
|
||||||
.map_err(Error::VhostUserGetProtocolFeatures)?;
|
)?;
|
||||||
|
|
||||||
let acked_protocol_features = avail_protocol_features & backend_protocol_features;
|
|
||||||
|
|
||||||
vhost_user_fs
|
|
||||||
.set_protocol_features(acked_protocol_features)
|
|
||||||
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
|
||||||
|
|
||||||
acked_protocol_features.bits()
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
let backend_num_queues =
|
let backend_num_queues =
|
||||||
if acked_protocol_features & VhostUserProtocolFeatures::MQ.bits() != 0 {
|
if acked_protocol_features & VhostUserProtocolFeatures::MQ.bits() != 0 {
|
||||||
|
@ -91,41 +91,15 @@ impl Net {
|
|||||||
.map_err(Error::VhostUserCreateMaster)?
|
.map_err(Error::VhostUserCreateMaster)?
|
||||||
};
|
};
|
||||||
|
|
||||||
vhost_user_net
|
|
||||||
.set_owner()
|
|
||||||
.map_err(Error::VhostUserSetOwner)?;
|
|
||||||
|
|
||||||
// Get features from backend, do negotiation to get a feature collection which
|
|
||||||
// both VMM and backend support.
|
|
||||||
let backend_features = vhost_user_net
|
|
||||||
.get_features()
|
|
||||||
.map_err(Error::VhostUserGetFeatures)?;
|
|
||||||
let acked_features = avail_features & backend_features;
|
|
||||||
// Set features back is required by the vhost crate mechanism, since the
|
|
||||||
// later vhost call will check if features is filled in master before execution.
|
|
||||||
vhost_user_net
|
|
||||||
.set_features(acked_features)
|
|
||||||
.map_err(Error::VhostUserSetFeatures)?;
|
|
||||||
|
|
||||||
let avail_protocol_features = VhostUserProtocolFeatures::MQ
|
let avail_protocol_features = VhostUserProtocolFeatures::MQ
|
||||||
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
||||||
| VhostUserProtocolFeatures::REPLY_ACK;
|
| VhostUserProtocolFeatures::REPLY_ACK;
|
||||||
let acked_protocol_features =
|
|
||||||
if acked_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() != 0 {
|
|
||||||
let backend_protocol_features = vhost_user_net
|
|
||||||
.get_protocol_features()
|
|
||||||
.map_err(Error::VhostUserGetProtocolFeatures)?;
|
|
||||||
|
|
||||||
let acked_protocol_features = avail_protocol_features & backend_protocol_features;
|
let (acked_features, acked_protocol_features) = negotiate_features_vhost_user(
|
||||||
|
&mut vhost_user_net,
|
||||||
vhost_user_net
|
avail_features,
|
||||||
.set_protocol_features(acked_protocol_features)
|
avail_protocol_features,
|
||||||
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
)?;
|
||||||
|
|
||||||
acked_protocol_features.bits()
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
// If the control queue feature has not been negotiated, let's decrease
|
// If the control queue feature has not been negotiated, let's decrease
|
||||||
// the number of queues.
|
// the number of queues.
|
||||||
@ -138,7 +112,7 @@ impl Net {
|
|||||||
vhost_user_net
|
vhost_user_net
|
||||||
.get_queue_num()
|
.get_queue_num()
|
||||||
.map_err(Error::VhostUserGetQueueMaxNum)? as usize
|
.map_err(Error::VhostUserGetQueueMaxNum)? as usize
|
||||||
} else if backend_features & (1 << virtio_net::VIRTIO_NET_F_CTRL_VQ) != 0 {
|
} else if acked_features & (1 << virtio_net::VIRTIO_NET_F_CTRL_VQ) != 0 {
|
||||||
DEFAULT_QUEUE_NUMBER + 1
|
DEFAULT_QUEUE_NUMBER + 1
|
||||||
} else {
|
} else {
|
||||||
DEFAULT_QUEUE_NUMBER
|
DEFAULT_QUEUE_NUMBER
|
||||||
|
@ -8,6 +8,7 @@ use std::convert::TryInto;
|
|||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
|
||||||
use vhost::vhost_user::{Master, VhostUserMaster};
|
use vhost::vhost_user::{Master, VhostUserMaster};
|
||||||
use vhost::{VhostBackend, VhostUserMemoryRegionInfo, VringConfigData};
|
use vhost::{VhostBackend, VhostUserMemoryRegionInfo, VringConfigData};
|
||||||
use vm_memory::{
|
use vm_memory::{
|
||||||
@ -68,6 +69,42 @@ pub fn add_memory_region(vu: &mut Master, region: &Arc<GuestRegionMmap>) -> Resu
|
|||||||
.map_err(Error::VhostUserAddMemReg)
|
.map_err(Error::VhostUserAddMemReg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn negotiate_features_vhost_user(
|
||||||
|
vu: &mut Master,
|
||||||
|
avail_features: u64,
|
||||||
|
avail_protocol_features: VhostUserProtocolFeatures,
|
||||||
|
) -> Result<(u64, u64)> {
|
||||||
|
// Set vhost-user owner.
|
||||||
|
vu.set_owner().map_err(Error::VhostUserSetOwner)?;
|
||||||
|
|
||||||
|
// Get features from backend, do negotiation to get a feature collection which
|
||||||
|
// both VMM and backend support.
|
||||||
|
let backend_features = vu.get_features().map_err(Error::VhostUserGetFeatures)?;
|
||||||
|
let acked_features = avail_features & backend_features;
|
||||||
|
// Set features back is required by the vhost crate mechanism, since the
|
||||||
|
// later vhost call will check if features is filled in master before execution.
|
||||||
|
vu.set_features(acked_features)
|
||||||
|
.map_err(Error::VhostUserSetFeatures)?;
|
||||||
|
|
||||||
|
let acked_protocol_features =
|
||||||
|
if acked_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() != 0 {
|
||||||
|
let backend_protocol_features = vu
|
||||||
|
.get_protocol_features()
|
||||||
|
.map_err(Error::VhostUserGetProtocolFeatures)?;
|
||||||
|
|
||||||
|
let acked_protocol_features = avail_protocol_features & backend_protocol_features;
|
||||||
|
|
||||||
|
vu.set_protocol_features(acked_protocol_features)
|
||||||
|
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
||||||
|
|
||||||
|
acked_protocol_features.bits()
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((acked_features, acked_protocol_features))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn setup_vhost_user(
|
pub fn setup_vhost_user(
|
||||||
vu: &mut Master,
|
vu: &mut Master,
|
||||||
mem: &GuestMemoryMmap,
|
mem: &GuestMemoryMmap,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user