From bcb1dfb86f8e5b4aa9c55b85cf69d949d6de4118 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Fri, 21 May 2021 12:52:07 +0200 Subject: [PATCH] virtio-devices: net: Rely on net_util crate for control queue Since the net_util crate contains the common code needed for processing the control queue, let's use it and remove the duplicate from inside the virtio-devices crate. Signed-off-by: Sebastien Boeuf --- virtio-devices/src/net.rs | 7 +- virtio-devices/src/net_util.rs | 138 ++------------------------------- 2 files changed, 13 insertions(+), 132 deletions(-) diff --git a/virtio-devices/src/net.rs b/virtio-devices/src/net.rs index 7b532a75e..aac347211 100644 --- a/virtio-devices/src/net.rs +++ b/virtio-devices/src/net.rs @@ -5,7 +5,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the THIRD-PARTY file. -use super::net_util::{NetCtrl, NetCtrlEpollHandler}; +use super::net_util::NetCtrlEpollHandler; use super::Error as DeviceError; use super::{ ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue, @@ -14,6 +14,7 @@ use super::{ }; use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::VirtioInterrupt; +use net_util::CtrlQueue; use net_util::{ build_net_config_space, build_net_config_space_with_mq, open_tap, virtio_features_to_tap_offload, MacAddr, NetCounters, NetQueuePair, OpenTapError, RxVirtio, @@ -516,7 +517,9 @@ impl VirtioDevice for Net { mem: mem.clone(), kill_evt, pause_evt, - ctrl_q: NetCtrl::new(cvq_queue, cvq_queue_evt, Some(self.taps.clone())), + ctrl_q: CtrlQueue::new(self.taps.clone()), + queue: cvq_queue, + queue_evt: cvq_queue_evt, }; let paused = self.common.paused.clone(); diff --git a/virtio-devices/src/net_util.rs b/virtio-devices/src/net_util.rs index 31a512cda..a7a1e02d2 100644 --- a/virtio-devices/src/net_util.rs +++ b/virtio-devices/src/net_util.rs @@ -3,145 +3,23 @@ // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause use super::{EpollHelper, EpollHelperError, EpollHelperHandler, Queue, EPOLL_HELPER_EVENT_LAST}; -use net_util::virtio_features_to_tap_offload; -use net_util::Tap; +use net_util::CtrlQueue; use std::os::unix::io::AsRawFd; use std::sync::atomic::AtomicBool; use std::sync::{Arc, Barrier}; -use virtio_bindings::bindings::virtio_net::{ - VIRTIO_NET_CTRL_GUEST_OFFLOADS, VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET, VIRTIO_NET_CTRL_MQ, - VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN, - VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, VIRTIO_NET_ERR, VIRTIO_NET_OK, -}; -use vm_memory::{ - ByteValued, Bytes, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryError, GuestMemoryMmap, -}; +use vm_memory::{GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap}; use vmm_sys_util::eventfd::EventFd; -type Result = std::result::Result; - -const QUEUE_SIZE: usize = 256; - // Event available on the control queue. const CTRL_QUEUE_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1; -#[derive(Debug)] -pub enum Error { - /// Read queue failed. - GuestMemory(GuestMemoryError), - /// No queue pairs number. - NoQueuePairsDescriptor, - /// No status descriptor - NoStatusDescriptor, -} - -pub struct NetCtrl { - pub queue_evt: EventFd, - pub queue: Queue, - pub taps: Option>, -} - -#[repr(C, packed)] -#[derive(Debug, Clone, Copy, Default)] -pub struct ControlHeader { - pub class: u8, - pub cmd: u8, -} - -unsafe impl ByteValued for ControlHeader {} - -impl NetCtrl { - pub fn new(queue: Queue, queue_evt: EventFd, taps: Option>) -> Self { - NetCtrl { - queue_evt, - queue, - taps, - } - } - - pub fn process_cvq(&mut self, mem: &GuestMemoryMmap) -> Result<()> { - let mut used_desc_heads = [(0, 0); QUEUE_SIZE]; - let mut used_count = 0; - let queue = &mut self.queue; - for avail_desc in queue.iter(&mem) { - let ctrl_hdr: ControlHeader = - mem.read_obj(avail_desc.addr).map_err(Error::GuestMemory)?; - let data_desc = avail_desc - .next_descriptor() - .ok_or(Error::NoQueuePairsDescriptor)?; - let status_desc = data_desc - .next_descriptor() - .ok_or(Error::NoStatusDescriptor)?; - - let ok = match u32::from(ctrl_hdr.class) { - VIRTIO_NET_CTRL_MQ => { - let queue_pairs = mem - .read_obj::(data_desc.addr) - .map_err(Error::GuestMemory)?; - if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET { - warn!("Unsupported command: {}", ctrl_hdr.cmd); - false - } else if (queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN as u16) - || (queue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX as u16) - { - warn!("Number of MQ pairs out of range: {}", queue_pairs); - false - } else { - info!("Number of MQ pairs requested: {}", queue_pairs); - true - } - } - VIRTIO_NET_CTRL_GUEST_OFFLOADS => { - let features = mem - .read_obj::(data_desc.addr) - .map_err(Error::GuestMemory)?; - if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET { - warn!("Unsupported command: {}", ctrl_hdr.cmd); - false - } else { - let mut ok = true; - if let Some(ref mut taps) = &mut self.taps { - for tap in taps.iter_mut() { - info!("Reprogramming tap offload with features: {}", features); - tap.set_offload(virtio_features_to_tap_offload(features)) - .map_err(|e| { - error!("Error programming tap offload: {:?}", e); - ok = false - }) - .ok(); - } - } - ok - } - } - _ => { - warn!("Unsupported command {:?}", ctrl_hdr); - false - } - }; - - mem.write_obj( - if ok { VIRTIO_NET_OK } else { VIRTIO_NET_ERR } as u8, - status_desc.addr, - ) - .map_err(Error::GuestMemory)?; - used_desc_heads[used_count] = (avail_desc.index, avail_desc.len); - used_count += 1; - } - for &(desc_index, len) in &used_desc_heads[..used_count] { - self.queue.add_used(&mem, desc_index, len); - self.queue.update_avail_event(&mem); - } - - Ok(()) - } -} - pub struct NetCtrlEpollHandler { pub mem: GuestMemoryAtomic, pub kill_evt: EventFd, pub pause_evt: EventFd, - pub ctrl_q: NetCtrl, + pub ctrl_q: CtrlQueue, + pub queue_evt: EventFd, + pub queue: Queue, } impl NetCtrlEpollHandler { @@ -151,7 +29,7 @@ impl NetCtrlEpollHandler { paused_sync: Arc, ) -> std::result::Result<(), EpollHelperError> { let mut helper = EpollHelper::new(&self.kill_evt, &self.pause_evt)?; - helper.add_event(self.ctrl_q.queue_evt.as_raw_fd(), CTRL_QUEUE_EVENT)?; + helper.add_event(self.queue_evt.as_raw_fd(), CTRL_QUEUE_EVENT)?; helper.run(paused, paused_sync, self)?; Ok(()) @@ -164,11 +42,11 @@ impl EpollHelperHandler for NetCtrlEpollHandler { match ev_type { CTRL_QUEUE_EVENT => { let mem = self.mem.memory(); - if let Err(e) = self.ctrl_q.queue_evt.read() { + if let Err(e) = self.queue_evt.read() { error!("failed to get ctl queue event: {:?}", e); return true; } - if let Err(e) = self.ctrl_q.process_cvq(&mem) { + if let Err(e) = self.ctrl_q.process(&mem, &mut self.queue) { error!("failed to process ctrl queue: {:?}", e); return true; }