mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-22 04:25:21 +00:00
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 <sebastien.boeuf@intel.com>
This commit is contained in:
parent
d7a69f8aa1
commit
bcb1dfb86f
@ -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();
|
||||
|
@ -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<T> = std::result::Result<T, Error>;
|
||||
|
||||
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<Vec<Tap>>,
|
||||
}
|
||||
|
||||
#[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<Vec<Tap>>) -> 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::<u16>(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::<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);
|
||||
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<GuestMemoryMmap>,
|
||||
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<Barrier>,
|
||||
) -> 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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user