mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-22 11:22:26 +00:00
vm-virtio: Add connection handshake to vsock
This patch has been cherry-picked from the Firecracker tree. The reference commit is 1db04ccc69862f30b7814f30024d112d1b86b80e. Changed the host-initiated vsock connection protocol to include a trivial handshake. The new protocol looks like this: - [host] CONNECT <port><LF> - [guest/success] OK <assigned_host_port><LF> On connection failure, the host host connection is reset without any accompanying message, as before. This allows host software to more easily detect connection failures, for instance when attempting to connect to a guest server that may have not yet started listening for client connections. Signed-off-by: Dan Horobeanu <dhr@amazon.com> Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
5c4e1726f8
commit
9701fde209
@ -557,7 +557,7 @@ where
|
||||
/// Raw data can either be sent straight to the host stream, or to our TX buffer, if the
|
||||
/// former fails.
|
||||
///
|
||||
fn send_bytes(&mut self, buf: &[u8]) -> Result<()> {
|
||||
pub fn send_bytes(&mut self, buf: &[u8]) -> Result<()> {
|
||||
// If there is data in the TX buffer, that means we're already registered for EPOLLOUT
|
||||
// events on the underlying stream. Therefore, there's no point in attempting a write
|
||||
// at this point. `self.notify()` will get called when EPOLLOUT arrives, and it will
|
||||
@ -592,6 +592,11 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Return the connections state.
|
||||
pub fn state(&self) -> ConnState {
|
||||
self.state
|
||||
}
|
||||
|
||||
/// Check if the credit information the peer has last received from us is outdated.
|
||||
///
|
||||
fn peer_needs_credit_update(&self) -> bool {
|
||||
|
@ -38,7 +38,7 @@ type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// A vsock connection state.
|
||||
///
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum ConnState {
|
||||
/// The connection has been initiated by the host end, but is yet to be confirmed by the guest.
|
||||
LocalInit,
|
||||
|
@ -36,6 +36,7 @@ use std::io::Read;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::os::unix::net::{UnixListener, UnixStream};
|
||||
|
||||
use super::super::csm::ConnState;
|
||||
use super::super::defs::uapi;
|
||||
use super::super::packet::VsockPacket;
|
||||
use super::super::{
|
||||
@ -652,9 +653,20 @@ impl VsockMuxer {
|
||||
if let Some(conn) = self.conn_map.get_mut(&key) {
|
||||
let had_rx = conn.has_pending_rx();
|
||||
let was_expiring = conn.will_expire();
|
||||
let prev_state = conn.state();
|
||||
|
||||
mut_fn(conn);
|
||||
|
||||
// If this is a host-initiated connection that has just become established, we'll have
|
||||
// to send an ack message to the host end.
|
||||
if prev_state == ConnState::LocalInit && conn.state() == ConnState::Established {
|
||||
conn.send_bytes(format!("OK {}\n", key.local_port).as_bytes())
|
||||
.unwrap_or_else(|err| {
|
||||
conn.kill();
|
||||
warn!("vsock: unable to ack host connection: {:?}", err);
|
||||
});
|
||||
}
|
||||
|
||||
// If the connection wasn't previously scheduled for RX, add it to our RX queue.
|
||||
if !had_rx && conn.has_pending_rx() {
|
||||
self.rxq.push(MuxerRx::ConnRx(key));
|
||||
@ -917,6 +929,10 @@ mod tests {
|
||||
self.init_pkt(local_port, peer_port, uapi::VSOCK_OP_RESPONSE);
|
||||
self.send();
|
||||
|
||||
let mut buf = vec![0u8; 32];
|
||||
let len = stream.read(&mut buf[..]).unwrap();
|
||||
assert_eq!(&buf[..len], format!("OK {}\n", local_port).as_bytes());
|
||||
|
||||
(stream, local_port)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user