aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlice Wang <aliceywang@google.com>2023-10-06 14:26:41 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-10-06 14:26:41 +0000
commitcd72dc14baa41b1efb15e1358d4251d027f15142 (patch)
tree05e9477c172db38ff5f69c7ce16339cfa3f90e33
parentfe5827db39540f30157a0561621600963d6b81d2 (diff)
parentf24f8940b4d9adf6567bad9c005db2a7f636808f (diff)
downloadvirtio-drivers-cd72dc14baa41b1efb15e1358d4251d027f15142.tar.gz
Upgrade virtio-drivers to 0.7.0 am: a82211672b am: d19421a342 am: 6d401ccb50 am: f24f8940b4
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/virtio-drivers/+/2774891 Change-Id: I4511cf80dcda875251886b9240f700e1aec723ae Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp6
-rw-r--r--Cargo.toml2
-rw-r--r--Cargo.toml.orig2
-rw-r--r--METADATA8
-rw-r--r--src/device/socket/connectionmanager.rs (renamed from src/device/socket/multiconnectionmanager.rs)12
-rw-r--r--src/device/socket/mod.rs16
-rw-r--r--src/device/socket/singleconnectionmanager.rs444
-rw-r--r--src/queue.rs2
9 files changed, 28 insertions, 466 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index b5546f9..c6e71f9 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
{
"git": {
- "sha1": "94e013fd4cfb8ff5061e9fa9a4f43521b49679bb"
+ "sha1": "fd54a1b1c3d7c8bfe59c5a4f0dbe1ea981328116"
},
"path_in_vcs": ""
} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 34dcc72..3734135 100644
--- a/Android.bp
+++ b/Android.bp
@@ -22,10 +22,9 @@ license {
rust_library_rlib {
name: "libvirtio_drivers",
- // has rustc warnings
crate_name: "virtio_drivers",
cargo_env_compat: true,
- cargo_pkg_version: "0.6.0",
+ cargo_pkg_version: "0.7.0",
srcs: ["src/lib.rs"],
edition: "2018",
features: ["alloc"],
@@ -48,10 +47,9 @@ rust_library_rlib {
rust_test {
name: "virtio-drivers_test_src_lib",
- // has rustc warnings
crate_name: "virtio_drivers",
cargo_env_compat: true,
- cargo_pkg_version: "0.6.0",
+ cargo_pkg_version: "0.7.0",
srcs: ["src/lib.rs"],
test_suites: ["general-tests"],
auto_gen_config: true,
diff --git a/Cargo.toml b/Cargo.toml
index ebd37e5..ab32372 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "virtio-drivers"
-version = "0.6.0"
+version = "0.7.0"
authors = [
"Jiajie Chen <noc@jiegec.ac.cn>",
"Runji Wang <wangrunji0408@163.com>",
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 8709240..9b216f6 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "virtio-drivers"
-version = "0.6.0"
+version = "0.7.0"
license = "MIT"
authors = [
"Jiajie Chen <noc@jiegec.ac.cn>",
diff --git a/METADATA b/METADATA
index 3d38cb5..a684494 100644
--- a/METADATA
+++ b/METADATA
@@ -11,13 +11,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/virtio-drivers/virtio-drivers-0.6.0.crate"
+ value: "https://static.crates.io/crates/virtio-drivers/virtio-drivers-0.7.0.crate"
}
- version: "0.6.0"
+ version: "0.7.0"
license_type: NOTICE
last_upgrade_date {
year: 2023
- month: 7
- day: 27
+ month: 10
+ day: 6
}
}
diff --git a/src/device/socket/multiconnectionmanager.rs b/src/device/socket/connectionmanager.rs
index 430f5e8..1a6915f 100644
--- a/src/device/socket/multiconnectionmanager.rs
+++ b/src/device/socket/connectionmanager.rs
@@ -226,6 +226,18 @@ impl<H: Hal, T: Transport> VsockConnectionManager<H, T> {
Ok(bytes_read)
}
+ /// Returns the number of bytes currently available in the recv buffer.
+ pub fn recv_buffer_available_bytes(&mut self, peer: VsockAddr, src_port: u32) -> Result<usize> {
+ let (_, connection) = get_connection(&mut self.connections, peer, src_port)?;
+ Ok(connection.buffer.available())
+ }
+
+ /// Sends a credit update to the given peer.
+ pub fn update_credit(&mut self, peer: VsockAddr, src_port: u32) -> Result {
+ let (_, connection) = get_connection(&mut self.connections, peer, src_port)?;
+ self.driver.credit_update(&connection.info)
+ }
+
/// Blocks until we get some event from the vsock device.
pub fn wait_for_event(&mut self) -> Result<VsockEvent> {
loop {
diff --git a/src/device/socket/mod.rs b/src/device/socket/mod.rs
index acc7def..8d2de2b 100644
--- a/src/device/socket/mod.rs
+++ b/src/device/socket/mod.rs
@@ -2,25 +2,21 @@
//!
//! To use the driver, you should first create a [`VirtIOSocket`] instance with your VirtIO
//! transport, and then create a [`VsockConnectionManager`] wrapping it to keep track of
-//! connections. If you only want to have a single outgoing vsock connection at once, you can use
-//! [`SingleConnectionManager`] for a slightly simpler interface.
+//! connections. If you want to manage connections yourself you can use the `VirtIOSocket` directly
+//! for a lower-level interface.
//!
//! See [`VsockConnectionManager`] for a usage example.
-mod error;
#[cfg(feature = "alloc")]
-mod multiconnectionmanager;
+mod connectionmanager;
+mod error;
mod protocol;
#[cfg(feature = "alloc")]
-mod singleconnectionmanager;
-#[cfg(feature = "alloc")]
mod vsock;
-pub use error::SocketError;
#[cfg(feature = "alloc")]
-pub use multiconnectionmanager::VsockConnectionManager;
+pub use connectionmanager::VsockConnectionManager;
+pub use error::SocketError;
pub use protocol::{VsockAddr, VMADDR_CID_HOST};
#[cfg(feature = "alloc")]
-pub use singleconnectionmanager::SingleConnectionManager;
-#[cfg(feature = "alloc")]
pub use vsock::{DisconnectReason, VirtIOSocket, VsockEvent, VsockEventType};
diff --git a/src/device/socket/singleconnectionmanager.rs b/src/device/socket/singleconnectionmanager.rs
deleted file mode 100644
index b5b21e4..0000000
--- a/src/device/socket/singleconnectionmanager.rs
+++ /dev/null
@@ -1,444 +0,0 @@
-use super::{
- protocol::VsockAddr, vsock::ConnectionInfo, SocketError, VirtIOSocket, VsockEvent,
- VsockEventType,
-};
-use crate::{transport::Transport, Hal, Result};
-use core::hint::spin_loop;
-use log::debug;
-
-/// A higher level interface for VirtIO socket (vsock) devices.
-///
-/// This can only keep track of a single vsock connection. If you want to support multiple
-/// simultaneous connections, try [`VsockConnectionManager`](super::VsockConnectionManager).
-pub struct SingleConnectionManager<H: Hal, T: Transport> {
- driver: VirtIOSocket<H, T>,
- connection_info: Option<ConnectionInfo>,
-}
-
-impl<H: Hal, T: Transport> SingleConnectionManager<H, T> {
- /// Construct a new connection manager wrapping the given low-level VirtIO socket driver.
- pub fn new(driver: VirtIOSocket<H, T>) -> Self {
- Self {
- driver,
- connection_info: None,
- }
- }
-
- /// Returns the CID which has been assigned to this guest.
- pub fn guest_cid(&self) -> u64 {
- self.driver.guest_cid()
- }
-
- /// Sends a request to connect to the given destination.
- ///
- /// This returns as soon as the request is sent; you should wait until `poll_recv` returns a
- /// `VsockEventType::Connected` event indicating that the peer has accepted the connection
- /// before sending data.
- pub fn connect(&mut self, destination: VsockAddr, src_port: u32) -> Result {
- if self.connection_info.is_some() {
- return Err(SocketError::ConnectionExists.into());
- }
-
- let new_connection_info = ConnectionInfo::new(destination, src_port);
-
- self.driver.connect(&new_connection_info)?;
- debug!("Connection requested: {:?}", new_connection_info);
- self.connection_info = Some(new_connection_info);
- Ok(())
- }
-
- /// Sends the buffer to the destination.
- pub fn send(&mut self, buffer: &[u8]) -> Result {
- let connection_info = self
- .connection_info
- .as_mut()
- .ok_or(SocketError::NotConnected)?;
- connection_info.buf_alloc = 0;
- self.driver.send(buffer, connection_info)
- }
-
- /// Polls the vsock device to receive data or other updates.
- ///
- /// A buffer must be provided to put the data in if there is some to
- /// receive.
- pub fn poll_recv(&mut self, buffer: &mut [u8]) -> Result<Option<VsockEvent>> {
- let Some(connection_info) = &mut self.connection_info else {
- return Err(SocketError::NotConnected.into());
- };
-
- // Tell the peer that we have space to receive some data.
- connection_info.buf_alloc = buffer.len() as u32;
- self.driver.credit_update(connection_info)?;
-
- self.poll_rx_queue(buffer)
- }
-
- /// Blocks until we get some event from the vsock device.
- ///
- /// A buffer must be provided to put the data in if there is some to
- /// receive.
- pub fn wait_for_recv(&mut self, buffer: &mut [u8]) -> Result<VsockEvent> {
- loop {
- if let Some(event) = self.poll_recv(buffer)? {
- return Ok(event);
- } else {
- spin_loop();
- }
- }
- }
-
- fn poll_rx_queue(&mut self, body: &mut [u8]) -> Result<Option<VsockEvent>> {
- let guest_cid = self.driver.guest_cid();
- let self_connection_info = &mut self.connection_info;
-
- self.driver.poll(|event, borrowed_body| {
- let Some(connection_info) = self_connection_info else {
- return Ok(None);
- };
-
- // Skip packets which don't match our current connection.
- if !event.matches_connection(connection_info, guest_cid) {
- debug!(
- "Skipping {:?} as connection is {:?}",
- event, connection_info
- );
- return Ok(None);
- }
-
- // Update stored connection info.
- connection_info.update_for_event(&event);
-
- match event.event_type {
- VsockEventType::ConnectionRequest => {
- // TODO: Send Rst or handle incoming connections.
- }
- VsockEventType::Connected => {}
- VsockEventType::Disconnected { .. } => {
- *self_connection_info = None;
- }
- VsockEventType::Received { length } => {
- body.get_mut(0..length)
- .ok_or(SocketError::OutputBufferTooShort(length))?
- .copy_from_slice(borrowed_body);
- connection_info.done_forwarding(length);
- }
- VsockEventType::CreditRequest => {
- // No point sending a credit update until `poll_recv` is called with a buffer,
- // as otherwise buf_alloc would just be 0 anyway.
- }
- VsockEventType::CreditUpdate => {}
- }
-
- Ok(Some(event))
- })
- }
-
- /// Requests to shut down the connection cleanly.
- ///
- /// This returns as soon as the request is sent; you should wait until `poll_recv` returns a
- /// `VsockEventType::Disconnected` event if you want to know that the peer has acknowledged the
- /// shutdown.
- pub fn shutdown(&mut self) -> Result {
- let connection_info = self
- .connection_info
- .as_mut()
- .ok_or(SocketError::NotConnected)?;
- connection_info.buf_alloc = 0;
-
- self.driver.shutdown(connection_info)
- }
-
- /// Forcibly closes the connection without waiting for the peer.
- pub fn force_close(&mut self) -> Result {
- let connection_info = self
- .connection_info
- .as_mut()
- .ok_or(SocketError::NotConnected)?;
- connection_info.buf_alloc = 0;
-
- self.driver.force_close(connection_info)?;
- self.connection_info = None;
- Ok(())
- }
-
- /// Blocks until the peer either accepts our connection request (with a
- /// `VIRTIO_VSOCK_OP_RESPONSE`) or rejects it (with a
- /// `VIRTIO_VSOCK_OP_RST`).
- pub fn wait_for_connect(&mut self) -> Result {
- loop {
- match self.wait_for_recv(&mut [])?.event_type {
- VsockEventType::Connected => return Ok(()),
- VsockEventType::Disconnected { .. } => {
- return Err(SocketError::ConnectionFailed.into())
- }
- VsockEventType::Received { .. } => return Err(SocketError::InvalidOperation.into()),
- VsockEventType::ConnectionRequest
- | VsockEventType::CreditRequest
- | VsockEventType::CreditUpdate => {}
- }
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::{
- device::socket::{
- protocol::{SocketType, VirtioVsockConfig, VirtioVsockHdr, VirtioVsockOp},
- vsock::{VsockBufferStatus, QUEUE_SIZE, RX_QUEUE_IDX, TX_QUEUE_IDX},
- },
- hal::fake::FakeHal,
- transport::{
- fake::{FakeTransport, QueueStatus, State},
- DeviceType,
- },
- volatile::ReadOnly,
- };
- use alloc::{sync::Arc, vec};
- use core::{mem::size_of, ptr::NonNull};
- use std::{sync::Mutex, thread};
- use zerocopy::{AsBytes, FromBytes};
-
- #[test]
- fn send_recv() {
- let host_cid = 2;
- let guest_cid = 66;
- let host_port = 1234;
- let guest_port = 4321;
- let host_address = VsockAddr {
- cid: host_cid,
- port: host_port,
- };
- let hello_from_guest = "Hello from guest";
- let hello_from_host = "Hello from host";
-
- let mut config_space = VirtioVsockConfig {
- guest_cid_low: ReadOnly::new(66),
- guest_cid_high: ReadOnly::new(0),
- };
- let state = Arc::new(Mutex::new(State {
- queues: vec![
- QueueStatus::default(),
- QueueStatus::default(),
- QueueStatus::default(),
- ],
- ..Default::default()
- }));
- let transport = FakeTransport {
- device_type: DeviceType::Socket,
- max_queue_size: 32,
- device_features: 0,
- config_space: NonNull::from(&mut config_space),
- state: state.clone(),
- };
- let mut socket = SingleConnectionManager::new(
- VirtIOSocket::<FakeHal, FakeTransport<VirtioVsockConfig>>::new(transport).unwrap(),
- );
-
- // Start a thread to simulate the device.
- let handle = thread::spawn(move || {
- // Wait for connection request.
- State::wait_until_queue_notified(&state, TX_QUEUE_IDX);
- assert_eq!(
- VirtioVsockHdr::read_from(
- state
- .lock()
- .unwrap()
- .read_from_queue::<QUEUE_SIZE>(TX_QUEUE_IDX)
- .as_slice()
- )
- .unwrap(),
- VirtioVsockHdr {
- op: VirtioVsockOp::Request.into(),
- src_cid: guest_cid.into(),
- dst_cid: host_cid.into(),
- src_port: guest_port.into(),
- dst_port: host_port.into(),
- len: 0.into(),
- socket_type: SocketType::Stream.into(),
- flags: 0.into(),
- buf_alloc: 0.into(),
- fwd_cnt: 0.into(),
- }
- );
-
- // Accept connection and give the peer enough credit to send the message.
- state.lock().unwrap().write_to_queue::<QUEUE_SIZE>(
- RX_QUEUE_IDX,
- VirtioVsockHdr {
- op: VirtioVsockOp::Response.into(),
- src_cid: host_cid.into(),
- dst_cid: guest_cid.into(),
- src_port: host_port.into(),
- dst_port: guest_port.into(),
- len: 0.into(),
- socket_type: SocketType::Stream.into(),
- flags: 0.into(),
- buf_alloc: 50.into(),
- fwd_cnt: 0.into(),
- }
- .as_bytes(),
- );
-
- // Expect a credit update.
- State::wait_until_queue_notified(&state, TX_QUEUE_IDX);
- assert_eq!(
- VirtioVsockHdr::read_from(
- state
- .lock()
- .unwrap()
- .read_from_queue::<QUEUE_SIZE>(TX_QUEUE_IDX)
- .as_slice()
- )
- .unwrap(),
- VirtioVsockHdr {
- op: VirtioVsockOp::CreditUpdate.into(),
- src_cid: guest_cid.into(),
- dst_cid: host_cid.into(),
- src_port: guest_port.into(),
- dst_port: host_port.into(),
- len: 0.into(),
- socket_type: SocketType::Stream.into(),
- flags: 0.into(),
- buf_alloc: 0.into(),
- fwd_cnt: 0.into(),
- }
- );
-
- // Expect the guest to send some data.
- State::wait_until_queue_notified(&state, TX_QUEUE_IDX);
- let request = state
- .lock()
- .unwrap()
- .read_from_queue::<QUEUE_SIZE>(TX_QUEUE_IDX);
- assert_eq!(
- request.len(),
- size_of::<VirtioVsockHdr>() + hello_from_guest.len()
- );
- assert_eq!(
- VirtioVsockHdr::read_from_prefix(request.as_slice()).unwrap(),
- VirtioVsockHdr {
- op: VirtioVsockOp::Rw.into(),
- src_cid: guest_cid.into(),
- dst_cid: host_cid.into(),
- src_port: guest_port.into(),
- dst_port: host_port.into(),
- len: (hello_from_guest.len() as u32).into(),
- socket_type: SocketType::Stream.into(),
- flags: 0.into(),
- buf_alloc: 0.into(),
- fwd_cnt: 0.into(),
- }
- );
- assert_eq!(
- &request[size_of::<VirtioVsockHdr>()..],
- hello_from_guest.as_bytes()
- );
-
- // Send a response.
- let mut response = vec![0; size_of::<VirtioVsockHdr>() + hello_from_host.len()];
- VirtioVsockHdr {
- op: VirtioVsockOp::Rw.into(),
- src_cid: host_cid.into(),
- dst_cid: guest_cid.into(),
- src_port: host_port.into(),
- dst_port: guest_port.into(),
- len: (hello_from_host.len() as u32).into(),
- socket_type: SocketType::Stream.into(),
- flags: 0.into(),
- buf_alloc: 50.into(),
- fwd_cnt: (hello_from_guest.len() as u32).into(),
- }
- .write_to_prefix(response.as_mut_slice());
- response[size_of::<VirtioVsockHdr>()..].copy_from_slice(hello_from_host.as_bytes());
- state
- .lock()
- .unwrap()
- .write_to_queue::<QUEUE_SIZE>(RX_QUEUE_IDX, &response);
-
- // Expect a credit update.
- State::wait_until_queue_notified(&state, TX_QUEUE_IDX);
- assert_eq!(
- VirtioVsockHdr::read_from(
- state
- .lock()
- .unwrap()
- .read_from_queue::<QUEUE_SIZE>(TX_QUEUE_IDX)
- .as_slice()
- )
- .unwrap(),
- VirtioVsockHdr {
- op: VirtioVsockOp::CreditUpdate.into(),
- src_cid: guest_cid.into(),
- dst_cid: host_cid.into(),
- src_port: guest_port.into(),
- dst_port: host_port.into(),
- len: 0.into(),
- socket_type: SocketType::Stream.into(),
- flags: 0.into(),
- buf_alloc: 64.into(),
- fwd_cnt: 0.into(),
- }
- );
-
- // Expect a shutdown.
- State::wait_until_queue_notified(&state, TX_QUEUE_IDX);
- assert_eq!(
- VirtioVsockHdr::read_from(
- state
- .lock()
- .unwrap()
- .read_from_queue::<QUEUE_SIZE>(TX_QUEUE_IDX)
- .as_slice()
- )
- .unwrap(),
- VirtioVsockHdr {
- op: VirtioVsockOp::Shutdown.into(),
- src_cid: guest_cid.into(),
- dst_cid: host_cid.into(),
- src_port: guest_port.into(),
- dst_port: host_port.into(),
- len: 0.into(),
- socket_type: SocketType::Stream.into(),
- flags: 0.into(),
- buf_alloc: 0.into(),
- fwd_cnt: (hello_from_host.len() as u32).into(),
- }
- );
- });
-
- socket.connect(host_address, guest_port).unwrap();
- socket.wait_for_connect().unwrap();
- socket.send(hello_from_guest.as_bytes()).unwrap();
- let mut buffer = [0u8; 64];
- let event = socket.wait_for_recv(&mut buffer).unwrap();
- assert_eq!(
- event,
- VsockEvent {
- source: VsockAddr {
- cid: host_cid,
- port: host_port,
- },
- destination: VsockAddr {
- cid: guest_cid,
- port: guest_port,
- },
- event_type: VsockEventType::Received {
- length: hello_from_host.len()
- },
- buffer_status: VsockBufferStatus {
- buffer_allocation: 50,
- forward_count: hello_from_guest.len() as u32,
- },
- }
- );
- assert_eq!(
- &buffer[0..hello_from_host.len()],
- hello_from_host.as_bytes()
- );
- socket.shutdown().unwrap();
-
- handle.join().unwrap();
- }
-}
diff --git a/src/queue.rs b/src/queue.rs
index dcafcbc..3257b35 100644
--- a/src/queue.rs
+++ b/src/queue.rs
@@ -944,7 +944,7 @@ mod tests {
transport::{
fake::{FakeTransport, QueueStatus, State},
mmio::{MmioTransport, VirtIOHeader, MODERN_VERSION},
- DeviceStatus, DeviceType,
+ DeviceType,
},
};
use core::ptr::NonNull;