1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File; 6*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::OpenOptions; 7*bb4ee6a4SAndroid Build Coastguard Worker use std::marker::PhantomData; 8*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::fs::OpenOptionsExt; 9*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path; 10*bb4ee6a4SAndroid Build Coastguard Worker 11*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_with_ref; 12*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor; 13*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor; 14*bb4ee6a4SAndroid Build Coastguard Worker use net_util::TapT; 15*bb4ee6a4SAndroid Build Coastguard Worker 16*bb4ee6a4SAndroid Build Coastguard Worker use super::ioctl_result; 17*bb4ee6a4SAndroid Build Coastguard Worker use super::Error; 18*bb4ee6a4SAndroid Build Coastguard Worker use super::Result; 19*bb4ee6a4SAndroid Build Coastguard Worker use super::Vhost; 20*bb4ee6a4SAndroid Build Coastguard Worker 21*bb4ee6a4SAndroid Build Coastguard Worker /// Handle to run VHOST_NET ioctls. 22*bb4ee6a4SAndroid Build Coastguard Worker /// 23*bb4ee6a4SAndroid Build Coastguard Worker /// This provides a simple wrapper around a VHOST_NET file descriptor and 24*bb4ee6a4SAndroid Build Coastguard Worker /// methods that safely run ioctls on that file descriptor. 25*bb4ee6a4SAndroid Build Coastguard Worker pub struct Net<T> { 26*bb4ee6a4SAndroid Build Coastguard Worker // descriptor must be dropped first, which will stop and tear down the 27*bb4ee6a4SAndroid Build Coastguard Worker // vhost-net worker before GuestMemory can potentially be unmapped. 28*bb4ee6a4SAndroid Build Coastguard Worker descriptor: File, 29*bb4ee6a4SAndroid Build Coastguard Worker phantom: PhantomData<T>, 30*bb4ee6a4SAndroid Build Coastguard Worker } 31*bb4ee6a4SAndroid Build Coastguard Worker 32*bb4ee6a4SAndroid Build Coastguard Worker pub trait NetT<T: TapT>: Vhost + AsRawDescriptor + Send + Sized { 33*bb4ee6a4SAndroid Build Coastguard Worker /// Create a new NetT instance new(vhost_net_device_path: &Path) -> Result<Self>34*bb4ee6a4SAndroid Build Coastguard Worker fn new(vhost_net_device_path: &Path) -> Result<Self>; 35*bb4ee6a4SAndroid Build Coastguard Worker 36*bb4ee6a4SAndroid Build Coastguard Worker /// Set the tap file descriptor that will serve as the VHOST_NET backend. 37*bb4ee6a4SAndroid Build Coastguard Worker /// This will start the vhost worker for the given queue. 38*bb4ee6a4SAndroid Build Coastguard Worker /// 39*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments 40*bb4ee6a4SAndroid Build Coastguard Worker /// * `queue_index` - Index of the queue to modify. 41*bb4ee6a4SAndroid Build Coastguard Worker /// * `descriptor` - Tap interface that will be used as the backend. set_backend(&self, queue_index: usize, descriptor: Option<&T>) -> Result<()>42*bb4ee6a4SAndroid Build Coastguard Worker fn set_backend(&self, queue_index: usize, descriptor: Option<&T>) -> Result<()>; 43*bb4ee6a4SAndroid Build Coastguard Worker } 44*bb4ee6a4SAndroid Build Coastguard Worker 45*bb4ee6a4SAndroid Build Coastguard Worker impl<T> NetT<T> for Net<T> 46*bb4ee6a4SAndroid Build Coastguard Worker where 47*bb4ee6a4SAndroid Build Coastguard Worker T: TapT, 48*bb4ee6a4SAndroid Build Coastguard Worker { 49*bb4ee6a4SAndroid Build Coastguard Worker /// Opens /dev/vhost-net and holds a file descriptor open for it. 50*bb4ee6a4SAndroid Build Coastguard Worker /// 51*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments 52*bb4ee6a4SAndroid Build Coastguard Worker /// * `mem` - Guest memory mapping. new(vhost_net_device_path: &Path) -> Result<Net<T>>53*bb4ee6a4SAndroid Build Coastguard Worker fn new(vhost_net_device_path: &Path) -> Result<Net<T>> { 54*bb4ee6a4SAndroid Build Coastguard Worker Ok(Net::<T> { 55*bb4ee6a4SAndroid Build Coastguard Worker descriptor: OpenOptions::new() 56*bb4ee6a4SAndroid Build Coastguard Worker .read(true) 57*bb4ee6a4SAndroid Build Coastguard Worker .write(true) 58*bb4ee6a4SAndroid Build Coastguard Worker .custom_flags(libc::O_CLOEXEC | libc::O_NONBLOCK) 59*bb4ee6a4SAndroid Build Coastguard Worker .open(vhost_net_device_path) 60*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::VhostOpen)?, 61*bb4ee6a4SAndroid Build Coastguard Worker phantom: PhantomData, 62*bb4ee6a4SAndroid Build Coastguard Worker }) 63*bb4ee6a4SAndroid Build Coastguard Worker } 64*bb4ee6a4SAndroid Build Coastguard Worker set_backend(&self, queue_index: usize, event: Option<&T>) -> Result<()>65*bb4ee6a4SAndroid Build Coastguard Worker fn set_backend(&self, queue_index: usize, event: Option<&T>) -> Result<()> { 66*bb4ee6a4SAndroid Build Coastguard Worker let vring_file = virtio_sys::vhost::vhost_vring_file { 67*bb4ee6a4SAndroid Build Coastguard Worker index: queue_index as u32, 68*bb4ee6a4SAndroid Build Coastguard Worker fd: event.map_or(-1, |event| event.as_raw_descriptor()), 69*bb4ee6a4SAndroid Build Coastguard Worker }; 70*bb4ee6a4SAndroid Build Coastguard Worker 71*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 72*bb4ee6a4SAndroid Build Coastguard Worker // This ioctl is called on a valid vhost_net descriptor and has its 73*bb4ee6a4SAndroid Build Coastguard Worker // return value checked. 74*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { 75*bb4ee6a4SAndroid Build Coastguard Worker ioctl_with_ref( 76*bb4ee6a4SAndroid Build Coastguard Worker &self.descriptor, 77*bb4ee6a4SAndroid Build Coastguard Worker virtio_sys::VHOST_NET_SET_BACKEND, 78*bb4ee6a4SAndroid Build Coastguard Worker &vring_file, 79*bb4ee6a4SAndroid Build Coastguard Worker ) 80*bb4ee6a4SAndroid Build Coastguard Worker }; 81*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 { 82*bb4ee6a4SAndroid Build Coastguard Worker return ioctl_result(); 83*bb4ee6a4SAndroid Build Coastguard Worker } 84*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 85*bb4ee6a4SAndroid Build Coastguard Worker } 86*bb4ee6a4SAndroid Build Coastguard Worker } 87*bb4ee6a4SAndroid Build Coastguard Worker 88*bb4ee6a4SAndroid Build Coastguard Worker impl<T> Vhost for Net<T> {} 89*bb4ee6a4SAndroid Build Coastguard Worker 90*bb4ee6a4SAndroid Build Coastguard Worker impl<T> AsRawDescriptor for Net<T> { as_raw_descriptor(&self) -> RawDescriptor91*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor { 92*bb4ee6a4SAndroid Build Coastguard Worker self.descriptor.as_raw_descriptor() 93*bb4ee6a4SAndroid Build Coastguard Worker } 94*bb4ee6a4SAndroid Build Coastguard Worker } 95*bb4ee6a4SAndroid Build Coastguard Worker 96*bb4ee6a4SAndroid Build Coastguard Worker pub mod fakes { 97*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::remove_file; 98*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::OpenOptions; 99*bb4ee6a4SAndroid Build Coastguard Worker 100*bb4ee6a4SAndroid Build Coastguard Worker use super::*; 101*bb4ee6a4SAndroid Build Coastguard Worker 102*bb4ee6a4SAndroid Build Coastguard Worker const TMP_FILE: &str = "/tmp/crosvm_vhost_test_file"; 103*bb4ee6a4SAndroid Build Coastguard Worker 104*bb4ee6a4SAndroid Build Coastguard Worker pub struct FakeNet<T> { 105*bb4ee6a4SAndroid Build Coastguard Worker descriptor: File, 106*bb4ee6a4SAndroid Build Coastguard Worker phantom: PhantomData<T>, 107*bb4ee6a4SAndroid Build Coastguard Worker } 108*bb4ee6a4SAndroid Build Coastguard Worker 109*bb4ee6a4SAndroid Build Coastguard Worker impl<T> Drop for FakeNet<T> { drop(&mut self)110*bb4ee6a4SAndroid Build Coastguard Worker fn drop(&mut self) { 111*bb4ee6a4SAndroid Build Coastguard Worker let _ = remove_file(TMP_FILE); 112*bb4ee6a4SAndroid Build Coastguard Worker } 113*bb4ee6a4SAndroid Build Coastguard Worker } 114*bb4ee6a4SAndroid Build Coastguard Worker 115*bb4ee6a4SAndroid Build Coastguard Worker impl<T> NetT<T> for FakeNet<T> 116*bb4ee6a4SAndroid Build Coastguard Worker where 117*bb4ee6a4SAndroid Build Coastguard Worker T: TapT, 118*bb4ee6a4SAndroid Build Coastguard Worker { new(_vhost_net_device_path: &Path) -> Result<FakeNet<T>>119*bb4ee6a4SAndroid Build Coastguard Worker fn new(_vhost_net_device_path: &Path) -> Result<FakeNet<T>> { 120*bb4ee6a4SAndroid Build Coastguard Worker Ok(FakeNet::<T> { 121*bb4ee6a4SAndroid Build Coastguard Worker descriptor: OpenOptions::new() 122*bb4ee6a4SAndroid Build Coastguard Worker .read(true) 123*bb4ee6a4SAndroid Build Coastguard Worker .append(true) 124*bb4ee6a4SAndroid Build Coastguard Worker .create(true) 125*bb4ee6a4SAndroid Build Coastguard Worker .open(TMP_FILE) 126*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(), 127*bb4ee6a4SAndroid Build Coastguard Worker phantom: PhantomData, 128*bb4ee6a4SAndroid Build Coastguard Worker }) 129*bb4ee6a4SAndroid Build Coastguard Worker } 130*bb4ee6a4SAndroid Build Coastguard Worker set_backend(&self, _queue_index: usize, _fd: Option<&T>) -> Result<()>131*bb4ee6a4SAndroid Build Coastguard Worker fn set_backend(&self, _queue_index: usize, _fd: Option<&T>) -> Result<()> { 132*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 133*bb4ee6a4SAndroid Build Coastguard Worker } 134*bb4ee6a4SAndroid Build Coastguard Worker } 135*bb4ee6a4SAndroid Build Coastguard Worker 136*bb4ee6a4SAndroid Build Coastguard Worker impl<T> Vhost for FakeNet<T> {} 137*bb4ee6a4SAndroid Build Coastguard Worker 138*bb4ee6a4SAndroid Build Coastguard Worker impl<T> AsRawDescriptor for FakeNet<T> { as_raw_descriptor(&self) -> RawDescriptor139*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor { 140*bb4ee6a4SAndroid Build Coastguard Worker self.descriptor.as_raw_descriptor() 141*bb4ee6a4SAndroid Build Coastguard Worker } 142*bb4ee6a4SAndroid Build Coastguard Worker } 143*bb4ee6a4SAndroid Build Coastguard Worker } 144