From d7a69f8aa122c693899912bcb58e998e79eaca05 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Fri, 21 May 2021 12:25:18 +0200 Subject: [PATCH] net_util: Move virtio-net helpers to net_util crate Moving helpers to the net_util crate since we don't want virtio-net common code to be split between two places. The net_util crate should be the only place to host virtio-net common code. Signed-off-by: Sebastien Boeuf --- Cargo.lock | 2 + net_util/Cargo.toml | 2 + net_util/src/lib.rs | 71 ++++++++++++++++++++++++++- virtio-devices/src/net.rs | 9 ++-- virtio-devices/src/net_util.rs | 72 +++------------------------- virtio-devices/src/vhost_user/net.rs | 3 +- 6 files changed, 85 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d5197a0e..9fef4faf1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -580,6 +580,8 @@ dependencies = [ "rate_limiter", "serde", "serde_json", + "versionize", + "versionize_derive", "virtio-bindings", "vm-memory", "vm-virtio", diff --git a/net_util/Cargo.toml b/net_util/Cargo.toml index 5cebd9c17..a894cbd1a 100644 --- a/net_util/Cargo.toml +++ b/net_util/Cargo.toml @@ -11,6 +11,8 @@ log = "0.4.14" net_gen = { path = "../net_gen" } rate_limiter = { path = "../rate_limiter" } serde = "1.0.126" +versionize = "0.1.6" +versionize_derive = "0.1.4" virtio-bindings = "0.1.0" vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-atomic"] } vm-virtio = { path = "../vm-virtio" } diff --git a/net_util/src/lib.rs b/net_util/src/lib.rs index 99e34e667..f77acd678 100644 --- a/net_util/src/lib.rs +++ b/net_util/src/lib.rs @@ -20,8 +20,17 @@ mod queue_pair; mod tap; use std::io::Error as IoError; +use std::os::raw::c_uint; use std::os::unix::io::{FromRawFd, RawFd}; use std::{io, mem, net}; +use versionize::{VersionMap, Versionize, VersionizeResult}; +use versionize_derive::Versionize; +use virtio_bindings::bindings::virtio_net::{ + virtio_net_hdr_v1, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN, + VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_TSO4, + VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_UFO, VIRTIO_NET_F_MAC, VIRTIO_NET_F_MQ, +}; +use vm_memory::ByteValued; pub use ctrl_queue::{CtrlQueue, Error as CtrlQueueError}; pub use mac::{MacAddr, MAC_ADDR_LEN}; @@ -37,6 +46,20 @@ pub enum Error { pub type Result = std::result::Result; +#[repr(C, packed)] +#[derive(Copy, Clone, Debug, Default, Versionize)] +pub struct VirtioNetConfig { + pub mac: [u8; 6], + pub status: u16, + pub max_virtqueue_pairs: u16, + pub mtu: u16, + pub speed: u32, + pub duplex: u8, +} + +// Safe because it only has data and has no implicit padding. +unsafe impl ByteValued for VirtioNetConfig {} + /// Create a sockaddr_in from an IPv4 address, and expose it as /// an opaque sockaddr suitable for usage by socket ioctls. fn create_sockaddr(ip_addr: net::Ipv4Addr) -> net_gen::sockaddr { @@ -64,7 +87,6 @@ fn create_socket() -> Result { } fn vnet_hdr_len() -> usize { - use virtio_bindings::bindings::virtio_net::virtio_net_hdr_v1; std::mem::size_of::() } @@ -96,6 +118,53 @@ pub fn unregister_listener( ) } +pub fn build_net_config_space( + mut config: &mut VirtioNetConfig, + mac: MacAddr, + num_queues: usize, + mut avail_features: &mut u64, +) { + config.mac.copy_from_slice(mac.get_bytes()); + *avail_features |= 1 << VIRTIO_NET_F_MAC; + + build_net_config_space_with_mq(&mut config, num_queues, &mut avail_features); +} + +pub fn build_net_config_space_with_mq( + config: &mut VirtioNetConfig, + num_queues: usize, + avail_features: &mut u64, +) { + let num_queue_pairs = (num_queues / 2) as u16; + if (num_queue_pairs >= VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN as u16) + && (num_queue_pairs <= VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX as u16) + { + config.max_virtqueue_pairs = num_queue_pairs; + *avail_features |= 1 << VIRTIO_NET_F_MQ; + } +} + +pub fn virtio_features_to_tap_offload(features: u64) -> c_uint { + let mut tap_offloads: c_uint = 0; + if features & (1 << VIRTIO_NET_F_GUEST_CSUM) != 0 { + tap_offloads |= net_gen::TUN_F_CSUM; + } + if features & (1 << VIRTIO_NET_F_GUEST_TSO4) != 0 { + tap_offloads |= net_gen::TUN_F_TSO4; + } + if features & (1 << VIRTIO_NET_F_GUEST_TSO6) != 0 { + tap_offloads |= net_gen::TUN_F_TSO6; + } + if features & (1 << VIRTIO_NET_F_GUEST_ECN) != 0 { + tap_offloads |= net_gen::TUN_F_TSO_ECN; + } + if features & (1 << VIRTIO_NET_F_GUEST_UFO) != 0 { + tap_offloads |= net_gen::TUN_F_UFO; + } + + tap_offloads +} + #[cfg(test)] mod tests { use super::*; diff --git a/virtio-devices/src/net.rs b/virtio-devices/src/net.rs index 1e285a722..7b532a75e 100644 --- a/virtio-devices/src/net.rs +++ b/virtio-devices/src/net.rs @@ -5,10 +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::{ - build_net_config_space, build_net_config_space_with_mq, virtio_features_to_tap_offload, - NetCtrl, NetCtrlEpollHandler, VirtioNetConfig, -}; +use super::net_util::{NetCtrl, NetCtrlEpollHandler}; use super::Error as DeviceError; use super::{ ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue, @@ -18,7 +15,9 @@ use super::{ use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::VirtioInterrupt; use net_util::{ - open_tap, MacAddr, NetCounters, NetQueuePair, OpenTapError, RxVirtio, Tap, TapError, TxVirtio, + build_net_config_space, build_net_config_space_with_mq, open_tap, + virtio_features_to_tap_offload, MacAddr, NetCounters, NetQueuePair, OpenTapError, RxVirtio, + Tap, TapError, TxVirtio, VirtioNetConfig, }; use seccomp::{SeccompAction, SeccompFilter}; use std::net::Ipv4Addr; diff --git a/virtio-devices/src/net_util.rs b/virtio-devices/src/net_util.rs index 89a91422c..31a512cda 100644 --- a/virtio-devices/src/net_util.rs +++ b/virtio-devices/src/net_util.rs @@ -3,15 +3,16 @@ // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause use super::{EpollHelper, EpollHelperError, EpollHelperHandler, Queue, EPOLL_HELPER_EVENT_LAST}; -use net_util::MacAddr; +use net_util::virtio_features_to_tap_offload; use net_util::Tap; -use std::os::raw::c_uint; use std::os::unix::io::AsRawFd; use std::sync::atomic::AtomicBool; use std::sync::{Arc, Barrier}; -use versionize::{VersionMap, Versionize, VersionizeResult}; -use versionize_derive::Versionize; -use virtio_bindings::bindings::virtio_net::*; +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, }; @@ -24,20 +25,6 @@ const QUEUE_SIZE: usize = 256; // Event available on the control queue. const CTRL_QUEUE_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1; -#[repr(C, packed)] -#[derive(Copy, Clone, Debug, Default, Versionize)] -pub struct VirtioNetConfig { - pub mac: [u8; 6], - pub status: u16, - pub max_virtqueue_pairs: u16, - pub mtu: u16, - pub speed: u32, - pub duplex: u8, -} - -// Safe because it only has data and has no implicit padding. -unsafe impl ByteValued for VirtioNetConfig {} - #[derive(Debug)] pub enum Error { /// Read queue failed. @@ -195,50 +182,3 @@ impl EpollHelperHandler for NetCtrlEpollHandler { false } } - -pub fn build_net_config_space( - mut config: &mut VirtioNetConfig, - mac: MacAddr, - num_queues: usize, - mut avail_features: &mut u64, -) { - config.mac.copy_from_slice(mac.get_bytes()); - *avail_features |= 1 << VIRTIO_NET_F_MAC; - - build_net_config_space_with_mq(&mut config, num_queues, &mut avail_features); -} - -pub fn build_net_config_space_with_mq( - config: &mut VirtioNetConfig, - num_queues: usize, - avail_features: &mut u64, -) { - let num_queue_pairs = (num_queues / 2) as u16; - if (num_queue_pairs >= VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN as u16) - && (num_queue_pairs <= VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX as u16) - { - config.max_virtqueue_pairs = num_queue_pairs; - *avail_features |= 1 << VIRTIO_NET_F_MQ; - } -} - -pub fn virtio_features_to_tap_offload(features: u64) -> c_uint { - let mut tap_offloads: c_uint = 0; - if features & (1 << VIRTIO_NET_F_GUEST_CSUM) != 0 { - tap_offloads |= net_gen::TUN_F_CSUM; - } - if features & (1 << VIRTIO_NET_F_GUEST_TSO4) != 0 { - tap_offloads |= net_gen::TUN_F_TSO4; - } - if features & (1 << VIRTIO_NET_F_GUEST_TSO6) != 0 { - tap_offloads |= net_gen::TUN_F_TSO6; - } - if features & (1 << VIRTIO_NET_F_GUEST_ECN) != 0 { - tap_offloads |= net_gen::TUN_F_TSO_ECN; - } - if features & (1 << VIRTIO_NET_F_GUEST_UFO) != 0 { - tap_offloads |= net_gen::TUN_F_UFO; - } - - tap_offloads -} diff --git a/virtio-devices/src/vhost_user/net.rs b/virtio-devices/src/vhost_user/net.rs index 406e5a55d..45f896f2d 100644 --- a/virtio-devices/src/vhost_user/net.rs +++ b/virtio-devices/src/vhost_user/net.rs @@ -1,14 +1,13 @@ // Copyright 2019 Intel Corporation. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -use super::super::net_util::{build_net_config_space, VirtioNetConfig}; use super::super::{ ActivateError, ActivateResult, Queue, VirtioCommon, VirtioDevice, VirtioDeviceType, }; use super::vu_common_ctrl::*; use super::{Error, Result}; use crate::VirtioInterrupt; -use net_util::MacAddr; +use net_util::{build_net_config_space, MacAddr, VirtioNetConfig}; use std::ops::Deref; use std::os::unix::io::AsRawFd; use std::os::unix::net::UnixListener;