122f91ab3SSebastien Boeuf // Copyright 2019 Intel Corporation. All Rights Reserved. 222f91ab3SSebastien Boeuf // SPDX-License-Identifier: Apache-2.0 322f91ab3SSebastien Boeuf // 422f91ab3SSebastien Boeuf // Portions Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 522f91ab3SSebastien Boeuf // SPDX-License-Identifier: Apache-2.0 622f91ab3SSebastien Boeuf // 722f91ab3SSebastien Boeuf // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. 822f91ab3SSebastien Boeuf // Use of this source code is governed by a BSD-style license that can be 922f91ab3SSebastien Boeuf // found in the THIRD-PARTY file. 1022f91ab3SSebastien Boeuf 11df61a8feSSebastien Boeuf mod csm; 1222f91ab3SSebastien Boeuf mod device; 13df61a8feSSebastien Boeuf mod packet; 14434a5d0eSSebastien Boeuf mod unix; 1522f91ab3SSebastien Boeuf 1688a9f799SRob Bradford use std::os::unix::io::RawFd; 1788a9f799SRob Bradford 1888a9f799SRob Bradford use packet::VsockPacket; 1988a9f799SRob Bradford 2022f91ab3SSebastien Boeuf pub use self::device::Vsock; 2161e57e1cSRuoqing He pub use self::unix::{VsockUnixBackend, VsockUnixError}; 22df61a8feSSebastien Boeuf 23df61a8feSSebastien Boeuf mod defs { 24df61a8feSSebastien Boeuf 25df61a8feSSebastien Boeuf /// Max vsock packet data/buffer size. 26df61a8feSSebastien Boeuf pub const MAX_PKT_BUF_SIZE: usize = 64 * 1024; 27df61a8feSSebastien Boeuf 28df61a8feSSebastien Boeuf pub mod uapi { 29df61a8feSSebastien Boeuf 30df61a8feSSebastien Boeuf /// Vsock packet operation IDs. 31df61a8feSSebastien Boeuf /// Defined in `/include/uapi/linux/virtio_vsock.h`. 32df61a8feSSebastien Boeuf /// 33df61a8feSSebastien Boeuf /// Connection request. 34df61a8feSSebastien Boeuf pub const VSOCK_OP_REQUEST: u16 = 1; 35df61a8feSSebastien Boeuf /// Connection response. 36df61a8feSSebastien Boeuf pub const VSOCK_OP_RESPONSE: u16 = 2; 37df61a8feSSebastien Boeuf /// Connection reset. 38df61a8feSSebastien Boeuf pub const VSOCK_OP_RST: u16 = 3; 39df61a8feSSebastien Boeuf /// Connection clean shutdown. 40df61a8feSSebastien Boeuf pub const VSOCK_OP_SHUTDOWN: u16 = 4; 41df61a8feSSebastien Boeuf /// Connection data (read/write). 42df61a8feSSebastien Boeuf pub const VSOCK_OP_RW: u16 = 5; 43df61a8feSSebastien Boeuf /// Flow control credit update. 44df61a8feSSebastien Boeuf pub const VSOCK_OP_CREDIT_UPDATE: u16 = 6; 45df61a8feSSebastien Boeuf /// Flow control credit update request. 46df61a8feSSebastien Boeuf pub const VSOCK_OP_CREDIT_REQUEST: u16 = 7; 47df61a8feSSebastien Boeuf 48df61a8feSSebastien Boeuf /// Vsock packet flags. 49df61a8feSSebastien Boeuf /// Defined in `/include/uapi/linux/virtio_vsock.h`. 50df61a8feSSebastien Boeuf /// 51df61a8feSSebastien Boeuf /// Valid with a VSOCK_OP_SHUTDOWN packet: the packet sender will receive no more data. 52df61a8feSSebastien Boeuf pub const VSOCK_FLAGS_SHUTDOWN_RCV: u32 = 1; 53df61a8feSSebastien Boeuf /// Valid with a VSOCK_OP_SHUTDOWN packet: the packet sender will send no more data. 54df61a8feSSebastien Boeuf pub const VSOCK_FLAGS_SHUTDOWN_SEND: u32 = 2; 55df61a8feSSebastien Boeuf 56df61a8feSSebastien Boeuf /// Vsock packet type. 57df61a8feSSebastien Boeuf /// Defined in `/include/uapi/linux/virtio_vsock.h`. 58df61a8feSSebastien Boeuf /// 59df61a8feSSebastien Boeuf /// Stream / connection-oriented packet (the only currently valid type). 60df61a8feSSebastien Boeuf pub const VSOCK_TYPE_STREAM: u16 = 1; 61df61a8feSSebastien Boeuf 62df61a8feSSebastien Boeuf pub const VSOCK_HOST_CID: u64 = 2; 63df61a8feSSebastien Boeuf } 64df61a8feSSebastien Boeuf } 65df61a8feSSebastien Boeuf 66df61a8feSSebastien Boeuf #[derive(Debug)] 67df61a8feSSebastien Boeuf pub enum VsockError { 68df61a8feSSebastien Boeuf /// The vsock data/buffer virtio descriptor length is smaller than expected. 69df61a8feSSebastien Boeuf BufDescTooSmall, 70df61a8feSSebastien Boeuf /// The vsock data/buffer virtio descriptor is expected, but missing. 71df61a8feSSebastien Boeuf BufDescMissing, 72df61a8feSSebastien Boeuf /// Chained GuestMemory error. 73df61a8feSSebastien Boeuf GuestMemory, 74df61a8feSSebastien Boeuf /// Bounds check failed on guest memory pointer. 75df61a8feSSebastien Boeuf GuestMemoryBounds, 76df61a8feSSebastien Boeuf /// The vsock header descriptor length is too small. 77df61a8feSSebastien Boeuf HdrDescTooSmall(u32), 780249e864SSebastien Boeuf /// The vsock header descriptor is expected, but missing. 790249e864SSebastien Boeuf HdrDescMissing, 80df61a8feSSebastien Boeuf /// The vsock header `len` field holds an invalid value. 81df61a8feSSebastien Boeuf InvalidPktLen(u32), 82df61a8feSSebastien Boeuf /// A data fetch was attempted when no data was available. 83df61a8feSSebastien Boeuf NoData, 84df61a8feSSebastien Boeuf /// A data buffer was expected for the provided packet, but it is missing. 85df61a8feSSebastien Boeuf PktBufMissing, 86df61a8feSSebastien Boeuf /// Encountered an unexpected write-only virtio descriptor. 87df61a8feSSebastien Boeuf UnreadableDescriptor, 88df61a8feSSebastien Boeuf /// Encountered an unexpected read-only virtio descriptor. 89df61a8feSSebastien Boeuf UnwritableDescriptor, 90df61a8feSSebastien Boeuf } 91df61a8feSSebastien Boeuf type Result<T> = std::result::Result<T, VsockError>; 92df61a8feSSebastien Boeuf 9379753949SSebastien Boeuf #[derive(Debug)] 9479753949SSebastien Boeuf pub enum VsockEpollHandlerError { 9579753949SSebastien Boeuf /// The vsock data/buffer virtio descriptor length is smaller than expected. 9679753949SSebastien Boeuf BufDescTooSmall, 9779753949SSebastien Boeuf /// The vsock data/buffer virtio descriptor is expected, but missing. 9879753949SSebastien Boeuf BufDescMissing, 9979753949SSebastien Boeuf /// Chained GuestMemory error. 10079753949SSebastien Boeuf GuestMemory, 10179753949SSebastien Boeuf /// Bounds check failed on guest memory pointer. 10279753949SSebastien Boeuf GuestMemoryBounds, 10379753949SSebastien Boeuf /// The vsock header descriptor length is too small. 10479753949SSebastien Boeuf HdrDescTooSmall(u32), 10579753949SSebastien Boeuf /// The vsock header `len` field holds an invalid value. 10679753949SSebastien Boeuf InvalidPktLen(u32), 10779753949SSebastien Boeuf /// A data fetch was attempted when no data was available. 10879753949SSebastien Boeuf NoData, 10979753949SSebastien Boeuf /// A data buffer was expected for the provided packet, but it is missing. 11079753949SSebastien Boeuf PktBufMissing, 11179753949SSebastien Boeuf /// Encountered an unexpected write-only virtio descriptor. 11279753949SSebastien Boeuf UnreadableDescriptor, 11379753949SSebastien Boeuf /// Encountered an unexpected read-only virtio descriptor. 11479753949SSebastien Boeuf UnwritableDescriptor, 11579753949SSebastien Boeuf } 11679753949SSebastien Boeuf 117df61a8feSSebastien Boeuf /// A passive, event-driven object, that needs to be notified whenever an epoll-able event occurs. 11860c8a72eSBo Chen /// 119df61a8feSSebastien Boeuf /// An event-polling control loop will use `get_polled_fd()` and `get_polled_evset()` to query 120df61a8feSSebastien Boeuf /// the listener for the file descriptor and the set of events it's interested in. When such an 121df61a8feSSebastien Boeuf /// event occurs, the control loop will route the event to the listener via `notify()`. 122df61a8feSSebastien Boeuf /// 123df61a8feSSebastien Boeuf pub trait VsockEpollListener { 124df61a8feSSebastien Boeuf /// Get the file descriptor the listener needs polled. get_polled_fd(&self) -> RawFd125df61a8feSSebastien Boeuf fn get_polled_fd(&self) -> RawFd; 126df61a8feSSebastien Boeuf 127df61a8feSSebastien Boeuf /// Get the set of events for which the listener wants to be notified. get_polled_evset(&self) -> epoll::Events128df61a8feSSebastien Boeuf fn get_polled_evset(&self) -> epoll::Events; 129df61a8feSSebastien Boeuf 13042e9632cSJosh Soref /// Notify the listener that one or more events have occurred. notify(&mut self, evset: epoll::Events)131df61a8feSSebastien Boeuf fn notify(&mut self, evset: epoll::Events); 132df61a8feSSebastien Boeuf } 133df61a8feSSebastien Boeuf 13460c8a72eSBo Chen /// Trait to describe any channel that handles vsock packet traffic (sending and receiving packets) 13560c8a72eSBo Chen /// 13660c8a72eSBo Chen /// Since we're implementing the device model here, our responsibility is to always process the sending of 137df61a8feSSebastien Boeuf /// packets (i.e. the TX queue). So, any locally generated data, addressed to the driver (e.g. 138df61a8feSSebastien Boeuf /// a connection response or RST), will have to be queued, until we get to processing the RX queue. 139df61a8feSSebastien Boeuf /// 140df61a8feSSebastien Boeuf /// Note: `recv_pkt()` and `send_pkt()` are named analogous to `Read::read()` and `Write::write()`, 141df61a8feSSebastien Boeuf /// respectively. I.e. 142df61a8feSSebastien Boeuf /// - `recv_pkt(&mut pkt)` will read data from the channel, and place it into `pkt`; and 143df61a8feSSebastien Boeuf /// - `send_pkt(&pkt)` will fetch data from `pkt`, and place it into the channel. 144df61a8feSSebastien Boeuf pub trait VsockChannel { 145df61a8feSSebastien Boeuf /// Read/receive an incoming packet from the channel. recv_pkt(&mut self, pkt: &mut VsockPacket) -> Result<()>146df61a8feSSebastien Boeuf fn recv_pkt(&mut self, pkt: &mut VsockPacket) -> Result<()>; 147df61a8feSSebastien Boeuf 148df61a8feSSebastien Boeuf /// Write/send a packet through the channel. send_pkt(&mut self, pkt: &VsockPacket) -> Result<()>149df61a8feSSebastien Boeuf fn send_pkt(&mut self, pkt: &VsockPacket) -> Result<()>; 150df61a8feSSebastien Boeuf 151df61a8feSSebastien Boeuf /// Checks whether there is pending incoming data inside the channel, meaning that a subsequent 152df61a8feSSebastien Boeuf /// call to `recv_pkt()` won't fail. has_pending_rx(&self) -> bool153df61a8feSSebastien Boeuf fn has_pending_rx(&self) -> bool; 154df61a8feSSebastien Boeuf } 155df61a8feSSebastien Boeuf 15660c8a72eSBo Chen /// The vsock backend, which is basically an epoll-event-driven vsock channel 15760c8a72eSBo Chen /// 15860c8a72eSBo Chen /// It that needs to be sendable through a mpsc channel (the latter due to how `vmm::EpollContext` works). 159df61a8feSSebastien Boeuf /// Currently, the only implementation we have is `crate::virtio::unix::muxer::VsockMuxer`, which 160df61a8feSSebastien Boeuf /// translates guest-side vsock connections to host-side Unix domain socket connections. 161df61a8feSSebastien Boeuf pub trait VsockBackend: VsockChannel + VsockEpollListener + Send {} 16279753949SSebastien Boeuf 163d359c8cdSWei Liu #[cfg(any(test, fuzzing))] 164d359c8cdSWei Liu pub mod tests { 16588a9f799SRob Bradford use std::os::unix::io::AsRawFd; 16688a9f799SRob Bradford use std::path::PathBuf; 16788a9f799SRob Bradford use std::sync::{Arc, RwLock}; 16888a9f799SRob Bradford 16988a9f799SRob Bradford use libc::EFD_NONBLOCK; 17088a9f799SRob Bradford use virtio_bindings::virtio_ring::{VRING_DESC_F_NEXT, VRING_DESC_F_WRITE}; 17188a9f799SRob Bradford use vm_memory::{GuestAddress, GuestMemoryAtomic}; 17288a9f799SRob Bradford use vm_virtio::queue::testing::VirtQueue as GuestQ; 17388a9f799SRob Bradford use vmm_sys_util::eventfd::EventFd; 17488a9f799SRob Bradford 17579753949SSebastien Boeuf use super::device::{VsockEpollHandler, RX_QUEUE_EVENT, TX_QUEUE_EVENT}; 17679753949SSebastien Boeuf use super::packet::VSOCK_PKT_HDR_SIZE; 17779753949SSebastien Boeuf use super::*; 17879753949SSebastien Boeuf use crate::device::{VirtioInterrupt, VirtioInterruptType}; 1798fbc4b40SSebastien Boeuf use crate::epoll_helper::EpollHelperHandler; 18061e57e1cSRuoqing He use crate::{EpollHelper, GuestMemoryMmap}; 18179753949SSebastien Boeuf 182c396bacaSSebastien Boeuf pub struct NoopVirtioInterrupt {} 183c396bacaSSebastien Boeuf 184c396bacaSSebastien Boeuf impl VirtioInterrupt for NoopVirtioInterrupt { trigger( &self, _int_type: VirtioInterruptType, ) -> std::result::Result<(), std::io::Error>185c396bacaSSebastien Boeuf fn trigger( 186c396bacaSSebastien Boeuf &self, 187de3e003eSSebastien Boeuf _int_type: VirtioInterruptType, 188c396bacaSSebastien Boeuf ) -> std::result::Result<(), std::io::Error> { 189c396bacaSSebastien Boeuf Ok(()) 190c396bacaSSebastien Boeuf } 191c396bacaSSebastien Boeuf } 192c396bacaSSebastien Boeuf 19379753949SSebastien Boeuf pub struct TestBackend { 19479753949SSebastien Boeuf pub evfd: EventFd, 19579753949SSebastien Boeuf pub rx_err: Option<VsockError>, 19679753949SSebastien Boeuf pub tx_err: Option<VsockError>, 19779753949SSebastien Boeuf pub pending_rx: bool, 19879753949SSebastien Boeuf pub rx_ok_cnt: usize, 19979753949SSebastien Boeuf pub tx_ok_cnt: usize, 20079753949SSebastien Boeuf pub evset: Option<epoll::Events>, 20179753949SSebastien Boeuf } 20279753949SSebastien Boeuf impl TestBackend { 203d359c8cdSWei Liu #[allow(clippy::new_without_default)] new() -> Self20479753949SSebastien Boeuf pub fn new() -> Self { 20579753949SSebastien Boeuf Self { 20679753949SSebastien Boeuf evfd: EventFd::new(EFD_NONBLOCK).unwrap(), 20779753949SSebastien Boeuf rx_err: None, 20879753949SSebastien Boeuf tx_err: None, 20979753949SSebastien Boeuf pending_rx: false, 21079753949SSebastien Boeuf rx_ok_cnt: 0, 21179753949SSebastien Boeuf tx_ok_cnt: 0, 21279753949SSebastien Boeuf evset: None, 21379753949SSebastien Boeuf } 21479753949SSebastien Boeuf } set_rx_err(&mut self, err: Option<VsockError>)21579753949SSebastien Boeuf pub fn set_rx_err(&mut self, err: Option<VsockError>) { 21679753949SSebastien Boeuf self.rx_err = err; 21779753949SSebastien Boeuf } set_tx_err(&mut self, err: Option<VsockError>)21879753949SSebastien Boeuf pub fn set_tx_err(&mut self, err: Option<VsockError>) { 21979753949SSebastien Boeuf self.tx_err = err; 22079753949SSebastien Boeuf } set_pending_rx(&mut self, prx: bool)22179753949SSebastien Boeuf pub fn set_pending_rx(&mut self, prx: bool) { 22279753949SSebastien Boeuf self.pending_rx = prx; 22379753949SSebastien Boeuf } 22479753949SSebastien Boeuf } 22579753949SSebastien Boeuf impl VsockChannel for TestBackend { recv_pkt(&mut self, _pkt: &mut VsockPacket) -> Result<()>22679753949SSebastien Boeuf fn recv_pkt(&mut self, _pkt: &mut VsockPacket) -> Result<()> { 22779753949SSebastien Boeuf match self.rx_err.take() { 22879753949SSebastien Boeuf None => { 22979753949SSebastien Boeuf self.rx_ok_cnt += 1; 23079753949SSebastien Boeuf Ok(()) 23179753949SSebastien Boeuf } 23279753949SSebastien Boeuf Some(e) => Err(e), 23379753949SSebastien Boeuf } 23479753949SSebastien Boeuf } send_pkt(&mut self, _pkt: &VsockPacket) -> Result<()>23579753949SSebastien Boeuf fn send_pkt(&mut self, _pkt: &VsockPacket) -> Result<()> { 23679753949SSebastien Boeuf match self.tx_err.take() { 23779753949SSebastien Boeuf None => { 23879753949SSebastien Boeuf self.tx_ok_cnt += 1; 23979753949SSebastien Boeuf Ok(()) 24079753949SSebastien Boeuf } 24179753949SSebastien Boeuf Some(e) => Err(e), 24279753949SSebastien Boeuf } 24379753949SSebastien Boeuf } has_pending_rx(&self) -> bool24479753949SSebastien Boeuf fn has_pending_rx(&self) -> bool { 24579753949SSebastien Boeuf self.pending_rx 24679753949SSebastien Boeuf } 24779753949SSebastien Boeuf } 24879753949SSebastien Boeuf impl VsockEpollListener for TestBackend { get_polled_fd(&self) -> RawFd24979753949SSebastien Boeuf fn get_polled_fd(&self) -> RawFd { 25079753949SSebastien Boeuf self.evfd.as_raw_fd() 25179753949SSebastien Boeuf } get_polled_evset(&self) -> epoll::Events25279753949SSebastien Boeuf fn get_polled_evset(&self) -> epoll::Events { 25379753949SSebastien Boeuf epoll::Events::EPOLLIN 25479753949SSebastien Boeuf } notify(&mut self, evset: epoll::Events)25579753949SSebastien Boeuf fn notify(&mut self, evset: epoll::Events) { 25679753949SSebastien Boeuf self.evset = Some(evset); 25779753949SSebastien Boeuf } 25879753949SSebastien Boeuf } 25979753949SSebastien Boeuf impl VsockBackend for TestBackend {} 26079753949SSebastien Boeuf 26179753949SSebastien Boeuf pub struct TestContext { 26279753949SSebastien Boeuf pub cid: u64, 26379753949SSebastien Boeuf pub mem: GuestMemoryMmap, 26479753949SSebastien Boeuf pub device: Vsock<TestBackend>, 26579753949SSebastien Boeuf } 26679753949SSebastien Boeuf 26779753949SSebastien Boeuf impl TestContext { 268d359c8cdSWei Liu #[allow(clippy::new_without_default)] new() -> Self26979753949SSebastien Boeuf pub fn new() -> Self { 270451d3fb2SAlyssa Ross const CID: u32 = 52; 27179753949SSebastien Boeuf const MEM_SIZE: usize = 1024 * 1024 * 128; 27279753949SSebastien Boeuf Self { 273451d3fb2SAlyssa Ross cid: CID as u64, 2743447e226SSebastien Boeuf mem: GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap(), 275fec97e05SRob Bradford device: Vsock::new( 276fec97e05SRob Bradford String::from("vsock"), 277fec97e05SRob Bradford CID, 278fec97e05SRob Bradford PathBuf::from("/test/sock"), 279fec97e05SRob Bradford TestBackend::new(), 280fec97e05SRob Bradford false, 28108ac3405SBo Chen seccompiler::SeccompAction::Trap, 282687d646cSRob Bradford EventFd::new(EFD_NONBLOCK).unwrap(), 2831f0e5eb6SSebastien Boeuf None, 284fec97e05SRob Bradford ) 285fec97e05SRob Bradford .unwrap(), 28679753949SSebastien Boeuf } 28779753949SSebastien Boeuf } 28879753949SSebastien Boeuf create_epoll_handler_context(&self) -> EpollHandlerContext<'_>289*2bc8d51aSJinank Jain pub fn create_epoll_handler_context(&self) -> EpollHandlerContext<'_> { 29079753949SSebastien Boeuf const QSIZE: u16 = 2; 29179753949SSebastien Boeuf 292a9ec0f33SBo Chen let guest_rxvq = GuestQ::new(GuestAddress(0x0010_0000), &self.mem, QSIZE); 293a9ec0f33SBo Chen let guest_txvq = GuestQ::new(GuestAddress(0x0020_0000), &self.mem, QSIZE); 294a9ec0f33SBo Chen let guest_evvq = GuestQ::new(GuestAddress(0x0030_0000), &self.mem, QSIZE); 29579753949SSebastien Boeuf let rxvq = guest_rxvq.create_queue(); 29679753949SSebastien Boeuf let txvq = guest_txvq.create_queue(); 29779753949SSebastien Boeuf let evvq = guest_evvq.create_queue(); 29879753949SSebastien Boeuf 29979753949SSebastien Boeuf // Set up one available descriptor in the RX queue. 30079753949SSebastien Boeuf guest_rxvq.dtable[0].set( 30179753949SSebastien Boeuf 0x0040_0000, 30279753949SSebastien Boeuf VSOCK_PKT_HDR_SIZE as u32, 303a423bf13SSebastien Boeuf (VRING_DESC_F_WRITE | VRING_DESC_F_NEXT).try_into().unwrap(), 30479753949SSebastien Boeuf 1, 30579753949SSebastien Boeuf ); 306a423bf13SSebastien Boeuf guest_rxvq.dtable[1].set(0x0040_1000, 4096, VRING_DESC_F_WRITE.try_into().unwrap(), 0); 30779753949SSebastien Boeuf guest_rxvq.avail.ring[0].set(0); 30879753949SSebastien Boeuf guest_rxvq.avail.idx.set(1); 30979753949SSebastien Boeuf 31079753949SSebastien Boeuf // Set up one available descriptor in the TX queue. 311a423bf13SSebastien Boeuf guest_txvq.dtable[0].set( 312a423bf13SSebastien Boeuf 0x0050_0000, 313a423bf13SSebastien Boeuf VSOCK_PKT_HDR_SIZE as u32, 314a423bf13SSebastien Boeuf VRING_DESC_F_NEXT.try_into().unwrap(), 315a423bf13SSebastien Boeuf 1, 316a423bf13SSebastien Boeuf ); 31779753949SSebastien Boeuf guest_txvq.dtable[1].set(0x0050_1000, 4096, 0, 0); 31879753949SSebastien Boeuf guest_txvq.avail.ring[0].set(0); 31979753949SSebastien Boeuf guest_txvq.avail.idx.set(1); 32079753949SSebastien Boeuf 32179753949SSebastien Boeuf let queues = vec![rxvq, txvq, evvq]; 32279753949SSebastien Boeuf let queue_evts = vec![ 32379753949SSebastien Boeuf EventFd::new(EFD_NONBLOCK).unwrap(), 32479753949SSebastien Boeuf EventFd::new(EFD_NONBLOCK).unwrap(), 32579753949SSebastien Boeuf EventFd::new(EFD_NONBLOCK).unwrap(), 32679753949SSebastien Boeuf ]; 327c396bacaSSebastien Boeuf let interrupt_cb = Arc::new(NoopVirtioInterrupt {}); 32879753949SSebastien Boeuf 32979753949SSebastien Boeuf EpollHandlerContext { 33079753949SSebastien Boeuf guest_rxvq, 33179753949SSebastien Boeuf guest_txvq, 33279753949SSebastien Boeuf guest_evvq, 33379753949SSebastien Boeuf handler: VsockEpollHandler { 334793d4e7bSSebastien Boeuf mem: GuestMemoryAtomic::new(self.mem.clone()), 33579753949SSebastien Boeuf queues, 33679753949SSebastien Boeuf queue_evts, 33779753949SSebastien Boeuf kill_evt: EventFd::new(EFD_NONBLOCK).unwrap(), 338dae0b2efSSamuel Ortiz pause_evt: EventFd::new(EFD_NONBLOCK).unwrap(), 33979753949SSebastien Boeuf interrupt_cb, 340dac77379SSebastien Boeuf backend: Arc::new(RwLock::new(TestBackend::new())), 341e2225bb4SSebastien Boeuf access_platform: None, 34279753949SSebastien Boeuf }, 34379753949SSebastien Boeuf } 34479753949SSebastien Boeuf } 34579753949SSebastien Boeuf } 34679753949SSebastien Boeuf 34779753949SSebastien Boeuf pub struct EpollHandlerContext<'a> { 34879753949SSebastien Boeuf pub handler: VsockEpollHandler<TestBackend>, 34979753949SSebastien Boeuf pub guest_rxvq: GuestQ<'a>, 35079753949SSebastien Boeuf pub guest_txvq: GuestQ<'a>, 35179753949SSebastien Boeuf pub guest_evvq: GuestQ<'a>, 35279753949SSebastien Boeuf } 35379753949SSebastien Boeuf 3540aab960bSRuoqing He impl EpollHandlerContext<'_> { signal_txq_event(&mut self)35579753949SSebastien Boeuf pub fn signal_txq_event(&mut self) { 35679753949SSebastien Boeuf self.handler.queue_evts[1].write(1).unwrap(); 3578fbc4b40SSebastien Boeuf let events = epoll::Events::EPOLLIN; 3588fbc4b40SSebastien Boeuf let event = epoll::Event::new(events, TX_QUEUE_EVENT as u64); 3598fbc4b40SSebastien Boeuf let mut epoll_helper = 3608fbc4b40SSebastien Boeuf EpollHelper::new(&self.handler.kill_evt, &self.handler.pause_evt).unwrap(); 361b1752994SBo Chen self.handler.handle_event(&mut epoll_helper, &event).ok(); 36279753949SSebastien Boeuf } signal_rxq_event(&mut self)36379753949SSebastien Boeuf pub fn signal_rxq_event(&mut self) { 36479753949SSebastien Boeuf self.handler.queue_evts[0].write(1).unwrap(); 3658fbc4b40SSebastien Boeuf let events = epoll::Events::EPOLLIN; 3668fbc4b40SSebastien Boeuf let event = epoll::Event::new(events, RX_QUEUE_EVENT as u64); 3678fbc4b40SSebastien Boeuf let mut epoll_helper = 3688fbc4b40SSebastien Boeuf EpollHelper::new(&self.handler.kill_evt, &self.handler.pause_evt).unwrap(); 369b1752994SBo Chen self.handler.handle_event(&mut epoll_helper, &event).ok(); 37079753949SSebastien Boeuf } 37179753949SSebastien Boeuf } 37279753949SSebastien Boeuf } 373