2019-09-04 19:49:55 +00:00
|
|
|
// 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.
|
|
|
|
|
2019-09-04 20:17:20 +00:00
|
|
|
mod csm;
|
2019-09-04 19:49:55 +00:00
|
|
|
mod device;
|
2019-09-04 20:17:20 +00:00
|
|
|
mod packet;
|
2019-09-04 20:26:06 +00:00
|
|
|
mod unix;
|
2019-09-04 19:49:55 +00:00
|
|
|
|
|
|
|
pub use self::device::Vsock;
|
2019-09-04 20:17:20 +00:00
|
|
|
|
|
|
|
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<T> = std::result::Result<T, VsockError>;
|
|
|
|
|
|
|
|
/// 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 {}
|