runtime-rs: introduce a new function generate_vhost_vsock_cid.

Introduce a new function generate_vhost_vsock_cid to generate
a guest CID and set guest CID for vsock fd.
Also this commit wouldn't introduce functional change and it's
just splited from the previous VsockDevice::new().

Fixes: #8474

Signed-off-by: alex.lyn <alex.lyn@antgroup.com>
This commit is contained in:
alex.lyn 2023-11-27 15:06:58 +08:00
parent 231b9dfd9d
commit eb90962b27

View File

@ -121,46 +121,53 @@ const CID_RETRY_COUNT: u32 = 50;
impl VsockDevice {
pub async fn new(id: String) -> Result<Self> {
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
);
}