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
|
||||
#[error("Invalid rate-limiter group")]
|
||||
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`.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[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);
|
||||
}
|
||||
|
||||
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() {
|
||||
return Err(ValidationError::InvalidRateLimiterGroup);
|
||||
}
|
||||
@@ -1709,6 +1720,10 @@ impl NetConfig {
|
||||
return Err(ValidationError::IommuNotSupported);
|
||||
}
|
||||
|
||||
if self.vhost_user && self.rate_limiter_config.is_some() {
|
||||
return Err(ValidationError::VhostUserRateLimiterNotSupported);
|
||||
}
|
||||
|
||||
if let Some(mtu) = self.mtu
|
||||
&& mtu < virtio_devices::net::MIN_MTU
|
||||
{
|
||||
@@ -2913,6 +2928,11 @@ impl VmConfig {
|
||||
if disk.vhost_user && disk.vhost_socket.is_none() {
|
||||
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_groups) = &self.rate_limit_groups {
|
||||
if !rate_limit_groups
|
||||
@@ -2938,6 +2958,9 @@ impl VmConfig {
|
||||
if net.vhost_user && !self.backed_by_shared_memory() {
|
||||
return Err(ValidationError::VhostUserRequiresSharedMemory);
|
||||
}
|
||||
if net.vhost_user && net.rate_limiter_config.is_some() {
|
||||
return Err(ValidationError::VhostUserRateLimiterNotSupported);
|
||||
}
|
||||
net.validate(self)?;
|
||||
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.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();
|
||||
invalid_config.net = Some(vec![NetConfig {
|
||||
fds: Some(vec![0]),
|
||||
|
||||
Reference in New Issue
Block a user