xref: /cloud-hypervisor/virtio-devices/src/net.rs (revision 30cf1eed5e63499f3101ed320fc384b59c60fc6b)
1 // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 // SPDX-License-Identifier: Apache-2.0
3 //
4 // Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
5 // Use of this source code is governed by a BSD-style license that can be
6 // found in the THIRD-PARTY file.
7 
8 use std::collections::HashMap;
9 use std::net::Ipv4Addr;
10 use std::num::Wrapping;
11 use std::ops::Deref;
12 use std::os::unix::io::{AsRawFd, RawFd};
13 use std::sync::atomic::{AtomicBool, Ordering};
14 use std::sync::{Arc, Barrier};
15 use std::{result, thread};
16 
17 use anyhow::anyhow;
18 #[cfg(not(fuzzing))]
19 use net_util::virtio_features_to_tap_offload;
20 use net_util::{
21     build_net_config_space, build_net_config_space_with_mq, open_tap, CtrlQueue, MacAddr,
22     NetCounters, NetQueuePair, OpenTapError, RxVirtio, Tap, TapError, TxVirtio, VirtioNetConfig,
23 };
24 use seccompiler::SeccompAction;
25 use serde::{Deserialize, Serialize};
26 use thiserror::Error;
27 use virtio_bindings::virtio_config::*;
28 use virtio_bindings::virtio_net::*;
29 use virtio_bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
30 use virtio_queue::{Queue, QueueT};
31 use vm_memory::{ByteValued, GuestAddressSpace, GuestMemoryAtomic};
32 use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
33 use vm_virtio::AccessPlatform;
34 use vmm_sys_util::eventfd::EventFd;
35 
36 use super::{
37     ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler,
38     Error as DeviceError, RateLimiterConfig, VirtioCommon, VirtioDevice, VirtioDeviceType,
39     VirtioInterruptType, EPOLL_HELPER_EVENT_LAST,
40 };
41 use crate::seccomp_filters::Thread;
42 use crate::thread_helper::spawn_virtio_thread;
43 use crate::{GuestMemoryMmap, VirtioInterrupt};
44 
45 /// Control queue
46 // Event available on the control queue.
47 const CTRL_QUEUE_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1;
48 
49 // Following the VIRTIO specification, the MTU should be at least 1280.
50 pub const MIN_MTU: u16 = 1280;
51 
52 pub struct NetCtrlEpollHandler {
53     pub mem: GuestMemoryAtomic<GuestMemoryMmap>,
54     pub kill_evt: EventFd,
55     pub pause_evt: EventFd,
56     pub ctrl_q: CtrlQueue,
57     pub queue_evt: EventFd,
58     pub queue: Queue,
59     pub access_platform: Option<Arc<dyn AccessPlatform>>,
60     pub interrupt_cb: Arc<dyn VirtioInterrupt>,
61     pub queue_index: u16,
62 }
63 
64 impl NetCtrlEpollHandler {
65     fn signal_used_queue(&self, queue_index: u16) -> result::Result<(), DeviceError> {
66         self.interrupt_cb
67             .trigger(VirtioInterruptType::Queue(queue_index))
68             .map_err(|e| {
69                 error!("Failed to signal used queue: {:?}", e);
70                 DeviceError::FailedSignalingUsedQueue(e)
71             })
72     }
73 
74     pub fn run_ctrl(
75         &mut self,
76         paused: Arc<AtomicBool>,
77         paused_sync: Arc<Barrier>,
78     ) -> std::result::Result<(), EpollHelperError> {
79         let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
80         helper.add_event(self.queue_evt.as_raw_fd(), CTRL_QUEUE_EVENT)?;
81         helper.run(paused, paused_sync, self)?;
82 
83         Ok(())
84     }
85 }
86 
87 impl EpollHelperHandler for NetCtrlEpollHandler {
88     fn handle_event(
89         &mut self,
90         _helper: &mut EpollHelper,
91         event: &epoll::Event,
92     ) -> result::Result<(), EpollHelperError> {
93         let ev_type = event.data as u16;
94         match ev_type {
95             CTRL_QUEUE_EVENT => {
96                 let mem = self.mem.memory();
97                 self.queue_evt.read().map_err(|e| {
98                     EpollHelperError::HandleEvent(anyhow!(
99                         "Failed to get control queue event: {:?}",
100                         e
101                     ))
102                 })?;
103                 self.ctrl_q
104                     .process(mem.deref(), &mut self.queue, self.access_platform.as_ref())
105                     .map_err(|e| {
106                         EpollHelperError::HandleEvent(anyhow!(
107                             "Failed to process control queue: {:?}",
108                             e
109                         ))
110                     })?;
111                 match self.queue.needs_notification(mem.deref()) {
112                     Ok(true) => {
113                         self.signal_used_queue(self.queue_index).map_err(|e| {
114                             EpollHelperError::HandleEvent(anyhow!(
115                                 "Error signalling that control queue was used: {:?}",
116                                 e
117                             ))
118                         })?;
119                     }
120                     Ok(false) => {}
121                     Err(e) => {
122                         return Err(EpollHelperError::HandleEvent(anyhow!(
123                             "Error getting notification state of control queue: {}",
124                             e
125                         )));
126                     }
127                 };
128             }
129             _ => {
130                 return Err(EpollHelperError::HandleEvent(anyhow!(
131                     "Unknown event for virtio-net control queue"
132                 )));
133             }
134         }
135 
136         Ok(())
137     }
138 }
139 
140 /// Rx/Tx queue pair
141 // The guest has made a buffer available to receive a frame into.
142 pub const RX_QUEUE_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1;
143 // The transmit queue has a frame that is ready to send from the guest.
144 pub const TX_QUEUE_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 2;
145 // A frame is available for reading from the tap device to receive in the guest.
146 pub const RX_TAP_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 3;
147 // The TAP can be written to. Used after an EAGAIN error to retry TX.
148 pub const TX_TAP_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 4;
149 // New 'wake up' event from the rx rate limiter
150 pub const RX_RATE_LIMITER_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 5;
151 // New 'wake up' event from the tx rate limiter
152 pub const TX_RATE_LIMITER_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 6;
153 
154 #[derive(Error, Debug)]
155 pub enum Error {
156     #[error("Failed to open taps: {0}")]
157     OpenTap(OpenTapError),
158     #[error("Using existing tap: {0}")]
159     TapError(TapError),
160     #[error("Error calling dup() on tap fd: {0}")]
161     DuplicateTapFd(std::io::Error),
162 }
163 
164 pub type Result<T> = result::Result<T, Error>;
165 
166 struct NetEpollHandler {
167     net: NetQueuePair,
168     mem: GuestMemoryAtomic<GuestMemoryMmap>,
169     interrupt_cb: Arc<dyn VirtioInterrupt>,
170     kill_evt: EventFd,
171     pause_evt: EventFd,
172     queue_index_base: u16,
173     queue_pair: (Queue, Queue),
174     queue_evt_pair: (EventFd, EventFd),
175     // Always generate interrupts until the driver has signalled to the device.
176     // This mitigates a problem with interrupts from tap events being "lost" upon
177     // a restore as the vCPU thread isn't ready to handle the interrupt. This causes
178     // issues when combined with VIRTIO_RING_F_EVENT_IDX interrupt suppression.
179     driver_awake: bool,
180 }
181 
182 impl NetEpollHandler {
183     fn signal_used_queue(&self, queue_index: u16) -> result::Result<(), DeviceError> {
184         self.interrupt_cb
185             .trigger(VirtioInterruptType::Queue(queue_index))
186             .map_err(|e| {
187                 error!("Failed to signal used queue: {:?}", e);
188                 DeviceError::FailedSignalingUsedQueue(e)
189             })
190     }
191 
192     fn handle_rx_event(&mut self) -> result::Result<(), DeviceError> {
193         let queue_evt = &self.queue_evt_pair.0;
194         if let Err(e) = queue_evt.read() {
195             error!("Failed to get rx queue event: {:?}", e);
196         }
197 
198         self.net.rx_desc_avail = true;
199 
200         let rate_limit_reached = self
201             .net
202             .rx_rate_limiter
203             .as_ref()
204             .is_some_and(|r| r.is_blocked());
205 
206         // Start to listen on RX_TAP_EVENT only when the rate limit is not reached
207         if !self.net.rx_tap_listening && !rate_limit_reached {
208             net_util::register_listener(
209                 self.net.epoll_fd.unwrap(),
210                 self.net.tap.as_raw_fd(),
211                 epoll::Events::EPOLLIN,
212                 u64::from(self.net.tap_rx_event_id),
213             )
214             .map_err(DeviceError::IoError)?;
215             self.net.rx_tap_listening = true;
216         }
217 
218         Ok(())
219     }
220 
221     fn process_tx(&mut self) -> result::Result<(), DeviceError> {
222         if self
223             .net
224             .process_tx(&self.mem.memory(), &mut self.queue_pair.1)
225             .map_err(DeviceError::NetQueuePair)?
226             || !self.driver_awake
227         {
228             self.signal_used_queue(self.queue_index_base + 1)?;
229             debug!("Signalling TX queue");
230         } else {
231             debug!("Not signalling TX queue");
232         }
233         Ok(())
234     }
235 
236     fn handle_tx_event(&mut self) -> result::Result<(), DeviceError> {
237         let rate_limit_reached = self
238             .net
239             .tx_rate_limiter
240             .as_ref()
241             .is_some_and(|r| r.is_blocked());
242 
243         if !rate_limit_reached {
244             self.process_tx()?;
245         }
246 
247         Ok(())
248     }
249 
250     fn handle_rx_tap_event(&mut self) -> result::Result<(), DeviceError> {
251         if self
252             .net
253             .process_rx(&self.mem.memory(), &mut self.queue_pair.0)
254             .map_err(DeviceError::NetQueuePair)?
255             || !self.driver_awake
256         {
257             self.signal_used_queue(self.queue_index_base)?;
258             debug!("Signalling RX queue");
259         } else {
260             debug!("Not signalling RX queue");
261         }
262         Ok(())
263     }
264 
265     fn run(
266         &mut self,
267         paused: Arc<AtomicBool>,
268         paused_sync: Arc<Barrier>,
269     ) -> result::Result<(), EpollHelperError> {
270         let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?;
271         helper.add_event(self.queue_evt_pair.0.as_raw_fd(), RX_QUEUE_EVENT)?;
272         helper.add_event(self.queue_evt_pair.1.as_raw_fd(), TX_QUEUE_EVENT)?;
273         if let Some(rate_limiter) = &self.net.rx_rate_limiter {
274             helper.add_event(rate_limiter.as_raw_fd(), RX_RATE_LIMITER_EVENT)?;
275         }
276         if let Some(rate_limiter) = &self.net.tx_rate_limiter {
277             helper.add_event(rate_limiter.as_raw_fd(), TX_RATE_LIMITER_EVENT)?;
278         }
279 
280         let mem = self.mem.memory();
281         // If there are some already available descriptors on the RX queue,
282         // then we can start the thread while listening onto the TAP.
283         if self
284             .queue_pair
285             .0
286             .used_idx(mem.deref(), Ordering::Acquire)
287             .map_err(EpollHelperError::QueueRingIndex)?
288             < self
289                 .queue_pair
290                 .0
291                 .avail_idx(mem.deref(), Ordering::Acquire)
292                 .map_err(EpollHelperError::QueueRingIndex)?
293         {
294             helper.add_event(self.net.tap.as_raw_fd(), RX_TAP_EVENT)?;
295             self.net.rx_tap_listening = true;
296             info!("Listener registered at start");
297         }
298 
299         // The NetQueuePair needs the epoll fd.
300         self.net.epoll_fd = Some(helper.as_raw_fd());
301 
302         helper.run(paused, paused_sync, self)?;
303 
304         Ok(())
305     }
306 }
307 
308 impl EpollHelperHandler for NetEpollHandler {
309     fn handle_event(
310         &mut self,
311         _helper: &mut EpollHelper,
312         event: &epoll::Event,
313     ) -> result::Result<(), EpollHelperError> {
314         let ev_type = event.data as u16;
315         match ev_type {
316             RX_QUEUE_EVENT => {
317                 self.driver_awake = true;
318                 self.handle_rx_event().map_err(|e| {
319                     EpollHelperError::HandleEvent(anyhow!("Error processing RX queue: {:?}", e))
320                 })?;
321             }
322             TX_QUEUE_EVENT => {
323                 let queue_evt = &self.queue_evt_pair.1;
324                 if let Err(e) = queue_evt.read() {
325                     error!("Failed to get tx queue event: {:?}", e);
326                 }
327                 self.driver_awake = true;
328                 self.handle_tx_event().map_err(|e| {
329                     EpollHelperError::HandleEvent(anyhow!("Error processing TX queue: {:?}", e))
330                 })?;
331             }
332             TX_TAP_EVENT => {
333                 self.handle_tx_event().map_err(|e| {
334                     EpollHelperError::HandleEvent(anyhow!(
335                         "Error processing TX queue (TAP event): {:?}",
336                         e
337                     ))
338                 })?;
339             }
340             RX_TAP_EVENT => {
341                 self.handle_rx_tap_event().map_err(|e| {
342                     EpollHelperError::HandleEvent(anyhow!("Error processing tap queue: {:?}", e))
343                 })?;
344             }
345             RX_RATE_LIMITER_EVENT => {
346                 if let Some(rate_limiter) = &mut self.net.rx_rate_limiter {
347                     // Upon rate limiter event, call the rate limiter handler and register the
348                     // TAP fd for further processing if some RX buffers are available
349                     rate_limiter.event_handler().map_err(|e| {
350                         EpollHelperError::HandleEvent(anyhow!(
351                             "Error from 'rate_limiter.event_handler()': {:?}",
352                             e
353                         ))
354                     })?;
355 
356                     if !self.net.rx_tap_listening && self.net.rx_desc_avail {
357                         net_util::register_listener(
358                             self.net.epoll_fd.unwrap(),
359                             self.net.tap.as_raw_fd(),
360                             epoll::Events::EPOLLIN,
361                             u64::from(self.net.tap_rx_event_id),
362                         )
363                         .map_err(|e| {
364                             EpollHelperError::HandleEvent(anyhow!(
365                                 "Error register_listener with `RX_RATE_LIMITER_EVENT`: {:?}",
366                                 e
367                             ))
368                         })?;
369 
370                         self.net.rx_tap_listening = true;
371                     }
372                 } else {
373                     return Err(EpollHelperError::HandleEvent(anyhow!(
374                         "Unexpected RX_RATE_LIMITER_EVENT"
375                     )));
376                 }
377             }
378             TX_RATE_LIMITER_EVENT => {
379                 if let Some(rate_limiter) = &mut self.net.tx_rate_limiter {
380                     // Upon rate limiter event, call the rate limiter handler
381                     // and restart processing the queue.
382                     rate_limiter.event_handler().map_err(|e| {
383                         EpollHelperError::HandleEvent(anyhow!(
384                             "Error from 'rate_limiter.event_handler()': {:?}",
385                             e
386                         ))
387                     })?;
388 
389                     self.driver_awake = true;
390                     self.process_tx().map_err(|e| {
391                         EpollHelperError::HandleEvent(anyhow!("Error processing TX queue: {:?}", e))
392                     })?;
393                 } else {
394                     return Err(EpollHelperError::HandleEvent(anyhow!(
395                         "Unexpected TX_RATE_LIMITER_EVENT"
396                     )));
397                 }
398             }
399             _ => {
400                 return Err(EpollHelperError::HandleEvent(anyhow!(
401                     "Unexpected event: {}",
402                     ev_type
403                 )));
404             }
405         }
406         Ok(())
407     }
408 }
409 
410 pub struct Net {
411     common: VirtioCommon,
412     id: String,
413     taps: Vec<Tap>,
414     config: VirtioNetConfig,
415     ctrl_queue_epoll_thread: Option<thread::JoinHandle<()>>,
416     counters: NetCounters,
417     seccomp_action: SeccompAction,
418     rate_limiter_config: Option<RateLimiterConfig>,
419     exit_evt: EventFd,
420 }
421 
422 #[derive(Serialize, Deserialize)]
423 pub struct NetState {
424     pub avail_features: u64,
425     pub acked_features: u64,
426     pub config: VirtioNetConfig,
427     pub queue_size: Vec<u16>,
428 }
429 
430 impl Net {
431     /// Create a new virtio network device with the given TAP interface.
432     #[allow(clippy::too_many_arguments)]
433     pub fn new_with_tap(
434         id: String,
435         taps: Vec<Tap>,
436         guest_mac: Option<MacAddr>,
437         iommu: bool,
438         num_queues: usize,
439         queue_size: u16,
440         seccomp_action: SeccompAction,
441         rate_limiter_config: Option<RateLimiterConfig>,
442         exit_evt: EventFd,
443         state: Option<NetState>,
444         offload_tso: bool,
445         offload_ufo: bool,
446         offload_csum: bool,
447     ) -> Result<Self> {
448         assert!(!taps.is_empty());
449 
450         let mtu = taps[0].mtu().map_err(Error::TapError)? as u16;
451 
452         let (avail_features, acked_features, config, queue_sizes, paused) =
453             if let Some(state) = state {
454                 info!("Restoring virtio-net {}", id);
455                 (
456                     state.avail_features,
457                     state.acked_features,
458                     state.config,
459                     state.queue_size,
460                     true,
461                 )
462             } else {
463                 let mut avail_features =
464                     1 << VIRTIO_NET_F_MTU | 1 << VIRTIO_RING_F_EVENT_IDX | 1 << VIRTIO_F_VERSION_1;
465 
466                 if iommu {
467                     avail_features |= 1u64 << VIRTIO_F_IOMMU_PLATFORM;
468                 }
469 
470                 // Configure TSO/UFO features when hardware checksum offload is enabled.
471                 if offload_csum {
472                     avail_features |= 1 << VIRTIO_NET_F_CSUM
473                         | 1 << VIRTIO_NET_F_GUEST_CSUM
474                         | 1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS;
475 
476                     if offload_tso {
477                         avail_features |= 1 << VIRTIO_NET_F_HOST_ECN
478                             | 1 << VIRTIO_NET_F_HOST_TSO4
479                             | 1 << VIRTIO_NET_F_HOST_TSO6
480                             | 1 << VIRTIO_NET_F_GUEST_ECN
481                             | 1 << VIRTIO_NET_F_GUEST_TSO4
482                             | 1 << VIRTIO_NET_F_GUEST_TSO6;
483                     }
484 
485                     if offload_ufo {
486                         avail_features |= 1 << VIRTIO_NET_F_HOST_UFO | 1 << VIRTIO_NET_F_GUEST_UFO;
487                     }
488                 }
489 
490                 avail_features |= 1 << VIRTIO_NET_F_CTRL_VQ;
491                 let queue_num = num_queues + 1;
492 
493                 let mut config = VirtioNetConfig::default();
494                 if let Some(mac) = guest_mac {
495                     build_net_config_space(
496                         &mut config,
497                         mac,
498                         num_queues,
499                         Some(mtu),
500                         &mut avail_features,
501                     );
502                 } else {
503                     build_net_config_space_with_mq(
504                         &mut config,
505                         num_queues,
506                         Some(mtu),
507                         &mut avail_features,
508                     );
509                 }
510 
511                 (
512                     avail_features,
513                     0,
514                     config,
515                     vec![queue_size; queue_num],
516                     false,
517                 )
518             };
519 
520         Ok(Net {
521             common: VirtioCommon {
522                 device_type: VirtioDeviceType::Net as u32,
523                 avail_features,
524                 acked_features,
525                 queue_sizes,
526                 paused_sync: Some(Arc::new(Barrier::new((num_queues / 2) + 1))),
527                 min_queues: 2,
528                 paused: Arc::new(AtomicBool::new(paused)),
529                 ..Default::default()
530             },
531             id,
532             taps,
533             config,
534             ctrl_queue_epoll_thread: None,
535             counters: NetCounters::default(),
536             seccomp_action,
537             rate_limiter_config,
538             exit_evt,
539         })
540     }
541 
542     /// Create a new virtio network device with the given IP address and
543     /// netmask.
544     #[allow(clippy::too_many_arguments)]
545     pub fn new(
546         id: String,
547         if_name: Option<&str>,
548         ip_addr: Option<Ipv4Addr>,
549         netmask: Option<Ipv4Addr>,
550         guest_mac: Option<MacAddr>,
551         host_mac: &mut Option<MacAddr>,
552         mtu: Option<u16>,
553         iommu: bool,
554         num_queues: usize,
555         queue_size: u16,
556         seccomp_action: SeccompAction,
557         rate_limiter_config: Option<RateLimiterConfig>,
558         exit_evt: EventFd,
559         state: Option<NetState>,
560         offload_tso: bool,
561         offload_ufo: bool,
562         offload_csum: bool,
563     ) -> Result<Self> {
564         let taps = open_tap(
565             if_name,
566             ip_addr,
567             netmask,
568             host_mac,
569             mtu,
570             num_queues / 2,
571             None,
572         )
573         .map_err(Error::OpenTap)?;
574 
575         Self::new_with_tap(
576             id,
577             taps,
578             guest_mac,
579             iommu,
580             num_queues,
581             queue_size,
582             seccomp_action,
583             rate_limiter_config,
584             exit_evt,
585             state,
586             offload_tso,
587             offload_ufo,
588             offload_csum,
589         )
590     }
591 
592     #[allow(clippy::too_many_arguments)]
593     pub fn from_tap_fds(
594         id: String,
595         fds: &[RawFd],
596         guest_mac: Option<MacAddr>,
597         mtu: Option<u16>,
598         iommu: bool,
599         queue_size: u16,
600         seccomp_action: SeccompAction,
601         rate_limiter_config: Option<RateLimiterConfig>,
602         exit_evt: EventFd,
603         state: Option<NetState>,
604         offload_tso: bool,
605         offload_ufo: bool,
606         offload_csum: bool,
607     ) -> Result<Self> {
608         let mut taps: Vec<Tap> = Vec::new();
609         let num_queue_pairs = fds.len();
610 
611         for fd in fds.iter() {
612             // Duplicate so that it can survive reboots
613             // SAFETY: FFI call to dup. Trivially safe.
614             let fd = unsafe { libc::dup(*fd) };
615             if fd < 0 {
616                 return Err(Error::DuplicateTapFd(std::io::Error::last_os_error()));
617             }
618             let tap = Tap::from_tap_fd(fd, num_queue_pairs).map_err(Error::TapError)?;
619             taps.push(tap);
620         }
621 
622         assert!(!taps.is_empty());
623 
624         if let Some(mtu) = mtu {
625             taps[0].set_mtu(mtu as i32).map_err(Error::TapError)?;
626         }
627 
628         Self::new_with_tap(
629             id,
630             taps,
631             guest_mac,
632             iommu,
633             num_queue_pairs * 2,
634             queue_size,
635             seccomp_action,
636             rate_limiter_config,
637             exit_evt,
638             state,
639             offload_tso,
640             offload_ufo,
641             offload_csum,
642         )
643     }
644 
645     fn state(&self) -> NetState {
646         NetState {
647             avail_features: self.common.avail_features,
648             acked_features: self.common.acked_features,
649             config: self.config,
650             queue_size: self.common.queue_sizes.clone(),
651         }
652     }
653 
654     #[cfg(fuzzing)]
655     pub fn wait_for_epoll_threads(&mut self) {
656         self.common.wait_for_epoll_threads();
657     }
658 }
659 
660 impl Drop for Net {
661     fn drop(&mut self) {
662         if let Some(kill_evt) = self.common.kill_evt.take() {
663             // Ignore the result because there is nothing we can do about it.
664             let _ = kill_evt.write(1);
665         }
666         // Needed to ensure all references to tap FDs are dropped (#4868)
667         self.common.wait_for_epoll_threads();
668         if let Some(thread) = self.ctrl_queue_epoll_thread.take() {
669             if let Err(e) = thread.join() {
670                 error!("Error joining thread: {:?}", e);
671             }
672         }
673     }
674 }
675 
676 impl VirtioDevice for Net {
677     fn device_type(&self) -> u32 {
678         self.common.device_type
679     }
680 
681     fn queue_max_sizes(&self) -> &[u16] {
682         &self.common.queue_sizes
683     }
684 
685     fn features(&self) -> u64 {
686         self.common.avail_features
687     }
688 
689     fn ack_features(&mut self, value: u64) {
690         self.common.ack_features(value)
691     }
692 
693     fn read_config(&self, offset: u64, data: &mut [u8]) {
694         self.read_config_from_slice(self.config.as_slice(), offset, data);
695     }
696 
697     fn activate(
698         &mut self,
699         mem: GuestMemoryAtomic<GuestMemoryMmap>,
700         interrupt_cb: Arc<dyn VirtioInterrupt>,
701         mut queues: Vec<(usize, Queue, EventFd)>,
702     ) -> ActivateResult {
703         self.common.activate(&queues, &interrupt_cb)?;
704 
705         let num_queues = queues.len();
706         let event_idx = self.common.feature_acked(VIRTIO_RING_F_EVENT_IDX.into());
707         if self.common.feature_acked(VIRTIO_NET_F_CTRL_VQ.into()) && num_queues % 2 != 0 {
708             let ctrl_queue_index = num_queues - 1;
709             let (_, mut ctrl_queue, ctrl_queue_evt) = queues.remove(ctrl_queue_index);
710 
711             ctrl_queue.set_event_idx(event_idx);
712 
713             let (kill_evt, pause_evt) = self.common.dup_eventfds();
714             let mut ctrl_handler = NetCtrlEpollHandler {
715                 mem: mem.clone(),
716                 kill_evt,
717                 pause_evt,
718                 ctrl_q: CtrlQueue::new(self.taps.clone()),
719                 queue: ctrl_queue,
720                 queue_evt: ctrl_queue_evt,
721                 access_platform: self.common.access_platform.clone(),
722                 queue_index: ctrl_queue_index as u16,
723                 interrupt_cb: interrupt_cb.clone(),
724             };
725 
726             let paused = self.common.paused.clone();
727             // Let's update the barrier as we need 1 for each RX/TX pair +
728             // 1 for the control queue + 1 for the main thread signalling
729             // the pause.
730             self.common.paused_sync = Some(Arc::new(Barrier::new(self.taps.len() + 2)));
731             let paused_sync = self.common.paused_sync.clone();
732 
733             let mut epoll_threads = Vec::new();
734             spawn_virtio_thread(
735                 &format!("{}_ctrl", &self.id),
736                 &self.seccomp_action,
737                 Thread::VirtioNetCtl,
738                 &mut epoll_threads,
739                 &self.exit_evt,
740                 move || ctrl_handler.run_ctrl(paused, paused_sync.unwrap()),
741             )?;
742             self.ctrl_queue_epoll_thread = Some(epoll_threads.remove(0));
743         }
744 
745         let mut epoll_threads = Vec::new();
746         let mut taps = self.taps.clone();
747         for i in 0..queues.len() / 2 {
748             let rx = RxVirtio::new();
749             let tx = TxVirtio::new();
750             let rx_tap_listening = false;
751 
752             let (_, queue_0, queue_evt_0) = queues.remove(0);
753             let (_, queue_1, queue_evt_1) = queues.remove(0);
754             let mut queue_pair = (queue_0, queue_1);
755             queue_pair.0.set_event_idx(event_idx);
756             queue_pair.1.set_event_idx(event_idx);
757 
758             let queue_evt_pair = (queue_evt_0, queue_evt_1);
759 
760             let (kill_evt, pause_evt) = self.common.dup_eventfds();
761 
762             let rx_rate_limiter: Option<rate_limiter::RateLimiter> = self
763                 .rate_limiter_config
764                 .map(RateLimiterConfig::try_into)
765                 .transpose()
766                 .map_err(ActivateError::CreateRateLimiter)?;
767 
768             let tx_rate_limiter: Option<rate_limiter::RateLimiter> = self
769                 .rate_limiter_config
770                 .map(RateLimiterConfig::try_into)
771                 .transpose()
772                 .map_err(ActivateError::CreateRateLimiter)?;
773 
774             let tap = taps.remove(0);
775             #[cfg(not(fuzzing))]
776             tap.set_offload(virtio_features_to_tap_offload(self.common.acked_features))
777                 .map_err(|e| {
778                     error!("Error programming tap offload: {:?}", e);
779                     ActivateError::BadActivate
780                 })?;
781 
782             let mut handler = NetEpollHandler {
783                 net: NetQueuePair {
784                     tap_for_write_epoll: tap.clone(),
785                     tap,
786                     rx,
787                     tx,
788                     epoll_fd: None,
789                     rx_tap_listening,
790                     tx_tap_listening: false,
791                     counters: self.counters.clone(),
792                     tap_rx_event_id: RX_TAP_EVENT,
793                     tap_tx_event_id: TX_TAP_EVENT,
794                     rx_desc_avail: false,
795                     rx_rate_limiter,
796                     tx_rate_limiter,
797                     access_platform: self.common.access_platform.clone(),
798                 },
799                 mem: mem.clone(),
800                 queue_index_base: (i * 2) as u16,
801                 queue_pair,
802                 queue_evt_pair,
803                 interrupt_cb: interrupt_cb.clone(),
804                 kill_evt,
805                 pause_evt,
806                 driver_awake: false,
807             };
808 
809             let paused = self.common.paused.clone();
810             let paused_sync = self.common.paused_sync.clone();
811 
812             spawn_virtio_thread(
813                 &format!("{}_qp{}", self.id.clone(), i),
814                 &self.seccomp_action,
815                 Thread::VirtioNet,
816                 &mut epoll_threads,
817                 &self.exit_evt,
818                 move || handler.run(paused, paused_sync.unwrap()),
819             )?;
820         }
821 
822         self.common.epoll_threads = Some(epoll_threads);
823 
824         event!("virtio-device", "activated", "id", &self.id);
825         Ok(())
826     }
827 
828     fn reset(&mut self) -> Option<Arc<dyn VirtioInterrupt>> {
829         let result = self.common.reset();
830         event!("virtio-device", "reset", "id", &self.id);
831         result
832     }
833 
834     fn counters(&self) -> Option<HashMap<&'static str, Wrapping<u64>>> {
835         let mut counters = HashMap::new();
836 
837         counters.insert(
838             "rx_bytes",
839             Wrapping(self.counters.rx_bytes.load(Ordering::Acquire)),
840         );
841         counters.insert(
842             "rx_frames",
843             Wrapping(self.counters.rx_frames.load(Ordering::Acquire)),
844         );
845         counters.insert(
846             "tx_bytes",
847             Wrapping(self.counters.tx_bytes.load(Ordering::Acquire)),
848         );
849         counters.insert(
850             "tx_frames",
851             Wrapping(self.counters.tx_frames.load(Ordering::Acquire)),
852         );
853 
854         Some(counters)
855     }
856 
857     fn set_access_platform(&mut self, access_platform: Arc<dyn AccessPlatform>) {
858         self.common.set_access_platform(access_platform)
859     }
860 }
861 
862 impl Pausable for Net {
863     fn pause(&mut self) -> result::Result<(), MigratableError> {
864         self.common.pause()
865     }
866 
867     fn resume(&mut self) -> result::Result<(), MigratableError> {
868         self.common.resume()?;
869 
870         if let Some(ctrl_queue_epoll_thread) = &self.ctrl_queue_epoll_thread {
871             ctrl_queue_epoll_thread.thread().unpark();
872         }
873         Ok(())
874     }
875 }
876 
877 impl Snapshottable for Net {
878     fn id(&self) -> String {
879         self.id.clone()
880     }
881 
882     fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
883         Snapshot::new_from_state(&self.state())
884     }
885 }
886 impl Transportable for Net {}
887 impl Migratable for Net {}
888