// Copyright 2019 Intel Corporation. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // // Portions Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the THIRD-PARTY file. mod csm; mod device; mod packet; mod unix; pub use self::device::Vsock; pub use self::unix::VsockUnixBackend; pub use self::unix::VsockUnixError; use std::os::unix::io::RawFd; use packet::VsockPacket; mod defs { /// Max vsock packet data/buffer size. pub const MAX_PKT_BUF_SIZE: usize = 64 * 1024; pub mod uapi { /// Vsock packet operation IDs. /// Defined in `/include/uapi/linux/virtio_vsock.h`. /// /// Connection request. pub const VSOCK_OP_REQUEST: u16 = 1; /// Connection response. pub const VSOCK_OP_RESPONSE: u16 = 2; /// Connection reset. pub const VSOCK_OP_RST: u16 = 3; /// Connection clean shutdown. pub const VSOCK_OP_SHUTDOWN: u16 = 4; /// Connection data (read/write). pub const VSOCK_OP_RW: u16 = 5; /// Flow control credit update. pub const VSOCK_OP_CREDIT_UPDATE: u16 = 6; /// Flow control credit update request. pub const VSOCK_OP_CREDIT_REQUEST: u16 = 7; /// Vsock packet flags. /// Defined in `/include/uapi/linux/virtio_vsock.h`. /// /// Valid with a VSOCK_OP_SHUTDOWN packet: the packet sender will receive no more data. pub const VSOCK_FLAGS_SHUTDOWN_RCV: u32 = 1; /// Valid with a VSOCK_OP_SHUTDOWN packet: the packet sender will send no more data. pub const VSOCK_FLAGS_SHUTDOWN_SEND: u32 = 2; /// Vsock packet type. /// Defined in `/include/uapi/linux/virtio_vsock.h`. /// /// Stream / connection-oriented packet (the only currently valid type). pub const VSOCK_TYPE_STREAM: u16 = 1; pub const VSOCK_HOST_CID: u64 = 2; } } #[derive(Debug)] pub enum VsockError { /// The vsock data/buffer virtio descriptor length is smaller than expected. BufDescTooSmall, /// The vsock data/buffer virtio descriptor is expected, but missing. BufDescMissing, /// Chained GuestMemory error. GuestMemory, /// Bounds check failed on guest memory pointer. GuestMemoryBounds, /// The vsock header descriptor length is too small. HdrDescTooSmall(u32), /// The vsock header `len` field holds an invalid value. InvalidPktLen(u32), /// A data fetch was attempted when no data was available. NoData, /// A data buffer was expected for the provided packet, but it is missing. PktBufMissing, /// Encountered an unexpected write-only virtio descriptor. UnreadableDescriptor, /// Encountered an unexpected read-only virtio descriptor. UnwritableDescriptor, } type Result = std::result::Result; /// A passive, event-driven object, that needs to be notified whenever an epoll-able event occurs. /// An event-polling control loop will use `get_polled_fd()` and `get_polled_evset()` to query /// the listener for the file descriptor and the set of events it's interested in. When such an /// event occurs, the control loop will route the event to the listener via `notify()`. /// pub trait VsockEpollListener { /// Get the file descriptor the listener needs polled. fn get_polled_fd(&self) -> RawFd; /// Get the set of events for which the listener wants to be notified. fn get_polled_evset(&self) -> epoll::Events; /// Notify the listener that one ore more events have occurred. fn notify(&mut self, evset: epoll::Events); } /// Any channel that handles vsock packet traffic: sending and receiving packets. Since we're /// implementing the device model here, our responsibility is to always process the sending of /// packets (i.e. the TX queue). So, any locally generated data, addressed to the driver (e.g. /// a connection response or RST), will have to be queued, until we get to processing the RX queue. /// /// Note: `recv_pkt()` and `send_pkt()` are named analogous to `Read::read()` and `Write::write()`, /// respectively. I.e. /// - `recv_pkt(&mut pkt)` will read data from the channel, and place it into `pkt`; and /// - `send_pkt(&pkt)` will fetch data from `pkt`, and place it into the channel. pub trait VsockChannel { /// Read/receive an incoming packet from the channel. fn recv_pkt(&mut self, pkt: &mut VsockPacket) -> Result<()>; /// Write/send a packet through the channel. fn send_pkt(&mut self, pkt: &VsockPacket) -> Result<()>; /// Checks whether there is pending incoming data inside the channel, meaning that a subsequent /// call to `recv_pkt()` won't fail. fn has_pending_rx(&self) -> bool; } /// The vsock backend, which is basically an epoll-event-driven vsock channel, that needs to be /// sendable through a mpsc channel (the latter due to how `vmm::EpollContext` works). /// Currently, the only implementation we have is `crate::virtio::unix::muxer::VsockMuxer`, which /// translates guest-side vsock connections to host-side Unix domain socket connections. pub trait VsockBackend: VsockChannel + VsockEpollListener + Send {}