diff --git a/src/runtime-rs/crates/hypervisor/src/device/driver/virtio_vsock.rs b/src/runtime-rs/crates/hypervisor/src/device/driver/virtio_vsock.rs index 6ca887953..76ca9dabc 100644 --- a/src/runtime-rs/crates/hypervisor/src/device/driver/virtio_vsock.rs +++ b/src/runtime-rs/crates/hypervisor/src/device/driver/virtio_vsock.rs @@ -121,46 +121,53 @@ const CID_RETRY_COUNT: u32 = 50; impl VsockDevice { pub async fn new(id: String) -> Result { - let vhost_fd = OpenOptions::new() - .read(true) - .write(true) - .open(VHOST_VSOCK_DEVICE) + let (guest_cid, vhost_fd) = generate_vhost_vsock_cid() .await - .context(format!( - "failed to open {}, try to run modprobe vhost_vsock.", - VHOST_VSOCK_DEVICE - ))?; - let mut rng = rand::thread_rng(); + .context("generate vhost vsock cid failed")?; - // Try 50 times to find a context ID that is not in use. - for _ in 0..CID_RETRY_COUNT { - // First usable CID above VMADDR_CID_HOST (see vsock(7)) - let first_usable_cid = 3; - let rand_cid = rng.gen_range(first_usable_cid..=(u32::MAX)); - let guest_cid = - unsafe { vhost_vsock_set_guest_cid(vhost_fd.as_raw_fd(), &(rand_cid as u64)) }; - match guest_cid { - Ok(_) => { - return Ok(VsockDevice { - id, - config: VsockConfig { - guest_cid: rand_cid, - vhost_fd, - }, - }); - } - Err(nix::Error::EADDRINUSE) => { - // The CID is already in use. Try another one. - } - Err(err) => { - return Err(err).context("failed to set guest CID"); - } - } - } - - anyhow::bail!( - "failed to find a free vsock context ID after {} attempts", - CID_RETRY_COUNT - ); + Ok(Self { + id, + config: VsockConfig { + guest_cid, + vhost_fd, + }, + }) } } + +pub async fn generate_vhost_vsock_cid() -> Result<(u32, File)> { + let vhost_fd = OpenOptions::new() + .read(true) + .write(true) + .open(VHOST_VSOCK_DEVICE) + .await + .context(format!( + "failed to open {}, try to run modprobe vhost_vsock.", + VHOST_VSOCK_DEVICE + ))?; + let mut rng = rand::thread_rng(); + + // Try 50 times to find a context ID that is not in use. + for _ in 0..CID_RETRY_COUNT { + // First usable CID above VMADDR_CID_HOST (see vsock(7)) + let first_usable_cid = 3; + let rand_cid = rng.gen_range(first_usable_cid..=(u32::MAX)); + let guest_cid = + unsafe { vhost_vsock_set_guest_cid(vhost_fd.as_raw_fd(), &(rand_cid as u64)) }; + match guest_cid { + Ok(_) => return Ok((rand_cid, vhost_fd)), + Err(nix::Error::EADDRINUSE) => { + // The CID is already in use. Try another one. + continue; + } + Err(err) => { + return Err(err).context("failed to set guest CID"); + } + }; + } + + anyhow::bail!( + "failed to find a free vsock context ID after {} attempts", + CID_RETRY_COUNT + ); +}