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 mod sys;
6*bb4ee6a4SAndroid Build Coastguard Worker
7*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::net::Ipv4Addr;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_uint;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::str::FromStr;
15*bb4ee6a4SAndroid Build Coastguard Worker
16*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow;
17*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
19*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
20*bb4ee6a4SAndroid Build Coastguard Worker use base::named_pipes::OverlappedWrapper;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
22*bb4ee6a4SAndroid Build Coastguard Worker use base::Error as SysError;
23*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
24*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken;
25*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
26*bb4ee6a4SAndroid Build Coastguard Worker use base::ReadNotifier;
27*bb4ee6a4SAndroid Build Coastguard Worker use base::WaitContext;
28*bb4ee6a4SAndroid Build Coastguard Worker use base::WorkerThread;
29*bb4ee6a4SAndroid Build Coastguard Worker use data_model::Le16;
30*bb4ee6a4SAndroid Build Coastguard Worker use data_model::Le64;
31*bb4ee6a4SAndroid Build Coastguard Worker use net_util::Error as TapError;
32*bb4ee6a4SAndroid Build Coastguard Worker use net_util::MacAddress;
33*bb4ee6a4SAndroid Build Coastguard Worker use net_util::TapT;
34*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
35*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
36*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
37*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error as ThisError;
38*bb4ee6a4SAndroid Build Coastguard Worker use virtio_sys::virtio_config::VIRTIO_F_RING_PACKED;
39*bb4ee6a4SAndroid Build Coastguard Worker use virtio_sys::virtio_net;
40*bb4ee6a4SAndroid Build Coastguard Worker use virtio_sys::virtio_net::VIRTIO_NET_CTRL_GUEST_OFFLOADS;
41*bb4ee6a4SAndroid Build Coastguard Worker use virtio_sys::virtio_net::VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET;
42*bb4ee6a4SAndroid Build Coastguard Worker use virtio_sys::virtio_net::VIRTIO_NET_CTRL_MQ;
43*bb4ee6a4SAndroid Build Coastguard Worker use virtio_sys::virtio_net::VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET;
44*bb4ee6a4SAndroid Build Coastguard Worker use virtio_sys::virtio_net::VIRTIO_NET_ERR;
45*bb4ee6a4SAndroid Build Coastguard Worker use virtio_sys::virtio_net::VIRTIO_NET_OK;
46*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
47*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
48*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes;
49*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromZeroes;
50*bb4ee6a4SAndroid Build Coastguard Worker
51*bb4ee6a4SAndroid Build Coastguard Worker use super::copy_config;
52*bb4ee6a4SAndroid Build Coastguard Worker use super::DeviceType;
53*bb4ee6a4SAndroid Build Coastguard Worker use super::Interrupt;
54*bb4ee6a4SAndroid Build Coastguard Worker use super::Queue;
55*bb4ee6a4SAndroid Build Coastguard Worker use super::Reader;
56*bb4ee6a4SAndroid Build Coastguard Worker use super::VirtioDevice;
57*bb4ee6a4SAndroid Build Coastguard Worker use crate::PciAddress;
58*bb4ee6a4SAndroid Build Coastguard Worker
59*bb4ee6a4SAndroid Build Coastguard Worker /// The maximum buffer size when segmentation offload is enabled. This
60*bb4ee6a4SAndroid Build Coastguard Worker /// includes the 12-byte virtio net header.
61*bb4ee6a4SAndroid Build Coastguard Worker /// http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html#x1-1740003
62*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
63*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) const MAX_BUFFER_SIZE: usize = 65562;
64*bb4ee6a4SAndroid Build Coastguard Worker const QUEUE_SIZE: u16 = 256;
65*bb4ee6a4SAndroid Build Coastguard Worker
66*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
67*bb4ee6a4SAndroid Build Coastguard Worker pub static VHOST_NET_DEFAULT_PATH: &str = "/dev/vhost-net";
68*bb4ee6a4SAndroid Build Coastguard Worker
69*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use sys::process_rx;
70*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use sys::process_tx;
71*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use sys::validate_and_configure_tap;
72*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use sys::virtio_features_to_tap_offload;
73*bb4ee6a4SAndroid Build Coastguard Worker
74*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
75*bb4ee6a4SAndroid Build Coastguard Worker #[derive(ThisError, Debug)]
76*bb4ee6a4SAndroid Build Coastguard Worker pub enum NetError {
77*bb4ee6a4SAndroid Build Coastguard Worker /// Cloning kill event failed.
78*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to clone kill event: {0}")]
79*bb4ee6a4SAndroid Build Coastguard Worker CloneKillEvent(SysError),
80*bb4ee6a4SAndroid Build Coastguard Worker /// Creating kill event failed.
81*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create kill event: {0}")]
82*bb4ee6a4SAndroid Build Coastguard Worker CreateKillEvent(SysError),
83*bb4ee6a4SAndroid Build Coastguard Worker /// Creating WaitContext failed.
84*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create wait context: {0}")]
85*bb4ee6a4SAndroid Build Coastguard Worker CreateWaitContext(SysError),
86*bb4ee6a4SAndroid Build Coastguard Worker /// Adding the tap descriptor back to the event context failed.
87*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to add tap trigger to event context: {0}")]
88*bb4ee6a4SAndroid Build Coastguard Worker EventAddTap(SysError),
89*bb4ee6a4SAndroid Build Coastguard Worker /// Removing the tap descriptor from the event context failed.
90*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to remove tap trigger from event context: {0}")]
91*bb4ee6a4SAndroid Build Coastguard Worker EventRemoveTap(SysError),
92*bb4ee6a4SAndroid Build Coastguard Worker /// Invalid control command
93*bb4ee6a4SAndroid Build Coastguard Worker #[error("invalid control command")]
94*bb4ee6a4SAndroid Build Coastguard Worker InvalidCmd,
95*bb4ee6a4SAndroid Build Coastguard Worker /// Error reading data from control queue.
96*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to read control message data: {0}")]
97*bb4ee6a4SAndroid Build Coastguard Worker ReadCtrlData(io::Error),
98*bb4ee6a4SAndroid Build Coastguard Worker /// Error reading header from control queue.
99*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to read control message header: {0}")]
100*bb4ee6a4SAndroid Build Coastguard Worker ReadCtrlHeader(io::Error),
101*bb4ee6a4SAndroid Build Coastguard Worker /// There are no more available descriptors to receive into.
102*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
103*bb4ee6a4SAndroid Build Coastguard Worker #[error("no rx descriptors available")]
104*bb4ee6a4SAndroid Build Coastguard Worker RxDescriptorsExhausted,
105*bb4ee6a4SAndroid Build Coastguard Worker /// Failure creating the Slirp loop.
106*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
107*bb4ee6a4SAndroid Build Coastguard Worker #[error("error creating Slirp: {0}")]
108*bb4ee6a4SAndroid Build Coastguard Worker SlirpCreateError(net_util::Error),
109*bb4ee6a4SAndroid Build Coastguard Worker /// Enabling tap interface failed.
110*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to enable tap interface: {0}")]
111*bb4ee6a4SAndroid Build Coastguard Worker TapEnable(TapError),
112*bb4ee6a4SAndroid Build Coastguard Worker /// Couldn't get the MTU from the tap device.
113*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to get tap interface MTU: {0}")]
114*bb4ee6a4SAndroid Build Coastguard Worker TapGetMtu(TapError),
115*bb4ee6a4SAndroid Build Coastguard Worker /// Open tap device failed.
116*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to open tap device: {0}")]
117*bb4ee6a4SAndroid Build Coastguard Worker TapOpen(TapError),
118*bb4ee6a4SAndroid Build Coastguard Worker /// Setting tap IP failed.
119*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to set tap IP: {0}")]
120*bb4ee6a4SAndroid Build Coastguard Worker TapSetIp(TapError),
121*bb4ee6a4SAndroid Build Coastguard Worker /// Setting tap mac address failed.
122*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to set tap mac address: {0}")]
123*bb4ee6a4SAndroid Build Coastguard Worker TapSetMacAddress(TapError),
124*bb4ee6a4SAndroid Build Coastguard Worker /// Setting tap netmask failed.
125*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to set tap netmask: {0}")]
126*bb4ee6a4SAndroid Build Coastguard Worker TapSetNetmask(TapError),
127*bb4ee6a4SAndroid Build Coastguard Worker /// Setting tap offload failed.
128*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to set tap offload: {0}")]
129*bb4ee6a4SAndroid Build Coastguard Worker TapSetOffload(TapError),
130*bb4ee6a4SAndroid Build Coastguard Worker /// Setting vnet header size failed.
131*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to set vnet header size: {0}")]
132*bb4ee6a4SAndroid Build Coastguard Worker TapSetVnetHdrSize(TapError),
133*bb4ee6a4SAndroid Build Coastguard Worker /// Validating tap interface failed.
134*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to validate tap interface: {0}")]
135*bb4ee6a4SAndroid Build Coastguard Worker TapValidate(String),
136*bb4ee6a4SAndroid Build Coastguard Worker /// Removing read event from the tap fd events failed.
137*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to disable EPOLLIN on tap fd: {0}")]
138*bb4ee6a4SAndroid Build Coastguard Worker WaitContextDisableTap(SysError),
139*bb4ee6a4SAndroid Build Coastguard Worker /// Adding read event to the tap fd events failed.
140*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to enable EPOLLIN on tap fd: {0}")]
141*bb4ee6a4SAndroid Build Coastguard Worker WaitContextEnableTap(SysError),
142*bb4ee6a4SAndroid Build Coastguard Worker /// Error while waiting for events.
143*bb4ee6a4SAndroid Build Coastguard Worker #[error("error while waiting for events: {0}")]
144*bb4ee6a4SAndroid Build Coastguard Worker WaitError(SysError),
145*bb4ee6a4SAndroid Build Coastguard Worker /// Failed writing an ack in response to a control message.
146*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to write control message ack: {0}")]
147*bb4ee6a4SAndroid Build Coastguard Worker WriteAck(io::Error),
148*bb4ee6a4SAndroid Build Coastguard Worker /// Writing to a buffer in the guest failed.
149*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
150*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to write to guest buffer: {0}")]
151*bb4ee6a4SAndroid Build Coastguard Worker WriteBuffer(io::Error),
152*bb4ee6a4SAndroid Build Coastguard Worker }
153*bb4ee6a4SAndroid Build Coastguard Worker
154*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
155*bb4ee6a4SAndroid Build Coastguard Worker #[serde(untagged, deny_unknown_fields)]
156*bb4ee6a4SAndroid Build Coastguard Worker pub enum NetParametersMode {
157*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename_all = "kebab-case")]
158*bb4ee6a4SAndroid Build Coastguard Worker TapName {
159*bb4ee6a4SAndroid Build Coastguard Worker tap_name: String,
160*bb4ee6a4SAndroid Build Coastguard Worker mac: Option<MacAddress>,
161*bb4ee6a4SAndroid Build Coastguard Worker },
162*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename_all = "kebab-case")]
163*bb4ee6a4SAndroid Build Coastguard Worker TapFd {
164*bb4ee6a4SAndroid Build Coastguard Worker tap_fd: i32,
165*bb4ee6a4SAndroid Build Coastguard Worker mac: Option<MacAddress>,
166*bb4ee6a4SAndroid Build Coastguard Worker },
167*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename_all = "kebab-case")]
168*bb4ee6a4SAndroid Build Coastguard Worker RawConfig {
169*bb4ee6a4SAndroid Build Coastguard Worker host_ip: Ipv4Addr,
170*bb4ee6a4SAndroid Build Coastguard Worker netmask: Ipv4Addr,
171*bb4ee6a4SAndroid Build Coastguard Worker mac: MacAddress,
172*bb4ee6a4SAndroid Build Coastguard Worker },
173*bb4ee6a4SAndroid Build Coastguard Worker }
174*bb4ee6a4SAndroid Build Coastguard Worker
175*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
vhost_net_device_path_default() -> PathBuf176*bb4ee6a4SAndroid Build Coastguard Worker fn vhost_net_device_path_default() -> PathBuf {
177*bb4ee6a4SAndroid Build Coastguard Worker PathBuf::from(VHOST_NET_DEFAULT_PATH)
178*bb4ee6a4SAndroid Build Coastguard Worker }
179*bb4ee6a4SAndroid Build Coastguard Worker
180*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
181*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
182*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename_all = "kebab-case", deny_unknown_fields)]
183*bb4ee6a4SAndroid Build Coastguard Worker pub struct VhostNetParameters {
184*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default = "vhost_net_device_path_default")]
185*bb4ee6a4SAndroid Build Coastguard Worker pub device: PathBuf,
186*bb4ee6a4SAndroid Build Coastguard Worker }
187*bb4ee6a4SAndroid Build Coastguard Worker
188*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
189*bb4ee6a4SAndroid Build Coastguard Worker impl Default for VhostNetParameters {
default() -> Self190*bb4ee6a4SAndroid Build Coastguard Worker fn default() -> Self {
191*bb4ee6a4SAndroid Build Coastguard Worker Self {
192*bb4ee6a4SAndroid Build Coastguard Worker device: vhost_net_device_path_default(),
193*bb4ee6a4SAndroid Build Coastguard Worker }
194*bb4ee6a4SAndroid Build Coastguard Worker }
195*bb4ee6a4SAndroid Build Coastguard Worker }
196*bb4ee6a4SAndroid Build Coastguard Worker
197*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
198*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename_all = "kebab-case")]
199*bb4ee6a4SAndroid Build Coastguard Worker pub struct NetParameters {
200*bb4ee6a4SAndroid Build Coastguard Worker #[serde(flatten)]
201*bb4ee6a4SAndroid Build Coastguard Worker pub mode: NetParametersMode,
202*bb4ee6a4SAndroid Build Coastguard Worker pub vq_pairs: Option<u16>,
203*bb4ee6a4SAndroid Build Coastguard Worker // Style-guide asks to refrain against #[cfg] directives in structs, this is an exception due
204*bb4ee6a4SAndroid Build Coastguard Worker // to the fact this struct is used for argument parsing.
205*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
206*bb4ee6a4SAndroid Build Coastguard Worker pub vhost_net: Option<VhostNetParameters>,
207*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)]
208*bb4ee6a4SAndroid Build Coastguard Worker pub packed_queue: bool,
209*bb4ee6a4SAndroid Build Coastguard Worker pub pci_address: Option<PciAddress>,
210*bb4ee6a4SAndroid Build Coastguard Worker }
211*bb4ee6a4SAndroid Build Coastguard Worker
212*bb4ee6a4SAndroid Build Coastguard Worker impl FromStr for NetParameters {
213*bb4ee6a4SAndroid Build Coastguard Worker type Err = String;
from_str(s: &str) -> Result<Self, Self::Err>214*bb4ee6a4SAndroid Build Coastguard Worker fn from_str(s: &str) -> Result<Self, Self::Err> {
215*bb4ee6a4SAndroid Build Coastguard Worker serde_keyvalue::from_key_values(s).map_err(|e| e.to_string())
216*bb4ee6a4SAndroid Build Coastguard Worker }
217*bb4ee6a4SAndroid Build Coastguard Worker }
218*bb4ee6a4SAndroid Build Coastguard Worker
219*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)]
220*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy, AsBytes, FromZeroes, FromBytes)]
221*bb4ee6a4SAndroid Build Coastguard Worker pub struct virtio_net_ctrl_hdr {
222*bb4ee6a4SAndroid Build Coastguard Worker pub class: u8,
223*bb4ee6a4SAndroid Build Coastguard Worker pub cmd: u8,
224*bb4ee6a4SAndroid Build Coastguard Worker }
225*bb4ee6a4SAndroid Build Coastguard Worker
226*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy, Default, AsBytes, FromZeroes, FromBytes)]
227*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
228*bb4ee6a4SAndroid Build Coastguard Worker pub struct VirtioNetConfig {
229*bb4ee6a4SAndroid Build Coastguard Worker mac: [u8; 6],
230*bb4ee6a4SAndroid Build Coastguard Worker status: Le16,
231*bb4ee6a4SAndroid Build Coastguard Worker max_vq_pairs: Le16,
232*bb4ee6a4SAndroid Build Coastguard Worker mtu: Le16,
233*bb4ee6a4SAndroid Build Coastguard Worker }
234*bb4ee6a4SAndroid Build Coastguard Worker
process_ctrl_request<T: TapT>( reader: &mut Reader, tap: &mut T, acked_features: u64, vq_pairs: u16, ) -> Result<(), NetError>235*bb4ee6a4SAndroid Build Coastguard Worker fn process_ctrl_request<T: TapT>(
236*bb4ee6a4SAndroid Build Coastguard Worker reader: &mut Reader,
237*bb4ee6a4SAndroid Build Coastguard Worker tap: &mut T,
238*bb4ee6a4SAndroid Build Coastguard Worker acked_features: u64,
239*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: u16,
240*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(), NetError> {
241*bb4ee6a4SAndroid Build Coastguard Worker let ctrl_hdr: virtio_net_ctrl_hdr = reader.read_obj().map_err(NetError::ReadCtrlHeader)?;
242*bb4ee6a4SAndroid Build Coastguard Worker
243*bb4ee6a4SAndroid Build Coastguard Worker match ctrl_hdr.class as c_uint {
244*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_NET_CTRL_GUEST_OFFLOADS => {
245*bb4ee6a4SAndroid Build Coastguard Worker if ctrl_hdr.cmd != VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET as u8 {
246*bb4ee6a4SAndroid Build Coastguard Worker error!(
247*bb4ee6a4SAndroid Build Coastguard Worker "invalid cmd for VIRTIO_NET_CTRL_GUEST_OFFLOADS: {}",
248*bb4ee6a4SAndroid Build Coastguard Worker ctrl_hdr.cmd
249*bb4ee6a4SAndroid Build Coastguard Worker );
250*bb4ee6a4SAndroid Build Coastguard Worker return Err(NetError::InvalidCmd);
251*bb4ee6a4SAndroid Build Coastguard Worker }
252*bb4ee6a4SAndroid Build Coastguard Worker let offloads: Le64 = reader.read_obj().map_err(NetError::ReadCtrlData)?;
253*bb4ee6a4SAndroid Build Coastguard Worker let tap_offloads = virtio_features_to_tap_offload(offloads.into());
254*bb4ee6a4SAndroid Build Coastguard Worker tap.set_offload(tap_offloads)
255*bb4ee6a4SAndroid Build Coastguard Worker .map_err(NetError::TapSetOffload)?;
256*bb4ee6a4SAndroid Build Coastguard Worker }
257*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_NET_CTRL_MQ => {
258*bb4ee6a4SAndroid Build Coastguard Worker if ctrl_hdr.cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET as u8 {
259*bb4ee6a4SAndroid Build Coastguard Worker let pairs: Le16 = reader.read_obj().map_err(NetError::ReadCtrlData)?;
260*bb4ee6a4SAndroid Build Coastguard Worker // Simple handle it now
261*bb4ee6a4SAndroid Build Coastguard Worker if acked_features & 1 << virtio_net::VIRTIO_NET_F_MQ == 0
262*bb4ee6a4SAndroid Build Coastguard Worker || pairs.to_native() != vq_pairs
263*bb4ee6a4SAndroid Build Coastguard Worker {
264*bb4ee6a4SAndroid Build Coastguard Worker error!(
265*bb4ee6a4SAndroid Build Coastguard Worker "Invalid VQ_PAIRS_SET cmd, driver request pairs: {}, device vq pairs: {}",
266*bb4ee6a4SAndroid Build Coastguard Worker pairs.to_native(),
267*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs
268*bb4ee6a4SAndroid Build Coastguard Worker );
269*bb4ee6a4SAndroid Build Coastguard Worker return Err(NetError::InvalidCmd);
270*bb4ee6a4SAndroid Build Coastguard Worker }
271*bb4ee6a4SAndroid Build Coastguard Worker }
272*bb4ee6a4SAndroid Build Coastguard Worker }
273*bb4ee6a4SAndroid Build Coastguard Worker _ => {
274*bb4ee6a4SAndroid Build Coastguard Worker warn!(
275*bb4ee6a4SAndroid Build Coastguard Worker "unimplemented class for VIRTIO_NET_CTRL_GUEST_OFFLOADS: {}",
276*bb4ee6a4SAndroid Build Coastguard Worker ctrl_hdr.class
277*bb4ee6a4SAndroid Build Coastguard Worker );
278*bb4ee6a4SAndroid Build Coastguard Worker return Err(NetError::InvalidCmd);
279*bb4ee6a4SAndroid Build Coastguard Worker }
280*bb4ee6a4SAndroid Build Coastguard Worker }
281*bb4ee6a4SAndroid Build Coastguard Worker
282*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
283*bb4ee6a4SAndroid Build Coastguard Worker }
284*bb4ee6a4SAndroid Build Coastguard Worker
process_ctrl<T: TapT>( ctrl_queue: &mut Queue, tap: &mut T, acked_features: u64, vq_pairs: u16, ) -> Result<(), NetError>285*bb4ee6a4SAndroid Build Coastguard Worker pub fn process_ctrl<T: TapT>(
286*bb4ee6a4SAndroid Build Coastguard Worker ctrl_queue: &mut Queue,
287*bb4ee6a4SAndroid Build Coastguard Worker tap: &mut T,
288*bb4ee6a4SAndroid Build Coastguard Worker acked_features: u64,
289*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: u16,
290*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(), NetError> {
291*bb4ee6a4SAndroid Build Coastguard Worker while let Some(mut desc_chain) = ctrl_queue.pop() {
292*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = process_ctrl_request(&mut desc_chain.reader, tap, acked_features, vq_pairs)
293*bb4ee6a4SAndroid Build Coastguard Worker {
294*bb4ee6a4SAndroid Build Coastguard Worker error!("process_ctrl_request failed: {}", e);
295*bb4ee6a4SAndroid Build Coastguard Worker desc_chain
296*bb4ee6a4SAndroid Build Coastguard Worker .writer
297*bb4ee6a4SAndroid Build Coastguard Worker .write_all(&[VIRTIO_NET_ERR as u8])
298*bb4ee6a4SAndroid Build Coastguard Worker .map_err(NetError::WriteAck)?;
299*bb4ee6a4SAndroid Build Coastguard Worker } else {
300*bb4ee6a4SAndroid Build Coastguard Worker desc_chain
301*bb4ee6a4SAndroid Build Coastguard Worker .writer
302*bb4ee6a4SAndroid Build Coastguard Worker .write_all(&[VIRTIO_NET_OK as u8])
303*bb4ee6a4SAndroid Build Coastguard Worker .map_err(NetError::WriteAck)?;
304*bb4ee6a4SAndroid Build Coastguard Worker }
305*bb4ee6a4SAndroid Build Coastguard Worker let len = desc_chain.writer.bytes_written() as u32;
306*bb4ee6a4SAndroid Build Coastguard Worker ctrl_queue.add_used(desc_chain, len);
307*bb4ee6a4SAndroid Build Coastguard Worker }
308*bb4ee6a4SAndroid Build Coastguard Worker
309*bb4ee6a4SAndroid Build Coastguard Worker ctrl_queue.trigger_interrupt();
310*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
311*bb4ee6a4SAndroid Build Coastguard Worker }
312*bb4ee6a4SAndroid Build Coastguard Worker
313*bb4ee6a4SAndroid Build Coastguard Worker #[derive(EventToken, Debug, Clone)]
314*bb4ee6a4SAndroid Build Coastguard Worker pub enum Token {
315*bb4ee6a4SAndroid Build Coastguard Worker // A frame is available for reading from the tap device to receive in the guest.
316*bb4ee6a4SAndroid Build Coastguard Worker RxTap,
317*bb4ee6a4SAndroid Build Coastguard Worker // The guest has made a buffer available to receive a frame into.
318*bb4ee6a4SAndroid Build Coastguard Worker RxQueue,
319*bb4ee6a4SAndroid Build Coastguard Worker // The transmit queue has a frame that is ready to send from the guest.
320*bb4ee6a4SAndroid Build Coastguard Worker TxQueue,
321*bb4ee6a4SAndroid Build Coastguard Worker // The control queue has a message.
322*bb4ee6a4SAndroid Build Coastguard Worker CtrlQueue,
323*bb4ee6a4SAndroid Build Coastguard Worker // Check if any interrupts need to be re-asserted.
324*bb4ee6a4SAndroid Build Coastguard Worker InterruptResample,
325*bb4ee6a4SAndroid Build Coastguard Worker // crosvm has requested the device to shut down.
326*bb4ee6a4SAndroid Build Coastguard Worker Kill,
327*bb4ee6a4SAndroid Build Coastguard Worker }
328*bb4ee6a4SAndroid Build Coastguard Worker
329*bb4ee6a4SAndroid Build Coastguard Worker pub(super) struct Worker<T: TapT> {
330*bb4ee6a4SAndroid Build Coastguard Worker pub(super) interrupt: Interrupt,
331*bb4ee6a4SAndroid Build Coastguard Worker pub(super) rx_queue: Queue,
332*bb4ee6a4SAndroid Build Coastguard Worker pub(super) tx_queue: Queue,
333*bb4ee6a4SAndroid Build Coastguard Worker pub(super) ctrl_queue: Option<Queue>,
334*bb4ee6a4SAndroid Build Coastguard Worker pub(super) tap: T,
335*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
336*bb4ee6a4SAndroid Build Coastguard Worker pub(super) overlapped_wrapper: OverlappedWrapper,
337*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
338*bb4ee6a4SAndroid Build Coastguard Worker pub(super) rx_buf: [u8; MAX_BUFFER_SIZE],
339*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
340*bb4ee6a4SAndroid Build Coastguard Worker pub(super) rx_count: usize,
341*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
342*bb4ee6a4SAndroid Build Coastguard Worker pub(super) deferred_rx: bool,
343*bb4ee6a4SAndroid Build Coastguard Worker acked_features: u64,
344*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: u16,
345*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
346*bb4ee6a4SAndroid Build Coastguard Worker kill_evt: Event,
347*bb4ee6a4SAndroid Build Coastguard Worker }
348*bb4ee6a4SAndroid Build Coastguard Worker
349*bb4ee6a4SAndroid Build Coastguard Worker impl<T> Worker<T>
350*bb4ee6a4SAndroid Build Coastguard Worker where
351*bb4ee6a4SAndroid Build Coastguard Worker T: TapT + ReadNotifier,
352*bb4ee6a4SAndroid Build Coastguard Worker {
process_tx(&mut self)353*bb4ee6a4SAndroid Build Coastguard Worker fn process_tx(&mut self) {
354*bb4ee6a4SAndroid Build Coastguard Worker process_tx(&mut self.tx_queue, &mut self.tap)
355*bb4ee6a4SAndroid Build Coastguard Worker }
356*bb4ee6a4SAndroid Build Coastguard Worker
process_ctrl(&mut self) -> Result<(), NetError>357*bb4ee6a4SAndroid Build Coastguard Worker fn process_ctrl(&mut self) -> Result<(), NetError> {
358*bb4ee6a4SAndroid Build Coastguard Worker let ctrl_queue = match self.ctrl_queue.as_mut() {
359*bb4ee6a4SAndroid Build Coastguard Worker Some(queue) => queue,
360*bb4ee6a4SAndroid Build Coastguard Worker None => return Ok(()),
361*bb4ee6a4SAndroid Build Coastguard Worker };
362*bb4ee6a4SAndroid Build Coastguard Worker
363*bb4ee6a4SAndroid Build Coastguard Worker process_ctrl(
364*bb4ee6a4SAndroid Build Coastguard Worker ctrl_queue,
365*bb4ee6a4SAndroid Build Coastguard Worker &mut self.tap,
366*bb4ee6a4SAndroid Build Coastguard Worker self.acked_features,
367*bb4ee6a4SAndroid Build Coastguard Worker self.vq_pairs,
368*bb4ee6a4SAndroid Build Coastguard Worker )
369*bb4ee6a4SAndroid Build Coastguard Worker }
370*bb4ee6a4SAndroid Build Coastguard Worker
run(&mut self, handle_interrupt_resample: bool) -> Result<(), NetError>371*bb4ee6a4SAndroid Build Coastguard Worker fn run(&mut self, handle_interrupt_resample: bool) -> Result<(), NetError> {
372*bb4ee6a4SAndroid Build Coastguard Worker let wait_ctx: WaitContext<Token> = WaitContext::build_with(&[
373*bb4ee6a4SAndroid Build Coastguard Worker // This doesn't use get_read_notifier() because of overlapped io; we
374*bb4ee6a4SAndroid Build Coastguard Worker // have overlapped wrapper separate from the TAP so that we can pass
375*bb4ee6a4SAndroid Build Coastguard Worker // the overlapped wrapper into the read function. This overlapped
376*bb4ee6a4SAndroid Build Coastguard Worker // wrapper's event is where we get the read notification.
377*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
378*bb4ee6a4SAndroid Build Coastguard Worker (
379*bb4ee6a4SAndroid Build Coastguard Worker self.overlapped_wrapper.get_h_event_ref().unwrap(),
380*bb4ee6a4SAndroid Build Coastguard Worker Token::RxTap,
381*bb4ee6a4SAndroid Build Coastguard Worker ),
382*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
383*bb4ee6a4SAndroid Build Coastguard Worker (self.tap.get_read_notifier(), Token::RxTap),
384*bb4ee6a4SAndroid Build Coastguard Worker (self.rx_queue.event(), Token::RxQueue),
385*bb4ee6a4SAndroid Build Coastguard Worker (self.tx_queue.event(), Token::TxQueue),
386*bb4ee6a4SAndroid Build Coastguard Worker (&self.kill_evt, Token::Kill),
387*bb4ee6a4SAndroid Build Coastguard Worker ])
388*bb4ee6a4SAndroid Build Coastguard Worker .map_err(NetError::CreateWaitContext)?;
389*bb4ee6a4SAndroid Build Coastguard Worker
390*bb4ee6a4SAndroid Build Coastguard Worker if let Some(ctrl_queue) = &self.ctrl_queue {
391*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx
392*bb4ee6a4SAndroid Build Coastguard Worker .add(ctrl_queue.event(), Token::CtrlQueue)
393*bb4ee6a4SAndroid Build Coastguard Worker .map_err(NetError::CreateWaitContext)?;
394*bb4ee6a4SAndroid Build Coastguard Worker }
395*bb4ee6a4SAndroid Build Coastguard Worker
396*bb4ee6a4SAndroid Build Coastguard Worker if handle_interrupt_resample {
397*bb4ee6a4SAndroid Build Coastguard Worker if let Some(resample_evt) = self.interrupt.get_resample_evt() {
398*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx
399*bb4ee6a4SAndroid Build Coastguard Worker .add(resample_evt, Token::InterruptResample)
400*bb4ee6a4SAndroid Build Coastguard Worker .map_err(NetError::CreateWaitContext)?;
401*bb4ee6a4SAndroid Build Coastguard Worker }
402*bb4ee6a4SAndroid Build Coastguard Worker }
403*bb4ee6a4SAndroid Build Coastguard Worker
404*bb4ee6a4SAndroid Build Coastguard Worker let mut tap_polling_enabled = true;
405*bb4ee6a4SAndroid Build Coastguard Worker 'wait: loop {
406*bb4ee6a4SAndroid Build Coastguard Worker let events = wait_ctx.wait().map_err(NetError::WaitError)?;
407*bb4ee6a4SAndroid Build Coastguard Worker for event in events.iter().filter(|e| e.is_readable) {
408*bb4ee6a4SAndroid Build Coastguard Worker match event.token {
409*bb4ee6a4SAndroid Build Coastguard Worker Token::RxTap => {
410*bb4ee6a4SAndroid Build Coastguard Worker let _trace = cros_tracing::trace_event!(VirtioNet, "handle RxTap event");
411*bb4ee6a4SAndroid Build Coastguard Worker self.handle_rx_token(&wait_ctx)?;
412*bb4ee6a4SAndroid Build Coastguard Worker tap_polling_enabled = false;
413*bb4ee6a4SAndroid Build Coastguard Worker }
414*bb4ee6a4SAndroid Build Coastguard Worker Token::RxQueue => {
415*bb4ee6a4SAndroid Build Coastguard Worker let _trace = cros_tracing::trace_event!(VirtioNet, "handle RxQueue event");
416*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = self.rx_queue.event().wait() {
417*bb4ee6a4SAndroid Build Coastguard Worker error!("net: error reading rx queue Event: {}", e);
418*bb4ee6a4SAndroid Build Coastguard Worker break 'wait;
419*bb4ee6a4SAndroid Build Coastguard Worker }
420*bb4ee6a4SAndroid Build Coastguard Worker self.handle_rx_queue(&wait_ctx, tap_polling_enabled)?;
421*bb4ee6a4SAndroid Build Coastguard Worker tap_polling_enabled = true;
422*bb4ee6a4SAndroid Build Coastguard Worker }
423*bb4ee6a4SAndroid Build Coastguard Worker Token::TxQueue => {
424*bb4ee6a4SAndroid Build Coastguard Worker let _trace = cros_tracing::trace_event!(VirtioNet, "handle TxQueue event");
425*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = self.tx_queue.event().wait() {
426*bb4ee6a4SAndroid Build Coastguard Worker error!("net: error reading tx queue Event: {}", e);
427*bb4ee6a4SAndroid Build Coastguard Worker break 'wait;
428*bb4ee6a4SAndroid Build Coastguard Worker }
429*bb4ee6a4SAndroid Build Coastguard Worker self.process_tx();
430*bb4ee6a4SAndroid Build Coastguard Worker }
431*bb4ee6a4SAndroid Build Coastguard Worker Token::CtrlQueue => {
432*bb4ee6a4SAndroid Build Coastguard Worker let _trace =
433*bb4ee6a4SAndroid Build Coastguard Worker cros_tracing::trace_event!(VirtioNet, "handle CtrlQueue event");
434*bb4ee6a4SAndroid Build Coastguard Worker if let Some(ctrl_evt) = self.ctrl_queue.as_ref().map(|q| q.event()) {
435*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = ctrl_evt.wait() {
436*bb4ee6a4SAndroid Build Coastguard Worker error!("net: error reading ctrl queue Event: {}", e);
437*bb4ee6a4SAndroid Build Coastguard Worker break 'wait;
438*bb4ee6a4SAndroid Build Coastguard Worker }
439*bb4ee6a4SAndroid Build Coastguard Worker } else {
440*bb4ee6a4SAndroid Build Coastguard Worker break 'wait;
441*bb4ee6a4SAndroid Build Coastguard Worker }
442*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = self.process_ctrl() {
443*bb4ee6a4SAndroid Build Coastguard Worker error!("net: failed to process control message: {}", e);
444*bb4ee6a4SAndroid Build Coastguard Worker break 'wait;
445*bb4ee6a4SAndroid Build Coastguard Worker }
446*bb4ee6a4SAndroid Build Coastguard Worker }
447*bb4ee6a4SAndroid Build Coastguard Worker Token::InterruptResample => {
448*bb4ee6a4SAndroid Build Coastguard Worker let _trace =
449*bb4ee6a4SAndroid Build Coastguard Worker cros_tracing::trace_event!(VirtioNet, "handle InterruptResample event");
450*bb4ee6a4SAndroid Build Coastguard Worker // We can unwrap safely because interrupt must have the event.
451*bb4ee6a4SAndroid Build Coastguard Worker let _ = self.interrupt.get_resample_evt().unwrap().wait();
452*bb4ee6a4SAndroid Build Coastguard Worker self.interrupt.do_interrupt_resample();
453*bb4ee6a4SAndroid Build Coastguard Worker }
454*bb4ee6a4SAndroid Build Coastguard Worker Token::Kill => {
455*bb4ee6a4SAndroid Build Coastguard Worker let _ = self.kill_evt.wait();
456*bb4ee6a4SAndroid Build Coastguard Worker break 'wait;
457*bb4ee6a4SAndroid Build Coastguard Worker }
458*bb4ee6a4SAndroid Build Coastguard Worker }
459*bb4ee6a4SAndroid Build Coastguard Worker }
460*bb4ee6a4SAndroid Build Coastguard Worker }
461*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
462*bb4ee6a4SAndroid Build Coastguard Worker }
463*bb4ee6a4SAndroid Build Coastguard Worker }
464*bb4ee6a4SAndroid Build Coastguard Worker
build_config(vq_pairs: u16, mtu: u16, mac: Option<[u8; 6]>) -> VirtioNetConfig465*bb4ee6a4SAndroid Build Coastguard Worker pub fn build_config(vq_pairs: u16, mtu: u16, mac: Option<[u8; 6]>) -> VirtioNetConfig {
466*bb4ee6a4SAndroid Build Coastguard Worker VirtioNetConfig {
467*bb4ee6a4SAndroid Build Coastguard Worker max_vq_pairs: Le16::from(vq_pairs),
468*bb4ee6a4SAndroid Build Coastguard Worker mtu: Le16::from(mtu),
469*bb4ee6a4SAndroid Build Coastguard Worker mac: mac.unwrap_or_default(),
470*bb4ee6a4SAndroid Build Coastguard Worker // Other field has meaningful value when the corresponding feature
471*bb4ee6a4SAndroid Build Coastguard Worker // is enabled, but all these features aren't supported now.
472*bb4ee6a4SAndroid Build Coastguard Worker // So set them to default.
473*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
474*bb4ee6a4SAndroid Build Coastguard Worker }
475*bb4ee6a4SAndroid Build Coastguard Worker }
476*bb4ee6a4SAndroid Build Coastguard Worker
477*bb4ee6a4SAndroid Build Coastguard Worker pub struct Net<T: TapT + ReadNotifier + 'static> {
478*bb4ee6a4SAndroid Build Coastguard Worker guest_mac: Option<[u8; 6]>,
479*bb4ee6a4SAndroid Build Coastguard Worker queue_sizes: Box<[u16]>,
480*bb4ee6a4SAndroid Build Coastguard Worker worker_threads: Vec<WorkerThread<Worker<T>>>,
481*bb4ee6a4SAndroid Build Coastguard Worker taps: Vec<T>,
482*bb4ee6a4SAndroid Build Coastguard Worker avail_features: u64,
483*bb4ee6a4SAndroid Build Coastguard Worker acked_features: u64,
484*bb4ee6a4SAndroid Build Coastguard Worker mtu: u16,
485*bb4ee6a4SAndroid Build Coastguard Worker pci_address: Option<PciAddress>,
486*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
487*bb4ee6a4SAndroid Build Coastguard Worker slirp_kill_evt: Option<Event>,
488*bb4ee6a4SAndroid Build Coastguard Worker }
489*bb4ee6a4SAndroid Build Coastguard Worker
490*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
491*bb4ee6a4SAndroid Build Coastguard Worker struct NetSnapshot {
492*bb4ee6a4SAndroid Build Coastguard Worker avail_features: u64,
493*bb4ee6a4SAndroid Build Coastguard Worker acked_features: u64,
494*bb4ee6a4SAndroid Build Coastguard Worker }
495*bb4ee6a4SAndroid Build Coastguard Worker
496*bb4ee6a4SAndroid Build Coastguard Worker impl<T> Net<T>
497*bb4ee6a4SAndroid Build Coastguard Worker where
498*bb4ee6a4SAndroid Build Coastguard Worker T: TapT + ReadNotifier,
499*bb4ee6a4SAndroid Build Coastguard Worker {
500*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a new virtio network device from a tap device that has already been
501*bb4ee6a4SAndroid Build Coastguard Worker /// configured.
new( base_features: u64, tap: T, vq_pairs: u16, mac_addr: Option<MacAddress>, use_packed_queue: bool, pci_address: Option<PciAddress>, ) -> Result<Net<T>, NetError>502*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(
503*bb4ee6a4SAndroid Build Coastguard Worker base_features: u64,
504*bb4ee6a4SAndroid Build Coastguard Worker tap: T,
505*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: u16,
506*bb4ee6a4SAndroid Build Coastguard Worker mac_addr: Option<MacAddress>,
507*bb4ee6a4SAndroid Build Coastguard Worker use_packed_queue: bool,
508*bb4ee6a4SAndroid Build Coastguard Worker pci_address: Option<PciAddress>,
509*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Net<T>, NetError> {
510*bb4ee6a4SAndroid Build Coastguard Worker let taps = tap.into_mq_taps(vq_pairs).map_err(NetError::TapOpen)?;
511*bb4ee6a4SAndroid Build Coastguard Worker
512*bb4ee6a4SAndroid Build Coastguard Worker let mut mtu = u16::MAX;
513*bb4ee6a4SAndroid Build Coastguard Worker // This would also validate a tap created by Self::new(), but that's a good thing as it
514*bb4ee6a4SAndroid Build Coastguard Worker // would ensure that any changes in the creation procedure are matched in the validation.
515*bb4ee6a4SAndroid Build Coastguard Worker // Plus we still need to set the offload and vnet_hdr_size values.
516*bb4ee6a4SAndroid Build Coastguard Worker for tap in &taps {
517*bb4ee6a4SAndroid Build Coastguard Worker validate_and_configure_tap(tap, vq_pairs)?;
518*bb4ee6a4SAndroid Build Coastguard Worker mtu = std::cmp::min(mtu, tap.mtu().map_err(NetError::TapGetMtu)?);
519*bb4ee6a4SAndroid Build Coastguard Worker }
520*bb4ee6a4SAndroid Build Coastguard Worker
521*bb4ee6a4SAndroid Build Coastguard Worker // Indicate that the TAP device supports a number of features, such as:
522*bb4ee6a4SAndroid Build Coastguard Worker // Partial checksum offload
523*bb4ee6a4SAndroid Build Coastguard Worker // TSO (TCP segmentation offload)
524*bb4ee6a4SAndroid Build Coastguard Worker // UFO (UDP fragmentation offload)
525*bb4ee6a4SAndroid Build Coastguard Worker // See the network device feature bits section for further details:
526*bb4ee6a4SAndroid Build Coastguard Worker // http://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-1970003
527*bb4ee6a4SAndroid Build Coastguard Worker let mut avail_features = base_features
528*bb4ee6a4SAndroid Build Coastguard Worker | 1 << virtio_net::VIRTIO_NET_F_GUEST_CSUM
529*bb4ee6a4SAndroid Build Coastguard Worker | 1 << virtio_net::VIRTIO_NET_F_CSUM
530*bb4ee6a4SAndroid Build Coastguard Worker | 1 << virtio_net::VIRTIO_NET_F_CTRL_VQ
531*bb4ee6a4SAndroid Build Coastguard Worker | 1 << virtio_net::VIRTIO_NET_F_CTRL_GUEST_OFFLOADS
532*bb4ee6a4SAndroid Build Coastguard Worker | 1 << virtio_net::VIRTIO_NET_F_GUEST_TSO4
533*bb4ee6a4SAndroid Build Coastguard Worker | 1 << virtio_net::VIRTIO_NET_F_GUEST_UFO
534*bb4ee6a4SAndroid Build Coastguard Worker | 1 << virtio_net::VIRTIO_NET_F_HOST_TSO4
535*bb4ee6a4SAndroid Build Coastguard Worker | 1 << virtio_net::VIRTIO_NET_F_HOST_UFO
536*bb4ee6a4SAndroid Build Coastguard Worker | 1 << virtio_net::VIRTIO_NET_F_MTU;
537*bb4ee6a4SAndroid Build Coastguard Worker
538*bb4ee6a4SAndroid Build Coastguard Worker if vq_pairs > 1 {
539*bb4ee6a4SAndroid Build Coastguard Worker avail_features |= 1 << virtio_net::VIRTIO_NET_F_MQ;
540*bb4ee6a4SAndroid Build Coastguard Worker }
541*bb4ee6a4SAndroid Build Coastguard Worker
542*bb4ee6a4SAndroid Build Coastguard Worker if use_packed_queue {
543*bb4ee6a4SAndroid Build Coastguard Worker avail_features |= 1 << VIRTIO_F_RING_PACKED;
544*bb4ee6a4SAndroid Build Coastguard Worker }
545*bb4ee6a4SAndroid Build Coastguard Worker
546*bb4ee6a4SAndroid Build Coastguard Worker if mac_addr.is_some() {
547*bb4ee6a4SAndroid Build Coastguard Worker avail_features |= 1 << virtio_net::VIRTIO_NET_F_MAC;
548*bb4ee6a4SAndroid Build Coastguard Worker }
549*bb4ee6a4SAndroid Build Coastguard Worker
550*bb4ee6a4SAndroid Build Coastguard Worker Self::new_internal(
551*bb4ee6a4SAndroid Build Coastguard Worker taps,
552*bb4ee6a4SAndroid Build Coastguard Worker avail_features,
553*bb4ee6a4SAndroid Build Coastguard Worker mtu,
554*bb4ee6a4SAndroid Build Coastguard Worker mac_addr,
555*bb4ee6a4SAndroid Build Coastguard Worker pci_address,
556*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
557*bb4ee6a4SAndroid Build Coastguard Worker None,
558*bb4ee6a4SAndroid Build Coastguard Worker )
559*bb4ee6a4SAndroid Build Coastguard Worker }
560*bb4ee6a4SAndroid Build Coastguard Worker
new_internal( taps: Vec<T>, avail_features: u64, mtu: u16, mac_addr: Option<MacAddress>, pci_address: Option<PciAddress>, #[cfg(windows)] slirp_kill_evt: Option<Event>, ) -> Result<Self, NetError>561*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn new_internal(
562*bb4ee6a4SAndroid Build Coastguard Worker taps: Vec<T>,
563*bb4ee6a4SAndroid Build Coastguard Worker avail_features: u64,
564*bb4ee6a4SAndroid Build Coastguard Worker mtu: u16,
565*bb4ee6a4SAndroid Build Coastguard Worker mac_addr: Option<MacAddress>,
566*bb4ee6a4SAndroid Build Coastguard Worker pci_address: Option<PciAddress>,
567*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] slirp_kill_evt: Option<Event>,
568*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Self, NetError> {
569*bb4ee6a4SAndroid Build Coastguard Worker let net = Self {
570*bb4ee6a4SAndroid Build Coastguard Worker guest_mac: mac_addr.map(|mac| mac.octets()),
571*bb4ee6a4SAndroid Build Coastguard Worker queue_sizes: vec![QUEUE_SIZE; taps.len() * 2 + 1].into_boxed_slice(),
572*bb4ee6a4SAndroid Build Coastguard Worker worker_threads: Vec::new(),
573*bb4ee6a4SAndroid Build Coastguard Worker taps,
574*bb4ee6a4SAndroid Build Coastguard Worker avail_features,
575*bb4ee6a4SAndroid Build Coastguard Worker acked_features: 0u64,
576*bb4ee6a4SAndroid Build Coastguard Worker mtu,
577*bb4ee6a4SAndroid Build Coastguard Worker pci_address,
578*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
579*bb4ee6a4SAndroid Build Coastguard Worker slirp_kill_evt: None,
580*bb4ee6a4SAndroid Build Coastguard Worker };
581*bb4ee6a4SAndroid Build Coastguard Worker cros_tracing::trace_simple_print!("New Net device created: {:?}", net);
582*bb4ee6a4SAndroid Build Coastguard Worker Ok(net)
583*bb4ee6a4SAndroid Build Coastguard Worker }
584*bb4ee6a4SAndroid Build Coastguard Worker
585*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the maximum number of receive/transmit queue pairs for this device.
586*bb4ee6a4SAndroid Build Coastguard Worker /// Only relevant when multi-queue support is negotiated.
max_virtqueue_pairs(&self) -> usize587*bb4ee6a4SAndroid Build Coastguard Worker fn max_virtqueue_pairs(&self) -> usize {
588*bb4ee6a4SAndroid Build Coastguard Worker self.taps.len()
589*bb4ee6a4SAndroid Build Coastguard Worker }
590*bb4ee6a4SAndroid Build Coastguard Worker }
591*bb4ee6a4SAndroid Build Coastguard Worker
592*bb4ee6a4SAndroid Build Coastguard Worker impl<T> Drop for Net<T>
593*bb4ee6a4SAndroid Build Coastguard Worker where
594*bb4ee6a4SAndroid Build Coastguard Worker T: TapT + ReadNotifier,
595*bb4ee6a4SAndroid Build Coastguard Worker {
drop(&mut self)596*bb4ee6a4SAndroid Build Coastguard Worker fn drop(&mut self) {
597*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
598*bb4ee6a4SAndroid Build Coastguard Worker {
599*bb4ee6a4SAndroid Build Coastguard Worker if let Some(slirp_kill_evt) = self.slirp_kill_evt.take() {
600*bb4ee6a4SAndroid Build Coastguard Worker let _ = slirp_kill_evt.signal();
601*bb4ee6a4SAndroid Build Coastguard Worker }
602*bb4ee6a4SAndroid Build Coastguard Worker }
603*bb4ee6a4SAndroid Build Coastguard Worker }
604*bb4ee6a4SAndroid Build Coastguard Worker }
605*bb4ee6a4SAndroid Build Coastguard Worker
606*bb4ee6a4SAndroid Build Coastguard Worker impl<T> VirtioDevice for Net<T>
607*bb4ee6a4SAndroid Build Coastguard Worker where
608*bb4ee6a4SAndroid Build Coastguard Worker T: 'static + TapT + ReadNotifier,
609*bb4ee6a4SAndroid Build Coastguard Worker {
keep_rds(&self) -> Vec<RawDescriptor>610*bb4ee6a4SAndroid Build Coastguard Worker fn keep_rds(&self) -> Vec<RawDescriptor> {
611*bb4ee6a4SAndroid Build Coastguard Worker let mut keep_rds = Vec::new();
612*bb4ee6a4SAndroid Build Coastguard Worker
613*bb4ee6a4SAndroid Build Coastguard Worker for tap in &self.taps {
614*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.push(tap.as_raw_descriptor());
615*bb4ee6a4SAndroid Build Coastguard Worker }
616*bb4ee6a4SAndroid Build Coastguard Worker
617*bb4ee6a4SAndroid Build Coastguard Worker keep_rds
618*bb4ee6a4SAndroid Build Coastguard Worker }
619*bb4ee6a4SAndroid Build Coastguard Worker
device_type(&self) -> DeviceType620*bb4ee6a4SAndroid Build Coastguard Worker fn device_type(&self) -> DeviceType {
621*bb4ee6a4SAndroid Build Coastguard Worker DeviceType::Net
622*bb4ee6a4SAndroid Build Coastguard Worker }
623*bb4ee6a4SAndroid Build Coastguard Worker
queue_max_sizes(&self) -> &[u16]624*bb4ee6a4SAndroid Build Coastguard Worker fn queue_max_sizes(&self) -> &[u16] {
625*bb4ee6a4SAndroid Build Coastguard Worker &self.queue_sizes
626*bb4ee6a4SAndroid Build Coastguard Worker }
627*bb4ee6a4SAndroid Build Coastguard Worker
features(&self) -> u64628*bb4ee6a4SAndroid Build Coastguard Worker fn features(&self) -> u64 {
629*bb4ee6a4SAndroid Build Coastguard Worker self.avail_features
630*bb4ee6a4SAndroid Build Coastguard Worker }
631*bb4ee6a4SAndroid Build Coastguard Worker
ack_features(&mut self, value: u64)632*bb4ee6a4SAndroid Build Coastguard Worker fn ack_features(&mut self, value: u64) {
633*bb4ee6a4SAndroid Build Coastguard Worker let mut v = value;
634*bb4ee6a4SAndroid Build Coastguard Worker
635*bb4ee6a4SAndroid Build Coastguard Worker // Check if the guest is ACK'ing a feature that we didn't claim to have.
636*bb4ee6a4SAndroid Build Coastguard Worker let unrequested_features = v & !self.avail_features;
637*bb4ee6a4SAndroid Build Coastguard Worker if unrequested_features != 0 {
638*bb4ee6a4SAndroid Build Coastguard Worker warn!("net: virtio net got unknown feature ack: {:x}", v);
639*bb4ee6a4SAndroid Build Coastguard Worker
640*bb4ee6a4SAndroid Build Coastguard Worker // Don't count these features as acked.
641*bb4ee6a4SAndroid Build Coastguard Worker v &= !unrequested_features;
642*bb4ee6a4SAndroid Build Coastguard Worker }
643*bb4ee6a4SAndroid Build Coastguard Worker self.acked_features |= v;
644*bb4ee6a4SAndroid Build Coastguard Worker
645*bb4ee6a4SAndroid Build Coastguard Worker // Set offload flags to match acked virtio features.
646*bb4ee6a4SAndroid Build Coastguard Worker if let Some(tap) = self.taps.first() {
647*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = tap.set_offload(virtio_features_to_tap_offload(self.acked_features)) {
648*bb4ee6a4SAndroid Build Coastguard Worker warn!(
649*bb4ee6a4SAndroid Build Coastguard Worker "net: failed to set tap offload to match acked features: {}",
650*bb4ee6a4SAndroid Build Coastguard Worker e
651*bb4ee6a4SAndroid Build Coastguard Worker );
652*bb4ee6a4SAndroid Build Coastguard Worker }
653*bb4ee6a4SAndroid Build Coastguard Worker }
654*bb4ee6a4SAndroid Build Coastguard Worker }
655*bb4ee6a4SAndroid Build Coastguard Worker
read_config(&self, offset: u64, data: &mut [u8])656*bb4ee6a4SAndroid Build Coastguard Worker fn read_config(&self, offset: u64, data: &mut [u8]) {
657*bb4ee6a4SAndroid Build Coastguard Worker let vq_pairs = self.queue_sizes.len() / 2;
658*bb4ee6a4SAndroid Build Coastguard Worker let config_space = build_config(vq_pairs as u16, self.mtu, self.guest_mac);
659*bb4ee6a4SAndroid Build Coastguard Worker copy_config(data, 0, config_space.as_bytes(), offset);
660*bb4ee6a4SAndroid Build Coastguard Worker }
661*bb4ee6a4SAndroid Build Coastguard Worker
activate( &mut self, _mem: GuestMemory, interrupt: Interrupt, mut queues: BTreeMap<usize, Queue>, ) -> anyhow::Result<()>662*bb4ee6a4SAndroid Build Coastguard Worker fn activate(
663*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
664*bb4ee6a4SAndroid Build Coastguard Worker _mem: GuestMemory,
665*bb4ee6a4SAndroid Build Coastguard Worker interrupt: Interrupt,
666*bb4ee6a4SAndroid Build Coastguard Worker mut queues: BTreeMap<usize, Queue>,
667*bb4ee6a4SAndroid Build Coastguard Worker ) -> anyhow::Result<()> {
668*bb4ee6a4SAndroid Build Coastguard Worker let ctrl_vq_enabled = self.acked_features & (1 << virtio_net::VIRTIO_NET_F_CTRL_VQ) != 0;
669*bb4ee6a4SAndroid Build Coastguard Worker let mq_enabled = self.acked_features & (1 << virtio_net::VIRTIO_NET_F_MQ) != 0;
670*bb4ee6a4SAndroid Build Coastguard Worker
671*bb4ee6a4SAndroid Build Coastguard Worker let vq_pairs = if mq_enabled {
672*bb4ee6a4SAndroid Build Coastguard Worker self.max_virtqueue_pairs()
673*bb4ee6a4SAndroid Build Coastguard Worker } else {
674*bb4ee6a4SAndroid Build Coastguard Worker 1
675*bb4ee6a4SAndroid Build Coastguard Worker };
676*bb4ee6a4SAndroid Build Coastguard Worker
677*bb4ee6a4SAndroid Build Coastguard Worker let mut num_queues_expected = vq_pairs * 2;
678*bb4ee6a4SAndroid Build Coastguard Worker if ctrl_vq_enabled {
679*bb4ee6a4SAndroid Build Coastguard Worker num_queues_expected += 1;
680*bb4ee6a4SAndroid Build Coastguard Worker }
681*bb4ee6a4SAndroid Build Coastguard Worker
682*bb4ee6a4SAndroid Build Coastguard Worker if queues.len() != num_queues_expected {
683*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!(
684*bb4ee6a4SAndroid Build Coastguard Worker "net: expected {} queues, got {} queues",
685*bb4ee6a4SAndroid Build Coastguard Worker self.queue_sizes.len(),
686*bb4ee6a4SAndroid Build Coastguard Worker queues.len(),
687*bb4ee6a4SAndroid Build Coastguard Worker ));
688*bb4ee6a4SAndroid Build Coastguard Worker }
689*bb4ee6a4SAndroid Build Coastguard Worker
690*bb4ee6a4SAndroid Build Coastguard Worker if self.taps.len() < vq_pairs {
691*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!(
692*bb4ee6a4SAndroid Build Coastguard Worker "net: expected {} taps, got {}",
693*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs,
694*bb4ee6a4SAndroid Build Coastguard Worker self.taps.len()
695*bb4ee6a4SAndroid Build Coastguard Worker ));
696*bb4ee6a4SAndroid Build Coastguard Worker }
697*bb4ee6a4SAndroid Build Coastguard Worker
698*bb4ee6a4SAndroid Build Coastguard Worker for i in 0..vq_pairs {
699*bb4ee6a4SAndroid Build Coastguard Worker let tap = self.taps.remove(0);
700*bb4ee6a4SAndroid Build Coastguard Worker let acked_features = self.acked_features;
701*bb4ee6a4SAndroid Build Coastguard Worker let interrupt = interrupt.clone();
702*bb4ee6a4SAndroid Build Coastguard Worker let first_queue = i == 0;
703*bb4ee6a4SAndroid Build Coastguard Worker // Queues alternate between rx0, tx0, rx1, tx1, ..., rxN, txN, ctrl.
704*bb4ee6a4SAndroid Build Coastguard Worker let rx_queue = queues.pop_first().unwrap().1;
705*bb4ee6a4SAndroid Build Coastguard Worker let tx_queue = queues.pop_first().unwrap().1;
706*bb4ee6a4SAndroid Build Coastguard Worker let ctrl_queue = if first_queue && ctrl_vq_enabled {
707*bb4ee6a4SAndroid Build Coastguard Worker Some(queues.pop_last().unwrap().1)
708*bb4ee6a4SAndroid Build Coastguard Worker } else {
709*bb4ee6a4SAndroid Build Coastguard Worker None
710*bb4ee6a4SAndroid Build Coastguard Worker };
711*bb4ee6a4SAndroid Build Coastguard Worker // Handle interrupt resampling on the first queue's thread.
712*bb4ee6a4SAndroid Build Coastguard Worker let handle_interrupt_resample = first_queue;
713*bb4ee6a4SAndroid Build Coastguard Worker let pairs = vq_pairs as u16;
714*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
715*bb4ee6a4SAndroid Build Coastguard Worker let overlapped_wrapper = OverlappedWrapper::new(true).unwrap();
716*bb4ee6a4SAndroid Build Coastguard Worker self.worker_threads
717*bb4ee6a4SAndroid Build Coastguard Worker .push(WorkerThread::start(format!("v_net:{i}"), move |kill_evt| {
718*bb4ee6a4SAndroid Build Coastguard Worker let mut worker = Worker {
719*bb4ee6a4SAndroid Build Coastguard Worker interrupt,
720*bb4ee6a4SAndroid Build Coastguard Worker rx_queue,
721*bb4ee6a4SAndroid Build Coastguard Worker tx_queue,
722*bb4ee6a4SAndroid Build Coastguard Worker ctrl_queue,
723*bb4ee6a4SAndroid Build Coastguard Worker tap,
724*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
725*bb4ee6a4SAndroid Build Coastguard Worker overlapped_wrapper,
726*bb4ee6a4SAndroid Build Coastguard Worker acked_features,
727*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: pairs,
728*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
729*bb4ee6a4SAndroid Build Coastguard Worker rx_buf: [0u8; MAX_BUFFER_SIZE],
730*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
731*bb4ee6a4SAndroid Build Coastguard Worker rx_count: 0,
732*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
733*bb4ee6a4SAndroid Build Coastguard Worker deferred_rx: false,
734*bb4ee6a4SAndroid Build Coastguard Worker kill_evt,
735*bb4ee6a4SAndroid Build Coastguard Worker };
736*bb4ee6a4SAndroid Build Coastguard Worker let result = worker.run(handle_interrupt_resample);
737*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = result {
738*bb4ee6a4SAndroid Build Coastguard Worker error!("net worker thread exited with error: {}", e);
739*bb4ee6a4SAndroid Build Coastguard Worker }
740*bb4ee6a4SAndroid Build Coastguard Worker worker
741*bb4ee6a4SAndroid Build Coastguard Worker }));
742*bb4ee6a4SAndroid Build Coastguard Worker }
743*bb4ee6a4SAndroid Build Coastguard Worker cros_tracing::trace_simple_print!("Net device activated: {:?}", self);
744*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
745*bb4ee6a4SAndroid Build Coastguard Worker }
746*bb4ee6a4SAndroid Build Coastguard Worker
pci_address(&self) -> Option<PciAddress>747*bb4ee6a4SAndroid Build Coastguard Worker fn pci_address(&self) -> Option<PciAddress> {
748*bb4ee6a4SAndroid Build Coastguard Worker self.pci_address
749*bb4ee6a4SAndroid Build Coastguard Worker }
750*bb4ee6a4SAndroid Build Coastguard Worker
virtio_sleep(&mut self) -> anyhow::Result<Option<BTreeMap<usize, Queue>>>751*bb4ee6a4SAndroid Build Coastguard Worker fn virtio_sleep(&mut self) -> anyhow::Result<Option<BTreeMap<usize, Queue>>> {
752*bb4ee6a4SAndroid Build Coastguard Worker if self.worker_threads.is_empty() {
753*bb4ee6a4SAndroid Build Coastguard Worker return Ok(None);
754*bb4ee6a4SAndroid Build Coastguard Worker }
755*bb4ee6a4SAndroid Build Coastguard Worker let mut queues = BTreeMap::new();
756*bb4ee6a4SAndroid Build Coastguard Worker let mut queue_index = 0;
757*bb4ee6a4SAndroid Build Coastguard Worker let mut ctrl_queue = None;
758*bb4ee6a4SAndroid Build Coastguard Worker for worker_thread in self.worker_threads.drain(..) {
759*bb4ee6a4SAndroid Build Coastguard Worker let mut worker = worker_thread.stop();
760*bb4ee6a4SAndroid Build Coastguard Worker if worker.ctrl_queue.is_some() {
761*bb4ee6a4SAndroid Build Coastguard Worker ctrl_queue = worker.ctrl_queue.take();
762*bb4ee6a4SAndroid Build Coastguard Worker }
763*bb4ee6a4SAndroid Build Coastguard Worker self.taps.push(worker.tap);
764*bb4ee6a4SAndroid Build Coastguard Worker queues.insert(queue_index + 0, worker.rx_queue);
765*bb4ee6a4SAndroid Build Coastguard Worker queues.insert(queue_index + 1, worker.tx_queue);
766*bb4ee6a4SAndroid Build Coastguard Worker queue_index += 2;
767*bb4ee6a4SAndroid Build Coastguard Worker }
768*bb4ee6a4SAndroid Build Coastguard Worker if let Some(ctrl_queue) = ctrl_queue {
769*bb4ee6a4SAndroid Build Coastguard Worker queues.insert(queue_index, ctrl_queue);
770*bb4ee6a4SAndroid Build Coastguard Worker }
771*bb4ee6a4SAndroid Build Coastguard Worker Ok(Some(queues))
772*bb4ee6a4SAndroid Build Coastguard Worker }
773*bb4ee6a4SAndroid Build Coastguard Worker
virtio_wake( &mut self, device_state: Option<(GuestMemory, Interrupt, BTreeMap<usize, Queue>)>, ) -> anyhow::Result<()>774*bb4ee6a4SAndroid Build Coastguard Worker fn virtio_wake(
775*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
776*bb4ee6a4SAndroid Build Coastguard Worker device_state: Option<(GuestMemory, Interrupt, BTreeMap<usize, Queue>)>,
777*bb4ee6a4SAndroid Build Coastguard Worker ) -> anyhow::Result<()> {
778*bb4ee6a4SAndroid Build Coastguard Worker match device_state {
779*bb4ee6a4SAndroid Build Coastguard Worker None => Ok(()),
780*bb4ee6a4SAndroid Build Coastguard Worker Some((mem, interrupt, queues)) => {
781*bb4ee6a4SAndroid Build Coastguard Worker // TODO: activate is just what we want at the moment, but we should probably move
782*bb4ee6a4SAndroid Build Coastguard Worker // it into a "start workers" function to make it obvious that it isn't strictly
783*bb4ee6a4SAndroid Build Coastguard Worker // used for activate events.
784*bb4ee6a4SAndroid Build Coastguard Worker self.activate(mem, interrupt, queues)?;
785*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
786*bb4ee6a4SAndroid Build Coastguard Worker }
787*bb4ee6a4SAndroid Build Coastguard Worker }
788*bb4ee6a4SAndroid Build Coastguard Worker }
789*bb4ee6a4SAndroid Build Coastguard Worker
virtio_snapshot(&mut self) -> anyhow::Result<serde_json::Value>790*bb4ee6a4SAndroid Build Coastguard Worker fn virtio_snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
791*bb4ee6a4SAndroid Build Coastguard Worker serde_json::to_value(NetSnapshot {
792*bb4ee6a4SAndroid Build Coastguard Worker acked_features: self.acked_features,
793*bb4ee6a4SAndroid Build Coastguard Worker avail_features: self.avail_features,
794*bb4ee6a4SAndroid Build Coastguard Worker })
795*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to snapshot virtio Net device")
796*bb4ee6a4SAndroid Build Coastguard Worker }
797*bb4ee6a4SAndroid Build Coastguard Worker
virtio_restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>798*bb4ee6a4SAndroid Build Coastguard Worker fn virtio_restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
799*bb4ee6a4SAndroid Build Coastguard Worker let deser: NetSnapshot =
800*bb4ee6a4SAndroid Build Coastguard Worker serde_json::from_value(data).context("failed to deserialize Net device")?;
801*bb4ee6a4SAndroid Build Coastguard Worker anyhow::ensure!(
802*bb4ee6a4SAndroid Build Coastguard Worker self.avail_features == deser.avail_features,
803*bb4ee6a4SAndroid Build Coastguard Worker "Available features for net device do not match. expected: {}, got: {}",
804*bb4ee6a4SAndroid Build Coastguard Worker deser.avail_features,
805*bb4ee6a4SAndroid Build Coastguard Worker self.avail_features
806*bb4ee6a4SAndroid Build Coastguard Worker );
807*bb4ee6a4SAndroid Build Coastguard Worker self.acked_features = deser.acked_features;
808*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
809*bb4ee6a4SAndroid Build Coastguard Worker }
810*bb4ee6a4SAndroid Build Coastguard Worker
reset(&mut self) -> anyhow::Result<()>811*bb4ee6a4SAndroid Build Coastguard Worker fn reset(&mut self) -> anyhow::Result<()> {
812*bb4ee6a4SAndroid Build Coastguard Worker for worker_thread in self.worker_threads.drain(..) {
813*bb4ee6a4SAndroid Build Coastguard Worker let worker = worker_thread.stop();
814*bb4ee6a4SAndroid Build Coastguard Worker self.taps.push(worker.tap);
815*bb4ee6a4SAndroid Build Coastguard Worker }
816*bb4ee6a4SAndroid Build Coastguard Worker
817*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
818*bb4ee6a4SAndroid Build Coastguard Worker }
819*bb4ee6a4SAndroid Build Coastguard Worker }
820*bb4ee6a4SAndroid Build Coastguard Worker
821*bb4ee6a4SAndroid Build Coastguard Worker impl<T> std::fmt::Debug for Net<T>
822*bb4ee6a4SAndroid Build Coastguard Worker where
823*bb4ee6a4SAndroid Build Coastguard Worker T: TapT + ReadNotifier,
824*bb4ee6a4SAndroid Build Coastguard Worker {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result825*bb4ee6a4SAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
826*bb4ee6a4SAndroid Build Coastguard Worker f.debug_struct("Net")
827*bb4ee6a4SAndroid Build Coastguard Worker .field("guest_mac", &self.guest_mac)
828*bb4ee6a4SAndroid Build Coastguard Worker .field("queue_sizes", &self.queue_sizes)
829*bb4ee6a4SAndroid Build Coastguard Worker .field("worker_threads_size", &self.worker_threads.len())
830*bb4ee6a4SAndroid Build Coastguard Worker .field("taps_size", &self.taps.len())
831*bb4ee6a4SAndroid Build Coastguard Worker .field("avail_features", &self.avail_features)
832*bb4ee6a4SAndroid Build Coastguard Worker .field("acked_features", &self.acked_features)
833*bb4ee6a4SAndroid Build Coastguard Worker .field("mtu", &self.mtu)
834*bb4ee6a4SAndroid Build Coastguard Worker .finish()
835*bb4ee6a4SAndroid Build Coastguard Worker }
836*bb4ee6a4SAndroid Build Coastguard Worker }
837*bb4ee6a4SAndroid Build Coastguard Worker
838*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
839*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
840*bb4ee6a4SAndroid Build Coastguard Worker use serde_keyvalue::*;
841*bb4ee6a4SAndroid Build Coastguard Worker
842*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
843*bb4ee6a4SAndroid Build Coastguard Worker
from_net_arg(options: &str) -> Result<NetParameters, ParseError>844*bb4ee6a4SAndroid Build Coastguard Worker fn from_net_arg(options: &str) -> Result<NetParameters, ParseError> {
845*bb4ee6a4SAndroid Build Coastguard Worker from_key_values(options)
846*bb4ee6a4SAndroid Build Coastguard Worker }
847*bb4ee6a4SAndroid Build Coastguard Worker
848*bb4ee6a4SAndroid Build Coastguard Worker #[test]
params_from_key_values()849*bb4ee6a4SAndroid Build Coastguard Worker fn params_from_key_values() {
850*bb4ee6a4SAndroid Build Coastguard Worker let params = from_net_arg("");
851*bb4ee6a4SAndroid Build Coastguard Worker assert!(params.is_err());
852*bb4ee6a4SAndroid Build Coastguard Worker
853*bb4ee6a4SAndroid Build Coastguard Worker let params = from_net_arg("tap-name=tap").unwrap();
854*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
855*bb4ee6a4SAndroid Build Coastguard Worker params,
856*bb4ee6a4SAndroid Build Coastguard Worker NetParameters {
857*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
858*bb4ee6a4SAndroid Build Coastguard Worker vhost_net: None,
859*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: None,
860*bb4ee6a4SAndroid Build Coastguard Worker mode: NetParametersMode::TapName {
861*bb4ee6a4SAndroid Build Coastguard Worker tap_name: "tap".to_string(),
862*bb4ee6a4SAndroid Build Coastguard Worker mac: None
863*bb4ee6a4SAndroid Build Coastguard Worker },
864*bb4ee6a4SAndroid Build Coastguard Worker packed_queue: false,
865*bb4ee6a4SAndroid Build Coastguard Worker pci_address: None,
866*bb4ee6a4SAndroid Build Coastguard Worker }
867*bb4ee6a4SAndroid Build Coastguard Worker );
868*bb4ee6a4SAndroid Build Coastguard Worker
869*bb4ee6a4SAndroid Build Coastguard Worker let params = from_net_arg("tap-name=tap,mac=\"3d:70:eb:61:1a:91\"").unwrap();
870*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
871*bb4ee6a4SAndroid Build Coastguard Worker params,
872*bb4ee6a4SAndroid Build Coastguard Worker NetParameters {
873*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
874*bb4ee6a4SAndroid Build Coastguard Worker vhost_net: None,
875*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: None,
876*bb4ee6a4SAndroid Build Coastguard Worker mode: NetParametersMode::TapName {
877*bb4ee6a4SAndroid Build Coastguard Worker tap_name: "tap".to_string(),
878*bb4ee6a4SAndroid Build Coastguard Worker mac: Some(MacAddress::from_str("3d:70:eb:61:1a:91").unwrap())
879*bb4ee6a4SAndroid Build Coastguard Worker },
880*bb4ee6a4SAndroid Build Coastguard Worker packed_queue: false,
881*bb4ee6a4SAndroid Build Coastguard Worker pci_address: None,
882*bb4ee6a4SAndroid Build Coastguard Worker }
883*bb4ee6a4SAndroid Build Coastguard Worker );
884*bb4ee6a4SAndroid Build Coastguard Worker
885*bb4ee6a4SAndroid Build Coastguard Worker let params = from_net_arg("tap-fd=12").unwrap();
886*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
887*bb4ee6a4SAndroid Build Coastguard Worker params,
888*bb4ee6a4SAndroid Build Coastguard Worker NetParameters {
889*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
890*bb4ee6a4SAndroid Build Coastguard Worker vhost_net: None,
891*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: None,
892*bb4ee6a4SAndroid Build Coastguard Worker mode: NetParametersMode::TapFd {
893*bb4ee6a4SAndroid Build Coastguard Worker tap_fd: 12,
894*bb4ee6a4SAndroid Build Coastguard Worker mac: None
895*bb4ee6a4SAndroid Build Coastguard Worker },
896*bb4ee6a4SAndroid Build Coastguard Worker packed_queue: false,
897*bb4ee6a4SAndroid Build Coastguard Worker pci_address: None,
898*bb4ee6a4SAndroid Build Coastguard Worker }
899*bb4ee6a4SAndroid Build Coastguard Worker );
900*bb4ee6a4SAndroid Build Coastguard Worker
901*bb4ee6a4SAndroid Build Coastguard Worker let params = from_net_arg("tap-fd=12,mac=\"3d:70:eb:61:1a:91\"").unwrap();
902*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
903*bb4ee6a4SAndroid Build Coastguard Worker params,
904*bb4ee6a4SAndroid Build Coastguard Worker NetParameters {
905*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
906*bb4ee6a4SAndroid Build Coastguard Worker vhost_net: None,
907*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: None,
908*bb4ee6a4SAndroid Build Coastguard Worker mode: NetParametersMode::TapFd {
909*bb4ee6a4SAndroid Build Coastguard Worker tap_fd: 12,
910*bb4ee6a4SAndroid Build Coastguard Worker mac: Some(MacAddress::from_str("3d:70:eb:61:1a:91").unwrap())
911*bb4ee6a4SAndroid Build Coastguard Worker },
912*bb4ee6a4SAndroid Build Coastguard Worker packed_queue: false,
913*bb4ee6a4SAndroid Build Coastguard Worker pci_address: None,
914*bb4ee6a4SAndroid Build Coastguard Worker }
915*bb4ee6a4SAndroid Build Coastguard Worker );
916*bb4ee6a4SAndroid Build Coastguard Worker
917*bb4ee6a4SAndroid Build Coastguard Worker let params = from_net_arg(
918*bb4ee6a4SAndroid Build Coastguard Worker "host-ip=\"192.168.10.1\",netmask=\"255.255.255.0\",mac=\"3d:70:eb:61:1a:91\"",
919*bb4ee6a4SAndroid Build Coastguard Worker )
920*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
921*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
922*bb4ee6a4SAndroid Build Coastguard Worker params,
923*bb4ee6a4SAndroid Build Coastguard Worker NetParameters {
924*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
925*bb4ee6a4SAndroid Build Coastguard Worker vhost_net: None,
926*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: None,
927*bb4ee6a4SAndroid Build Coastguard Worker mode: NetParametersMode::RawConfig {
928*bb4ee6a4SAndroid Build Coastguard Worker host_ip: Ipv4Addr::from_str("192.168.10.1").unwrap(),
929*bb4ee6a4SAndroid Build Coastguard Worker netmask: Ipv4Addr::from_str("255.255.255.0").unwrap(),
930*bb4ee6a4SAndroid Build Coastguard Worker mac: MacAddress::from_str("3d:70:eb:61:1a:91").unwrap(),
931*bb4ee6a4SAndroid Build Coastguard Worker },
932*bb4ee6a4SAndroid Build Coastguard Worker packed_queue: false,
933*bb4ee6a4SAndroid Build Coastguard Worker pci_address: None,
934*bb4ee6a4SAndroid Build Coastguard Worker }
935*bb4ee6a4SAndroid Build Coastguard Worker );
936*bb4ee6a4SAndroid Build Coastguard Worker
937*bb4ee6a4SAndroid Build Coastguard Worker let params = from_net_arg("tap-fd=12,pci-address=00:01.1").unwrap();
938*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
939*bb4ee6a4SAndroid Build Coastguard Worker params,
940*bb4ee6a4SAndroid Build Coastguard Worker NetParameters {
941*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
942*bb4ee6a4SAndroid Build Coastguard Worker vhost_net: None,
943*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: None,
944*bb4ee6a4SAndroid Build Coastguard Worker mode: NetParametersMode::TapFd {
945*bb4ee6a4SAndroid Build Coastguard Worker tap_fd: 12,
946*bb4ee6a4SAndroid Build Coastguard Worker mac: None,
947*bb4ee6a4SAndroid Build Coastguard Worker },
948*bb4ee6a4SAndroid Build Coastguard Worker packed_queue: false,
949*bb4ee6a4SAndroid Build Coastguard Worker pci_address: Some(PciAddress {
950*bb4ee6a4SAndroid Build Coastguard Worker bus: 0,
951*bb4ee6a4SAndroid Build Coastguard Worker dev: 1,
952*bb4ee6a4SAndroid Build Coastguard Worker func: 1,
953*bb4ee6a4SAndroid Build Coastguard Worker }),
954*bb4ee6a4SAndroid Build Coastguard Worker }
955*bb4ee6a4SAndroid Build Coastguard Worker );
956*bb4ee6a4SAndroid Build Coastguard Worker
957*bb4ee6a4SAndroid Build Coastguard Worker // wrong pci format
958*bb4ee6a4SAndroid Build Coastguard Worker assert!(from_net_arg("tap-fd=12,pci-address=hello").is_err());
959*bb4ee6a4SAndroid Build Coastguard Worker
960*bb4ee6a4SAndroid Build Coastguard Worker // missing netmask
961*bb4ee6a4SAndroid Build Coastguard Worker assert!(from_net_arg("host-ip=\"192.168.10.1\",mac=\"3d:70:eb:61:1a:91\"").is_err());
962*bb4ee6a4SAndroid Build Coastguard Worker
963*bb4ee6a4SAndroid Build Coastguard Worker // invalid parameter
964*bb4ee6a4SAndroid Build Coastguard Worker assert!(from_net_arg("tap-name=tap,foomatic=true").is_err());
965*bb4ee6a4SAndroid Build Coastguard Worker }
966*bb4ee6a4SAndroid Build Coastguard Worker
967*bb4ee6a4SAndroid Build Coastguard Worker #[test]
968*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
params_from_key_values_vhost_net()969*bb4ee6a4SAndroid Build Coastguard Worker fn params_from_key_values_vhost_net() {
970*bb4ee6a4SAndroid Build Coastguard Worker let params = from_net_arg(
971*bb4ee6a4SAndroid Build Coastguard Worker "vhost-net=[device=/dev/foo],\
972*bb4ee6a4SAndroid Build Coastguard Worker host-ip=\"192.168.10.1\",\
973*bb4ee6a4SAndroid Build Coastguard Worker netmask=\"255.255.255.0\",\
974*bb4ee6a4SAndroid Build Coastguard Worker mac=\"3d:70:eb:61:1a:91\"",
975*bb4ee6a4SAndroid Build Coastguard Worker )
976*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
977*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
978*bb4ee6a4SAndroid Build Coastguard Worker params,
979*bb4ee6a4SAndroid Build Coastguard Worker NetParameters {
980*bb4ee6a4SAndroid Build Coastguard Worker vhost_net: Some(VhostNetParameters {
981*bb4ee6a4SAndroid Build Coastguard Worker device: PathBuf::from("/dev/foo")
982*bb4ee6a4SAndroid Build Coastguard Worker }),
983*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: None,
984*bb4ee6a4SAndroid Build Coastguard Worker mode: NetParametersMode::RawConfig {
985*bb4ee6a4SAndroid Build Coastguard Worker host_ip: Ipv4Addr::from_str("192.168.10.1").unwrap(),
986*bb4ee6a4SAndroid Build Coastguard Worker netmask: Ipv4Addr::from_str("255.255.255.0").unwrap(),
987*bb4ee6a4SAndroid Build Coastguard Worker mac: MacAddress::from_str("3d:70:eb:61:1a:91").unwrap(),
988*bb4ee6a4SAndroid Build Coastguard Worker },
989*bb4ee6a4SAndroid Build Coastguard Worker packed_queue: false,
990*bb4ee6a4SAndroid Build Coastguard Worker pci_address: None,
991*bb4ee6a4SAndroid Build Coastguard Worker }
992*bb4ee6a4SAndroid Build Coastguard Worker );
993*bb4ee6a4SAndroid Build Coastguard Worker
994*bb4ee6a4SAndroid Build Coastguard Worker let params = from_net_arg("tap-fd=3,vhost-net").unwrap();
995*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
996*bb4ee6a4SAndroid Build Coastguard Worker params,
997*bb4ee6a4SAndroid Build Coastguard Worker NetParameters {
998*bb4ee6a4SAndroid Build Coastguard Worker vhost_net: Some(Default::default()),
999*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: None,
1000*bb4ee6a4SAndroid Build Coastguard Worker mode: NetParametersMode::TapFd {
1001*bb4ee6a4SAndroid Build Coastguard Worker tap_fd: 3,
1002*bb4ee6a4SAndroid Build Coastguard Worker mac: None
1003*bb4ee6a4SAndroid Build Coastguard Worker },
1004*bb4ee6a4SAndroid Build Coastguard Worker packed_queue: false,
1005*bb4ee6a4SAndroid Build Coastguard Worker pci_address: None,
1006*bb4ee6a4SAndroid Build Coastguard Worker }
1007*bb4ee6a4SAndroid Build Coastguard Worker );
1008*bb4ee6a4SAndroid Build Coastguard Worker
1009*bb4ee6a4SAndroid Build Coastguard Worker let params = from_net_arg("vhost-net,tap-name=crosvm_tap").unwrap();
1010*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1011*bb4ee6a4SAndroid Build Coastguard Worker params,
1012*bb4ee6a4SAndroid Build Coastguard Worker NetParameters {
1013*bb4ee6a4SAndroid Build Coastguard Worker vhost_net: Some(Default::default()),
1014*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: None,
1015*bb4ee6a4SAndroid Build Coastguard Worker mode: NetParametersMode::TapName {
1016*bb4ee6a4SAndroid Build Coastguard Worker tap_name: "crosvm_tap".to_owned(),
1017*bb4ee6a4SAndroid Build Coastguard Worker mac: None
1018*bb4ee6a4SAndroid Build Coastguard Worker },
1019*bb4ee6a4SAndroid Build Coastguard Worker packed_queue: false,
1020*bb4ee6a4SAndroid Build Coastguard Worker pci_address: None,
1021*bb4ee6a4SAndroid Build Coastguard Worker }
1022*bb4ee6a4SAndroid Build Coastguard Worker );
1023*bb4ee6a4SAndroid Build Coastguard Worker
1024*bb4ee6a4SAndroid Build Coastguard Worker let params =
1025*bb4ee6a4SAndroid Build Coastguard Worker from_net_arg("vhost-net,mac=\"3d:70:eb:61:1a:91\",tap-name=crosvm_tap").unwrap();
1026*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1027*bb4ee6a4SAndroid Build Coastguard Worker params,
1028*bb4ee6a4SAndroid Build Coastguard Worker NetParameters {
1029*bb4ee6a4SAndroid Build Coastguard Worker vhost_net: Some(Default::default()),
1030*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: None,
1031*bb4ee6a4SAndroid Build Coastguard Worker mode: NetParametersMode::TapName {
1032*bb4ee6a4SAndroid Build Coastguard Worker tap_name: "crosvm_tap".to_owned(),
1033*bb4ee6a4SAndroid Build Coastguard Worker mac: Some(MacAddress::from_str("3d:70:eb:61:1a:91").unwrap())
1034*bb4ee6a4SAndroid Build Coastguard Worker },
1035*bb4ee6a4SAndroid Build Coastguard Worker packed_queue: false,
1036*bb4ee6a4SAndroid Build Coastguard Worker pci_address: None,
1037*bb4ee6a4SAndroid Build Coastguard Worker }
1038*bb4ee6a4SAndroid Build Coastguard Worker );
1039*bb4ee6a4SAndroid Build Coastguard Worker
1040*bb4ee6a4SAndroid Build Coastguard Worker let params = from_net_arg("tap-name=tap,packed-queue=true").unwrap();
1041*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1042*bb4ee6a4SAndroid Build Coastguard Worker params,
1043*bb4ee6a4SAndroid Build Coastguard Worker NetParameters {
1044*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
1045*bb4ee6a4SAndroid Build Coastguard Worker vhost_net: None,
1046*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: None,
1047*bb4ee6a4SAndroid Build Coastguard Worker mode: NetParametersMode::TapName {
1048*bb4ee6a4SAndroid Build Coastguard Worker tap_name: "tap".to_string(),
1049*bb4ee6a4SAndroid Build Coastguard Worker mac: None
1050*bb4ee6a4SAndroid Build Coastguard Worker },
1051*bb4ee6a4SAndroid Build Coastguard Worker packed_queue: true,
1052*bb4ee6a4SAndroid Build Coastguard Worker pci_address: None,
1053*bb4ee6a4SAndroid Build Coastguard Worker }
1054*bb4ee6a4SAndroid Build Coastguard Worker );
1055*bb4ee6a4SAndroid Build Coastguard Worker
1056*bb4ee6a4SAndroid Build Coastguard Worker let params = from_net_arg("tap-name=tap,packed-queue").unwrap();
1057*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1058*bb4ee6a4SAndroid Build Coastguard Worker params,
1059*bb4ee6a4SAndroid Build Coastguard Worker NetParameters {
1060*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
1061*bb4ee6a4SAndroid Build Coastguard Worker vhost_net: None,
1062*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: None,
1063*bb4ee6a4SAndroid Build Coastguard Worker mode: NetParametersMode::TapName {
1064*bb4ee6a4SAndroid Build Coastguard Worker tap_name: "tap".to_string(),
1065*bb4ee6a4SAndroid Build Coastguard Worker mac: None
1066*bb4ee6a4SAndroid Build Coastguard Worker },
1067*bb4ee6a4SAndroid Build Coastguard Worker packed_queue: true,
1068*bb4ee6a4SAndroid Build Coastguard Worker pci_address: None,
1069*bb4ee6a4SAndroid Build Coastguard Worker }
1070*bb4ee6a4SAndroid Build Coastguard Worker );
1071*bb4ee6a4SAndroid Build Coastguard Worker
1072*bb4ee6a4SAndroid Build Coastguard Worker let params = from_net_arg("vhost-net,tap-name=crosvm_tap,pci-address=00:01.1").unwrap();
1073*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1074*bb4ee6a4SAndroid Build Coastguard Worker params,
1075*bb4ee6a4SAndroid Build Coastguard Worker NetParameters {
1076*bb4ee6a4SAndroid Build Coastguard Worker vhost_net: Some(Default::default()),
1077*bb4ee6a4SAndroid Build Coastguard Worker vq_pairs: None,
1078*bb4ee6a4SAndroid Build Coastguard Worker mode: NetParametersMode::TapName {
1079*bb4ee6a4SAndroid Build Coastguard Worker tap_name: "crosvm_tap".to_owned(),
1080*bb4ee6a4SAndroid Build Coastguard Worker mac: None,
1081*bb4ee6a4SAndroid Build Coastguard Worker },
1082*bb4ee6a4SAndroid Build Coastguard Worker packed_queue: false,
1083*bb4ee6a4SAndroid Build Coastguard Worker pci_address: Some(PciAddress {
1084*bb4ee6a4SAndroid Build Coastguard Worker bus: 0,
1085*bb4ee6a4SAndroid Build Coastguard Worker dev: 1,
1086*bb4ee6a4SAndroid Build Coastguard Worker func: 1,
1087*bb4ee6a4SAndroid Build Coastguard Worker }),
1088*bb4ee6a4SAndroid Build Coastguard Worker }
1089*bb4ee6a4SAndroid Build Coastguard Worker );
1090*bb4ee6a4SAndroid Build Coastguard Worker
1091*bb4ee6a4SAndroid Build Coastguard Worker // mixed configs
1092*bb4ee6a4SAndroid Build Coastguard Worker assert!(from_net_arg(
1093*bb4ee6a4SAndroid Build Coastguard Worker "tap-name=tap,\
1094*bb4ee6a4SAndroid Build Coastguard Worker vhost-net,\
1095*bb4ee6a4SAndroid Build Coastguard Worker host-ip=\"192.168.10.1\",\
1096*bb4ee6a4SAndroid Build Coastguard Worker netmask=\"255.255.255.0\",\
1097*bb4ee6a4SAndroid Build Coastguard Worker mac=\"3d:70:eb:61:1a:91\"",
1098*bb4ee6a4SAndroid Build Coastguard Worker )
1099*bb4ee6a4SAndroid Build Coastguard Worker .is_err());
1100*bb4ee6a4SAndroid Build Coastguard Worker }
1101*bb4ee6a4SAndroid Build Coastguard Worker }
1102