diff options
-rw-r--r-- | src/vhost_kern/mod.rs | 3 | ||||
-rw-r--r-- | src/vhost_kern/vsock.rs | 84 |
2 files changed, 87 insertions, 0 deletions
diff --git a/src/vhost_kern/mod.rs b/src/vhost_kern/mod.rs index 8727fc8..51fd671 100644 --- a/src/vhost_kern/mod.rs +++ b/src/vhost_kern/mod.rs @@ -26,6 +26,9 @@ use super::{ pub mod vhost_binding; use self::vhost_binding::*; +#[cfg(feature = "vhost-vsock")] +pub mod vsock; + #[inline] fn ioctl_result<T>(rc: i32, res: T) -> Result<T> { if rc < 0 { diff --git a/src/vhost_kern/vsock.rs b/src/vhost_kern/vsock.rs new file mode 100644 index 0000000..7483744 --- /dev/null +++ b/src/vhost_kern/vsock.rs @@ -0,0 +1,84 @@ +// Copyright (C) 2019 Alibaba Cloud Computing. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause +// +// Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE-BSD-Google file. + +//! Kernel-based vsock vhost backend. + +use std::fs::{File, OpenOptions}; +use std::marker::PhantomData; +use std::os::unix::fs::OpenOptionsExt; +use std::os::unix::io::{AsRawFd, RawFd}; + +use super::vhost_binding::{VHOST_VSOCK_SET_GUEST_CID, VHOST_VSOCK_SET_RUNNING}; +use super::{ioctl_result, Error, Result, VhostKernBackend}; +use libc; +use vm_memory::GuestMemory; +use vmm_sys_util::ioctl::ioctl_with_ref; + +const VHOST_PATH: &str = "/dev/vhost-vsock"; + +/// Handle for running VHOST_VSOCK ioctls. +pub struct Vsock<'a, M: GuestMemory> { + fd: File, + mem: M, + _phatomdata: PhantomData<&'a M>, // Get rid of unused type parameter `a +} + +impl<'a, M: GuestMemory> Vsock<'a, M> { + /// Open a handle to a new VHOST-VSOCK instance. + pub fn new(mem: M) -> Result<Self> { + Ok(Vsock { + fd: OpenOptions::new() + .read(true) + .write(true) + .custom_flags(libc::O_CLOEXEC | libc::O_NONBLOCK) + .open(VHOST_PATH) + .map_err(Error::VhostOpen)?, + mem, + _phatomdata: PhantomData, + }) + } + + /// Set the CID for the guest. This number is used for routing all data destined for + /// running in the guest. Each guest on a hypervisor must have an unique CID + /// + /// # Arguments + /// * `cid` - CID to assign to the guest + pub fn set_guest_cid(&self, cid: u64) -> Result<()> { + let ret = unsafe { ioctl_with_ref(&self.fd, VHOST_VSOCK_SET_GUEST_CID(), &cid) }; + ioctl_result(ret, ()) + } + + /// Tell the VHOST driver to start performing data transfer. + pub fn start(&self) -> Result<()> { + self.set_running(true) + } + + /// Tell the VHOST driver to stop performing data transfer. + pub fn stop(&self) -> Result<()> { + self.set_running(false) + } + + fn set_running(&self, running: bool) -> Result<()> { + let on: ::std::os::raw::c_int = if running { 1 } else { 0 }; + let ret = unsafe { ioctl_with_ref(&self.fd, VHOST_VSOCK_SET_RUNNING(), &on) }; + ioctl_result(ret, ()) + } +} + +impl<'a, M: GuestMemory> VhostKernBackend<'a> for Vsock<'a, M> { + type M = M; + + fn mem(&self) -> &Self::M { + &self.mem + } +} + +impl<'a, M: GuestMemory> AsRawFd for Vsock<'a, M> { + fn as_raw_fd(&self) -> RawFd { + self.fd.as_raw_fd() + } +} |