mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-03 11:25:20 +00:00
virtio-devices: net: Add support for VIRTIO_NET_F_CTRL_GUEST_OFFLOADS
This allows the guest to reprogram the offload settings and mitigates issues where the Linux kernel tries to reprogram the queues even when the feature is not advertised. Fixes: #2528 Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
9ef1a68539
commit
51a93bc635
@ -315,6 +315,7 @@ impl Net {
|
|||||||
rate_limiter_config: Option<RateLimiterConfig>,
|
rate_limiter_config: Option<RateLimiterConfig>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let mut avail_features = 1 << VIRTIO_NET_F_CSUM
|
let mut avail_features = 1 << VIRTIO_NET_F_CSUM
|
||||||
|
| 1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS
|
||||||
| 1 << VIRTIO_NET_F_GUEST_CSUM
|
| 1 << VIRTIO_NET_F_GUEST_CSUM
|
||||||
| 1 << VIRTIO_NET_F_GUEST_ECN
|
| 1 << VIRTIO_NET_F_GUEST_ECN
|
||||||
| 1 << VIRTIO_NET_F_GUEST_TSO4
|
| 1 << VIRTIO_NET_F_GUEST_TSO4
|
||||||
@ -511,7 +512,7 @@ impl VirtioDevice for Net {
|
|||||||
mem: mem.clone(),
|
mem: mem.clone(),
|
||||||
kill_evt,
|
kill_evt,
|
||||||
pause_evt,
|
pause_evt,
|
||||||
ctrl_q: NetCtrl::new(cvq_queue, cvq_queue_evt),
|
ctrl_q: NetCtrl::new(cvq_queue, cvq_queue_evt, Some(self.taps.clone())),
|
||||||
};
|
};
|
||||||
|
|
||||||
let paused = self.common.paused.clone();
|
let paused = self.common.paused.clone();
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
use super::{EpollHelper, EpollHelperError, EpollHelperHandler, Queue, EPOLL_HELPER_EVENT_LAST};
|
use super::{EpollHelper, EpollHelperError, EpollHelperHandler, Queue, EPOLL_HELPER_EVENT_LAST};
|
||||||
use net_util::MacAddr;
|
use net_util::MacAddr;
|
||||||
|
use net_util::Tap;
|
||||||
use std::os::raw::c_uint;
|
use std::os::raw::c_uint;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
@ -48,6 +49,7 @@ pub enum Error {
|
|||||||
pub struct NetCtrl {
|
pub struct NetCtrl {
|
||||||
pub queue_evt: EventFd,
|
pub queue_evt: EventFd,
|
||||||
pub queue: Queue,
|
pub queue: Queue,
|
||||||
|
pub taps: Option<Vec<Tap>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
@ -60,8 +62,12 @@ pub struct ControlHeader {
|
|||||||
unsafe impl ByteValued for ControlHeader {}
|
unsafe impl ByteValued for ControlHeader {}
|
||||||
|
|
||||||
impl NetCtrl {
|
impl NetCtrl {
|
||||||
pub fn new(queue: Queue, queue_evt: EventFd) -> Self {
|
pub fn new(queue: Queue, queue_evt: EventFd, taps: Option<Vec<Tap>>) -> Self {
|
||||||
NetCtrl { queue_evt, queue }
|
NetCtrl {
|
||||||
|
queue_evt,
|
||||||
|
queue,
|
||||||
|
taps,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_cvq(&mut self, mem: &GuestMemoryMmap) -> Result<()> {
|
pub fn process_cvq(&mut self, mem: &GuestMemoryMmap) -> Result<()> {
|
||||||
@ -96,6 +102,29 @@ impl NetCtrl {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
VIRTIO_NET_CTRL_GUEST_OFFLOADS => {
|
||||||
|
let features = mem
|
||||||
|
.read_obj::<u64>(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);
|
warn!("Unsupported command {:?}", ctrl_hdr);
|
||||||
false
|
false
|
||||||
|
@ -59,6 +59,9 @@ const FIONBIO: u64 = 0x5421;
|
|||||||
const VFIO_IOMMU_MAP_DMA: u64 = 0x3b71;
|
const VFIO_IOMMU_MAP_DMA: u64 = 0x3b71;
|
||||||
const VFIO_IOMMU_UNMAP_DMA: u64 = 0x3b72;
|
const VFIO_IOMMU_UNMAP_DMA: u64 = 0x3b72;
|
||||||
|
|
||||||
|
// See include/uapi/linux/if_tun.h in the kernel code.
|
||||||
|
const TUNSETOFFLOAD: u64 = 0x4004_54d0;
|
||||||
|
|
||||||
fn create_virtio_iommu_ioctl_seccomp_rule() -> Vec<SeccompRule> {
|
fn create_virtio_iommu_ioctl_seccomp_rule() -> Vec<SeccompRule> {
|
||||||
or![
|
or![
|
||||||
and![Cond::new(1, ArgLen::DWORD, Eq, VFIO_IOMMU_MAP_DMA).unwrap()],
|
and![Cond::new(1, ArgLen::DWORD, Eq, VFIO_IOMMU_MAP_DMA).unwrap()],
|
||||||
@ -234,8 +237,12 @@ fn virtio_net_thread_rules() -> Vec<SyscallRuleSet> {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn virtio_net_ctl_thread_rules() -> Vec<SyscallRuleSet> {
|
fn create_virtio_net_ctl_ioctl_seccomp_rule() -> Result<Vec<SeccompRule>, Error> {
|
||||||
vec![
|
Ok(or![and![Cond::new(1, ArgLen::DWORD, Eq, TUNSETOFFLOAD)?],])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn virtio_net_ctl_thread_rules() -> Result<Vec<SyscallRuleSet>, Error> {
|
||||||
|
Ok(vec![
|
||||||
allow_syscall(libc::SYS_brk),
|
allow_syscall(libc::SYS_brk),
|
||||||
allow_syscall(libc::SYS_close),
|
allow_syscall(libc::SYS_close),
|
||||||
allow_syscall(libc::SYS_dup),
|
allow_syscall(libc::SYS_dup),
|
||||||
@ -246,13 +253,14 @@ fn virtio_net_ctl_thread_rules() -> Vec<SyscallRuleSet> {
|
|||||||
allow_syscall(libc::SYS_epoll_wait),
|
allow_syscall(libc::SYS_epoll_wait),
|
||||||
allow_syscall(libc::SYS_exit),
|
allow_syscall(libc::SYS_exit),
|
||||||
allow_syscall(libc::SYS_futex),
|
allow_syscall(libc::SYS_futex),
|
||||||
|
allow_syscall_if(libc::SYS_ioctl, create_virtio_net_ctl_ioctl_seccomp_rule()?),
|
||||||
allow_syscall(libc::SYS_madvise),
|
allow_syscall(libc::SYS_madvise),
|
||||||
allow_syscall(libc::SYS_munmap),
|
allow_syscall(libc::SYS_munmap),
|
||||||
allow_syscall(libc::SYS_read),
|
allow_syscall(libc::SYS_read),
|
||||||
allow_syscall(libc::SYS_rt_sigprocmask),
|
allow_syscall(libc::SYS_rt_sigprocmask),
|
||||||
allow_syscall(libc::SYS_sigaltstack),
|
allow_syscall(libc::SYS_sigaltstack),
|
||||||
allow_syscall(libc::SYS_write),
|
allow_syscall(libc::SYS_write),
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn virtio_pmem_thread_rules() -> Vec<SyscallRuleSet> {
|
fn virtio_pmem_thread_rules() -> Vec<SyscallRuleSet> {
|
||||||
@ -451,7 +459,7 @@ fn get_seccomp_filter_trap(thread_type: Thread) -> Result<SeccompFilter, Error>
|
|||||||
Thread::VirtioIommu => virtio_iommu_thread_rules(),
|
Thread::VirtioIommu => virtio_iommu_thread_rules(),
|
||||||
Thread::VirtioMem => virtio_mem_thread_rules(),
|
Thread::VirtioMem => virtio_mem_thread_rules(),
|
||||||
Thread::VirtioNet => virtio_net_thread_rules(),
|
Thread::VirtioNet => virtio_net_thread_rules(),
|
||||||
Thread::VirtioNetCtl => virtio_net_ctl_thread_rules(),
|
Thread::VirtioNetCtl => virtio_net_ctl_thread_rules()?,
|
||||||
Thread::VirtioPmem => virtio_pmem_thread_rules(),
|
Thread::VirtioPmem => virtio_pmem_thread_rules(),
|
||||||
Thread::VirtioRng => virtio_rng_thread_rules(),
|
Thread::VirtioRng => virtio_rng_thread_rules(),
|
||||||
Thread::VirtioVhostBlk => virtio_vhost_blk_thread_rules(),
|
Thread::VirtioVhostBlk => virtio_vhost_blk_thread_rules(),
|
||||||
@ -473,7 +481,7 @@ fn get_seccomp_filter_log(thread_type: Thread) -> Result<SeccompFilter, Error> {
|
|||||||
Thread::VirtioIommu => virtio_iommu_thread_rules(),
|
Thread::VirtioIommu => virtio_iommu_thread_rules(),
|
||||||
Thread::VirtioMem => virtio_mem_thread_rules(),
|
Thread::VirtioMem => virtio_mem_thread_rules(),
|
||||||
Thread::VirtioNet => virtio_net_thread_rules(),
|
Thread::VirtioNet => virtio_net_thread_rules(),
|
||||||
Thread::VirtioNetCtl => virtio_net_ctl_thread_rules(),
|
Thread::VirtioNetCtl => virtio_net_ctl_thread_rules()?,
|
||||||
Thread::VirtioPmem => virtio_pmem_thread_rules(),
|
Thread::VirtioPmem => virtio_pmem_thread_rules(),
|
||||||
Thread::VirtioRng => virtio_rng_thread_rules(),
|
Thread::VirtioRng => virtio_rng_thread_rules(),
|
||||||
Thread::VirtioVhostBlk => virtio_vhost_blk_thread_rules(),
|
Thread::VirtioVhostBlk => virtio_vhost_blk_thread_rules(),
|
||||||
|
@ -247,7 +247,7 @@ impl VirtioDevice for Net {
|
|||||||
mem: mem.clone(),
|
mem: mem.clone(),
|
||||||
kill_evt,
|
kill_evt,
|
||||||
pause_evt,
|
pause_evt,
|
||||||
ctrl_q: NetCtrl::new(cvq_queue, cvq_queue_evt),
|
ctrl_q: NetCtrl::new(cvq_queue, cvq_queue_evt, None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let paused = self.common.paused.clone();
|
let paused = self.common.paused.clone();
|
||||||
|
Loading…
Reference in New Issue
Block a user