diff --git a/src/main.rs b/src/main.rs index 30f22d9fc..2a5c34e67 100644 --- a/src/main.rs +++ b/src/main.rs @@ -984,11 +984,13 @@ mod unit_tests { ( vec![ "cloud-hypervisor", "--kernel", "/path/to/kernel", + "--cpus", "boot=2", "--net", "mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=4", ], r#"{ "kernel": {"path": "/path/to/kernel"}, + "cpus": {"boot_vcpus": 2, "max_vcpus": 2}, "net": [ {"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 4} ] @@ -998,11 +1000,13 @@ mod unit_tests { ( vec![ "cloud-hypervisor", "--kernel", "/path/to/kernel", + "--cpus", "boot=2", "--net", "mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=4,queue_size=128", ], r#"{ "kernel": {"path": "/path/to/kernel"}, + "cpus": {"boot_vcpus": 2, "max_vcpus": 2}, "net": [ {"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 4, "queue_size": 128} ] @@ -1163,13 +1167,14 @@ mod unit_tests { ( vec![ "cloud-hypervisor", "--kernel", "/path/to/kernel", - "--memory", "shared=true", + "--memory", "shared=true", "--cpus", "boot=4", "--fs", "tag=virtiofs1,socket=/path/to/sock1,num_queues=4", ], r#"{ "kernel": {"path": "/path/to/kernel"}, "memory" : { "shared": true, "size": 536870912 }, + "cpus": {"boot_vcpus": 4, "max_vcpus": 4}, "fs": [ {"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4} ] @@ -1179,13 +1184,14 @@ mod unit_tests { ( vec![ "cloud-hypervisor", "--kernel", "/path/to/kernel", - "--memory", "shared=true", + "--memory", "shared=true", "--cpus", "boot=4", "--fs", "tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128" ], r#"{ "kernel": {"path": "/path/to/kernel"}, "memory" : { "shared": true, "size": 536870912 }, + "cpus": {"boot_vcpus": 4, "max_vcpus": 4}, "fs": [ {"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128} ] @@ -1195,13 +1201,14 @@ mod unit_tests { ( vec![ "cloud-hypervisor", "--kernel", "/path/to/kernel", - "--memory", "shared=true", + "--memory", "shared=true", "--cpus", "boot=4", "--fs", "tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,dax=on" ], r#"{ "kernel": {"path": "/path/to/kernel"}, "memory" : { "shared": true, "size": 536870912 }, + "cpus": {"boot_vcpus": 4, "max_vcpus": 4}, "fs": [ {"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128} ] @@ -1211,13 +1218,14 @@ mod unit_tests { ( vec![ "cloud-hypervisor", "--kernel", "/path/to/kernel", - "--memory", "shared=true", + "--memory", "shared=true", "--cpus", "boot=4", "--fs", "tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,dax=on" ], r#"{ "kernel": {"path": "/path/to/kernel"}, "memory" : { "shared": true, "size": 536870912 }, + "cpus": {"boot_vcpus": 4, "max_vcpus": 4}, "fs": [ {"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "dax": true} ] @@ -1227,13 +1235,14 @@ mod unit_tests { ( vec![ "cloud-hypervisor", "--kernel", "/path/to/kernel", - "--memory", "shared=true", + "--memory", "shared=true", "--cpus", "boot=4", "--fs", "tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128" ], r#"{ "kernel": {"path": "/path/to/kernel"}, "memory" : { "shared": true, "size": 536870912 }, + "cpus": {"boot_vcpus": 4, "max_vcpus": 4}, "fs": [ {"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "dax": true} ] @@ -1243,13 +1252,14 @@ mod unit_tests { ( vec![ "cloud-hypervisor", "--kernel", "/path/to/kernel", - "--memory", "shared=true", + "--memory", "shared=true", "--cpus", "boot=4", "--fs", "tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,cache_size=8589934592" ], r#"{ "kernel": {"path": "/path/to/kernel"}, "memory" : { "shared": true, "size": 536870912 }, + "cpus": {"boot_vcpus": 4, "max_vcpus": 4}, "fs": [ {"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128} ] @@ -1259,13 +1269,14 @@ mod unit_tests { ( vec![ "cloud-hypervisor", "--kernel", "/path/to/kernel", - "--memory", "shared=true", + "--memory", "shared=true", "--cpus", "boot=4", "--fs", "tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128" ], r#"{ "kernel": {"path": "/path/to/kernel"}, "memory" : { "shared": true, "size": 536870912 }, + "cpus": {"boot_vcpus": 4, "max_vcpus": 4}, "fs": [ {"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "cache_size": 8589934592} ] @@ -1275,13 +1286,14 @@ mod unit_tests { ( vec![ "cloud-hypervisor", "--kernel", "/path/to/kernel", - "--memory", "shared=true", + "--memory", "shared=true","--cpus", "boot=4", "--fs", "tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,cache_size=4294967296" ], r#"{ "kernel": {"path": "/path/to/kernel"}, "memory" : { "shared": true, "size": 536870912 }, + "cpus": {"boot_vcpus": 4, "max_vcpus": 4}, "fs": [ {"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "cache_size": 4294967296} ] @@ -1291,13 +1303,14 @@ mod unit_tests { ( vec![ "cloud-hypervisor", "--kernel", "/path/to/kernel", - "--memory", "shared=true", + "--memory", "shared=true","--cpus", "boot=4", "--fs", "tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,cache_size=4294967296" ], r#"{ "kernel": {"path": "/path/to/kernel"}, "memory" : { "shared": true, "size": 536870912 }, + "cpus": {"boot_vcpus": 4, "max_vcpus": 4}, "fs": [ {"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128} ] diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 5242aedf0..5d2d84eb0 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -126,6 +126,8 @@ pub enum ValidationError { // CPU Hotplug not permitted with TDX #[cfg(feature = "tdx")] TdxNoCpuHotplug, + // Insuffient vCPUs for queues + TooManyQueues, } type ValidationResult = std::result::Result; @@ -166,6 +168,9 @@ impl fmt::Display for ValidationError { TdxNoCpuHotplug => { write!(f, "CPU hotplug not possible with TDX") } + TooManyQueues => { + write!(f, "Number of vCPUs is insufficient for number of queues") + } } } } @@ -863,6 +868,14 @@ impl DiskConfig { disable_io_uring, }) } + + pub fn validate(&self, vm_config: &VmConfig) -> ValidationResult<()> { + if self.num_queues > vm_config.cpus.boot_vcpus as usize { + return Err(ValidationError::TooManyQueues); + } + + Ok(()) + } } #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] @@ -1075,11 +1088,10 @@ impl NetConfig { fds, rate_limiter_config, }; - config.validate().map_err(Error::Validation)?; Ok(config) } - pub fn validate(&self) -> ValidationResult<()> { + pub fn validate(&self, vm_config: &VmConfig) -> ValidationResult<()> { if self.num_queues < 2 { return Err(ValidationError::VnetQueueLowerThan2); } @@ -1096,6 +1108,10 @@ impl NetConfig { } } + if (self.num_queues / 2) > vm_config.cpus.boot_vcpus as usize { + return Err(ValidationError::TooManyQueues); + } + Ok(()) } } @@ -1264,6 +1280,14 @@ impl FsConfig { id, }) } + + pub fn validate(&self, vm_config: &VmConfig) -> ValidationResult<()> { + if self.num_queues > vm_config.cpus.boot_vcpus as usize { + return Err(ValidationError::TooManyQueues); + } + + Ok(()) + } } #[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)] @@ -1719,6 +1743,7 @@ impl VmConfig { if disk.vhost_user && disk.vhost_socket.is_none() { return Err(ValidationError::VhostUserMissingSocket); } + disk.validate(self)?; } } @@ -1727,7 +1752,7 @@ impl VmConfig { if net.vhost_user && !self.memory.shared { return Err(ValidationError::VhostUserRequiresSharedMemory); } - net.validate()?; + net.validate(self)?; } } @@ -1735,6 +1760,9 @@ impl VmConfig { if !fses.is_empty() && !self.memory.shared { return Err(ValidationError::VhostUserRequiresSharedMemory); } + for fs in fses { + fs.validate(self)?; + } } if let Some(t) = &self.cpus.topology {