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