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 <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2021-05-21 12:25:18 +02:00
parent f36b5f3e3c
commit d7a69f8aa1
6 changed files with 85 additions and 74 deletions

2
Cargo.lock generated
View File

@ -580,6 +580,8 @@ dependencies = [
"rate_limiter",
"serde",
"serde_json",
"versionize",
"versionize_derive",
"virtio-bindings",
"vm-memory",
"vm-virtio",

View File

@ -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" }

View File

@ -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<T> = std::result::Result<T, Error>;
#[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<net::UdpSocket> {
}
fn vnet_hdr_len() -> usize {
use virtio_bindings::bindings::virtio_net::virtio_net_hdr_v1;
std::mem::size_of::<virtio_net_hdr_v1>()
}
@ -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::*;

View File

@ -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;

View File

@ -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
}

View File

@ -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;