Skip to content

Commit

Permalink
Merge pull request #136 from rcore-os/shutdown
Browse files Browse the repository at this point in the history
 Allow vsock stream shutdown hints to be specified
  • Loading branch information
qwandor authored Jun 5, 2024
2 parents 3a9a69c + e5f9868 commit 9a467d7
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 7 deletions.
9 changes: 6 additions & 3 deletions src/device/socket/connectionmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,8 @@ impl<H: Hal, T: Transport> VsockConnectionManager<H, T> {
}
}

/// Requests to shut down the connection cleanly.
/// Requests to shut down the connection cleanly, telling the peer that we won't send or receive
/// any more data.
///
/// This returns as soon as the request is sent; you should wait until `poll` returns a
/// `VsockEventType::Disconnected` event if you want to know that the peer has acknowledged the
Expand Down Expand Up @@ -389,7 +390,9 @@ mod tests {
use super::*;
use crate::{
device::socket::{
protocol::{SocketType, VirtioVsockConfig, VirtioVsockHdr, VirtioVsockOp},
protocol::{
SocketType, StreamShutdown, VirtioVsockConfig, VirtioVsockHdr, VirtioVsockOp,
},
vsock::{VsockBufferStatus, QUEUE_SIZE, RX_QUEUE_IDX, TX_QUEUE_IDX},
},
hal::fake::FakeHal,
Expand Down Expand Up @@ -557,7 +560,7 @@ mod tests {
dst_port: host_port.into(),
len: 0.into(),
socket_type: SocketType::Stream.into(),
flags: 0.into(),
flags: (StreamShutdown::SEND | StreamShutdown::RECEIVE).into(),
buf_alloc: 1024.into(),
fwd_cnt: (hello_from_host.len() as u32).into(),
}
Expand Down
19 changes: 18 additions & 1 deletion src/device/socket/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub struct VirtioVsockConfig {
}

/// The message header for data packets sent on the tx/rx queues
#[repr(packed)]
#[repr(C, packed)]
#[derive(AsBytes, Clone, Copy, Debug, Eq, FromBytes, FromZeroes, PartialEq)]
pub struct VirtioVsockHdr {
pub src_cid: U64<LittleEndian>,
Expand Down Expand Up @@ -214,3 +214,20 @@ bitflags! {
const NOTIFICATION_DATA = 1 << 38;
}
}

bitflags! {
/// Flags sent with a shutdown request to hint that the peer won't send or receive more data.
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub struct StreamShutdown: u32 {
/// The peer will not receive any more data.
const RECEIVE = 1 << 0;
/// The peer will not send any more data.
const SEND = 1 << 1;
}
}

impl From<StreamShutdown> for U32<LittleEndian> {
fn from(flags: StreamShutdown) -> Self {
flags.bits().into()
}
}
27 changes: 24 additions & 3 deletions src/device/socket/vsock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
#![deny(unsafe_op_in_unsafe_fn)]

use super::error::SocketError;
use super::protocol::{Feature, VirtioVsockConfig, VirtioVsockHdr, VirtioVsockOp, VsockAddr};
use super::protocol::{
Feature, StreamShutdown, VirtioVsockConfig, VirtioVsockHdr, VirtioVsockOp, VsockAddr,
};
use crate::hal::Hal;
use crate::queue::VirtQueue;
use crate::transport::Transport;
Expand Down Expand Up @@ -409,19 +411,38 @@ impl<H: Hal, T: Transport> VirtIOSocket<H, T> {
result
}

/// Requests to shut down the connection cleanly.
/// Requests to shut down the connection cleanly, sending hints about whether we will send or
/// receive more data.
///
/// This returns as soon as the request is sent; you should wait until `poll` returns a
/// `VsockEventType::Disconnected` event if you want to know that the peer has acknowledged the
/// shutdown.
pub fn shutdown(&mut self, connection_info: &ConnectionInfo) -> Result {
pub fn shutdown_with_hints(
&mut self,
connection_info: &ConnectionInfo,
hints: StreamShutdown,
) -> Result {
let header = VirtioVsockHdr {
op: VirtioVsockOp::Shutdown.into(),
flags: hints.into(),
..connection_info.new_header(self.guest_cid)
};
self.send_packet_to_tx_queue(&header, &[])
}

/// Requests to shut down the connection cleanly, telling the peer that we won't send or receive
/// any more data.
///
/// This returns as soon as the request is sent; you should wait until `poll` returns a
/// `VsockEventType::Disconnected` event if you want to know that the peer has acknowledged the
/// shutdown.
pub fn shutdown(&mut self, connection_info: &ConnectionInfo) -> Result {
self.shutdown_with_hints(
connection_info,
StreamShutdown::SEND | StreamShutdown::RECEIVE,
)
}

/// Forcibly closes the connection without waiting for the peer.
pub fn force_close(&mut self, connection_info: &ConnectionInfo) -> Result {
let header = VirtioVsockHdr {
Expand Down

0 comments on commit 9a467d7

Please sign in to comment.