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