• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
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::{self, Write};
6 use std::mem;
7 use std::net::Ipv4Addr;
8 use std::os::raw::c_uint;
9 use std::result;
10 use std::sync::Arc;
11 use std::thread;
12 
13 use base::Error as SysError;
14 use base::{error, warn, AsRawDescriptor, Event, EventType, PollToken, RawDescriptor, WaitContext};
15 use data_model::{DataInit, Le16, Le64};
16 use net_util::{Error as TapError, MacAddress, TapT};
17 use remain::sorted;
18 use thiserror::Error as ThisError;
19 use virtio_sys::virtio_net;
20 use virtio_sys::virtio_net::{
21     virtio_net_hdr_v1, VIRTIO_NET_CTRL_GUEST_OFFLOADS, VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET,
22     VIRTIO_NET_CTRL_MQ, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, VIRTIO_NET_ERR, VIRTIO_NET_OK,
23 };
24 use vm_memory::GuestMemory;
25 
26 use super::{
27     copy_config, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt, VirtioDevice,
28     Writer, TYPE_NET,
29 };
30 
31 const QUEUE_SIZE: u16 = 256;
32 
33 #[sorted]
34 #[derive(ThisError, Debug)]
35 pub enum NetError {
36     /// Cloning kill event failed.
37     #[error("failed to clone kill event: {0}")]
38     CloneKillEvent(SysError),
39     /// Creating kill event failed.
40     #[error("failed to create kill event: {0}")]
41     CreateKillEvent(SysError),
42     /// Creating WaitContext failed.
43     #[error("failed to create wait context: {0}")]
44     CreateWaitContext(SysError),
45     /// Descriptor chain was invalid.
46     #[error("failed to valildate descriptor chain: {0}")]
47     DescriptorChain(DescriptorError),
48     /// Error reading data from control queue.
49     #[error("failed to read control message data: {0}")]
50     ReadCtrlData(io::Error),
51     /// Error reading header from control queue.
52     #[error("failed to read control message header: {0}")]
53     ReadCtrlHeader(io::Error),
54     /// There are no more available descriptors to receive into.
55     #[error("no rx descriptors available")]
56     RxDescriptorsExhausted,
57     /// Enabling tap interface failed.
58     #[error("failed to enable tap interface: {0}")]
59     TapEnable(TapError),
60     /// Couldn't get the MTU from the tap device.
61     #[error("failed to get tap interface MTU: {0}")]
62     TapGetMtu(TapError),
63     /// Open tap device failed.
64     #[error("failed to open tap device: {0}")]
65     TapOpen(TapError),
66     /// Setting tap IP failed.
67     #[error("failed to set tap IP: {0}")]
68     TapSetIp(TapError),
69     /// Setting tap mac address failed.
70     #[error("failed to set tap mac address: {0}")]
71     TapSetMacAddress(TapError),
72     /// Setting tap netmask failed.
73     #[error("failed to set tap netmask: {0}")]
74     TapSetNetmask(TapError),
75     /// Setting vnet header size failed.
76     #[error("failed to set vnet header size: {0}")]
77     TapSetVnetHdrSize(TapError),
78     /// Validating tap interface failed.
79     #[error("failed to validate tap interface: {0}")]
80     TapValidate(String),
81     /// Removing read event from the tap fd events failed.
82     #[error("failed to disable EPOLLIN on tap fd: {0}")]
83     WaitContextDisableTap(SysError),
84     /// Adding read event to the tap fd events failed.
85     #[error("failed to enable EPOLLIN on tap fd: {0}")]
86     WaitContextEnableTap(SysError),
87     /// Error while waiting for events.
88     #[error("error while waiting for events: {0}")]
89     WaitError(SysError),
90     /// Failed writing an ack in response to a control message.
91     #[error("failed to write control message ack: {0}")]
92     WriteAck(io::Error),
93     /// Writing to a buffer in the guest failed.
94     #[error("failed to write to guest buffer: {0}")]
95     WriteBuffer(io::Error),
96 }
97 
98 #[repr(C, packed)]
99 #[derive(Debug, Clone, Copy)]
100 pub struct virtio_net_ctrl_hdr {
101     pub class: u8,
102     pub cmd: u8,
103 }
104 
105 // Safe because it only has data and has no implicit padding.
106 unsafe impl DataInit for virtio_net_ctrl_hdr {}
107 
108 /// Converts virtio-net feature bits to tap's offload bits.
virtio_features_to_tap_offload(features: u64) -> c_uint109 pub fn virtio_features_to_tap_offload(features: u64) -> c_uint {
110     let mut tap_offloads: c_uint = 0;
111     if features & (1 << virtio_net::VIRTIO_NET_F_GUEST_CSUM) != 0 {
112         tap_offloads |= net_sys::TUN_F_CSUM;
113     }
114     if features & (1 << virtio_net::VIRTIO_NET_F_GUEST_TSO4) != 0 {
115         tap_offloads |= net_sys::TUN_F_TSO4;
116     }
117     if features & (1 << virtio_net::VIRTIO_NET_F_GUEST_TSO6) != 0 {
118         tap_offloads |= net_sys::TUN_F_TSO6;
119     }
120     if features & (1 << virtio_net::VIRTIO_NET_F_GUEST_ECN) != 0 {
121         tap_offloads |= net_sys::TUN_F_TSO_ECN;
122     }
123     if features & (1 << virtio_net::VIRTIO_NET_F_GUEST_UFO) != 0 {
124         tap_offloads |= net_sys::TUN_F_UFO;
125     }
126 
127     tap_offloads
128 }
129 
130 #[derive(Debug, Clone, Copy, Default)]
131 #[repr(C)]
132 pub struct VirtioNetConfig {
133     mac: [u8; 6],
134     status: Le16,
135     max_vq_pairs: Le16,
136     mtu: Le16,
137 }
138 
139 // Safe because it only has data and has no implicit padding.
140 unsafe impl DataInit for VirtioNetConfig {}
141 
process_rx<I: SignalableInterrupt, T: TapT>( interrupt: &I, rx_queue: &mut Queue, mem: &GuestMemory, mut tap: &mut T, ) -> result::Result<(), NetError>142 pub fn process_rx<I: SignalableInterrupt, T: TapT>(
143     interrupt: &I,
144     rx_queue: &mut Queue,
145     mem: &GuestMemory,
146     mut tap: &mut T,
147 ) -> result::Result<(), NetError> {
148     let mut needs_interrupt = false;
149     let mut exhausted_queue = false;
150 
151     // Read as many frames as possible.
152     loop {
153         let desc_chain = match rx_queue.peek(mem) {
154             Some(desc) => desc,
155             None => {
156                 exhausted_queue = true;
157                 break;
158             }
159         };
160 
161         let index = desc_chain.index;
162         let bytes_written = match Writer::new(mem.clone(), desc_chain) {
163             Ok(mut writer) => {
164                 match writer.write_from(&mut tap, writer.available_bytes()) {
165                     Ok(_) => {}
166                     Err(ref e) if e.kind() == io::ErrorKind::WriteZero => {
167                         warn!("net: rx: buffer is too small to hold frame");
168                         break;
169                     }
170                     Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
171                         // No more to read from the tap.
172                         break;
173                     }
174                     Err(e) => {
175                         warn!("net: rx: failed to write slice: {}", e);
176                         return Err(NetError::WriteBuffer(e));
177                     }
178                 };
179 
180                 writer.bytes_written() as u32
181             }
182             Err(e) => {
183                 error!("net: failed to create Writer: {}", e);
184                 0
185             }
186         };
187 
188         if bytes_written > 0 {
189             rx_queue.pop_peeked(mem);
190             rx_queue.add_used(mem, index, bytes_written);
191             needs_interrupt = true;
192         }
193     }
194 
195     if needs_interrupt {
196         rx_queue.trigger_interrupt(mem, interrupt);
197     }
198 
199     if exhausted_queue {
200         Err(NetError::RxDescriptorsExhausted)
201     } else {
202         Ok(())
203     }
204 }
205 
process_tx<I: SignalableInterrupt, T: TapT>( interrupt: &I, tx_queue: &mut Queue, mem: &GuestMemory, mut tap: &mut T, )206 pub fn process_tx<I: SignalableInterrupt, T: TapT>(
207     interrupt: &I,
208     tx_queue: &mut Queue,
209     mem: &GuestMemory,
210     mut tap: &mut T,
211 ) {
212     while let Some(desc_chain) = tx_queue.pop(mem) {
213         let index = desc_chain.index;
214 
215         match Reader::new(mem.clone(), desc_chain) {
216             Ok(mut reader) => {
217                 let expected_count = reader.available_bytes();
218                 match reader.read_to(&mut tap, expected_count) {
219                     Ok(count) => {
220                         // Tap writes must be done in one call. If the entire frame was not
221                         // written, it's an error.
222                         if count != expected_count {
223                             error!(
224                                 "net: tx: wrote only {} bytes of {} byte frame",
225                                 count, expected_count
226                             );
227                         }
228                     }
229                     Err(e) => error!("net: tx: failed to write frame to tap: {}", e),
230                 }
231             }
232             Err(e) => error!("net: failed to create Reader: {}", e),
233         }
234 
235         tx_queue.add_used(mem, index, 0);
236     }
237 
238     tx_queue.trigger_interrupt(mem, interrupt);
239 }
240 
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>241 pub fn process_ctrl<I: SignalableInterrupt, T: TapT>(
242     interrupt: &I,
243     ctrl_queue: &mut Queue,
244     mem: &GuestMemory,
245     tap: &mut T,
246     acked_features: u64,
247     vq_pairs: u16,
248 ) -> Result<(), NetError> {
249     while let Some(desc_chain) = ctrl_queue.pop(mem) {
250         let index = desc_chain.index;
251 
252         let mut reader =
253             Reader::new(mem.clone(), desc_chain.clone()).map_err(NetError::DescriptorChain)?;
254         let mut writer = Writer::new(mem.clone(), desc_chain).map_err(NetError::DescriptorChain)?;
255         let ctrl_hdr: virtio_net_ctrl_hdr = reader.read_obj().map_err(NetError::ReadCtrlHeader)?;
256 
257         let mut write_error = || {
258             writer
259                 .write_all(&[VIRTIO_NET_ERR as u8])
260                 .map_err(NetError::WriteAck)?;
261             ctrl_queue.add_used(mem, index, writer.bytes_written() as u32);
262             Ok(())
263         };
264 
265         match ctrl_hdr.class as c_uint {
266             VIRTIO_NET_CTRL_GUEST_OFFLOADS => {
267                 if ctrl_hdr.cmd != VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET as u8 {
268                     error!(
269                         "invalid cmd for VIRTIO_NET_CTRL_GUEST_OFFLOADS: {}",
270                         ctrl_hdr.cmd
271                     );
272                     write_error()?;
273                     continue;
274                 }
275                 let offloads: Le64 = reader.read_obj().map_err(NetError::ReadCtrlData)?;
276                 let tap_offloads = virtio_features_to_tap_offload(offloads.into());
277                 if let Err(e) = tap.set_offload(tap_offloads) {
278                     error!("Failed to set tap itnerface offload flags: {}", e);
279                     write_error()?;
280                     continue;
281                 }
282 
283                 let ack = VIRTIO_NET_OK as u8;
284                 writer.write_all(&[ack]).map_err(NetError::WriteAck)?;
285             }
286             VIRTIO_NET_CTRL_MQ => {
287                 if ctrl_hdr.cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET as u8 {
288                     let pairs: Le16 = reader.read_obj().map_err(NetError::ReadCtrlData)?;
289                     // Simple handle it now
290                     if acked_features & 1 << virtio_net::VIRTIO_NET_F_MQ == 0
291                         || pairs.to_native() != vq_pairs
292                     {
293                         error!("Invalid VQ_PAIRS_SET cmd, driver request pairs: {}, device vq pairs: {}",
294                                    pairs.to_native(), vq_pairs);
295                         write_error()?;
296                         continue;
297                     }
298                     let ack = VIRTIO_NET_OK as u8;
299                     writer.write_all(&[ack]).map_err(NetError::WriteAck)?;
300                 }
301             }
302             _ => warn!(
303                 "unimplemented class for VIRTIO_NET_CTRL_GUEST_OFFLOADS: {}",
304                 ctrl_hdr.class
305             ),
306         }
307 
308         ctrl_queue.add_used(mem, index, writer.bytes_written() as u32);
309     }
310 
311     ctrl_queue.trigger_interrupt(mem, interrupt);
312     Ok(())
313 }
314 
315 #[derive(PollToken, Debug, Clone)]
316 pub enum Token {
317     // A frame is available for reading from the tap device to receive in the guest.
318     RxTap,
319     // The guest has made a buffer available to receive a frame into.
320     RxQueue,
321     // The transmit queue has a frame that is ready to send from the guest.
322     TxQueue,
323     // The control queue has a message.
324     CtrlQueue,
325     // Check if any interrupts need to be re-asserted.
326     InterruptResample,
327     // crosvm has requested the device to shut down.
328     Kill,
329 }
330 
331 struct Worker<T: TapT> {
332     interrupt: Arc<Interrupt>,
333     mem: GuestMemory,
334     rx_queue: Queue,
335     tx_queue: Queue,
336     ctrl_queue: Option<Queue>,
337     tap: T,
338     acked_features: u64,
339     vq_pairs: u16,
340     kill_evt: Event,
341 }
342 
343 impl<T> Worker<T>
344 where
345     T: TapT,
346 {
process_rx(&mut self) -> result::Result<(), NetError>347     fn process_rx(&mut self) -> result::Result<(), NetError> {
348         process_rx(
349             self.interrupt.as_ref(),
350             &mut self.rx_queue,
351             &self.mem,
352             &mut self.tap,
353         )
354     }
355 
process_tx(&mut self)356     fn process_tx(&mut self) {
357         process_tx(
358             self.interrupt.as_ref(),
359             &mut self.tx_queue,
360             &self.mem,
361             &mut self.tap,
362         )
363     }
364 
process_ctrl(&mut self) -> Result<(), NetError>365     fn process_ctrl(&mut self) -> Result<(), NetError> {
366         let ctrl_queue = match self.ctrl_queue.as_mut() {
367             Some(queue) => queue,
368             None => return Ok(()),
369         };
370 
371         process_ctrl(
372             self.interrupt.as_ref(),
373             ctrl_queue,
374             &self.mem,
375             &mut self.tap,
376             self.acked_features,
377             self.vq_pairs,
378         )
379     }
380 
run( &mut self, rx_queue_evt: Event, tx_queue_evt: Event, ctrl_queue_evt: Option<Event>, ) -> Result<(), NetError>381     fn run(
382         &mut self,
383         rx_queue_evt: Event,
384         tx_queue_evt: Event,
385         ctrl_queue_evt: Option<Event>,
386     ) -> Result<(), NetError> {
387         let wait_ctx: WaitContext<Token> = WaitContext::build_with(&[
388             (&self.tap, Token::RxTap),
389             (&rx_queue_evt, Token::RxQueue),
390             (&tx_queue_evt, Token::TxQueue),
391             (&self.kill_evt, Token::Kill),
392         ])
393         .map_err(NetError::CreateWaitContext)?;
394 
395         if let Some(ctrl_evt) = &ctrl_queue_evt {
396             wait_ctx
397                 .add(ctrl_evt, Token::CtrlQueue)
398                 .map_err(NetError::CreateWaitContext)?;
399             // Let CtrlQueue's thread handle InterruptResample also.
400             if let Some(resample_evt) = self.interrupt.get_resample_evt() {
401                 wait_ctx
402                     .add(resample_evt, Token::InterruptResample)
403                     .map_err(NetError::CreateWaitContext)?;
404             }
405         }
406 
407         let mut tap_polling_enabled = true;
408         'wait: loop {
409             let events = wait_ctx.wait().map_err(NetError::WaitError)?;
410             for event in events.iter().filter(|e| e.is_readable) {
411                 match event.token {
412                     Token::RxTap => match self.process_rx() {
413                         Ok(()) => {}
414                         Err(NetError::RxDescriptorsExhausted) => {
415                             wait_ctx
416                                 .modify(&self.tap, EventType::None, Token::RxTap)
417                                 .map_err(NetError::WaitContextDisableTap)?;
418                             tap_polling_enabled = false;
419                         }
420                         Err(e) => return Err(e),
421                     },
422                     Token::RxQueue => {
423                         if let Err(e) = rx_queue_evt.read() {
424                             error!("net: error reading rx queue Event: {}", e);
425                             break 'wait;
426                         }
427                         if !tap_polling_enabled {
428                             wait_ctx
429                                 .modify(&self.tap, EventType::Read, Token::RxTap)
430                                 .map_err(NetError::WaitContextEnableTap)?;
431                             tap_polling_enabled = true;
432                         }
433                     }
434                     Token::TxQueue => {
435                         if let Err(e) = tx_queue_evt.read() {
436                             error!("net: error reading tx queue Event: {}", e);
437                             break 'wait;
438                         }
439                         self.process_tx();
440                     }
441                     Token::CtrlQueue => {
442                         if let Some(ctrl_evt) = &ctrl_queue_evt {
443                             if let Err(e) = ctrl_evt.read() {
444                                 error!("net: error reading ctrl queue Event: {}", e);
445                                 break 'wait;
446                             }
447                         } else {
448                             break 'wait;
449                         }
450                         if let Err(e) = self.process_ctrl() {
451                             error!("net: failed to process control message: {}", e);
452                             break 'wait;
453                         }
454                     }
455                     Token::InterruptResample => {
456                         // We can unwrap safely because interrupt must have the event.
457                         let _ = self.interrupt.get_resample_evt().unwrap().read();
458                         self.interrupt.do_interrupt_resample();
459                     }
460                     Token::Kill => {
461                         let _ = self.kill_evt.read();
462                         break 'wait;
463                     }
464                 }
465             }
466         }
467         Ok(())
468     }
469 }
470 
build_config(vq_pairs: u16, mtu: u16) -> VirtioNetConfig471 pub fn build_config(vq_pairs: u16, mtu: u16) -> VirtioNetConfig {
472     VirtioNetConfig {
473         max_vq_pairs: Le16::from(vq_pairs),
474         mtu: Le16::from(mtu),
475         // Other field has meaningful value when the corresponding feature
476         // is enabled, but all these features aren't supported now.
477         // So set them to default.
478         ..Default::default()
479     }
480 }
481 
482 pub struct Net<T: TapT> {
483     queue_sizes: Box<[u16]>,
484     workers_kill_evt: Vec<Event>,
485     kill_evts: Vec<Event>,
486     worker_threads: Vec<thread::JoinHandle<Worker<T>>>,
487     taps: Vec<T>,
488     avail_features: u64,
489     acked_features: u64,
490     mtu: u16,
491 }
492 
493 impl<T> Net<T>
494 where
495     T: TapT,
496 {
497     /// Create a new virtio network device with the given IP address and
498     /// netmask.
new( base_features: u64, ip_addr: Ipv4Addr, netmask: Ipv4Addr, mac_addr: MacAddress, vq_pairs: u16, ) -> Result<Net<T>, NetError>499     pub fn new(
500         base_features: u64,
501         ip_addr: Ipv4Addr,
502         netmask: Ipv4Addr,
503         mac_addr: MacAddress,
504         vq_pairs: u16,
505     ) -> Result<Net<T>, NetError> {
506         let multi_queue = vq_pairs > 1;
507         let tap: T = T::new(true, multi_queue).map_err(NetError::TapOpen)?;
508         tap.set_ip_addr(ip_addr).map_err(NetError::TapSetIp)?;
509         tap.set_netmask(netmask).map_err(NetError::TapSetNetmask)?;
510         tap.set_mac_address(mac_addr)
511             .map_err(NetError::TapSetMacAddress)?;
512 
513         tap.enable().map_err(NetError::TapEnable)?;
514 
515         Net::from(base_features, tap, vq_pairs)
516     }
517 
518     /// Try to open the already-configured TAP interface `name` and to create a network device from
519     /// it.
new_from_name( base_features: u64, name: &[u8], vq_pairs: u16, ) -> Result<Net<T>, NetError>520     pub fn new_from_name(
521         base_features: u64,
522         name: &[u8],
523         vq_pairs: u16,
524     ) -> Result<Net<T>, NetError> {
525         let multi_queue = vq_pairs > 1;
526         let tap: T = T::new_with_name(name, true, multi_queue).map_err(NetError::TapOpen)?;
527 
528         Net::from(base_features, tap, vq_pairs)
529     }
530 
531     /// Creates a new virtio network device from a tap device that has already been
532     /// configured.
from(base_features: u64, tap: T, vq_pairs: u16) -> Result<Net<T>, NetError>533     pub fn from(base_features: u64, tap: T, vq_pairs: u16) -> Result<Net<T>, NetError> {
534         let taps = tap.into_mq_taps(vq_pairs).map_err(NetError::TapOpen)?;
535 
536         let mut mtu = u16::MAX;
537         // This would also validate a tap created by Self::new(), but that's a good thing as it
538         // would ensure that any changes in the creation procedure are matched in the validation.
539         // Plus we still need to set the offload and vnet_hdr_size values.
540         for tap in &taps {
541             validate_and_configure_tap(tap, vq_pairs)?;
542             mtu = std::cmp::min(mtu, tap.mtu().map_err(NetError::TapGetMtu)?);
543         }
544 
545         let mut avail_features = base_features
546             | 1 << virtio_net::VIRTIO_NET_F_GUEST_CSUM
547             | 1 << virtio_net::VIRTIO_NET_F_CSUM
548             | 1 << virtio_net::VIRTIO_NET_F_CTRL_VQ
549             | 1 << virtio_net::VIRTIO_NET_F_CTRL_GUEST_OFFLOADS
550             | 1 << virtio_net::VIRTIO_NET_F_GUEST_TSO4
551             | 1 << virtio_net::VIRTIO_NET_F_GUEST_UFO
552             | 1 << virtio_net::VIRTIO_NET_F_HOST_TSO4
553             | 1 << virtio_net::VIRTIO_NET_F_HOST_UFO
554             | 1 << virtio_net::VIRTIO_NET_F_MTU;
555 
556         if vq_pairs > 1 {
557             avail_features |= 1 << virtio_net::VIRTIO_NET_F_MQ;
558         }
559 
560         let mut kill_evts: Vec<Event> = Vec::new();
561         let mut workers_kill_evt: Vec<Event> = Vec::new();
562         for _ in 0..taps.len() {
563             let kill_evt = Event::new().map_err(NetError::CreateKillEvent)?;
564             let worker_kill_evt = kill_evt.try_clone().map_err(NetError::CloneKillEvent)?;
565             kill_evts.push(kill_evt);
566             workers_kill_evt.push(worker_kill_evt);
567         }
568 
569         Ok(Net {
570             queue_sizes: vec![QUEUE_SIZE; (vq_pairs * 2 + 1) as usize].into_boxed_slice(),
571             workers_kill_evt,
572             kill_evts,
573             worker_threads: Vec::new(),
574             taps,
575             avail_features,
576             acked_features: 0u64,
577             mtu,
578         })
579     }
580 }
581 
582 // Ensure that the tap interface has the correct flags and sets the offload and VNET header size
583 // to the appropriate values.
validate_and_configure_tap<T: TapT>(tap: &T, vq_pairs: u16) -> Result<(), NetError>584 pub fn validate_and_configure_tap<T: TapT>(tap: &T, vq_pairs: u16) -> Result<(), NetError> {
585     let flags = tap.if_flags();
586     let mut required_flags = vec![
587         (libc::IFF_TAP, "IFF_TAP"),
588         (libc::IFF_NO_PI, "IFF_NO_PI"),
589         (libc::IFF_VNET_HDR, "IFF_VNET_HDR"),
590     ];
591     if vq_pairs > 1 {
592         required_flags.push((libc::IFF_MULTI_QUEUE, "IFF_MULTI_QUEUE"));
593     }
594     let missing_flags = required_flags
595         .iter()
596         .filter_map(
597             |(value, name)| {
598                 if value & flags == 0 {
599                     Some(name)
600                 } else {
601                     None
602                 }
603             },
604         )
605         .collect::<Vec<_>>();
606 
607     if !missing_flags.is_empty() {
608         return Err(NetError::TapValidate(format!(
609             "Missing flags: {:?}",
610             missing_flags
611         )));
612     }
613 
614     let vnet_hdr_size = mem::size_of::<virtio_net_hdr_v1>() as i32;
615     tap.set_vnet_hdr_size(vnet_hdr_size)
616         .map_err(NetError::TapSetVnetHdrSize)?;
617 
618     Ok(())
619 }
620 
621 impl<T> Drop for Net<T>
622 where
623     T: TapT,
624 {
drop(&mut self)625     fn drop(&mut self) {
626         let len = self.kill_evts.len();
627         for i in 0..len {
628             // Only kill the child if it claimed its event.
629             if self.workers_kill_evt.get(i).is_none() {
630                 if let Some(kill_evt) = self.kill_evts.get(i) {
631                     // Ignore the result because there is nothing we can do about it.
632                     let _ = kill_evt.write(1);
633                 }
634             }
635         }
636 
637         let len = self.worker_threads.len();
638         for _ in 0..len {
639             let _ = self.worker_threads.remove(0).join();
640         }
641     }
642 }
643 
644 impl<T> VirtioDevice for Net<T>
645 where
646     T: 'static + TapT,
647 {
keep_rds(&self) -> Vec<RawDescriptor>648     fn keep_rds(&self) -> Vec<RawDescriptor> {
649         let mut keep_rds = Vec::new();
650 
651         for tap in &self.taps {
652             keep_rds.push(tap.as_raw_descriptor());
653         }
654 
655         for worker_kill_evt in &self.workers_kill_evt {
656             keep_rds.push(worker_kill_evt.as_raw_descriptor());
657         }
658         for kill_evt in &self.kill_evts {
659             keep_rds.push(kill_evt.as_raw_descriptor());
660         }
661 
662         keep_rds
663     }
664 
device_type(&self) -> u32665     fn device_type(&self) -> u32 {
666         TYPE_NET
667     }
668 
queue_max_sizes(&self) -> &[u16]669     fn queue_max_sizes(&self) -> &[u16] {
670         &self.queue_sizes
671     }
672 
features(&self) -> u64673     fn features(&self) -> u64 {
674         self.avail_features
675     }
676 
ack_features(&mut self, value: u64)677     fn ack_features(&mut self, value: u64) {
678         let mut v = value;
679 
680         // Check if the guest is ACK'ing a feature that we didn't claim to have.
681         let unrequested_features = v & !self.avail_features;
682         if unrequested_features != 0 {
683             warn!("net: virtio net got unknown feature ack: {:x}", v);
684 
685             // Don't count these features as acked.
686             v &= !unrequested_features;
687         }
688         self.acked_features |= v;
689 
690         // Set offload flags to match acked virtio features.
691         if let Some(tap) = self.taps.first() {
692             if let Err(e) = tap.set_offload(virtio_features_to_tap_offload(self.acked_features)) {
693                 warn!(
694                     "net: failed to set tap offload to match acked features: {}",
695                     e
696                 );
697             }
698         }
699     }
700 
read_config(&self, offset: u64, data: &mut [u8])701     fn read_config(&self, offset: u64, data: &mut [u8]) {
702         let vq_pairs = self.queue_sizes.len() / 2;
703         let config_space = build_config(vq_pairs as u16, self.mtu);
704         copy_config(data, 0, config_space.as_slice(), offset);
705     }
706 
activate( &mut self, mem: GuestMemory, interrupt: Interrupt, mut queues: Vec<Queue>, mut queue_evts: Vec<Event>, )707     fn activate(
708         &mut self,
709         mem: GuestMemory,
710         interrupt: Interrupt,
711         mut queues: Vec<Queue>,
712         mut queue_evts: Vec<Event>,
713     ) {
714         if queues.len() != self.queue_sizes.len() || queue_evts.len() != self.queue_sizes.len() {
715             error!(
716                 "net: expected {} queues, got {}",
717                 self.queue_sizes.len(),
718                 queues.len()
719             );
720             return;
721         }
722 
723         let vq_pairs = self.queue_sizes.len() / 2;
724         if self.taps.len() != vq_pairs {
725             error!("net: expected {} taps, got {}", vq_pairs, self.taps.len());
726             return;
727         }
728         if self.workers_kill_evt.len() != vq_pairs {
729             error!(
730                 "net: expected {} worker_kill_evt, got {}",
731                 vq_pairs,
732                 self.workers_kill_evt.len()
733             );
734             return;
735         }
736         let interrupt_arc = Arc::new(interrupt);
737         for i in 0..vq_pairs {
738             let tap = self.taps.remove(0);
739             let acked_features = self.acked_features;
740             let interrupt = interrupt_arc.clone();
741             let memory = mem.clone();
742             let kill_evt = self.workers_kill_evt.remove(0);
743             // Queues alternate between rx0, tx0, rx1, tx1, ..., rxN, txN, ctrl.
744             let rx_queue = queues.remove(0);
745             let tx_queue = queues.remove(0);
746             let ctrl_queue = if i == 0 {
747                 Some(queues.remove(queues.len() - 1))
748             } else {
749                 None
750             };
751             let pairs = vq_pairs as u16;
752             let rx_queue_evt = queue_evts.remove(0);
753             let tx_queue_evt = queue_evts.remove(0);
754             let ctrl_queue_evt = if i == 0 {
755                 Some(queue_evts.remove(queue_evts.len() - 1))
756             } else {
757                 None
758             };
759             let worker_result = thread::Builder::new()
760                 .name(format!("virtio_net worker {}", i))
761                 .spawn(move || {
762                     let mut worker = Worker {
763                         interrupt,
764                         mem: memory,
765                         rx_queue,
766                         tx_queue,
767                         ctrl_queue,
768                         tap,
769                         acked_features,
770                         vq_pairs: pairs,
771                         kill_evt,
772                     };
773                     let result = worker.run(rx_queue_evt, tx_queue_evt, ctrl_queue_evt);
774                     if let Err(e) = result {
775                         error!("net worker thread exited with error: {}", e);
776                     }
777                     worker
778                 });
779 
780             match worker_result {
781                 Err(e) => {
782                     error!("failed to spawn virtio_net worker: {}", e);
783                     return;
784                 }
785                 Ok(join_handle) => self.worker_threads.push(join_handle),
786             }
787         }
788     }
789 
reset(&mut self) -> bool790     fn reset(&mut self) -> bool {
791         let len = self.kill_evts.len();
792         for i in 0..len {
793             // Only kill the child if it claimed its event.
794             if self.workers_kill_evt.get(i).is_none() {
795                 if let Some(kill_evt) = self.kill_evts.get(i) {
796                     if kill_evt.write(1).is_err() {
797                         error!("{}: failed to notify the kill event", self.debug_label());
798                         return false;
799                     }
800                 }
801             }
802         }
803 
804         let len = self.worker_threads.len();
805         for _ in 0..len {
806             match self.worker_threads.remove(0).join() {
807                 Err(_) => {
808                     error!("{}: failed to get back resources", self.debug_label());
809                     return false;
810                 }
811                 Ok(worker) => {
812                     self.taps.push(worker.tap);
813                     self.workers_kill_evt.push(worker.kill_evt);
814                 }
815             }
816         }
817 
818         true
819     }
820 }
821