xref: /cloud-hypervisor/virtio-devices/src/vsock/mod.rs (revision 2bc8d51a60821504abdbd52f9ca7873c31ccdac2)
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