From 67e2786a0e14b8bcbeb9431aac27843ce389f7f5 Mon Sep 17 00:00:00 2001 From: Matt Coleman Date: Mon, 1 Feb 2021 19:48:39 -0500 Subject: [PATCH] hyperv: XML parsing of Ethernet adapters Co-authored-by: Sri Ramanujam Signed-off-by: Matt Coleman Reviewed-by: Michal Privoznik --- src/hyperv/hyperv_driver.c | 111 ++++++++++++++++++++++++++ src/hyperv/hyperv_wmi.c | 20 +++++ src/hyperv/hyperv_wmi.h | 8 ++ src/hyperv/hyperv_wmi_classes.h | 12 +++ src/hyperv/hyperv_wmi_generator.input | 109 +++++++++++++++++++++++++ 5 files changed, 260 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index e268e71081..a3e6b95776 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1379,6 +1379,105 @@ hypervDomainDefParseSerial(virDomainDefPtr def, Msvm_ResourceAllocationSettingDa } +static int +hypervDomainDefParseEthernetAdapter(virDomainDefPtr def, + Msvm_EthernetPortAllocationSettingData *net, + hypervPrivate *priv) +{ + g_autoptr(virDomainNetDef) ndef = g_new0(virDomainNetDef, 1); + g_autoptr(Msvm_SyntheticEthernetPortSettingData) sepsd = NULL; + g_autoptr(Msvm_VirtualEthernetSwitch) vSwitch = NULL; + char **switchConnection = NULL; + g_autofree char *switchConnectionEscaped = NULL; + char *sepsdPATH = NULL; + g_autofree char *sepsdEscaped = NULL; + g_auto(virBuffer) query = VIR_BUFFER_INITIALIZER; + + VIR_DEBUG("Parsing ethernet adapter '%s'", net->data->InstanceID); + + ndef->type = VIR_DOMAIN_NET_TYPE_BRIDGE; + + /* + * If there's no switch port connection or the EnabledState is disabled, + * then the adapter isn't hooked up to anything and we don't have to + * do anything more. + */ + switchConnection = net->data->HostResource.data; + if (net->data->HostResource.count < 1 || !*switchConnection || + net->data->EnabledState == MSVM_ETHERNETPORTALLOCATIONSETTINGDATA_ENABLEDSTATE_DISABLED) { + VIR_DEBUG("Adapter not connected to switch"); + return 0; + } + + /* + * Now we retrieve the associated Msvm_SyntheticEthernetPortSettingData and + * Msvm_VirtualEthernetSwitch objects and use them to build the XML definition. + */ + + /* begin by getting the Msvm_SyntheticEthernetPortSettingData object */ + sepsdPATH = net->data->Parent; + sepsdEscaped = virStringReplace(sepsdPATH, "\\", "\\\\"); + virBufferAsprintf(&query, + MSVM_SYNTHETICETHERNETPORTSETTINGDATA_WQL_SELECT "WHERE __PATH = '%s'", + sepsdEscaped); + + if (hypervGetWmiClass(Msvm_SyntheticEthernetPortSettingData, &sepsd) < 0) + return -1; + + if (!sepsd) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not retrieve NIC settings")); + return -1; + } + + /* set mac address */ + if (virMacAddrParseHex(sepsd->data->Address, &ndef->mac) < 0) + return -1; + + /* now we get the Msvm_VirtualEthernetSwitch */ + virBufferFreeAndReset(&query); + switchConnectionEscaped = virStringReplace(*switchConnection, "\\", "\\\\"); + virBufferAsprintf(&query, + MSVM_VIRTUALETHERNETSWITCH_WQL_SELECT "WHERE __PATH = '%s'", + switchConnectionEscaped); + + if (hypervGetWmiClass(Msvm_VirtualEthernetSwitch, &vSwitch) < 0) + return -1; + + if (!vSwitch) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not retrieve virtual switch")); + return -1; + } + + /* get bridge name */ + ndef->data.bridge.brname = g_strdup(vSwitch->data->Name); + + if (VIR_APPEND_ELEMENT(def->nets, def->nnets, ndef) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not append definition to domain")); + return -1; + } + + return 0; +} + +static int +hypervDomainDefParseEthernet(virDomainPtr domain, + virDomainDefPtr def, + Msvm_EthernetPortAllocationSettingData *nets) +{ + Msvm_EthernetPortAllocationSettingData *entry = nets; + hypervPrivate *priv = domain->conn->privateData; + + while (entry) { + if (hypervDomainDefParseEthernetAdapter(def, entry, priv) < 0) + return -1; + + entry = entry->next; + } + + return 0; +} + + /* * Driver functions */ @@ -2240,6 +2339,7 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags) g_autoptr(Msvm_StorageAllocationSettingData) sasd = NULL; g_autoptr(Msvm_SerialPortSettingData) spsd = NULL; Msvm_ResourceAllocationSettingData *serialDevices = NULL; + g_autoptr(Msvm_EthernetPortAllocationSettingData) nets = NULL; virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS, NULL); @@ -2281,6 +2381,10 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags) if (hypervGetSerialPortSD(priv, virtualSystemSettingData->data->InstanceID, &spsd) < 0) return NULL; + if (hypervGetEthernetPortAllocationSD(priv, + virtualSystemSettingData->data->InstanceID, &nets) < 0) + return NULL; + /* Fill struct */ def->virtType = VIR_DOMAIN_VIRT_HYPERV; @@ -2342,6 +2446,10 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags) def->controllers = g_new0(virDomainControllerDefPtr, 5); def->ncontrollers = 0; + /* 8 synthetic + 4 legacy NICs */ + def->nets = g_new0(virDomainNetDefPtr, 12); + def->nnets = 0; + if (hypervDomainDefParseStorage(priv, def, rasd, sasd) < 0) return NULL; @@ -2353,6 +2461,9 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags) if (hypervDomainDefParseSerial(def, serialDevices) < 0) return NULL; + if (hypervDomainDefParseEthernet(domain, def, nets) < 0) + return NULL; + /* XXX xmlopts must be non-NULL */ return virDomainDefFormat(def, NULL, virDomainDefFormatConvertXMLFlags(flags)); } diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index f5f0797605..4c1bd5e0d2 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -1498,6 +1498,26 @@ hypervGetSerialPortSD(hypervPrivate *priv, } +int +hypervGetSyntheticEthernetPortSD(hypervPrivate *priv, + const char *id, + Msvm_SyntheticEthernetPortSettingData **data) +{ + hypervGetSettingData(Msvm_SyntheticEthernetPortSettingData, id, data); + return 0; +} + + +int +hypervGetEthernetPortAllocationSD(hypervPrivate *priv, + const char *id, + Msvm_EthernetPortAllocationSettingData **data) +{ + hypervGetSettingData(Msvm_EthernetPortAllocationSettingData, id, data); + return 0; +} + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Msvm_VirtualSystemManagementService */ diff --git a/src/hyperv/hyperv_wmi.h b/src/hyperv/hyperv_wmi.h index 2b0d0e4a3f..6021a46f3e 100644 --- a/src/hyperv/hyperv_wmi.h +++ b/src/hyperv/hyperv_wmi.h @@ -258,6 +258,14 @@ int hypervGetSerialPortSD(hypervPrivate *priv, const char *id, Msvm_SerialPortSettingData **data); +int hypervGetSyntheticEthernetPortSD(hypervPrivate *priv, + const char *id, + Msvm_SyntheticEthernetPortSettingData **data); + +int hypervGetEthernetPortAllocationSD(hypervPrivate *priv, + const char *id, + Msvm_EthernetPortAllocationSettingData **data); + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Msvm_VirtualSystemManagementService */ diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h index 2f813bedb3..eea24235a5 100644 --- a/src/hyperv/hyperv_wmi_classes.h +++ b/src/hyperv/hyperv_wmi_classes.h @@ -119,6 +119,18 @@ enum _Msvm_ResourceAllocationSettingData_ResourceType { +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Msvm_EthernetPortAllocationSettingData + */ + +/* https://docs.microsoft.com/en-us/windows/win32/hyperv_v2/msvm-ethernetportallocationsettingdata#enabled */ +enum _Msvm_EthernetPortAllocationSettingData_EnabledState { + MSVM_ETHERNETPORTALLOCATIONSETTINGDATA_ENABLEDSTATE_ENABLED = 2, + MSVM_ETHERNETPORTALLOCATIONSETTINGDATA_ENABLEDSTATE_DISABLED = 3, +}; + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * WMI */ diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 765ffba169..df240361e6 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -827,3 +827,112 @@ class Msvm_StorageAllocationSettingData string IOPSAllocationUnits boolean PersistentReservationsSupported end + + +class Msvm_SyntheticEthernetPortSettingData + string InstanceID + string Caption + string Description + string ElementName + uint16 ResourceType + string OtherResourceType + string ResourceSubType + string PoolID + uint16 ConsumerVisibility + string HostResource[] + string AllocationUnits + uint64 VirtualQuantity + uint64 Reservation + uint64 Limit + uint32 Weight + boolean AutomaticAllocation + boolean AutomaticDeallocation + string Parent + string Connection[] + string Address + uint16 MappingBehavior + string AddressOnParent + string VirtualQuantityUnits + uint16 DesiredVLANEndpointMode + string OtherEndpointMode + string VirtualSystemIdentifiers[] +# DeviceNamingEnabled and AllowPacketDirect are not present in Windows Server 2012R2. +# They were added in Windows 10 and Windows Server 2016. +# They have been omitted to retain compatibility with Windows Server 2012R2. +# boolean DeviceNamingEnabled +# boolean AllowPacketDirect + boolean StaticMacAddress + boolean ClusterMonitored +end + + +class Msvm_EthernetPortAllocationSettingData + string InstanceID + string Caption + string Description + string ElementName + uint16 ResourceType + string OtherResourceType + string ResourceSubType + string PoolID + uint16 ConsumerVisibility + string HostResource[] + string AllocationUnits + uint64 VirtualQuantity + uint64 Reservation + uint64 Limit + uint32 Weight + boolean AutomaticAllocation + boolean AutomaticDeallocation + string Parent + string Connection[] + string Address + uint16 MappingBehavior + string AddressOnParent + string VirtualQuantityUnits + uint16 DesiredVLANEndpointMode + string OtherEndpointMode + uint16 EnabledState + string RequiredFeatures[] + string RequiredFeatureHints[] + string TestReplicaPoolID + string TestReplicaSwitchName +end + + +class Msvm_VirtualEthernetSwitch + string InstanceID + string Caption + string Description + string ElementName + datetime InstallDate + uint16 OperationalStatus[] + string StatusDescriptions[] + string Status + uint16 HealthState + uint16 CommunicationStatus + uint16 DetailedStatus + uint16 OperatingStatus + uint16 PrimaryStatus + uint16 EnabledState + string OtherEnabledState + uint16 RequestedState + uint16 EnabledDefault + datetime TimeOfLastStateChange + uint16 AvailableRequestedStates[] + uint16 TransitioningToState + string CreationClassName + string Name + string PrimaryOwnerName + string PrimaryOwnerContact + string Roles[] + string NameFormat + string OtherIdentifyingInfo[] + string IdentifyingDescriptions[] + uint16 Dedicated[] + string OtherDedicatedDescriptions[] + uint16 ResetCapability + uint16 PowerManagementCapabilities[] + uint32 MaxVMQOffloads + uint32 MaxIOVOffloads +end