device_virtio_net/
pci_hotplug.rs1use base::AsRawDescriptor;
6use base::AsRawDescriptors;
7use base::RawDescriptor;
8use base::Tube;
9use devices::IntxParameter;
10use devices::IrqLevelEvent;
11use devices::PciAddress;
12use devices::PciDeviceError;
13use devices::PciInterruptPin;
14use serde::Deserialize;
15use serde::Serialize;
16use vm_control::api::VmMemoryClient;
17
18use crate::NetParameters;
19
20pub type Result<T> = std::result::Result<T, PciDeviceError>;
21
22#[derive(Serialize, Deserialize)]
26pub struct NetPciHotplugResourceCarrier {
27 pub net_param: NetParameters,
29 pub msi_device_tube: Tube,
31 pub ioevent_vm_memory_client: VmMemoryClient,
33 pub pci_address: Option<PciAddress>,
35 pub intx_parameter: Option<IntxParameter>,
37 pub vm_control_tube: Tube,
39}
40
41impl NetPciHotplugResourceCarrier {
42 pub fn new(
44 net_param: NetParameters,
45 msi_device_tube: Tube,
46 ioevent_vm_memory_client: VmMemoryClient,
47 vm_control_tube: Tube,
48 ) -> Self {
49 Self {
50 net_param,
51 msi_device_tube,
52 ioevent_vm_memory_client,
53 pci_address: None,
54 intx_parameter: None,
55 vm_control_tube,
56 }
57 }
58
59 pub fn debug_label(&self) -> String {
60 "virtio-net".to_owned()
61 }
62
63 pub fn keep_rds(&self) -> Vec<RawDescriptor> {
64 let mut keep_rds = vec![
65 self.msi_device_tube.as_raw_descriptor(),
66 self.ioevent_vm_memory_client.as_raw_descriptor(),
67 ];
68 if let Some(intx_parameter) = &self.intx_parameter {
69 keep_rds.extend(intx_parameter.irq_evt.as_raw_descriptors());
70 }
71 keep_rds
72 }
73
74 pub fn allocate_address(
75 &mut self,
76 preferred_address: PciAddress,
77 resources: &mut resources::SystemAllocator,
78 ) -> Result<()> {
79 match self.pci_address {
80 None => {
81 if resources.reserve_pci(preferred_address, self.debug_label()) {
82 self.pci_address = Some(preferred_address);
83 } else {
84 return Err(PciDeviceError::PciAllocationFailed);
85 }
86 }
87 Some(pci_address) => {
88 if pci_address != preferred_address {
89 return Err(PciDeviceError::PciAllocationFailed);
90 }
91 }
92 }
93 Ok(())
94 }
95
96 pub fn assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32) {
97 self.intx_parameter = Some(IntxParameter {
98 irq_evt,
99 pin,
100 irq_num,
101 });
102 }
103}