diff --git a/docs/usage.md b/docs/usage.md index 8b43af2..cf8d528 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -166,10 +166,14 @@ facilitate communication between the two. Multiple instances of a `virtio-vsock` device can be specified, yet port numbers for these sockets must be unique. +There are two modes - `listen` and `connect`. + #### Arguments - `port`: `AF_VSOCK` port to connect to on the guest. - `socketURL`: Path to the UNIX socket on the host. +- `listen`: Enable guest to host communication. (Default mode) +- `connect`: Enable host to guest communication. #### Example @@ -180,6 +184,12 @@ This adds a virtio-vsock device to a virtual machine, and will forward all guest --device virtio-vsock,port=1024,socketURL=/Users/user/vm-socket.sock ``` +To enable host-initiated connections to the guest: + +``` +--device virtio-vsock,port=1024,socketURL=/Users/user/vm-socket.sock,connect +``` + ### File Sharing The `virtio-fs` option allows a guest to share a file system directory with a host. The directory can be mounted diff --git a/src/virtio.rs b/src/virtio.rs index 7032e08..9a6e337 100644 --- a/src/virtio.rs +++ b/src/virtio.rs @@ -50,7 +50,8 @@ extern "C" { disk_format: u32, read_only: bool, ) -> i32; - fn krun_add_vsock_port(ctx_id: u32, port: u32, c_filepath: *const c_char) -> i32; + fn krun_add_vsock_port2(ctx_id: u32, port: u32, c_filepath: *const c_char, listen: bool) + -> i32; fn krun_add_virtiofs(ctx_id: u32, c_tag: *const c_char, c_path: *const c_char) -> i32; fn krun_set_console_output(ctx_id: u32, c_filepath: *const c_char) -> i32; fn krun_add_net_unixgram( @@ -286,12 +287,25 @@ impl FromStr for VsockConfig { vsock_config.socket_url = PathBuf::from_str(socket_url.as_str()) .context("socketURL argument not a valid path")?; + if let Some(v) = args.remove("connect") { + if !v.is_empty() { + return Err(anyhow!(format!( + "unexpected value for virtio-vsock argument: connect={v}" + ))); + } + vsock_config.action = VsockAction::from_str("connect")? + } if let Some(v) = args.remove("listen") { if !v.is_empty() { return Err(anyhow!(format!( "unexpected value for virtio-vsock argument: listen={v}" ))); } + if vsock_config.action == VsockAction::Connect { + return Err(anyhow!( + "virtio-vsock argument \"listen\" and \"connect\" are mutually exclusive and cannot be used together." + )); + } vsock_config.action = VsockAction::from_str("listen")? } @@ -307,7 +321,14 @@ impl KrunContextSet for VsockConfig { unsafe fn krun_ctx_set(&self, id: u32) -> Result<(), anyhow::Error> { let path_cstr = path_to_cstring(&self.socket_url)?; - if krun_add_vsock_port(id, self.port, path_cstr.as_ptr()) < 0 { + // libkrun's `listen` parameter means "guest expects connections from host" which is true when VsockAction::Connect. + if krun_add_vsock_port2( + id, + self.port, + path_cstr.as_ptr(), + self.action == VsockAction::Connect, + ) < 0 + { return Err(anyhow!(format!( "unable to add vsock port {} for path {}", self.port, @@ -322,8 +343,11 @@ impl KrunContextSet for VsockConfig { /// virtio-vsock action. #[derive(Clone, Debug, Default, PartialEq)] pub enum VsockAction { + /// Host listens for guest-initiated connections (default). #[default] Listen, + /// Host connects to guest; guest listens for host-initiated connections. + Connect, } impl FromStr for VsockAction { @@ -334,6 +358,7 @@ impl FromStr for VsockAction { match &s[..] { "listen" => Ok(Self::Listen), + "connect" => Ok(Self::Connect), _ => Err(anyhow!("invalid vsock action")), } }