diff --git a/src/vmm/benches/queue.rs b/src/vmm/benches/queue.rs index 9724e8227e4..de4e94ee27f 100644 --- a/src/vmm/benches/queue.rs +++ b/src/vmm/benches/queue.rs @@ -64,7 +64,7 @@ pub fn queue_benchmark(c: &mut Criterion) { let desc = queue.pop().unwrap(); c.bench_function("next_descriptor_1", |b| { b.iter(|| { - let mut head = Some(desc.clone()); + let mut head = Some(desc); while let Some(d) = head { head = std::hint::black_box(d.next_descriptor()); } @@ -76,7 +76,7 @@ pub fn queue_benchmark(c: &mut Criterion) { let desc = queue.pop().unwrap(); c.bench_function("next_descriptor_2", |b| { b.iter(|| { - let mut head = Some(desc.clone()); + let mut head = Some(desc); while let Some(d) = head { head = std::hint::black_box(d.next_descriptor()); } @@ -88,7 +88,7 @@ pub fn queue_benchmark(c: &mut Criterion) { let desc = queue.pop().unwrap(); c.bench_function("next_descriptor_4", |b| { b.iter(|| { - let mut head = Some(desc.clone()); + let mut head = Some(desc); while let Some(d) = head { head = std::hint::black_box(d.next_descriptor()); } @@ -100,7 +100,7 @@ pub fn queue_benchmark(c: &mut Criterion) { let desc = queue.pop().unwrap(); c.bench_function("next_descriptor_16", |b| { b.iter(|| { - let mut head = Some(desc.clone()); + let mut head = Some(desc); while let Some(d) = head { head = std::hint::black_box(d.next_descriptor()); } diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index 29b99cfb775..975e1588333 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -5,7 +5,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the THIRD-PARTY file. -#[cfg(not(test))] use std::io::Read; use std::mem; use std::net::Ipv4Addr; @@ -716,12 +715,10 @@ impl Net { self.tx_rate_limiter.update_buckets(tx_bytes, tx_ops); } - #[cfg(not(test))] fn read_tap(&mut self) -> std::io::Result { self.tap.read(&mut self.rx_frame_buf) } - #[cfg(not(test))] fn write_tap(tap: &mut Tap, buf: &IoVecBuffer) -> std::io::Result { tap.write_iovec(buf) } @@ -932,11 +929,11 @@ impl VirtioDevice for Net { #[cfg(test)] #[macro_use] pub mod tests { - use std::io::Read; use std::net::Ipv4Addr; + use std::os::fd::AsRawFd; use std::str::FromStr; use std::time::Duration; - use std::{io, mem, thread}; + use std::{mem, thread}; use utils::net::mac::{MacAddr, MAC_ADDR_LEN}; @@ -949,8 +946,8 @@ pub mod tests { }; use crate::devices::virtio::net::test_utils::test::TestHelper; use crate::devices::virtio::net::test_utils::{ - default_net, if_index, inject_tap_tx_frame, set_mac, NetEvent, NetQueue, ReadTapMock, - TapTrafficSimulator, WriteTapMock, + default_net, if_index, inject_tap_tx_frame, set_mac, NetEvent, NetQueue, + TapTrafficSimulator, }; use crate::devices::virtio::net::NET_QUEUE_SIZES; use crate::devices::virtio::queue::VIRTQ_DESC_F_WRITE; @@ -959,34 +956,9 @@ pub mod tests { use crate::dumbo::EthernetFrame; use crate::logger::IncMetric; use crate::rate_limiter::{BucketUpdate, RateLimiter, TokenBucket, TokenType}; + use crate::utilities::test_utils::single_region_mem; use crate::vstate::memory::{Address, GuestMemory}; - impl Net { - pub(crate) fn read_tap(&mut self) -> io::Result { - match &self.tap.mocks.read_tap { - ReadTapMock::MockFrame(frame) => { - self.rx_frame_buf[..frame.len()].copy_from_slice(frame); - Ok(frame.len()) - } - ReadTapMock::Failure => Err(io::Error::new( - io::ErrorKind::Other, - "Read tap synthetically failed.", - )), - ReadTapMock::TapFrame => self.tap.read(&mut self.rx_frame_buf), - } - } - - pub(crate) fn write_tap(tap: &mut Tap, buf: &IoVecBuffer) -> io::Result { - match tap.mocks.write_tap { - WriteTapMock::Success => tap.write_iovec(buf), - WriteTapMock::Failure => Err(io::Error::new( - io::ErrorKind::Other, - "Write tap mock failure.", - )), - } - } - } - #[test] fn test_vnet_helpers() { let mut frame_buf = vec![42u8; vnet_hdr_len() - 1]; @@ -1142,7 +1114,8 @@ pub mod tests { #[test] fn test_rx_missing_queue_signal() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); th.add_desc_chain(NetQueue::Rx, 0, &[(0, 4096, VIRTQ_DESC_F_WRITE)]); @@ -1159,7 +1132,8 @@ pub mod tests { #[test] fn test_rx_read_only_descriptor() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); th.add_desc_chain( @@ -1179,7 +1153,8 @@ pub mod tests { #[test] fn test_rx_short_writable_descriptor() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); th.add_desc_chain(NetQueue::Rx, 0, &[(0, 100, VIRTQ_DESC_F_WRITE)]); @@ -1191,7 +1166,8 @@ pub mod tests { #[test] fn test_rx_partial_write() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); // The descriptor chain is created so that the last descriptor doesn't fit in the @@ -1214,9 +1190,9 @@ pub mod tests { #[test] fn test_rx_retry() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); - th.net().tap.mocks.set_read_tap(ReadTapMock::TapFrame); // Add invalid descriptor chain - read only descriptor. th.add_desc_chain( @@ -1265,9 +1241,9 @@ pub mod tests { #[test] fn test_rx_complex_desc_chain() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); - th.net().tap.mocks.set_read_tap(ReadTapMock::TapFrame); // Create a valid Rx avail descriptor chain with multiple descriptors. th.add_desc_chain( @@ -1304,9 +1280,9 @@ pub mod tests { #[test] fn test_rx_multiple_frames() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); - th.net().tap.mocks.set_read_tap(ReadTapMock::TapFrame); // Create 2 valid Rx avail descriptor chains. Each one has enough space to fit the // following 2 frames. But only 1 frame has to be written to each chain. @@ -1348,7 +1324,8 @@ pub mod tests { #[test] fn test_tx_missing_queue_signal() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap)); @@ -1368,7 +1345,8 @@ pub mod tests { #[test] fn test_tx_writeable_descriptor() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap)); @@ -1387,7 +1365,8 @@ pub mod tests { #[test] fn test_tx_short_frame() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap)); @@ -1409,7 +1388,8 @@ pub mod tests { #[test] fn test_tx_big_frame() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap)); @@ -1435,7 +1415,8 @@ pub mod tests { #[test] fn test_tx_empty_frame() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap)); @@ -1457,7 +1438,8 @@ pub mod tests { #[test] fn test_tx_retry() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap)); @@ -1499,7 +1481,8 @@ pub mod tests { #[test] fn test_tx_complex_descriptor() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap)); @@ -1527,9 +1510,12 @@ pub mod tests { #[test] fn test_tx_tap_failure() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); - th.net().tap.mocks.set_write_tap(WriteTapMock::Failure); + // force the next write to the tap to return an error by simply closing the fd + // SAFETY: its a valid fd + unsafe { libc::close(th.net.lock().unwrap().tap.as_raw_fd()) }; let desc_list = [(0, 1000, 0)]; th.add_desc_chain(NetQueue::Tx, 0, &desc_list); @@ -1549,7 +1535,8 @@ pub mod tests { #[test] fn test_tx_multiple_frame() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap)); @@ -1702,7 +1689,8 @@ pub mod tests { #[test] fn test_process_error_cases() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); // RX rate limiter events should error since the limiter is not blocked. @@ -1727,9 +1715,12 @@ pub mod tests { // * interrupt_evt.write #[test] fn test_read_tap_fail_event_handler() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); - th.net().tap.mocks.set_read_tap(ReadTapMock::Failure); + // force the next write to the tap to return an error by simply closing the fd + // SAFETY: its a valid fd + unsafe { libc::close(th.net.lock().unwrap().tap.as_raw_fd()) }; // The RX queue is empty and rx_deffered_frame is set. th.net().rx_deferred_frame = true; @@ -1755,9 +1746,9 @@ pub mod tests { #[test] fn test_deferred_frame() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); - th.net().tap.mocks.set_read_tap(ReadTapMock::TapFrame); let rx_packets_count = th.net().metrics.rx_packets_count.count(); let _ = inject_tap_tx_frame(&th.net(), 1000); @@ -1808,7 +1799,8 @@ pub mod tests { #[test] fn test_rx_rate_limiter_handling() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); th.net().rx_rate_limiter = RateLimiter::new(0, 0, 0, 0, 0, 0).unwrap(); @@ -1822,7 +1814,8 @@ pub mod tests { #[test] fn test_tx_rate_limiter_handling() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); th.net().tx_rate_limiter = RateLimiter::new(0, 0, 0, 0, 0, 0).unwrap(); @@ -1837,7 +1830,8 @@ pub mod tests { #[test] fn test_bandwidth_rate_limiter() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); // Test TX bandwidth rate limiting @@ -1911,18 +1905,22 @@ pub mod tests { // Test RX bandwidth rate limiting { - // create bandwidth rate limiter that allows 40960 bytes/s with bucket size 4096 bytes - let mut rl = RateLimiter::new(0x1000, 0, 100, 0, 0, 0).unwrap(); - // use up the budget - assert!(rl.consume(0x1000, TokenType::Bytes)); - - // set this rx rate limiter to be used - th.net().rx_rate_limiter = rl; + // create bandwidth rate limiter that allows 2000 bytes/s with bucket size 1000 bytes + let mut rl = RateLimiter::new(1000, 0, 500, 0, 0, 0).unwrap(); // set up RX assert!(!th.net().rx_deferred_frame); th.add_desc_chain(NetQueue::Rx, 0, &[(0, 4096, VIRTQ_DESC_F_WRITE)]); + let frame = inject_tap_tx_frame(&th.net(), 1000); + + // use up the budget (do it after injecting the tx frame, as socket communication is + // slow enough that the ratelimiter could replenish in the meantime). + assert!(rl.consume(1000, TokenType::Bytes)); + + // set this rx rate limiter to be used + th.net().rx_rate_limiter = rl; + // following RX procedure should fail because of bandwidth rate limiting { // trigger the RX handler @@ -1946,13 +1944,12 @@ pub mod tests { assert_eq!(th.net().metrics.rx_rate_limiter_throttled.count(), 2); } - // wait for 100ms to give the rate-limiter timer a chance to replenish - // wait for an extra 100ms to make sure the timerfd event makes its way from the kernel - thread::sleep(Duration::from_millis(200)); + // wait for 500ms to give the rate-limiter timer a chance to replenish + // wait for an extra 500ms to make sure the timerfd event makes its way from the kernel + thread::sleep(Duration::from_millis(1000)); // following RX procedure should succeed because bandwidth should now be available { - let frame = &th.net().tap.mocks.read_tap.mock_frame(); // no longer throttled check_metric_after_block!( th.net().metrics.rx_rate_limiter_throttled, @@ -1967,14 +1964,15 @@ pub mod tests { assert_eq!(th.rxq.used.idx.get(), 1); th.rxq .check_used_elem(0, 0, frame.len().try_into().unwrap()); - th.rxq.dtable[0].check_data(frame); + th.rxq.dtable[0].check_data(&frame); } } } #[test] fn test_ops_rate_limiter() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); // Test TX ops rate limiting @@ -2025,18 +2023,20 @@ pub mod tests { // Test RX ops rate limiting { - // create ops rate limiter that allows 10 ops/s with bucket size 1 ops - let mut rl = RateLimiter::new(0, 0, 0, 1, 0, 100).unwrap(); + // create ops rate limiter that allows 2 ops/s with bucket size 1 ops + let mut rl = RateLimiter::new(0, 0, 0, 1, 0, 500).unwrap(); + + // set up RX + assert!(!th.net().rx_deferred_frame); + th.add_desc_chain(NetQueue::Rx, 0, &[(0, 4096, VIRTQ_DESC_F_WRITE)]); + let frame = inject_tap_tx_frame(&th.net(), 1234); + // use up the initial budget assert!(rl.consume(1, TokenType::Ops)); // set this rx rate limiter to be used th.net().rx_rate_limiter = rl; - // set up RX - assert!(!th.net().rx_deferred_frame); - th.add_desc_chain(NetQueue::Rx, 0, &[(0, 4096, VIRTQ_DESC_F_WRITE)]); - // following RX procedure should fail because of ops rate limiting { // trigger the RX handler @@ -2063,13 +2063,12 @@ pub mod tests { assert_eq!(th.rxq.used.idx.get(), 0); } - // wait for 100ms to give the rate-limiter timer a chance to replenish - // wait for an extra 100ms to make sure the timerfd event makes its way from the kernel - thread::sleep(Duration::from_millis(200)); + // wait for 500ms to give the rate-limiter timer a chance to replenish + // wait for an extra 500ms to make sure the timerfd event makes its way from the kernel + thread::sleep(Duration::from_millis(1000)); // following RX procedure should succeed because ops should now be available { - let frame = &th.net().tap.mocks.read_tap.mock_frame(); th.simulate_event(NetEvent::RxRateLimiter); // make sure the virtio queue operation completed this time assert!(&th.net().irq_trigger.has_pending_irq(IrqType::Vring)); @@ -2077,14 +2076,15 @@ pub mod tests { assert_eq!(th.rxq.used.idx.get(), 1); th.rxq .check_used_elem(0, 0, frame.len().try_into().unwrap()); - th.rxq.dtable[0].check_data(frame); + th.rxq.dtable[0].check_data(&frame); } } } #[test] fn test_patch_rate_limiters() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); th.net().rx_rate_limiter = RateLimiter::new(10, 0, 10, 2, 0, 2).unwrap(); @@ -2125,7 +2125,8 @@ pub mod tests { #[test] fn test_virtio_device() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.activate_net(); let net = th.net.lock().unwrap(); @@ -2146,7 +2147,8 @@ pub mod tests { fn test_queues_notification_suppression() { let features = 1 << VIRTIO_RING_F_EVENT_IDX; - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); th.net().set_acked_features(features); th.activate_net(); diff --git a/src/vmm/src/devices/virtio/net/event_handler.rs b/src/vmm/src/devices/virtio/net/event_handler.rs index 9bc0632ea2c..f6c4fddbf91 100644 --- a/src/vmm/src/devices/virtio/net/event_handler.rs +++ b/src/vmm/src/devices/virtio/net/event_handler.rs @@ -134,11 +134,13 @@ impl MutEventSubscriber for Net { pub mod tests { use crate::devices::virtio::net::test_utils::test::TestHelper; use crate::devices::virtio::net::test_utils::NetQueue; - use crate::devices::virtio::net::TX_INDEX; + use crate::devices::virtio::net::{MAX_BUFFER_SIZE, TX_INDEX}; + use crate::utilities::test_utils::single_region_mem; #[test] fn test_event_handler() { - let mut th = TestHelper::get_default(); + let mem = single_region_mem(2 * MAX_BUFFER_SIZE); + let mut th = TestHelper::get_default(&mem); // Push a queue event, use the TX_QUEUE_EVENT in this test. th.add_desc_chain(NetQueue::Tx, 0, &[(0, 4096, 0)]); diff --git a/src/vmm/src/devices/virtio/net/tap.rs b/src/vmm/src/devices/virtio/net/tap.rs index 9da0cbf5785..d6ab7d3f840 100644 --- a/src/vmm/src/devices/virtio/net/tap.rs +++ b/src/vmm/src/devices/virtio/net/tap.rs @@ -7,7 +7,7 @@ use std::fmt::{self, Debug}; use std::fs::File; -use std::io::{Error as IoError, Read, Write}; +use std::io::{Error as IoError, Read}; use std::os::raw::*; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; @@ -16,8 +16,6 @@ use utils::{ioctl_ioc_nr, ioctl_iow_nr}; use crate::devices::virtio::iovec::IoVecBuffer; use crate::devices::virtio::net::gen; -#[cfg(test)] -use crate::devices::virtio::net::test_utils::Mocks; // As defined in the Linux UAPI: // https://elixir.bootlin.com/linux/v4.17/source/include/uapi/linux/if.h#L33 @@ -53,9 +51,6 @@ ioctl_iow_nr!(TUNSETVNETHDRSZ, TUNTAP, 216, ::std::os::raw::c_int); pub struct Tap { tap_file: File, pub(crate) if_name: [u8; IFACE_NAME_MAX_LEN], - - #[cfg(test)] - pub(crate) mocks: Mocks, } // Returns a byte vector representing the contents of a null terminated C string which @@ -149,9 +144,6 @@ impl Tap { tap_file: tuntap, // SAFETY: Safe since only the name is accessed, and it's cloned out. if_name: unsafe { ifreq.ifr_ifrn.ifrn_name }, - - #[cfg(test)] - mocks: Mocks::default(), }) } @@ -206,16 +198,6 @@ impl Read for Tap { } } -impl Write for Tap { - fn write(&mut self, buf: &[u8]) -> Result { - self.tap_file.write(buf) - } - - fn flush(&mut self) -> Result<(), IoError> { - Ok(()) - } -} - impl AsRawFd for Tap { fn as_raw_fd(&self) -> RawFd { self.tap_file.as_raw_fd() @@ -288,7 +270,6 @@ pub mod tests { let faulty_tap = Tap { tap_file: unsafe { File::from_raw_fd(-2) }, if_name: [0x01; 16], - mocks: Default::default(), }; assert_eq!( faulty_tap.set_vnet_hdr_size(16).unwrap_err().to_string(), @@ -323,26 +304,6 @@ pub mod tests { ); } - #[test] - fn test_write() { - let mut tap = Tap::open_named("").unwrap(); - enable(&tap); - let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&tap)); - - let mut packet = [0u8; PACKET_SIZE]; - let payload = utils::rand::rand_alphanumerics(PAYLOAD_SIZE); - packet[gen::ETH_HLEN as usize..payload.len() + gen::ETH_HLEN as usize] - .copy_from_slice(payload.as_bytes()); - assert_eq!(tap.write(&packet).unwrap(), PACKET_SIZE); - - let mut read_buf = [0u8; PACKET_SIZE]; - assert!(tap_traffic_simulator.pop_rx_packet(&mut read_buf)); - assert_eq!( - &read_buf[..PACKET_SIZE - VNET_HDR_SIZE], - &packet[VNET_HDR_SIZE..] - ); - } - #[test] fn test_write_iovec() { let mut tap = Tap::open_named("").unwrap(); diff --git a/src/vmm/src/devices/virtio/net/test_utils.rs b/src/vmm/src/devices/virtio/net/test_utils.rs index c2bffa1d2a9..efbafba482f 100644 --- a/src/vmm/src/devices/virtio/net/test_utils.rs +++ b/src/vmm/src/devices/virtio/net/test_utils.rs @@ -6,7 +6,6 @@ use std::fs::File; use std::mem; use std::os::raw::c_ulong; -use std::os::unix::ffi::OsStrExt; use std::os::unix::io::{AsRawFd, FromRawFd}; use std::process::Command; use std::str::FromStr; @@ -77,56 +76,6 @@ pub fn default_net_no_mmds() -> Net { net } -#[derive(Debug)] -pub enum ReadTapMock { - Failure, - MockFrame(Vec), - TapFrame, -} - -impl ReadTapMock { - pub fn mock_frame(&self) -> Vec { - if let ReadTapMock::MockFrame(frame) = self { - return frame.clone(); - } - panic!("Can't get last mock frame"); - } -} - -#[derive(Debug)] -pub enum WriteTapMock { - Failure, - Success, -} - -// Used to simulate tap read and write fails in tests. -#[derive(Debug)] -pub struct Mocks { - pub(crate) read_tap: ReadTapMock, - pub(crate) write_tap: WriteTapMock, -} - -impl Mocks { - pub fn set_read_tap(&mut self, read_tap: ReadTapMock) { - self.read_tap = read_tap; - } - - pub fn set_write_tap(&mut self, write_tap: WriteTapMock) { - self.write_tap = write_tap; - } -} - -impl Default for Mocks { - fn default() -> Mocks { - Mocks { - read_tap: ReadTapMock::MockFrame( - utils::rand::rand_alphanumerics(1234).as_bytes().to_vec(), - ), - write_tap: WriteTapMock::Success, - } - } -} - #[derive(Debug)] pub enum NetQueue { Rx, @@ -298,6 +247,8 @@ pub fn enable(tap: &Tap) { #[cfg(test)] pub(crate) fn inject_tap_tx_frame(net: &Net, len: usize) -> Vec { + use std::os::unix::ffi::OsStrExt; + assert!(len >= vnet_hdr_len()); let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&net.tap)); let mut frame = utils::rand::rand_alphanumerics(len - vnet_hdr_len()) @@ -349,7 +300,7 @@ pub mod test { #![allow(clippy::undocumented_unsafe_blocks)] use std::os::unix::ffi::OsStrExt; use std::sync::{Arc, Mutex, MutexGuard}; - use std::{cmp, fmt, mem}; + use std::{cmp, fmt}; use event_manager::{EventManager, SubscriberId, SubscriberOps}; @@ -358,20 +309,19 @@ pub mod test { use crate::devices::virtio::net::device::vnet_hdr_len; use crate::devices::virtio::net::gen::ETH_HLEN; use crate::devices::virtio::net::test_utils::{ - assign_queues, default_net, inject_tap_tx_frame, NetEvent, NetQueue, ReadTapMock, + assign_queues, default_net, inject_tap_tx_frame, NetEvent, NetQueue, }; - use crate::devices::virtio::net::{Net, MAX_BUFFER_SIZE, RX_INDEX, TX_INDEX}; + use crate::devices::virtio::net::{Net, RX_INDEX, TX_INDEX}; use crate::devices::virtio::queue::{VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE}; use crate::devices::virtio::test_utils::{VirtQueue, VirtqDesc}; use crate::logger::IncMetric; - use crate::utilities::test_utils::single_region_mem; use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemoryMmap}; pub struct TestHelper<'a> { pub event_manager: EventManager>>, pub subscriber_id: SubscriberId, pub net: Arc>, - pub mem: GuestMemoryMmap, + pub mem: &'a GuestMemoryMmap, pub rxq: VirtQueue<'a>, pub txq: VirtQueue<'a>, } @@ -392,18 +342,14 @@ pub mod test { impl<'a> TestHelper<'a> { const QUEUE_SIZE: u16 = 16; - pub fn get_default() -> TestHelper<'a> { + pub fn get_default(mem: &'a GuestMemoryMmap) -> TestHelper<'a> { let mut event_manager = EventManager::new().unwrap(); let mut net = default_net(); - let mem = single_region_mem(2 * MAX_BUFFER_SIZE); - - // transmute mem_ref lifetime to 'a - let mem_ref = unsafe { mem::transmute::<&GuestMemoryMmap, &'a GuestMemoryMmap>(&mem) }; - let rxq = VirtQueue::new(GuestAddress(0), mem_ref, Self::QUEUE_SIZE); + let rxq = VirtQueue::new(GuestAddress(0), mem, Self::QUEUE_SIZE); let txq = VirtQueue::new( rxq.end().unchecked_align_up(VirtqDesc::ALIGNMENT), - mem_ref, + mem, Self::QUEUE_SIZE, ); assign_queues(&mut net, rxq.create_queue(), txq.create_queue()); @@ -487,7 +433,6 @@ pub mod test { /// Generate a tap frame of `frame_len` and check that it is deferred pub fn check_rx_deferred_frame(&mut self, frame_len: usize) -> Vec { - self.net().tap.mocks.set_read_tap(ReadTapMock::TapFrame); let used_idx = self.rxq.used.idx.get(); // Inject frame to tap and run epoll.