diff options
Diffstat (limited to 'meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/vhu_can.rs')
-rw-r--r-- | meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/vhu_can.rs | 732 |
1 files changed, 0 insertions, 732 deletions
diff --git a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/vhu_can.rs b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/vhu_can.rs deleted file mode 100644 index 6aa12488..00000000 --- a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/vhu_can.rs +++ /dev/null @@ -1,732 +0,0 @@ -// vhost device can -// -// Copyright 2023 VIRTUAL OPEN SYSTEMS SAS. All Rights Reserved. -// Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com> -// -// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause - -use log::{warn, error}; -use std::mem::size_of; -use std::slice::from_raw_parts; -use std::sync::{Arc, RwLock}; -use std::{ - convert, - io::{self, Result as IoResult}, -}; -use std::os::fd::AsRawFd; -use thiserror::Error as ThisError; -use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures}; -use vhost_user_backend::{VhostUserBackendMut, VringRwLock, VringT}; -use virtio_bindings::bindings::virtio_config::{VIRTIO_F_NOTIFY_ON_EMPTY, VIRTIO_F_VERSION_1}; -use virtio_bindings::bindings::virtio_ring::{ - VIRTIO_RING_F_EVENT_IDX, VIRTIO_RING_F_INDIRECT_DESC, -}; -use virtio_queue::{DescriptorChain, QueueOwnedT}; -use vm_memory::{ - ByteValued, Bytes, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryLoadGuard, - GuestMemoryMmap, Le16, Le32, -}; -use vmm_sys_util::epoll::EventSet; -use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK}; -use crate::can::{ - CanController, CAN_EFF_FLAG, CAN_RTR_FLAG, CAN_ERR_FLAG, CAN_SFF_MASK, - CAN_EFF_MASK, VIRTIO_CAN_FLAGS_FD, VIRTIO_CAN_FLAGS_RTR, - VIRTIO_CAN_FLAGS_EXTENDED, VIRTIO_CAN_TX, VIRTIO_CAN_RX, - CAN_FRMF_TYPE_FD, CAN_ERR_BUSOFF, -}; -use vhost_user_backend::VringEpollHandler; - -/// Feature bit numbers -pub const VIRTIO_CAN_F_CAN_CLASSIC: u16 = 0; -pub const VIRTIO_CAN_F_CAN_FD: u16 = 1; -//pub const VIRTIO_CAN_F_LATE_TX_ACK: u16 = 2; -pub const VIRTIO_CAN_F_RTR_FRAMES: u16 = 3; - -/// Possible values of the status field -pub const VIRTIO_CAN_STATUS_OK: u8 = 0x0; -pub const VIRTIO_CAN_STATUS_ERR: u8 = 0x1; - -/// CAN Control messages -const VIRTIO_CAN_SET_CTRL_MODE_START: u16 = 0x0201; -const VIRTIO_CAN_SET_CTRL_MODE_STOP: u16 = 0x0202; - -/// Virtio configuration -const QUEUE_SIZE: usize = 64; -const NUM_QUEUES: usize = 3; - -/// Queues -const TX_QUEUE: u16 = 0; -const RX_QUEUE: u16 = 1; -const CTRL_QUEUE: u16 = 2; -const BACKEND_EFD: u16 = 4; - -type Result<T> = std::result::Result<T, Error>; - -#[derive(Copy, Clone, Debug, PartialEq, ThisError)] -/// Errors related to vhost-device-gpio-daemon. -pub(crate) enum Error { - #[error("Failed to handle event, didn't match EPOLLIN")] - HandleEventNotEpollIn, - #[error("Failed to handle unknown event")] - HandleEventUnknown, - #[error("Received unexpected write only descriptor at index {0}")] - UnexpectedWriteOnlyDescriptor(usize), - #[error("Received unexpected readable descriptor at index {0}")] - UnexpectedReadableDescriptor(usize), - #[error("Invalid descriptor count {0}")] - UnexpectedDescriptorCount(usize), - #[error("Invalid descriptor size, expected: {0}, found: {1}")] - UnexpectedDescriptorSize(usize, u32), - #[error("Descriptor not found")] - DescriptorNotFound, - #[error("Descriptor read failed")] - DescriptorReadFailed, - #[error("Descriptor write failed")] - DescriptorWriteFailed, - #[error("Failed to send notification")] - NotificationFailed, - #[error("Failed to create new EventFd")] - EventFdFailed, - #[error("Unknown can message type: {0}")] - UnexpectedCanMsgType(u16), - #[error("RTR frames not negotiated")] - UnexpectedRtrFlag, - #[error("Can FD frames not negotiated")] - UnexpectedFdFlag, - #[error("Classic CAN frames not negotiated")] - UnexpectedClassicFlag, -} - -impl convert::From<Error> for io::Error { - fn from(e: Error) -> Self { - io::Error::new(io::ErrorKind::Other, e) - } -} - -/// Virtio CAN Request / Response messages -/// -/// The response message is a stream of bytes, where first byte represents the -/// status, and rest is message specific data. - -#[derive(Copy, Clone, Default)] -#[repr(C)] -struct VirtioCanTxResponse { - result: i8, -} -// SAFETY: The layout of the structure is fixed and can be initialized by -// reading its content from byte array. -unsafe impl ByteValued for VirtioCanTxResponse {} - -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct VirtioCanFrame { - pub msg_type: Le16, - pub length: Le16, /* 0..8 CC, 0..64 CANFD, 0..2048 CANXL, 12 bits */ - pub reserved: Le32, /* May be needed in part for CAN XL priority */ - pub flags: Le32, - pub can_id: Le32, - pub sdu: [u8; 64], -} - -impl Default for VirtioCanFrame { - fn default() -> Self { - VirtioCanFrame { - msg_type: Le16::default(), - length: Le16::default(), - reserved: Le32::default(), - flags: Le32::default(), - can_id: Le32::default(), - sdu: [0; 64], // Initialize "asd" with default value (0 in this case) - } - } -} - -// SAFETY: The layout of the structure is fixed and can be initialized by -// reading its content from byte array. -unsafe impl ByteValued for VirtioCanFrame {} - -#[derive(Copy, Clone, Default)] -#[repr(C)] -struct VirtioCanCtrlRequest { - msg_type: Le16, -} -// SAFETY: The layout of the structure is fixed and can be initialized by -// reading its content from byte array. -unsafe impl ByteValued for VirtioCanCtrlRequest {} - -#[derive(Copy, Clone, Default)] -#[repr(C)] -struct VirtioCanCtrlResponse { - result: i8, -} -// SAFETY: The layout of the structure is fixed and can be initialized by -// reading its content from byte array. -unsafe impl ByteValued for VirtioCanCtrlResponse {} - -pub(crate) struct VhostUserCanBackend { - controller: Arc<RwLock<CanController>>, - acked_features: u64, - event_idx: bool, - pub(crate) exit_event: EventFd, - mem: Option<GuestMemoryAtomic<GuestMemoryMmap>>, -} - -type CanDescriptorChain = DescriptorChain<GuestMemoryLoadGuard<GuestMemoryMmap<()>>>; - -impl VhostUserCanBackend { - pub(crate) fn new(controller: Arc<RwLock<CanController>>) -> Result<Self> { - Ok(VhostUserCanBackend { - controller: controller, - event_idx: false, - acked_features: 0x0, - exit_event: EventFd::new(EFD_NONBLOCK).map_err(|_| Error::EventFdFailed)?, - mem: None, - }) - } - - fn check_features (&self, features: u16) -> bool { - (self.acked_features & (1 << features)) != 0 - } - - fn process_ctrl_requests( - &self, - requests: Vec<CanDescriptorChain>, - vring: &VringRwLock - ) -> Result<bool> { - dbg!("process_ctrl_requests"); - - if requests.is_empty() { - return Ok(true); - } - - for desc_chain in requests { - let descriptors: Vec<_> = desc_chain.clone().collect(); - - if descriptors.len() < 1 { - warn!("Error::UnexpectedDescriptorCount"); - return Err(Error::UnexpectedDescriptorCount(descriptors.len())); - } - - println!("descriptors.len(): {:?}", descriptors.len()); - - let desc_request = descriptors[0]; - if desc_request.is_write_only() { - warn!("Error::UnexpectedWriteOnlyDescriptor"); - return Err(Error::UnexpectedWriteOnlyDescriptor(0)); - } - - if desc_request.len() as usize != size_of::<VirtioCanCtrlRequest>() { - println!("UnexpectedDescriptorSize, len = {:?}", desc_request.len()); - return Err(Error::UnexpectedDescriptorSize( - size_of::<VirtioCanCtrlRequest>(), - desc_request.len(), - )); - } - - let request = desc_chain - .memory() - .read_obj::<VirtioCanCtrlRequest>(desc_request.addr()) - .map_err(|_| Error::DescriptorReadFailed)?; - - - match request.msg_type.into() { - VIRTIO_CAN_SET_CTRL_MODE_START => { - println!("VIRTIO_CAN_SET_CTRL_MODE_START"); - //vcan->busoff = false; - Ok(()) - } - VIRTIO_CAN_SET_CTRL_MODE_STOP => { - println!("VIRTIO_CAN_SET_CTRL_MODE_STOP"); - //vcan->busoff = false; - Ok(()) - } - _ => { - println!("Ctrl queue: msg type 0x{:?} unknown", request.msg_type); - return Err(Error::HandleEventUnknown.into()) - }, - }?; - - let desc_response = descriptors[1]; - if !desc_response.is_write_only() { - println!("This is not wirtable"); - return Err(Error::UnexpectedReadableDescriptor(1)); - } - - let response = VIRTIO_CAN_STATUS_OK; - - desc_chain - .memory() - .write_slice(response.as_slice(), desc_response.addr()) - .map_err(|_| Error::DescriptorWriteFailed)?; - - if vring.add_used(desc_chain.head_index(), desc_response.len()).is_err() { - println!("Couldn't return used descriptors to the ring"); - warn!("Couldn't return used descriptors to the ring"); - } - } - - Ok(true) - } - - fn process_tx_requests( - &self, - requests: Vec<CanDescriptorChain>, - vring: &VringRwLock - ) -> Result<bool> { - dbg!("process_tx_requests"); - - if requests.is_empty() { - return Ok(true); - } - - println!("requests.len: {:?}", requests.len()); - for desc_chain in requests { - let descriptors: Vec<_> = desc_chain.clone().collect(); - - if descriptors.len() != 2 { - println!("Error::UnexpectedDescriptorCount"); - return Err(Error::UnexpectedDescriptorCount(descriptors.len())); - } - - let desc_request = descriptors[0]; - if desc_request.is_write_only() { - println!("Error::UnexpectedReadOnlyDescriptor"); - return Err(Error::UnexpectedWriteOnlyDescriptor(0)); - } - - if desc_request.len() as usize != size_of::<VirtioCanFrame>() { - println!("Tx UnexpectedDescriptorSize, len = {:?}", desc_request.len()); - //return Err(Error::UnexpectedDescriptorSize( - // size_of::<VirtioCanFrame>(), - // desc_request.len(), - //)); - } - - let request = desc_chain - .memory() - .read_obj::<VirtioCanFrame>(desc_request.addr()) - .map_err(|_| Error::DescriptorReadFailed)?; - - CanController::print_can_frame(request); - - let msg_type = request.msg_type.to_native(); - let mut can_id = request.can_id.to_native(); - let mut flags = request.flags.to_native(); - let mut length = request.length.to_native(); - - if msg_type != VIRTIO_CAN_TX { - warn!("TX: Message type 0x{:x} unknown\n", msg_type); - return Err(Error::UnexpectedCanMsgType(msg_type)); - } - - if (flags & VIRTIO_CAN_FLAGS_FD) != 0 { - if length > 64 { - println!("Cut sdu_len from {:?} to 64\n", request.length); - length = 64; - } - } else { - if length > 8 { - println!("Cut sdu_len from {:?} to 8\n", request.length); - length = 8; - } - } - - /* - * Copy Virtio frame structure to qemu frame structure and - * check while doing this whether the frame type was negotiated - */ - if (flags & VIRTIO_CAN_FLAGS_EXTENDED) != 0 { - flags &= CAN_EFF_MASK; - flags |= CAN_EFF_FLAG; - } else { - flags &= CAN_SFF_MASK; - } - - if (flags & VIRTIO_CAN_FLAGS_RTR) != 0 { - if !self.check_features(VIRTIO_CAN_F_CAN_CLASSIC) || - !self.check_features(VIRTIO_CAN_F_RTR_FRAMES) { - warn!("TX: RTR frames not negotiated"); - return Err(Error::UnexpectedRtrFlag); - } - can_id |= flags | CAN_RTR_FLAG; - } - - if (flags & VIRTIO_CAN_FLAGS_FD) != 0 { - if !self.check_features(VIRTIO_CAN_F_CAN_FD) { - warn!("TX: FD frames not negotiated\n"); - return Err(Error::UnexpectedFdFlag); - } - flags |= CAN_FRMF_TYPE_FD; - } else { - if !self.check_features(VIRTIO_CAN_F_CAN_CLASSIC) { - warn!("TX: Classic frames not negotiated\n"); - return Err(Error::UnexpectedClassicFlag); - } - flags = 0; - } - - let mut corrected_request = VirtioCanFrame::default(); - corrected_request.msg_type = msg_type.into(); - corrected_request.can_id = can_id.into(); - corrected_request.flags = flags.into(); - corrected_request.length = length.into(); - corrected_request.sdu.copy_from_slice(&request.sdu[0..64]); - - let desc_response = descriptors[1]; - if !desc_response.is_write_only() { - println!("Error::UnexpectedWriteOnlyDescriptor"); - return Err(Error::UnexpectedReadableDescriptor(1)); - } - - let response = match self.controller.write().unwrap().operation(corrected_request) { - Ok(result) => { - result - } - Err(_) => { - warn!("We got an error from controller send func"); - VIRTIO_CAN_STATUS_ERR - } - }; - - desc_chain - .memory() - .write_slice(response.as_slice(), desc_response.addr()) - .map_err(|_| Error::DescriptorWriteFailed)?; - - if vring.add_used(desc_chain.head_index(), desc_response.len()).is_err() { - println!("Couldn't return used descriptors to the ring"); - warn!("Couldn't return used descriptors to the ring"); - } - } - - Ok(true) - } - - fn process_rx_requests( - &mut self, - requests: Vec<CanDescriptorChain>, - vring: &VringRwLock - ) -> Result<bool> { - dbg!("process_rx_requests"); - - if requests.is_empty() { - return Ok(true); - } - - let desc_chain = &requests[0]; - let descriptors: Vec<_> = desc_chain.clone().collect(); - - if descriptors.len() != 1 { - println!("Error::UnexpectedDescriptorCount"); - return Err(Error::UnexpectedDescriptorCount(descriptors.len())); - } - - let desc_response = descriptors[0]; - if !desc_response.is_write_only() { - return Err(Error::UnexpectedReadableDescriptor(1)); - } - - let mut response = match self.controller.write().unwrap().pop() { - Ok(item) => item, - Err(_) => return Err(Error::HandleEventUnknown), - }; - - CanController::print_can_frame(response); - - if (response.can_id.to_native() & CAN_ERR_FLAG) != 0 { - if (response.can_id.to_native() & CAN_ERR_BUSOFF) != 0 { - warn!("Got BusOff error frame, device does a local bus off\n"); - //vcan->busoff = true; - } else { - println!("Dropping error frame 0x{:x}\n", response.can_id.to_native()); - } - return Ok(true); - } - - let mut can_rx = VirtioCanFrame::default(); - can_rx.msg_type = VIRTIO_CAN_RX.into(); - can_rx.can_id = response.can_id; - can_rx.length = response.length; - can_rx.flags = (can_rx.flags.to_native() | VIRTIO_CAN_FLAGS_FD).into(); - - if (response.flags.to_native() & CAN_FRMF_TYPE_FD) != 0 { - if !self.check_features(VIRTIO_CAN_F_CAN_FD) { - warn!("Drop non-supported CAN FD frame"); - return Err(Error::UnexpectedFdFlag); - } - } else { - if !self.check_features(VIRTIO_CAN_F_CAN_CLASSIC) { - warn!("Drop non-supported CAN classic frame"); - return Err(Error::UnexpectedClassicFlag); - } - } - if (response.can_id.to_native() & CAN_RTR_FLAG) != 0 && - !self.check_features(VIRTIO_CAN_F_RTR_FRAMES) { - warn!("Drop non-supported RTR frame"); - return Err(Error::UnexpectedRtrFlag); - } - - if (response.can_id.to_native() & CAN_EFF_FLAG) != 0 { - can_rx.flags = VIRTIO_CAN_FLAGS_EXTENDED.into(); - can_rx.can_id = (response.can_id.to_native() & CAN_EFF_MASK).into(); - } else { - can_rx.can_id = (response.can_id.to_native() & CAN_SFF_MASK).into(); - } - if (response.can_id.to_native() & CAN_RTR_FLAG) != 0 { - can_rx.flags = (can_rx.flags.to_native() & VIRTIO_CAN_FLAGS_RTR).into(); - } - - // HACK AHEAD: Vcan can not be comfigured as CANFD interface, but possible - // to configure its MTU to 64 bytes. So if a messages bigger than 8 bytes - // is being received we consider it as CANFD message. - let can_in_name = self.controller.read().unwrap().can_in_name.clone(); - if self.check_features(VIRTIO_CAN_F_CAN_FD) && - response.length.to_native() > 8 && can_in_name == "vcan0" { - response.flags = (response.flags.to_native() | CAN_FRMF_TYPE_FD).into(); - warn!("\n\n\nCANFD VCAN0\n\n"); - } - - if (response.flags.to_native() & CAN_FRMF_TYPE_FD) != 0 { - can_rx.flags = (can_rx.flags.to_native() | VIRTIO_CAN_FLAGS_FD).into(); - if response.length.to_native() > 64 { - warn!("%s(): Cut length from {} to 64\n", response.length.to_native()); - can_rx.length = 64.into(); - } - } else { - if response.length.to_native() > 8 { - warn!("%s(): Cut length from {} to 8\n", response.length.to_native()); - can_rx.length = 8.into(); - } - } - - can_rx.sdu.copy_from_slice(&response.sdu[0..64]); - CanController::print_can_frame(can_rx); - - desc_chain - .memory() - .write_slice(can_rx.as_slice(), desc_response.addr()) - .map_err(|_| Error::DescriptorWriteFailed)?; - - if vring.add_used(desc_chain.head_index(), desc_response.len()).is_err() { - warn!("Couldn't return used descriptors to the ring"); - } - - Ok(true) - } - - /// Process the messages in the vring and dispatch replies - fn process_ctrl_queue(&mut self, vring: &VringRwLock) -> Result<()> { - dbg!("process_ctrl_queue"); - let requests: Vec<_> = vring - .get_mut() - .get_queue_mut() - .iter(self.mem.as_ref().unwrap().memory()) - .map_err(|_| Error::DescriptorNotFound)? - .collect(); - - if self.process_ctrl_requests(requests, vring)? { - // Send notification once all the requests are processed - vring - .signal_used_queue() - .map_err(|_| Error::NotificationFailed)?; - } - Ok(()) - } - - /// Process the messages in the vring and dispatch replies - fn process_tx_queue(&self, vring: &VringRwLock) -> Result<()> { - dbg!("process_tx_queue"); - let requests: Vec<_> = vring - .get_mut() - .get_queue_mut() - .iter(self.mem.as_ref().unwrap().memory()) - .map_err(|_| Error::DescriptorNotFound)? - .collect(); - - if self.process_tx_requests(requests, vring)? { - // Send notification once all the requests are processed - vring - .signal_used_queue() - .map_err(|_| { - println!("signal_used_queue error"); - Error::NotificationFailed - })?; - } - - Ok(()) - } - - /// Process the messages in the vring and dispatch replies - fn process_rx_queue(&mut self, vring: &VringRwLock) -> Result<()> { - dbg!("process_rx_queue"); - let requests: Vec<_> = vring - .get_mut() - .get_queue_mut() - .iter(self.mem.as_ref().unwrap().memory()) - .map_err(|_| Error::DescriptorNotFound)? - .collect(); - - if self.process_rx_requests(requests, vring)? { - // Send notification once all the requests are processed - vring - .signal_used_queue() - .map_err(|_| { - println!("NotificationFailed"); - Error::NotificationFailed - })?; - } - Ok(()) - } - - fn process_rx_queue_dump(&mut self, _vring: &VringRwLock) -> Result<()> { - dbg!("Do nothing, if you reach that point!"); - Ok(()) - } - - /// Set self's VringWorker. - pub(crate) fn set_vring_worker( - &self, - vring_worker: &Arc<VringEpollHandler<Arc<RwLock<VhostUserCanBackend>>, VringRwLock, ()>>, - ) { - let rx_event_fd = self.controller.read().unwrap().rx_event_fd.as_raw_fd(); - vring_worker - .register_listener( - rx_event_fd, - EventSet::IN, - //u64::from(BACKEND_EFD)) - 4u64 as u64) - .unwrap(); - } -} - -/// VhostUserBackendMut trait methods -impl VhostUserBackendMut<VringRwLock, ()> - for VhostUserCanBackend -{ - fn num_queues(&self) -> usize { - println!("num_queues: {:?}", NUM_QUEUES); - NUM_QUEUES - } - - fn max_queue_size(&self) -> usize { - println!("max_queue_size: {:?}", QUEUE_SIZE); - QUEUE_SIZE - } - - fn features(&self) -> u64 { - // this matches the current libvhost defaults except VHOST_F_LOG_ALL - let features = 1 << VIRTIO_F_VERSION_1 - | 1 << VIRTIO_F_NOTIFY_ON_EMPTY - | 1 << VIRTIO_RING_F_EVENT_IDX - | 1 << VIRTIO_CAN_F_CAN_CLASSIC - | 1 << VIRTIO_CAN_F_CAN_FD - | 1 << VIRTIO_RING_F_INDIRECT_DESC - | VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits(); - - println!("vhu_can->features: {:x}", features); - features - } - - fn acked_features(&mut self, _features: u64) { - println!("\nacked_features: 0x{:x}\n", _features); - self.acked_features = _features; - } - - fn protocol_features(&self) -> VhostUserProtocolFeatures { - let protocol_features = VhostUserProtocolFeatures::MQ - | VhostUserProtocolFeatures::CONFIG - | VhostUserProtocolFeatures::REPLY_ACK; - //| VhostUserProtocolFeatures::STATUS - - println!("protocol_features: {:x}", protocol_features); - protocol_features - } - - fn get_config(&self, offset: u32, size: u32) -> Vec<u8> { - // SAFETY: The layout of the structure is fixed and can be initialized by - // reading its content from byte array. - dbg!("vhu_can->get_config"); - unsafe { - from_raw_parts( - self.controller.write().unwrap() - .config() - .as_slice() - .as_ptr() - .offset(offset as isize) as *const _ as *const _, - size as usize, - ) - .to_vec() - } - } - - fn set_event_idx(&mut self, enabled: bool) { - dbg!(self.event_idx = enabled); - } - - fn update_memory(&mut self, mem: GuestMemoryAtomic<GuestMemoryMmap>) -> IoResult<()> { - dbg!("update_memory\n"); - self.mem = Some(mem); - Ok(()) - } - - fn handle_event( - &mut self, - device_event: u16, - evset: EventSet, - vrings: &[VringRwLock], - _thread_id: usize, - ) -> IoResult<bool> { - dbg!("\nhandle_event:"); - - if evset != EventSet::IN { - return Err(Error::HandleEventNotEpollIn.into()); - } - if device_event == RX_QUEUE { - println!("RX_QUEUE\n"); - return Ok(false); - }; - let vring = if device_event != BACKEND_EFD { - &vrings[device_event as usize] - } else { - println!("BACKEND_EFD\n"); - let _ = self.controller.write().unwrap().rx_event_fd.read(); - &vrings[RX_QUEUE as usize] - }; - if self.event_idx { - // vm-virtio's Queue implementation only checks avail_index - // once, so to properly support EVENT_IDX we need to keep - // calling process_request_queue() until it stops finding - // new requests on the queue. - loop { - vring.disable_notification().unwrap(); - //match queue_idx { - match device_event { - CTRL_QUEUE => self.process_ctrl_queue(vring), - TX_QUEUE => self.process_tx_queue(vring), - RX_QUEUE => self.process_rx_queue_dump(vring), - BACKEND_EFD => self.process_rx_queue(vring), - _ => Err(Error::HandleEventUnknown.into()), - }?; - if !vring.enable_notification().unwrap() { - break; - } - } - } else { - // Without EVENT_IDX, a single call is enough. - match device_event { - CTRL_QUEUE => self.process_ctrl_queue(vring), - TX_QUEUE => self.process_tx_queue(vring), - RX_QUEUE => self.process_rx_queue_dump(vring), - BACKEND_EFD => self.process_rx_queue(vring), - _ => Err(Error::HandleEventUnknown.into()), - }?; - } - Ok(false) - } - - fn exit_event(&self, _thread_index: usize) -> Option<EventFd> { - dbg!("exit_event\n"); - self.exit_event.try_clone().ok() - } -} - |