mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: http_api: Accept a VFIO device FD via SCM_RIGHTS
Signed-off-by: Bo Chen <bchen@crusoe.ai> Assisted-by: Claude:Opus-4.7
This commit is contained in:
@@ -45,7 +45,7 @@ use crate::api::VmCoredump;
|
|||||||
use crate::api::http::http_endpoint::fds_helper::{attach_fds_to_cfg, attach_fds_to_cfgs};
|
use crate::api::http::http_endpoint::fds_helper::{attach_fds_to_cfg, attach_fds_to_cfgs};
|
||||||
use crate::api::http::{EndpointHandler, HttpError, error_response};
|
use crate::api::http::{EndpointHandler, HttpError, error_response};
|
||||||
use crate::api::{
|
use crate::api::{
|
||||||
AddDisk, ApiAction, ApiError, ApiRequest, NetConfig, VmAddDevice, VmAddFs,
|
AddDisk, ApiAction, ApiError, ApiRequest, DeviceConfig, NetConfig, VmAddDevice, VmAddFs,
|
||||||
VmAddGenericVhostUser, VmAddNet, VmAddPmem, VmAddUserDevice, VmAddVdpa, VmAddVsock, VmBoot,
|
VmAddGenericVhostUser, VmAddNet, VmAddPmem, VmAddUserDevice, VmAddVdpa, VmAddVsock, VmBoot,
|
||||||
VmConfig, VmCounters, VmDelete, VmNmi, VmPause, VmPowerButton, VmReboot, VmReceiveMigration,
|
VmConfig, VmCounters, VmDelete, VmNmi, VmPause, VmPowerButton, VmReboot, VmReceiveMigration,
|
||||||
VmRemoveDevice, VmResize, VmResizeDisk, VmResizeZone, VmRestore, VmResume, VmSendMigration,
|
VmRemoveDevice, VmResize, VmResizeDisk, VmResizeZone, VmRestore, VmResume, VmSendMigration,
|
||||||
@@ -115,10 +115,11 @@ mod fds_helper {
|
|||||||
|
|
||||||
mod config_with_fds_impls {
|
mod config_with_fds_impls {
|
||||||
use std::os::fd::RawFd;
|
use std::os::fd::RawFd;
|
||||||
|
use std::slice::from_ref;
|
||||||
|
|
||||||
use super::{ConfigWithFDs, ConfigWithVariableFDs};
|
use super::{ConfigWithFDs, ConfigWithVariableFDs};
|
||||||
use crate::config::RestoredNetConfig;
|
use crate::config::RestoredNetConfig;
|
||||||
use crate::vm_config::NetConfig;
|
use crate::vm_config::{DeviceConfig, NetConfig};
|
||||||
|
|
||||||
impl ConfigWithFDs for NetConfig {
|
impl ConfigWithFDs for NetConfig {
|
||||||
fn id(&self) -> Option<&str> {
|
fn id(&self) -> Option<&str> {
|
||||||
@@ -134,6 +135,24 @@ mod fds_helper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ConfigWithFDs for DeviceConfig {
|
||||||
|
fn id(&self) -> Option<&str> {
|
||||||
|
self.pci_common.id.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fds_from_http_body(&self) -> Option<&[RawFd]> {
|
||||||
|
// A DeviceConfig carries at most one FD.
|
||||||
|
self.fd.as_ref().map(from_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_fds(&mut self, fds: Option<Vec<RawFd>>) {
|
||||||
|
// The VmAddDevice PutHandler enforces `fds.len() <= 1`
|
||||||
|
// before calling into this trait, so `pop()` yields the
|
||||||
|
// single FD when present.
|
||||||
|
self.fd = fds.and_then(|mut v| v.pop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ConfigWithFDs for RestoredNetConfig {
|
impl ConfigWithFDs for RestoredNetConfig {
|
||||||
fn id(&self) -> Option<&str> {
|
fn id(&self) -> Option<&str> {
|
||||||
Some(self.id.as_str())
|
Some(self.id.as_str())
|
||||||
@@ -295,6 +314,19 @@ impl EndpointHandler for VmCreate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(ref mut devices) = vm_config.devices {
|
||||||
|
// For the VmCreate call, we do not accept FDs from the socket currently.
|
||||||
|
// This call sets all FDs to null while doing the same logging as
|
||||||
|
// similar code paths.
|
||||||
|
for cfg in devices.iter_mut() {
|
||||||
|
if let Err(e) =
|
||||||
|
attach_fds_to_cfg(vec![], cfg).map_err(error_response)
|
||||||
|
{
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match crate::api::VmCreate
|
match crate::api::VmCreate
|
||||||
.send(api_notifier, api_sender, vm_config)
|
.send(api_notifier, api_sender, vm_config)
|
||||||
.map_err(HttpError::ApiError)
|
.map_err(HttpError::ApiError)
|
||||||
@@ -417,7 +449,6 @@ vm_action_put_handler!(VmResume);
|
|||||||
vm_action_put_handler!(VmPowerButton);
|
vm_action_put_handler!(VmPowerButton);
|
||||||
vm_action_put_handler!(VmNmi);
|
vm_action_put_handler!(VmNmi);
|
||||||
|
|
||||||
vm_action_put_handler_body!(VmAddDevice);
|
|
||||||
vm_action_put_handler_body!(AddDisk);
|
vm_action_put_handler_body!(AddDisk);
|
||||||
vm_action_put_handler_body!(VmAddFs);
|
vm_action_put_handler_body!(VmAddFs);
|
||||||
vm_action_put_handler_body!(VmAddGenericVhostUser);
|
vm_action_put_handler_body!(VmAddGenericVhostUser);
|
||||||
@@ -435,6 +466,34 @@ vm_action_put_handler_body!(VmSendMigration);
|
|||||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||||
vm_action_put_handler_body!(VmCoredump);
|
vm_action_put_handler_body!(VmCoredump);
|
||||||
|
|
||||||
|
// Special handling for VFIO devices backed by an externally-opened cdev FD.
|
||||||
|
// See module description for more info.
|
||||||
|
impl PutHandler for VmAddDevice {
|
||||||
|
fn handle_request(
|
||||||
|
&'static self,
|
||||||
|
api_notifier: EventFd,
|
||||||
|
api_sender: Sender<ApiRequest>,
|
||||||
|
body: &Option<Body>,
|
||||||
|
files: Vec<File>,
|
||||||
|
) -> Result<Option<Body>, HttpError> {
|
||||||
|
if let Some(body) = body {
|
||||||
|
// A DeviceConfig is backed by at most one FD.
|
||||||
|
if files.len() > 1 {
|
||||||
|
return Err(HttpError::BadRequest);
|
||||||
|
}
|
||||||
|
let mut device_cfg: DeviceConfig = serde_json::from_slice(body.raw())?;
|
||||||
|
attach_fds_to_cfg(files, &mut device_cfg)?;
|
||||||
|
|
||||||
|
self.send(api_notifier, api_sender, device_cfg)
|
||||||
|
.map_err(HttpError::ApiError)
|
||||||
|
} else {
|
||||||
|
Err(HttpError::BadRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetHandler for VmAddDevice {}
|
||||||
|
|
||||||
// Special handling for virtio-net devices backed by network FDs.
|
// Special handling for virtio-net devices backed by network FDs.
|
||||||
// See module description for more info.
|
// See module description for more info.
|
||||||
impl PutHandler for VmAddNet {
|
impl PutHandler for VmAddNet {
|
||||||
|
|||||||
Reference in New Issue
Block a user