mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: config: Reject rate limiting with vhost_user
Rate limiting is implemented in the virtio device layer and does not apply to vhost-user devices which delegate I/O handling to an external process. Add validation to reject configurations where vhost_user is enabled along with rate limiting options (bw_size, ops_size, or rate_limit_group) for both disk and network devices. This prevents users from mistakenly configuring rate limiting that would be silently ignored when using vhost-user backends. Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit is contained in:
@@ -348,6 +348,9 @@ pub enum ValidationError {
|
|||||||
/// Invalid rate-limiter group
|
/// Invalid rate-limiter group
|
||||||
#[error("Invalid rate-limiter group")]
|
#[error("Invalid rate-limiter group")]
|
||||||
InvalidRateLimiterGroup,
|
InvalidRateLimiterGroup,
|
||||||
|
/// Rate limiting is not supported with vhost-user
|
||||||
|
#[error("Rate limiting is not supported with vhost-user")]
|
||||||
|
VhostUserRateLimiterNotSupported,
|
||||||
/// The specified I/O port was invalid. It should be provided in hex, such as `0xe9`.
|
/// The specified I/O port was invalid. It should be provided in hex, such as `0xe9`.
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
#[error("The IO port was not properly provided in hex or a `0x` prefix is missing: {0}")]
|
#[error("The IO port was not properly provided in hex or a `0x` prefix is missing: {0}")]
|
||||||
@@ -1480,6 +1483,14 @@ impl DiskConfig {
|
|||||||
return Err(ValidationError::IommuNotSupported);
|
return Err(ValidationError::IommuNotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.vhost_user && self.rate_limiter_config.is_some() {
|
||||||
|
return Err(ValidationError::VhostUserRateLimiterNotSupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.vhost_user && self.rate_limit_group.is_some() {
|
||||||
|
return Err(ValidationError::VhostUserRateLimiterNotSupported);
|
||||||
|
}
|
||||||
|
|
||||||
if self.rate_limiter_config.is_some() && self.rate_limit_group.is_some() {
|
if self.rate_limiter_config.is_some() && self.rate_limit_group.is_some() {
|
||||||
return Err(ValidationError::InvalidRateLimiterGroup);
|
return Err(ValidationError::InvalidRateLimiterGroup);
|
||||||
}
|
}
|
||||||
@@ -1709,6 +1720,10 @@ impl NetConfig {
|
|||||||
return Err(ValidationError::IommuNotSupported);
|
return Err(ValidationError::IommuNotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.vhost_user && self.rate_limiter_config.is_some() {
|
||||||
|
return Err(ValidationError::VhostUserRateLimiterNotSupported);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(mtu) = self.mtu
|
if let Some(mtu) = self.mtu
|
||||||
&& mtu < virtio_devices::net::MIN_MTU
|
&& mtu < virtio_devices::net::MIN_MTU
|
||||||
{
|
{
|
||||||
@@ -2913,6 +2928,11 @@ impl VmConfig {
|
|||||||
if disk.vhost_user && disk.vhost_socket.is_none() {
|
if disk.vhost_user && disk.vhost_socket.is_none() {
|
||||||
return Err(ValidationError::VhostUserMissingSocket);
|
return Err(ValidationError::VhostUserMissingSocket);
|
||||||
}
|
}
|
||||||
|
if disk.vhost_user
|
||||||
|
&& (disk.rate_limiter_config.is_some() || disk.rate_limit_group.is_some())
|
||||||
|
{
|
||||||
|
return Err(ValidationError::VhostUserRateLimiterNotSupported);
|
||||||
|
}
|
||||||
if let Some(rate_limit_group) = &disk.rate_limit_group {
|
if let Some(rate_limit_group) = &disk.rate_limit_group {
|
||||||
if let Some(rate_limit_groups) = &self.rate_limit_groups {
|
if let Some(rate_limit_groups) = &self.rate_limit_groups {
|
||||||
if !rate_limit_groups
|
if !rate_limit_groups
|
||||||
@@ -2938,6 +2958,9 @@ impl VmConfig {
|
|||||||
if net.vhost_user && !self.backed_by_shared_memory() {
|
if net.vhost_user && !self.backed_by_shared_memory() {
|
||||||
return Err(ValidationError::VhostUserRequiresSharedMemory);
|
return Err(ValidationError::VhostUserRequiresSharedMemory);
|
||||||
}
|
}
|
||||||
|
if net.vhost_user && net.rate_limiter_config.is_some() {
|
||||||
|
return Err(ValidationError::VhostUserRateLimiterNotSupported);
|
||||||
|
}
|
||||||
net.validate(self)?;
|
net.validate(self)?;
|
||||||
self.iommu |= net.pci_common.iommu;
|
self.iommu |= net.pci_common.iommu;
|
||||||
|
|
||||||
@@ -5162,6 +5185,50 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
|
|||||||
still_valid_config.memory.shared = true;
|
still_valid_config.memory.shared = true;
|
||||||
still_valid_config.validate().unwrap();
|
still_valid_config.validate().unwrap();
|
||||||
|
|
||||||
|
// Test vhost_user with rate limiting for disk
|
||||||
|
let mut invalid_config = valid_config.clone();
|
||||||
|
invalid_config.memory.shared = true;
|
||||||
|
invalid_config.disks = Some(vec![DiskConfig {
|
||||||
|
path: None,
|
||||||
|
vhost_user: true,
|
||||||
|
vhost_socket: Some("/path/to/sock".to_owned()),
|
||||||
|
rate_limiter_config: Some(RateLimiterConfig::default()),
|
||||||
|
..disk_fixture()
|
||||||
|
}]);
|
||||||
|
assert_eq!(
|
||||||
|
invalid_config.validate(),
|
||||||
|
Err(ValidationError::VhostUserRateLimiterNotSupported)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test vhost_user with rate_limit_group for disk
|
||||||
|
let mut invalid_config = valid_config.clone();
|
||||||
|
invalid_config.memory.shared = true;
|
||||||
|
invalid_config.disks = Some(vec![DiskConfig {
|
||||||
|
path: None,
|
||||||
|
vhost_user: true,
|
||||||
|
vhost_socket: Some("/path/to/sock".to_owned()),
|
||||||
|
rate_limit_group: Some("group0".to_string()),
|
||||||
|
..disk_fixture()
|
||||||
|
}]);
|
||||||
|
assert_eq!(
|
||||||
|
invalid_config.validate(),
|
||||||
|
Err(ValidationError::VhostUserRateLimiterNotSupported)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test vhost_user with rate limiting for net
|
||||||
|
let mut invalid_config = valid_config.clone();
|
||||||
|
invalid_config.memory.shared = true;
|
||||||
|
invalid_config.net = Some(vec![NetConfig {
|
||||||
|
vhost_user: true,
|
||||||
|
vhost_socket: Some("/path/to/sock".to_owned()),
|
||||||
|
rate_limiter_config: Some(RateLimiterConfig::default()),
|
||||||
|
..net_fixture()
|
||||||
|
}]);
|
||||||
|
assert_eq!(
|
||||||
|
invalid_config.validate(),
|
||||||
|
Err(ValidationError::VhostUserRateLimiterNotSupported)
|
||||||
|
);
|
||||||
|
|
||||||
let mut invalid_config = valid_config.clone();
|
let mut invalid_config = valid_config.clone();
|
||||||
invalid_config.net = Some(vec![NetConfig {
|
invalid_config.net = Some(vec![NetConfig {
|
||||||
fds: Some(vec![0]),
|
fds: Some(vec![0]),
|
||||||
|
|||||||
Reference in New Issue
Block a user