From 92c2cf0103e25505b2cf034c97676be7e76c809f Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Fri, 3 Apr 2026 11:49:54 -0700 Subject: [PATCH] vmm: config: Switch NetConfig to use PciDeviceCommonConfig Switch NetConfig over to using the newly extracted struct members as used by all PCI based devices. The use of #[serde(flatten)] means that this change has no impact on the JSON format that the data is stored as. Signed-off-by: Rob Bradford --- vmm/src/api/http/http_endpoint.rs | 2 +- vmm/src/config.rs | 88 ++++++++++++++++--------------- vmm/src/device_manager.rs | 20 +++---- vmm/src/lib.rs | 4 +- vmm/src/vm_config.rs | 8 +-- 5 files changed, 61 insertions(+), 61 deletions(-) diff --git a/vmm/src/api/http/http_endpoint.rs b/vmm/src/api/http/http_endpoint.rs index 15ebfd2f9..92b53ac68 100644 --- a/vmm/src/api/http/http_endpoint.rs +++ b/vmm/src/api/http/http_endpoint.rs @@ -122,7 +122,7 @@ mod fds_helper { impl ConfigWithFDs for NetConfig { fn id(&self) -> Option<&str> { - self.id.as_deref() + self.pci_common.id.as_deref() } fn fds_from_http_body(&self) -> Option<&[RawFd]> { diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 9ff05bb5f..5e53e8bda 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -1554,11 +1554,6 @@ impl NetConfig { .unwrap_or(Toggle(true)) .0; let mtu = parser.convert("mtu").map_err(Error::ParseNetwork)?; - let iommu = parser - .convert::("iommu") - .map_err(Error::ParseNetwork)? - .unwrap_or(Toggle(false)) - .0; let queue_size = parser .convert("queue_size") .map_err(Error::ParseNetwork)? @@ -1577,15 +1572,10 @@ impl NetConfig { .convert("vhost_mode") .map_err(Error::ParseNetwork)? .unwrap_or_default(); - let id = parser.get("id"); let fds = parser .convert::("fd") .map_err(Error::ParseNetwork)? .map(|v| v.0.iter().map(|e| *e as i32).collect()); - let pci_segment = parser - .convert("pci_segment") - .map_err(Error::ParseNetwork)? - .unwrap_or_default(); let bw_size = parser .convert("bw_size") .map_err(Error::ParseNetwork)? @@ -1637,23 +1627,23 @@ impl NetConfig { None }; + let pci_common = PciDeviceCommonConfig::parse(net)?; + let config = NetConfig { + pci_common, tap, ip, mask, mac, host_mac, mtu, - iommu, num_queues, queue_size, vhost_user, vhost_socket, vhost_mode, - id, fds, rate_limiter_config, - pci_segment, offload_tso, offload_ufo, offload_csum, @@ -1662,6 +1652,8 @@ impl NetConfig { } pub fn validate(&self, vm_config: &VmConfig) -> ValidationResult<()> { + self.pci_common.validate(vm_config)?; + if self.num_queues < 2 { return Err(ValidationError::VnetQueueLowerThan2(self.num_queues)); } @@ -1689,23 +1681,10 @@ impl NetConfig { )); } - if self.vhost_user && self.iommu { + if self.vhost_user && self.pci_common.iommu { return Err(ValidationError::IommuNotSupported); } - if let Some(platform_config) = vm_config.platform.as_ref() { - if self.pci_segment >= platform_config.num_pci_segments { - return Err(ValidationError::InvalidPciSegment(self.pci_segment)); - } - - if let Some(iommu_segments) = platform_config.iommu_segments.as_ref() - && iommu_segments.contains(&self.pci_segment) - && !self.iommu - { - return Err(ValidationError::OnIommuSegment(self.pci_segment)); - } - } - if let Some(mtu) = self.mtu && mtu < virtio_devices::net::MIN_MTU { @@ -2778,6 +2757,7 @@ impl RestoreConfig { for net_fds in vm_config.net.iter().flatten() { if let Some(expected_fds) = &net_fds.fds { let expected_id = net_fds + .pci_common .id .as_ref() .expect("Invalid 'NetConfig' with empty 'id' for VM restore."); @@ -3066,9 +3046,9 @@ impl VmConfig { return Err(ValidationError::VhostUserRequiresSharedMemory); } net.validate(self)?; - self.iommu |= net.iommu; + self.iommu |= net.pci_common.iommu; - Self::validate_identifier(&mut id_list, &net.id)?; + Self::validate_identifier(&mut id_list, &net.pci_common.id)?; } } @@ -3564,7 +3544,7 @@ impl VmConfig { // Remove if net device if let Some(net) = self.net.as_mut() { let len = net.len(); - net.retain(|dev| dev.id.as_ref().map(|id| id.as_ref()) != Some(id)); + net.retain(|dev| dev.pci_common.id.as_ref().map(|id| id.as_ref()) != Some(id)); removed |= net.len() != len; } @@ -4148,22 +4128,20 @@ mod unit_tests { fn net_fixture() -> NetConfig { NetConfig { + pci_common: PciDeviceCommonConfig::default(), tap: None, ip: None, mask: None, mac: MacAddr::parse_str("de:ad:be:ef:12:34").unwrap(), host_mac: Some(MacAddr::parse_str("12:34:de:ad:be:ef").unwrap()), mtu: None, - iommu: false, num_queues: 2, queue_size: 256, vhost_user: false, vhost_socket: None, vhost_mode: VhostMode::Client, - id: None, fds: None, rate_limiter_config: None, - pci_segment: 0, offload_tso: true, offload_ufo: true, offload_csum: true, @@ -4181,7 +4159,10 @@ mod unit_tests { assert_eq!( NetConfig::parse("mac=de:ad:be:ef:12:34,host_mac=12:34:de:ad:be:ef,id=mynet0")?, NetConfig { - id: Some("mynet0".to_owned()), + pci_common: PciDeviceCommonConfig { + id: Some("mynet0".to_owned()), + ..Default::default() + }, ..net_fixture() } ); @@ -4214,9 +4195,12 @@ mod unit_tests { "mac=de:ad:be:ef:12:34,host_mac=12:34:de:ad:be:ef,num_queues=4,queue_size=1024,iommu=on" )?, NetConfig { + pci_common: PciDeviceCommonConfig { + iommu: true, + ..Default::default() + }, num_queues: 4, queue_size: 1024, - iommu: true, ..net_fixture() } ); @@ -4840,19 +4824,28 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}" preserved_fds: None, net: Some(vec![ NetConfig { - id: Some("net0".to_owned()), + pci_common: PciDeviceCommonConfig { + id: Some("net0".to_owned()), + ..Default::default() + }, num_queues: 2, fds: Some(vec![-1, -1, -1, -1]), ..net_fixture() }, NetConfig { - id: Some("net1".to_owned()), + pci_common: PciDeviceCommonConfig { + id: Some("net1".to_owned()), + ..Default::default() + }, num_queues: 1, fds: Some(vec![-1, -1]), ..net_fixture() }, NetConfig { - id: Some("net2".to_owned()), + pci_common: PciDeviceCommonConfig { + id: Some("net2".to_owned()), + ..Default::default() + }, fds: None, ..net_fixture() }, @@ -4947,7 +4940,10 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}" resume: false, }; snapshot_vm_config.net = Some(vec![NetConfig { - id: Some("net2".to_owned()), + pci_common: PciDeviceCommonConfig { + id: Some("net2".to_owned()), + ..Default::default() + }, fds: None, ..net_fixture() }]); @@ -5330,8 +5326,11 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}" ..platform_fixture() }); still_valid_config.net = Some(vec![NetConfig { - iommu: true, - pci_segment: 1, + pci_common: PciDeviceCommonConfig { + iommu: true, + pci_segment: 1, + ..Default::default() + }, ..net_fixture() }]); still_valid_config.validate().unwrap(); @@ -5398,8 +5397,11 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}" ..platform_fixture() }); invalid_config.net = Some(vec![NetConfig { - iommu: false, - pci_segment: 1, + pci_common: PciDeviceCommonConfig { + iommu: false, + pci_segment: 1, + ..Default::default() + }, ..net_fixture() }]); assert_eq!( diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 9cfbbc4e2..9a5bdff56 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -2937,11 +2937,11 @@ impl DeviceManager { &mut self, net_cfg: &mut NetConfig, ) -> DeviceManagerResult { - let id = if let Some(id) = &net_cfg.id { + let id = if let Some(id) = &net_cfg.pci_common.id { id.clone() } else { let id = self.next_device_name(NET_DEVICE_NAME_PREFIX)?; - net_cfg.id = Some(id.clone()); + net_cfg.pci_common.id = Some(id.clone()); id }; info!("Creating virtio-net device: {net_cfg:?}"); @@ -2999,7 +2999,7 @@ impl DeviceManager { Some(net_cfg.mac), &mut net_cfg.host_mac, net_cfg.mtu, - self.force_iommu | net_cfg.iommu, + self.force_iommu | net_cfg.pci_common.iommu, net_cfg.num_queues, net_cfg.queue_size, self.seccomp_action.clone(), @@ -3020,7 +3020,7 @@ impl DeviceManager { fds, Some(net_cfg.mac), net_cfg.mtu, - self.force_iommu | net_cfg.iommu, + self.force_iommu | net_cfg.pci_common.iommu, net_cfg.queue_size, self.seccomp_action.clone(), net_cfg.rate_limiter_config, @@ -3050,7 +3050,7 @@ impl DeviceManager { Some(net_cfg.mac), &mut net_cfg.host_mac, net_cfg.mtu, - self.force_iommu | net_cfg.iommu, + self.force_iommu | net_cfg.pci_common.iommu, net_cfg.num_queues, net_cfg.queue_size, self.seccomp_action.clone(), @@ -3083,9 +3083,9 @@ impl DeviceManager { Ok(MetaVirtioDevice { virtio_device, - iommu: net_cfg.iommu, + iommu: net_cfg.pci_common.iommu, id, - pci_segment: net_cfg.pci_segment, + pci_segment: net_cfg.pci_common.pci_segment, dma_handler: None, }) } @@ -4737,7 +4737,7 @@ impl DeviceManager { let nets = config.net.as_deref_mut().unwrap(); let net_dev_cfg = nets .iter_mut() - .find(|net| net.id.as_deref() == Some(id)) + .find(|net| net.pci_common.id.as_deref() == Some(id)) // unwrap: the device could not have been removed without an ID .unwrap(); let fds = net_dev_cfg.fds.take().unwrap_or(Vec::new()); @@ -5067,9 +5067,9 @@ impl DeviceManager { } pub fn add_net(&mut self, net_cfg: &mut NetConfig) -> DeviceManagerResult { - self.validate_identifier(&net_cfg.id)?; + self.validate_identifier(&net_cfg.pci_common.id)?; - if net_cfg.iommu && !self.is_iommu_segment(net_cfg.pci_segment) { + if net_cfg.pci_common.iommu && !self.is_iommu_segment(net_cfg.pci_common.pci_segment) { return Err(DeviceManagerError::InvalidIommuHotplug); } diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index df94b54e2..66a2a104d 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -1879,7 +1879,9 @@ impl RequestHandler for Vmm { for net in restored_nets.iter() { for net_config in vm_net_configs.iter_mut() { // update only if the net dev is backed by FDs - if net_config.id.as_ref() == Some(&net.id) && net_config.fds.is_some() { + if net_config.pci_common.id.as_ref() == Some(&net.id) + && net_config.fds.is_some() + { net_config.fds.clone_from(&net.fds); } } diff --git a/vmm/src/vm_config.rs b/vmm/src/vm_config.rs index d5465d924..e318aba7d 100644 --- a/vmm/src/vm_config.rs +++ b/vmm/src/vm_config.rs @@ -350,6 +350,8 @@ pub fn default_diskconfig_sparse() -> bool { #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] pub struct NetConfig { + #[serde(flatten)] + pub pci_common: PciDeviceCommonConfig, #[serde(default = "default_netconfig_tap")] pub tap: Option, pub ip: Option, @@ -360,8 +362,6 @@ pub struct NetConfig { pub host_mac: Option, #[serde(default)] pub mtu: Option, - #[serde(default)] - pub iommu: bool, #[serde(default = "default_netconfig_num_queues")] pub num_queues: usize, #[serde(default = "default_netconfig_queue_size")] @@ -371,8 +371,6 @@ pub struct NetConfig { pub vhost_socket: Option, #[serde(default)] pub vhost_mode: VhostMode, - #[serde(default)] - pub id: Option, // Special deserialize handling: // Therefore, we don't serialize FDs, and whatever value is here after // deserialization is invalid. @@ -383,8 +381,6 @@ pub struct NetConfig { pub fds: Option>, #[serde(default)] pub rate_limiter_config: Option, - #[serde(default)] - pub pci_segment: u16, #[serde(default = "default_netconfig_true")] pub offload_tso: bool, #[serde(default = "default_netconfig_true")]