mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-01-30 04:19:20 +00:00
crosvm: rename Net virtio device to VhostNet
BUG=chromium:703920 TEST=networking still works Change-Id: I28517cc61a572998cd57868c2dbccec247140a58 Signed-off-by: Stephen Barber <smbarber@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/604936 Reviewed-by: Zach Reizner <zachr@chromium.org>
This commit is contained in:
parent
604d989d7e
commit
d579e3cd49
4 changed files with 72 additions and 65 deletions
|
@ -7,12 +7,12 @@
|
|||
mod queue;
|
||||
mod mmio;
|
||||
mod block;
|
||||
mod net;
|
||||
mod vhost_net;
|
||||
|
||||
pub use self::queue::*;
|
||||
pub use self::mmio::*;
|
||||
pub use self::block::*;
|
||||
pub use self::net::*;
|
||||
pub use self::vhost_net::*;
|
||||
|
||||
const DEVICE_ACKNOWLEDGE: u32 = 0x01;
|
||||
const DEVICE_DRIVER: u32 = 0x02;
|
||||
|
|
|
@ -13,7 +13,7 @@ use std::thread::spawn;
|
|||
use net_sys;
|
||||
use net_util::{Tap, Error as TapError};
|
||||
use sys_util::{Error as SysError, EventFd, GuestMemory, Poller};
|
||||
use vhost::{VhostNet, Error as VhostError};
|
||||
use vhost::{VhostNet as VhostNetHandle, Error as VhostError};
|
||||
use virtio_sys::{vhost, virtio_net};
|
||||
use virtio_sys::virtio_net::virtio_net_hdr_mrg_rxbuf;
|
||||
|
||||
|
@ -23,7 +23,7 @@ const QUEUE_SIZE: u16 = 256;
|
|||
const QUEUE_SIZES: &'static [u16] = &[QUEUE_SIZE, QUEUE_SIZE];
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum NetError {
|
||||
pub enum VhostNetError {
|
||||
/// Creating kill eventfd failed.
|
||||
CreateKillEventFd(SysError),
|
||||
/// Cloning kill eventfd failed.
|
||||
|
@ -73,7 +73,7 @@ pub enum NetError {
|
|||
struct Worker {
|
||||
queues: Vec<Queue>,
|
||||
tap: Tap,
|
||||
vhost_net: VhostNet,
|
||||
vhost_net_handle: VhostNetHandle,
|
||||
vhost_interrupt: EventFd,
|
||||
interrupt_status: Arc<AtomicUsize>,
|
||||
interrupt_evt: EventFd,
|
||||
|
@ -87,29 +87,31 @@ impl Worker {
|
|||
self.interrupt_evt.write(1).unwrap();
|
||||
}
|
||||
|
||||
fn run(&mut self, queue_evts: Vec<EventFd>, kill_evt: EventFd) -> Result<(), NetError> {
|
||||
fn run(&mut self, queue_evts: Vec<EventFd>, kill_evt: EventFd) -> Result<(), VhostNetError> {
|
||||
// Preliminary setup for vhost net.
|
||||
self.vhost_net.set_owner().map_err(NetError::VhostSetOwner)?;
|
||||
self.vhost_net_handle
|
||||
.set_owner()
|
||||
.map_err(VhostNetError::VhostSetOwner)?;
|
||||
|
||||
let avail_features = self.vhost_net
|
||||
let avail_features = self.vhost_net_handle
|
||||
.get_features()
|
||||
.map_err(NetError::VhostGetFeatures)?;
|
||||
.map_err(VhostNetError::VhostGetFeatures)?;
|
||||
|
||||
let features: c_ulonglong = self.acked_features & avail_features;
|
||||
self.vhost_net
|
||||
self.vhost_net_handle
|
||||
.set_features(features)
|
||||
.map_err(NetError::VhostSetFeatures)?;
|
||||
.map_err(VhostNetError::VhostSetFeatures)?;
|
||||
|
||||
self.vhost_net
|
||||
self.vhost_net_handle
|
||||
.set_mem_table()
|
||||
.map_err(NetError::VhostSetMemTable)?;
|
||||
.map_err(VhostNetError::VhostSetMemTable)?;
|
||||
|
||||
for (queue_index, ref queue) in self.queues.iter().enumerate() {
|
||||
self.vhost_net
|
||||
self.vhost_net_handle
|
||||
.set_vring_num(queue_index, queue.max_size)
|
||||
.map_err(NetError::VhostSetVringNum)?;
|
||||
.map_err(VhostNetError::VhostSetVringNum)?;
|
||||
|
||||
self.vhost_net
|
||||
self.vhost_net_handle
|
||||
.set_vring_addr(QUEUE_SIZES[queue_index],
|
||||
queue.actual_size(),
|
||||
queue_index,
|
||||
|
@ -118,19 +120,19 @@ impl Worker {
|
|||
queue.used_ring,
|
||||
queue.avail_ring,
|
||||
None)
|
||||
.map_err(NetError::VhostSetVringAddr)?;
|
||||
self.vhost_net
|
||||
.map_err(VhostNetError::VhostSetVringAddr)?;
|
||||
self.vhost_net_handle
|
||||
.set_vring_base(queue_index, 0)
|
||||
.map_err(NetError::VhostSetVringBase)?;
|
||||
self.vhost_net
|
||||
.map_err(VhostNetError::VhostSetVringBase)?;
|
||||
self.vhost_net_handle
|
||||
.set_vring_call(queue_index, &self.vhost_interrupt)
|
||||
.map_err(NetError::VhostSetVringCall)?;
|
||||
self.vhost_net
|
||||
.map_err(VhostNetError::VhostSetVringCall)?;
|
||||
self.vhost_net_handle
|
||||
.set_vring_kick(queue_index, &queue_evts[queue_index])
|
||||
.map_err(NetError::VhostSetVringKick)?;
|
||||
self.vhost_net
|
||||
.map_err(VhostNetError::VhostSetVringKick)?;
|
||||
self.vhost_net_handle
|
||||
.net_set_backend(queue_index, &self.tap)
|
||||
.map_err(NetError::VhostNetSetBackend)?;
|
||||
.map_err(VhostNetError::VhostNetSetBackend)?;
|
||||
}
|
||||
|
||||
const VHOST_IRQ: u32 = 1;
|
||||
|
@ -139,18 +141,20 @@ impl Worker {
|
|||
let mut poller = Poller::new(2);
|
||||
|
||||
'poll: loop {
|
||||
let tokens =
|
||||
match poller.poll(&[(VHOST_IRQ, &self.vhost_interrupt), (KILL, &kill_evt)]) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return Err(NetError::PollError(e))
|
||||
};
|
||||
let tokens = match poller.poll(&[(VHOST_IRQ, &self.vhost_interrupt),
|
||||
(KILL, &kill_evt)]) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return Err(VhostNetError::PollError(e)),
|
||||
};
|
||||
|
||||
let mut needs_interrupt = false;
|
||||
for &token in tokens {
|
||||
match token {
|
||||
VHOST_IRQ => {
|
||||
needs_interrupt = true;
|
||||
self.vhost_interrupt.read().map_err(NetError::VhostIrqRead)?;
|
||||
self.vhost_interrupt
|
||||
.read()
|
||||
.map_err(VhostNetError::VhostIrqRead)?;
|
||||
}
|
||||
KILL => break 'poll,
|
||||
_ => unreachable!(),
|
||||
|
@ -164,42 +168,44 @@ impl Worker {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Net {
|
||||
pub struct VhostNet {
|
||||
workers_kill_evt: Option<EventFd>,
|
||||
kill_evt: EventFd,
|
||||
tap: Option<Tap>,
|
||||
vhost_net: Option<VhostNet>,
|
||||
vhost_net_handle: Option<VhostNetHandle>,
|
||||
vhost_interrupt: Option<EventFd>,
|
||||
avail_features: u64,
|
||||
acked_features: u64,
|
||||
}
|
||||
|
||||
impl Net {
|
||||
impl VhostNet {
|
||||
/// Create a new virtio network device with the given IP address and
|
||||
/// netmask.
|
||||
pub fn new(ip_addr: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
mem: &GuestMemory) -> Result<Net, NetError> {
|
||||
let kill_evt = EventFd::new().map_err(NetError::CreateKillEventFd)?;
|
||||
mem: &GuestMemory)
|
||||
-> Result<VhostNet, VhostNetError> {
|
||||
let kill_evt = EventFd::new().map_err(VhostNetError::CreateKillEventFd)?;
|
||||
|
||||
let tap = Tap::new().map_err(NetError::TapOpen)?;
|
||||
tap.set_ip_addr(ip_addr).map_err(NetError::TapSetIp)?;
|
||||
tap.set_netmask(netmask).map_err(NetError::TapSetNetmask)?;
|
||||
let tap = Tap::new().map_err(VhostNetError::TapOpen)?;
|
||||
tap.set_ip_addr(ip_addr)
|
||||
.map_err(VhostNetError::TapSetIp)?;
|
||||
tap.set_netmask(netmask)
|
||||
.map_err(VhostNetError::TapSetNetmask)?;
|
||||
|
||||
// Set offload flags to match the virtio features below.
|
||||
tap.set_offload(net_sys::TUN_F_CSUM |
|
||||
net_sys::TUN_F_UFO |
|
||||
net_sys::TUN_F_TSO4 |
|
||||
net_sys::TUN_F_TSO6)
|
||||
.map_err(NetError::TapSetOffload)?;
|
||||
tap.set_offload(net_sys::TUN_F_CSUM | net_sys::TUN_F_UFO |
|
||||
net_sys::TUN_F_TSO4 | net_sys::TUN_F_TSO6)
|
||||
.map_err(VhostNetError::TapSetOffload)?;
|
||||
|
||||
// We declare VIRTIO_NET_F_MRG_RXBUF, so set the vnet hdr size to match.
|
||||
let vnet_hdr_size = mem::size_of::<virtio_net_hdr_mrg_rxbuf>() as i32;
|
||||
tap.set_vnet_hdr_size(vnet_hdr_size)
|
||||
.map_err(NetError::TapSetVnetHdrSize)?;
|
||||
.map_err(VhostNetError::TapSetVnetHdrSize)?;
|
||||
|
||||
tap.enable().map_err(NetError::TapEnable)?;
|
||||
let vhost_net = VhostNet::new(mem).map_err(NetError::VhostOpen)?;
|
||||
tap.enable().map_err(VhostNetError::TapEnable)?;
|
||||
let vhost_net_handle = VhostNetHandle::new(mem)
|
||||
.map_err(VhostNetError::VhostOpen)?;
|
||||
|
||||
let avail_features =
|
||||
1 << virtio_net::VIRTIO_NET_F_GUEST_CSUM |
|
||||
|
@ -214,19 +220,21 @@ impl Net {
|
|||
1 << vhost::VIRTIO_F_NOTIFY_ON_EMPTY |
|
||||
1 << vhost::VIRTIO_F_VERSION_1;
|
||||
|
||||
Ok(Net {
|
||||
workers_kill_evt: Some(kill_evt.try_clone().map_err(NetError::CloneKillEventFd)?),
|
||||
Ok(VhostNet {
|
||||
workers_kill_evt: Some(kill_evt
|
||||
.try_clone()
|
||||
.map_err(VhostNetError::CloneKillEventFd)?),
|
||||
kill_evt: kill_evt,
|
||||
tap: Some(tap),
|
||||
vhost_net: Some(vhost_net),
|
||||
vhost_interrupt: Some(EventFd::new().map_err(NetError::VhostIrqCreate)?),
|
||||
vhost_net_handle: Some(vhost_net_handle),
|
||||
vhost_interrupt: Some(EventFd::new().map_err(VhostNetError::VhostIrqCreate)?),
|
||||
avail_features: avail_features,
|
||||
acked_features: 0u64,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Net {
|
||||
impl Drop for VhostNet {
|
||||
fn drop(&mut self) {
|
||||
// Only kill the child if it claimed its eventfd.
|
||||
if self.workers_kill_evt.is_none() {
|
||||
|
@ -236,7 +244,7 @@ impl Drop for Net {
|
|||
}
|
||||
}
|
||||
|
||||
impl VirtioDevice for Net {
|
||||
impl VirtioDevice for VhostNet {
|
||||
fn keep_fds(&self) -> Vec<RawFd> {
|
||||
let mut keep_fds = Vec::new();
|
||||
|
||||
|
@ -244,8 +252,8 @@ impl VirtioDevice for Net {
|
|||
keep_fds.push(tap.as_raw_fd());
|
||||
}
|
||||
|
||||
if let Some(ref vhost_net) = self.vhost_net {
|
||||
keep_fds.push(vhost_net.as_raw_fd());
|
||||
if let Some(ref vhost_net_handle) = self.vhost_net_handle {
|
||||
keep_fds.push(vhost_net_handle.as_raw_fd());
|
||||
}
|
||||
|
||||
if let Some(ref vhost_interrupt) = self.vhost_interrupt {
|
||||
|
@ -284,7 +292,7 @@ impl VirtioDevice for Net {
|
|||
1 => (value as u64) << 32,
|
||||
_ => {
|
||||
warn!("net: virtio net device cannot ack unknown feature page: {}",
|
||||
page);
|
||||
page);
|
||||
0u64
|
||||
}
|
||||
};
|
||||
|
@ -311,7 +319,7 @@ impl VirtioDevice for Net {
|
|||
return;
|
||||
}
|
||||
|
||||
if let Some(vhost_net) = self.vhost_net.take() {
|
||||
if let Some(vhost_net_handle) = self.vhost_net_handle.take() {
|
||||
if let Some(tap) = self.tap.take() {
|
||||
if let Some(vhost_interrupt) = self.vhost_interrupt.take() {
|
||||
if let Some(kill_evt) = self.workers_kill_evt.take() {
|
||||
|
@ -320,7 +328,7 @@ impl VirtioDevice for Net {
|
|||
let mut worker = Worker {
|
||||
queues: queues,
|
||||
tap: tap,
|
||||
vhost_net: vhost_net,
|
||||
vhost_net_handle: vhost_net_handle,
|
||||
vhost_interrupt: vhost_interrupt,
|
||||
interrupt_status: status,
|
||||
interrupt_evt: interrupt_evt,
|
||||
|
@ -328,8 +336,7 @@ impl VirtioDevice for Net {
|
|||
};
|
||||
let result = worker.run(queue_evts, kill_evt);
|
||||
if let Err(e) = result {
|
||||
error!("net worker thread exited with error: {:?}",
|
||||
e);
|
||||
error!("net worker thread exited with error: {:?}", e);
|
||||
}
|
||||
});
|
||||
}
|
10
src/main.rs
10
src/main.rs
|
@ -51,7 +51,7 @@ enum Error {
|
|||
Disk(std::io::Error),
|
||||
BlockDeviceNew(sys_util::Error),
|
||||
BlockDeviceRootSetup(sys_util::Error),
|
||||
NetDeviceNew(hw::virtio::NetError),
|
||||
VhostNetDeviceNew(hw::virtio::VhostNetError),
|
||||
NetDeviceRootSetup(sys_util::Error),
|
||||
MacAddressNeedsNetConfig,
|
||||
NetMissingConfig,
|
||||
|
@ -100,7 +100,7 @@ impl fmt::Display for Error {
|
|||
write!(f, "failed to create root directory for a block device: {:?}", e)
|
||||
}
|
||||
&Error::RegisterBlock(ref e) => write!(f, "error registering block device: {:?}", e),
|
||||
&Error::NetDeviceNew(ref e) => write!(f, "failed to set up networking: {:?}", e),
|
||||
&Error::VhostNetDeviceNew(ref e) => write!(f, "failed to set up vhost networking: {:?}", e),
|
||||
&Error::NetDeviceRootSetup(ref e) => {
|
||||
write!(f, "failed to create root directory for a net device: {:?}", e)
|
||||
}
|
||||
|
@ -266,12 +266,12 @@ fn run_config(cfg: Config) -> Result<()> {
|
|||
.map_err(Error::NetDeviceRootSetup)?;
|
||||
if let Some(host_ip) = cfg.host_ip {
|
||||
if let Some(netmask) = cfg.netmask {
|
||||
let net_box = Box::new(hw::virtio::Net::new(host_ip, netmask, &guest_mem)
|
||||
.map_err(|e| Error::NetDeviceNew(e))?);
|
||||
let net_box = Box::new(hw::virtio::VhostNet::new(host_ip, netmask, &guest_mem)
|
||||
.map_err(|e| Error::VhostNetDeviceNew(e))?);
|
||||
let jail = if cfg.multiprocess {
|
||||
let net_root_path = net_root.as_path().unwrap(); // Won't fail if new succeeded.
|
||||
|
||||
Some(create_base_minijail(net_root_path, Path::new("net_device.policy"))?)
|
||||
Some(create_base_minijail(net_root_path, Path::new("vhost_net_device.policy"))?)
|
||||
}
|
||||
else {
|
||||
None
|
||||
|
|
Loading…
Reference in a new issue