From f213083386bc43b5183cc9d1baafcc7cac84aae1 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Mon, 26 Apr 2021 16:19:53 +0100 Subject: [PATCH] virtio-devices: net: Set tap offload features based on those negotiated Configure the tap offload features to match those that the guest has acknowledged. The function for converting virtio to tap features came from crosvm: https://chromium.googlesource.com/chromiumos/platform/crosvm/+/4786cee52197ccc99c21d9383cab3016ad0ce84c/devices/src/virtio/net.rs#115 Signed-off-by: Rob Bradford --- virtio-devices/src/net.rs | 13 ++++++++++--- virtio-devices/src/net_util.rs | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/virtio-devices/src/net.rs b/virtio-devices/src/net.rs index b95fd77a4..631826a7d 100644 --- a/virtio-devices/src/net.rs +++ b/virtio-devices/src/net.rs @@ -6,8 +6,8 @@ // found in the THIRD-PARTY file. use super::net_util::{ - build_net_config_space, build_net_config_space_with_mq, CtrlVirtio, NetCtrlEpollHandler, - VirtioNetConfig, + build_net_config_space, build_net_config_space_with_mq, virtio_features_to_tap_offload, + CtrlVirtio, NetCtrlEpollHandler, VirtioNetConfig, }; use super::Error as DeviceError; use super::{ @@ -586,10 +586,17 @@ impl VirtioDevice for Net { .transpose() .map_err(ActivateError::CreateRateLimiter)?; + let tap = taps.remove(0); + tap.set_offload(virtio_features_to_tap_offload(self.common.acked_features)) + .map_err(|e| { + error!("Error programming tap offload: {:?}", e); + ActivateError::BadActivate + })?; + let mut handler = NetEpollHandler { net: NetQueuePair { mem: Some(mem.clone()), - tap: taps.remove(0), + tap, rx, tx, epoll_fd: None, diff --git a/virtio-devices/src/net_util.rs b/virtio-devices/src/net_util.rs index 2ae263737..47716610d 100644 --- a/virtio-devices/src/net_util.rs +++ b/virtio-devices/src/net_util.rs @@ -7,6 +7,7 @@ use super::{ EPOLL_HELPER_EVENT_LAST, }; use net_util::MacAddr; +use std::os::raw::c_uint; use std::os::unix::io::{AsRawFd, RawFd}; use std::sync::atomic::AtomicBool; use std::sync::{Arc, Barrier}; @@ -208,3 +209,24 @@ pub fn build_net_config_space_with_mq( *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 +}