devices: resync with downstream

This closes the deltas between some of the files of the crate. The
changes include
- Enables building/testing balloon module on windows.
- Suppressing dead-code warnings on windows in cross platform files.
- u16 to enum fix.
- Organizing imports.
- Using Descriptor(windows friendly) over RawDescriptor.
- Using Option<Tube> instead of Tube.
- Fix some args parsing on windows.

BUG=213149155
TEST=presubmit and built on windows downstream

Change-Id: Idd2ee81384bc5fade610aa864b2c712ea0a0e0d2
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3783010
Tested-by: Vikram Auradkar <auradkar@google.com>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Commit-Queue: Vikram Auradkar <auradkar@google.com>
Auto-Submit: Vikram Auradkar <auradkar@google.com>
This commit is contained in:
Vikram Auradkar 2022-07-22 02:38:15 +00:00 committed by crosvm LUCI
parent 15e1e977d2
commit 02028483bc
27 changed files with 167 additions and 148 deletions

View file

@ -66,7 +66,8 @@ sync = { path = "../common/sync" }
system_api = { version = "*", optional = true }
thiserror = "1.0.20"
tpm2 = { path = "../tpm2", optional = true }
uuid = { version = "0.8.2" }
tracing = { path = "../tracing" }
uuid = { version = "0.8.2", features = [ "serde" ] }
vhost = { path = "../vhost" }
vmm_vhost = { path = "../third_party/vmm_vhost", features = ["vmm", "device", "vfio-device"] }
virtio_sys = { path = "../virtio_sys" }
@ -87,8 +88,9 @@ vfio_sys = { path = "../vfio_sys" }
[target.'cfg(windows)'.dependencies]
broker_ipc = { path = "../broker_ipc" }
chrono = "*"
tracing = { path = "../tracing" }
metrics = { path = "../metrics" }
tube_transporter = { path = "../tube_transporter" }
win_util = { path = "../win_util"}
winapi = "*"
[dependencies.futures]

View file

