mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-22 11:22:26 +00:00
virtio-devices: Add support for adding a single memory region
Assuming vhost-user devices support CONFIGURE_MEM_SLOTS protocol feature, we introduce a new method to the VirtioDevice trait in order to update one single memory at a time. In case CONFIGURE_MEM_SLOTS is not supported by the backend (feature not acked), we fallback onto the current way of updating the memory mappings, that is with SET_MEM_TABLE. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
4f22f57651
commit
9e53efa3ca
@ -16,7 +16,7 @@ use std::sync::{
|
|||||||
Arc, Barrier,
|
Arc, Barrier,
|
||||||
};
|
};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use vm_memory::{GuestAddress, GuestMemoryAtomic, GuestMemoryMmap, GuestUsize};
|
use vm_memory::{GuestAddress, GuestMemoryAtomic, GuestMemoryMmap, GuestRegionMmap, GuestUsize};
|
||||||
use vm_migration::{MigratableError, Pausable};
|
use vm_migration::{MigratableError, Pausable};
|
||||||
use vm_virtio::VirtioDeviceType;
|
use vm_virtio::VirtioDeviceType;
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
@ -143,6 +143,13 @@ pub trait VirtioDevice: Send {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_memory_region(
|
||||||
|
&mut self,
|
||||||
|
_region: &Arc<GuestRegionMmap>,
|
||||||
|
) -> std::result::Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the list of userspace mappings associated with this device.
|
/// Returns the list of userspace mappings associated with this device.
|
||||||
fn userspace_mappings(&self) -> Vec<UserspaceMapping> {
|
fn userspace_mappings(&self) -> Vec<UserspaceMapping> {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
|
@ -119,6 +119,7 @@ pub enum Error {
|
|||||||
EpollWait(io::Error),
|
EpollWait(io::Error),
|
||||||
FailedSignalingDriver(io::Error),
|
FailedSignalingDriver(io::Error),
|
||||||
VhostUserUpdateMemory(vhost_user::Error),
|
VhostUserUpdateMemory(vhost_user::Error),
|
||||||
|
VhostUserAddMemoryRegion(vhost_user::Error),
|
||||||
EventfdError(io::Error),
|
EventfdError(io::Error),
|
||||||
SetShmRegionsNotSupported,
|
SetShmRegionsNotSupported,
|
||||||
EpollHander(String),
|
EpollHander(String),
|
||||||
|
@ -12,6 +12,7 @@ use crate::VirtioInterrupt;
|
|||||||
use block_util::VirtioBlockConfig;
|
use block_util::VirtioBlockConfig;
|
||||||
use seccomp::{SeccompAction, SeccompFilter};
|
use seccomp::{SeccompAction, SeccompFilter};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::ops::Deref;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
@ -24,7 +25,9 @@ use vhost::vhost_user::{Master, VhostUserMaster, VhostUserMasterReqHandler};
|
|||||||
use vhost::VhostBackend;
|
use vhost::VhostBackend;
|
||||||
use virtio_bindings::bindings::virtio_blk::*;
|
use virtio_bindings::bindings::virtio_blk::*;
|
||||||
use virtio_bindings::bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
|
use virtio_bindings::bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
|
||||||
use vm_memory::{ByteValued, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap};
|
use vm_memory::{
|
||||||
|
ByteValued, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap, GuestRegionMmap,
|
||||||
|
};
|
||||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshottable, Transportable};
|
use vm_migration::{Migratable, MigratableError, Pausable, Snapshottable, Transportable};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
@ -37,6 +40,8 @@ pub struct Blk {
|
|||||||
vhost_user_blk: Master,
|
vhost_user_blk: Master,
|
||||||
config: VirtioBlockConfig,
|
config: VirtioBlockConfig,
|
||||||
seccomp_action: SeccompAction,
|
seccomp_action: SeccompAction,
|
||||||
|
guest_memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||||
|
acked_protocol_features: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Blk {
|
impl Blk {
|
||||||
@ -79,17 +84,21 @@ impl Blk {
|
|||||||
|
|
||||||
// Identify if protocol features are supported by the slave.
|
// Identify if protocol features are supported by the slave.
|
||||||
let mut acked_features = 0;
|
let mut acked_features = 0;
|
||||||
|
let mut acked_protocol_features = 0;
|
||||||
if avail_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() != 0 {
|
if avail_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() != 0 {
|
||||||
acked_features |= VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
|
acked_features |= VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
|
||||||
|
|
||||||
let mut protocol_features = vhost_user_blk
|
let mut protocol_features = vhost_user_blk
|
||||||
.get_protocol_features()
|
.get_protocol_features()
|
||||||
.map_err(Error::VhostUserGetProtocolFeatures)?;
|
.map_err(Error::VhostUserGetProtocolFeatures)?;
|
||||||
protocol_features |= VhostUserProtocolFeatures::MQ;
|
protocol_features &= VhostUserProtocolFeatures::CONFIG
|
||||||
protocol_features &= !VhostUserProtocolFeatures::INFLIGHT_SHMFD;
|
| VhostUserProtocolFeatures::MQ
|
||||||
|
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS;
|
||||||
vhost_user_blk
|
vhost_user_blk
|
||||||
.set_protocol_features(protocol_features)
|
.set_protocol_features(protocol_features)
|
||||||
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
||||||
|
|
||||||
|
acked_protocol_features = protocol_features.bits();
|
||||||
}
|
}
|
||||||
// Get the max queues number from backend, and the queue number set
|
// Get the max queues number from backend, and the queue number set
|
||||||
// should be less than this max queue number.
|
// should be less than this max queue number.
|
||||||
@ -142,6 +151,8 @@ impl Blk {
|
|||||||
vhost_user_blk,
|
vhost_user_blk,
|
||||||
config,
|
config,
|
||||||
seccomp_action,
|
seccomp_action,
|
||||||
|
guest_memory: None,
|
||||||
|
acked_protocol_features,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,6 +217,8 @@ impl VirtioDevice for Blk {
|
|||||||
) -> ActivateResult {
|
) -> ActivateResult {
|
||||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||||
|
|
||||||
|
self.guest_memory = Some(mem.clone());
|
||||||
|
|
||||||
let mut vu_interrupt_list = setup_vhost_user(
|
let mut vu_interrupt_list = setup_vhost_user(
|
||||||
&mut self.vhost_user_blk,
|
&mut self.vhost_user_blk,
|
||||||
&mem.memory(),
|
&mem.memory(),
|
||||||
@ -305,6 +318,22 @@ impl VirtioDevice for Blk {
|
|||||||
fn update_memory(&mut self, mem: &GuestMemoryMmap) -> std::result::Result<(), crate::Error> {
|
fn update_memory(&mut self, mem: &GuestMemoryMmap) -> std::result::Result<(), crate::Error> {
|
||||||
update_mem_table(&mut self.vhost_user_blk, mem).map_err(crate::Error::VhostUserUpdateMemory)
|
update_mem_table(&mut self.vhost_user_blk, mem).map_err(crate::Error::VhostUserUpdateMemory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_memory_region(
|
||||||
|
&mut self,
|
||||||
|
region: &Arc<GuestRegionMmap>,
|
||||||
|
) -> std::result::Result<(), crate::Error> {
|
||||||
|
if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits() != 0
|
||||||
|
{
|
||||||
|
add_memory_region(&mut self.vhost_user_blk, region)
|
||||||
|
.map_err(crate::Error::VhostUserAddMemoryRegion)
|
||||||
|
} else if let Some(guest_memory) = &self.guest_memory {
|
||||||
|
update_mem_table(&mut self.vhost_user_blk, guest_memory.memory().deref())
|
||||||
|
.map_err(crate::Error::VhostUserUpdateMemory)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pausable for Blk {
|
impl Pausable for Blk {
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
// Copyright 2019 Intel Corporation. All Rights Reserved.
|
// Copyright 2019 Intel Corporation. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use super::vu_common_ctrl::{reset_vhost_user, setup_vhost_user, update_mem_table};
|
use super::vu_common_ctrl::{
|
||||||
|
add_memory_region, 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};
|
||||||
use crate::vhost_user::handler::{VhostUserEpollConfig, VhostUserEpollHandler};
|
use crate::vhost_user::handler::{VhostUserEpollConfig, VhostUserEpollHandler};
|
||||||
@ -12,6 +14,7 @@ use crate::{
|
|||||||
use libc::{self, c_void, off64_t, pread64, pwrite64};
|
use libc::{self, c_void, off64_t, pread64, pwrite64};
|
||||||
use seccomp::{SeccompAction, SeccompFilter};
|
use seccomp::{SeccompAction, SeccompFilter};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::ops::Deref;
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
@ -26,7 +29,7 @@ use vhost::vhost_user::{
|
|||||||
use vhost::VhostBackend;
|
use vhost::VhostBackend;
|
||||||
use vm_memory::{
|
use vm_memory::{
|
||||||
Address, ByteValued, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
|
Address, ByteValued, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
|
||||||
GuestMemoryMmap, MmapRegion,
|
GuestMemoryMmap, GuestRegionMmap, MmapRegion,
|
||||||
};
|
};
|
||||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshottable, Transportable};
|
use vm_migration::{Migratable, MigratableError, Pausable, Snapshottable, Transportable};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
@ -274,6 +277,8 @@ pub struct Fs {
|
|||||||
cache: Option<(VirtioSharedMemoryList, MmapRegion)>,
|
cache: Option<(VirtioSharedMemoryList, MmapRegion)>,
|
||||||
slave_req_support: bool,
|
slave_req_support: bool,
|
||||||
seccomp_action: SeccompAction,
|
seccomp_action: SeccompAction,
|
||||||
|
guest_memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||||
|
acked_protocol_features: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fs {
|
impl Fs {
|
||||||
@ -315,6 +320,7 @@ impl Fs {
|
|||||||
|
|
||||||
// Identify if protocol features are supported by the slave.
|
// Identify if protocol features are supported by the slave.
|
||||||
let mut acked_features = 0;
|
let mut acked_features = 0;
|
||||||
|
let mut acked_protocol_features = 0;
|
||||||
if avail_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() != 0 {
|
if avail_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() != 0 {
|
||||||
acked_features |= VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
|
acked_features |= VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
|
||||||
|
|
||||||
@ -322,20 +328,23 @@ impl Fs {
|
|||||||
.get_protocol_features()
|
.get_protocol_features()
|
||||||
.map_err(Error::VhostUserGetProtocolFeatures)?;
|
.map_err(Error::VhostUserGetProtocolFeatures)?;
|
||||||
|
|
||||||
|
let mut supported_protocol_features = VhostUserProtocolFeatures::MQ
|
||||||
|
| VhostUserProtocolFeatures::REPLY_ACK
|
||||||
|
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS;
|
||||||
|
|
||||||
if cache.is_some() {
|
if cache.is_some() {
|
||||||
protocol_features &= VhostUserProtocolFeatures::MQ
|
supported_protocol_features |=
|
||||||
| VhostUserProtocolFeatures::REPLY_ACK
|
VhostUserProtocolFeatures::SLAVE_REQ | VhostUserProtocolFeatures::SLAVE_SEND_FD
|
||||||
| VhostUserProtocolFeatures::SLAVE_REQ
|
|
||||||
| VhostUserProtocolFeatures::SLAVE_SEND_FD;
|
|
||||||
} else {
|
|
||||||
protocol_features &=
|
|
||||||
VhostUserProtocolFeatures::MQ | VhostUserProtocolFeatures::REPLY_ACK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protocol_features &= supported_protocol_features;
|
||||||
|
|
||||||
master
|
master
|
||||||
.set_protocol_features(protocol_features)
|
.set_protocol_features(protocol_features)
|
||||||
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
||||||
|
|
||||||
|
acked_protocol_features = protocol_features.bits();
|
||||||
|
|
||||||
slave_req_support = true;
|
slave_req_support = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,6 +370,8 @@ impl Fs {
|
|||||||
cache,
|
cache,
|
||||||
slave_req_support,
|
slave_req_support,
|
||||||
seccomp_action,
|
seccomp_action,
|
||||||
|
guest_memory: None,
|
||||||
|
acked_protocol_features,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -404,6 +415,8 @@ impl VirtioDevice for Fs {
|
|||||||
) -> ActivateResult {
|
) -> ActivateResult {
|
||||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||||
|
|
||||||
|
self.guest_memory = Some(mem.clone());
|
||||||
|
|
||||||
let kill_evt = self
|
let kill_evt = self
|
||||||
.common
|
.common
|
||||||
.kill_evt
|
.kill_evt
|
||||||
@ -548,6 +561,21 @@ impl VirtioDevice for Fs {
|
|||||||
update_mem_table(&mut self.vu, mem).map_err(crate::Error::VhostUserUpdateMemory)
|
update_mem_table(&mut self.vu, mem).map_err(crate::Error::VhostUserUpdateMemory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_memory_region(
|
||||||
|
&mut self,
|
||||||
|
region: &Arc<GuestRegionMmap>,
|
||||||
|
) -> std::result::Result<(), crate::Error> {
|
||||||
|
if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits() != 0
|
||||||
|
{
|
||||||
|
add_memory_region(&mut self.vu, region).map_err(crate::Error::VhostUserAddMemoryRegion)
|
||||||
|
} else if let Some(guest_memory) = &self.guest_memory {
|
||||||
|
update_mem_table(&mut self.vu, guest_memory.memory().deref())
|
||||||
|
.map_err(crate::Error::VhostUserUpdateMemory)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn userspace_mappings(&self) -> Vec<UserspaceMapping> {
|
fn userspace_mappings(&self) -> Vec<UserspaceMapping> {
|
||||||
let mut mappings = Vec::new();
|
let mut mappings = Vec::new();
|
||||||
if let Some(cache) = self.cache.as_ref() {
|
if let Some(cache) = self.cache.as_ref() {
|
||||||
|
@ -84,9 +84,13 @@ pub enum Error {
|
|||||||
MasterReqHandlerCreation(vhost::vhost_user::Error),
|
MasterReqHandlerCreation(vhost::vhost_user::Error),
|
||||||
/// Set slave request fd failed.
|
/// Set slave request fd failed.
|
||||||
VhostUserSetSlaveRequestFd(vhost::Error),
|
VhostUserSetSlaveRequestFd(vhost::Error),
|
||||||
|
/// Add memory region failed.
|
||||||
|
VhostUserAddMemReg(VhostError),
|
||||||
/// Invalid used address.
|
/// Invalid used address.
|
||||||
UsedAddress,
|
UsedAddress,
|
||||||
/// Invalid features provided from vhost-user backend
|
/// Invalid features provided from vhost-user backend
|
||||||
InvalidFeatures,
|
InvalidFeatures,
|
||||||
|
/// Missing file descriptor for the region.
|
||||||
|
MissingRegionFd,
|
||||||
}
|
}
|
||||||
type Result<T> = std::result::Result<T, Error>;
|
type Result<T> = std::result::Result<T, Error>;
|
||||||
|
@ -14,6 +14,7 @@ use crate::seccomp_filters::{get_seccomp_filter, Thread};
|
|||||||
use crate::VirtioInterrupt;
|
use crate::VirtioInterrupt;
|
||||||
use net_util::MacAddr;
|
use net_util::MacAddr;
|
||||||
use seccomp::{SeccompAction, SeccompFilter};
|
use seccomp::{SeccompAction, SeccompFilter};
|
||||||
|
use std::ops::Deref;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
@ -24,7 +25,9 @@ use vhost::vhost_user::{Master, VhostUserMaster, VhostUserMasterReqHandler};
|
|||||||
use vhost::VhostBackend;
|
use vhost::VhostBackend;
|
||||||
use virtio_bindings::bindings::virtio_net;
|
use virtio_bindings::bindings::virtio_net;
|
||||||
use virtio_bindings::bindings::virtio_ring;
|
use virtio_bindings::bindings::virtio_ring;
|
||||||
use vm_memory::{ByteValued, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap};
|
use vm_memory::{
|
||||||
|
ByteValued, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap, GuestRegionMmap,
|
||||||
|
};
|
||||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshottable, Transportable};
|
use vm_migration::{Migratable, MigratableError, Pausable, Snapshottable, Transportable};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
@ -41,6 +44,8 @@ pub struct Net {
|
|||||||
config: VirtioNetConfig,
|
config: VirtioNetConfig,
|
||||||
ctrl_queue_epoll_thread: Option<thread::JoinHandle<()>>,
|
ctrl_queue_epoll_thread: Option<thread::JoinHandle<()>>,
|
||||||
seccomp_action: SeccompAction,
|
seccomp_action: SeccompAction,
|
||||||
|
guest_memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||||
|
acked_protocol_features: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Net {
|
impl Net {
|
||||||
@ -88,7 +93,7 @@ impl Net {
|
|||||||
.set_features(avail_features)
|
.set_features(avail_features)
|
||||||
.map_err(Error::VhostUserSetFeatures)?;
|
.map_err(Error::VhostUserSetFeatures)?;
|
||||||
|
|
||||||
let protocol_features;
|
let mut protocol_features;
|
||||||
let mut acked_features = 0;
|
let mut acked_features = 0;
|
||||||
if avail_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() != 0 {
|
if avail_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() != 0 {
|
||||||
acked_features |= VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
|
acked_features |= VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
|
||||||
@ -99,11 +104,17 @@ impl Net {
|
|||||||
return Err(Error::VhostUserProtocolNotSupport);
|
return Err(Error::VhostUserProtocolNotSupport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protocol_features &=
|
||||||
|
VhostUserProtocolFeatures::MQ | VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS;
|
||||||
|
|
||||||
|
vhost_user_net
|
||||||
|
.set_protocol_features(protocol_features)
|
||||||
|
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
||||||
|
|
||||||
|
let acked_protocol_features = protocol_features.bits();
|
||||||
|
|
||||||
let max_queue_number =
|
let max_queue_number =
|
||||||
if protocol_features.bits() & VhostUserProtocolFeatures::MQ.bits() != 0 {
|
if protocol_features.bits() & VhostUserProtocolFeatures::MQ.bits() != 0 {
|
||||||
vhost_user_net
|
|
||||||
.set_protocol_features(protocol_features & VhostUserProtocolFeatures::MQ)
|
|
||||||
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
|
||||||
match vhost_user_net.get_queue_num() {
|
match vhost_user_net.get_queue_num() {
|
||||||
Ok(qn) => qn,
|
Ok(qn) => qn,
|
||||||
Err(_) => DEFAULT_QUEUE_NUMBER as u64,
|
Err(_) => DEFAULT_QUEUE_NUMBER as u64,
|
||||||
@ -111,6 +122,7 @@ impl Net {
|
|||||||
} else {
|
} else {
|
||||||
DEFAULT_QUEUE_NUMBER as u64
|
DEFAULT_QUEUE_NUMBER as u64
|
||||||
};
|
};
|
||||||
|
|
||||||
if vu_cfg.num_queues > max_queue_number as usize {
|
if vu_cfg.num_queues > max_queue_number as usize {
|
||||||
error!("vhost-user-net has queue number: {} larger than the max queue number: {} backend allowed\n",
|
error!("vhost-user-net has queue number: {} larger than the max queue number: {} backend allowed\n",
|
||||||
vu_cfg.num_queues, max_queue_number);
|
vu_cfg.num_queues, max_queue_number);
|
||||||
@ -152,6 +164,8 @@ impl Net {
|
|||||||
config,
|
config,
|
||||||
ctrl_queue_epoll_thread: None,
|
ctrl_queue_epoll_thread: None,
|
||||||
seccomp_action,
|
seccomp_action,
|
||||||
|
guest_memory: None,
|
||||||
|
acked_protocol_features,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -196,6 +210,8 @@ impl VirtioDevice for Net {
|
|||||||
) -> ActivateResult {
|
) -> ActivateResult {
|
||||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||||
|
|
||||||
|
self.guest_memory = Some(mem.clone());
|
||||||
|
|
||||||
let queue_num = self.common.queue_evts.as_ref().unwrap().len();
|
let queue_num = self.common.queue_evts.as_ref().unwrap().len();
|
||||||
|
|
||||||
if self
|
if self
|
||||||
@ -360,6 +376,22 @@ impl VirtioDevice for Net {
|
|||||||
fn update_memory(&mut self, mem: &GuestMemoryMmap) -> std::result::Result<(), crate::Error> {
|
fn update_memory(&mut self, mem: &GuestMemoryMmap) -> std::result::Result<(), crate::Error> {
|
||||||
update_mem_table(&mut self.vhost_user_net, mem).map_err(crate::Error::VhostUserUpdateMemory)
|
update_mem_table(&mut self.vhost_user_net, mem).map_err(crate::Error::VhostUserUpdateMemory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_memory_region(
|
||||||
|
&mut self,
|
||||||
|
region: &Arc<GuestRegionMmap>,
|
||||||
|
) -> std::result::Result<(), crate::Error> {
|
||||||
|
if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits() != 0
|
||||||
|
{
|
||||||
|
add_memory_region(&mut self.vhost_user_net, region)
|
||||||
|
.map_err(crate::Error::VhostUserAddMemoryRegion)
|
||||||
|
} else if let Some(guest_memory) = &self.guest_memory {
|
||||||
|
update_mem_table(&mut self.vhost_user_net, guest_memory.memory().deref())
|
||||||
|
.map_err(crate::Error::VhostUserUpdateMemory)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pausable for Net {
|
impl Pausable for Net {
|
||||||
|
@ -11,7 +11,9 @@ use std::sync::Arc;
|
|||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
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::{Address, Error as MmapError, GuestMemory, GuestMemoryMmap, GuestMemoryRegion};
|
use vm_memory::{
|
||||||
|
Address, Error as MmapError, GuestMemory, GuestMemoryMmap, GuestMemoryRegion, GuestRegionMmap,
|
||||||
|
};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -49,6 +51,24 @@ pub fn update_mem_table(vu: &mut Master, mem: &GuestMemoryMmap) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_memory_region(vu: &mut Master, region: &Arc<GuestRegionMmap>) -> Result<()> {
|
||||||
|
let (mmap_handle, mmap_offset) = match region.file_offset() {
|
||||||
|
Some(file_offset) => (file_offset.file().as_raw_fd(), file_offset.start()),
|
||||||
|
None => return Err(Error::MissingRegionFd),
|
||||||
|
};
|
||||||
|
|
||||||
|
let region = VhostUserMemoryRegionInfo {
|
||||||
|
guest_phys_addr: region.start_addr().raw_value(),
|
||||||
|
memory_size: region.len() as u64,
|
||||||
|
userspace_addr: region.as_ptr() as u64,
|
||||||
|
mmap_offset,
|
||||||
|
mmap_handle,
|
||||||
|
};
|
||||||
|
|
||||||
|
vu.add_mem_region(®ion)
|
||||||
|
.map_err(Error::VhostUserAddMemReg)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn setup_vhost_user_vring(
|
pub fn setup_vhost_user_vring(
|
||||||
vu: &mut Master,
|
vu: &mut Master,
|
||||||
mem: &GuestMemoryMmap,
|
mem: &GuestMemoryMmap,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user