@ -192,6 +192,7 @@ impl DelayedIoApicIrqEvents {
}
}
#[cfg_attr(windows, allow(dead_code))]
#[cfg(test)]
/// This module contains tests that apply to any implementations of IrqChipX86_64
pub(super) mod tests {

View file

@ -75,7 +75,7 @@ pub const PCI_VENDOR_ID_INTEL: u16 = 0x8086;
pub const PCI_VENDOR_ID_REDHAT: u16 = 0x1b36;
#[repr(u16)]
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum CrosvmDeviceId {
Pit = 1,
Pic = 2,
@ -118,7 +118,8 @@ impl TryFrom<u16> for CrosvmDeviceId {
14 => Ok(CrosvmDeviceId::DirectMmio),
15 => Ok(CrosvmDeviceId::DirectIo),
16 => Ok(CrosvmDeviceId::UserspaceIrqChip),
17 => Ok(CrosvmDeviceId::Pflash),
17 => Ok(CrosvmDeviceId::VmWatchdog),
18 => Ok(CrosvmDeviceId::Pflash),
_ => Err(base::Error::new(EINVAL)),
}
}

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#![cfg_attr(windows, allow(dead_code))]
use base::{error, AsRawDescriptor, Event, RawDescriptor, Tube};
use bit_field::*;
use data_model::DataInit;

View file

@ -12,8 +12,6 @@ use std::sync::Arc;
use std::thread::{self};
use base::{error, Event, Result};
#[cfg(windows)]
use base::{named_pipes, FileSync};
use crate::bus::BusAccessInfo;
use crate::pci::CrosvmDeviceId;

View file

@ -8,9 +8,8 @@ use std::thread::{self, JoinHandle};
use std::time::Duration;
use base::{
error,
named_pipes::{self, PipeConnection},
Event, EventToken, FileSync, RawDescriptor, Result, WaitContext,
error, named_pipes::PipeConnection, Event, EventToken, FileSync, RawDescriptor, Result,
WaitContext,
};
use hypervisor::ProtectionType;
@ -117,7 +116,7 @@ impl SerialDevice for Serial {
out: Option<Box<dyn io::Write + Send>>,
sync: Option<Box<dyn FileSync + Send>>,
out_timestamp: bool,
keep_rds: Vec<RawDescriptor>,
_keep_rds: Vec<RawDescriptor>,
) -> Serial {
let system_params = SystemSerialParams {
out_timestamp,
@ -137,9 +136,9 @@ impl SerialDevice for Serial {
fn new_with_pipe(
_protected_vm: ProtectionType,
interrupt_evt: Event,
pipe_in: named_pipes::PipeConnection,
pipe_out: named_pipes::PipeConnection,
keep_rds: Vec<RawDescriptor>,
pipe_in: PipeConnection,
pipe_out: PipeConnection,
_keep_rds: Vec<RawDescriptor>,
) -> Serial {
let system_params = SystemSerialParams {
out_timestamp: false,
@ -238,8 +237,6 @@ mod tests {
use super::*;
use regex::Regex;
use std::sync::Arc;
use sync::Mutex;
use crate::serial::tests::*;
use crate::serial::*;

View file

@ -3,9 +3,7 @@
// found in the LICENSE file.
use super::error::{Error, Result};
use base::{
error, warn, AsRawDescriptor, Descriptor, Event, EventType, RawDescriptor, WaitContext,
};
use base::{error, warn, AsRawDescriptor, Descriptor, Event, EventType, WaitContext};
use std::collections::BTreeMap;
use std::mem::drop;
use std::sync::{Arc, Weak};
@ -41,7 +39,7 @@ impl FailHandle for Option<Arc<dyn FailHandle>> {
pub struct EventLoop {
fail_handle: Option<Arc<dyn FailHandle>>,
poll_ctx: Arc<WaitContext<Descriptor>>,
handlers: Arc<Mutex<BTreeMap<RawDescriptor, Weak<dyn EventHandler>>>>,
handlers: Arc<Mutex<BTreeMap<Descriptor, Weak<dyn EventHandler>>>>,
stop_evt: Event,
}
@ -60,7 +58,7 @@ impl EventLoop {
.and_then(|e| Ok((e.try_clone()?, e)))
.map_err(Error::CreateEvent)?;
let fd_callbacks: Arc<Mutex<BTreeMap<RawDescriptor, Weak<dyn EventHandler>>>> =
let fd_callbacks: Arc<Mutex<BTreeMap<Descriptor, Weak<dyn EventHandler>>>> =
Arc::new(Mutex::new(BTreeMap::new()));
let poll_ctx: WaitContext<Descriptor> = WaitContext::new()
.and_then(|pc| {
@ -100,7 +98,7 @@ impl EventLoop {
}
let mut locked = fd_callbacks.lock();
let weak_handler = match locked.get(&fd) {
let weak_handler = match locked.get(&Descriptor(fd)) {
Some(cb) => cb.clone(),
None => {
warn!("callback for fd {} already removed", fd);
@ -127,7 +125,7 @@ impl EventLoop {
if remove {
let _ = poll_ctx.delete(&event.token);
let _ = locked.remove(&fd);
let _ = locked.remove(&Descriptor(fd));
}
}
}
@ -154,7 +152,7 @@ impl EventLoop {
}
self.handlers
.lock()
.insert(descriptor.as_raw_descriptor(), handler);
.insert(Descriptor(descriptor.as_raw_descriptor()), handler);
// This might fail due to epoll syscall. Check epoll_ctl(2).
self.poll_ctx
.add_for_event(
@ -176,7 +174,9 @@ impl EventLoop {
self.poll_ctx
.delete(descriptor)
.map_err(Error::WaitContextDeleteDescriptor)?;
self.handlers.lock().remove(&descriptor.as_raw_descriptor());
self.handlers
.lock()
.remove(&Descriptor(descriptor.as_raw_descriptor()));
Ok(())
}

View file

@ -4,6 +4,8 @@
//! Provides helpers that make it easier to process virtio queues on an async executor.
#![cfg_attr(windows, allow(dead_code))]
use anyhow::{bail, Context};
use async_task::Task;
use base::warn;

View file

@ -491,7 +491,7 @@ fn run_worker(
&guest_address,
len,
#[cfg(windows)]
dynamic_mapping_tube,
&dynamic_mapping_tube,
#[cfg(unix)]
&mem,
)
@ -511,7 +511,7 @@ fn run_worker(
&guest_address,
len,
#[cfg(windows)]
dynamic_mapping_tube,
&dynamic_mapping_tube,
)
},
);
@ -571,7 +571,7 @@ fn run_worker(
/// Virtio device for memory balloon inflation/deflation.
pub struct Balloon {
command_tube: Tube,
command_tube: Option<Tube>,
#[cfg(windows)]
dynamic_mapping_tube: Option<Tube>,
inflate_tube: Option<Tube>,
@ -616,7 +616,7 @@ impl Balloon {
};
Ok(Balloon {
command_tube,
command_tube: Some(command_tube),
#[cfg(windows)]
dynamic_mapping_tube: Some(dynamic_mapping_tube),
inflate_tube,
@ -662,7 +662,10 @@ impl Drop for Balloon {
impl VirtioDevice for Balloon {
fn keep_rds(&self) -> Vec<RawDescriptor> {
let mut rds = vec![self.command_tube.as_raw_descriptor()];
let mut rds = Vec::new();
if let Some(command_tube) = &self.command_tube {
rds.push(command_tube.as_raw_descriptor());
}
if let Some(inflate_tube) = &self.inflate_tube {
rds.push(inflate_tube.as_raw_descriptor());
}
@ -723,8 +726,10 @@ impl VirtioDevice for Balloon {
let state = self.state.clone();
// TODO(b/222588331): this relies on Tube::try_clone working
#[cfg(unix)]
#[allow(deprecated)]
let command_tube = match self.command_tube.try_clone() {
let command_tube = match self.command_tube.as_ref().unwrap().try_clone() {
Ok(tube) => tube,
Err(e) => {
error!("failed to clone command tube {:?}", e);
@ -732,6 +737,8 @@ impl VirtioDevice for Balloon {
}
};
#[cfg(windows)]
let command_tube = self.command_tube.take().unwrap();
#[cfg(windows)]
let mapping_tube = self.dynamic_mapping_tube.take().unwrap();
let inflate_tube = self.inflate_tube.take();
let worker_result = thread::Builder::new()

View file

@ -34,15 +34,19 @@ pub(in crate::virtio::balloon) async fn send_adjusted_response_async(
pub(in crate::virtio::balloon) fn send_adjusted_response_if_needed(
state: &Arc<AsyncMutex<BalloonState>>,
command_tube: &Tube,
command_tube: &Option<Tube>,
config: virtio_balloon_config,
) {
let mut state = block_on(state.lock());
state.actual_pages = config.actual.to_native();
if state.failable_update && state.actual_pages == state.num_pages {
state.failable_update = false;
if let Err(e) = send_adjusted_response(command_tube, state.num_pages) {
error!("Failed to send response {:?}", e);
if let Some(ref command_tube) = command_tube {
if let Err(e) = send_adjusted_response(command_tube, state.num_pages) {
error!("Failed to send response {:?}", e);
}
} else {
panic!("Command tube missing!");
}
}
}

View file

@ -6,9 +6,9 @@ use std::sync::Arc;
use balloon_control::BalloonTubeResult;
use base::{warn, Tube};
use cros_async::{AsyncMutex, AsyncTube};
use cros_async::{block_on, sync::Mutex as AsyncMutex, AsyncTube};
use vm_control::{VmMemoryRequest, VmMemoryResponse};
use vm_memory::{GuestAddress, GuestMemory};
use vm_memory::GuestAddress;
use crate::virtio::balloon::virtio_balloon_config;
use crate::virtio::balloon::{BalloonState, VIRTIO_BALLOON_PFN_SHIFT};
@ -22,12 +22,12 @@ pub(in crate::virtio::balloon) fn send_adjusted_response(
Ok(())
}
pub(in crate::virtio::balloon) async fn send_adjusted_response_if_needed(
pub(in crate::virtio::balloon) fn send_adjusted_response_if_needed(
state: &Arc<AsyncMutex<BalloonState>>,
_command_tube: &Tube,
_command_tube: &Option<Tube>,
config: virtio_balloon_config,
) {
let mut state = block_on(self.state.lock());
let mut state = block_on(state.lock());
state.actual_pages = config.actual.to_native();
}
@ -45,7 +45,10 @@ pub(in crate::virtio::balloon) fn free_memory(
len: u64,
dynamic_mapping_tube: &Tube,
) {
let request = VmMemoryRequest::DynamicallyFreeMemoryRange { guest_address, len };
let request = VmMemoryRequest::DynamicallyFreeMemoryRange {
guest_address: *guest_address,
size: len,
};
if let Err(e) = dynamic_mapping_tube.send(&request) {
warn!(
"Failed to send free memory request. Marking pages unused failed: {}, addr={}",
@ -61,8 +64,15 @@ pub(in crate::virtio::balloon) fn free_memory(
}
}
pub(in crate::virtio::balloon) fn reclaim_memory(guest_address: &GuestAddress, len: u64) {
let request = VmMemoryRequest::DynamicallyReclaimMemoryRange { guest_address, len };
pub(in crate::virtio::balloon) fn reclaim_memory(
guest_address: &GuestAddress,
len: u64,
dynamic_mapping_tube: &Tube,
) {
let request = VmMemoryRequest::DynamicallyReclaimMemoryRange {
guest_address: *guest_address,
size: len,
};
if let Err(e) = dynamic_mapping_tube.send(&request) {
warn!(
"Failed to send reclaim memory request. Marking pages used failed: {}, addr={}",

View file

@ -13,11 +13,11 @@ use std::thread;
use std::time::Duration;
use std::u32;
#[cfg(unix)]
use base::AsRawDescriptor;
use base::Error as SysError;
use base::Result as SysResult;
use base::{
error, info, warn, AsRawDescriptor, Event, EventToken, RawDescriptor, Timer, Tube, WaitContext,
};
use base::{error, info, warn, Event, EventToken, RawDescriptor, Timer, Tube, WaitContext};
use data_model::DataInit;
use disk::DiskFile;
@ -140,7 +140,7 @@ fn deserialize_disk_id<'de, D: Deserializer<'de>>(
Ok(Some(ret))
}
#[derive(Debug, Serialize, Deserialize, PartialEq, serde_keyvalue::FromKeyValues)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, serde_keyvalue::FromKeyValues)]
#[serde(deny_unknown_fields)]
pub struct DiskOption {
pub path: PathBuf,
@ -657,6 +657,8 @@ impl VirtioDevice for Block {
keep_rds.extend(disk_image.as_raw_descriptors());
}
// TODO: b/143318939 uncomment this when msgOnSocket is ported
#[cfg(unix)]
if let Some(control_tube) = &self.control_tube {
keep_rds.push(control_tube.as_raw_descriptor());
}
@ -1142,6 +1144,24 @@ mod tests {
}
);
// io_concurrency
#[cfg(windows)]
{
let params = from_block_arg("/some/path.img,io_concurrency=4").unwrap();
assert_eq!(
params,
DiskOption {
path: "/some/path.img".into(),
read_only: false,
sparse: true,
o_direct: false,
block_size: 512,
id: None,
io_concurrency: NonZeroU32::new(4).unwrap(),
}
);
}
// id
let params = from_block_arg("/some/path.img,id=DISK").unwrap();
assert_eq!(

View file

@ -146,6 +146,7 @@ struct State {
page_mask: u64,
// Hot-pluggable PCI endpoints ranges
// RangeInclusive: (start endpoint PCI address .. =end endpoint PCI address)
#[cfg_attr(windows, allow(dead_code))]
hp_endpoints_ranges: Vec<RangeInclusive<u32>>,
// All PCI endpoints that attach to certain IOMMU domain
// key: endpoint PCI address

View file

@ -24,6 +24,7 @@
//! doc, "Arrays of sizes from 0 to 32 (inclusive) implement the Default trait
//! if the element type allows it."
#![cfg_attr(windows, allow(dead_code))]
#![allow(non_camel_case_types)]
use data_model::{DataInit, Le16, Le32, Le64};

View file

@ -11,16 +11,16 @@ use cros_async::AsyncTube;
use crate::virtio::iommu::{Result, State};
pub(in crate::virtio::iommu) async fn handle_command_tube(
state: &Rc<RefCell<State>>,
command_tube: AsyncTube,
_state: &Rc<RefCell<State>>,
_command_tube: AsyncTube,
) -> Result<()> {
panic!("IOMMU is not supported on Windows");
}
pub(in crate::virtio::iommu) async fn handle_translate_request(
state: &Rc<RefCell<State>>,
request_tube: Option<AsyncTube>,
response_tubes: Option<BTreeMap<u32, AsyncTube>>,
_state: &Rc<RefCell<State>>,
_request_tube: Option<AsyncTube>,
_response_tubes: Option<BTreeMap<u32, AsyncTube>>,
) -> Result<()> {
// TODO nkgold (b/222588331): the below implementation assures AsyncTube::send is sync, where it
// should be async (as it is on Windows). Once that's fixed there's no reason this function

View file

@ -6,6 +6,7 @@
mod async_device;
mod async_utils;
mod balloon;
mod descriptor_utils;
mod input;
mod interrupt;
@ -27,6 +28,7 @@ pub mod resource_bridge;
pub mod snd;
pub mod vhost;
pub use self::balloon::*;
pub use self::block::*;
pub use self::console::*;
pub use self::descriptor_utils::Error as DescriptorError;
@ -44,7 +46,6 @@ pub use self::virtio_device::*;
pub use self::virtio_pci_device::*;
cfg_if::cfg_if! {
if #[cfg(unix)] {
mod balloon;
mod p9;
mod pmem;
pub mod wl;
@ -54,7 +55,6 @@ cfg_if::cfg_if! {
pub mod gpu;
pub mod net;
pub use self::balloon::*;
#[cfg(feature = "gpu")]
pub use self::gpu::*;
pub use self::iommu::sys::unix::vfio_wrapper;

View file

@ -254,6 +254,11 @@ impl<'a, 'b> Iterator for AvailIter<'a, 'b> {
#[derive(Clone)]
/// A virtio queue's parameters.
///
/// WARNING: it is NOT safe to clone and then use n>1 Queue(s) to interact with the same virtqueue.
/// That will prevent descriptor index tracking from being accurate, which can cause incorrect
/// interrupt masking.
/// TODO(b/201119859) drop Clone from this struct.
pub struct Queue {
/// The maximal size in elements offered by the device
pub max_size: u16,
@ -773,6 +778,7 @@ mod tests {
use super::super::Interrupt;
use super::*;
use crate::IrqLevelEvent;
use memoffset::offset_of;
use std::convert::TryInto;
use std::sync::atomic::AtomicUsize;
use std::sync::Arc;
@ -879,10 +885,8 @@ mod tests {
10,
);
// Calculating the offset of used_event within Avail structure
#[allow(deref_nullptr)]
let used_event_offset: u64 =
unsafe { &(*(::std::ptr::null::<Avail>())).used_event as *const _ as u64 };
// Offset of used_event within Avail structure
let used_event_offset = offset_of!(Avail, used_event) as u64;
let used_event_address = GuestAddress(AVAIL_OFFSET + used_event_offset);
// Assume driver submit 0x100 req to device,
@ -955,10 +959,8 @@ mod tests {
10,
);
// Calculating the offset of used_event within Avail structure
#[allow(deref_nullptr)]
let used_event_offset: u64 =
unsafe { &(*(::std::ptr::null::<Avail>())).used_event as *const _ as u64 };
// Offset of used_event within Avail structure
let used_event_offset = offset_of!(Avail, used_event) as u64;
let used_event_address = GuestAddress(AVAIL_OFFSET + used_event_offset);
// Assume driver submit 0x100 req to device,

View file

@ -81,7 +81,7 @@ pub struct Sound {
impl VirtioDevice for Sound {
fn keep_rds(&self) -> Vec<RawDescriptor> {
self.vios_client.keep_fds()
self.vios_client.keep_rds()
}
fn device_type(&self) -> DeviceType {

View file

@ -173,7 +173,7 @@ impl ShmStreamSource<base::Error> for VioSShmStreamSource {
/// This list helps users of the ShmStreamSource enter Linux jails without
/// closing needed file descriptors.
fn keep_fds(&self) -> Vec<RawDescriptor> {
self.vios_client.keep_fds()
self.vios_client.keep_rds()
}
}

View file

@ -15,7 +15,7 @@ use data_model::{DataInit, VolatileMemory, VolatileMemoryError, VolatileSlice};
use std::collections::{HashMap, VecDeque};
use std::fs::File;
use std::io::{Error as IOError, ErrorKind as IOErrorKind, IoSliceMut, Seek, SeekFrom};
use std::os::unix::io::{AsRawFd, RawFd};
use std::os::unix::io::RawFd;
use std::path::Path;
use std::sync::mpsc::{channel, Receiver, RecvError, Sender};
use std::sync::Arc;
@ -447,14 +447,14 @@ impl VioSClient {
}
/// Get a list of file descriptors used by the implementation.
pub fn keep_fds(&self) -> Vec<RawFd> {
let control_fd = self.control_socket.lock().as_raw_fd();
let event_fd = self.event_socket.as_raw_fd();
pub fn keep_rds(&self) -> Vec<RawDescriptor> {
let control_desc = self.control_socket.lock().as_raw_descriptor();
let event_desc = self.event_socket.as_raw_descriptor();
let recv_event = self.recv_event.as_raw_descriptor();
let event_notifier = self.event_notifier.as_raw_descriptor();
let mut ret = vec![control_fd, event_fd, recv_event, event_notifier];
ret.append(&mut self.tx.keep_fds());
ret.append(&mut self.rx.keep_fds());
let mut ret = vec![control_desc, event_desc, recv_event, event_notifier];
ret.append(&mut self.tx.keep_rds());
ret.append(&mut self.rx.keep_rds());
ret
}
@ -747,7 +747,7 @@ impl IoBufferQueue {
seq_socket_send(&self.socket, msg)
}
fn keep_fds(&self) -> Vec<RawDescriptor> {
fn keep_rds(&self) -> Vec<RawDescriptor> {
vec![
self.file.as_raw_descriptor(),
self.socket.as_raw_descriptor(),

View file

@ -53,8 +53,8 @@ fn open_disk_file(disk_option: &DiskOption, take_write_lock: bool) -> anyhow::Re
.context("Failed to open disk file")
}
#[derive(FromArgs)]
#[argh(description = "")]
#[derive(FromArgs, Debug)]
#[argh(subcommand, name = "block", description = "")]
pub struct Options {
#[argh(
option,
@ -64,19 +64,7 @@ pub struct Options {
bootstrap: usize,
}
pub fn start_device(program_name: &str, args: &[&str]) -> anyhow::Result<()> {
let opts = match Options::from_args(&[program_name], args) {
Ok(opts) => opts,
Err(e) => {
if e.status.is_err() {
bail!(e.output);
} else {
println!("{}", e.output);
}
return Ok(());
}
};
pub fn start_device(opts: Options) -> anyhow::Result<()> {
tracing::init();
let raw_transport_tube = opts.bootstrap as RawDescriptor;

View file

@ -90,6 +90,7 @@ use {base::clear_fd_flags, std::os::unix::io::AsRawFd};
pub struct CallEvent(Event);
impl CallEvent {
#[cfg_attr(windows, allow(dead_code))]
pub fn into_inner(self) -> Event {
self.0
}
@ -226,6 +227,7 @@ impl Vring {
}
/// Performs the run loop for an already-constructed request handler.
#[cfg_attr(windows, allow(dead_code))]
pub async fn run_handler<S, E>(mut req_handler: SlaveReqHandler<S, E>, ex: &Executor) -> Result<()>
where
S: VhostUserSlaveReqHandler,
@ -791,11 +793,14 @@ impl SharedMemoryMapper for VhostShmemMapper {
mod tests {
use super::*;
#[cfg(unix)]
use std::sync::mpsc::channel;
#[cfg(unix)]
use std::sync::Barrier;
use anyhow::{anyhow, bail};
use data_model::DataInit;
#[cfg(unix)]
use tempfile::{Builder, TempDir};
use crate::virtio::vhost::user::vmm::VhostUserHandler;

View file

@ -2,9 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::fs::File;
use std::mem::ManuallyDrop;
use std::sync::Arc;
use anyhow::{Context, Result};
use base::named_pipes::{BlockingMode, FramingMode, PipeConnection};
@ -13,15 +11,10 @@ use cros_async::{EventAsync, Executor};
use futures::FutureExt;
use futures::{pin_mut, select};
use tube_transporter::{TubeTransferDataList, TubeTransporterReader};
use vm_memory::GuestMemory;
use vmm_vhost::{Protocol, SlaveReqHandler};
use vmm_vhost::SlaveReqHandler;
use crate::virtio::vhost::user::device::{
handler::{
CallEvent, DeviceRequestHandler, MappingInfo, VhostResult, VhostUserBackend,
VhostUserMemoryRegion, VhostUserRegularOps,
},
listener::{VhostUserListener, VhostUserListenerTrait},
use crate::virtio::vhost::user::device::handler::{
CallEvent, DeviceRequestHandler, VhostUserRegularOps,
};
pub type Doorbell = CallEvent;

View file

@ -19,17 +19,17 @@ pub struct VhostUserListener;
impl VhostUserListenerTrait for VhostUserListener {
fn new(
path: &str,
max_num_queues: usize,
keep_rds: Option<&mut Vec<RawDescriptor>>,
_path: &str,
_max_num_queues: usize,
_keep_rds: Option<&mut Vec<RawDescriptor>>,
) -> anyhow::Result<Self> {
todo!()
}
fn run_backend(
self,
backend: Box<dyn VhostUserBackend>,
ex: &Executor,
_backend: Box<dyn VhostUserBackend>,
_ex: &Executor,
) -> Pin<Box<dyn Future<Output = anyhow::Result<()>>>> {
todo!()
}

View file

@ -38,7 +38,7 @@ cfg_if::cfg_if! {
#[cfg(feature = "slirp")]
mod net;
#[cfg(feature = "slirp")]
pub use net::run_net_device;
pub use net::{run_net_device, Options as NetOptions};
#[cfg(feature = "slirp")]
pub use net::sys::windows::NetBackendConfig;

View file

@ -7,7 +7,7 @@ use crate::virtio;
use crate::virtio::net::MAX_BUFFER_SIZE;
use crate::virtio::net::{process_rx, NetError};
use crate::virtio::vhost::user::device::handler::sys::windows::read_from_tube_transporter;
use crate::virtio::vhost::user::device::handler::{DeviceRequestHandler, Doorbell};
use crate::virtio::vhost::user::device::handler::{sys::Doorbell, DeviceRequestHandler};
use crate::virtio::vhost::user::device::net::{
run_ctrl_queue, run_tx_queue, NetBackend, NET_EXECUTOR,
};
@ -93,7 +93,7 @@ async fn run_rx_queue<T: TapT>(
&mut overlapped_wrapper,
);
if needs_interrupt {
call_evt.lock().signal_used_queue(queue.vector);
call_evt.lock().signal_used_queue(queue.vector());
}
// There aren't any RX descriptors available for us to write packets to. Wait for the guest
@ -127,7 +127,7 @@ pub(in crate::virtio::vhost::user::device::net) fn start_queue<T: 'static + Into
let overlapped_wrapper =
OverlappedWrapper::new(true).expect("Failed to create overlapped wrapper");
super::NET_EXECUTOR.with(|ex| {
super::super::NET_EXECUTOR.with(|ex| {
// Safe because the executor is initialized in main() below.
let ex = ex.get().expect("Executor not initialized");
@ -143,11 +143,13 @@ pub(in crate::virtio::vhost::user::device::net) fn start_queue<T: 'static + Into
let tap = ex
.async_from(tap)
.context("failed to create async tap device")?;
let read_notifier = overlapped_wrapper
.get_h_event_ref()
.unwrap()
.try_clone()
.unwrap();
let read_notifier = base::Event(
overlapped_wrapper
.get_h_event_ref()
.unwrap()
.try_clone()
.unwrap(),
);
let read_notifier = EventAsync::new_without_reset(read_notifier, &ex)
.context("failed to create async read notifier")?;
@ -214,9 +216,9 @@ pub struct NetBackendConfig {
pub slirp_kill_event: Event,
}
#[derive(FromArgs)]
#[argh(description = "")]
struct Options {
#[derive(FromArgs, Debug)]
#[argh(subcommand, name = "net", description = "")]
pub struct Options {
#[argh(
option,
description = "pipe handle end for Tube Transporter",
@ -229,19 +231,7 @@ struct Options {
compile_error!("vhost-user net device requires slirp feature on Windows.");
#[cfg(feature = "slirp")]
pub fn run_device(program_name: &str, args: &[&str]) -> anyhow::Result<()> {
let opts = match Options::from_args(&[program_name], args) {
Ok(opts) => opts,
Err(e) => {
if e.status.is_err() {
bail!(e.output);
} else {
println!("{}", e.output);
}
return Ok(());
}
};
pub fn start_device(opts: Options) -> anyhow::Result<()> {
// Get the Tubes from the TubeTransporter. Then get the "Config" from the bootstrap_tube
// which will contain slirp settings.
let raw_transport_tube = opts.bootstrap as RawDescriptor;
@ -253,7 +243,7 @@ pub fn run_device(program_name: &str, args: &[&str]) -> anyhow::Result<()> {
let startup_args: CommonChildStartupArgs =
bootstrap_tube.recv::<CommonChildStartupArgs>().unwrap();
common_child_setup(startup_args).unwrap();
let _child_cleanup = common_child_setup(startup_args).unwrap();
let net_backend_config = bootstrap_tube.recv::<NetBackendConfig>().unwrap();

View file

@ -198,7 +198,7 @@ impl VirtioDevice for Vsock {
};
self.kill_evt = Some(self_kill_evt);
let host_guid = self.host_guid.clone();
let guest_cid = self.guest_cid.clone();
let guest_cid = self.guest_cid;
let worker_result = thread::Builder::new()
.name("userspace_virtio_vsock".to_string())
.spawn(move || {
@ -351,7 +351,7 @@ impl Worker {
VsockError::CloneDescriptor(e)
})
.map(base::Event)?;
let evt_async = EventAsync::new(h_evt, &ex).map_err(|e| {
let evt_async = EventAsync::new(h_evt, ex).map_err(|e| {
error!("Could not create EventAsync.");
VsockError::CreateEventAsync(e)
})?;
@ -362,7 +362,7 @@ impl Worker {
error!("Could not clone connection_event.");
VsockError::CloneDescriptor(e)
})?;
let connection_evt_async = EventAsync::new(connection_evt_clone, &ex).map_err(|e| {
let connection_evt_async = EventAsync::new(connection_evt_clone, ex).map_err(|e| {
error!("Could not create EventAsync.");
VsockError::CreateEventAsync(e)
})?;
@ -428,7 +428,7 @@ impl Worker {
let pipe_connection = &mut connection.pipe;
let overlapped = &mut connection.overlapped;
let guest_port = connection.guest_port.clone();
let guest_port = connection.guest_port;
let buffer = &mut connection.buffer;
match overlapped.get_h_event_ref() {
@ -533,19 +533,18 @@ impl Worker {
break;
}
let mut data = vec![0 as u8; len];
let mut data = vec![0_u8; len];
if len > 0 {
if let Err(e) = reader.read_exact(&mut data) {
error!("vosck: failed to read data from tx packet: {:?}", e);
}
}
match process_packets_queue.send((header, data)).await {
Err(e) => error!(
if let Err(e) = process_packets_queue.send((header, data)).await {
error!(
"Error while sending packet to queue, dropping packet: {:?}",
e
),
_ => {}
)
};
queue.add_used(&self.mem, index, 0);
queue.trigger_interrupt(&self.mem, &*self.interrupt.borrow());
@ -649,16 +648,15 @@ impl Worker {
buffer,
// The connection has just been made, so we haven't received
// anything yet.
recv_cnt: 0 as usize,
prev_recv_cnt: 0 as usize,
tx_cnt: 0 as usize,
recv_cnt: 0_usize,
prev_recv_cnt: 0_usize,
tx_cnt: 0_usize,
is_buffer_full: false,
};
self.connections.write().unwrap().insert(port, connection);
self.connection_event
.write(0) // 0 is arbitrary
.expect(&format!(
"Failed to signal new connection event for vsock port {}.", port));
.unwrap_or_else(|_| panic!("Failed to signal new connection event for vsock port {}.", port));
true
}
Err(e) => {
@ -801,7 +799,7 @@ impl Worker {
let (send, recv) = mpsc::channel(CHANNEL_SIZE);
let event_async = EventAsync::new(
rx_queue_evt.try_clone().expect("Failed to clone event"),
&ex,
ex,
)
.expect("Failed to set up the rx queue event");
futures.push(
@ -817,11 +815,8 @@ impl Worker {
send
});
// Try to send the packet. Do not block other ports if the queue is full.
match queue.try_send(packet) {
Err(e) => {
error!("Error sending packet to queue, dropping packet: {:?}", e)
}
_ => {}
if let Err(e) = queue.try_send(packet) {
error!("Error sending packet to queue, dropping packet: {:?}", e)
}
}
SelectResult::Finished(_) => {
@ -846,7 +841,7 @@ impl Worker {
) -> PortPair {
while let Some((header, mut data)) = packet_recv_queue.next().await {
if !self
.handle_tx_packet(header, &mut data, send_queue, &mut rx_queue_evt, ex)
.handle_tx_packet(header, &data, send_queue, &mut rx_queue_evt, ex)
.await
{
packet_recv_queue.close();
@ -1284,7 +1279,7 @@ impl Worker {
}
}
fn get_pipe_name(guid: &String, pipe: u32) -> String {
fn get_pipe_name(guid: &str, pipe: u32) -> String {
format!("\\\\.\\pipe\\{}\\vsock-{}", guid, pipe)
}