[libvirt] [PATCH 00/27] network: refactor to decouple virt drivers from network driver

Currently the network driver registers a set of callbacks with the virt driver in order to handle allocating/releasing network ports associated with guest NICs. This series introduces a virNetworkPortPtr object and associated XML that describes a network port. The virt drivers now call public APIs associated with this new object to create/delete ports for guest NICs. There are some parts that are not yet addressed by this series - The live updating of bandwidth limits on network ports - The old code would re-connect VIFs to bridges, and/or change bridges during startup. This code is deleted right now as it doesn't belong in the network driver. It needs to move to the virt drivers in some (to be determined) manner. Daniel P. Berrangé (27): conf: make virPCIDeviceAddressFormat void network: restrict usage of port management APIs network: pass a virNetworkPtr to port management APIs conf: simplify link from hostdev back to network device network: add missing bandwidth limits for bridge forward type network: use 'bridge' as actual type instead of 'network' virt drivers: don't handle type=network after resolving actual network type network: unconditionally merge port profiles conf: introduce virNetworkPortDefPtr struct and XML support network: stop passing virDomainNetDefPtr into bandwidth functions network: make networkLogAllocation independent of domain conf util: add API for copying virtual port profile data conf: add APIs to convert virDomainNetDef to virNetworkPortDef network: convert networkAllocateActualDevice to virNetworkPortDef network: convert networkNotifyActualDevice to virNetworkPortDef network: convert networkReleaseActualDevice to virNetworkPortDef network: convert hook script to take a network port XML network: introduce networkAllocatePort network: introduce networkNotifyPort network: introduce networkReleasePort network: add public APIs for network port object access: add permissions for network port objects remote: add support for new network port APIs virsh: add support for network port APIs conf: support recording ports against virNetworkObjPtr network: add implementation of network port APIs conf: switch over to use network port APIs for virt drivers include/libvirt/libvirt-network.h | 49 + include/libvirt/virterror.h | 3 + src/access/genpolkit.pl | 2 +- src/access/viraccessdriver.h | 6 + src/access/viraccessdrivernop.c | 11 + src/access/viraccessdriverpolkit.c | 26 + src/access/viraccessdriverstack.c | 25 + src/access/viraccessmanager.c | 16 + src/access/viraccessmanager.h | 6 + src/access/viraccessperm.c | 8 +- src/access/viraccessperm.h | 38 + src/conf/Makefile.inc.am | 2 + src/conf/device_conf.c | 3 +- src/conf/device_conf.h | 6 +- src/conf/domain_conf.c | 413 ++++++- src/conf/domain_conf.h | 46 +- src/conf/network_conf.c | 7 +- src/conf/storage_adapter_conf.c | 4 +- src/conf/virnetworkobj.c | 303 +++++ src/conf/virnetworkobj.h | 30 + src/conf/virnetworkportdef.c | 497 ++++++++ src/conf/virnetworkportdef.h | 112 ++ src/datatypes.c | 60 + src/datatypes.h | 41 + src/driver-network.h | 27 + src/libvirt-network.c | 351 ++++++ src/libvirt_private.syms | 21 + src/libvirt_public.syms | 14 + src/libxl/libxl_conf.c | 21 +- src/libxl/libxl_domain.c | 28 +- src/libxl/libxl_driver.c | 27 +- src/lxc/lxc_driver.c | 37 +- src/lxc/lxc_process.c | 21 +- src/network/bridge_driver.c | 1069 +++++++++-------- src/qemu/qemu_command.c | 11 +- src/qemu/qemu_domain_address.c | 4 +- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_hotplug.c | 84 +- src/qemu/qemu_hotplug.h | 2 +- src/qemu/qemu_interface.c | 12 +- src/qemu/qemu_process.c | 32 +- src/remote/remote_daemon_dispatch.c | 25 + src/remote/remote_driver.c | 28 + src/remote/remote_protocol.x | 89 +- src/remote_protocol-structs | 47 + src/rpc/gendispatch.pl | 18 +- src/util/virerror.c | 9 + src/util/virhook.c | 4 +- src/util/virhook.h | 4 +- src/util/virhostdev.c | 17 +- src/util/virnetdevvportprofile.c | 16 + src/util/virnetdevvportprofile.h | 2 + tests/Makefile.am | 7 + .../plug-bridge-mactbl.xml | 9 + .../virnetworkportxml2xmldata/plug-bridge.xml | 9 + .../virnetworkportxml2xmldata/plug-direct.xml | 12 + .../plug-hostdev-pci.xml | 12 + tests/virnetworkportxml2xmldata/plug-none.xml | 8 + tests/virnetworkportxml2xmltest.c | 104 ++ tools/virsh-completer.c | 51 + tools/virsh-completer.h | 4 + tools/virsh-network.c | 399 +++++- tools/virsh-network.h | 5 + 63 files changed, 3681 insertions(+), 675 deletions(-) create mode 100644 src/conf/virnetworkportdef.c create mode 100644 src/conf/virnetworkportdef.h create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge-mactbl.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-direct.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-none.xml create mode 100644 tests/virnetworkportxml2xmltest.c -- 2.19.2

Only one of the three callers of virPCIDeviceAddressFormat correctly handles an error return status. Fortunately it can't fail so can be made void. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/device_conf.c | 3 +-- src/conf/device_conf.h | 6 +++--- src/conf/domain_conf.c | 6 ++---- src/conf/network_conf.c | 7 +++---- src/conf/storage_adapter_conf.c | 4 ++-- 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c index 32628c6448..cd994057c5 100644 --- a/src/conf/device_conf.c +++ b/src/conf/device_conf.c @@ -308,7 +308,7 @@ virPCIDeviceAddressParseXML(xmlNodePtr node, return ret; } -int +void virPCIDeviceAddressFormat(virBufferPtr buf, virPCIDeviceAddress addr, bool includeTypeInAddr) @@ -320,7 +320,6 @@ virPCIDeviceAddressFormat(virBufferPtr buf, addr.bus, addr.slot, addr.function); - return 0; } bool diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h index 56745707d9..7a3455f99f 100644 --- a/src/conf/device_conf.h +++ b/src/conf/device_conf.h @@ -202,9 +202,9 @@ bool virDeviceInfoPCIAddressExtensionIsPresent(const virDomainDeviceInfo *info); int virPCIDeviceAddressParseXML(xmlNodePtr node, virPCIDeviceAddressPtr addr); -int virPCIDeviceAddressFormat(virBufferPtr buf, - virPCIDeviceAddress addr, - bool includeTypeInAddr); +void virPCIDeviceAddressFormat(virBufferPtr buf, + virPCIDeviceAddress addr, + bool includeTypeInAddr); bool virDomainDeviceCCWAddressIsValid(virDomainDeviceCCWAddressPtr addr); int virDomainDeviceCCWAddressParseXML(xmlNodePtr node, diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index d8dfd1656f..706ee361ff 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -24809,10 +24809,8 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, } break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: - if (virPCIDeviceAddressFormat(buf, pcisrc->addr, - includeTypeInAddr) != 0) - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("PCI address Formatting failed")); + virPCIDeviceAddressFormat(buf, pcisrc->addr, + includeTypeInAddr); if ((flags & VIR_DOMAIN_DEF_FORMAT_PCI_ORIG_STATES) && (def->origstates.states.pci.unbind_from_stub || diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index e035d8aba7..3e2d6dc756 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -2471,10 +2471,9 @@ virNetworkDefFormatBuf(virBufferPtr buf, virBufferAddLit(buf, "/>\n"); } else { if (def->forward.ifs[i].type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI) { - if (virPCIDeviceAddressFormat(buf, - def->forward.ifs[i].device.pci, - true) < 0) - goto error; + virPCIDeviceAddressFormat(buf, + def->forward.ifs[i].device.pci, + true); } } } diff --git a/src/conf/storage_adapter_conf.c b/src/conf/storage_adapter_conf.c index f333ae16ff..65d664b89b 100644 --- a/src/conf/storage_adapter_conf.c +++ b/src/conf/storage_adapter_conf.c @@ -325,8 +325,8 @@ virStorageAdapterFormatSCSIHost(virBufferPtr buf, virBufferAsprintf(buf, "<parentaddr unique_id='%d'>\n", scsi_host->unique_id); virBufferAdjustIndent(buf, 2); - ignore_value(virPCIDeviceAddressFormat(buf, scsi_host->parentaddr, - false)); + virPCIDeviceAddressFormat(buf, scsi_host->parentaddr, + false); virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</parentaddr>\n"); virBufferAdjustIndent(buf, -2); -- 2.19.2

The port allocation APIs are currently called unconditionally for all types of NIC, but (mostly) only do anything for NICs with type=network. The exception is the port allocate API which does some validation even for NICs with type!=network. Relying on this validation is flawed, however, since the network driver may not even be installed. IOW virt drivers must not delegate validation to the network driver for NICs with type != network. This change allows us to report errors when the virtual network driver is not registered. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_conf.c | 12 +++---- src/libxl/libxl_domain.c | 6 ++-- src/libxl/libxl_driver.c | 9 +++-- src/lxc/lxc_driver.c | 6 ++-- src/lxc/lxc_process.c | 10 ++++-- src/network/bridge_driver.c | 66 ++++++++++++++++++------------------- src/qemu/qemu_hotplug.c | 17 ++++++---- src/qemu/qemu_process.c | 9 +++-- 8 files changed, 76 insertions(+), 59 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 706ee361ff..a3b539ccaa 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -30476,13 +30476,11 @@ int virDomainNetAllocateActualDevice(virDomainDefPtr dom, virDomainNetDefPtr iface) { - /* Just silently ignore if network driver isn't present. If something - * has tried to use a NIC with type=network, other code will already - * cause an error. This ensures type=bridge doesn't break when - * network driver is compiled out. - */ - if (!netAllocate) - return 0; + if (!netAllocate) { + virReportError(VIR_ERR_NO_SUPPORT, "%s", + _("Virtual networking driver is not available")); + return -1; + } return netAllocate(dom, iface); } diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 3ada51f517..e595e552b0 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -898,7 +898,8 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver, /* cleanup actual device */ virDomainNetRemoveHostdev(vm->def, net); - virDomainNetReleaseActualDevice(vm->def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) + virDomainNetReleaseActualDevice(vm->def, net); } } @@ -1055,7 +1056,8 @@ libxlNetworkPrepareDevices(virDomainDefPtr def) * network's pool of devices, or resolve bridge device name * to the one defined in the network definition. */ - if (virDomainNetAllocateActualDevice(def, net) < 0) + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && + virDomainNetAllocateActualDevice(def, net) < 0) return -1; actualType = virDomainNetGetActualType(net); diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 3d03e7320a..d702873892 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -3396,7 +3396,8 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, * network's pool of devices, or resolve bridge device name * to the one defined in the network definition. */ - if (virDomainNetAllocateActualDevice(vm->def, net) < 0) + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && + virDomainNetAllocateActualDevice(vm->def, net) < 0) goto cleanup; actualType = virDomainNetGetActualType(net); @@ -3446,7 +3447,8 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, vm->def->nets[vm->def->nnets++] = net; } else { virDomainNetRemoveHostdev(vm->def, net); - virDomainNetReleaseActualDevice(vm->def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) + virDomainNetReleaseActualDevice(vm->def, net); } virObjectUnref(cfg); return ret; @@ -3869,7 +3871,8 @@ libxlDomainDetachNetDevice(libxlDriverPrivatePtr driver, cleanup: libxl_device_nic_dispose(&nic); if (!ret) { - virDomainNetReleaseActualDevice(vm->def, detach); + if (detach->type == VIR_DOMAIN_NET_TYPE_NETWORK) + virDomainNetReleaseActualDevice(vm->def, detach); virDomainNetRemove(vm->def, detachidx); } virObjectUnref(cfg); diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index de045c80bb..a5eaf12ce1 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3867,7 +3867,8 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn, * network's pool of devices, or resolve bridge device name * to the one defined in the network definition. */ - if (virDomainNetAllocateActualDevice(vm->def, net) < 0) + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && + virDomainNetAllocateActualDevice(vm->def, net) < 0) return -1; actualType = virDomainNetGetActualType(net); @@ -4421,7 +4422,8 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm, ret = 0; cleanup: if (!ret) { - virDomainNetReleaseActualDevice(vm->def, detach); + if (detach->type == VIR_DOMAIN_NET_TYPE_NETWORK) + virDomainNetReleaseActualDevice(vm->def, detach); virDomainNetRemove(vm->def, detachidx); virDomainNetDefFree(detach); } diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 33c806630b..7a6b40d9b8 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -213,7 +213,8 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver, iface->ifname)); ignore_value(virNetDevVethDelete(iface->ifname)); } - virDomainNetReleaseActualDevice(vm->def, iface); + if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK) + virDomainNetReleaseActualDevice(vm->def, iface); } virDomainConfVMNWFilterTeardown(vm); @@ -547,6 +548,10 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, if (virLXCProcessValidateInterface(net) < 0) goto cleanup; + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && + virDomainNetAllocateActualDevice(def, net) < 0) + goto cleanup; + if (virDomainNetAllocateActualDevice(def, net) < 0) goto cleanup; @@ -626,7 +631,8 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, ignore_value(virNetDevOpenvswitchRemovePort( virDomainNetGetActualBridgeName(iface), iface->ifname)); - virDomainNetReleaseActualDevice(def, iface); + if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK) + virDomainNetReleaseActualDevice(def, iface); } } return ret; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index aed80c04d5..6555a020aa 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -4452,8 +4452,11 @@ networkAllocateActualDevice(virDomainDefPtr dom, size_t i; int ret = -1; - if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) - goto validate; + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Expected a interface for a virtual network")); + goto error; + } virDomainActualNetDefFree(iface->data.network.actual); iface->data.network.actual = NULL; @@ -4772,7 +4775,6 @@ networkAllocateActualDevice(virDomainDefPtr dom, if (virNetDevVPortProfileCheckComplete(virtport, true) < 0) goto error; - validate: /* make sure that everything now specified for the device is * actually supported on this type of network. NB: network, * netdev, and iface->data.network.actual may all be NULL. @@ -4791,19 +4793,11 @@ networkAllocateActualDevice(virDomainDefPtr dom, (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE && virtport && virtport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH))) { - if (netdef) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("an interface connecting to network '%s' " - "is requesting a vlan tag, but that is not " - "supported for this type of network"), - netdef->name); - } else { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("an interface of type '%s' " - "is requesting a vlan tag, but that is not " - "supported for this type of connection"), - virDomainNetTypeToString(iface->type)); - } + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("an interface connecting to network '%s' " + "is requesting a vlan tag, but that is not " + "supported for this type of network"), + netdef->name); goto error; } } @@ -4819,22 +4813,20 @@ networkAllocateActualDevice(virDomainDefPtr dom, } } - if (netdef) { - netdef->connections++; + netdef->connections++; + if (dev) + dev->connections++; + /* finally we can call the 'plugged' hook script if any */ + if (networkRunHook(obj, dom, iface, + VIR_HOOK_NETWORK_OP_IFACE_PLUGGED, + VIR_HOOK_SUBOP_BEGIN) < 0) { + /* adjust for failure */ + netdef->connections--; if (dev) - dev->connections++; - /* finally we can call the 'plugged' hook script if any */ - if (networkRunHook(obj, dom, iface, - VIR_HOOK_NETWORK_OP_IFACE_PLUGGED, - VIR_HOOK_SUBOP_BEGIN) < 0) { - /* adjust for failure */ - netdef->connections--; - if (dev) - dev->connections--; - goto error; - } - networkLogAllocation(netdef, actualType, dev, iface, true); + dev->connections--; + goto error; } + networkLogAllocation(netdef, actualType, dev, iface, true); ret = 0; @@ -4875,8 +4867,11 @@ networkNotifyActualDevice(virDomainDefPtr dom, size_t i; char *master = NULL; - if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) - return; + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Expected a interface for a virtual network")); + goto error; + } obj = virNetworkObjFindByName(driver->networks, iface->data.network.name); if (!obj) { @@ -5108,8 +5103,11 @@ networkReleaseActualDevice(virDomainDefPtr dom, size_t i; int ret = -1; - if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) - return 0; + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Expected a interface for a virtual network")); + goto error; + } obj = virNetworkObjFindByName(driver->networks, iface->data.network.name); if (!obj) { diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 8da023315b..663a59b0b3 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1336,7 +1336,8 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, * network's pool of devices, or resolve bridge device name * to the one defined in the network definition. */ - if (virDomainNetAllocateActualDevice(vm->def, net) < 0) + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && + virDomainNetAllocateActualDevice(vm->def, net) < 0) goto cleanup; actualType = virDomainNetGetActualType(net); @@ -1640,7 +1641,8 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, virDomainNetRemoveHostdev(vm->def, net); - virDomainNetReleaseActualDevice(vm->def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) + virDomainNetReleaseActualDevice(vm->def, net); } VIR_FREE(nicstr); @@ -4050,7 +4052,8 @@ qemuDomainChangeNet(virQEMUDriverPtr driver, /* this function doesn't work with HOSTDEV networks yet, thus * no need to change the pointer in the hostdev structure */ - virDomainNetReleaseActualDevice(vm->def, olddev); + if (olddev->type == VIR_DOMAIN_NET_TYPE_NETWORK) + virDomainNetReleaseActualDevice(vm->def, olddev); virDomainNetDefFree(olddev); /* move newdev into the nets list, and NULL it out from the * virDomainDeviceDef that we were given so that the caller @@ -4081,7 +4084,7 @@ qemuDomainChangeNet(virQEMUDriverPtr driver, * that the changes were minor enough that we didn't need to * replace the entire device object. */ - if (newdev) + if (newdev && newdev->type == VIR_DOMAIN_NET_TYPE_NETWORK) virDomainNetReleaseActualDevice(vm->def, newdev); return ret; @@ -4639,7 +4642,8 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver, virDomainHostdevDefFree(hostdev); if (net) { - virDomainNetReleaseActualDevice(vm->def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) + virDomainNetReleaseActualDevice(vm->def, net); virDomainNetDefFree(net); } @@ -4735,7 +4739,8 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver, qemuDomainNetDeviceVportRemove(net); - virDomainNetReleaseActualDevice(vm->def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) + virDomainNetReleaseActualDevice(vm->def, net); virDomainNetDefFree(net); ret = 0; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index d061591f62..d9baff587e 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3196,7 +3196,8 @@ qemuProcessNotifyNets(virDomainDefPtr def) if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) ignore_value(virNetDevMacVLanReserveName(net->ifname, false)); - virDomainNetNotifyActualDevice(def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) + virDomainNetNotifyActualDevice(def, net); } } @@ -5385,7 +5386,8 @@ qemuProcessNetworkPrepareDevices(virDomainDefPtr def) * network's pool of devices, or resolve bridge device name * to the one defined in the network definition. */ - if (virDomainNetAllocateActualDevice(def, net) < 0) + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && + virDomainNetAllocateActualDevice(def, net) < 0) goto cleanup; actualType = virDomainNetGetActualType(net); @@ -7225,7 +7227,8 @@ void qemuProcessStop(virQEMUDriverPtr driver, /* kick the device out of the hostdev list too */ virDomainNetRemoveHostdev(def, net); - virDomainNetReleaseActualDevice(vm->def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) + virDomainNetReleaseActualDevice(vm->def, net); } retry: -- 2.19.2

On 12/24/18 3:58 PM, Daniel P. Berrangé wrote:
The port allocation APIs are currently called unconditionally for all types of NIC, but (mostly) only do anything for NICs with type=network.
The exception is the port allocate API which does some validation even for NICs with type!=network. Relying on this validation is flawed, however, since the network driver may not even be installed. IOW virt drivers must not delegate validation to the network driver for NICs with type != network.
This change allows us to report errors when the virtual network driver is not registered.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_conf.c | 12 +++---- src/libxl/libxl_domain.c | 6 ++-- src/libxl/libxl_driver.c | 9 +++-- src/lxc/lxc_driver.c | 6 ++-- src/lxc/lxc_process.c | 10 ++++-- src/network/bridge_driver.c | 66 ++++++++++++++++++------------------- src/qemu/qemu_hotplug.c | 17 ++++++---- src/qemu/qemu_process.c | 9 +++-- 8 files changed, 76 insertions(+), 59 deletions(-)
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 33c806630b..7a6b40d9b8 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c
@@ -547,6 +548,10 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, if (virLXCProcessValidateInterface(net) < 0) goto cleanup;
+ if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && + virDomainNetAllocateActualDevice(def, net) < 0) + goto cleanup; + if (virDomainNetAllocateActualDevice(def, net) < 0) goto cleanup;
This looks fishy. Even though you fix it later in the series. Michal

On Tue, Jan 08, 2019 at 05:15:48PM +0100, Michal Privoznik wrote:
On 12/24/18 3:58 PM, Daniel P. Berrangé wrote:
The port allocation APIs are currently called unconditionally for all types of NIC, but (mostly) only do anything for NICs with type=network.
The exception is the port allocate API which does some validation even for NICs with type!=network. Relying on this validation is flawed, however, since the network driver may not even be installed. IOW virt drivers must not delegate validation to the network driver for NICs with type != network.
This change allows us to report errors when the virtual network driver is not registered.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_conf.c | 12 +++---- src/libxl/libxl_domain.c | 6 ++-- src/libxl/libxl_driver.c | 9 +++-- src/lxc/lxc_driver.c | 6 ++-- src/lxc/lxc_process.c | 10 ++++-- src/network/bridge_driver.c | 66 ++++++++++++++++++------------------- src/qemu/qemu_hotplug.c | 17 ++++++---- src/qemu/qemu_process.c | 9 +++-- 8 files changed, 76 insertions(+), 59 deletions(-)
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 33c806630b..7a6b40d9b8 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c
@@ -547,6 +548,10 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, if (virLXCProcessValidateInterface(net) < 0) goto cleanup;
+ if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && + virDomainNetAllocateActualDevice(def, net) < 0) + goto cleanup; + if (virDomainNetAllocateActualDevice(def, net) < 0) goto cleanup;
This looks fishy. Even though you fix it later in the series.
Well spotted, that is clearly nonsense ! Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

The APIs for allocating/notifying/removing network ports just take an internal domain interface struct right now. As a step towards turning these into public facing APIs, add a virNetworkPtr argument to all of them. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_conf.c | 40 ++++++++++++++++++++---- src/conf/domain_conf.h | 18 +++++++---- src/libxl/libxl_domain.c | 30 +++++++++++++----- src/libxl/libxl_driver.c | 26 +++++++++++----- src/lxc/lxc_driver.c | 24 +++++++++++--- src/lxc/lxc_process.c | 27 ++++++++++------ src/network/bridge_driver.c | 54 ++++++++++++++++++-------------- src/qemu/qemu_hotplug.c | 62 +++++++++++++++++++++++++++---------- src/qemu/qemu_process.c | 30 +++++++++++++----- 9 files changed, 223 insertions(+), 88 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index a3b539ccaa..3320a03572 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -30473,37 +30473,65 @@ virDomainNetSetDeviceImpl(virDomainNetAllocateActualDeviceImpl allocate, } int -virDomainNetAllocateActualDevice(virDomainDefPtr dom, +virDomainNetAllocateActualDevice(virConnectPtr conn, + virDomainDefPtr dom, virDomainNetDefPtr iface) { + virNetworkPtr net = NULL; + int ret = -1; + if (!netAllocate) { virReportError(VIR_ERR_NO_SUPPORT, "%s", _("Virtual networking driver is not available")); return -1; } - return netAllocate(dom, iface); + if (!(net = virNetworkLookupByName(conn, iface->data.network.name))) + return -1; + + ret = netAllocate(net, dom, iface); + + virObjectUnref(net); + return ret; } void -virDomainNetNotifyActualDevice(virDomainDefPtr dom, +virDomainNetNotifyActualDevice(virConnectPtr conn, + virDomainDefPtr dom, virDomainNetDefPtr iface) { + virNetworkPtr net = NULL; + if (!netNotify) return; - netNotify(dom, iface); + if (!(net = virNetworkLookupByName(conn, iface->data.network.name))) + return; + + netNotify(net, dom, iface); + + virObjectUnref(net); } int -virDomainNetReleaseActualDevice(virDomainDefPtr dom, +virDomainNetReleaseActualDevice(virConnectPtr conn, + virDomainDefPtr dom, virDomainNetDefPtr iface) { + virNetworkPtr net = NULL; + int ret; + if (!netRelease) return 0; - return netRelease(dom, iface); + if (!(net = virNetworkLookupByName(conn, iface->data.network.name))) + return -1; + + ret = netRelease(net, dom, iface); + + virObjectUnref(net); + return ret; } bool diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 5814997bdb..e611457314 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3600,15 +3600,18 @@ virDomainDefLifecycleActionAllowed(virDomainLifecycle type, virDomainLifecycleAction action); typedef int -(*virDomainNetAllocateActualDeviceImpl)(virDomainDefPtr dom, +(*virDomainNetAllocateActualDeviceImpl)(virNetworkPtr net, + virDomainDefPtr dom, virDomainNetDefPtr iface); typedef void -(*virDomainNetNotifyActualDeviceImpl)(virDomainDefPtr dom, +(*virDomainNetNotifyActualDeviceImpl)(virNetworkPtr net, + virDomainDefPtr dom, virDomainNetDefPtr iface); typedef int -(*virDomainNetReleaseActualDeviceImpl)(virDomainDefPtr dom, +(*virDomainNetReleaseActualDeviceImpl)(virNetworkPtr net, + virDomainDefPtr dom, virDomainNetDefPtr iface); typedef bool @@ -3628,17 +3631,20 @@ virDomainNetSetDeviceImpl(virDomainNetAllocateActualDeviceImpl allocate, virDomainNetBandwidthUpdateImpl bandwidthUpdate); int -virDomainNetAllocateActualDevice(virDomainDefPtr dom, +virDomainNetAllocateActualDevice(virConnectPtr conn, + virDomainDefPtr dom, virDomainNetDefPtr iface) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); void -virDomainNetNotifyActualDevice(virDomainDefPtr dom, +virDomainNetNotifyActualDevice(virConnectPtr conn, + virDomainDefPtr dom, virDomainNetDefPtr iface) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); int -virDomainNetReleaseActualDevice(virDomainDefPtr dom, +virDomainNetReleaseActualDevice(virConnectPtr conn, + virDomainDefPtr dom, virDomainNetDefPtr iface) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index e595e552b0..ddb64083b1 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -35,6 +35,7 @@ #include "virtime.h" #include "locking/domain_lock.h" #include "xen_common.h" +#include "driver.h" #define VIR_FROM_THIS VIR_FROM_LIBXL @@ -839,6 +840,7 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver, char *file; virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; unsigned int hostdev_flags = VIR_HOSTDEV_SP_PCI; + virConnectPtr conn = NULL; #ifdef LIBXL_HAVE_PVUSB hostdev_flags |= VIR_HOSTDEV_SP_USB; @@ -898,8 +900,12 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver, /* cleanup actual device */ virDomainNetRemoveHostdev(vm->def, net); - if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) - virDomainNetReleaseActualDevice(vm->def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (conn || (conn = virGetConnectNetwork())) + virDomainNetReleaseActualDevice(conn, vm->def, net); + else + VIR_WARN("Unable to release network device '%s'", NULLSTR(net->ifname)); + } } } @@ -922,6 +928,7 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver, virDomainObjRemoveTransientDef(vm); virObjectUnref(cfg); + virObjectUnref(conn); } /* @@ -1047,6 +1054,8 @@ static int libxlNetworkPrepareDevices(virDomainDefPtr def) { size_t i; + virConnectPtr conn = NULL; + int ret = -1; for (i = 0; i < def->nnets; i++) { virDomainNetDefPtr net = def->nets[i]; @@ -1056,9 +1065,12 @@ libxlNetworkPrepareDevices(virDomainDefPtr def) * network's pool of devices, or resolve bridge device name * to the one defined in the network definition. */ - if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && - virDomainNetAllocateActualDevice(def, net) < 0) - return -1; + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (!conn && !(conn = virGetConnectNetwork())) + goto cleanup; + if (virDomainNetAllocateActualDevice(conn, def, net) < 0) + goto cleanup; + } actualType = virDomainNetGetActualType(net); if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV && @@ -1078,10 +1090,14 @@ libxlNetworkPrepareDevices(virDomainDefPtr def) pcisrc->backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN; if (virDomainHostdevInsert(def, hostdev) < 0) - return -1; + goto cleanup; } } - return 0; + + ret = 0; + cleanup: + virObjectUnref(conn); + return ret; } static void diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index d702873892..faebb40d31 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -3385,6 +3385,7 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, libxl_device_nic nic; int ret = -1; char mac[VIR_MAC_STRING_BUFLEN]; + virConnectPtr conn = NULL; libxl_device_nic_init(&nic); @@ -3396,9 +3397,12 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, * network's pool of devices, or resolve bridge device name * to the one defined in the network definition. */ - if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && - virDomainNetAllocateActualDevice(vm->def, net) < 0) - goto cleanup; + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (!(conn = virGetConnectNetwork())) + goto cleanup; + if (virDomainNetAllocateActualDevice(conn, vm->def, net) < 0) + goto cleanup; + } actualType = virDomainNetGetActualType(net); @@ -3447,9 +3451,10 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver, vm->def->nets[vm->def->nnets++] = net; } else { virDomainNetRemoveHostdev(vm->def, net); - if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) - virDomainNetReleaseActualDevice(vm->def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && conn) + virDomainNetReleaseActualDevice(conn, vm->def, net); } + virObjectUnref(conn); virObjectUnref(cfg); return ret; } @@ -3871,8 +3876,15 @@ libxlDomainDetachNetDevice(libxlDriverPrivatePtr driver, cleanup: libxl_device_nic_dispose(&nic); if (!ret) { - if (detach->type == VIR_DOMAIN_NET_TYPE_NETWORK) - virDomainNetReleaseActualDevice(vm->def, detach); + if (detach->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + virConnectPtr conn = virGetConnectNetwork(); + if (conn) { + virDomainNetReleaseActualDevice(conn, vm->def, detach); + virObjectUnref(conn); + } else { + VIR_WARN("Unable to release network device '%s'", NULLSTR(detach->ifname)); + } + } virDomainNetRemove(vm->def, detachidx); } virObjectUnref(cfg); diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index a5eaf12ce1..f4138a0e10 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3867,9 +3867,16 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn, * network's pool of devices, or resolve bridge device name * to the one defined in the network definition. */ - if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && - virDomainNetAllocateActualDevice(vm->def, net) < 0) - return -1; + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + virConnectPtr netconn = virGetConnectNetwork(); + if (!netconn) + return -1; + if (virDomainNetAllocateActualDevice(netconn, vm->def, net) < 0) { + virObjectUnref(netconn); + return -1; + } + virObjectUnref(netconn); + } actualType = virDomainNetGetActualType(net); @@ -4422,8 +4429,15 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm, ret = 0; cleanup: if (!ret) { - if (detach->type == VIR_DOMAIN_NET_TYPE_NETWORK) - virDomainNetReleaseActualDevice(vm->def, detach); + if (detach->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + virConnectPtr conn = virGetConnectNetwork(); + if (conn) { + virDomainNetReleaseActualDevice(conn, vm->def, detach); + virObjectUnref(conn); + } else { + VIR_WARN("Unable to release network device '%s'", NULLSTR(detach->ifname)); + } + } virDomainNetRemove(vm->def, detachidx); virDomainNetDefFree(detach); } diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 7a6b40d9b8..cff67985e5 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -165,6 +165,7 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver, virLXCDomainObjPrivatePtr priv = vm->privateData; virNetDevVPortProfilePtr vport = NULL; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); + virConnectPtr conn = NULL; VIR_DEBUG("Cleanup VM name=%s pid=%d reason=%d", vm->def->name, (int)vm->pid, (int)reason); @@ -213,8 +214,12 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver, iface->ifname)); ignore_value(virNetDevVethDelete(iface->ifname)); } - if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK) - virDomainNetReleaseActualDevice(vm->def, iface); + if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (conn || (conn = virGetConnectNetwork())) + virDomainNetReleaseActualDevice(conn, vm->def, iface); + else + VIR_WARN("Unable to release network device '%s'", NULLSTR(iface->ifname)); + } } virDomainConfVMNWFilterTeardown(vm); @@ -532,6 +537,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, size_t niface = 0; virDomainNetDefPtr net; virDomainNetType type; + virConnectPtr netconn = NULL; if (VIR_ALLOC_N(*veths, def->nnets + 1) < 0) return -1; @@ -548,12 +554,12 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, if (virLXCProcessValidateInterface(net) < 0) goto cleanup; - if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && - virDomainNetAllocateActualDevice(def, net) < 0) - goto cleanup; - - if (virDomainNetAllocateActualDevice(def, net) < 0) - goto cleanup; + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (!netconn && !(netconn = virGetConnectNetwork())) + goto cleanup; + if (virDomainNetAllocateActualDevice(netconn, def, net) < 0) + goto cleanup; + } type = virDomainNetGetActualType(net); switch (type) { @@ -631,10 +637,11 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, ignore_value(virNetDevOpenvswitchRemovePort( virDomainNetGetActualBridgeName(iface), iface->ifname)); - if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK) - virDomainNetReleaseActualDevice(def, iface); + if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK && netconn) + virDomainNetReleaseActualDevice(netconn, def, iface); } } + virObjectUnref(netconn); return ret; } diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 6555a020aa..f3cdf40bfb 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -4437,7 +4437,8 @@ networkLogAllocation(virNetworkDefPtr netdef, * Returns 0 on success, -1 on failure. */ static int -networkAllocateActualDevice(virDomainDefPtr dom, +networkAllocateActualDevice(virNetworkPtr net, + virDomainDefPtr dom, virDomainNetDefPtr iface) { virNetworkDriverStatePtr driver = networkGetDriver(); @@ -4452,6 +4453,14 @@ networkAllocateActualDevice(virDomainDefPtr dom, size_t i; int ret = -1; + obj = virNetworkObjFindByName(driver->networks, net->name); + if (!obj) { + virReportError(VIR_ERR_NO_NETWORK, + _("no network with matching name '%s'"), + net->name); + goto error; + } + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Expected a interface for a virtual network")); @@ -4461,13 +4470,6 @@ networkAllocateActualDevice(virDomainDefPtr dom, virDomainActualNetDefFree(iface->data.network.actual); iface->data.network.actual = NULL; - obj = virNetworkObjFindByName(driver->networks, iface->data.network.name); - if (!obj) { - virReportError(VIR_ERR_NO_NETWORK, - _("no network with matching name '%s'"), - iface->data.network.name); - goto error; - } netdef = virNetworkObjGetDef(obj); if (!virNetworkObjIsActive(obj)) { @@ -4856,7 +4858,8 @@ networkAllocateActualDevice(virDomainDefPtr dom, * No return value (but does log any failures) */ static void -networkNotifyActualDevice(virDomainDefPtr dom, +networkNotifyActualDevice(virNetworkPtr net, + virDomainDefPtr dom, virDomainNetDefPtr iface) { virNetworkDriverStatePtr driver = networkGetDriver(); @@ -4867,19 +4870,20 @@ networkNotifyActualDevice(virDomainDefPtr dom, size_t i; char *master = NULL; + obj = virNetworkObjFindByName(driver->networks, net->name); + if (!obj) { + virReportError(VIR_ERR_NO_NETWORK, + _("no network with matching name '%s'"), + net->name); + goto error; + } + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Expected a interface for a virtual network")); goto error; } - obj = virNetworkObjFindByName(driver->networks, iface->data.network.name); - if (!obj) { - virReportError(VIR_ERR_NO_NETWORK, - _("no network with matching name '%s'"), - iface->data.network.name); - goto error; - } netdef = virNetworkObjGetDef(obj); if (!virNetworkObjIsActive(obj)) { @@ -5092,7 +5096,8 @@ networkNotifyActualDevice(virDomainDefPtr dom, * Returns 0 on success, -1 on failure. */ static int -networkReleaseActualDevice(virDomainDefPtr dom, +networkReleaseActualDevice(virNetworkPtr net, + virDomainDefPtr dom, virDomainNetDefPtr iface) { virNetworkDriverStatePtr driver = networkGetDriver(); @@ -5103,19 +5108,20 @@ networkReleaseActualDevice(virDomainDefPtr dom, size_t i; int ret = -1; + obj = virNetworkObjFindByName(driver->networks, net->name); + if (!obj) { + virReportError(VIR_ERR_NO_NETWORK, + _("no network with matching name '%s'"), + net->name); + goto error; + } + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Expected a interface for a virtual network")); goto error; } - obj = virNetworkObjFindByName(driver->networks, iface->data.network.name); - if (!obj) { - virReportError(VIR_ERR_NO_NETWORK, - _("no network with matching name '%s'"), - iface->data.network.name); - goto error; - } netdef = virNetworkObjGetDef(obj); switch ((virNetworkForwardType) netdef->forward.type) { diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 663a59b0b3..575c5854d3 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1327,6 +1327,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, bool charDevPlugged = false; bool netdevPlugged = false; char *netdev_name; + virConnectPtr conn = NULL; /* preallocate new slot for device */ if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) @@ -1336,9 +1337,12 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, * network's pool of devices, or resolve bridge device name * to the one defined in the network definition. */ - if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && - virDomainNetAllocateActualDevice(vm->def, net) < 0) - goto cleanup; + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (!(conn = virGetConnectNetwork())) + goto cleanup; + if (virDomainNetAllocateActualDevice(conn, vm->def, net) < 0) + goto cleanup; + } actualType = virDomainNetGetActualType(net); @@ -1641,8 +1645,12 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, virDomainNetRemoveHostdev(vm->def, net); - if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) - virDomainNetReleaseActualDevice(vm->def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (conn) + virDomainNetReleaseActualDevice(conn, vm->def, net); + else + VIR_WARN("Unable to release network device '%s'", NULLSTR(net->ifname)); + } } VIR_FREE(nicstr); @@ -1662,6 +1670,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, VIR_FREE(vhostfd); VIR_FREE(vhostfdName); VIR_FREE(charDevAlias); + virObjectUnref(conn); virObjectUnref(cfg); virDomainCCWAddressSetFree(ccwaddrs); @@ -3664,6 +3673,7 @@ qemuDomainChangeNet(virQEMUDriverPtr driver, bool needVlanUpdate = false; int ret = -1; int changeidx = -1; + virConnectPtr conn = NULL; if ((changeidx = virDomainNetFindIdx(vm->def, newdev)) < 0) goto cleanup; @@ -3839,9 +3849,11 @@ qemuDomainChangeNet(virQEMUDriverPtr driver, /* allocate new actual device to compare to old - we will need to * free it if we fail for any reason */ - if (newdev->type == VIR_DOMAIN_NET_TYPE_NETWORK && - virDomainNetAllocateActualDevice(vm->def, newdev) < 0) { - goto cleanup; + if (newdev->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (!(conn = virGetConnectNetwork())) + goto cleanup; + if (virDomainNetAllocateActualDevice(conn, vm->def, newdev) < 0) + goto cleanup; } newType = virDomainNetGetActualType(newdev); @@ -4052,8 +4064,12 @@ qemuDomainChangeNet(virQEMUDriverPtr driver, /* this function doesn't work with HOSTDEV networks yet, thus * no need to change the pointer in the hostdev structure */ - if (olddev->type == VIR_DOMAIN_NET_TYPE_NETWORK) - virDomainNetReleaseActualDevice(vm->def, olddev); + if (olddev->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (conn || (conn = virGetConnectNetwork())) + virDomainNetReleaseActualDevice(conn, vm->def, olddev); + else + VIR_WARN("Unable to release network device '%s'", NULLSTR(olddev->ifname)); + } virDomainNetDefFree(olddev); /* move newdev into the nets list, and NULL it out from the * virDomainDeviceDef that we were given so that the caller @@ -4084,8 +4100,8 @@ qemuDomainChangeNet(virQEMUDriverPtr driver, * that the changes were minor enough that we didn't need to * replace the entire device object. */ - if (newdev && newdev->type == VIR_DOMAIN_NET_TYPE_NETWORK) - virDomainNetReleaseActualDevice(vm->def, newdev); + if (newdev && newdev->type == VIR_DOMAIN_NET_TYPE_NETWORK && conn) + virDomainNetReleaseActualDevice(conn, vm->def, newdev); return ret; } @@ -4642,8 +4658,15 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver, virDomainHostdevDefFree(hostdev); if (net) { - if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) - virDomainNetReleaseActualDevice(vm->def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + virConnectPtr conn = virGetConnectNetwork(); + if (conn) { + virDomainNetReleaseActualDevice(conn, vm->def, net); + virObjectUnref(conn); + } else { + VIR_WARN("Unable to release network device '%s'", NULLSTR(net->ifname)); + } + } virDomainNetDefFree(net); } @@ -4739,8 +4762,15 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver, qemuDomainNetDeviceVportRemove(net); - if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) - virDomainNetReleaseActualDevice(vm->def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + virConnectPtr conn = virGetConnectNetwork(); + if (conn) { + virDomainNetReleaseActualDevice(conn, vm->def, net); + virObjectUnref(conn); + } else { + VIR_WARN("Unable to release network device '%s'", NULLSTR(net->ifname)); + } + } virDomainNetDefFree(net); ret = 0; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index d9baff587e..5597436fba 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3185,6 +3185,7 @@ static void qemuProcessNotifyNets(virDomainDefPtr def) { size_t i; + virConnectPtr conn = NULL; for (i = 0; i < def->nnets; i++) { virDomainNetDefPtr net = def->nets[i]; @@ -3196,9 +3197,14 @@ qemuProcessNotifyNets(virDomainDefPtr def) if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) ignore_value(virNetDevMacVLanReserveName(net->ifname, false)); - if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) - virDomainNetNotifyActualDevice(def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (!conn && !(conn = virGetConnectNetwork())) + continue; + virDomainNetNotifyActualDevice(conn, def, net); + } } + + virObjectUnref(conn); } /* Attempt to instantiate the filters. Ignore failures because it's @@ -5377,6 +5383,7 @@ qemuProcessNetworkPrepareDevices(virDomainDefPtr def) { int ret = -1; size_t i; + virConnectPtr conn = NULL; for (i = 0; i < def->nnets; i++) { virDomainNetDefPtr net = def->nets[i]; @@ -5386,9 +5393,12 @@ qemuProcessNetworkPrepareDevices(virDomainDefPtr def) * network's pool of devices, or resolve bridge device name * to the one defined in the network definition. */ - if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && - virDomainNetAllocateActualDevice(def, net) < 0) - goto cleanup; + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (!conn && !(conn = virGetConnectNetwork())) + goto cleanup; + if (virDomainNetAllocateActualDevice(conn, def, net) < 0) + goto cleanup; + } actualType = virDomainNetGetActualType(net); if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV && @@ -5419,6 +5429,7 @@ qemuProcessNetworkPrepareDevices(virDomainDefPtr def) } ret = 0; cleanup: + virObjectUnref(conn); return ret; } @@ -7027,6 +7038,7 @@ void qemuProcessStop(virQEMUDriverPtr driver, size_t i; char *timestamp; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + virConnectPtr conn = NULL; VIR_DEBUG("Shutting down vm=%p name=%s id=%d pid=%lld, " "reason=%s, asyncJob=%s, flags=0x%x", @@ -7227,8 +7239,12 @@ void qemuProcessStop(virQEMUDriverPtr driver, /* kick the device out of the hostdev list too */ virDomainNetRemoveHostdev(def, net); - if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) - virDomainNetReleaseActualDevice(vm->def, net); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (conn || (conn = virGetConnectNetwork())) + virDomainNetReleaseActualDevice(conn, vm->def, net); + else + VIR_WARN("Unable to release network device '%s'", NULLSTR(net->ifname)); + } } retry: -- 2.19.2

hostdevs have a link back to the original network device. This is fairly generic accepting any type of device, however, we don't intend to make use of this approach in future. It can thus be specialized to network devices. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_conf.c | 18 ++++++++---------- src/conf/domain_conf.h | 8 +++++++- src/libxl/libxl_driver.c | 4 ++-- src/network/bridge_driver.c | 3 +-- src/qemu/qemu_command.c | 3 +-- src/qemu/qemu_domain_address.c | 4 ++-- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_hotplug.c | 14 ++++++-------- src/qemu/qemu_hotplug.h | 2 +- src/util/virhostdev.c | 17 ++++++++--------- 10 files changed, 37 insertions(+), 38 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 3320a03572..2181940144 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2614,7 +2614,7 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def) /* If there is a parent device object, it will handle freeing * def->info. */ - if (def->parent.type == VIR_DOMAIN_DEVICE_NONE) + if (!def->parent) virDomainDeviceInfoFree(def->info); switch (def->mode) { @@ -2685,7 +2685,7 @@ void virDomainHostdevDefFree(virDomainHostdevDefPtr def) /* If there is a parent device object, it will handle freeing * the memory. */ - if (def->parent.type == VIR_DOMAIN_DEVICE_NONE) + if (!def->parent) VIR_FREE(def); } @@ -5061,7 +5061,7 @@ virDomainDefCollectBootOrder(virDomainDefPtr def ATTRIBUTE_UNUSED, return 0; if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV && - dev->data.hostdev->parent.type != VIR_DOMAIN_DEVICE_NONE) { + dev->data.hostdev->parent) { /* This hostdev is a child of a higher level device * (e.g. interface), and thus already being counted on the * list for the other device type. @@ -5902,7 +5902,7 @@ virDomainDeviceDefValidateAliasesIterator(virDomainDefPtr def, return 0; if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV && - dev->data.hostdev->parent.type == VIR_DOMAIN_DEVICE_NET) { + dev->data.hostdev->parent) { /* This hostdev is a copy of some previous interface. * Aliases are duplicated. */ return 0; @@ -10842,8 +10842,7 @@ virDomainActualNetDefParseXML(xmlNodePtr node, } else if (actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) { virDomainHostdevDefPtr hostdev = &actual->data.hostdev.def; - hostdev->parent.type = VIR_DOMAIN_DEVICE_NET; - hostdev->parent.data.net = parent; + hostdev->parent = parent; hostdev->info = &parent->info; /* The helper function expects type to already be found and * passed in as a string, since it is in a different place in @@ -11499,8 +11498,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, case VIR_DOMAIN_NET_TYPE_HOSTDEV: hostdev = &def->data.hostdev.def; - hostdev->parent.type = VIR_DOMAIN_DEVICE_NET; - hostdev->parent.data.net = def; + hostdev->parent = def; hostdev->info = &def->info; /* The helper function expects type to already be found and * passed in as a string, since it is in a different place in @@ -28656,11 +28654,11 @@ virDomainDefFormatInternal(virDomainDefPtr def, } for (n = 0; n < def->nhostdevs; n++) { - /* If parent.type != NONE, this is just a pointer to the + /* If parent != NONE, this is just a pointer to the * hostdev in a higher-level device (e.g. virDomainNetDef), * and will have already been formatted there. */ - if (def->hostdevs[n]->parent.type == VIR_DOMAIN_DEVICE_NONE && + if (!def->hostdevs[n]->parent && virDomainHostdevDefFormat(buf, def->hostdevs[n], flags) < 0) { goto error; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e611457314..829d7cd83e 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -444,7 +444,13 @@ struct _virDomainHostdevCaps { /* basic device for direct passthrough */ struct _virDomainHostdevDef { - virDomainDeviceDef parent; /* higher level Def containing this */ + /* If 'parent' is non-NULL it means this host dev was + * not originally present in the XML. It was copied from + * a network interface for convenience when handling + * hostdevs internally. This hostdev should never be + * visible to the user except as part of the interface + */ + virDomainNetDefPtr parent; int mode; /* enum virDomainHostdevMode */ int startupPolicy; /* enum virDomainStartupPolicy */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index faebb40d31..1690400db6 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -3921,9 +3921,9 @@ libxlDomainDetachDeviceLive(libxlDriverPrivatePtr driver, /* If this is a network hostdev, we need to use the higher-level * detach function so that mac address / virtualport are reset */ - if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET) + if (hostdev->parent) ret = libxlDomainDetachNetDevice(driver, vm, - hostdev->parent.data.net); + hostdev->parent); else ret = libxlDomainDetachHostDevice(driver, vm, hostdev); break; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index f3cdf40bfb..b5aac9350b 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -4570,8 +4570,7 @@ networkAllocateActualDevice(virNetworkPtr net, netdef->name); goto error; } - iface->data.network.actual->data.hostdev.def.parent.type = VIR_DOMAIN_DEVICE_NET; - iface->data.network.actual->data.hostdev.def.parent.data.net = iface; + iface->data.network.actual->data.hostdev.def.parent = iface; iface->data.network.actual->data.hostdev.def.info = &iface->info; iface->data.network.actual->data.hostdev.def.mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; iface->data.network.actual->data.hostdev.def.managed = netdef->forward.managed ? 1 : 0; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 66a4a35184..8bce416d83 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5466,8 +5466,7 @@ qemuBuildHostdevCommandLine(virCommandPtr cmd, /* bootNet will be non-0 if boot order was set and no other * net devices were encountered */ - if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET && - bootIndex == 0) { + if (hostdev->parent && bootIndex == 0) { bootIndex = *bootHostdevNet; *bootHostdevNet = 0; } diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index bd6c4031e0..73d53e08a9 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1436,7 +1436,7 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, if (!virDeviceInfoPCIAddressIsPresent(info) || ((device->type == VIR_DOMAIN_DEVICE_HOSTDEV) && - (device->data.hostdev->parent.type != VIR_DOMAIN_DEVICE_NONE))) { + device->data.hostdev->parent)) { /* If a hostdev has a parent, its info will be a part of the * parent, and will have its address collected during the scan * of the parent's device type. @@ -1531,7 +1531,7 @@ qemuDomainCollectPCIAddressExtension(virDomainDefPtr def ATTRIBUTE_UNUSED, if (!virDeviceInfoPCIAddressExtensionIsPresent(info) || ((device->type == VIR_DOMAIN_DEVICE_HOSTDEV) && - (device->data.hostdev->parent.type != VIR_DOMAIN_DEVICE_NONE))) { + device->data.hostdev->parent)) { /* If a hostdev has a parent, its info will be a part of the * parent, and will have its address collected during the scan * of the parent's device type. diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ea316f61d1..b69db58a44 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -8023,7 +8023,7 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm, ret = qemuDomainDetachLease(driver, vm, dev->data.lease); break; case VIR_DOMAIN_DEVICE_NET: - ret = qemuDomainDetachNetDevice(driver, vm, dev, async); + ret = qemuDomainDetachNetDevice(driver, vm, dev->data.net, async); break; case VIR_DOMAIN_DEVICE_HOSTDEV: ret = qemuDomainDetachHostDevice(driver, vm, dev, async); diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 575c5854d3..c7c26e7685 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -4601,11 +4601,9 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver, event = virDomainEventDeviceRemovedNewFromObj(vm, hostdev->info->alias); virObjectEventStateQueue(driver->domainEventState, event); - if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET) { - net = hostdev->parent.data.net; - + if (hostdev->parent) { for (i = 0; i < vm->def->nnets; i++) { - if (vm->def->nets[i] == net) { + if (vm->def->nets[i] == hostdev->parent) { virDomainNetRemove(vm->def, i); break; } @@ -5797,8 +5795,8 @@ int qemuDomainDetachHostDevice(virQEMUDriverPtr driver, /* If this is a network hostdev, we need to use the higher-level detach * function so that mac address / virtualport are reset */ - if (detach->parent.type == VIR_DOMAIN_DEVICE_NET) - return qemuDomainDetachNetDevice(driver, vm, &detach->parent, async); + if (detach->parent) + return qemuDomainDetachNetDevice(driver, vm, detach->parent, async); else return qemuDomainDetachThisHostDevice(driver, vm, detach, async); } @@ -5978,14 +5976,14 @@ qemuDomainDetachRedirdevDevice(virQEMUDriverPtr driver, int qemuDomainDetachNetDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, - virDomainDeviceDefPtr dev, + virDomainNetDefPtr net, bool async) { int detachidx, ret = -1; virDomainNetDefPtr detach = NULL; qemuDomainObjPrivatePtr priv = vm->privateData; - if ((detachidx = virDomainNetFindIdx(vm->def, dev->data.net)) < 0) + if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0) goto cleanup; detach = vm->def->nets[detachidx]; diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index 7ac03b7810..d3fa588aac 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -109,7 +109,7 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver, bool async); int qemuDomainDetachNetDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, - virDomainDeviceDefPtr dev, + virDomainNetDefPtr net, bool async); int qemuDomainDetachHostDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 41d4e8d936..4a1e760984 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -333,8 +333,7 @@ virHostdevIsPCINetDevice(virDomainHostdevDefPtr hostdev) { return hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && - hostdev->parent.type == VIR_DOMAIN_DEVICE_NET && - hostdev->parent.data.net; + hostdev->parent != NULL; } @@ -427,7 +426,7 @@ virHostdevSaveNetConfig(virDomainHostdevDefPtr hostdev, int vf = -1; if (!virHostdevIsPCINetDevice(hostdev) || - virDomainNetGetActualVirtPortProfile(hostdev->parent.data.net)) + virDomainNetGetActualVirtPortProfile(hostdev->parent)) return 0; if (virHostdevIsVirtualFunction(hostdev) != 1) { @@ -474,8 +473,8 @@ virHostdevSetNetConfig(virDomainHostdevDefPtr hostdev, if (virHostdevNetDevice(hostdev, -1, &linkdev, &vf) < 0) return -1; - vlan = virDomainNetGetActualVlan(hostdev->parent.data.net); - virtPort = virDomainNetGetActualVirtPortProfile(hostdev->parent.data.net); + vlan = virDomainNetGetActualVlan(hostdev->parent); + virtPort = virDomainNetGetActualVirtPortProfile(hostdev->parent); if (virtPort) { if (vlan) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -485,11 +484,11 @@ virHostdevSetNetConfig(virDomainHostdevDefPtr hostdev, return -1; } if (virHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort, - &hostdev->parent.data.net->mac, + &hostdev->parent->mac, uuid, port_profile_associate) < 0) return -1; } else { - if (virNetDevSetNetConfig(linkdev, vf, &hostdev->parent.data.net->mac, + if (virNetDevSetNetConfig(linkdev, vf, &hostdev->parent->mac, vlan, NULL, true) < 0) return -1; } @@ -535,10 +534,10 @@ virHostdevRestoreNetConfig(virDomainHostdevDefPtr hostdev, if (virHostdevNetDevice(hostdev, 0, &linkdev, &vf) < 0) return -1; - virtPort = virDomainNetGetActualVirtPortProfile(hostdev->parent.data.net); + virtPort = virDomainNetGetActualVirtPortProfile(hostdev->parent); if (virtPort) { return virHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort, - &hostdev->parent.data.net->mac, + &hostdev->parent->mac, NULL, port_profile_associate); } else { -- 2.19.2

In the case of a network with forward=bridge, which has a bridge device listed, we are capable of setting bandwidth limits but fail to call the function to register them. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index b5aac9350b..2639b5ce61 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -3374,7 +3374,13 @@ networkValidate(virNetworkDriverStatePtr driver, virNetworkForwardTypeToString(def->forward.type)); return -1; } - if (def->bandwidth) { + + bandwidthAllowed = ( + def->forward.type == VIR_NETWORK_FORWARD_BRIDGE && + def->bridge != NULL); + + if (def->bandwidth && + !bandwidthAllowed) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported network-wide <bandwidth> element " "in network %s with forward mode='%s'"), @@ -3382,7 +3388,6 @@ networkValidate(virNetworkDriverStatePtr driver, virNetworkForwardTypeToString(def->forward.type)); return -1; } - bandwidthAllowed = false; break; case VIR_NETWORK_FORWARD_LAST: @@ -4659,6 +4664,9 @@ networkAllocateActualDevice(virNetworkPtr net, goto error; } } + + if (networkPlugBandwidth(obj, iface) < 0) + goto error; break; } @@ -5133,6 +5141,11 @@ networkReleaseActualDevice(virNetworkPtr net, break; case VIR_NETWORK_FORWARD_BRIDGE: + if (iface->data.network.actual && + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE && + networkUnplugBandwidth(obj, iface) < 0) + goto error; + break; case VIR_NETWORK_FORWARD_PRIVATE: case VIR_NETWORK_FORWARD_VEPA: case VIR_NETWORK_FORWARD_PASSTHROUGH: -- 2.19.2

On 12/24/18 3:58 PM, Daniel P. Berrangé wrote:
In the case of a network with forward=bridge, which has a bridge device listed, we are capable of setting bandwidth limits but fail to call the function to register them.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index b5aac9350b..2639b5ce61 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -3374,7 +3374,13 @@ networkValidate(virNetworkDriverStatePtr driver, virNetworkForwardTypeToString(def->forward.type)); return -1; } - if (def->bandwidth) { + + bandwidthAllowed = ( + def->forward.type == VIR_NETWORK_FORWARD_BRIDGE && + def->bridge != NULL);
Whoa. This looks ugly. Can you please turn it into: bool bandwidthAllowed = false; if (...) bandwidthAllowed = true;
+ + if (def->bandwidth && + !bandwidthAllowed) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported network-wide <bandwidth> element " "in network %s with forward mode='%s'"),
Michal

On Tue, Jan 08, 2019 at 05:16:25PM +0100, Michal Privoznik wrote:
On 12/24/18 3:58 PM, Daniel P. Berrangé wrote:
In the case of a network with forward=bridge, which has a bridge device listed, we are capable of setting bandwidth limits but fail to call the function to register them.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index b5aac9350b..2639b5ce61 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -3374,7 +3374,13 @@ networkValidate(virNetworkDriverStatePtr driver, virNetworkForwardTypeToString(def->forward.type)); return -1; } - if (def->bandwidth) { + + bandwidthAllowed = ( + def->forward.type == VIR_NETWORK_FORWARD_BRIDGE && + def->bridge != NULL);
Whoa. This looks ugly. Can you please turn it into: bool bandwidthAllowed = false;
if (...) bandwidthAllowed = true;
Ok, i'll refactor this a little
+ + if (def->bandwidth && + !bandwidthAllowed) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported network-wide <bandwidth> element " "in network %s with forward mode='%s'"),
Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

Ports allocated on virtual networks with type=nat|route|open all get given an actual type of 'network'. Only ports in networks with type=bridge use an actual type of 'bridge'. This distinction makes little sense since the virtualization drivers will treat both actual types in exactly the same way, as they're all just bridge devices a VM needs to be connected to. This doesn't affect user visible XML since the "actual" device XML is internal only, but we need code to convert the data upgrades. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 2639b5ce61..822da7c6ac 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -4533,11 +4533,7 @@ networkAllocateActualDevice(virNetworkPtr net, case VIR_NETWORK_FORWARD_NAT: case VIR_NETWORK_FORWARD_ROUTE: case VIR_NETWORK_FORWARD_OPEN: - /* for these forward types, the actual net type really *is* - * NETWORK; we just keep the info from the portgroup in - * iface->data.network.actual - */ - iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_NETWORK; + iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_BRIDGE; /* we also store the bridge device and macTableManager settings * in iface->data.network.actual->data.bridge for later use @@ -4905,12 +4901,21 @@ networkNotifyActualDevice(virNetworkPtr net, * actualType==network, we need to copy it in so that it will be * available in all cases */ - if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK && + if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE && !iface->data.network.actual->data.bridge.brname && (VIR_STRDUP(iface->data.network.actual->data.bridge.brname, netdef->bridge) < 0)) goto error; + /* Older libvirtd uses actualType==network, but we now + * just use actualType==bridge, as nothing needs to + * distinguish the two cases, and this simplifies virt + * drive code */ + if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK) { + iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_BRIDGE; + actualType = VIR_DOMAIN_NET_TYPE_BRIDGE; + } + /* see if we're connected to the correct bridge */ if (netdef->bridge) { bool useOVS = false; -- 2.19.2

The call to resolve the actual network type will turn any NICs with type=network into one of the other types. Thus there should be no need to handle type=network in later switch() statements jumping off the actual type. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/libxl/libxl_conf.c | 21 +++------------------ src/lxc/lxc_driver.c | 15 +++++++++++---- src/qemu/qemu_command.c | 8 ++++++-- src/qemu/qemu_hotplug.c | 13 +++++++++++-- src/qemu/qemu_interface.c | 12 ++++++++++-- src/qemu/qemu_process.c | 5 ++++- 6 files changed, 45 insertions(+), 29 deletions(-) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 73e988a3dc..e7d0480b34 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1341,25 +1341,10 @@ libxlMakeNic(virDomainDefPtr def, } break; case VIR_DOMAIN_NET_TYPE_NETWORK: - { - if (!(conn = virConnectOpen("xen:///system"))) - goto cleanup; - - if (!(network = - virNetworkLookupByName(conn, l_nic->data.network.name))) { - goto cleanup; - } - - if (l_nic->guestIP.nips > 0) { - x_nic->ip = xenMakeIPList(&l_nic->guestIP); - if (!x_nic->ip) - goto cleanup; - } + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unexpectedly found type=network for actual NIC type")); + goto cleanup; - if (!(x_nic->bridge = virNetworkGetBridgeName(network))) - goto cleanup; - break; - } case VIR_DOMAIN_NET_TYPE_VHOSTUSER: case VIR_DOMAIN_NET_TYPE_USER: case VIR_DOMAIN_NET_TYPE_SERVER: diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index f4138a0e10..6162c05c46 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3881,8 +3881,7 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn, actualType = virDomainNetGetActualType(net); switch (actualType) { - case VIR_DOMAIN_NET_TYPE_BRIDGE: - case VIR_DOMAIN_NET_TYPE_NETWORK: { + case VIR_DOMAIN_NET_TYPE_BRIDGE: { const char *brname = virDomainNetGetActualBridgeName(net); if (!brname) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -3900,6 +3899,10 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn, if (!(veth = virLXCProcessSetupInterfaceDirect(conn, vm->def, net))) goto cleanup; } break; + case VIR_DOMAIN_NET_TYPE_NETWORK: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unexpectedly found type=network for actual NIC type")); + goto cleanup; case VIR_DOMAIN_NET_TYPE_USER: case VIR_DOMAIN_NET_TYPE_VHOSTUSER: case VIR_DOMAIN_NET_TYPE_SERVER: @@ -3945,7 +3948,6 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn, } else if (veth) { switch (actualType) { case VIR_DOMAIN_NET_TYPE_BRIDGE: - case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_ETHERNET: ignore_value(virNetDevVethDelete(veth)); break; @@ -3954,6 +3956,7 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn, ignore_value(virNetDevMacVLanDelete(veth)); break; + case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_USER: case VIR_DOMAIN_NET_TYPE_VHOSTUSER: case VIR_DOMAIN_NET_TYPE_SERVER: @@ -4385,7 +4388,6 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm, switch (actualType) { case VIR_DOMAIN_NET_TYPE_BRIDGE: - case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_ETHERNET: if (virNetDevVethDelete(detach->ifname) < 0) { virDomainAuditNet(vm, detach, NULL, "detach", false); @@ -4393,6 +4395,11 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm, } break; + case VIR_DOMAIN_NET_TYPE_NETWORK: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unexpectedly found type=network for actual NIC type")); + goto cleanup; + /* It'd be nice to support this, but with macvlan * once assigned to a container nothing exists on * the host side. Further the container can change diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8bce416d83..b9274e5a81 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8527,7 +8527,6 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, } switch (actualType) { - case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_BRIDGE: tapfdSize = net->driver.virtio.queues; if (!tapfdSize) @@ -8605,6 +8604,11 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, break; + case VIR_DOMAIN_NET_TYPE_NETWORK: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unexpectedly found type=network for actual NIC type")); + goto cleanup; + case VIR_DOMAIN_NET_TYPE_USER: case VIR_DOMAIN_NET_TYPE_SERVER: case VIR_DOMAIN_NET_TYPE_CLIENT: @@ -8621,7 +8625,6 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, */ switch ((virDomainNetType)actualType) { case VIR_DOMAIN_NET_TYPE_ETHERNET: - case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_DIRECT: { @@ -8639,6 +8642,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, break; } + case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_USER: case VIR_DOMAIN_NET_TYPE_VHOSTUSER: case VIR_DOMAIN_NET_TYPE_SERVER: diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index c7c26e7685..271cae77c9 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1376,7 +1376,6 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, switch (actualType) { case VIR_DOMAIN_NET_TYPE_BRIDGE: - case VIR_DOMAIN_NET_TYPE_NETWORK: tapfdSize = vhostfdSize = net->driver.virtio.queues; if (!tapfdSize) tapfdSize = vhostfdSize = 1; @@ -1468,6 +1467,11 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, /* No preparation needed. */ break; + case VIR_DOMAIN_NET_TYPE_NETWORK: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unexpectedly found type=network for actual NIC type")); + goto cleanup; + case VIR_DOMAIN_NET_TYPE_SERVER: case VIR_DOMAIN_NET_TYPE_CLIENT: case VIR_DOMAIN_NET_TYPE_MCAST: @@ -3580,8 +3584,13 @@ qemuDomainChangeNetFilter(virDomainObjPtr vm, switch (virDomainNetGetActualType(newdev)) { case VIR_DOMAIN_NET_TYPE_ETHERNET: case VIR_DOMAIN_NET_TYPE_BRIDGE: - case VIR_DOMAIN_NET_TYPE_NETWORK: break; + + case VIR_DOMAIN_NET_TYPE_NETWORK: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unexpectedly found type=network for actual NIC type")); + return -1; + case VIR_DOMAIN_NET_TYPE_USER: case VIR_DOMAIN_NET_TYPE_VHOSTUSER: case VIR_DOMAIN_NET_TYPE_SERVER: diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c index 2607dea1f5..ac0a17acc3 100644 --- a/src/qemu/qemu_interface.c +++ b/src/qemu/qemu_interface.c @@ -58,7 +58,6 @@ qemuInterfaceStartDevice(virDomainNetDefPtr net) switch (actualType) { case VIR_DOMAIN_NET_TYPE_BRIDGE: - case VIR_DOMAIN_NET_TYPE_NETWORK: if (virDomainNetGetActualBridgeMACTableManager(net) == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) { /* libvirt is managing the FDB of the bridge this device @@ -111,6 +110,11 @@ qemuInterfaceStartDevice(virDomainNetDefPtr net) break; + case VIR_DOMAIN_NET_TYPE_NETWORK: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unexpectedly found type=network for actual NIC type")); + goto cleanup; + case VIR_DOMAIN_NET_TYPE_USER: case VIR_DOMAIN_NET_TYPE_VHOSTUSER: case VIR_DOMAIN_NET_TYPE_SERVER: @@ -164,7 +168,6 @@ qemuInterfaceStopDevice(virDomainNetDefPtr net) switch (actualType) { case VIR_DOMAIN_NET_TYPE_BRIDGE: - case VIR_DOMAIN_NET_TYPE_NETWORK: if (virDomainNetGetActualBridgeMACTableManager(net) == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) { /* remove the FDB entries that were added during @@ -198,6 +201,11 @@ qemuInterfaceStopDevice(virDomainNetDefPtr net) break; } + case VIR_DOMAIN_NET_TYPE_NETWORK: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unexpectedly found type=network for actual NIC type")); + goto cleanup; + case VIR_DOMAIN_NET_TYPE_ETHERNET: case VIR_DOMAIN_NET_TYPE_USER: case VIR_DOMAIN_NET_TYPE_VHOSTUSER: diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 5597436fba..d7877a3526 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -7206,12 +7206,15 @@ void qemuProcessStop(virQEMUDriverPtr driver, } break; case VIR_DOMAIN_NET_TYPE_BRIDGE: - case VIR_DOMAIN_NET_TYPE_NETWORK: #ifdef VIR_NETDEV_TAP_REQUIRE_MANUAL_CLEANUP if (!(vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)) ignore_value(virNetDevTapDelete(net->ifname, net->backend.tap)); #endif break; + case VIR_DOMAIN_NET_TYPE_NETWORK: + VIR_WARN("Unexpectedly found type=network for actual NIC type"); + break; + case VIR_DOMAIN_NET_TYPE_USER: case VIR_DOMAIN_NET_TYPE_VHOSTUSER: case VIR_DOMAIN_NET_TYPE_SERVER: -- 2.19.2

All but one of the network types supports port profiles. Rather than duplicating the code to merge profiles 3 times, do it once and then later report an error if used from the wrong place. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 54 +++++++++++++++---------------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 822da7c6ac..8cb108ea46 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -4528,6 +4528,18 @@ networkAllocateActualDevice(virNetworkPtr net, iface->data.network.actual->trustGuestRxFilters = netdef->trustGuestRxFilters; + /* merge virtualports from interface, network, and portgroup to + * arrive at actual virtualport to use + */ + if (virNetDevVPortProfileMerge3(&iface->data.network.actual->virtPortProfile, + iface->virtPortProfile, + netdef->virtPortProfile, + portgroup + ? portgroup->virtPortProfile : NULL) < 0) { + goto error; + } + virtport = iface->data.network.actual->virtPortProfile; + switch ((virNetworkForwardType) netdef->forward.type) { case VIR_NETWORK_FORWARD_NONE: case VIR_NETWORK_FORWARD_NAT: @@ -4546,6 +4558,15 @@ networkAllocateActualDevice(virNetworkPtr net, iface->data.network.actual->data.bridge.macTableManager = netdef->macTableManager; + if (virtport) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("<virtualport type='%s'> not supported for network " + "'%s' which uses IP forwarding"), + virNetDevVPortTypeToString(virtport->virtPortType), + netdef->name); + goto error; + } + if (networkPlugBandwidth(obj, iface) < 0) goto error; break; @@ -4598,17 +4619,6 @@ networkAllocateActualDevice(virNetworkPtr net, iface->data.network.actual->data.hostdev.def.source.subsys.u.pci.backend = backend; - /* merge virtualports from interface, network, and portgroup to - * arrive at actual virtualport to use - */ - if (virNetDevVPortProfileMerge3(&iface->data.network.actual->virtPortProfile, - iface->virtPortProfile, - netdef->virtPortProfile, - portgroup - ? portgroup->virtPortProfile : NULL) < 0) { - goto error; - } - virtport = iface->data.network.actual->virtPortProfile; if (virtport) { /* make sure type is supported for hostdev connections */ if (virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBG && @@ -4638,17 +4648,6 @@ networkAllocateActualDevice(virNetworkPtr net, iface->data.network.actual->data.bridge.macTableManager = netdef->macTableManager; - /* merge virtualports from interface, network, and portgroup to - * arrive at actual virtualport to use - */ - if (virNetDevVPortProfileMerge3(&iface->data.network.actual->virtPortProfile, - iface->virtPortProfile, - netdef->virtPortProfile, - portgroup - ? portgroup->virtPortProfile : NULL) < 0) { - goto error; - } - virtport = iface->data.network.actual->virtPortProfile; if (virtport) { /* only type='openvswitch' is allowed for bridges */ if (virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) { @@ -4687,17 +4686,6 @@ networkAllocateActualDevice(virNetworkPtr net, iface->data.network.actual->data.direct.mode = virNetDevMacVLanModeTypeFromString(virNetworkForwardTypeToString(netdef->forward.type)); - /* merge virtualports from interface, network, and portgroup to - * arrive at actual virtualport to use - */ - if (virNetDevVPortProfileMerge3(&iface->data.network.actual->virtPortProfile, - iface->virtPortProfile, - netdef->virtPortProfile, - portgroup - ? portgroup->virtPortProfile : NULL) < 0) { - goto error; - } - virtport = iface->data.network.actual->virtPortProfile; if (virtport) { /* make sure type is supported for macvtap connections */ if (virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBG && -- 2.19.2

Introduce a virNetworkPortDefPtr struct to represent the data associated with a virtual network port. Add APIs for parsing/formatting XML docs with the data. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/Makefile.inc.am | 2 + src/conf/virnetworkportdef.c | 497 ++++++++++++++++++ src/conf/virnetworkportdef.h | 112 ++++ src/libvirt_private.syms | 10 + tests/Makefile.am | 7 + .../plug-bridge-mactbl.xml | 9 + .../virnetworkportxml2xmldata/plug-bridge.xml | 9 + .../virnetworkportxml2xmldata/plug-direct.xml | 12 + .../plug-hostdev-pci.xml | 12 + tests/virnetworkportxml2xmldata/plug-none.xml | 8 + tests/virnetworkportxml2xmltest.c | 104 ++++ 11 files changed, 782 insertions(+) create mode 100644 src/conf/virnetworkportdef.c create mode 100644 src/conf/virnetworkportdef.h create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge-mactbl.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-direct.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-none.xml create mode 100644 tests/virnetworkportxml2xmltest.c diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am index 219ff350d7..eec861591f 100644 --- a/src/conf/Makefile.inc.am +++ b/src/conf/Makefile.inc.am @@ -5,6 +5,8 @@ NETDEV_CONF_SOURCES = \ conf/netdev_vport_profile_conf.c \ conf/netdev_vlan_conf.h \ conf/netdev_vlan_conf.c \ + conf/virnetworkportdef.h \ + conf/virnetworkportdef.c \ $(NULL) DOMAIN_CONF_SOURCES = \ diff --git a/src/conf/virnetworkportdef.c b/src/conf/virnetworkportdef.c new file mode 100644 index 0000000000..12b5f086ab --- /dev/null +++ b/src/conf/virnetworkportdef.c @@ -0,0 +1,497 @@ +/* + * virnetworkportdef.c: network port XML processing + * + * Copyright (C) 2018 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "viralloc.h" +#include "virerror.h" +#include "virstring.h" +#include "virfile.h" +#include "virnetworkportdef.h" +#include "network_conf.h" + +#define VIR_FROM_THIS VIR_FROM_NETWORK + +VIR_ENUM_IMPL(virNetworkPortPlug, VIR_NETWORK_PORT_PLUG_TYPE_LAST, + "none", "bridge", "direct", "hostdev-pci"); + +void +virNetworkPortDefFree(virNetworkPortDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def->ownername); + VIR_FREE(def->group); + + virNetDevBandwidthFree(def->bandwidth); + virNetDevVlanClear(&def->vlan); + VIR_FREE(def->virtPortProfile); + + switch ((virNetworkPortPlugType)def->plugtype) { + case VIR_NETWORK_PORT_PLUG_TYPE_NONE: + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE: + VIR_FREE(def->plug.bridge.brname); + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT: + VIR_FREE(def->plug.direct.linkdev); + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI: + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_LAST: + default: + break; + } + + VIR_FREE(def); +} + + + +static virNetworkPortDefPtr +virNetworkPortDefParseXML(xmlXPathContextPtr ctxt) +{ + virNetworkPortDefPtr def; + char *uuid = NULL; + xmlNodePtr virtPortNode; + xmlNodePtr vlanNode; + xmlNodePtr bandwidthNode; + xmlNodePtr addressNode; + char *trustGuestRxFilters = NULL; + char *mac = NULL; + char *macmgr = NULL; + char *mode = NULL; + char *plugtype = NULL; + char *managed = NULL; + char *driver = NULL; + + if (VIR_ALLOC(def) < 0) + return NULL; + + uuid = virXPathString("string(./uuid)", ctxt); + if (!uuid) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("network port has no uuid")); + goto error; + } + if (virUUIDParse(uuid, def->uuid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse UUID '%s'"), uuid); + goto error; + } + + def->ownername = virXPathString("string(./owner/name)", ctxt); + if (!def->ownername) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("network port has no owner name")); + goto error; + } + + VIR_FREE(uuid); + uuid = virXPathString("string(./owner/uuid)", ctxt); + if (!uuid) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("network port has no owner UUID")); + goto error; + } + + if (virUUIDParse(uuid, def->owneruuid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse UUID '%s'"), uuid); + goto error; + } + + def->group = virXPathString("string(./group)", ctxt); + + virtPortNode = virXPathNode("./virtualport", ctxt); + if (virtPortNode && + (!(def->virtPortProfile = virNetDevVPortProfileParse(virtPortNode, 0)))) { + goto error; + } + + mac = virXPathString("string(./mac/@address)", ctxt); + if (!mac) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("network port has no mac")); + goto error; + } + if (virMacAddrParse(mac, &def->mac) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse MAC '%s'"), mac); + goto error; + } + + bandwidthNode = virXPathNode("./bandwidth", ctxt); + if (bandwidthNode && + virNetDevBandwidthParse(&def->bandwidth, bandwidthNode, -1) < 0) + goto error; + + vlanNode = virXPathNode("./vlan", ctxt); + if (vlanNode && virNetDevVlanParse(vlanNode, ctxt, &def->vlan) < 0) + goto error; + + + trustGuestRxFilters + = virXPathString("string(./rxfilters/@trustGuest)", ctxt); + if (trustGuestRxFilters) { + if ((def->trustGuestRxFilters + = virTristateBoolTypeFromString(trustGuestRxFilters)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid guest rx filters trust setting '%s' "), + trustGuestRxFilters); + goto error; + } + } + + plugtype = virXPathString("string(./plug/@type)", ctxt); + + if (plugtype && + (def->plugtype = virNetworkPortPlugTypeFromString(plugtype)) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid network prt plug type '%s'"), plugtype); + } + + switch (def->plugtype) { + case VIR_NETWORK_PORT_PLUG_TYPE_NONE: + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE: + if (!(def->plug.bridge.brname = virXPathString("string(./plug/@bridge)", ctxt))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing network port bridge name")); + goto error; + } + macmgr = virXPathString("string(./plug/@macTableManager)", ctxt); + if (macmgr && + (def->plug.bridge.macTableManager = + virNetworkBridgeMACTableManagerTypeFromString(macmgr)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid macTableManager setting '%s' " + "in network port"), macmgr); + goto error; + } + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT: + if (!(def->plug.direct.linkdev = virXPathString("string(./plug/@dev)", ctxt))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing network port link device name")); + goto error; + } + mode = virXPathString("string(./plug/@mode)", ctxt); + if (mode && + (def->plug.direct.mode = + virNetDevMacVLanModeTypeFromString(mode)) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid mode setting '%s' in network port"), mode); + goto error; + } + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI: + managed = virXPathString("string(./plug/@managed)", ctxt); + if (managed && + (def->plug.hostdevpci.managed = + virTristateBoolTypeFromString(managed)) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid managed setting '%s' in network port"), mode); + goto error; + } + driver = virXPathString("string(./plug/driver/@name)", ctxt); + if (driver && + (def->plug.hostdevpci.driver = + virNetworkForwardDriverNameTypeFromString(driver)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing network port driver name")); + goto error; + } + if (!(addressNode = virXPathNode("./plug/address", ctxt))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing network port PCI address")); + goto error; + } + + if (virPCIDeviceAddressParseXML(addressNode, &def->plug.hostdevpci.addr) < 0) + goto error; + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_LAST: + default: + virReportEnumRangeError(virNetworkPortPlugType, def->plugtype); + goto error; + } + +cleanup: + VIR_FREE(uuid); + VIR_FREE(plugtype); + VIR_FREE(mac); + VIR_FREE(mode); + VIR_FREE(macmgr); + VIR_FREE(driver); + VIR_FREE(managed); + return def; + + error: + virNetworkPortDefFree(def); + def = NULL; + goto cleanup; +} + + +virNetworkPortDefPtr +virNetworkPortDefParseNode(xmlDocPtr xml, + xmlNodePtr root) +{ + xmlXPathContextPtr ctxt = NULL; + virNetworkPortDefPtr def = NULL; + + if (STRNEQ((const char *)root->name, "networkport")) { + virReportError(VIR_ERR_XML_ERROR, + "%s", + _("unknown root element for network port")); + goto cleanup; + } + + ctxt = xmlXPathNewContext(xml); + if (ctxt == NULL) { + virReportOOMError(); + goto cleanup; + } + + ctxt->node = root; + def = virNetworkPortDefParseXML(ctxt); + + cleanup: + xmlXPathFreeContext(ctxt); + return def; +} + + +static virNetworkPortDefPtr +virNetworkPortDefParse(const char *xmlStr, + const char *filename) +{ + virNetworkPortDefPtr def = NULL; + xmlDocPtr xml; + + if ((xml = virXMLParse(filename, xmlStr, _("(networkport_definition)")))) { + def = virNetworkPortDefParseNode(xml, xmlDocGetRootElement(xml)); + xmlFreeDoc(xml); + } + + return def; +} + + +virNetworkPortDefPtr +virNetworkPortDefParseString(const char *xmlStr) +{ + return virNetworkPortDefParse(xmlStr, NULL); +} + + +virNetworkPortDefPtr +virNetworkPortDefParseFile(const char *filename) +{ + return virNetworkPortDefParse(NULL, filename); +} + + +char * +virNetworkPortDefFormat(const virNetworkPortDef *def) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (virNetworkPortDefFormatBuf(&buf, def) < 0) { + virBufferFreeAndReset(&buf); + return NULL; + } + + if (virBufferCheckError(&buf) < 0) + return NULL; + + return virBufferContentAndReset(&buf); +} + + +int +virNetworkPortDefFormatBuf(virBufferPtr buf, + const virNetworkPortDef *def) +{ + char uuid[VIR_UUID_STRING_BUFLEN]; + char macaddr[VIR_MAC_STRING_BUFLEN]; + + virBufferAddLit(buf, "<networkport>\n"); + + virBufferAdjustIndent(buf, 2); + + virUUIDFormat(def->uuid, uuid); + virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuid); + + virBufferAddLit(buf, "<owner>\n"); + virBufferAdjustIndent(buf, 2); + virBufferEscapeString(buf, "<name>%s</name>\n", def->ownername); + virUUIDFormat(def->owneruuid, uuid); + virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuid); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</owner>\n"); + + if (def->group) + virBufferEscapeString(buf, "<group>%s</group>\n", def->group); + + virMacAddrFormat(&def->mac, macaddr); + virBufferAsprintf(buf, "<mac address='%s'/>\n", macaddr); + + if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0) + return -1; + virNetDevBandwidthFormat(def->bandwidth, buf); + if (def->class_id) + virBufferAsprintf(buf, "<class id='%u'/>\n", def->class_id); + if (virNetDevVlanFormat(&def->vlan, buf) < 0) + return -1; + if (def->trustGuestRxFilters) + virBufferAsprintf(buf, "<rxfilters trustGuest='%s'/>", + virTristateBoolTypeToString(def->trustGuestRxFilters)); + + if (def->plugtype != VIR_NETWORK_PORT_PLUG_TYPE_NONE) { + virBufferAsprintf(buf, "<plug type='%s'", + virNetworkPortPlugTypeToString(def->plugtype)); + + switch (def->plugtype) { + case VIR_NETWORK_PORT_PLUG_TYPE_NONE: + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE: + virBufferEscapeString(buf, " bridge='%s'", def->plug.bridge.brname); + if (def->plug.bridge.macTableManager) + virBufferAsprintf(buf, " macTableManager='%s'", + virNetworkBridgeMACTableManagerTypeToString( + def->plug.bridge.macTableManager)); + virBufferAddLit(buf, "/>\n"); + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT: + virBufferEscapeString(buf, " dev='%s'", def->plug.direct.linkdev); + virBufferAsprintf(buf, " mode='%s'", + virNetDevMacVLanModeTypeToString( + def->plug.direct.mode)); + virBufferAddLit(buf, "/>\n"); + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI: + virBufferAsprintf(buf, " managed='%s'>\n", + def->plug.hostdevpci.managed ? "yes" : "no"); + virBufferAdjustIndent(buf, 2); + if (def->plug.hostdevpci.driver) + virBufferEscapeString(buf, "<driver name='%s'/>\n", + virNetworkForwardDriverNameTypeToString( + def->plug.hostdevpci.driver)); + + virPCIDeviceAddressFormat(buf, def->plug.hostdevpci.addr, false); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</plug>\n"); + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_LAST: + default: + virReportEnumRangeError(virNetworkPortPlugType, def->plugtype); + return -1; + } + } + + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</networkport>\n"); + + return 0; +} + + +static char * +virNetworkPortDefConfigFile(const char *dir, + const char *name) +{ + char *ret = NULL; + + ignore_value(virAsprintf(&ret, "%s/%s.xml", dir, name)); + return ret; +} + + +int +virNetworkPortDefSaveStatus(virNetworkPortDef *def, + const char *dir) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + char *path; + char *xml = NULL; + int ret = -1; + + virUUIDFormat(def->uuid, uuidstr); + + if (virFileMakePath(dir) < 0) + goto cleanup; + + if (!(path = virNetworkPortDefConfigFile(dir, uuidstr))) + goto cleanup; + + if (!(xml = virNetworkPortDefFormat(def))) + goto cleanup; + + if (virXMLSaveFile(path, uuidstr, "net-port-create", xml) < 0) + goto cleanup; + + ret = 0; + cleanup: + VIR_FREE(xml); + VIR_FREE(path); + return ret; +} + + +int +virNetworkPortDefDeleteStatus(virNetworkPortDef *def, + const char *dir) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + char *path; + int ret = -1; + + virUUIDFormat(def->uuid, uuidstr); + + if (!(path = virNetworkPortDefConfigFile(dir, uuidstr))) + goto cleanup; + + if (unlink(path) < 0 && errno != ENOENT) { + virReportSystemError(errno, + _("Unable to delete %s"), path); + goto cleanup; + } + + ret = 0; + cleanup: + VIR_FREE(path); + return ret; +} diff --git a/src/conf/virnetworkportdef.h b/src/conf/virnetworkportdef.h new file mode 100644 index 0000000000..fe5e249611 --- /dev/null +++ b/src/conf/virnetworkportdef.h @@ -0,0 +1,112 @@ +/* + * virnetworkportdef.h: network port XML processing + * + * Copyright (C) 2018 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#ifndef LIBVIRT_VIRNETWORKPORTDEF_H +# define LIBVIRT_VIRNETWORKPORTDEF_H + +# include "internal.h" +# include "viruuid.h" +# include "virnetdevvlan.h" +# include "virnetdevvportprofile.h" +# include "virnetdevbandwidth.h" +# include "virpci.h" +# include "virxml.h" +# include "netdev_vport_profile_conf.h" +# include "netdev_bandwidth_conf.h" +# include "netdev_vlan_conf.h" + +typedef struct _virNetworkPortDef virNetworkPortDef; +typedef virNetworkPortDef *virNetworkPortDefPtr; + +typedef enum { + VIR_NETWORK_PORT_PLUG_TYPE_NONE, + VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE, + VIR_NETWORK_PORT_PLUG_TYPE_DIRECT, + VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI, + + VIR_NETWORK_PORT_PLUG_TYPE_LAST, +} virNetworkPortPlugType; + +VIR_ENUM_DECL(virNetworkPortPlug) + +struct _virNetworkPortDef { + unsigned char uuid[VIR_UUID_BUFLEN]; + char *ownername; + unsigned char owneruuid[VIR_UUID_BUFLEN]; + + char *group; + virMacAddr mac; + + virNetDevVPortProfilePtr virtPortProfile; + virNetDevBandwidthPtr bandwidth; + unsigned int class_id; /* class ID for bandwidth 'floor' */ + virNetDevVlan vlan; + int trustGuestRxFilters; /* enum virTristateBool */ + + int plugtype; /* virNetworkPortPlugType */ + union { + struct { + char *brname; + int macTableManager; /* enum virNetworkBridgeMACTableManagerType */ + } bridge; + struct { + char *linkdev; + int mode; /* enum virMacvtapMode from util/macvtap.h */ + } direct; + struct { + virPCIDeviceAddress addr; /* PCI Address of device */ + int driver; /* virNetworkForwardDriverNameType */ + int managed; + } hostdevpci; + } plug; +}; + + +void +virNetworkPortDefFree(virNetworkPortDefPtr port); + +virNetworkPortDefPtr +virNetworkPortDefParseNode(xmlDocPtr xml, + xmlNodePtr root); + +virNetworkPortDefPtr +virNetworkPortDefParseString(const char *xml); + +virNetworkPortDefPtr +virNetworkPortDefParseFile(const char *filename); + +char * +virNetworkPortDefFormat(const virNetworkPortDef *def); + +int +virNetworkPortDefFormatBuf(virBufferPtr buf, + const virNetworkPortDef *def); + +int +virNetworkPortDefSaveStatus(virNetworkPortDef *def, + const char *dir); + +int +virNetworkPortDefDeleteStatus(virNetworkPortDef *def, + const char *dir); + + +#endif /* LIBVIRT_VIRNETWORKPORTDEF_H */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c3d6306809..0b363f8ec8 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1034,6 +1034,16 @@ virNetworkObjUpdate; virNetworkObjUpdateAssignDef; +# conf/virnetworkportdef.h +virNetworkPortDefFormat; +virNetworkPortDefFormatBuf; +virNetworkPortDefFree; +virNetworkPortDefParseFile; +virNetworkPortDefParseNode; +virNetworkPortDefParseString; + + + # conf/virnodedeviceobj.h virNodeDeviceObjEndAPI; virNodeDeviceObjGetDef; diff --git a/tests/Makefile.am b/tests/Makefile.am index 3b413dca43..7549b1d3ee 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -157,6 +157,7 @@ EXTRA_DIST = \ virmock.h \ virnetdaemondata \ virnetdevtestdata \ + viretworkportxml2xmldata \ virnwfilterbindingxml2xmldata \ virpcitestdata \ virscsidata \ @@ -343,6 +344,7 @@ endif WITH_YAJL test_programs += \ networkxml2xmltest \ networkxml2xmlupdatetest \ + virnetworkportxml2xmltest \ $(NULL) if WITH_NETWORK @@ -832,6 +834,11 @@ networkxml2xmlupdatetest_SOURCES = \ testutils.c testutils.h networkxml2xmlupdatetest_LDADD = $(LDADDS) +virnetworkportxml2xmltest_SOURCES = \ + virnetworkportxml2xmltest.c \ + testutils.c testutils.h +virnetworkportxml2xmltest_LDADD = $(LDADDS) + if WITH_NETWORK networkxml2conftest_SOURCES = \ networkxml2conftest.c \ diff --git a/tests/virnetworkportxml2xmldata/plug-bridge-mactbl.xml b/tests/virnetworkportxml2xmldata/plug-bridge-mactbl.xml new file mode 100644 index 0000000000..8036bc2e1c --- /dev/null +++ b/tests/virnetworkportxml2xmldata/plug-bridge-mactbl.xml @@ -0,0 +1,9 @@ +<networkport> + <uuid>5d744f21-ba4a-4d6e-bdb2-30a35ff3207d</uuid> + <owner> + <name>memtest</name> + <uuid>d54df46f-1ab5-4a22-8618-4560ef5fac2c</uuid> + </owner> + <mac address='52:54:00:7b:35:93'/> + <plug type='bridge' bridge='virbr0' macTableManager='libvirt'/> +</networkport> diff --git a/tests/virnetworkportxml2xmldata/plug-bridge.xml b/tests/virnetworkportxml2xmldata/plug-bridge.xml new file mode 100644 index 0000000000..967d8472f1 --- /dev/null +++ b/tests/virnetworkportxml2xmldata/plug-bridge.xml @@ -0,0 +1,9 @@ +<networkport> + <uuid>5d744f21-ba4a-4d6e-bdb2-30a35ff3207d</uuid> + <owner> + <name>memtest</name> + <uuid>d54df46f-1ab5-4a22-8618-4560ef5fac2c</uuid> + </owner> + <mac address='52:54:00:7b:35:93'/> + <plug type='bridge' bridge='virbr0'/> +</networkport> diff --git a/tests/virnetworkportxml2xmldata/plug-direct.xml b/tests/virnetworkportxml2xmldata/plug-direct.xml new file mode 100644 index 0000000000..81554b4579 --- /dev/null +++ b/tests/virnetworkportxml2xmldata/plug-direct.xml @@ -0,0 +1,12 @@ +<networkport> + <uuid>5d744f21-ba4a-4d6e-bdb2-30a35ff3207d</uuid> + <owner> + <name>memtest</name> + <uuid>d54df46f-1ab5-4a22-8618-4560ef5fac2c</uuid> + </owner> + <mac address='52:54:00:7b:35:93'/> + <virtualport type='802.1Qbg'> + <parameters managerid='11' typeid='1193047' typeidversion='2'/> + </virtualport> + <plug type='direct' dev='ens3' mode='vepa'/> +</networkport> diff --git a/tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml b/tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml new file mode 100644 index 0000000000..cc4419f3fd --- /dev/null +++ b/tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml @@ -0,0 +1,12 @@ +<networkport> + <uuid>5d744f21-ba4a-4d6e-bdb2-30a35ff3207d</uuid> + <owner> + <name>memtest</name> + <uuid>d54df46f-1ab5-4a22-8618-4560ef5fac2c</uuid> + </owner> + <mac address='52:54:00:7b:35:93'/> + <plug type='hostdev-pci' managed='yes'> + <driver name='vfio'/> + <address domain='0x0001' bus='0x02' slot='0x03' function='0x4'/> + </plug> +</networkport> diff --git a/tests/virnetworkportxml2xmldata/plug-none.xml b/tests/virnetworkportxml2xmldata/plug-none.xml new file mode 100644 index 0000000000..ed7199ec8c --- /dev/null +++ b/tests/virnetworkportxml2xmldata/plug-none.xml @@ -0,0 +1,8 @@ +<networkport> + <uuid>5d744f21-ba4a-4d6e-bdb2-30a35ff3207d</uuid> + <owner> + <name>memtest</name> + <uuid>d54df46f-1ab5-4a22-8618-4560ef5fac2c</uuid> + </owner> + <mac address='52:54:00:7b:35:93'/> +</networkport> diff --git a/tests/virnetworkportxml2xmltest.c b/tests/virnetworkportxml2xmltest.c new file mode 100644 index 0000000000..b737973c5e --- /dev/null +++ b/tests/virnetworkportxml2xmltest.c @@ -0,0 +1,104 @@ +/* + * virnetworkportdeftest.c: network port XML processing test suite + * + * Copyright (C) 2018 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include <unistd.h> + +#include <sys/types.h> +#include <fcntl.h> + +#include "internal.h" +#include "testutils.h" +#include "virnetworkportdef.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + + +static int +testCompareXMLToXMLFiles(const char *expected) +{ + char *actual = NULL; + int ret = -1; + virNetworkPortDefPtr dev = NULL; + + if (!(dev = virNetworkPortDefParseFile(expected))) + goto cleanup; + + if (!(actual = virNetworkPortDefFormat(dev))) + goto cleanup; + + if (virTestCompareToFile(actual, expected) < 0) + goto cleanup; + + ret = 0; + cleanup: + VIR_FREE(actual); + virNetworkPortDefFree(dev); + return ret; +} + +struct testInfo { + const char *name; +}; + +static int +testCompareXMLToXMLHelper(const void *data) +{ + const struct testInfo *info = data; + int ret = -1; + char *xml = NULL; + + if (virAsprintf(&xml, "%s/virnetworkportxml2xmldata/%s.xml", + abs_srcdir, info->name) < 0) + goto cleanup; + + ret = testCompareXMLToXMLFiles(xml); + + cleanup: + VIR_FREE(xml); + + return ret; +} + +static int +mymain(void) +{ + int ret = 0; + +#define DO_TEST(name) \ + do { \ + const struct testInfo info = {name}; \ + if (virTestRun("virnetworkportdeftest " name, \ + testCompareXMLToXMLHelper, &info) < 0) \ + ret = -1; \ + } while (0) + + DO_TEST("plug-none"); + DO_TEST("plug-bridge"); + DO_TEST("plug-bridge-mactbl"); + DO_TEST("plug-direct"); + DO_TEST("plug-hostdev-pci"); + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIR_TEST_MAIN(mymain) -- 2.19.2

On 12/24/18 3:58 PM, Daniel P. Berrangé wrote:
Introduce a virNetworkPortDefPtr struct to represent the data associated with a virtual network port. Add APIs for parsing/formatting XML docs with the data.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/Makefile.inc.am | 2 + src/conf/virnetworkportdef.c | 497 ++++++++++++++++++ src/conf/virnetworkportdef.h | 112 ++++ src/libvirt_private.syms | 10 + tests/Makefile.am | 7 + .../plug-bridge-mactbl.xml | 9 + .../virnetworkportxml2xmldata/plug-bridge.xml | 9 + .../virnetworkportxml2xmldata/plug-direct.xml | 12 + .../plug-hostdev-pci.xml | 12 + tests/virnetworkportxml2xmldata/plug-none.xml | 8 + tests/virnetworkportxml2xmltest.c | 104 ++++ 11 files changed, 782 insertions(+) create mode 100644 src/conf/virnetworkportdef.c create mode 100644 src/conf/virnetworkportdef.h create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge-mactbl.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-direct.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-none.xml create mode 100644 tests/virnetworkportxml2xmltest.c
diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am index 219ff350d7..eec861591f 100644 --- a/src/conf/Makefile.inc.am +++ b/src/conf/Makefile.inc.am @@ -5,6 +5,8 @@ NETDEV_CONF_SOURCES = \ conf/netdev_vport_profile_conf.c \ conf/netdev_vlan_conf.h \ conf/netdev_vlan_conf.c \ + conf/virnetworkportdef.h \ + conf/virnetworkportdef.c \ $(NULL)
DOMAIN_CONF_SOURCES = \ diff --git a/src/conf/virnetworkportdef.c b/src/conf/virnetworkportdef.c new file mode 100644 index 0000000000..12b5f086ab --- /dev/null +++ b/src/conf/virnetworkportdef.c @@ -0,0 +1,497 @@ +/* + * virnetworkportdef.c: network port XML processing + * + * Copyright (C) 2018 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "viralloc.h" +#include "virerror.h" +#include "virstring.h" +#include "virfile.h" +#include "virnetworkportdef.h" +#include "network_conf.h" + +#define VIR_FROM_THIS VIR_FROM_NETWORK + +VIR_ENUM_IMPL(virNetworkPortPlug, VIR_NETWORK_PORT_PLUG_TYPE_LAST, + "none", "bridge", "direct", "hostdev-pci"); + +void +virNetworkPortDefFree(virNetworkPortDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def->ownername); + VIR_FREE(def->group); + + virNetDevBandwidthFree(def->bandwidth); + virNetDevVlanClear(&def->vlan); + VIR_FREE(def->virtPortProfile); + + switch ((virNetworkPortPlugType)def->plugtype) { + case VIR_NETWORK_PORT_PLUG_TYPE_NONE: + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE: + VIR_FREE(def->plug.bridge.brname); + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT: + VIR_FREE(def->plug.direct.linkdev); + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI: + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_LAST: + default: + break; + } + + VIR_FREE(def); +} + + + +static virNetworkPortDefPtr +virNetworkPortDefParseXML(xmlXPathContextPtr ctxt) +{ + virNetworkPortDefPtr def; + char *uuid = NULL; + xmlNodePtr virtPortNode; + xmlNodePtr vlanNode; + xmlNodePtr bandwidthNode; + xmlNodePtr addressNode; + char *trustGuestRxFilters = NULL; + char *mac = NULL; + char *macmgr = NULL; + char *mode = NULL; + char *plugtype = NULL; + char *managed = NULL; + char *driver = NULL; + + if (VIR_ALLOC(def) < 0) + return NULL; + + uuid = virXPathString("string(./uuid)", ctxt); + if (!uuid) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("network port has no uuid")); + goto error; + } + if (virUUIDParse(uuid, def->uuid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse UUID '%s'"), uuid); + goto error; + } + + def->ownername = virXPathString("string(./owner/name)", ctxt); + if (!def->ownername) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("network port has no owner name")); + goto error; + } + + VIR_FREE(uuid); + uuid = virXPathString("string(./owner/uuid)", ctxt); + if (!uuid) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("network port has no owner UUID")); + goto error; + } + + if (virUUIDParse(uuid, def->owneruuid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse UUID '%s'"), uuid); + goto error; + } + + def->group = virXPathString("string(./group)", ctxt); + + virtPortNode = virXPathNode("./virtualport", ctxt); + if (virtPortNode && + (!(def->virtPortProfile = virNetDevVPortProfileParse(virtPortNode, 0)))) { + goto error; + } + + mac = virXPathString("string(./mac/@address)", ctxt); + if (!mac) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("network port has no mac")); + goto error; + } + if (virMacAddrParse(mac, &def->mac) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse MAC '%s'"), mac); + goto error; + } + + bandwidthNode = virXPathNode("./bandwidth", ctxt); + if (bandwidthNode && + virNetDevBandwidthParse(&def->bandwidth, bandwidthNode, -1) < 0)
This must not be -1. The bandwidth corresponds to the interface not the bridge. If this is -1 then 'floor' is disallowed, which is not what we want. Maybe we need to change the @net_type argument of virNetDevBandwidthParse() so that it is bool which allows/denies 'floor'.
+ goto error; + + vlanNode = virXPathNode("./vlan", ctxt); + if (vlanNode && virNetDevVlanParse(vlanNode, ctxt, &def->vlan) < 0) + goto error; + + + trustGuestRxFilters + = virXPathString("string(./rxfilters/@trustGuest)", ctxt); + if (trustGuestRxFilters) { + if ((def->trustGuestRxFilters + = virTristateBoolTypeFromString(trustGuestRxFilters)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid guest rx filters trust setting '%s' "), + trustGuestRxFilters); + goto error; + } + } + + plugtype = virXPathString("string(./plug/@type)", ctxt); + + if (plugtype && + (def->plugtype = virNetworkPortPlugTypeFromString(plugtype)) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid network prt plug type '%s'"), plugtype); + } +
+int +virNetworkPortDefFormatBuf(virBufferPtr buf, + const virNetworkPortDef *def) +{ + char uuid[VIR_UUID_STRING_BUFLEN]; + char macaddr[VIR_MAC_STRING_BUFLEN]; + + virBufferAddLit(buf, "<networkport>\n"); + + virBufferAdjustIndent(buf, 2); + + virUUIDFormat(def->uuid, uuid); + virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuid); + + virBufferAddLit(buf, "<owner>\n"); + virBufferAdjustIndent(buf, 2); + virBufferEscapeString(buf, "<name>%s</name>\n", def->ownername); + virUUIDFormat(def->owneruuid, uuid); + virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuid); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</owner>\n"); + + if (def->group) + virBufferEscapeString(buf, "<group>%s</group>\n", def->group); + + virMacAddrFormat(&def->mac, macaddr); + virBufferAsprintf(buf, "<mac address='%s'/>\n", macaddr); + + if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0) + return -1; + virNetDevBandwidthFormat(def->bandwidth, buf); + if (def->class_id) + virBufferAsprintf(buf, "<class id='%u'/>\n", def->class_id); + if (virNetDevVlanFormat(&def->vlan, buf) < 0) + return -1; + if (def->trustGuestRxFilters) + virBufferAsprintf(buf, "<rxfilters trustGuest='%s'/>",
Add "\n" here.
+ virTristateBoolTypeToString(def->trustGuestRxFilters)); +
Michal

On Tue, Jan 08, 2019 at 05:15:49PM +0100, Michal Privoznik wrote:
On 12/24/18 3:58 PM, Daniel P. Berrangé wrote:
Introduce a virNetworkPortDefPtr struct to represent the data associated with a virtual network port. Add APIs for parsing/formatting XML docs with the data.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
[snip]
+static virNetworkPortDefPtr +virNetworkPortDefParseXML(xmlXPathContextPtr ctxt) +{ + virNetworkPortDefPtr def; + char *uuid = NULL; + xmlNodePtr virtPortNode; + xmlNodePtr vlanNode; + xmlNodePtr bandwidthNode; + xmlNodePtr addressNode; + char *trustGuestRxFilters = NULL; + char *mac = NULL; + char *macmgr = NULL; + char *mode = NULL; + char *plugtype = NULL; + char *managed = NULL; + char *driver = NULL; + + if (VIR_ALLOC(def) < 0) + return NULL; + + uuid = virXPathString("string(./uuid)", ctxt); + if (!uuid) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("network port has no uuid")); + goto error; + } + if (virUUIDParse(uuid, def->uuid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse UUID '%s'"), uuid); + goto error; + } + + def->ownername = virXPathString("string(./owner/name)", ctxt); + if (!def->ownername) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("network port has no owner name")); + goto error; + } + + VIR_FREE(uuid); + uuid = virXPathString("string(./owner/uuid)", ctxt); + if (!uuid) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("network port has no owner UUID")); + goto error; + } + + if (virUUIDParse(uuid, def->owneruuid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse UUID '%s'"), uuid); + goto error; + } + + def->group = virXPathString("string(./group)", ctxt); + + virtPortNode = virXPathNode("./virtualport", ctxt); + if (virtPortNode && + (!(def->virtPortProfile = virNetDevVPortProfileParse(virtPortNode, 0)))) { + goto error; + } + + mac = virXPathString("string(./mac/@address)", ctxt); + if (!mac) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("network port has no mac")); + goto error; + } + if (virMacAddrParse(mac, &def->mac) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse MAC '%s'"), mac); + goto error; + } + + bandwidthNode = virXPathNode("./bandwidth", ctxt); + if (bandwidthNode && + virNetDevBandwidthParse(&def->bandwidth, bandwidthNode, -1) < 0)
This must not be -1. The bandwidth corresponds to the interface not the bridge. If this is -1 then 'floor' is disallowed, which is not what we want. Maybe we need to change the @net_type argument of virNetDevBandwidthParse() so that it is bool which allows/denies 'floor'.
Yes, I'll introduce a prerequisite patch turning that parameter into a 'bool allowFloor'. When parsing network port XML, we'll have to pass true unconditionally. At the time the port is actually wired up we'll have a runtime check as to whether floor can actually be used or not for a given port.
+ if (def->trustGuestRxFilters) + virBufferAsprintf(buf, "<rxfilters trustGuest='%s'/>",
Add "\n" here.
Yep, this shows some missing coverage in the test XML files which I'll address too. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Thu, Jan 31, 2019 at 01:48:33PM +0000, Daniel P. Berrangé wrote:
On Tue, Jan 08, 2019 at 05:15:49PM +0100, Michal Privoznik wrote:
On 12/24/18 3:58 PM, Daniel P. Berrangé wrote:
Introduce a virNetworkPortDefPtr struct to represent the data associated with a virtual network port. Add APIs for parsing/formatting XML docs with the data.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
[snip]
+ if (def->trustGuestRxFilters) + virBufferAsprintf(buf, "<rxfilters trustGuest='%s'/>",
Add "\n" here.
Yep, this shows some missing coverage in the test XML files which I'll address too.
And adding them made me discover this patch missed parsing of the <class id=/> element. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On 12/24/18 3:58 PM, Daniel P. Berrangé wrote:
Introduce a virNetworkPortDefPtr struct to represent the data associated with a virtual network port. Add APIs for parsing/formatting XML docs with the data.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/Makefile.inc.am | 2 + src/conf/virnetworkportdef.c | 497 ++++++++++++++++++ src/conf/virnetworkportdef.h | 112 ++++ src/libvirt_private.syms | 10 + tests/Makefile.am | 7 + .../plug-bridge-mactbl.xml | 9 + .../virnetworkportxml2xmldata/plug-bridge.xml | 9 + .../virnetworkportxml2xmldata/plug-direct.xml | 12 + .../plug-hostdev-pci.xml | 12 + tests/virnetworkportxml2xmldata/plug-none.xml | 8 + tests/virnetworkportxml2xmltest.c | 104 ++++ 11 files changed, 782 insertions(+) create mode 100644 src/conf/virnetworkportdef.c create mode 100644 src/conf/virnetworkportdef.h create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge-mactbl.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-direct.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-none.xml create mode 100644 tests/virnetworkportxml2xmltest.c
This breaks syntax-check. Squash this in to fix it: diff --git i/src/conf/virnetworkportdef.c w/src/conf/virnetworkportdef.c index 12b5f086ab..067f9afaaa 100644 --- i/src/conf/virnetworkportdef.c +++ w/src/conf/virnetworkportdef.c @@ -232,7 +232,7 @@ virNetworkPortDefParseXML(xmlXPathContextPtr ctxt) _("Missing network port PCI address")); goto error; } - + if (virPCIDeviceAddressParseXML(addressNode, &def->plug.hostdevpci.addr) < 0) goto error; break; @@ -243,7 +243,7 @@ virNetworkPortDefParseXML(xmlXPathContextPtr ctxt) goto error; } -cleanup: + cleanup: VIR_FREE(uuid); VIR_FREE(plugtype); VIR_FREE(mac); diff --git i/tests/virnetworkportxml2xmltest.c w/tests/virnetworkportxml2xmltest.c index b737973c5e..bb0ae8a8d5 100644 --- i/tests/virnetworkportxml2xmltest.c +++ w/tests/virnetworkportxml2xmltest.c @@ -1,5 +1,5 @@ /* - * virnetworkportdeftest.c: network port XML processing test suite + * virnetworkportxml2xmltest.c: network port XML processing test suite * * Copyright (C) 2018 Red Hat, Inc. * Michal

On Tue, Jan 08, 2019 at 05:16:00PM +0100, Michal Privoznik wrote:
On 12/24/18 3:58 PM, Daniel P. Berrangé wrote:
Introduce a virNetworkPortDefPtr struct to represent the data associated with a virtual network port. Add APIs for parsing/formatting XML docs with the data.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/Makefile.inc.am | 2 + src/conf/virnetworkportdef.c | 497 ++++++++++++++++++ src/conf/virnetworkportdef.h | 112 ++++ src/libvirt_private.syms | 10 + tests/Makefile.am | 7 + .../plug-bridge-mactbl.xml | 9 + .../virnetworkportxml2xmldata/plug-bridge.xml | 9 + .../virnetworkportxml2xmldata/plug-direct.xml | 12 + .../plug-hostdev-pci.xml | 12 + tests/virnetworkportxml2xmldata/plug-none.xml | 8 + tests/virnetworkportxml2xmltest.c | 104 ++++ 11 files changed, 782 insertions(+) create mode 100644 src/conf/virnetworkportdef.c create mode 100644 src/conf/virnetworkportdef.h create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge-mactbl.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-direct.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-none.xml create mode 100644 tests/virnetworkportxml2xmltest.c
This breaks syntax-check. Squash this in to fix it:
Yes, will do.. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

The networkPlugBandwidth & networkUnplugBandwidth methods currently take a virDomainNetDefPtr. To remove the dependency on the domain config struct, pass individual parameters instead. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 94 ++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 8cb108ea46..1014b53201 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -170,11 +170,14 @@ networkRefreshDaemons(virNetworkDriverStatePtr driver); static int networkPlugBandwidth(virNetworkObjPtr obj, - virDomainNetDefPtr iface); + virMacAddrPtr mac, + virNetDevBandwidthPtr ifaceBand, + unsigned int *class_id); static int networkUnplugBandwidth(virNetworkObjPtr obj, - virDomainNetDefPtr iface); + virNetDevBandwidthPtr ifaceBand, + unsigned int *class_id); static void networkNetworkObjTaint(virNetworkObjPtr obj, @@ -4567,7 +4570,9 @@ networkAllocateActualDevice(virNetworkPtr net, goto error; } - if (networkPlugBandwidth(obj, iface) < 0) + if (networkPlugBandwidth(obj, &iface->mac, iface->bandwidth, + iface->data.network.actual ? + &iface->data.network.actual->class_id : NULL) < 0) goto error; break; @@ -4660,7 +4665,9 @@ networkAllocateActualDevice(virNetworkPtr net, } } - if (networkPlugBandwidth(obj, iface) < 0) + if (networkPlugBandwidth(obj, &iface->mac, iface->bandwidth, + iface->data.network.actual ? + &iface->data.network.actual->class_id : NULL) < 0) goto error; break; } @@ -5129,14 +5136,17 @@ networkReleaseActualDevice(virNetworkPtr net, case VIR_NETWORK_FORWARD_NAT: case VIR_NETWORK_FORWARD_ROUTE: case VIR_NETWORK_FORWARD_OPEN: - if (iface->data.network.actual && networkUnplugBandwidth(obj, iface) < 0) + if (iface->data.network.actual && + networkUnplugBandwidth(obj, iface->bandwidth, + &iface->data.network.actual->class_id) < 0) goto error; break; case VIR_NETWORK_FORWARD_BRIDGE: if (iface->data.network.actual && actualType == VIR_DOMAIN_NET_TYPE_BRIDGE && - networkUnplugBandwidth(obj, iface) < 0) + networkUnplugBandwidth(obj, iface->bandwidth, + &iface->data.network.actual->class_id) < 0) goto error; break; case VIR_NETWORK_FORWARD_PRIVATE: @@ -5276,7 +5286,7 @@ static int networkCheckBandwidth(virNetworkObjPtr obj, virNetDevBandwidthPtr ifaceBand, virNetDevBandwidthPtr oldBandwidth, - virMacAddr ifaceMac, + virMacAddrPtr ifaceMac, unsigned long long *new_rate) { int ret = -1; @@ -5286,7 +5296,7 @@ networkCheckBandwidth(virNetworkObjPtr obj, unsigned long long tmp_new_rate = 0; char ifmac[VIR_MAC_STRING_BUFLEN]; - virMacAddrFormat(&ifaceMac, ifmac); + virMacAddrFormat(ifaceMac, ifmac); if (ifaceBand && ifaceBand->in && ifaceBand->in->floor && !(netBand && netBand->in)) { @@ -5371,44 +5381,45 @@ networkNextClassID(virNetworkObjPtr obj) static int networkPlugBandwidthImpl(virNetworkObjPtr obj, - virDomainNetDefPtr iface, + virMacAddrPtr mac, virNetDevBandwidthPtr ifaceBand, + unsigned int *class_id, unsigned long long new_rate) { virNetworkDriverStatePtr driver = networkGetDriver(); virNetworkDefPtr def = virNetworkObjGetDef(obj); virBitmapPtr classIdMap = virNetworkObjGetClassIdMap(obj); unsigned long long tmp_floor_sum = virNetworkObjGetFloorSum(obj); - ssize_t class_id = 0; + ssize_t next_id = 0; int plug_ret; int ret = -1; /* generate new class_id */ - if ((class_id = networkNextClassID(obj)) < 0) { + if ((next_id = networkNextClassID(obj)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not generate next class ID")); goto cleanup; } plug_ret = virNetDevBandwidthPlug(def->bridge, def->bandwidth, - &iface->mac, ifaceBand, class_id); + mac, ifaceBand, next_id); if (plug_ret < 0) { - ignore_value(virNetDevBandwidthUnplug(def->bridge, class_id)); + ignore_value(virNetDevBandwidthUnplug(def->bridge, next_id)); goto cleanup; } /* QoS was set, generate new class ID */ - iface->data.network.actual->class_id = class_id; + *class_id = next_id; /* update sum of 'floor'-s of attached NICs */ tmp_floor_sum += ifaceBand->in->floor; virNetworkObjSetFloorSum(obj, tmp_floor_sum); /* update status file */ if (virNetworkObjSaveStatus(driver->stateDir, obj) < 0) { - ignore_value(virBitmapClearBit(classIdMap, class_id)); + ignore_value(virBitmapClearBit(classIdMap, next_id)); tmp_floor_sum -= ifaceBand->in->floor; virNetworkObjSetFloorSum(obj, tmp_floor_sum); - iface->data.network.actual->class_id = 0; - ignore_value(virNetDevBandwidthUnplug(def->bridge, class_id)); + *class_id = 0; + ignore_value(virNetDevBandwidthUnplug(def->bridge, next_id)); goto cleanup; } /* update rate for non guaranteed NICs */ @@ -5426,16 +5437,17 @@ networkPlugBandwidthImpl(virNetworkObjPtr obj, static int networkPlugBandwidth(virNetworkObjPtr obj, - virDomainNetDefPtr iface) + virMacAddrPtr mac, + virNetDevBandwidthPtr ifaceBand, + unsigned int *class_id) { int ret = -1; int plug_ret; unsigned long long new_rate = 0; char ifmac[VIR_MAC_STRING_BUFLEN]; - virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface); if ((plug_ret = networkCheckBandwidth(obj, ifaceBand, NULL, - iface->mac, &new_rate)) < 0) { + mac, &new_rate)) < 0) { /* helper reported error */ goto cleanup; } @@ -5446,16 +5458,9 @@ networkPlugBandwidth(virNetworkObjPtr obj, goto cleanup; } - virMacAddrFormat(&iface->mac, ifmac); - if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK || - !iface->data.network.actual) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Cannot set bandwidth on interface '%s' of type %d"), - ifmac, iface->type); - goto cleanup; - } + virMacAddrFormat(mac, ifmac); - if (networkPlugBandwidthImpl(obj, iface, ifaceBand, new_rate) < 0) + if (networkPlugBandwidthImpl(obj, mac, ifaceBand, class_id, new_rate) < 0) goto cleanup; ret = 0; @@ -5467,7 +5472,8 @@ networkPlugBandwidth(virNetworkObjPtr obj, static int networkUnplugBandwidth(virNetworkObjPtr obj, - virDomainNetDefPtr iface) + virNetDevBandwidthPtr ifaceBand, + unsigned int *class_id) { virNetworkDefPtr def = virNetworkObjGetDef(obj); virBitmapPtr classIdMap = virNetworkObjGetClassIdMap(obj); @@ -5475,10 +5481,8 @@ networkUnplugBandwidth(virNetworkObjPtr obj, virNetworkDriverStatePtr driver = networkGetDriver(); int ret = 0; unsigned long long new_rate; - virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface); - if (iface->data.network.actual && - iface->data.network.actual->class_id) { + if (class_id && *class_id) { if (!def->bandwidth || !def->bandwidth->in) { VIR_WARN("Network %s has no bandwidth but unplug requested", def->name); @@ -5490,8 +5494,7 @@ networkUnplugBandwidth(virNetworkObjPtr obj, if (def->bandwidth->in->peak > 0) new_rate = def->bandwidth->in->peak; - ret = virNetDevBandwidthUnplug(def->bridge, - iface->data.network.actual->class_id); + ret = virNetDevBandwidthUnplug(def->bridge, *class_id); if (ret < 0) goto cleanup; /* update sum of 'floor'-s of attached NICs */ @@ -5499,14 +5502,12 @@ networkUnplugBandwidth(virNetworkObjPtr obj, virNetworkObjSetFloorSum(obj, tmp_floor_sum); /* return class ID */ - ignore_value(virBitmapClearBit(classIdMap, - iface->data.network.actual->class_id)); + ignore_value(virBitmapClearBit(classIdMap, *class_id)); /* update status file */ if (virNetworkObjSaveStatus(driver->stateDir, obj) < 0) { tmp_floor_sum += ifaceBand->in->floor; virNetworkObjSetFloorSum(obj, tmp_floor_sum); - ignore_value(virBitmapSetBit(classIdMap, - iface->data.network.actual->class_id)); + ignore_value(virBitmapSetBit(classIdMap, *class_id)); goto cleanup; } /* update rate for non guaranteed NICs */ @@ -5516,7 +5517,7 @@ networkUnplugBandwidth(virNetworkObjPtr obj, VIR_WARN("Unable to update rate for 1:2 class on %s bridge", def->bridge); /* no class is associated any longer */ - iface->data.network.actual->class_id = 0; + *class_id = 0; } cleanup: @@ -5585,7 +5586,7 @@ networkBandwidthChangeAllowed(virDomainNetDefPtr iface, return false; } - if (networkCheckBandwidth(obj, newBandwidth, ifaceBand, iface->mac, NULL) < 0) + if (networkCheckBandwidth(obj, newBandwidth, ifaceBand, &iface->mac, NULL) < 0) goto cleanup; ret = true; @@ -5622,7 +5623,7 @@ networkBandwidthUpdate(virDomainNetDefPtr iface, def = virNetworkObjGetDef(obj); if ((plug_ret = networkCheckBandwidth(obj, newBandwidth, ifaceBand, - iface->mac, &new_rate)) < 0) { + &iface->mac, &new_rate)) < 0) { /* helper reported error */ goto cleanup; } @@ -5668,12 +5669,17 @@ networkBandwidthUpdate(virDomainNetDefPtr iface, } else if (newBandwidth->in && newBandwidth->in->floor) { /* .. or we need to plug in new .. */ - if (networkPlugBandwidthImpl(obj, iface, newBandwidth, new_rate) < 0) + if (networkPlugBandwidthImpl(obj, &iface->mac, newBandwidth, + iface->data.network.actual ? + &iface->data.network.actual->class_id : NULL, + new_rate) < 0) goto cleanup; } else { /* .. or unplug old. */ - if (networkUnplugBandwidth(obj, iface) < 0) + if (networkUnplugBandwidth(obj, iface->bandwidth, + iface->data.network.actual ? + &iface->data.network.actual->class_id : NULL) < 0) goto cleanup; } -- 2.19.2

Stop passing a virDomainNetDefPtr parameter to networkLogAllocation, instead just pass in the MAC address. The actual device type is also not required, since virNetworkForwardIfDefPtr has a type field that can be used instad. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 1014b53201..8d1a1b95d2 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -4392,32 +4392,29 @@ networkGetDHCPLeases(virNetworkPtr net, static void networkLogAllocation(virNetworkDefPtr netdef, - virDomainNetType actualType, virNetworkForwardIfDefPtr dev, - virDomainNetDefPtr iface, + virMacAddrPtr mac, bool inUse) { char macStr[VIR_MAC_STRING_BUFLEN]; const char *verb = inUse ? "using" : "releasing"; + virMacAddrFormat(mac, macStr); if (!dev) { VIR_INFO("MAC %s %s network %s (%d connections)", - virMacAddrFormat(&iface->mac, macStr), verb, - netdef->name, netdef->connections); + macStr, verb, netdef->name, netdef->connections); } else { - if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) { + if (dev->type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI) { VIR_INFO("MAC %s %s network %s (%d connections) " "physical device %04x:%02x:%02x.%x (%d connections)", - virMacAddrFormat(&iface->mac, macStr), verb, - netdef->name, netdef->connections, + macStr, verb, netdef->name, netdef->connections, dev->device.pci.domain, dev->device.pci.bus, dev->device.pci.slot, dev->device.pci.function, dev->connections); } else { VIR_INFO("MAC %s %s network %s (%d connections) " "physical device %s (%d connections)", - virMacAddrFormat(&iface->mac, macStr), verb, - netdef->name, netdef->connections, + macStr, verb, netdef->name, netdef->connections, dev->device.dev, dev->connections); } } @@ -4826,7 +4823,7 @@ networkAllocateActualDevice(virNetworkPtr net, dev->connections--; goto error; } - networkLogAllocation(netdef, actualType, dev, iface, true); + networkLogAllocation(netdef, dev, &iface->mac, true); ret = 0; @@ -5079,7 +5076,7 @@ networkNotifyActualDevice(virNetworkPtr net, netdef->connections--; goto error; } - networkLogAllocation(netdef, actualType, dev, iface, true); + networkLogAllocation(netdef, dev, &iface->mac, true); cleanup: virNetworkObjEndAPI(&obj); @@ -5246,7 +5243,7 @@ networkReleaseActualDevice(virNetworkPtr net, /* finally we can call the 'unplugged' hook script if any */ networkRunHook(obj, dom, iface, VIR_HOOK_NETWORK_OP_IFACE_UNPLUGGED, VIR_HOOK_SUBOP_BEGIN); - networkLogAllocation(netdef, actualType, dev, iface, false); + networkLogAllocation(netdef, dev, &iface->mac, false); } ret = 0; cleanup: -- 2.19.2

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/libvirt_private.syms | 1 + src/util/virnetdevvportprofile.c | 16 ++++++++++++++++ src/util/virnetdevvportprofile.h | 2 ++ 3 files changed, 19 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 0b363f8ec8..0a0079ae06 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2454,6 +2454,7 @@ virNetDevVlanFree; virNetDevVPortProfileAssociate; virNetDevVPortProfileCheckComplete; virNetDevVPortProfileCheckNoExtras; +virNetDevVPortProfileCopy; virNetDevVPortProfileDisassociate; virNetDevVPortProfileEqual; virNetDevVPortProfileMerge3; diff --git a/src/util/virnetdevvportprofile.c b/src/util/virnetdevvportprofile.c index 09c212bc4d..6aa0c9267b 100644 --- a/src/util/virnetdevvportprofile.c +++ b/src/util/virnetdevvportprofile.c @@ -123,6 +123,22 @@ virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a, virNetDevVPortProfilePtr return true; } + +int virNetDevVPortProfileCopy(virNetDevVPortProfilePtr *dst, const virNetDevVPortProfile *src) +{ + if (!src) { + *dst = NULL; + return 0; + } + + if (VIR_ALLOC(*dst) < 0) + return -1; + + memcpy(*dst, src, sizeof(*src)); + return 0; +} + + /* virNetDevVPortProfileCheckComplete() checks that all attributes * required for the type of virtport are specified. When * generateMissing is true, any missing attribute that can be diff --git a/src/util/virnetdevvportprofile.h b/src/util/virnetdevvportprofile.h index da52d00708..af98c7e1f7 100644 --- a/src/util/virnetdevvportprofile.h +++ b/src/util/virnetdevvportprofile.h @@ -79,6 +79,8 @@ struct _virNetDevVPortProfile { bool virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a, virNetDevVPortProfilePtr b); +int virNetDevVPortProfileCopy(virNetDevVPortProfilePtr *dst, + const virNetDevVPortProfile *src); int virNetDevVPortProfileCheckComplete(virNetDevVPortProfilePtr virtport, bool generateMissing); -- 2.19.2

Helper APIs are needed to - Populate basic virNetworkPortDef from virDomainNetDef - Set a virDomainActualNetDef from virNetworkPortDef - Populate a full virNetworkPortDef from virDomainActualNetDef Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_conf.c | 258 +++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 17 +++ src/libvirt_private.syms | 3 + 3 files changed, 278 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 2181940144..e384c60dfd 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -39,6 +39,7 @@ #include "virbuffer.h" #include "virlog.h" #include "nwfilter_conf.h" +#include "virnetworkportdef.h" #include "storage_conf.h" #include "virstoragefile.h" #include "virfile.h" @@ -30449,6 +30450,263 @@ virDomainNetTypeSharesHostView(const virDomainNetDef *net) return false; } +virNetworkPortDefPtr +virDomainNetDefToNetworkPort(virDomainDefPtr dom, + virDomainNetDefPtr iface) +{ + virNetworkPortDefPtr port; + + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Expected an interface of type 'network' not '%s'"), + virDomainNetTypeToString(iface->type)); + return NULL; + } + + if (VIR_ALLOC(port) < 0) + return NULL; + + virUUIDGenerate(port->uuid); + + memcpy(port->owneruuid, dom->uuid, VIR_UUID_BUFLEN); + if (VIR_STRDUP(port->ownername, dom->name) < 0) + goto error; + + if (VIR_STRDUP(port->group, iface->data.network.portgroup) < 0) + goto error; + + memcpy(&port->mac, &iface->mac, VIR_MAC_BUFLEN); + + if (virNetDevVPortProfileCopy(&port->virtPortProfile, iface->virtPortProfile) < 0) + goto error; + + if (virNetDevBandwidthCopy(&port->bandwidth, iface->bandwidth) < 0) + goto error; + + if (virNetDevVlanCopy(&port->vlan, &iface->vlan) < 0) + goto error; + + port->trustGuestRxFilters = iface->trustGuestRxFilters; + + return port; + + error: + virNetworkPortDefFree(port); + return NULL; +} + +int +virDomainNetDefActualFromNetworkPort(virDomainNetDefPtr iface, + virNetworkPortDefPtr port) +{ + virDomainActualNetDefPtr actual = NULL; + + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Expected an interface of type 'network' not '%s'"), + virDomainNetTypeToString(iface->type)); + return -1; + } + + if (VIR_ALLOC(actual) < 0) + return -1; + + switch ((virNetworkPortPlugType)port->plugtype) { + case VIR_NETWORK_PORT_PLUG_TYPE_NONE: + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE: + if (VIR_STRDUP(actual->data.bridge.brname, + port->plug.bridge.brname) < 0) + goto error; + actual->data.bridge.macTableManager = port->plug.bridge.macTableManager; + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT: + if (VIR_STRDUP(actual->data.direct.linkdev, + port->plug.direct.linkdev) < 0) + goto error; + actual->data.direct.mode = port->plug.direct.mode; + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI: + actual->data.hostdev.def.parent = iface; + actual->data.hostdev.def.info = &iface->info; + actual->data.hostdev.def.mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; + actual->data.hostdev.def.managed = port->plug.hostdevpci.managed; + actual->data.hostdev.def.source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI; + actual->data.hostdev.def.source.subsys.u.pci.addr = port->plug.hostdevpci.addr; + switch ((virNetworkForwardDriverNameType)port->plug.hostdevpci.driver) { + case VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT: + actual->data.hostdev.def.source.subsys.u.pci.backend = + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT; + break; + + case VIR_NETWORK_FORWARD_DRIVER_NAME_KVM: + actual->data.hostdev.def.source.subsys.u.pci.backend = + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM; + break; + + case VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO: + actual->data.hostdev.def.source.subsys.u.pci.backend = + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO; + break; + + case VIR_NETWORK_FORWARD_DRIVER_NAME_LAST: + default: + virReportEnumRangeError(virNetworkForwardDriverNameType, + port->plug.hostdevpci.driver); + goto error; + } + + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_LAST: + default: + virReportEnumRangeError(virNetworkPortPlugType, port->plugtype); + goto error; + } + + if (virNetDevVPortProfileCopy(&actual->virtPortProfile, port->virtPortProfile) < 0) + goto error; + + if (virNetDevBandwidthCopy(&actual->bandwidth, port->bandwidth) < 0) + goto error; + + if (virNetDevVlanCopy(&actual->vlan, &port->vlan) < 0) + goto error; + + actual->class_id = port->class_id; + actual->trustGuestRxFilters = port->trustGuestRxFilters; + + virDomainActualNetDefFree(iface->data.network.actual); + iface->data.network.actual = actual; + + return 0; + + error: + virDomainActualNetDefFree(actual); + return -1; +} + +virNetworkPortDefPtr +virDomainNetDefActualToNetworkPort(virDomainDefPtr dom, + virDomainNetDefPtr iface) +{ + virDomainActualNetDefPtr actual; + virNetworkPortDefPtr port; + + if (!iface->data.network.actual) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Missing actual data for interface '%s'"), + iface->ifname); + return NULL; + } + + actual = iface->data.network.actual; + + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Expected an interface of type 'network' not '%s'"), + virDomainNetTypeToString(iface->type)); + return NULL; + } + + if (VIR_ALLOC(port) < 0) + return NULL; + + /* Bad - we need to preserve original port uuid */ + virUUIDGenerate(port->uuid); + + memcpy(port->owneruuid, dom->uuid, VIR_UUID_BUFLEN); + if (VIR_STRDUP(port->ownername, dom->name) < 0) + goto error; + + if (VIR_STRDUP(port->group, iface->data.network.portgroup) < 0) + goto error; + + memcpy(&port->mac, &iface->mac, VIR_MAC_BUFLEN); + + switch ((virNetworkPortPlugType)port->plugtype) { + case VIR_NETWORK_PORT_PLUG_TYPE_NONE: + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE: + if (VIR_STRDUP(port->plug.bridge.brname, + actual->data.bridge.brname) < 0) + goto error; + port->plug.bridge.macTableManager = actual->data.bridge.macTableManager; + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT: + if (VIR_STRDUP(port->plug.direct.linkdev, + actual->data.direct.linkdev) < 0) + goto error; + port->plug.direct.mode = actual->data.direct.mode; + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI: + if (actual->data.hostdev.def.mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || + actual->data.hostdev.def.source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Actual interface '%s' hostdev was not a PCI device"), + iface->ifname); + goto error; + } + port->plug.hostdevpci.managed = actual->data.hostdev.def.managed; + port->plug.hostdevpci.addr = actual->data.hostdev.def.source.subsys.u.pci.addr; + switch ((virDomainHostdevSubsysPCIBackendType)actual->data.hostdev.def.source.subsys.u.pci.backend) { + case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT: + port->plug.hostdevpci.driver = VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT; + break; + + case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM: + port->plug.hostdevpci.driver = VIR_NETWORK_FORWARD_DRIVER_NAME_KVM; + break; + + case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO: + port->plug.hostdevpci.driver = VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO; + break; + + case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Unexpected PCI backend 'xen'")); + break; + + case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST: + default: + virReportEnumRangeError(virDomainHostdevSubsysPCIBackendType, + actual->data.hostdev.def.source.subsys.u.pci.backend); + goto error; + } + + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_LAST: + default: + virReportEnumRangeError(virNetworkPortPlugType, port->plugtype); + goto error; + } + + if (virNetDevVPortProfileCopy(&port->virtPortProfile, actual->virtPortProfile) < 0) + goto error; + + if (virNetDevBandwidthCopy(&port->bandwidth, actual->bandwidth) < 0) + goto error; + + if (virNetDevVlanCopy(&port->vlan, &actual->vlan) < 0) + goto error; + + port->class_id = actual->class_id; + port->trustGuestRxFilters = actual->trustGuestRxFilters; + + return port; + + error: + virNetworkPortDefFree(port); + return NULL; +} + static virDomainNetAllocateActualDeviceImpl netAllocate; static virDomainNetNotifyActualDeviceImpl netNotify; static virDomainNetReleaseActualDeviceImpl netRelease; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 829d7cd83e..0f672d718e 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3605,6 +3605,23 @@ bool virDomainDefLifecycleActionAllowed(virDomainLifecycle type, virDomainLifecycleAction action); +// Forward decl to avoid pulling in virnetworkportdef.h because +// that pulls in virhostdev.h which pulls in domain_conf.h (evil) +typedef struct _virNetworkPortDef virNetworkPortDef; +typedef virNetworkPortDef *virNetworkPortDefPtr; + +virNetworkPortDefPtr +virDomainNetDefToNetworkPort(virDomainDefPtr dom, + virDomainNetDefPtr iface); + +int +virDomainNetDefActualFromNetworkPort(virDomainNetDefPtr iface, + virNetworkPortDefPtr port); + +virNetworkPortDefPtr +virDomainNetDefActualToNetworkPort(virDomainDefPtr dom, + virDomainNetDefPtr iface); + typedef int (*virDomainNetAllocateActualDeviceImpl)(virNetworkPtr net, virDomainDefPtr dom, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 0a0079ae06..92e0994612 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -451,9 +451,12 @@ virDomainNetAllocateActualDevice; virDomainNetAppendIPAddress; virDomainNetBandwidthChangeAllowed; virDomainNetBandwidthUpdate; +virDomainNetDefActualFromNetworkPort; +virDomainNetDefActualToNetworkPort; virDomainNetDefClear; virDomainNetDefFormat; virDomainNetDefFree; +virDomainNetDefToNetworkPort; virDomainNetFind; virDomainNetFindByName; virDomainNetFindIdx; -- 2.19.2

Convert the virDomainNetDef object into a virNetworkPortDef object at the start of networkAllocateActualDevice. This largely decouples the method impl from the domain object type. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 222 +++++++++++++++--------------------- 1 file changed, 91 insertions(+), 131 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 8d1a1b95d2..594574db8c 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -68,6 +68,7 @@ #include "network_event.h" #include "virhook.h" #include "virjson.h" +#include "conf/virnetworkportdef.h" #define VIR_FROM_THIS VIR_FROM_NETWORK #define MAX_BRIDGE_ID 256 @@ -4447,17 +4448,16 @@ networkAllocateActualDevice(virNetworkPtr net, virDomainNetDefPtr iface) { virNetworkDriverStatePtr driver = networkGetDriver(); - virDomainNetType actualType = iface->type; virNetworkObjPtr obj = NULL; virNetworkDefPtr netdef = NULL; - virNetDevBandwidthPtr bandwidth = NULL; virPortGroupDefPtr portgroup = NULL; - virNetDevVPortProfilePtr virtport = iface->virtPortProfile; - virNetDevVlanPtr vlan = NULL; virNetworkForwardIfDefPtr dev = NULL; size_t i; int ret = -1; + virNetDevVPortProfilePtr portprofile = NULL; + virNetworkPortDefPtr port = NULL; + VIR_DEBUG("Allocating port from net %s", net->name); obj = virNetworkObjFindByName(driver->networks, net->name); if (!obj) { virReportError(VIR_ERR_NO_NETWORK, @@ -4472,9 +4472,6 @@ networkAllocateActualDevice(virNetworkPtr net, goto error; } - virDomainActualNetDefFree(iface->data.network.actual); - iface->data.network.actual = NULL; - netdef = virNetworkObjGetDef(obj); if (!virNetworkObjIsActive(obj)) { @@ -4484,99 +4481,84 @@ networkAllocateActualDevice(virNetworkPtr net, goto error; } - if (VIR_ALLOC(iface->data.network.actual) < 0) + if (!(port = virDomainNetDefToNetworkPort(dom, iface))) goto error; + VIR_DEBUG("Interface port group %s", port->group); /* portgroup can be present for any type of network, in particular * for bandwidth information, so we need to check for that and * fill it in appropriately for all forward types. */ - portgroup = virPortGroupFindByName(netdef, iface->data.network.portgroup); - - /* If there is already interface-specific bandwidth, just use that - * (already in NetDef). Otherwise, if there is bandwidth info in - * the portgroup, fill that into the ActualDef. - */ - - if (iface->bandwidth) - bandwidth = iface->bandwidth; - else if (portgroup && portgroup->bandwidth) - bandwidth = portgroup->bandwidth; + portgroup = virPortGroupFindByName(netdef, port->group); - if (bandwidth && virNetDevBandwidthCopy(&iface->data.network.actual->bandwidth, - bandwidth) < 0) - goto error; + if (!port->bandwidth) { + if (portgroup && portgroup->bandwidth && + virNetDevBandwidthCopy(&port->bandwidth, + portgroup->bandwidth) < 0) + goto error; + } - /* copy appropriate vlan info to actualNet */ - if (iface->vlan.nTags > 0) - vlan = &iface->vlan; - else if (portgroup && portgroup->vlan.nTags > 0) - vlan = &portgroup->vlan; - else if (netdef->vlan.nTags > 0) - vlan = &netdef->vlan; + if (port->vlan.nTags == 0) { + virNetDevVlanPtr vlan = NULL; + if (portgroup && portgroup->vlan.nTags > 0) + vlan = &portgroup->vlan; + else if (netdef->vlan.nTags > 0) + vlan = &netdef->vlan; - if (vlan && virNetDevVlanCopy(&iface->data.network.actual->vlan, vlan) < 0) - goto error; + if (vlan && virNetDevVlanCopy(&port->vlan, vlan) < 0) + goto error; + } - if (iface->trustGuestRxFilters) - iface->data.network.actual->trustGuestRxFilters - = iface->trustGuestRxFilters; - else if (portgroup && portgroup->trustGuestRxFilters) - iface->data.network.actual->trustGuestRxFilters - = portgroup->trustGuestRxFilters; - else if (netdef->trustGuestRxFilters) - iface->data.network.actual->trustGuestRxFilters - = netdef->trustGuestRxFilters; + if (!port->trustGuestRxFilters) { + if (portgroup && portgroup->trustGuestRxFilters) + port->trustGuestRxFilters = portgroup->trustGuestRxFilters; + else if (netdef->trustGuestRxFilters) + port->trustGuestRxFilters = netdef->trustGuestRxFilters; + } /* merge virtualports from interface, network, and portgroup to * arrive at actual virtualport to use */ - if (virNetDevVPortProfileMerge3(&iface->data.network.actual->virtPortProfile, - iface->virtPortProfile, + if (virNetDevVPortProfileMerge3(&portprofile, + port->virtPortProfile, netdef->virtPortProfile, portgroup ? portgroup->virtPortProfile : NULL) < 0) { - goto error; + goto error; + } + if (portprofile) { + VIR_FREE(port->virtPortProfile); + port->virtPortProfile = portprofile; } - virtport = iface->data.network.actual->virtPortProfile; + VIR_DEBUG("Processing forward type %d", netdef->forward.type); switch ((virNetworkForwardType) netdef->forward.type) { case VIR_NETWORK_FORWARD_NONE: case VIR_NETWORK_FORWARD_NAT: case VIR_NETWORK_FORWARD_ROUTE: case VIR_NETWORK_FORWARD_OPEN: - iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_BRIDGE; + port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE; - /* we also store the bridge device and macTableManager settings - * in iface->data.network.actual->data.bridge for later use - * after the domain's tap device is created (to attach to the - * bridge and set flood/learning mode on the tap device) - */ - if (VIR_STRDUP(iface->data.network.actual->data.bridge.brname, - netdef->bridge) < 0) + if (VIR_STRDUP(port->plug.bridge.brname, netdef->bridge) < 0) goto error; - iface->data.network.actual->data.bridge.macTableManager - = netdef->macTableManager; + port->plug.bridge.macTableManager = netdef->macTableManager; - if (virtport) { + if (port->virtPortProfile) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("<virtualport type='%s'> not supported for network " "'%s' which uses IP forwarding"), - virNetDevVPortTypeToString(virtport->virtPortType), + virNetDevVPortTypeToString(port->virtPortProfile->virtPortType), netdef->name); goto error; } - if (networkPlugBandwidth(obj, &iface->mac, iface->bandwidth, - iface->data.network.actual ? - &iface->data.network.actual->class_id : NULL) < 0) + if (networkPlugBandwidth(obj, &port->mac, port->bandwidth, &port->class_id) < 0) goto error; break; case VIR_NETWORK_FORWARD_HOSTDEV: { - virDomainHostdevSubsysPCIBackendType backend; + port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI; - iface->data.network.actual->type = actualType = VIR_DOMAIN_NET_TYPE_HOSTDEV; if (networkCreateInterfacePool(netdef) < 0) goto error; @@ -4594,42 +4576,19 @@ networkAllocateActualDevice(virNetworkPtr net, netdef->name); goto error; } - iface->data.network.actual->data.hostdev.def.parent = iface; - iface->data.network.actual->data.hostdev.def.info = &iface->info; - iface->data.network.actual->data.hostdev.def.mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; - iface->data.network.actual->data.hostdev.def.managed = netdef->forward.managed ? 1 : 0; - iface->data.network.actual->data.hostdev.def.source.subsys.type = dev->type; - iface->data.network.actual->data.hostdev.def.source.subsys.u.pci.addr = dev->device.pci; - - switch (netdef->forward.driverName) { - case VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT: - backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT; - break; - case VIR_NETWORK_FORWARD_DRIVER_NAME_KVM: - backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM; - break; - case VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO: - backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO; - break; - default: - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unrecognized driver name value %d " - " in network '%s'"), - netdef->forward.driverName, netdef->name); - goto error; - } - iface->data.network.actual->data.hostdev.def.source.subsys.u.pci.backend - = backend; + port->plug.hostdevpci.addr = dev->device.pci; + port->plug.hostdevpci.driver = netdef->forward.driverName; + port->plug.hostdevpci.managed = netdef->forward.managed; - if (virtport) { + if (port->virtPortProfile) { /* make sure type is supported for hostdev connections */ - if (virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBG && - virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBH) { + if (port->virtPortProfile->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBG && + port->virtPortProfile->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBH) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("<virtualport type='%s'> not supported for network " "'%s' which uses an SR-IOV Virtual Function " "via PCI passthrough"), - virNetDevVPortTypeToString(virtport->virtPortType), + virNetDevVPortTypeToString(port->virtPortProfile->virtPortType), netdef->name); goto error; } @@ -4643,28 +4602,24 @@ networkAllocateActualDevice(virNetworkPtr net, * is VIR_DOMAIN_NET_TYPE_BRIDGE */ - iface->data.network.actual->type = actualType = VIR_DOMAIN_NET_TYPE_BRIDGE; - if (VIR_STRDUP(iface->data.network.actual->data.bridge.brname, - netdef->bridge) < 0) + port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE; + if (VIR_STRDUP(port->plug.bridge.brname, netdef->bridge) < 0) goto error; - iface->data.network.actual->data.bridge.macTableManager - = netdef->macTableManager; + port->plug.bridge.macTableManager = netdef->macTableManager; - if (virtport) { + if (port->virtPortProfile) { /* only type='openvswitch' is allowed for bridges */ - if (virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) { + if (port->virtPortProfile->virtPortType != VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("<virtualport type='%s'> not supported for network " "'%s' which uses a bridge device"), - virNetDevVPortTypeToString(virtport->virtPortType), + virNetDevVPortTypeToString(port->virtPortProfile->virtPortType), netdef->name); goto error; } } - if (networkPlugBandwidth(obj, &iface->mac, iface->bandwidth, - iface->data.network.actual ? - &iface->data.network.actual->class_id : NULL) < 0) + if (networkPlugBandwidth(obj, &port->mac, port->bandwidth, &port->class_id) < 0) goto error; break; } @@ -4682,22 +4637,22 @@ networkAllocateActualDevice(virNetworkPtr net, */ /* Set type=direct and appropriate <source mode='xxx'/> */ - iface->data.network.actual->type = actualType = VIR_DOMAIN_NET_TYPE_DIRECT; + port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_DIRECT; /* NO need to check the value returned from virNetDevMacVLanModeTypeFromString * it must be valid for these forward type(bridge|private|vepa|passthrough) */ - iface->data.network.actual->data.direct.mode = + port->plug.direct.mode = virNetDevMacVLanModeTypeFromString(virNetworkForwardTypeToString(netdef->forward.type)); - if (virtport) { + if (port->virtPortProfile) { /* make sure type is supported for macvtap connections */ - if (virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBG && - virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBH) { + if (port->virtPortProfile->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBG && + port->virtPortProfile->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBH) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("<virtualport type='%s'> not supported for network " "'%s' which uses a macvtap device"), - virNetDevVPortTypeToString(virtport->virtPortType), + virNetDevVPortTypeToString(port->virtPortProfile->virtPortType), netdef->name); goto error; } @@ -4726,8 +4681,8 @@ networkAllocateActualDevice(virNetworkPtr net, */ if ((netdef->forward.type == VIR_NETWORK_FORWARD_PASSTHROUGH) || ((netdef->forward.type == VIR_NETWORK_FORWARD_PRIVATE) && - iface->data.network.actual->virtPortProfile && - (iface->data.network.actual->virtPortProfile->virtPortType + port->virtPortProfile && + (port->virtPortProfile->virtPortType == VIR_NETDEV_VPORT_PROFILE_8021QBH))) { /* pick first dev with 0 connections */ @@ -4753,7 +4708,7 @@ networkAllocateActualDevice(virNetworkPtr net, netdef->name); goto error; } - if (VIR_STRDUP(iface->data.network.actual->data.direct.linkdev, + if (VIR_STRDUP(port->plug.direct.linkdev, dev->device.dev) < 0) goto error; } @@ -4766,30 +4721,30 @@ networkAllocateActualDevice(virNetworkPtr net, } if (virNetworkObjMacMgrAdd(obj, driver->dnsmasqStateDir, - dom->name, &iface->mac) < 0) + dom->name, &port->mac) < 0) goto error; - if (virNetDevVPortProfileCheckComplete(virtport, true) < 0) + if (virNetDevVPortProfileCheckComplete(port->virtPortProfile, true) < 0) goto error; /* make sure that everything now specified for the device is * actually supported on this type of network. NB: network, * netdev, and iface->data.network.actual may all be NULL. */ + VIR_DEBUG("Sanity check port config"); - if (virDomainNetGetActualVlan(iface)) { + if (port->vlan.nTags) { /* vlan configuration via libvirt is only supported for PCI * Passthrough SR-IOV devices (hostdev or macvtap passthru * mode) and openvswitch bridges. Otherwise log an error and * fail */ - if (!(actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV || - (actualType == VIR_DOMAIN_NET_TYPE_DIRECT && - virDomainNetGetActualDirectMode(iface) - == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) || - (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE && - virtport && virtport->virtPortType - == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH))) { + if (!(port->plugtype == VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI || + (port->plugtype == VIR_NETWORK_PORT_PLUG_TYPE_DIRECT && + port->plug.direct.mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) || + (port->plugtype == VIR_DOMAIN_NET_TYPE_BRIDGE && + port->virtPortProfile && + port->virtPortProfile->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH))) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("an interface connecting to network '%s' " "is requesting a vlan tag, but that is not " @@ -4798,16 +4753,15 @@ networkAllocateActualDevice(virNetworkPtr net, goto error; } } - if (virDomainNetGetActualBandwidth(iface)) { - /* bandwidth configuration via libvirt is not supported for - * hostdev network devices - */ - if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("bandwidth settings are not supported " - "for hostdev interfaces")); - goto error; - } + + /* bandwidth configuration via libvirt is not supported for + * hostdev network devices + */ + if (port->bandwidth && port->plugtype == VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("bandwidth settings are not supported " + "for hostdev interfaces")); + goto error; } netdef->connections++; @@ -4825,9 +4779,15 @@ networkAllocateActualDevice(virNetworkPtr net, } networkLogAllocation(netdef, dev, &iface->mac, true); + VIR_DEBUG("Populating net def"); + if (virDomainNetDefActualFromNetworkPort(iface, port) < 0) + goto error; + + VIR_DEBUG("Port allocated"); ret = 0; cleanup: + virNetworkPortDefFree(port); virNetworkObjEndAPI(&obj); return ret; -- 2.19.2

Convert the virDomainNetDef object into a virNetworkPortDef object at the start of networkNotifyActualDevice. This largely decouples the method impl from the domain object type. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 127 +++++++++++++++++------------------- 1 file changed, 61 insertions(+), 66 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 594574db8c..109d284791 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -4822,8 +4822,10 @@ networkNotifyActualDevice(virNetworkPtr net, virNetworkObjPtr obj; virNetworkDefPtr netdef; virNetworkForwardIfDefPtr dev = NULL; + virNetworkPortDefPtr port = NULL; size_t i; char *master = NULL; + bool useOVS = false; obj = virNetworkObjFindByName(driver->networks, net->name); if (!obj) { @@ -4868,29 +4870,42 @@ networkNotifyActualDevice(virNetworkPtr net, actualType = VIR_DOMAIN_NET_TYPE_BRIDGE; } - /* see if we're connected to the correct bridge */ - if (netdef->bridge) { - bool useOVS = false; + if (!(port = virDomainNetDefActualToNetworkPort(dom, iface))) + goto cleanup; + + switch (port->plugtype) { + case VIR_NETWORK_PORT_PLUG_TYPE_NONE: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unexpectedly got a network port without a plug")); + goto error; - if (virNetDevGetMaster(iface->ifname, &master) < 0) + case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE: + /* see if we're connected to the correct bridge */ + if (!netdef->bridge) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unexpectedly got a network port plugged into a bridge")); + goto error; + } + + if (virNetDevGetMaster(port->plug.bridge.brname, &master) < 0) goto error; /* IFLA_MASTER for a tap on an OVS switch is always "ovs-system" */ if (STREQ_NULLABLE(master, "ovs-system")) { useOVS = true; VIR_FREE(master); - if (virNetDevOpenvswitchInterfaceGetMaster(iface->ifname, &master) < 0) + if (virNetDevOpenvswitchInterfaceGetMaster(port->plug.bridge.brname, &master) < 0) goto error; } if (STRNEQ_NULLABLE(netdef->bridge, master)) { /* disconnect from current (incorrect) bridge */ if (master) { - VIR_INFO("Removing %s from %s", iface->ifname, master); + VIR_INFO("Removing %s from %s", port->plug.bridge.brname, master); if (useOVS) - ignore_value(virNetDevOpenvswitchRemovePort(master, iface->ifname)); + ignore_value(virNetDevOpenvswitchRemovePort(master, port->plug.bridge.brname)); else - ignore_value(virNetDevBridgeRemovePort(master, iface->ifname)); + ignore_value(virNetDevBridgeRemovePort(master, port->plug.bridge.brname)); } /* attach/reattach to correct bridge. @@ -4898,51 +4913,28 @@ networkNotifyActualDevice(virNetworkPtr net, * so there is no point in trying to learn the actualMTU * (final arg to virNetDevTapAttachBridge()) */ - VIR_INFO("Attaching %s to %s", iface->ifname, netdef->bridge); - if (virNetDevTapAttachBridge(iface->ifname, netdef->bridge, - &iface->mac, dom->uuid, - virDomainNetGetActualVirtPortProfile(iface), - virDomainNetGetActualVlan(iface), - iface->mtu, NULL) < 0) { + VIR_INFO("Attaching %s to %s", port->plug.bridge.brname, netdef->bridge); + /* XXXXXXXXXXXXXXX MTU is bad perhaps ? */ + if (virNetDevTapAttachBridge(port->plug.bridge.brname, netdef->bridge, + &port->mac, port->owneruuid, + port->virtPortProfile, + &port->vlan, + 0, NULL) < 0) { goto error; } } - } - - if (!iface->data.network.actual || - (actualType != VIR_DOMAIN_NET_TYPE_DIRECT && - actualType != VIR_DOMAIN_NET_TYPE_HOSTDEV)) { - VIR_DEBUG("Nothing to claim from network %s", iface->data.network.name); - goto success; - } - - if (networkCreateInterfacePool(netdef) < 0) - goto error; - - if (netdef->forward.nifs == 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("network '%s' uses a direct or hostdev mode, " - "but has no forward dev and no interface pool"), - netdef->name); - goto error; - } - - if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) { - const char *actualDev; + break; - actualDev = virDomainNetGetActualDirectDev(iface); - if (!actualDev) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("the interface uses a direct mode, " - "but has no source dev")); + case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT: + if (networkCreateInterfacePool(netdef) < 0) goto error; - } /* find the matching interface and increment its connections */ for (i = 0; i < netdef->forward.nifs; i++) { if (netdef->forward.ifs[i].type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV && - STREQ(actualDev, netdef->forward.ifs[i].device.dev)) { + STREQ(port->plug.direct.linkdev, + netdef->forward.ifs[i].device.dev)) { dev = &netdef->forward.ifs[i]; break; } @@ -4951,8 +4943,9 @@ networkNotifyActualDevice(virNetworkPtr net, if (!dev) { virReportError(VIR_ERR_INTERNAL_ERROR, _("network '%s' doesn't have dev='%s' " - "in use by domain"), - netdef->name, actualDev); + "in use by network port '%s'"), + netdef->name, port->plug.direct.linkdev, + port->uuid); goto error; } @@ -4963,31 +4956,26 @@ networkNotifyActualDevice(virNetworkPtr net, if ((dev->connections > 0) && ((netdef->forward.type == VIR_NETWORK_FORWARD_PASSTHROUGH) || ((netdef->forward.type == VIR_NETWORK_FORWARD_PRIVATE) && - iface->data.network.actual->virtPortProfile && - (iface->data.network.actual->virtPortProfile->virtPortType - == VIR_NETDEV_VPORT_PROFILE_8021QBH)))) { + port->virtPortProfile && + (port->virtPortProfile->virtPortType == VIR_NETDEV_VPORT_PROFILE_8021QBH)))) { virReportError(VIR_ERR_INTERNAL_ERROR, _("network '%s' claims dev='%s' is already in " - "use by a different domain"), - netdef->name, actualDev); + "use by a different port"), + netdef->name, port->plug.direct.linkdev); goto error; } - } else /* if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) */ { - virDomainHostdevDefPtr hostdev; + break; - hostdev = virDomainNetGetActualHostdev(iface); - if (!hostdev) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("the interface uses a hostdev mode, " - "but has no hostdev")); + case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI: + + if (networkCreateInterfacePool(netdef) < 0) goto error; - } /* find the matching interface and increment its connections */ for (i = 0; i < netdef->forward.nifs; i++) { if (netdef->forward.ifs[i].type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI && - virPCIDeviceAddressEqual(&hostdev->source.subsys.u.pci.addr, + virPCIDeviceAddressEqual(&port->plug.hostdevpci.addr, &netdef->forward.ifs[i].device.pci)) { dev = &netdef->forward.ifs[i]; break; @@ -4997,12 +4985,12 @@ networkNotifyActualDevice(virNetworkPtr net, if (!dev) { virReportError(VIR_ERR_INTERNAL_ERROR, _("network '%s' doesn't have " - "PCI device %04x:%02x:%02x.%x in use by domain"), + "PCI device %04x:%02x:%02x.%x in use by network port"), netdef->name, - hostdev->source.subsys.u.pci.addr.domain, - hostdev->source.subsys.u.pci.addr.bus, - hostdev->source.subsys.u.pci.addr.slot, - hostdev->source.subsys.u.pci.addr.function); + port->plug.hostdevpci.addr.domain, + port->plug.hostdevpci.addr.bus, + port->plug.hostdevpci.addr.slot, + port->plug.hostdevpci.addr.function); goto error; } @@ -5015,15 +5003,21 @@ networkNotifyActualDevice(virNetworkPtr net, virReportError(VIR_ERR_INTERNAL_ERROR, _("network '%s' claims the PCI device at " "domain=%d bus=%d slot=%d function=%d " - "is already in use by a different domain"), + "is already in use by a different network port"), netdef->name, dev->device.pci.domain, dev->device.pci.bus, dev->device.pci.slot, dev->device.pci.function); goto error; } + + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_LAST: + default: + virReportEnumRangeError(virNetworkPortPlugType, port->plugtype); + goto error; } - success: netdef->connections++; if (dev) dev->connections++; @@ -5040,6 +5034,7 @@ networkNotifyActualDevice(virNetworkPtr net, cleanup: virNetworkObjEndAPI(&obj); + virNetworkPortDefFree(port); VIR_FREE(master); return; -- 2.19.2

Convert the virDomainNetDef object into a virNetworkPortDef object at the start of networkReleaseActualDevice. This largely decouples the method impl from the domain object type. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 137 +++++++++++++++--------------------- 1 file changed, 56 insertions(+), 81 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 109d284791..e75c596120 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -5060,10 +5060,10 @@ networkReleaseActualDevice(virNetworkPtr net, virDomainNetDefPtr iface) { virNetworkDriverStatePtr driver = networkGetDriver(); - virDomainNetType actualType = virDomainNetGetActualType(iface); virNetworkObjPtr obj; virNetworkDefPtr netdef; virNetworkForwardIfDefPtr dev = NULL; + virNetworkPortDefPtr port = NULL; size_t i; int ret = -1; @@ -5072,77 +5072,49 @@ networkReleaseActualDevice(virNetworkPtr net, virReportError(VIR_ERR_NO_NETWORK, _("no network with matching name '%s'"), net->name); - goto error; + goto cleanup; } if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Expected a interface for a virtual network")); - goto error; + goto cleanup; } + if (iface->data.network.actual == NULL) { + ret = 0; + goto cleanup; + } + + if (!(port = virDomainNetDefActualToNetworkPort(dom, iface))) + goto cleanup; + netdef = virNetworkObjGetDef(obj); - switch ((virNetworkForwardType) netdef->forward.type) { - case VIR_NETWORK_FORWARD_NONE: - case VIR_NETWORK_FORWARD_NAT: - case VIR_NETWORK_FORWARD_ROUTE: - case VIR_NETWORK_FORWARD_OPEN: - if (iface->data.network.actual && - networkUnplugBandwidth(obj, iface->bandwidth, - &iface->data.network.actual->class_id) < 0) - goto error; + switch ((virNetworkPortPlugType)port->plugtype) { + case VIR_NETWORK_PORT_PLUG_TYPE_NONE: + VIR_DEBUG("Releasing network device with no plug type"); break; - case VIR_NETWORK_FORWARD_BRIDGE: - if (iface->data.network.actual && - actualType == VIR_DOMAIN_NET_TYPE_BRIDGE && - networkUnplugBandwidth(obj, iface->bandwidth, - &iface->data.network.actual->class_id) < 0) - goto error; - break; - case VIR_NETWORK_FORWARD_PRIVATE: - case VIR_NETWORK_FORWARD_VEPA: - case VIR_NETWORK_FORWARD_PASSTHROUGH: - case VIR_NETWORK_FORWARD_HOSTDEV: + case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE: + if (networkUnplugBandwidth(obj, port->bandwidth, + &port->class_id) < 0) + goto cleanup; break; - case VIR_NETWORK_FORWARD_LAST: - default: - virReportEnumRangeError(virNetworkForwardType, netdef->forward.type); - goto error; - } - - if ((!iface->data.network.actual) || - ((actualType != VIR_DOMAIN_NET_TYPE_DIRECT) && - (actualType != VIR_DOMAIN_NET_TYPE_HOSTDEV))) { - VIR_DEBUG("Nothing to release to network %s", iface->data.network.name); - goto success; - } - - if (netdef->forward.nifs == 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("network '%s' uses a direct/hostdev mode, but " - "has no forward dev and no interface pool"), - netdef->name); - goto error; - } - - if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) { - const char *actualDev; - - actualDev = virDomainNetGetActualDirectDev(iface); - if (!actualDev) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("the interface uses a direct mode, " - "but has no source dev")); - goto error; + case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT: + if (netdef->forward.nifs == 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("network '%s' uses a direct mode, but " + "has no forward dev and no interface pool"), + netdef->name); + goto cleanup; } for (i = 0; i < netdef->forward.nifs; i++) { if (netdef->forward.ifs[i].type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV && - STREQ(actualDev, netdef->forward.ifs[i].device.dev)) { + STREQ(port->plug.direct.linkdev, netdef->forward.ifs[i].device.dev)) { dev = &netdef->forward.ifs[i]; break; } @@ -5152,23 +5124,24 @@ networkReleaseActualDevice(virNetworkPtr net, virReportError(VIR_ERR_INTERNAL_ERROR, _("network '%s' doesn't have dev='%s' " "in use by domain"), - netdef->name, actualDev); - goto error; + netdef->name, port->plug.direct.linkdev); + goto cleanup; } - } else /* if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) */ { - virDomainHostdevDefPtr hostdev; + break; - hostdev = virDomainNetGetActualHostdev(iface); - if (!hostdev) { + case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI: + if (netdef->forward.nifs == 0) { virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("the interface uses a hostdev mode, but has no hostdev")); - goto error; + _("network '%s' uses a hostdev mode, but " + "has no forward dev and no interface pool"), + netdef->name); + goto cleanup; } for (i = 0; i < netdef->forward.nifs; i++) { if (netdef->forward.ifs[i].type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI && - virPCIDeviceAddressEqual(&hostdev->source.subsys.u.pci.addr, + virPCIDeviceAddressEqual(&port->plug.hostdevpci.addr, &netdef->forward.ifs[i].device.pci)) { dev = &netdef->forward.ifs[i]; break; @@ -5180,26 +5153,30 @@ networkReleaseActualDevice(virNetworkPtr net, _("network '%s' doesn't have " "PCI device %04x:%02x:%02x.%x in use by domain"), netdef->name, - hostdev->source.subsys.u.pci.addr.domain, - hostdev->source.subsys.u.pci.addr.bus, - hostdev->source.subsys.u.pci.addr.slot, - hostdev->source.subsys.u.pci.addr.function); - goto error; + port->plug.hostdevpci.addr.domain, + port->plug.hostdevpci.addr.bus, + port->plug.hostdevpci.addr.slot, + port->plug.hostdevpci.addr.function); + goto cleanup; } + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_LAST: + default: + virReportEnumRangeError(virNetworkPortPlugType, port->plugtype); + goto cleanup; } - success: virNetworkObjMacMgrDel(obj, driver->dnsmasqStateDir, dom->name, &iface->mac); - if (iface->data.network.actual) { - netdef->connections--; - if (dev) - dev->connections--; - /* finally we can call the 'unplugged' hook script if any */ - networkRunHook(obj, dom, iface, VIR_HOOK_NETWORK_OP_IFACE_UNPLUGGED, - VIR_HOOK_SUBOP_BEGIN); - networkLogAllocation(netdef, dev, &iface->mac, false); - } + netdef->connections--; + if (dev) + dev->connections--; + /* finally we can call the 'unplugged' hook script if any */ + networkRunHook(obj, dom, iface, VIR_HOOK_NETWORK_OP_IFACE_UNPLUGGED, + VIR_HOOK_SUBOP_BEGIN); + networkLogAllocation(netdef, dev, &iface->mac, false); + ret = 0; cleanup: virNetworkObjEndAPI(&obj); @@ -5207,10 +5184,8 @@ networkReleaseActualDevice(virNetworkPtr net, virDomainActualNetDefFree(iface->data.network.actual); iface->data.network.actual = NULL; } + virNetworkPortDefFree(port); return ret; - - error: - goto cleanup; } -- 2.19.2

When (un)plugging an interface into a network, the 'plugged' and 'unplugged' operations are invoked in the hook script. The data provided to the script contains the network XML, the domain XML and the domain interface XML. When we strictly split the drivers up this will no longer be possible and thus breakage is unavoidable. The hook scripts are not considered to be covered by the API guarantee so this is OK. To avoid existing scripts taking the wrong action, the existing operations are changed to 'port-created' and 'port-deleted' instead. These will receive the network XML and the network port XML. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 27 +++++++++++---------------- src/util/virhook.c | 4 ++-- src/util/virhook.h | 4 ++-- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index e75c596120..c3875cb68e 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -206,14 +206,13 @@ networkObjFromNetwork(virNetworkPtr net) static int networkRunHook(virNetworkObjPtr obj, - virDomainDefPtr dom, - virDomainNetDefPtr iface, + virNetworkPortDefPtr port, int op, int sub_op) { virNetworkDefPtr def; virBuffer buf = VIR_BUFFER_INITIALIZER; - char *xml = NULL, *net_xml = NULL, *dom_xml = NULL; + char *xml = NULL; int hookret; int ret = -1; @@ -227,12 +226,10 @@ networkRunHook(virNetworkObjPtr obj, virBufferAddLit(&buf, "<hookData>\n"); virBufferAdjustIndent(&buf, 2); - if (iface && virDomainNetDefFormat(&buf, iface, NULL, 0) < 0) + if (port && virNetworkPortDefFormatBuf(&buf, port) < 0) goto cleanup; if (virNetworkDefFormatBuf(&buf, def, 0) < 0) goto cleanup; - if (dom && virDomainDefFormatInternal(dom, NULL, 0, &buf, NULL) < 0) - goto cleanup; virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</hookData>"); @@ -257,8 +254,6 @@ networkRunHook(virNetworkObjPtr obj, cleanup: virBufferFreeAndReset(&buf); VIR_FREE(xml); - VIR_FREE(net_xml); - VIR_FREE(dom_xml); return ret; } @@ -2847,7 +2842,7 @@ networkStartNetwork(virNetworkDriverStatePtr driver, /* Run an early hook to set-up missing devices. * If the script raised an error abort the launch. */ - if (networkRunHook(obj, NULL, NULL, + if (networkRunHook(obj, NULL, VIR_HOOK_NETWORK_OP_START, VIR_HOOK_SUBOP_BEGIN) < 0) goto cleanup; @@ -2889,7 +2884,7 @@ networkStartNetwork(virNetworkDriverStatePtr driver, } /* finally we can call the 'started' hook script if any */ - if (networkRunHook(obj, NULL, NULL, + if (networkRunHook(obj, NULL, VIR_HOOK_NETWORK_OP_STARTED, VIR_HOOK_SUBOP_BEGIN) < 0) goto cleanup; @@ -2973,7 +2968,7 @@ networkShutdownNetwork(virNetworkDriverStatePtr driver, } /* now that we know it's stopped call the hook if present */ - networkRunHook(obj, NULL, NULL, VIR_HOOK_NETWORK_OP_STOPPED, + networkRunHook(obj, NULL, VIR_HOOK_NETWORK_OP_STOPPED, VIR_HOOK_SUBOP_END); virNetworkObjSetActive(obj, false); @@ -3947,7 +3942,7 @@ networkUpdate(virNetworkPtr net, } /* call the 'updated' network hook script */ - if (networkRunHook(obj, NULL, NULL, VIR_HOOK_NETWORK_OP_UPDATED, + if (networkRunHook(obj, NULL, VIR_HOOK_NETWORK_OP_UPDATED, VIR_HOOK_SUBOP_BEGIN) < 0) goto cleanup; @@ -4768,8 +4763,8 @@ networkAllocateActualDevice(virNetworkPtr net, if (dev) dev->connections++; /* finally we can call the 'plugged' hook script if any */ - if (networkRunHook(obj, dom, iface, - VIR_HOOK_NETWORK_OP_IFACE_PLUGGED, + if (networkRunHook(obj, port, + VIR_HOOK_NETWORK_OP_PORT_CREATED, VIR_HOOK_SUBOP_BEGIN) < 0) { /* adjust for failure */ netdef->connections--; @@ -5022,7 +5017,7 @@ networkNotifyActualDevice(virNetworkPtr net, if (dev) dev->connections++; /* finally we can call the 'plugged' hook script if any */ - if (networkRunHook(obj, dom, iface, VIR_HOOK_NETWORK_OP_IFACE_PLUGGED, + if (networkRunHook(obj, port, VIR_HOOK_NETWORK_OP_PORT_CREATED, VIR_HOOK_SUBOP_BEGIN) < 0) { /* adjust for failure */ if (dev) @@ -5173,7 +5168,7 @@ networkReleaseActualDevice(virNetworkPtr net, if (dev) dev->connections--; /* finally we can call the 'unplugged' hook script if any */ - networkRunHook(obj, dom, iface, VIR_HOOK_NETWORK_OP_IFACE_UNPLUGGED, + networkRunHook(obj, port, VIR_HOOK_NETWORK_OP_PORT_DELETED, VIR_HOOK_SUBOP_BEGIN); networkLogAllocation(netdef, dev, &iface->mac, false); diff --git a/src/util/virhook.c b/src/util/virhook.c index 2b91603dcf..51a9df3e4e 100644 --- a/src/util/virhook.c +++ b/src/util/virhook.c @@ -90,8 +90,8 @@ VIR_ENUM_IMPL(virHookNetworkOp, VIR_HOOK_NETWORK_OP_LAST, "start", "started", "stopped", - "plugged", - "unplugged", + "port-created", + "port-deleted", "updated") VIR_ENUM_IMPL(virHookLibxlOp, VIR_HOOK_LIBXL_OP_LAST, diff --git a/src/util/virhook.h b/src/util/virhook.h index 034fb8f263..fa188c89e3 100644 --- a/src/util/virhook.h +++ b/src/util/virhook.h @@ -79,8 +79,8 @@ typedef enum { VIR_HOOK_NETWORK_OP_START, /* network is about to start */ VIR_HOOK_NETWORK_OP_STARTED, /* network has start */ VIR_HOOK_NETWORK_OP_STOPPED, /* network has stopped */ - VIR_HOOK_NETWORK_OP_IFACE_PLUGGED, /* an interface has been plugged into the network */ - VIR_HOOK_NETWORK_OP_IFACE_UNPLUGGED, /* an interface was unplugged from the network */ + VIR_HOOK_NETWORK_OP_PORT_CREATED, /* port has been created in the network */ + VIR_HOOK_NETWORK_OP_PORT_DELETED, /* port has been deleted in the network */ VIR_HOOK_NETWORK_OP_UPDATED, /* network has been updated */ VIR_HOOK_NETWORK_OP_LAST, -- 2.19.2

Separate network port allocation code from the domain driver network callback implementation. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 143 +++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 66 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index c3875cb68e..ebce90d89a 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -4425,60 +4425,38 @@ networkLogAllocation(virNetworkDefPtr netdef, * "backend" function table. */ -/* networkAllocateActualDevice: - * @dom: domain definition that @iface belongs to - * @iface: the original NetDef from the domain +/* networkAllocatePort: + * @obj: the network to allocate from + * @port: the port definition to allocate * - * Looks up the network reference by iface, allocates a physical + * Looks up the network reference by port, allocates a physical * device from that network (if appropriate), and returns with the - * virDomainActualNetDef filled in accordingly. If there are no - * changes to be made in the netdef, then just leave the actualdef - * empty. + * port configuration filled in accordingly. * * Returns 0 on success, -1 on failure. */ static int -networkAllocateActualDevice(virNetworkPtr net, - virDomainDefPtr dom, - virDomainNetDefPtr iface) +networkAllocatePort(virNetworkObjPtr obj, + virNetworkPortDefPtr port) { virNetworkDriverStatePtr driver = networkGetDriver(); - virNetworkObjPtr obj = NULL; virNetworkDefPtr netdef = NULL; virPortGroupDefPtr portgroup = NULL; virNetworkForwardIfDefPtr dev = NULL; size_t i; int ret = -1; virNetDevVPortProfilePtr portprofile = NULL; - virNetworkPortDefPtr port = NULL; - - VIR_DEBUG("Allocating port from net %s", net->name); - obj = virNetworkObjFindByName(driver->networks, net->name); - if (!obj) { - virReportError(VIR_ERR_NO_NETWORK, - _("no network with matching name '%s'"), - net->name); - goto error; - } - - if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Expected a interface for a virtual network")); - goto error; - } netdef = virNetworkObjGetDef(obj); + VIR_DEBUG("Allocating port from net %s", netdef->name); if (!virNetworkObjIsActive(obj)) { virReportError(VIR_ERR_OPERATION_INVALID, _("network '%s' is not active"), netdef->name); - goto error; + goto cleanup; } - if (!(port = virDomainNetDefToNetworkPort(dom, iface))) - goto error; - VIR_DEBUG("Interface port group %s", port->group); /* portgroup can be present for any type of network, in particular * for bandwidth information, so we need to check for that and @@ -4490,7 +4468,7 @@ networkAllocateActualDevice(virNetworkPtr net, if (portgroup && portgroup->bandwidth && virNetDevBandwidthCopy(&port->bandwidth, portgroup->bandwidth) < 0) - goto error; + goto cleanup; } if (port->vlan.nTags == 0) { @@ -4501,7 +4479,7 @@ networkAllocateActualDevice(virNetworkPtr net, vlan = &netdef->vlan; if (vlan && virNetDevVlanCopy(&port->vlan, vlan) < 0) - goto error; + goto cleanup; } if (!port->trustGuestRxFilters) { @@ -4519,7 +4497,7 @@ networkAllocateActualDevice(virNetworkPtr net, netdef->virtPortProfile, portgroup ? portgroup->virtPortProfile : NULL) < 0) { - goto error; + goto cleanup; } if (portprofile) { VIR_FREE(port->virtPortProfile); @@ -4535,7 +4513,7 @@ networkAllocateActualDevice(virNetworkPtr net, port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE; if (VIR_STRDUP(port->plug.bridge.brname, netdef->bridge) < 0) - goto error; + goto cleanup; port->plug.bridge.macTableManager = netdef->macTableManager; if (port->virtPortProfile) { @@ -4544,18 +4522,18 @@ networkAllocateActualDevice(virNetworkPtr net, "'%s' which uses IP forwarding"), virNetDevVPortTypeToString(port->virtPortProfile->virtPortType), netdef->name); - goto error; + goto cleanup; } if (networkPlugBandwidth(obj, &port->mac, port->bandwidth, &port->class_id) < 0) - goto error; + goto cleanup; break; case VIR_NETWORK_FORWARD_HOSTDEV: { port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI; if (networkCreateInterfacePool(netdef) < 0) - goto error; + goto cleanup; /* pick first dev with 0 connections */ for (i = 0; i < netdef->forward.nifs; i++) { @@ -4569,7 +4547,7 @@ networkAllocateActualDevice(virNetworkPtr net, _("network '%s' requires exclusive access " "to interfaces, but none are available"), netdef->name); - goto error; + goto cleanup; } port->plug.hostdevpci.addr = dev->device.pci; port->plug.hostdevpci.driver = netdef->forward.driverName; @@ -4585,7 +4563,7 @@ networkAllocateActualDevice(virNetworkPtr net, "via PCI passthrough"), virNetDevVPortTypeToString(port->virtPortProfile->virtPortType), netdef->name); - goto error; + goto cleanup; } } break; @@ -4599,7 +4577,7 @@ networkAllocateActualDevice(virNetworkPtr net, port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE; if (VIR_STRDUP(port->plug.bridge.brname, netdef->bridge) < 0) - goto error; + goto cleanup; port->plug.bridge.macTableManager = netdef->macTableManager; if (port->virtPortProfile) { @@ -4610,12 +4588,12 @@ networkAllocateActualDevice(virNetworkPtr net, "'%s' which uses a bridge device"), virNetDevVPortTypeToString(port->virtPortProfile->virtPortType), netdef->name); - goto error; + goto cleanup; } } if (networkPlugBandwidth(obj, &port->mac, port->bandwidth, &port->class_id) < 0) - goto error; + goto cleanup; break; } @@ -4649,7 +4627,7 @@ networkAllocateActualDevice(virNetworkPtr net, "'%s' which uses a macvtap device"), virNetDevVPortTypeToString(port->virtPortProfile->virtPortType), netdef->name); - goto error; + goto cleanup; } } @@ -4661,12 +4639,12 @@ networkAllocateActualDevice(virNetworkPtr net, _("network '%s' uses a direct mode, but " "has no forward dev and no interface pool"), netdef->name); - goto error; + goto cleanup; } else { /* pick an interface from the pool */ if (networkCreateInterfacePool(netdef) < 0) - goto error; + goto cleanup; /* PASSTHROUGH mode, and PRIVATE Mode + 802.1Qbh both * require exclusive access to a device, so current @@ -4701,26 +4679,26 @@ networkAllocateActualDevice(virNetworkPtr net, _("network '%s' requires exclusive access " "to interfaces, but none are available"), netdef->name); - goto error; + goto cleanup; } if (VIR_STRDUP(port->plug.direct.linkdev, dev->device.dev) < 0) - goto error; + goto cleanup; } break; case VIR_NETWORK_FORWARD_LAST: default: virReportEnumRangeError(virNetworkForwardType, netdef->forward.type); - goto error; + goto cleanup; } if (virNetworkObjMacMgrAdd(obj, driver->dnsmasqStateDir, - dom->name, &port->mac) < 0) - goto error; + port->ownername, &port->mac) < 0) + goto cleanup; if (virNetDevVPortProfileCheckComplete(port->virtPortProfile, true) < 0) - goto error; + goto cleanup; /* make sure that everything now specified for the device is * actually supported on this type of network. NB: network, @@ -4745,7 +4723,7 @@ networkAllocateActualDevice(virNetworkPtr net, "is requesting a vlan tag, but that is not " "supported for this type of network"), netdef->name); - goto error; + goto cleanup; } } @@ -4756,7 +4734,7 @@ networkAllocateActualDevice(virNetworkPtr net, virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("bandwidth settings are not supported " "for hostdev interfaces")); - goto error; + goto cleanup; } netdef->connections++; @@ -4770,28 +4748,61 @@ networkAllocateActualDevice(virNetworkPtr net, netdef->connections--; if (dev) dev->connections--; - goto error; + goto cleanup; } - networkLogAllocation(netdef, dev, &iface->mac, true); - - VIR_DEBUG("Populating net def"); - if (virDomainNetDefActualFromNetworkPort(iface, port) < 0) - goto error; + networkLogAllocation(netdef, dev, &port->mac, true); VIR_DEBUG("Port allocated"); - ret = 0; + ret = 0; cleanup: - virNetworkPortDefFree(port); - virNetworkObjEndAPI(&obj); return ret; +} - error: - if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + +static int +networkAllocateActualDevice(virNetworkPtr net, + virDomainDefPtr dom, + virDomainNetDefPtr iface) +{ + virNetworkDriverStatePtr driver = networkGetDriver(); + virNetworkPortDefPtr port = NULL; + virNetworkObjPtr obj; + int ret = -1; + + obj = virNetworkObjFindByName(driver->networks, net->name); + if (!obj) { + virReportError(VIR_ERR_NO_NETWORK, + _("no network with matching name '%s'"), + net->name); + return -1; + } + + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Expected a interface for a virtual network")); + goto cleanup; + } + + if (!(port = virDomainNetDefToNetworkPort(dom, iface))) + goto cleanup; + + if (networkAllocatePort(obj, port) < 0) + goto cleanup; + + VIR_DEBUG("Populating net def"); + if (virDomainNetDefActualFromNetworkPort(iface, port) < 0) + goto cleanup; + + ret = 0; + cleanup: + if (ret < 0) { virDomainActualNetDefFree(iface->data.network.actual); iface->data.network.actual = NULL; } - goto cleanup; + virNetworkPortDefFree(port); + virNetworkObjEndAPI(&obj); + return ret; } -- 2.19.2

Separate network port notification code from the domain driver network callback implementation. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 159 ++++++++++++++++++++---------------- 1 file changed, 89 insertions(+), 70 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index ebce90d89a..25e856a7e2 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -4806,46 +4806,26 @@ networkAllocateActualDevice(virNetworkPtr net, } -/* networkNotifyActualDevice: - * @dom: domain definition that @iface belongs to - * @iface: the domain's NetDef with an "actual" device already filled in. +/* networkNotifyPort: + * @obj: the network to notify + * @port: the port definition to notify * * Called to notify the network driver when libvirtd is restarted and * finds an already running domain. If appropriate it will force an * allocation of the actual->direct.linkdev to get everything back in * order, or re-attach the interface's tap device to the network's * bridge. - * - * No return value (but does log any failures) */ -static void -networkNotifyActualDevice(virNetworkPtr net, - virDomainDefPtr dom, - virDomainNetDefPtr iface) +static int +networkNotifyPort(virNetworkObjPtr obj, + virNetworkPortDefPtr port) { - virNetworkDriverStatePtr driver = networkGetDriver(); - virDomainNetType actualType = virDomainNetGetActualType(iface); - virNetworkObjPtr obj; virNetworkDefPtr netdef; virNetworkForwardIfDefPtr dev = NULL; - virNetworkPortDefPtr port = NULL; size_t i; char *master = NULL; bool useOVS = false; - - obj = virNetworkObjFindByName(driver->networks, net->name); - if (!obj) { - virReportError(VIR_ERR_NO_NETWORK, - _("no network with matching name '%s'"), - net->name); - goto error; - } - - if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Expected a interface for a virtual network")); - goto error; - } + int ret = -1; netdef = virNetworkObjGetDef(obj); @@ -4853,55 +4833,32 @@ networkNotifyActualDevice(virNetworkPtr net, virReportError(VIR_ERR_OPERATION_INVALID, _("network '%s' is not active"), netdef->name); - goto error; - } - - /* if we're restarting libvirtd after an upgrade from a version - * that didn't save bridge name in actualNetDef for - * actualType==network, we need to copy it in so that it will be - * available in all cases - */ - if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE && - !iface->data.network.actual->data.bridge.brname && - (VIR_STRDUP(iface->data.network.actual->data.bridge.brname, - netdef->bridge) < 0)) - goto error; - - /* Older libvirtd uses actualType==network, but we now - * just use actualType==bridge, as nothing needs to - * distinguish the two cases, and this simplifies virt - * drive code */ - if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK) { - iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_BRIDGE; - actualType = VIR_DOMAIN_NET_TYPE_BRIDGE; - } - - if (!(port = virDomainNetDefActualToNetworkPort(dom, iface))) goto cleanup; + } switch (port->plugtype) { case VIR_NETWORK_PORT_PLUG_TYPE_NONE: virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unexpectedly got a network port without a plug")); - goto error; + goto cleanup; case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE: /* see if we're connected to the correct bridge */ if (!netdef->bridge) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unexpectedly got a network port plugged into a bridge")); - goto error; + goto cleanup; } if (virNetDevGetMaster(port->plug.bridge.brname, &master) < 0) - goto error; + goto cleanup; /* IFLA_MASTER for a tap on an OVS switch is always "ovs-system" */ if (STREQ_NULLABLE(master, "ovs-system")) { useOVS = true; VIR_FREE(master); if (virNetDevOpenvswitchInterfaceGetMaster(port->plug.bridge.brname, &master) < 0) - goto error; + goto cleanup; } if (STRNEQ_NULLABLE(netdef->bridge, master)) { @@ -4926,14 +4883,14 @@ networkNotifyActualDevice(virNetworkPtr net, port->virtPortProfile, &port->vlan, 0, NULL) < 0) { - goto error; + goto cleanup; } } break; case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT: if (networkCreateInterfacePool(netdef) < 0) - goto error; + goto cleanup; /* find the matching interface and increment its connections */ for (i = 0; i < netdef->forward.nifs; i++) { @@ -4952,7 +4909,7 @@ networkNotifyActualDevice(virNetworkPtr net, "in use by network port '%s'"), netdef->name, port->plug.direct.linkdev, port->uuid); - goto error; + goto cleanup; } /* PASSTHROUGH mode and PRIVATE Mode + 802.1Qbh both require @@ -4968,14 +4925,14 @@ networkNotifyActualDevice(virNetworkPtr net, _("network '%s' claims dev='%s' is already in " "use by a different port"), netdef->name, port->plug.direct.linkdev); - goto error; + goto cleanup; } break; case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI: if (networkCreateInterfacePool(netdef) < 0) - goto error; + goto cleanup; /* find the matching interface and increment its connections */ for (i = 0; i < netdef->forward.nifs; i++) { @@ -4997,7 +4954,7 @@ networkNotifyActualDevice(virNetworkPtr net, port->plug.hostdevpci.addr.bus, port->plug.hostdevpci.addr.slot, port->plug.hostdevpci.addr.function); - goto error; + goto cleanup; } /* PASSTHROUGH mode, PRIVATE Mode + 802.1Qbh, and hostdev (PCI @@ -5013,7 +4970,7 @@ networkNotifyActualDevice(virNetworkPtr net, netdef->name, dev->device.pci.domain, dev->device.pci.bus, dev->device.pci.slot, dev->device.pci.function); - goto error; + goto cleanup; } break; @@ -5021,7 +4978,7 @@ networkNotifyActualDevice(virNetworkPtr net, case VIR_NETWORK_PORT_PLUG_TYPE_LAST: default: virReportEnumRangeError(virNetworkPortPlugType, port->plugtype); - goto error; + goto cleanup; } netdef->connections++; @@ -5034,18 +4991,80 @@ networkNotifyActualDevice(virNetworkPtr net, if (dev) dev->connections--; netdef->connections--; - goto error; + goto cleanup; } - networkLogAllocation(netdef, dev, &iface->mac, true); + networkLogAllocation(netdef, dev, &port->mac, true); + ret = 0; cleanup: - virNetworkObjEndAPI(&obj); - virNetworkPortDefFree(port); VIR_FREE(master); - return; + return ret; +} - error: - goto cleanup; + +static void +networkNotifyActualDevice(virNetworkPtr net, + virDomainDefPtr dom, + virDomainNetDefPtr iface) +{ + virNetworkDriverStatePtr driver = networkGetDriver(); + virDomainNetType actualType = virDomainNetGetActualType(iface); + virNetworkObjPtr obj; + virNetworkDefPtr netdef; + virNetworkPortDefPtr port = NULL; + + obj = virNetworkObjFindByName(driver->networks, net->name); + if (!obj) { + virReportError(VIR_ERR_NO_NETWORK, + _("no network with matching name '%s'"), + net->name); + goto cleanup; + } + + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Expected a interface for a virtual network")); + goto cleanup; + } + + netdef = virNetworkObjGetDef(obj); + + if (!virNetworkObjIsActive(obj)) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("network '%s' is not active"), + netdef->name); + goto cleanup; + } + + /* if we're restarting libvirtd after an upgrade from a version + * that didn't save bridge name in actualNetDef for + * actualType==network, we need to copy it in so that it will be + * available in all cases + */ + if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE && + !iface->data.network.actual->data.bridge.brname && + (VIR_STRDUP(iface->data.network.actual->data.bridge.brname, + netdef->bridge) < 0)) + goto cleanup; + + /* Older libvirtd uses actualType==network, but we now + * just use actualType==bridge, as nothing needs to + * distinguish the two cases, and this simplifies virt + * drive code */ + if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK) { + iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_BRIDGE; + actualType = VIR_DOMAIN_NET_TYPE_BRIDGE; + } + + if (!(port = virDomainNetDefActualToNetworkPort(dom, iface))) + goto cleanup; + + if (networkNotifyPort(obj, port) < 0) + goto cleanup; + + cleanup: + virNetworkObjEndAPI(&obj); + virNetworkPortDefFree(port); } -- 2.19.2

Separate network port deletion code from the domain driver network callback implementation. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 91 ++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 25e856a7e2..37c49abde7 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -5068,9 +5068,9 @@ networkNotifyActualDevice(virNetworkPtr net, } -/* networkReleaseActualDevice: - * @dom: domain definition that @iface belongs to - * @iface: a domain's NetDef (interface definition) +/* networkReleasePort: + * @obj: the network to release from + * @port: the port definition to release * * Given a domain <interface> element that previously had its <actual> * element filled in (and possibly a physical device allocated to it), @@ -5080,40 +5080,15 @@ networkNotifyActualDevice(virNetworkPtr net, * Returns 0 on success, -1 on failure. */ static int -networkReleaseActualDevice(virNetworkPtr net, - virDomainDefPtr dom, - virDomainNetDefPtr iface) +networkReleasePort(virNetworkObjPtr obj, + virNetworkPortDefPtr port) { virNetworkDriverStatePtr driver = networkGetDriver(); - virNetworkObjPtr obj; virNetworkDefPtr netdef; virNetworkForwardIfDefPtr dev = NULL; - virNetworkPortDefPtr port = NULL; size_t i; int ret = -1; - obj = virNetworkObjFindByName(driver->networks, net->name); - if (!obj) { - virReportError(VIR_ERR_NO_NETWORK, - _("no network with matching name '%s'"), - net->name); - goto cleanup; - } - - if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Expected a interface for a virtual network")); - goto cleanup; - } - - if (iface->data.network.actual == NULL) { - ret = 0; - goto cleanup; - } - - if (!(port = virDomainNetDefActualToNetworkPort(dom, iface))) - goto cleanup; - netdef = virNetworkObjGetDef(obj); switch ((virNetworkPortPlugType)port->plugtype) { @@ -5192,7 +5167,7 @@ networkReleaseActualDevice(virNetworkPtr net, goto cleanup; } - virNetworkObjMacMgrDel(obj, driver->dnsmasqStateDir, dom->name, &iface->mac); + virNetworkObjMacMgrDel(obj, driver->dnsmasqStateDir, port->ownername, &port->mac); netdef->connections--; if (dev) @@ -5200,7 +5175,59 @@ networkReleaseActualDevice(virNetworkPtr net, /* finally we can call the 'unplugged' hook script if any */ networkRunHook(obj, port, VIR_HOOK_NETWORK_OP_PORT_DELETED, VIR_HOOK_SUBOP_BEGIN); - networkLogAllocation(netdef, dev, &iface->mac, false); + networkLogAllocation(netdef, dev, &port->mac, false); + + ret = 0; + cleanup: + return ret; +} + + +/* networkReleaseActualDevice: + * @dom: domain definition that @iface belongs to + * @iface: a domain's NetDef (interface definition) + * + * Given a domain <interface> element that previously had its <actual> + * element filled in (and possibly a physical device allocated to it), + * free up the physical device for use by someone else, and free the + * virDomainActualNetDef. + * + * Returns 0 on success, -1 on failure. + */ +static int +networkReleaseActualDevice(virNetworkPtr net, + virDomainDefPtr dom, + virDomainNetDefPtr iface) +{ + virNetworkDriverStatePtr driver = networkGetDriver(); + virNetworkObjPtr obj; + virNetworkPortDefPtr port = NULL; + int ret = -1; + + obj = virNetworkObjFindByName(driver->networks, net->name); + if (!obj) { + virReportError(VIR_ERR_NO_NETWORK, + _("no network with matching name '%s'"), + net->name); + goto cleanup; + } + + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Expected a interface for a virtual network")); + goto cleanup; + } + + if (iface->data.network.actual == NULL) { + ret = 0; + goto cleanup; + } + + if (!(port = virDomainNetDefActualToNetworkPort(dom, iface))) + goto cleanup; + + if (networkReleasePort(obj, port) < 0) + goto cleanup; ret = 0; cleanup: -- 2.19.2

Introduce a new virNetworPort object that will present an attachment to a virtual network from a VM. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- include/libvirt/libvirt-network.h | 49 +++++ include/libvirt/virterror.h | 3 + src/datatypes.c | 60 +++++ src/datatypes.h | 41 ++++ src/driver-network.h | 27 +++ src/libvirt-network.c | 351 ++++++++++++++++++++++++++++++ src/libvirt_private.syms | 2 + src/libvirt_public.syms | 14 ++ src/util/virerror.c | 9 + 9 files changed, 556 insertions(+) diff --git a/include/libvirt/libvirt-network.h b/include/libvirt/libvirt-network.h index 5115251fbe..08b91e6021 100644 --- a/include/libvirt/libvirt-network.h +++ b/include/libvirt/libvirt-network.h @@ -46,6 +46,22 @@ typedef struct _virNetwork virNetwork; */ typedef virNetwork *virNetworkPtr; +/** + * virNetworkPort: + * + * a virNetworkPort is a private structure representing a virtual network + * port + */ +typedef struct _virNetworkPort virNetworkPort; + +/** + * virNetworkPortPtr: + * + * a virNetworkPortPtr is pointer to a virNetworkPort private structure, + * this is the type used to reference a virtual network port in the API. + */ +typedef virNetworkPort *virNetworkPortPtr; + /* * Get connection from network. */ @@ -333,4 +349,37 @@ int virConnectNetworkEventRegisterAny(virConnectPtr conn, int virConnectNetworkEventDeregisterAny(virConnectPtr conn, int callbackID); +virNetworkPortPtr virNetworkPortLookupByUUID(virNetworkPtr net, + const unsigned char *uuid); + +virNetworkPortPtr virNetworkPortLookupByUUIDString(virNetworkPtr net, + const char *uuidstr); + +typedef enum { + VIR_NETWORK_PORT_CREATE_RECLAIM = (1 << 0), /* reclaim existing used resources */ +} virNetworkPortCreateFlags; + +virNetworkPortPtr virNetworkPortCreateXML(virNetworkPtr net, + const char *xmldesc, + unsigned int flags); + +virNetworkPtr virNetworkPortGetNetwork(virNetworkPortPtr port); + +char *virNetworkPortGetXMLDesc(virNetworkPortPtr port, + unsigned int flags); + +int virNetworkPortGetUUID(virNetworkPortPtr port, + unsigned char *uuid); +int virNetworkPortGetUUIDString(virNetworkPortPtr port, + char *buf); + +int virNetworkPortDelete(virNetworkPortPtr port, + unsigned int flags); + +int virNetworkListAllPorts(virNetworkPtr network, + virNetworkPortPtr **ports, + unsigned int flags); + +int virNetworkPortFree(virNetworkPortPtr port); + #endif /* LIBVIRT_NETWORK_H */ diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index fbbe2d5624..3db8067391 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -321,6 +321,9 @@ typedef enum { VIR_ERR_DEVICE_MISSING = 99, /* fail to find the desired device */ VIR_ERR_INVALID_NWFILTER_BINDING = 100, /* invalid nwfilter binding */ VIR_ERR_NO_NWFILTER_BINDING = 101, /* no nwfilter binding */ + VIR_ERR_INVALID_NETWORK_PORT = 102, /* invalid network port object */ + VIR_ERR_NETWORK_PORT_EXIST = 103, /* the network port already exist */ + VIR_ERR_NO_NETWORK_PORT = 104, /* network port not found */ # ifdef VIR_ENUM_SENTINELS VIR_ERR_NUMBER_LAST diff --git a/src/datatypes.c b/src/datatypes.c index caf035f178..30c98d62a5 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -39,6 +39,7 @@ virClassPtr virDomainClass; virClassPtr virDomainSnapshotClass; virClassPtr virInterfaceClass; virClassPtr virNetworkClass; +virClassPtr virNetworkPortClass; virClassPtr virNodeDeviceClass; virClassPtr virNWFilterClass; virClassPtr virNWFilterBindingClass; @@ -53,6 +54,7 @@ static void virDomainDispose(void *obj); static void virDomainSnapshotDispose(void *obj); static void virInterfaceDispose(void *obj); static void virNetworkDispose(void *obj); +static void virNetworkPortDispose(void *obj); static void virNodeDeviceDispose(void *obj); static void virNWFilterDispose(void *obj); static void virNWFilterBindingDispose(void *obj); @@ -89,6 +91,7 @@ virDataTypesOnceInit(void) DECLARE_CLASS(virDomainSnapshot); DECLARE_CLASS(virInterface); DECLARE_CLASS(virNetwork); + DECLARE_CLASS(virNetworkPort); DECLARE_CLASS(virNodeDevice); DECLARE_CLASS(virNWFilter); DECLARE_CLASS(virNWFilterBinding); @@ -385,6 +388,63 @@ virNetworkDispose(void *obj) } +/** + * virGetNetworkPort: + * @net: the network object + * @uuid: pointer to the uuid + * + * Allocates a new network port object. When the object is no longer needed, + * virObjectUnref() must be called in order to not leak data. + * + * Returns a pointer to the network port object, or NULL on error. + */ +virNetworkPortPtr +virGetNetworkPort(virNetworkPtr net, const unsigned char *uuid) +{ + virNetworkPortPtr ret = NULL; + + if (virDataTypesInitialize() < 0) + return NULL; + + virCheckNetworkGoto(net, error); + virCheckNonNullArgGoto(uuid, error); + + if (!(ret = virObjectNew(virNetworkPortClass))) + goto error; + + ret->net = virObjectRef(net); + memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN); + + return ret; + + error: + virObjectUnref(ret); + return NULL; +} + +/** + * virNetworkPortDispose: + * @obj: the network port to release + * + * Unconditionally release all memory associated with a network port. + * The network port object must not be used once this method returns. + * + * It will also unreference the associated network object, + * which may also be released if its ref count hits zero. + */ +static void +virNetworkPortDispose(void *obj) +{ + virNetworkPortPtr port = obj; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + virUUIDFormat(port->uuid, uuidstr); + VIR_DEBUG("release network port %p %s", port, uuidstr); + + virObjectUnref(port->net); +} + + /** * virGetInterface: * @conn: the hypervisor connection diff --git a/src/datatypes.h b/src/datatypes.h index 529b340587..94e814e7a3 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -34,6 +34,7 @@ extern virClassPtr virDomainClass; extern virClassPtr virDomainSnapshotClass; extern virClassPtr virInterfaceClass; extern virClassPtr virNetworkClass; +extern virClassPtr virNetworkPortClass; extern virClassPtr virNodeDeviceClass; extern virClassPtr virNWFilterClass; extern virClassPtr virNWFilterBindingClass; @@ -116,6 +117,33 @@ extern virClassPtr virAdmClientClass; } \ } while (0) +# define virCheckNetworkPortReturn(obj, retval) \ + do { \ + virNetworkPortPtr _port = (obj); \ + if (!virObjectIsClass(_port, virNetworkPortClass) || \ + !virObjectIsClass(_port->net, virNetworkClass)) { \ + virReportErrorHelper(VIR_FROM_NETWORK, \ + VIR_ERR_INVALID_NETWORK_PORT, \ + __FILE__, __FUNCTION__, __LINE__, \ + __FUNCTION__); \ + virDispatchError(NULL); \ + return retval; \ + } \ + } while (0) + +# define virCheckNetworkPortGoto(obj, label) \ + do { \ + virNetworkPortPtr _port = (obj); \ + if (!virObjectIsClass(_port, virNetworkPortClass) || \ + !virObjectIsClass(_port->net, virNetworkClass)) { \ + virReportErrorHelper(VIR_FROM_NETWORK, \ + VIR_ERR_INVALID_NETWORK_PORT, \ + __FILE__, __FUNCTION__, __LINE__, \ + __FUNCTION__); \ + goto label; \ + } \ + } while (0) + # define virCheckInterfaceReturn(obj, retval) \ do { \ virInterfacePtr _iface = (obj); \ @@ -573,6 +601,17 @@ struct _virNetwork { unsigned char uuid[VIR_UUID_BUFLEN]; /* the network unique identifier */ }; +/** +* _virNetworkPort: +* +* Internal structure associated to a network port +*/ +struct _virNetworkPort { + virObject parent; + virNetworkPtr net; /* pointer back to the connection */ + unsigned char uuid[VIR_UUID_BUFLEN]; /* the network unique identifier */ +}; + /** * _virInterface: * @@ -716,6 +755,8 @@ virDomainPtr virGetDomain(virConnectPtr conn, virNetworkPtr virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid); +virNetworkPortPtr virGetNetworkPort(virNetworkPtr net, + const unsigned char *uuid); virInterfacePtr virGetInterface(virConnectPtr conn, const char *name, const char *mac); diff --git a/src/driver-network.h b/src/driver-network.h index 2715c7bfec..11c2e0df15 100644 --- a/src/driver-network.h +++ b/src/driver-network.h @@ -118,6 +118,28 @@ typedef int virNetworkDHCPLeasePtr **leases, unsigned int flags); +typedef virNetworkPortPtr +(*virDrvNetworkPortLookupByUUID)(virNetworkPtr net, + const unsigned char *uuid); + +typedef virNetworkPortPtr +(*virDrvNetworkPortCreateXML)(virNetworkPtr net, + const char *xmldesc, + unsigned int flags); + +typedef char * +(*virDrvNetworkPortGetXMLDesc)(virNetworkPortPtr port, + unsigned int flags); + +typedef int +(*virDrvNetworkPortDelete)(virNetworkPortPtr port, + unsigned int flags); + +typedef int +(*virDrvNetworkListAllPorts)(virNetworkPtr network, + virNetworkPortPtr **ports, + unsigned int flags); + typedef struct _virNetworkDriver virNetworkDriver; typedef virNetworkDriver *virNetworkDriverPtr; @@ -151,6 +173,11 @@ struct _virNetworkDriver { virDrvNetworkIsActive networkIsActive; virDrvNetworkIsPersistent networkIsPersistent; virDrvNetworkGetDHCPLeases networkGetDHCPLeases; + virDrvNetworkPortLookupByUUID networkPortLookupByUUID; + virDrvNetworkPortCreateXML networkPortCreateXML; + virDrvNetworkPortGetXMLDesc networkPortGetXMLDesc; + virDrvNetworkPortDelete networkPortDelete; + virDrvNetworkListAllPorts networkListAllPorts; }; diff --git a/src/libvirt-network.c b/src/libvirt-network.c index 9f9e0ddaf8..a6546a68e9 100644 --- a/src/libvirt-network.c +++ b/src/libvirt-network.c @@ -1246,3 +1246,354 @@ virNetworkDHCPLeaseFree(virNetworkDHCPLeasePtr lease) VIR_FREE(lease->clientid); VIR_FREE(lease); } + + +/** + * virNetworkPortLookupByUUID: + * @net: pointer to the network object + * @uuid: the raw UUID for the network port + * + * Try to lookup a port on the given network based on its UUID. + * + * virNetworkPortFree should be used to free the resources after the + * network port object is no longer needed. + * + * Returns a new network port object or NULL in case of failure. If the + * network port cannot be found, then VIR_ERR_NO_NETWORK_PORT error is raised. + */ +virNetworkPortPtr +virNetworkPortLookupByUUID(virNetworkPtr net, + const unsigned char *uuid) +{ + VIR_UUID_DEBUG(net, uuid); + + virResetLastError(); + + virCheckNetworkReturn(net, NULL); + virCheckNonNullArgGoto(uuid, error); + + if (net->conn->networkDriver && net->conn->networkDriver->networkPortLookupByUUID) { + virNetworkPortPtr ret; + ret = net->conn->networkDriver->networkPortLookupByUUID(net, uuid); + if (!ret) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(net->conn); + return NULL; +} + + +/** + * virNetworkPortLookupByUUIDString: + * @net: pointer to the network object + * @uuidstr: the string UUID for the port + * + * Try to lookup a port on the given network based on its UUID. + * + * Returns a new network port object or NULL in case of failure. If the + * network port cannot be found, then VIR_ERR_NO_NETWORK_PORT error is raised. + */ +virNetworkPortPtr +virNetworkPortLookupByUUIDString(virNetworkPtr net, + const char *uuidstr) +{ + unsigned char uuid[VIR_UUID_BUFLEN]; + VIR_DEBUG("net=%p, uuidstr=%s", net, NULLSTR(uuidstr)); + + virResetLastError(); + + virCheckNetworkReturn(net, NULL); + virCheckNonNullArgGoto(uuidstr, error); + + if (virUUIDParse(uuidstr, uuid) < 0) { + virReportInvalidArg(uuidstr, + _("uuidstr in %s must be a valid UUID"), + __FUNCTION__); + goto error; + } + + return virNetworkPortLookupByUUID(net, &uuid[0]); + + error: + virDispatchError(net->conn); + return NULL; +} + +/** + * virNetworkPortCreateXML: + * @net: pointer to the network object + * @xmldesc: an XML description of the port + * @flags: currently unused, pass 0 + * + * Create a new network port, based on an XML description + * similar to the one returned by virNetworkPortGetXMLDesc() + * + * virNetworkPortFree should be used to free the resources after the + * network port object is no longer needed. + * + * Returns a new network port object or NULL in case of failure + */ +virNetworkPortPtr +virNetworkPortCreateXML(virNetworkPtr net, + const char *xmldesc, + unsigned int flags) +{ + VIR_DEBUG("net=%p, xmldesc=%s, flags=0x%x", net, NULLSTR(xmldesc), flags); + + virResetLastError(); + + virCheckNetworkReturn(net, NULL); + virCheckNonNullArgGoto(xmldesc, error); + virCheckReadOnlyGoto(net->conn->flags, error); + + if (net->conn->networkDriver && net->conn->networkDriver->networkPortCreateXML) { + virNetworkPortPtr ret; + ret = net->conn->networkDriver->networkPortCreateXML(net, xmldesc, flags); + if (!ret) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(net->conn); + return NULL; +} + +/** + * virNetworkPortGetNetwork: + * @port: pointer to a network port + * + * Provides the network pointer associated with a port. The + * reference counter on the connection is not increased by this + * call. + * + * Returns the virNetworkPtr or NULL in case of failure. + */ +virNetworkPtr +virNetworkPortGetNetwork(virNetworkPortPtr port) +{ + VIR_DEBUG("port=%p", port); + + virResetLastError(); + + virCheckNetworkPortReturn(port, NULL); + + return port->net; +} + + +/** + * virNetworkPortGetXMLDesc: + * @port: a network port object + * @flags: currently unused, pass 0 + * + * Provide an XML description of the network port. The description may be reused + * later to recreate the port with virNetworkPortCreateXML(). + * + * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error. + * the caller must free() the returned value. + */ +char * +virNetworkPortGetXMLDesc(virNetworkPortPtr port, + unsigned int flags) +{ + virConnectPtr conn; + VIR_DEBUG("port=%p, flags=0x%x", port, flags); + + virResetLastError(); + + virCheckNetworkPortReturn(port, NULL); + conn = port->net->conn; + + if (conn->networkDriver && conn->networkDriver->networkPortGetXMLDesc) { + char *ret; + ret = conn->networkDriver->networkPortGetXMLDesc(port, flags); + if (!ret) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(conn); + return NULL; +} + + +/** + * virNetworkPortGetUUID: + * @port: a network port object + * @uuid: pointer to a VIR_UUID_BUFLEN bytes array + * + * Get the UUID for a network port + * + * Returns -1 in case of error, 0 in case of success + */ +int +virNetworkPortGetUUID(virNetworkPortPtr port, + unsigned char *uuid) +{ + VIR_DEBUG("port=%p, uuid=%p", port, uuid); + + virResetLastError(); + + virCheckNetworkPortReturn(port, -1); + virCheckNonNullArgGoto(uuid, error); + + memcpy(uuid, &port->uuid[0], VIR_UUID_BUFLEN); + + return 0; + + error: + virDispatchError(port->net->conn); + return -1; +} + + +/** + * virNetworkPortGetUUIDString: + * @port: a network port object + * @buf: pointer to a VIR_UUID_STRING_BUFLEN bytes array + * + * Get the UUID for a network as string. For more information about + * UUID see RFC4122. + * + * Returns -1 in case of error, 0 in case of success + */ +int +virNetworkPortGetUUIDString(virNetworkPortPtr port, + char *buf) +{ + VIR_DEBUG("port=%p, buf=%p", port, buf); + + virResetLastError(); + + virCheckNetworkPortReturn(port, -1); + virCheckNonNullArgGoto(buf, error); + + virUUIDFormat(port->uuid, buf); + return 0; + + error: + virDispatchError(port->net->conn); + return -1; +} + +/** + * virNetworkPortDelete: + * @port: a port object + * @flags: currently unused, pass 0 + * + * Delete the network port. This does not free the + * associated virNetworkPortPtr object. It is the + * caller's responsibility to ensure the port is not + * still in use by a virtual machine before deleting + * port. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virNetworkPortDelete(virNetworkPortPtr port, + unsigned int flags) +{ + virConnectPtr conn; + VIR_DEBUG("port=%p, flags=0x%x", port, flags); + + virResetLastError(); + + virCheckNetworkPortReturn(port, -1); + conn = port->net->conn; + + virCheckReadOnlyGoto(conn->flags, error); + + if (conn->networkDriver && conn->networkDriver->networkPortDelete) { + int ret; + ret = conn->networkDriver->networkPortDelete(port, flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(conn); + return -1; +} + + +/** + * virNetworkListAllPorts: + * @network: pointer to a network object + * @ports: Pointer to a variable to store the array containing network port + * objects or NULL if the list is not required (just returns number + * of ports). + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * Collect the list of network ports, and allocate an array to store those + * objects. + * + * Returns the number of network ports found or -1 and sets @ports to + * NULL in case of error. On success, the array stored into @ports is + * guaranteed to have an extra allocated element set to NULL but not included + * in the return count, to make iteration easier. The caller is responsible + * for calling virNetworkPortFree() on each array element, then calling + * free() on @ports. + */ +int +virNetworkListAllPorts(virNetworkPtr network, + virNetworkPortPtr **ports, + unsigned int flags) +{ + VIR_DEBUG("network=%p, ports=%p, flags=0x%x", network, ports, flags); + + virResetLastError(); + + virCheckNetworkReturn(network, -1); + + if (network->conn->networkDriver && + network->conn->networkDriver->networkListAllPorts) { + int ret; + ret = network->conn->networkDriver->networkListAllPorts(network, ports, flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(network->conn); + return -1; +} + + +/** + * virNetworkPortFree: + * @port: a network port object + * + * Free the network port object. + * The data structure is freed and should not be used thereafter. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virNetworkPortFree(virNetworkPortPtr port) +{ + VIR_DEBUG("port=%p", port); + + virResetLastError(); + + virCheckNetworkPortReturn(port, -1); + + virObjectUnref(port); + return 0; +} diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 92e0994612..5a7d19f6d7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1235,6 +1235,7 @@ virGetDomain; virGetDomainSnapshot; virGetInterface; virGetNetwork; +virGetNetworkPort; virGetNodeDevice; virGetNWFilter; virGetNWFilterBinding; @@ -1244,6 +1245,7 @@ virGetStorageVol; virGetStream; virInterfaceClass; virNetworkClass; +virNetworkPortClass; virNewConnectCloseCallbackData; virNodeDeviceClass; virNWFilterClass; diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 042b4df043..3a18277eb9 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -814,4 +814,18 @@ LIBVIRT_4.10.0 { virDomainSetIOThreadParams; } LIBVIRT_4.5.0; +LIBVIRT_5.0.0 { + global: + virNetworkListAllPorts; + virNetworkPortLookupByUUID; + virNetworkPortLookupByUUIDString; + virNetworkPortCreateXML; + virNetworkPortGetNetwork; + virNetworkPortGetXMLDesc; + virNetworkPortGetUUID; + virNetworkPortGetUUIDString; + virNetworkPortDelete; + virNetworkPortFree; +} LIBVIRT_4.10.0; + # .... define new API here using predicted next version number .... diff --git a/src/util/virerror.c b/src/util/virerror.c index 61b47d2be0..c195a72c74 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -1213,6 +1213,15 @@ const virErrorMsgTuple virErrorMsgStrings[VIR_ERR_NUMBER_LAST] = { [VIR_ERR_NO_NWFILTER_BINDING] = { N_("Network filter binding not found"), N_("Network filter binding not found: %s") }, + [VIR_ERR_INVALID_NETWORK_PORT] = { + N_("Invalid network port pointer"), + N_("Invalid network port pointer: %s") }, + [VIR_ERR_NETWORK_PORT_EXIST] = { + N_("this network port exists already"), + N_("network port %s exists already") }, + [VIR_ERR_NO_NETWORK_PORT] = { + N_("network port not found"), + N_("network port not found: %s") }, }; -- 2.19.2

On 12/24/18 3:59 PM, Daniel P. Berrangé wrote:
Introduce a new virNetworPort object that will present an attachment to a virtual network from a VM.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- include/libvirt/libvirt-network.h | 49 +++++ include/libvirt/virterror.h | 3 + src/datatypes.c | 60 +++++ src/datatypes.h | 41 ++++ src/driver-network.h | 27 +++ src/libvirt-network.c | 351 ++++++++++++++++++++++++++++++ src/libvirt_private.syms | 2 + src/libvirt_public.syms | 14 ++ src/util/virerror.c | 9 + 9 files changed, 556 insertions(+)
+/** + * virNetworkPortFree: + * @port: a network port object + * + * Free the network port object. + * The data structure is freed and should not be used thereafter. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virNetworkPortFree(virNetworkPortPtr port) +{ + VIR_DEBUG("port=%p", port); + + virResetLastError(); + + virCheckNetworkPortReturn(port, -1); + + virObjectUnref(port); + return 0;
Don't we want to make this accept NULL? I know we don't do it for some other public free functions, but that was a mistake we can't fix (in fact I think we could because one can argue that relying on virDomainFree() returning -1 is a broken code anyway). Michal

On Tue, Jan 08, 2019 at 05:16:32PM +0100, Michal Privoznik wrote:
On 12/24/18 3:59 PM, Daniel P. Berrangé wrote:
Introduce a new virNetworPort object that will present an attachment to a virtual network from a VM.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- include/libvirt/libvirt-network.h | 49 +++++ include/libvirt/virterror.h | 3 + src/datatypes.c | 60 +++++ src/datatypes.h | 41 ++++ src/driver-network.h | 27 +++ src/libvirt-network.c | 351 ++++++++++++++++++++++++++++++ src/libvirt_private.syms | 2 + src/libvirt_public.syms | 14 ++ src/util/virerror.c | 9 + 9 files changed, 556 insertions(+)
+/** + * virNetworkPortFree: + * @port: a network port object + * + * Free the network port object. + * The data structure is freed and should not be used thereafter. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virNetworkPortFree(virNetworkPortPtr port) +{ + VIR_DEBUG("port=%p", port); + + virResetLastError(); + + virCheckNetworkPortReturn(port, -1); + + virObjectUnref(port); + return 0;
Don't we want to make this accept NULL? I know we don't do it for some other public free functions, but that was a mistake we can't fix (in fact I think we could because one can argue that relying on virDomainFree() returning -1 is a broken code anyway).
AFAIK, all our other public API object free functions forbid NULL, so I'd rather keep consistency, rather than have this be an exception. The rejection of NULL as an error is done by the virCheckNetworkPortReturn method which does a virObjectIsClass call. This was always somewhat sketchy as really the only way that could fail is if you passed an invalid pointer to libvirt APIs. IOW at best it is accessing unrelated memory, at worst it could access freed memory. That said while these checks are never going to be 100% reliable, they have been useful in debugging problems related to the language bindings in particular. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/access/genpolkit.pl | 2 +- src/access/viraccessdriver.h | 6 +++++ src/access/viraccessdrivernop.c | 11 +++++++++ src/access/viraccessdriverpolkit.c | 26 ++++++++++++++++++++ src/access/viraccessdriverstack.c | 25 ++++++++++++++++++++ src/access/viraccessmanager.c | 16 +++++++++++++ src/access/viraccessmanager.h | 6 +++++ src/access/viraccessperm.c | 8 ++++++- src/access/viraccessperm.h | 38 ++++++++++++++++++++++++++++++ 9 files changed, 136 insertions(+), 2 deletions(-) diff --git a/src/access/genpolkit.pl b/src/access/genpolkit.pl index e074c90eb6..f8f20caf65 100755 --- a/src/access/genpolkit.pl +++ b/src/access/genpolkit.pl @@ -21,7 +21,7 @@ use strict; use warnings; my @objects = ( - "CONNECT", "DOMAIN", "INTERFACE", + "CONNECT", "DOMAIN", "INTERFACE", "NETWORK_PORT", "NETWORK","NODE_DEVICE", "NWFILTER_BINDING", "NWFILTER", "SECRET", "STORAGE_POOL", "STORAGE_VOL", ); diff --git a/src/access/viraccessdriver.h b/src/access/viraccessdriver.h index 2cc3950f60..590d86fdf0 100644 --- a/src/access/viraccessdriver.h +++ b/src/access/viraccessdriver.h @@ -39,6 +39,11 @@ typedef int (*virAccessDriverCheckNetworkDrv)(virAccessManagerPtr manager, const char *driverName, virNetworkDefPtr network, virAccessPermNetwork av); +typedef int (*virAccessDriverCheckNetworkPortDrv)(virAccessManagerPtr manager, + const char *driverName, + virNetworkDefPtr network, + virNetworkPortDefPtr port, + virAccessPermNetworkPort av); typedef int (*virAccessDriverCheckNodeDeviceDrv)(virAccessManagerPtr manager, const char *driverName, virNodeDeviceDefPtr nodedev, @@ -82,6 +87,7 @@ struct _virAccessDriver { virAccessDriverCheckDomainDrv checkDomain; virAccessDriverCheckInterfaceDrv checkInterface; virAccessDriverCheckNetworkDrv checkNetwork; + virAccessDriverCheckNetworkPortDrv checkNetworkPort; virAccessDriverCheckNodeDeviceDrv checkNodeDevice; virAccessDriverCheckNWFilterDrv checkNWFilter; virAccessDriverCheckNWFilterBindingDrv checkNWFilterBinding; diff --git a/src/access/viraccessdrivernop.c b/src/access/viraccessdrivernop.c index 98ef9206c5..5e9d9db759 100644 --- a/src/access/viraccessdrivernop.c +++ b/src/access/viraccessdrivernop.c @@ -57,6 +57,16 @@ virAccessDriverNopCheckNetwork(virAccessManagerPtr manager ATTRIBUTE_UNUSED, return 1; /* Allow */ } +static int +virAccessDriverNopCheckNetworkPort(virAccessManagerPtr manager ATTRIBUTE_UNUSED, + const char *driverName ATTRIBUTE_UNUSED, + virNetworkDefPtr network ATTRIBUTE_UNUSED, + virNetworkPortDefPtr port ATTRIBUTE_UNUSED, + virAccessPermNetworkPort perm ATTRIBUTE_UNUSED) +{ + return 1; /* Allow */ +} + static int virAccessDriverNopCheckNodeDevice(virAccessManagerPtr manager ATTRIBUTE_UNUSED, const char *driverName ATTRIBUTE_UNUSED, @@ -119,6 +129,7 @@ virAccessDriver accessDriverNop = { .checkDomain = virAccessDriverNopCheckDomain, .checkInterface = virAccessDriverNopCheckInterface, .checkNetwork = virAccessDriverNopCheckNetwork, + .checkNetworkPort = virAccessDriverNopCheckNetworkPort, .checkNodeDevice = virAccessDriverNopCheckNodeDevice, .checkNWFilter = virAccessDriverNopCheckNWFilter, .checkNWFilterBinding = virAccessDriverNopCheckNWFilterBinding, diff --git a/src/access/viraccessdriverpolkit.c b/src/access/viraccessdriverpolkit.c index 6954d74a15..b1473cd0a4 100644 --- a/src/access/viraccessdriverpolkit.c +++ b/src/access/viraccessdriverpolkit.c @@ -237,6 +237,31 @@ virAccessDriverPolkitCheckNetwork(virAccessManagerPtr manager, attrs); } +static int +virAccessDriverPolkitCheckNetworkPort(virAccessManagerPtr manager, + const char *driverName, + virNetworkDefPtr network, + virNetworkPortDefPtr port, + virAccessPermNetworkPort perm) +{ + char uuidstr1[VIR_UUID_STRING_BUFLEN]; + char uuidstr2[VIR_UUID_STRING_BUFLEN]; + const char *attrs[] = { + "connect_driver", driverName, + "network_name", network->name, + "network_uuid", uuidstr1, + "port_uuid", uuidstr2, + NULL, + }; + virUUIDFormat(network->uuid, uuidstr1); + virUUIDFormat(port->uuid, uuidstr2); + + return virAccessDriverPolkitCheck(manager, + "network-port", + virAccessPermNetworkPortTypeToString(perm), + attrs); +} + static int virAccessDriverPolkitCheckNodeDevice(virAccessManagerPtr manager, const char *driverName, @@ -427,6 +452,7 @@ virAccessDriver accessDriverPolkit = { .checkDomain = virAccessDriverPolkitCheckDomain, .checkInterface = virAccessDriverPolkitCheckInterface, .checkNetwork = virAccessDriverPolkitCheckNetwork, + .checkNetworkPort = virAccessDriverPolkitCheckNetworkPort, .checkNodeDevice = virAccessDriverPolkitCheckNodeDevice, .checkNWFilter = virAccessDriverPolkitCheckNWFilter, .checkNWFilterBinding = virAccessDriverPolkitCheckNWFilterBinding, diff --git a/src/access/viraccessdriverstack.c b/src/access/viraccessdriverstack.c index 0ffc6abaf3..238caef115 100644 --- a/src/access/viraccessdriverstack.c +++ b/src/access/viraccessdriverstack.c @@ -151,6 +151,30 @@ virAccessDriverStackCheckNetwork(virAccessManagerPtr manager, return ret; } +static int +virAccessDriverStackCheckNetworkPort(virAccessManagerPtr manager, + const char *driverName, + virNetworkDefPtr network, + virNetworkPortDefPtr port, + virAccessPermNetworkPort perm) +{ + virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager); + int ret = 1; + size_t i; + + for (i = 0; i < priv->managersLen; i++) { + int rv; + /* We do not short-circuit on first denial - always check all drivers */ + rv = virAccessManagerCheckNetworkPort(priv->managers[i], driverName, network, port, perm); + if (rv == 0 && ret != -1) + ret = 0; + else if (rv < 0) + ret = -1; + } + + return ret; +} + static int virAccessDriverStackCheckNodeDevice(virAccessManagerPtr manager, const char *driverName, @@ -298,6 +322,7 @@ virAccessDriver accessDriverStack = { .checkDomain = virAccessDriverStackCheckDomain, .checkInterface = virAccessDriverStackCheckInterface, .checkNetwork = virAccessDriverStackCheckNetwork, + .checkNetworkPort = virAccessDriverStackCheckNetworkPort, .checkNodeDevice = virAccessDriverStackCheckNodeDevice, .checkNWFilter = virAccessDriverStackCheckNWFilter, .checkNWFilterBinding = virAccessDriverStackCheckNWFilterBinding, diff --git a/src/access/viraccessmanager.c b/src/access/viraccessmanager.c index f5d62604cf..24d9713cfd 100644 --- a/src/access/viraccessmanager.c +++ b/src/access/viraccessmanager.c @@ -268,6 +268,22 @@ int virAccessManagerCheckNetwork(virAccessManagerPtr manager, return virAccessManagerSanitizeError(ret, driverName); } +int virAccessManagerCheckNetworkPort(virAccessManagerPtr manager, + const char *driverName, + virNetworkDefPtr network, + virNetworkPortDefPtr port, + virAccessPermNetworkPort perm) +{ + int ret = 0; + VIR_DEBUG("manager=%p(name=%s) driver=%s network=%p port=%p perm=%d", + manager, manager->drv->name, driverName, network, port, perm); + + if (manager->drv->checkNetworkPort) + ret = manager->drv->checkNetworkPort(manager, driverName, network, port, perm); + + return virAccessManagerSanitizeError(ret, driverName); +} + int virAccessManagerCheckNodeDevice(virAccessManagerPtr manager, const char *driverName, virNodeDeviceDefPtr nodedev, diff --git a/src/access/viraccessmanager.h b/src/access/viraccessmanager.h index ab5ef87585..bedd6ba475 100644 --- a/src/access/viraccessmanager.h +++ b/src/access/viraccessmanager.h @@ -30,6 +30,7 @@ # include "conf/secret_conf.h" # include "conf/interface_conf.h" # include "conf/virnwfilterbindingdef.h" +# include "conf/virnetworkportdef.h" # include "access/viraccessperm.h" typedef struct _virAccessManager virAccessManager; @@ -66,6 +67,11 @@ int virAccessManagerCheckNetwork(virAccessManagerPtr manager, const char *driverName, virNetworkDefPtr network, virAccessPermNetwork perm); +int virAccessManagerCheckNetworkPort(virAccessManagerPtr manager, + const char *driverName, + virNetworkDefPtr network, + virNetworkPortDefPtr port, + virAccessPermNetworkPort perm); int virAccessManagerCheckNodeDevice(virAccessManagerPtr manager, const char *driverName, virNodeDeviceDefPtr nodedev, diff --git a/src/access/viraccessperm.c b/src/access/viraccessperm.c index d7cbb70b7b..929698a232 100644 --- a/src/access/viraccessperm.c +++ b/src/access/viraccessperm.c @@ -53,7 +53,13 @@ VIR_ENUM_IMPL(virAccessPermInterface, VIR_ENUM_IMPL(virAccessPermNetwork, VIR_ACCESS_PERM_NETWORK_LAST, "getattr", "read", "write", - "save", "delete", "start", "stop"); + "save", "delete", "start", "stop", + "search_ports"); + +VIR_ENUM_IMPL(virAccessPermNetworkPort, + VIR_ACCESS_PERM_NETWORK_PORT_LAST, + "getattr", "read", "create", + "delete"); VIR_ENUM_IMPL(virAccessPermNodeDevice, VIR_ACCESS_PERM_NODE_DEVICE_LAST, diff --git a/src/access/viraccessperm.h b/src/access/viraccessperm.h index ce3865b359..281b920f9c 100644 --- a/src/access/viraccessperm.h +++ b/src/access/viraccessperm.h @@ -404,6 +404,12 @@ typedef enum { */ VIR_ACCESS_PERM_NETWORK_START, + /** + * @desc: List network ports + * @message: Listing network ports requires authorization + */ + VIR_ACCESS_PERM_NETWORK_SEARCH_PORTS, + /** * @desc: Stop network * @message: Stopping network requires authorization @@ -413,6 +419,37 @@ typedef enum { VIR_ACCESS_PERM_NETWORK_LAST } virAccessPermNetwork; +typedef enum { + + /** + * @desc: Access network port + * @message: Accessing network port requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_NETWORK_PORT_GETATTR, + + /** + * @desc: Read network port + * @message: Reading network port configuration requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_NETWORK_PORT_READ, + + /** + * @desc: Create network port + * @message: Creating network port configuration requires authorization + */ + VIR_ACCESS_PERM_NETWORK_PORT_CREATE, + + /** + * @desc: Delete network port + * @message: Deleting network port configuration requires authorization + */ + VIR_ACCESS_PERM_NETWORK_PORT_DELETE, + + VIR_ACCESS_PERM_NETWORK_PORT_LAST +} virAccessPermNetworkPort; + typedef enum { /** @@ -692,6 +729,7 @@ VIR_ENUM_DECL(virAccessPermConnect); VIR_ENUM_DECL(virAccessPermDomain); VIR_ENUM_DECL(virAccessPermInterface); VIR_ENUM_DECL(virAccessPermNetwork); +VIR_ENUM_DECL(virAccessPermNetworkPort); VIR_ENUM_DECL(virAccessPermNodeDevice); VIR_ENUM_DECL(virAccessPermNWFilter); VIR_ENUM_DECL(virAccessPermNWFilterBinding); -- 2.19.2

Define the wire protocol for the virNetworkPort APIs and enable the client/server RPC dispatch. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/remote/remote_daemon_dispatch.c | 25 ++++++++ src/remote/remote_driver.c | 28 +++++++++ src/remote/remote_protocol.x | 89 ++++++++++++++++++++++++++++- src/remote_protocol-structs | 47 +++++++++++++++ src/rpc/gendispatch.pl | 18 ++++-- 5 files changed, 200 insertions(+), 7 deletions(-) diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c index fcd602304f..2620699600 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -83,6 +83,7 @@ struct daemonClientEventCallback { static virDomainPtr get_nonnull_domain(virConnectPtr conn, remote_nonnull_domain domain); static virNetworkPtr get_nonnull_network(virConnectPtr conn, remote_nonnull_network network); +static virNetworkPortPtr get_nonnull_network_port(virConnectPtr conn, remote_nonnull_network_port port); static virInterfacePtr get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface); static virStoragePoolPtr get_nonnull_storage_pool(virConnectPtr conn, remote_nonnull_storage_pool pool); static virStorageVolPtr get_nonnull_storage_vol(virConnectPtr conn, remote_nonnull_storage_vol vol); @@ -93,6 +94,7 @@ static virDomainSnapshotPtr get_nonnull_domain_snapshot(virDomainPtr dom, remote static virNodeDevicePtr get_nonnull_node_device(virConnectPtr conn, remote_nonnull_node_device dev); static int make_nonnull_domain(remote_nonnull_domain *dom_dst, virDomainPtr dom_src) ATTRIBUTE_RETURN_CHECK; static int make_nonnull_network(remote_nonnull_network *net_dst, virNetworkPtr net_src) ATTRIBUTE_RETURN_CHECK; +static int make_nonnull_network_port(remote_nonnull_network_port *port_dst, virNetworkPortPtr port_src) ATTRIBUTE_RETURN_CHECK; static int make_nonnull_interface(remote_nonnull_interface *interface_dst, virInterfacePtr interface_src) ATTRIBUTE_RETURN_CHECK; static int make_nonnull_storage_pool(remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src) ATTRIBUTE_RETURN_CHECK; static int make_nonnull_storage_vol(remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src) ATTRIBUTE_RETURN_CHECK; @@ -7202,6 +7204,19 @@ get_nonnull_network(virConnectPtr conn, remote_nonnull_network network) return virGetNetwork(conn, network.name, BAD_CAST network.uuid); } +static virNetworkPortPtr +get_nonnull_network_port(virConnectPtr conn, remote_nonnull_network_port port) +{ + virNetworkPortPtr ret; + virNetworkPtr net; + net = virGetNetwork(conn, port.net.name, BAD_CAST port.net.uuid); + if (!net) + return NULL; + ret = virGetNetworkPort(net, BAD_CAST port.uuid); + virObjectUnref(net); + return ret; +} + static virInterfacePtr get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface) { @@ -7274,6 +7289,16 @@ make_nonnull_network(remote_nonnull_network *net_dst, virNetworkPtr net_src) return 0; } +static int +make_nonnull_network_port(remote_nonnull_network_port *port_dst, virNetworkPortPtr port_src) +{ + if (VIR_STRDUP(port_dst->net.name, port_src->net->name) < 0) + return -1; + memcpy(port_dst->net.uuid, port_src->net->uuid, VIR_UUID_BUFLEN); + memcpy(port_dst->uuid, port_src->uuid, VIR_UUID_BUFLEN); + return 0; +} + static int make_nonnull_interface(remote_nonnull_interface *interface_dst, virInterfacePtr interface_src) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 058e4c926b..d2e8ce2473 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -138,6 +138,7 @@ static int remoteAuthPolkit(virConnectPtr conn, struct private_data *priv, static virDomainPtr get_nonnull_domain(virConnectPtr conn, remote_nonnull_domain domain); static virNetworkPtr get_nonnull_network(virConnectPtr conn, remote_nonnull_network network); +static virNetworkPortPtr get_nonnull_network_port(virConnectPtr conn, remote_nonnull_network_port port); static virNWFilterPtr get_nonnull_nwfilter(virConnectPtr conn, remote_nonnull_nwfilter nwfilter); static virNWFilterBindingPtr get_nonnull_nwfilter_binding(virConnectPtr conn, remote_nonnull_nwfilter_binding binding); static virInterfacePtr get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface); @@ -148,6 +149,7 @@ static virSecretPtr get_nonnull_secret(virConnectPtr conn, remote_nonnull_secret static virDomainSnapshotPtr get_nonnull_domain_snapshot(virDomainPtr domain, remote_nonnull_domain_snapshot snapshot); static void make_nonnull_domain(remote_nonnull_domain *dom_dst, virDomainPtr dom_src); static void make_nonnull_network(remote_nonnull_network *net_dst, virNetworkPtr net_src); +static void make_nonnull_network_port(remote_nonnull_network_port *port_dst, virNetworkPortPtr port_src); static void make_nonnull_interface(remote_nonnull_interface *interface_dst, virInterfacePtr interface_src); static void make_nonnull_storage_pool(remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr vol_src); static void make_nonnull_storage_vol(remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src); @@ -8168,6 +8170,19 @@ get_nonnull_network(virConnectPtr conn, remote_nonnull_network network) return virGetNetwork(conn, network.name, BAD_CAST network.uuid); } +static virNetworkPortPtr +get_nonnull_network_port(virConnectPtr conn, remote_nonnull_network_port port) +{ + virNetworkPortPtr ret; + virNetworkPtr net; + net = virGetNetwork(conn, port.net.name, BAD_CAST port.net.uuid); + if (!net) + return NULL; + ret = virGetNetworkPort(net, BAD_CAST port.uuid); + virObjectUnref(net); + return ret; +} + static virInterfacePtr get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface) { @@ -8235,6 +8250,14 @@ make_nonnull_network(remote_nonnull_network *net_dst, virNetworkPtr net_src) memcpy(net_dst->uuid, net_src->uuid, VIR_UUID_BUFLEN); } +static void +make_nonnull_network_port(remote_nonnull_network_port *port_dst, virNetworkPortPtr port_src) +{ + port_dst->net.name = port_src->net->name; + memcpy(port_dst->net.uuid, port_src->net->uuid, VIR_UUID_BUFLEN); + memcpy(port_dst->uuid, port_src->uuid, VIR_UUID_BUFLEN); +} + static void make_nonnull_interface(remote_nonnull_interface *interface_dst, virInterfacePtr interface_src) @@ -8561,6 +8584,11 @@ static virNetworkDriver network_driver = { .networkIsActive = remoteNetworkIsActive, /* 0.7.3 */ .networkIsPersistent = remoteNetworkIsPersistent, /* 0.7.3 */ .networkGetDHCPLeases = remoteNetworkGetDHCPLeases, /* 1.2.6 */ + .networkListAllPorts = remoteNetworkListAllPorts, /* 5.0.0 */ + .networkPortLookupByUUID = remoteNetworkPortLookupByUUID, /* 5.0.0 */ + .networkPortCreateXML = remoteNetworkPortCreateXML, /* 5.0.0 */ + .networkPortGetXMLDesc = remoteNetworkPortGetXMLDesc, /* 5.0.0 */ + .networkPortDelete = remoteNetworkPortDelete, /* 5.0.0 */ }; static virInterfaceDriver interface_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index b9d26b1849..d9c3bfe5f1 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -74,6 +74,9 @@ const REMOTE_MIGRATE_COOKIE_MAX = 4194304; /* Upper limit on lists of networks. */ const REMOTE_NETWORK_LIST_MAX = 16384; +/* Upper limit on lists of network ports. */ +const REMOTE_NETWORK_PORT_LIST_MAX = 16384; + /* Upper limit on lists of interfaces. */ const REMOTE_INTERFACE_LIST_MAX = 16384; @@ -279,6 +282,11 @@ struct remote_nonnull_network { remote_uuid uuid; }; +struct remote_nonnull_network_port { + remote_nonnull_network net; + remote_uuid uuid; +}; + /* A network filter which may not be NULL. */ struct remote_nonnull_nwfilter { remote_nonnull_string name; @@ -331,6 +339,7 @@ struct remote_nonnull_domain_snapshot { /* A domain or network which may be NULL. */ typedef remote_nonnull_domain *remote_domain; typedef remote_nonnull_network *remote_network; +typedef remote_nonnull_network_port *remote_network_port; typedef remote_nonnull_nwfilter *remote_nwfilter; typedef remote_nonnull_nwfilter_binding *remote_nwfilter_binding; typedef remote_nonnull_storage_pool *remote_storage_pool; @@ -3565,6 +3574,51 @@ struct remote_connect_list_all_nwfilter_bindings_ret { /* insert@1 */ unsigned int ret; }; +struct remote_network_list_all_ports_args { + remote_nonnull_network network; + int need_results; + unsigned int flags; +}; + +struct remote_network_list_all_ports_ret { /* insert@1 */ + remote_nonnull_network_port ports<REMOTE_NETWORK_PORT_LIST_MAX>; + unsigned int ret; +}; + +struct remote_network_port_lookup_by_uuid_args { + remote_nonnull_network network; + remote_uuid uuid; +}; + +struct remote_network_port_lookup_by_uuid_ret { + remote_nonnull_network_port port; +}; + +struct remote_network_port_create_xml_args { + remote_nonnull_network network; + remote_nonnull_string xml; + unsigned int flags; +}; + +struct remote_network_port_create_xml_ret { + remote_nonnull_network_port port; +}; + +struct remote_network_port_get_xml_desc_args { + remote_nonnull_network_port port; + unsigned int flags; +}; + +struct remote_network_port_get_xml_desc_ret { + remote_nonnull_string xml; +}; + +struct remote_network_port_delete_args { + remote_nonnull_network_port port; + unsigned int flags; +}; + + /*----- Protocol. -----*/ /* Define the program number, protocol version and procedure numbers here. */ @@ -6328,6 +6382,39 @@ enum remote_procedure { * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ - REMOTE_PROC_DOMAIN_SET_IOTHREAD_PARAMS = 402 + REMOTE_PROC_DOMAIN_SET_IOTHREAD_PARAMS = 402, + + /** + * @generate: both + * @priority: high + * @acl: network:search_ports + * @aclfilter: network_port:getattr + */ + REMOTE_PROC_NETWORK_LIST_ALL_PORTS = 403, + + /** + * @generate: both + * @priority: high + * @acl: network_port:getattr + */ + REMOTE_PROC_NETWORK_PORT_LOOKUP_BY_UUID = 404, + + /** + * @generate: both + * @acl: network_port:create + */ + REMOTE_PROC_NETWORK_PORT_CREATE_XML = 405, + + /** + * @generate: both + * @acl: network_port:read + */ + REMOTE_PROC_NETWORK_PORT_GET_XML_DESC = 406, + + /** + * @generate: both + * @acl: network_port:delete + */ + REMOTE_PROC_NETWORK_PORT_DELETE = 407 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 7c27c63542..8f419e60f8 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -17,6 +17,10 @@ struct remote_nonnull_network { remote_nonnull_string name; remote_uuid uuid; }; +struct remote_nonnull_network_port { + remote_nonnull_network net; + remote_uuid uuid; +}; struct remote_nonnull_nwfilter { remote_nonnull_string name; remote_uuid uuid; @@ -2975,6 +2979,44 @@ struct remote_connect_list_all_nwfilter_bindings_ret { } bindings; u_int ret; }; +struct remote_network_list_all_ports_args { + remote_nonnull_network network; + int need_results; + u_int flags; +}; +struct remote_network_list_all_ports_ret { + struct { + u_int ports_len; + remote_nonnull_network_port * ports_val; + } ports; + u_int ret; +}; +struct remote_network_port_lookup_by_uuid_args { + remote_nonnull_network network; + remote_uuid uuid; +}; +struct remote_network_port_lookup_by_uuid_ret { + remote_nonnull_network_port port; +}; +struct remote_network_port_create_xml_args { + remote_nonnull_network network; + remote_nonnull_string xml; + u_int flags; +}; +struct remote_network_port_create_xml_ret { + remote_nonnull_network_port port; +}; +struct remote_network_port_get_xml_desc_args { + remote_nonnull_network_port port; + u_int flags; +}; +struct remote_network_port_get_xml_desc_ret { + remote_nonnull_string xml; +}; +struct remote_network_port_delete_args { + remote_nonnull_network_port port; + u_int flags; +}; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN = 1, REMOTE_PROC_CONNECT_CLOSE = 2, @@ -3378,4 +3420,9 @@ enum remote_procedure { REMOTE_PROC_NWFILTER_BINDING_DELETE = 400, REMOTE_PROC_CONNECT_LIST_ALL_NWFILTER_BINDINGS = 401, REMOTE_PROC_DOMAIN_SET_IOTHREAD_PARAMS = 402, + REMOTE_PROC_NETWORK_LIST_ALL_PORTS = 403, + REMOTE_PROC_NETWORK_PORT_LOOKUP_BY_UUID = 404, + REMOTE_PROC_NETWORK_PORT_CREATE_XML = 405, + REMOTE_PROC_NETWORK_PORT_GET_XML_DESC = 406, + REMOTE_PROC_NETWORK_PORT_DELETE = 407, }; diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl index ce4db5d7b7..6b950ee839 100755 --- a/src/rpc/gendispatch.pl +++ b/src/rpc/gendispatch.pl @@ -557,7 +557,7 @@ elsif ($mode eq "server") { if ($args_member =~ m/^remote_nonnull_string name;/ and $has_node_device) { # ignore the name arg for node devices next - } elsif ($args_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|secret|nwfilter|nwfilter_binding) (\S+);/) { + } elsif ($args_member =~ m/^remote_nonnull_(domain|network|network_port|storage_pool|storage_vol|interface|secret|nwfilter|nwfilter_binding) (\S+);/) { my $type_name = name_to_TypeName($1); push(@vars_list, "vir${type_name}Ptr $2 = NULL"); @@ -722,7 +722,7 @@ elsif ($mode eq "server") { if (!$modern_ret_as_list) { push(@ret_list, "ret->$3 = tmp.$3;"); } - } elsif ($ret_member =~ m/(?:admin|remote)_nonnull_(secret|nwfilter|nwfilter_binding|node_device|interface|network|storage_vol|storage_pool|domain_snapshot|domain|server|client) (\S+)<(\S+)>;/) { + } elsif ($ret_member =~ m/(?:admin|remote)_nonnull_(secret|nwfilter|nwfilter_binding|node_device|interface|network|network_port|storage_vol|storage_pool|domain_snapshot|domain|server|client) (\S+)<(\S+)>;/) { $modern_ret_struct_name = $1; $single_ret_list_error_msg_type = $1; $single_ret_list_name = $2; @@ -780,7 +780,7 @@ elsif ($mode eq "server") { $single_ret_var = $1; $single_ret_by_ref = 0; $single_ret_check = " == NULL"; - } elsif ($ret_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|node_device|secret|nwfilter|nwfilter_binding|domain_snapshot) (\S+);/) { + } elsif ($ret_member =~ m/^remote_nonnull_(domain|network|network_port|storage_pool|storage_vol|interface|node_device|secret|nwfilter|nwfilter_binding|domain_snapshot) (\S+);/) { my $type_name = name_to_TypeName($1); if ($call->{ProcName} eq "DomainCreateWithFlags") { @@ -1328,7 +1328,7 @@ elsif ($mode eq "client") { $priv_src = "dev->conn"; push(@args_list, "virNodeDevicePtr dev"); push(@setters_list, "args.name = dev->name;"); - } elsif ($args_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|secret|nwfilter|nwfilter_binding|domain_snapshot) (\S+);/) { + } elsif ($args_member =~ m/^remote_nonnull_(domain|network|network_port|storage_pool|storage_vol|interface|secret|nwfilter|nwfilter_binding|domain_snapshot) (\S+);/) { my $name = $1; my $arg_name = $2; my $type_name = name_to_TypeName($name); @@ -1336,6 +1336,8 @@ elsif ($mode eq "client") { if ($is_first_arg) { if ($name eq "domain_snapshot") { $priv_src = "$arg_name->domain->conn"; + } elsif ($name eq "network_port") { + $priv_src = "$arg_name->net->conn"; } else { $priv_src = "$arg_name->conn"; } @@ -1521,7 +1523,7 @@ elsif ($mode eq "client") { } push(@ret_list, "memcpy(result->$3, ret.$3, sizeof(result->$3));"); - } elsif ($ret_member =~ m/(?:admin|remote)_nonnull_(secret|nwfilter|nwfilter_binding|node_device|interface|network|storage_vol|storage_pool|domain_snapshot|domain|server|client) (\S+)<(\S+)>;/) { + } elsif ($ret_member =~ m/(?:admin|remote)_nonnull_(secret|nwfilter|nwfilter_binding|node_device|interface|network|network_port|storage_vol|storage_pool|domain_snapshot|domain|server|client) (\S+)<(\S+)>;/) { my $proc_name = name_to_TypeName($1); if ($structprefix eq "admin") { @@ -1574,7 +1576,7 @@ elsif ($mode eq "client") { push(@ret_list, "VIR_FREE(ret.$1);"); $single_ret_var = "char *rv = NULL"; $single_ret_type = "char *"; - } elsif ($ret_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|node_device|interface|secret|nwfilter|nwfilter_binding|domain_snapshot) (\S+);/) { + } elsif ($ret_member =~ m/^remote_nonnull_(domain|network|network_port|storage_pool|storage_vol|node_device|interface|secret|nwfilter|nwfilter_binding|domain_snapshot) (\S+);/) { my $name = $1; my $arg_name = $2; my $type_name = name_to_TypeName($name); @@ -2134,6 +2136,8 @@ elsif ($mode eq "client") { if ($object ne "Connect") { if ($object eq "StorageVol") { push @argdecls, "virStoragePoolDefPtr pool"; + } elsif ($object eq "NetworkPort") { + push @argdecls, "virNetworkDefPtr net"; } push @argdecls, "$objecttype $arg"; } @@ -2163,6 +2167,8 @@ elsif ($mode eq "client") { if ($object ne "Connect") { if ($object eq "StorageVol") { push @argvars, "pool"; + } elsif ($object eq "NetworkPort") { + push @argvars, "net"; } push @argvars, $arg; } -- 2.19.2

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- tools/virsh-completer.c | 51 +++++ tools/virsh-completer.h | 4 + tools/virsh-network.c | 399 +++++++++++++++++++++++++++++++++++++++- tools/virsh-network.h | 5 + 4 files changed, 458 insertions(+), 1 deletion(-) diff --git a/tools/virsh-completer.c b/tools/virsh-completer.c index cfbfeae328..e9ff09b696 100644 --- a/tools/virsh-completer.c +++ b/tools/virsh-completer.c @@ -22,6 +22,7 @@ #include "virsh-completer.h" #include "virsh-domain.h" +#include "virsh-network.h" #include "virsh.h" #include "virsh-pool.h" #include "virsh-nodedev.h" @@ -382,6 +383,56 @@ virshNetworkNameCompleter(vshControl *ctl, } +char ** +virshNetworkPortUUIDCompleter(vshControl *ctl, + const vshCmd *cmd ATTRIBUTE_UNUSED, + unsigned int flags) +{ + virshControlPtr priv = ctl->privData; + virNetworkPtr net = NULL; + virNetworkPortPtr *ports = NULL; + int nports = 0; + size_t i = 0; + char **ret = NULL; + + virCheckFlags(0, NULL); + + if (!priv->conn || virConnectIsAlive(priv->conn) <= 0) + return NULL; + + if (!(net = virshCommandOptNetwork(ctl, cmd, NULL))) + return false; + + if ((nports = virNetworkListAllPorts(net, &ports, flags)) < 0) + return NULL; + + if (VIR_ALLOC_N(ret, nports + 1) < 0) + goto error; + + for (i = 0; i < nports; i++) { + char uuid[VIR_UUID_STRING_BUFLEN]; + + if (virNetworkPortGetUUIDString(ports[i], uuid) < 0 || + VIR_STRDUP(ret[i], uuid) < 0) + goto error; + + virNetworkPortFree(ports[i]); + } + VIR_FREE(ports); + + return ret; + + error: + for (; i < nports; i++) + virNetworkPortFree(ports[i]); + VIR_FREE(ports); + for (i = 0; i < nports; i++) + VIR_FREE(ret[i]); + VIR_FREE(ret); + return NULL; +} + + char ** virshNodeDeviceNameCompleter(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED, diff --git a/tools/virsh-completer.h b/tools/virsh-completer.h index 4069d976b8..e9f999567d 100644 --- a/tools/virsh-completer.h +++ b/tools/virsh-completer.h @@ -58,6 +58,10 @@ char ** virshNetworkNameCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); +char ** virshNetworkPortUUIDCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); + char ** virshNodeDeviceNameCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); diff --git a/tools/virsh-network.c b/tools/virsh-network.c index 440b23d8a8..38e57efe74 100644 --- a/tools/virsh-network.c +++ b/tools/virsh-network.c @@ -1,7 +1,7 @@ /* * virsh-network.c: Commands to manage network * - * Copyright (C) 2005, 2007-2016 Red Hat, Inc. + * Copyright (C) 2005, 2007-2018 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -58,6 +58,16 @@ #define VIRSH_COMMON_OPT_NETWORK_OT_STRING_FULL(cflags) \ VIRSH_COMMON_OPT_NETWORK_OT_STRING(N_("network name or uuid"), cflags) +#define VIRSH_COMMON_OPT_NETWORK_PORT(cflags) \ + {.name = "port", \ + .type = VSH_OT_DATA, \ + .flags = VSH_OFLAG_REQ, \ + .help = N_("port UUID"), \ + .completer = virshNetworkPortUUIDCompleter, \ + .completer_flags = cflags, \ + } + + virNetworkPtr virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd, const char **name, unsigned int flags) @@ -96,6 +106,35 @@ virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd, return network; } + +virNetworkPortPtr +virshCommandOptNetworkPort(vshControl *ctl, const vshCmd *cmd, + virNetworkPtr net, + const char **name) +{ + virNetworkPortPtr port = NULL; + const char *n = NULL; + const char *optname = "port"; + + if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0) + return NULL; + + vshDebug(ctl, VSH_ERR_INFO, "%s: found option <%s>: %s\n", + cmd->def->name, optname, n); + + if (name) + *name = n; + + vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as network UUID\n", + cmd->def->name, optname); + port = virNetworkPortLookupByUUIDString(net, n); + + if (!port) + vshError(ctl, _("failed to get network port '%s'"), n); + + return port; +} + /* * "net-autostart" command */ @@ -1427,6 +1466,340 @@ cmdNetworkDHCPLeases(vshControl *ctl, const vshCmd *cmd) return ret; } +/* + * "net-port-create" command + */ +static const vshCmdInfo info_network_port_create[] = { + {.name = "help", + .data = N_("create a network port from an XML file") + }, + {.name = "desc", + .data = N_("Create a network port.") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_network_port_create[] = { + VIRSH_COMMON_OPT_NETWORK_FULL(0), + VIRSH_COMMON_OPT_FILE(N_("file containing an XML network port description")), + {.name = NULL} +}; + +static bool +cmdNetworkPortCreate(vshControl *ctl, const vshCmd *cmd) +{ + virNetworkPortPtr port = NULL; + const char *from = NULL; + bool ret = false; + char *buffer = NULL; + virNetworkPtr network = NULL; + + network = virshCommandOptNetwork(ctl, cmd, NULL); + if (network == NULL) + goto cleanup; + + if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) + goto cleanup; + + if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + goto cleanup; + + port = virNetworkPortCreateXML(network, buffer, 0); + + if (port != NULL) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virNetworkPortGetUUIDString(port, uuidstr); + vshPrintExtra(ctl, _("Network port %s created from %s\n"), + uuidstr, from); + } else { + vshError(ctl, _("Failed to create network from %s"), from); + goto cleanup; + } + + ret = true; + cleanup: + VIR_FREE(buffer); + if (port) + virNetworkPortFree(port); + if (network) + virNetworkFree(network); + return ret; +} + +/* + * "net-port-dumpxml" command + */ +static const vshCmdInfo info_network_port_dumpxml[] = { + {.name = "help", + .data = N_("network port information in XML") + }, + {.name = "desc", + .data = N_("Output the network port information as an XML dump to stdout.") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_network_port_dumpxml[] = { + VIRSH_COMMON_OPT_NETWORK_FULL(0), + VIRSH_COMMON_OPT_NETWORK_PORT(0), + {.name = NULL} +}; + +static bool +cmdNetworkPortDumpXML(vshControl *ctl, const vshCmd *cmd) +{ + virNetworkPtr network; + virNetworkPortPtr port = NULL; + bool ret = true; + char *dump; + unsigned int flags = 0; + + if (!(network = virshCommandOptNetwork(ctl, cmd, NULL))) + goto cleanup; + + if (!(port = virshCommandOptNetworkPort(ctl, cmd, network, NULL))) + goto cleanup; + + dump = virNetworkPortGetXMLDesc(port, flags); + + if (dump != NULL) { + vshPrint(ctl, "%s", dump); + VIR_FREE(dump); + } else { + ret = false; + } + + cleanup: + if (port) + virNetworkPortFree(port); + if (network) + virNetworkFree(network); + return ret; +} + + +/* + * "net-port-delete" command + */ +static const vshCmdInfo info_network_port_delete[] = { + {.name = "help", + .data = N_("network port information in XML") + }, + {.name = "desc", + .data = N_("Output the network port information as an XML dump to stdout.") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_network_port_delete[] = { + VIRSH_COMMON_OPT_NETWORK_FULL(0), + VIRSH_COMMON_OPT_NETWORK_PORT(0), + {.name = NULL} +}; + +static bool +cmdNetworkPortDelete(vshControl *ctl, const vshCmd *cmd) +{ + virNetworkPtr network = NULL; + virNetworkPortPtr port = NULL; + bool ret = true; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + if (!(network = virshCommandOptNetwork(ctl, cmd, NULL))) + goto cleanup; + + if (!(port = virshCommandOptNetworkPort(ctl, cmd, network, NULL))) + goto cleanup; + + if (virNetworkPortGetUUIDString(port, uuidstr) < 0) + goto cleanup; + + if (virNetworkPortDelete(port, 0) < 0) { + vshError(ctl, _("Failed to delete network port %s"), uuidstr); + goto cleanup; + } else { + vshPrintExtra(ctl, _("Network port %s deleted\n"), uuidstr); + } + + ret = true; + cleanup: + if (port) + virNetworkPortFree(port); + if (network) + virNetworkFree(network); + return ret; +} + + +static int +virshNetworkPortSorter(const void *a, const void *b) +{ + virNetworkPortPtr *na = (virNetworkPortPtr *) a; + virNetworkPortPtr *nb = (virNetworkPortPtr *) b; + unsigned char uuida[VIR_UUID_BUFLEN]; + unsigned char uuidb[VIR_UUID_BUFLEN]; + + if (*na && !*nb) + return -1; + + if (!*na) + return *nb != NULL; + + if (virNetworkPortGetUUID(*na, uuida) < 0 || + virNetworkPortGetUUID(*nb, uuidb) < 0) + return -1; + + return memcmp(uuida, uuidb, VIR_UUID_BUFLEN); +} + +struct virshNetworkPortList { + virNetworkPortPtr *ports; + size_t nports; +}; +typedef struct virshNetworkPortList *virshNetworkPortListPtr; + +static void +virshNetworkPortListFree(virshNetworkPortListPtr list) +{ + size_t i; + + if (list && list->ports) { + for (i = 0; i < list->nports; i++) { + if (list->ports[i]) + virNetworkPortFree(list->ports[i]); + } + VIR_FREE(list->ports); + } + VIR_FREE(list); +} + +static virshNetworkPortListPtr +virshNetworkPortListCollect(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags) +{ + virshNetworkPortListPtr list = vshMalloc(ctl, sizeof(*list)); + int ret; + virNetworkPtr network = NULL; + bool success = false; + + if (!(network = virshCommandOptNetwork(ctl, cmd, NULL))) + goto cleanup; + + /* try the list with flags support (0.10.2 and later) */ + if ((ret = virNetworkListAllPorts(network, + &list->ports, + flags)) < 0) + goto cleanup; + + list->nports = ret; + + /* sort the list */ + if (list->ports && list->nports) + qsort(list->ports, list->nports, + sizeof(*list->ports), virshNetworkPortSorter); + + success = true; + + cleanup: + if (!success) { + virshNetworkPortListFree(list); + list = NULL; + } + + if (network) + virNetworkFree(network); + + return list; +} + +/* + * "net-list" command + */ +static const vshCmdInfo info_network_port_list[] = { + {.name = "help", + .data = N_("list network ports") + }, + {.name = "desc", + .data = N_("Returns list of network ports.") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_network_port_list[] = { + VIRSH_COMMON_OPT_NETWORK_FULL(0), + {.name = "uuid", + .type = VSH_OT_BOOL, + .help = N_("list uuid's only") + }, + {.name = "table", + .type = VSH_OT_BOOL, + .help = N_("list table (default)") + }, + {.name = NULL} +}; + +#define FILTER(NAME, FLAG) \ + if (vshCommandOptBool(cmd, NAME)) \ + flags |= (FLAG) +static bool +cmdNetworkPortList(vshControl *ctl, const vshCmd *cmd) +{ + virshNetworkPortListPtr list = NULL; + size_t i; + bool ret = false; + bool optTable = vshCommandOptBool(cmd, "table"); + bool optUUID = vshCommandOptBool(cmd, "uuid"); + char uuid[VIR_UUID_STRING_BUFLEN]; + unsigned int flags = 0; + vshTablePtr table = NULL; + + if (optTable + optUUID > 1) { + vshError(ctl, "%s", + _("Only one argument from --table and --uuid " + "may be specified.")); + return false; + } + + if (!optUUID) + optTable = true; + + if (!(list = virshNetworkPortListCollect(ctl, cmd, flags))) + return false; + + if (optTable) { + table = vshTableNew(_("UUID"), NULL); + if (!table) + goto cleanup; + } + + for (i = 0; i < list->nports; i++) { + virNetworkPortPtr port = list->ports[i]; + + if (virNetworkPortGetUUIDString(port, uuid) < 0) { + vshError(ctl, "%s", _("Failed to get network's UUID")); + goto cleanup; + } + if (optTable) { + if (vshTableRowAppend(table, uuid, NULL) < 0) + goto cleanup; + } else if (optUUID) { + vshPrint(ctl, "%s\n", uuid); + } + } + + if (optTable) + vshTablePrintToStdout(table, ctl); + + ret = true; + cleanup: + vshTableFree(table); + virshNetworkPortListFree(list); + return ret; +} +#undef FILTER + + const vshCmdDef networkCmds[] = { {.name = "net-autostart", .handler = cmdNetworkAutostart, @@ -1518,5 +1891,29 @@ const vshCmdDef networkCmds[] = { .info = info_network_uuid, .flags = 0 }, + {.name = "net-port-list", + .handler = cmdNetworkPortList, + .opts = opts_network_port_list, + .info = info_network_port_list, + .flags = 0 + }, + {.name = "net-port-create", + .handler = cmdNetworkPortCreate, + .opts = opts_network_port_create, + .info = info_network_port_create, + .flags = 0 + }, + {.name = "net-port-dumpxml", + .handler = cmdNetworkPortDumpXML, + .opts = opts_network_port_dumpxml, + .info = info_network_port_dumpxml, + .flags = 0 + }, + {.name = "net-port-delete", + .handler = cmdNetworkPortDelete, + .opts = opts_network_port_delete, + .info = info_network_port_delete, + .flags = 0 + }, {.name = NULL} }; diff --git a/tools/virsh-network.h b/tools/virsh-network.h index 2aeb894484..b55dd38224 100644 --- a/tools/virsh-network.h +++ b/tools/virsh-network.h @@ -32,6 +32,11 @@ virNetworkPtr virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd, const char **name, unsigned int flags); +virNetworkPortPtr +virshCommandOptNetworkPort(vshControl *ctl, const vshCmd *cmd, + virNetworkPtr net, + const char **name); + /* default is lookup by Name and UUID */ # define virshCommandOptNetwork(_ctl, _cmd, _name) \ virshCommandOptNetworkBy(_ctl, _cmd, _name, \ -- 2.19.2

On 12/24/18 3:59 PM, Daniel P. Berrangé wrote:
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- tools/virsh-completer.c | 51 +++++ tools/virsh-completer.h | 4 + tools/virsh-network.c | 399 +++++++++++++++++++++++++++++++++++++++- tools/virsh-network.h | 5 + 4 files changed, 458 insertions(+), 1 deletion(-)
diff --git a/tools/virsh-completer.c b/tools/virsh-completer.c index cfbfeae328..e9ff09b696 100644 --- a/tools/virsh-completer.c +++ b/tools/virsh-completer.c @@ -22,6 +22,7 @@
#include "virsh-completer.h" #include "virsh-domain.h" +#include "virsh-network.h" #include "virsh.h" #include "virsh-pool.h" #include "virsh-nodedev.h" @@ -382,6 +383,56 @@ virshNetworkNameCompleter(vshControl *ctl, }
+char ** +virshNetworkPortUUIDCompleter(vshControl *ctl, + const vshCmd *cmd ATTRIBUTE_UNUSED, + unsigned int flags) +{ + virshControlPtr priv = ctl->privData; + virNetworkPtr net = NULL; + virNetworkPortPtr *ports = NULL; + int nports = 0; + size_t i = 0; + char **ret = NULL; + + virCheckFlags(0, NULL); + + if (!priv->conn || virConnectIsAlive(priv->conn) <= 0) + return NULL; + + if (!(net = virshCommandOptNetwork(ctl, cmd, NULL))) + return false;
s/false/NULL/
+ + if ((nports = virNetworkListAllPorts(net, &ports, flags)) < 0) + return NULL; + + if (VIR_ALLOC_N(ret, nports + 1) < 0) + goto error; + + for (i = 0; i < nports; i++) { + char uuid[VIR_UUID_STRING_BUFLEN]; + + if (virNetworkPortGetUUIDString(ports[i], uuid) < 0 || + VIR_STRDUP(ret[i], uuid) < 0) + goto error; + + virNetworkPortFree(ports[i]); + } + VIR_FREE(ports); + + return ret; + + error: + for (; i < nports; i++) + virNetworkPortFree(ports[i]); + VIR_FREE(ports); + for (i = 0; i < nports; i++) + VIR_FREE(ret[i]); + VIR_FREE(ret); + return NULL; +}
Kudos for implementing completer. Michal

The virNetworkObjPtr state will need to maintain a record of all virNetworkPortDefPtr objects associated with the network. Record these in a hash and add APIs for manipulating them. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/virnetworkobj.c | 303 +++++++++++++++++++++++++++++++++++++++ src/conf/virnetworkobj.h | 30 ++++ src/libvirt_private.syms | 5 + 3 files changed, 338 insertions(+) diff --git a/src/conf/virnetworkobj.c b/src/conf/virnetworkobj.c index e6b01388f5..935edcea57 100644 --- a/src/conf/virnetworkobj.c +++ b/src/conf/virnetworkobj.c @@ -58,6 +58,8 @@ struct _virNetworkObj { /* Immutable pointer, self locking APIs */ virMacMapPtr macmap; + + virHashTablePtr ports; /* uuid -> virNetworkPortDefPtr */ }; struct _virNetworkObjList { @@ -86,6 +88,17 @@ virNetworkObjOnceInit(void) VIR_ONCE_GLOBAL_INIT(virNetworkObj) +static int +virNetworkObjLoadAllPorts(virNetworkObjPtr net, + const char *stateDir); + + +static void +virNetworkObjPortFree(void *val, const void *key ATTRIBUTE_UNUSED) +{ + virNetworkPortDefFree(val); +} + virNetworkObjPtr virNetworkObjNew(void) { @@ -106,6 +119,10 @@ virNetworkObjNew(void) virBitmapSetBitExpand(obj->classIdMap, 2) < 0) goto error; + if (!(obj->ports = virHashCreate(10, + virNetworkObjPortFree))) + goto error; + virObjectLock(obj); return obj; @@ -458,6 +475,7 @@ virNetworkObjDispose(void *opaque) { virNetworkObjPtr obj = opaque; + virHashFree(obj->ports); virNetworkDefFree(obj->def); virNetworkDefFree(obj->newDef); virBitmapFree(obj->classIdMap); @@ -1073,9 +1091,16 @@ virNetworkObjLoadAllState(virNetworkObjListPtr nets, continue; obj = virNetworkLoadState(nets, stateDir, entry->d_name); + + if (obj && + virNetworkObjLoadAllPorts(obj, stateDir) < 0) { + virNetworkObjEndAPI(&obj); + goto cleanup; + } virNetworkObjEndAPI(&obj); } + cleanup: VIR_DIR_CLOSE(dir); return ret; } @@ -1585,3 +1610,281 @@ virNetworkObjListPrune(virNetworkObjListPtr nets, virHashRemoveSet(nets->objs, virNetworkObjListPruneHelper, &data); virObjectRWUnlock(nets); } + + +static char * +virNetworkObjGetPortStatusDir(virNetworkObjPtr net, + const char *stateDir) +{ + char *ret; + ignore_value(virAsprintf(&ret, "%s/%s/ports", stateDir, net->def->name)); + return ret; +} + +int +virNetworkObjAddPort(virNetworkObjPtr net, + virNetworkPortDefPtr portdef, + const char *stateDir) +{ + int ret = -1; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + char *dir = NULL; + + virUUIDFormat(portdef->uuid, uuidstr); + + if (virHashLookup(net->ports, uuidstr)) { + virReportError(VIR_ERR_NETWORK_PORT_EXIST, + _("Network port with UUID %s already exists"), + uuidstr); + goto cleanup; + } + + if (!(dir = virNetworkObjGetPortStatusDir(net, stateDir))) + goto cleanup; + + if (virHashAddEntry(net->ports, uuidstr, portdef) < 0) + goto cleanup; + + if (virNetworkPortDefSaveStatus(portdef, dir) < 0) { + virHashRemoveEntry(net->ports, uuidstr); + goto cleanup; + } + + ret = 0; + + cleanup: + return ret; +} + + +virNetworkPortDefPtr +virNetworkObjLookupPort(virNetworkObjPtr net, + const unsigned char *uuid) +{ + virNetworkPortDefPtr ret = NULL; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + virUUIDFormat(uuid, uuidstr); + + if (!(ret = virHashLookup(net->ports, uuidstr))) { + virReportError(VIR_ERR_NO_NETWORK_PORT, + _("Network port with UUID %s does not exist"), + uuidstr); + goto cleanup; + } + + cleanup: + return ret; +} + + +int +virNetworkObjDeletePort(virNetworkObjPtr net, + const unsigned char *uuid, + const char *stateDir) +{ + int ret = -1; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + char *dir = NULL; + virNetworkPortDefPtr portdef; + + virUUIDFormat(uuid, uuidstr); + + if (!(portdef = virHashLookup(net->ports, uuidstr))) { + virReportError(VIR_ERR_NO_NETWORK_PORT, + _("Network port with UUID %s does not exist"), + uuidstr); + goto cleanup; + } + + if (!(dir = virNetworkObjGetPortStatusDir(net, stateDir))) + goto cleanup; + + if (virNetworkPortDefDeleteStatus(portdef, dir) < 0) + goto cleanup; + + if (virHashRemoveEntry(net->ports, uuidstr) < 0) + goto cleanup; + + ret = 0; + + cleanup: + VIR_FREE(dir); + return ret; +} + + +int +virNetworkObjDeleteAllPorts(virNetworkObjPtr net, + const char *stateDir) +{ + char *dir; + DIR *dh; + struct dirent *de; + int rc; + int ret = -1; + + if (!(dir = virNetworkObjGetPortStatusDir(net, stateDir))) + goto cleanup; + + if ((rc = virDirOpenIfExists(&dh, dir)) <= 0) { + ret = rc; + goto cleanup; + } + + while ((rc = virDirRead(dh, &de, dir)) > 0) { + char *file = NULL; + + if (!virFileStripSuffix(de->d_name, ".xml")) + continue; + + if (virAsprintf(&file, "%s/%s.xml", dir, de->d_name) < 0) + goto cleanup; + + if (unlink(file) < 0 && errno != ENOENT) + VIR_WARN("Unable to delete %s", file); + + VIR_FREE(file); + } + + virHashRemoveAll(net->ports); + + ret = 0; + cleanup: + return ret; +} + + +typedef struct _virNetworkObjPortListExportData virNetworkObjPortListExportData; +typedef virNetworkObjPortListExportData *virNetworkObjPortListExportDataPtr; +struct _virNetworkObjPortListExportData { + virNetworkPtr net; + virNetworkDefPtr def; + virNetworkPortPtr *ports; + virNetworkPortListFilter filter; + int nports; + bool error; +}; + +static int +virNetworkObjPortListExportCallback(void *payload, + const void *name ATTRIBUTE_UNUSED, + void *opaque) +{ + virNetworkObjPortListExportDataPtr data = opaque; + virNetworkPortDefPtr def = payload; + virNetworkPortPtr port; + + if (data->error) + return 0; + + if (data->filter && + !data->filter(data->net->conn, data->def, def)) + goto cleanup; + + if (!data->ports) { + data->nports++; + goto cleanup; + } + + if (!(port = virGetNetworkPort(data->net, def->uuid))) { + data->error = true; + goto cleanup; + } + + data->ports[data->nports++] = port; + + cleanup: + return 0; +} + + +int +virNetworkObjPortListExport(virNetworkPtr net, + virNetworkObjPtr obj, + virNetworkPortPtr **ports, + virNetworkPortListFilter filter) +{ + virNetworkObjPortListExportData data = { + net, obj->def, NULL, filter, 0, false, + }; + int ret = -1; + + *ports = NULL; + + if (ports && VIR_ALLOC_N(data.ports, virHashSize(obj->ports) + 1) < 0) + goto cleanup; + + virHashForEach(obj->ports, virNetworkObjPortListExportCallback, &data); + + if (data.error) + goto cleanup; + + if (data.ports) { + /* trim the array to the final size */ + ignore_value(VIR_REALLOC_N(data.ports, data.nports + 1)); + *ports = data.ports; + data.ports = NULL; + } + + ret = data.nports; + cleanup: + while (data.ports && data.nports) + virObjectUnref(data.ports[--data.nports]); + + VIR_FREE(data.ports); + return ret; +} + + +static int +virNetworkObjLoadAllPorts(virNetworkObjPtr net, + const char *stateDir) +{ + char *dir; + DIR *dh = NULL; + struct dirent *de; + int ret = -1; + int rc; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virNetworkPortDefPtr portdef = NULL; + + if (!(dir = virNetworkObjGetPortStatusDir(net, stateDir))) + goto cleanup; + + if ((rc = virDirOpenIfExists(&dh, dir)) <= 0) { + ret = rc; + goto cleanup; + } + + while ((rc = virDirRead(dh, &de, dir)) > 0) { + char *file = NULL; + + if (!virFileStripSuffix(de->d_name, ".xml")) + continue; + + if (virAsprintf(&file, "%s/%s.xml", dir, de->d_name) < 0) + goto cleanup; + + portdef = virNetworkPortDefParseFile(file); + VIR_FREE(file); + file = NULL; + + if (!portdef) { + VIR_WARN("Cannot parse port %s", file); + continue; + } + + virUUIDFormat(portdef->uuid, uuidstr); + if (virHashAddEntry(net->ports, uuidstr, portdef) < 0) + goto cleanup; + + portdef = NULL; + } + + ret = 0; + cleanup: + VIR_DIR_CLOSE(dh); + virNetworkPortDefFree(portdef); + return ret; +} diff --git a/src/conf/virnetworkobj.h b/src/conf/virnetworkobj.h index 9c8f141cd9..6ee2550959 100644 --- a/src/conf/virnetworkobj.h +++ b/src/conf/virnetworkobj.h @@ -23,6 +23,7 @@ # include "internal.h" # include "network_conf.h" +# include "virnetworkportdef.h" typedef struct _virNetworkObj virNetworkObj; typedef virNetworkObj *virNetworkObjPtr; @@ -156,6 +157,35 @@ void virNetworkObjRemoveInactive(virNetworkObjListPtr nets, virNetworkObjPtr net); +int +virNetworkObjAddPort(virNetworkObjPtr net, + virNetworkPortDefPtr portdef, + const char *stateDir); + +virNetworkPortDefPtr +virNetworkObjLookupPort(virNetworkObjPtr net, + const unsigned char *uuid); + +int +virNetworkObjDeletePort(virNetworkObjPtr net, + const unsigned char *uuid, + const char *stateDir); + +int +virNetworkObjDeleteAllPorts(virNetworkObjPtr net, + const char *stateDir); + +typedef bool +(*virNetworkPortListFilter)(virConnectPtr conn, + virNetworkDefPtr def, + virNetworkPortDefPtr portdef); + +int +virNetworkObjPortListExport(virNetworkPtr net, + virNetworkObjPtr obj, + virNetworkPortPtr **ports, + virNetworkPortListFilter filter); + int virNetworkObjSaveStatus(const char *statusDir, virNetworkObjPtr net) ATTRIBUTE_RETURN_CHECK; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5a7d19f6d7..16ab01ca38 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -991,9 +991,12 @@ virInterfaceObjSetActive; # conf/virnetworkobj.h +virNetworkObjAddPort; virNetworkObjAssignDef; virNetworkObjBridgeInUse; +virNetworkObjDeleteAllPorts; virNetworkObjDeleteConfig; +virNetworkObjDeletePort; virNetworkObjEndAPI; virNetworkObjFindByName; virNetworkObjFindByUUID; @@ -1016,9 +1019,11 @@ virNetworkObjListNumOfNetworks; virNetworkObjListPrune; virNetworkObjLoadAllConfigs; virNetworkObjLoadAllState; +virNetworkObjLookupPort; virNetworkObjMacMgrAdd; virNetworkObjMacMgrDel; virNetworkObjNew; +virNetworkObjPortListExport; virNetworkObjRemoveInactive; virNetworkObjReplacePersistentDef; virNetworkObjSaveStatus; -- 2.19.2

This initial implementation just wires up the APIs and does tracking of the port XML definitions. It is not yet integrated into the resource allocation logic. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/network/bridge_driver.c | 233 ++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 37c49abde7..8401b72bc8 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2836,6 +2836,8 @@ networkStartNetwork(virNetworkDriverStatePtr driver, VIR_DEBUG("Beginning network startup process"); + virNetworkObjDeleteAllPorts(obj, driver->stateDir); + VIR_DEBUG("Setting current network def as transient"); if (virNetworkObjSetDefTransient(obj, true) < 0) goto cleanup; @@ -4009,6 +4011,9 @@ networkDestroy(virNetworkPtr net) if ((ret = networkShutdownNetwork(driver, obj)) < 0) goto cleanup; + + virNetworkObjDeleteAllPorts(obj, driver->stateDir); + /* @def replaced in virNetworkObjUnsetDefTransient*/ def = virNetworkObjGetDef(obj); @@ -5669,6 +5674,229 @@ networkBandwidthUpdate(virDomainNetDefPtr iface, } +static virNetworkPortPtr +networkPortLookupByUUID(virNetworkPtr net, + const unsigned char *uuid) +{ + virNetworkObjPtr obj; + virNetworkDefPtr def; + virNetworkPortDefPtr portdef = NULL; + virNetworkPortPtr ret = NULL; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(uuid, uuidstr); + + if (!(obj = networkObjFromNetwork(net))) + return ret; + + def = virNetworkObjGetDef(obj); + + if (!(portdef = virNetworkObjLookupPort(obj, uuid))) + goto cleanup; + + if (virNetworkPortLookupByUUIDEnsureACL(net->conn, def, portdef) < 0) + goto cleanup; + + if (!virNetworkObjIsActive(obj)) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("network '%s' is not active"), + def->name); + goto cleanup; + } + + ret = virGetNetworkPort(net, uuid); + + cleanup: + virNetworkObjEndAPI(&obj); + return ret; +} + + +static virNetworkPortPtr +networkPortCreateXML(virNetworkPtr net, + const char *xmldesc, + unsigned int flags) +{ + virNetworkDriverStatePtr driver = networkGetDriver(); + virNetworkObjPtr obj; + virNetworkDefPtr def; + virNetworkPortDefPtr portdef = NULL; + virNetworkPortPtr ret = NULL; + int rc; + + virCheckFlags(VIR_NETWORK_PORT_CREATE_RECLAIM, NULL); + + if (!(obj = networkObjFromNetwork(net))) + return ret; + + def = virNetworkObjGetDef(obj); + + if (!(portdef = virNetworkPortDefParseString(xmldesc))) + goto cleanup; + + if (virNetworkPortCreateXMLEnsureACL(net->conn, def, portdef) < 0) + goto cleanup; + + if (!virNetworkObjIsActive(obj)) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("network '%s' is not active"), + def->name); + goto cleanup; + } + + if (portdef->plugtype == VIR_NETWORK_PORT_PLUG_TYPE_NONE) { + if (flags & VIR_NETWORK_PORT_CREATE_RECLAIM) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Port reclaim requested but plug type is none")); + goto cleanup; + } + } else { + if (!(flags & VIR_NETWORK_PORT_CREATE_RECLAIM)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Port reclaim not requested but plug type is not none")); + goto cleanup; + } + } + + if (virNetworkObjAddPort(obj, portdef, driver->stateDir) < 0) { + virNetworkPortDefFree(portdef); + goto cleanup; + } + + if (flags & VIR_NETWORK_PORT_CREATE_RECLAIM) + rc = networkNotifyPort(obj, portdef); + else + rc = networkAllocatePort(obj, portdef); + if (rc < 0) { + virErrorPtr saved; + saved = virSaveLastError(); + virNetworkObjDeletePort(obj, portdef->uuid, driver->stateDir); + virSetError(saved); + virFreeError(saved); + goto cleanup; + } + + ret = virGetNetworkPort(net, portdef->uuid); + cleanup: + virNetworkObjEndAPI(&obj); + return ret; +} + + +static char * +networkPortGetXMLDesc(virNetworkPortPtr port, + unsigned int flags) +{ + virNetworkObjPtr obj; + virNetworkDefPtr def; + virNetworkPortDefPtr portdef = NULL; + char *ret = NULL; + + virCheckFlags(0, NULL); + + if (!(obj = networkObjFromNetwork(port->net))) + return ret; + + def = virNetworkObjGetDef(obj); + + if (!(portdef = virNetworkObjLookupPort(obj, port->uuid))) + goto cleanup; + + if (virNetworkPortGetXMLDescEnsureACL(port->net->conn, def, portdef) < 0) + goto cleanup; + + if (!virNetworkObjIsActive(obj)) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("network '%s' is not active"), + def->name); + goto cleanup; + } + + if (!(ret = virNetworkPortDefFormat(portdef))) + goto cleanup; + + cleanup: + virNetworkObjEndAPI(&obj); + return ret; +} + + +static int +networkPortDelete(virNetworkPortPtr port, + unsigned int flags) +{ + virNetworkDriverStatePtr driver = networkGetDriver(); + virNetworkObjPtr obj; + virNetworkDefPtr def; + virNetworkPortDefPtr portdef; + int ret = -1; + + virCheckFlags(0, -1); + + if (!(obj = networkObjFromNetwork(port->net))) + return ret; + + def = virNetworkObjGetDef(obj); + + if (!(portdef = virNetworkObjLookupPort(obj, port->uuid))) + goto cleanup; + + if (virNetworkPortDeleteEnsureACL(port->net->conn, def, portdef) < 0) + goto cleanup; + + if (!virNetworkObjIsActive(obj)) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("network '%s' is not active"), + def->name); + goto cleanup; + } + + if (networkReleasePort(obj, portdef) < 0) + goto cleanup; + + virNetworkObjDeletePort(obj, port->uuid, driver->stateDir); + + ret = 0; + cleanup: + virNetworkObjEndAPI(&obj); + return ret; +} + + +static int +networkListAllPorts(virNetworkPtr net, + virNetworkPortPtr **ports, + unsigned int flags) +{ + virNetworkObjPtr obj; + virNetworkDefPtr def; + int ret = -1; + + virCheckFlags(0, -1); + + if (!(obj = networkObjFromNetwork(net))) + return ret; + + def = virNetworkObjGetDef(obj); + + if (virNetworkListAllPortsEnsureACL(net->conn, def) < 0) + goto cleanup; + + if (!virNetworkObjIsActive(obj)) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("network '%s' is not active"), + def->name); + goto cleanup; + } + + ret = virNetworkObjPortListExport(net, obj, ports, + virNetworkListAllPortsCheckACL); + + cleanup: + virNetworkObjEndAPI(&obj); + return ret; +} + + static virNetworkDriver networkDriver = { .name = "bridge", .connectNumOfNetworks = networkConnectNumOfNetworks, /* 0.2.0 */ @@ -5693,6 +5921,11 @@ static virNetworkDriver networkDriver = { .networkIsActive = networkIsActive, /* 0.7.3 */ .networkIsPersistent = networkIsPersistent, /* 0.7.3 */ .networkGetDHCPLeases = networkGetDHCPLeases, /* 1.2.6 */ + .networkPortLookupByUUID = networkPortLookupByUUID, /* 5.0.0 */ + .networkPortCreateXML = networkPortCreateXML, /* 5.0.0 */ + .networkPortGetXMLDesc = networkPortGetXMLDesc, /* 5.0.0 */ + .networkPortDelete = networkPortDelete, /* 5.0.0 */ + .networkListAllPorts = networkListAllPorts, /* 5.0.0 */ }; -- 2.19.2

Change the domain conf so invoke the new network port public APIs instead of the network callbacks. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_conf.c | 125 ++++++++++++++++++-------- src/conf/domain_conf.h | 21 +---- src/network/bridge_driver.c | 172 ------------------------------------ 3 files changed, 90 insertions(+), 228 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e384c60dfd..689a397e44 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -11022,6 +11022,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, char *type = NULL; char *network = NULL; char *portgroup = NULL; + char *portid = NULL; char *bridge = NULL; char *dev = NULL; char *ifname = NULL; @@ -11104,6 +11105,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, virXMLNodeNameEqual(cur, "source")) { network = virXMLPropString(cur, "network"); portgroup = virXMLPropString(cur, "portgroup"); + portid = virXMLPropString(cur, "portid"); } else if (!internal && def->type == VIR_DOMAIN_NET_TYPE_INTERNAL && virXMLNodeNameEqual(cur, "source")) { @@ -11312,12 +11314,20 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, "specified with <interface type='network'/>")); goto error; } + if (portid && + virUUIDParse(portid, def->data.network.portid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse port id '%s'"), portid); + goto error; + } + def->data.network.name = network; network = NULL; def->data.network.portgroup = portgroup; portgroup = NULL; def->data.network.actual = actual; actual = NULL; + break; case VIR_DOMAIN_NET_TYPE_VHOSTUSER: @@ -11830,6 +11840,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_FREE(macaddr); VIR_FREE(network); VIR_FREE(portgroup); + VIR_FREE(portid); VIR_FREE(address); VIR_FREE(port); VIR_FREE(vhostuser_type); @@ -24941,6 +24952,11 @@ virDomainActualNetDefContentsFormat(virBufferPtr buf, def->data.network.name); virBufferEscapeString(buf, " portgroup='%s'", def->data.network.portgroup); + if (virUUIDIsValid(def->data.network.portid)) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(def->data.network.portid, uuidstr); + virBufferAsprintf(buf, " portid='%s'", uuidstr); + } } if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE || actualType == VIR_DOMAIN_NET_TYPE_NETWORK) { @@ -30519,6 +30535,7 @@ virDomainNetDefActualFromNetworkPort(virDomainNetDefPtr iface, if (VIR_STRDUP(actual->data.bridge.brname, port->plug.bridge.brname) < 0) goto error; + actual->type = VIR_DOMAIN_NET_TYPE_BRIDGE; actual->data.bridge.macTableManager = port->plug.bridge.macTableManager; break; @@ -30526,10 +30543,12 @@ virDomainNetDefActualFromNetworkPort(virDomainNetDefPtr iface, if (VIR_STRDUP(actual->data.direct.linkdev, port->plug.direct.linkdev) < 0) goto error; + actual->type = VIR_DOMAIN_NET_TYPE_DIRECT; actual->data.direct.mode = port->plug.direct.mode; break; case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI: + actual->type = VIR_DOMAIN_NET_TYPE_HOSTDEV; actual->data.hostdev.def.parent = iface; actual->data.hostdev.def.info = &iface->info; actual->data.hostdev.def.mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; @@ -30707,48 +30726,82 @@ virDomainNetDefActualToNetworkPort(virDomainDefPtr dom, return NULL; } -static virDomainNetAllocateActualDeviceImpl netAllocate; -static virDomainNetNotifyActualDeviceImpl netNotify; -static virDomainNetReleaseActualDeviceImpl netRelease; static virDomainNetBandwidthChangeAllowedImpl netBandwidthChangeAllowed; static virDomainNetBandwidthUpdateImpl netBandwidthUpdate; void -virDomainNetSetDeviceImpl(virDomainNetAllocateActualDeviceImpl allocate, - virDomainNetNotifyActualDeviceImpl notify, - virDomainNetReleaseActualDeviceImpl release, - virDomainNetBandwidthChangeAllowedImpl bandwidthChangeAllowed, +virDomainNetSetDeviceImpl(virDomainNetBandwidthChangeAllowedImpl bandwidthChangeAllowed, virDomainNetBandwidthUpdateImpl bandwidthUpdate) { - netAllocate = allocate; - netNotify = notify; - netRelease = release; netBandwidthChangeAllowed = bandwidthChangeAllowed; netBandwidthUpdate = bandwidthUpdate; } -int -virDomainNetAllocateActualDevice(virConnectPtr conn, - virDomainDefPtr dom, - virDomainNetDefPtr iface) + +static int +virDomainNetCreatePort(virConnectPtr conn, + virDomainDefPtr dom, + virDomainNetDefPtr iface, + unsigned int flags) { virNetworkPtr net = NULL; int ret = -1; - - if (!netAllocate) { - virReportError(VIR_ERR_NO_SUPPORT, "%s", - _("Virtual networking driver is not available")); - return -1; - } + virNetworkPortDefPtr portdef = NULL; + virNetworkPortPtr port = NULL; + char *portxml = NULL; + virErrorPtr saved; if (!(net = virNetworkLookupByName(conn, iface->data.network.name))) return -1; - ret = netAllocate(net, dom, iface); + if (!(portdef = virDomainNetDefToNetworkPort(dom, iface))) + goto cleanup; + + if (!(portxml = virNetworkPortDefFormat(portdef))) + goto cleanup; + + virNetworkPortDefFree(portdef); + portdef = NULL; + + if (!(port = virNetworkPortCreateXML(net, portxml, flags))) + goto cleanup; + + VIR_FREE(portxml); + + if (!(portxml = virNetworkPortGetXMLDesc(port, 0))) + goto deleteport; + + if (!(portdef = virNetworkPortDefParseString(portxml))) + goto deleteport; + if (virDomainNetDefActualFromNetworkPort(iface, portdef) < 0) + goto deleteport; + + virNetworkPortGetUUID(port, iface->data.network.portid); + + ret = 0; + cleanup: + virNetworkPortDefFree(portdef); + VIR_FREE(portxml); + virObjectUnref(port); virObjectUnref(net); return ret; + + deleteport: + saved = virSaveLastError(); + virNetworkPortDelete(port, 0); + virSetError(saved); + virFreeError(saved); + goto cleanup; +} + +int +virDomainNetAllocateActualDevice(virConnectPtr conn, + virDomainDefPtr dom, + virDomainNetDefPtr iface) +{ + return virDomainNetCreatePort(conn, dom, iface, 0); } void @@ -30756,36 +30809,34 @@ virDomainNetNotifyActualDevice(virConnectPtr conn, virDomainDefPtr dom, virDomainNetDefPtr iface) { - virNetworkPtr net = NULL; - - if (!netNotify) + if (virUUIDIsValid(iface->data.network.portid)) return; - if (!(net = virNetworkLookupByName(conn, iface->data.network.name))) - return; - - netNotify(net, dom, iface); - - virObjectUnref(net); + virDomainNetCreatePort(conn, dom, iface, + VIR_NETWORK_PORT_CREATE_RECLAIM); } int virDomainNetReleaseActualDevice(virConnectPtr conn, - virDomainDefPtr dom, + virDomainDefPtr dom ATTRIBUTE_UNUSED, virDomainNetDefPtr iface) { virNetworkPtr net = NULL; - int ret; - - if (!netRelease) - return 0; + virNetworkPortPtr port = NULL; + int ret = -1; if (!(net = virNetworkLookupByName(conn, iface->data.network.name))) - return -1; + goto cleanup; + + if (!(port = virNetworkPortLookupByUUID(net, iface->data.network.portid))) + goto cleanup; - ret = netRelease(net, dom, iface); + if (virNetworkPortDelete(port, 0) < 0) + goto cleanup; + cleanup: + virObjectUnref(port); virObjectUnref(net); return ret; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 0f672d718e..1f271fde84 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1027,6 +1027,7 @@ struct _virDomainNetDef { struct { char *name; char *portgroup; + unsigned char portid[VIR_UUID_BUFLEN]; /* actual has info about the currently used physical * device (if the network is of type * bridge/private/vepa/passthrough). This is saved in the @@ -3622,21 +3623,6 @@ virNetworkPortDefPtr virDomainNetDefActualToNetworkPort(virDomainDefPtr dom, virDomainNetDefPtr iface); -typedef int -(*virDomainNetAllocateActualDeviceImpl)(virNetworkPtr net, - virDomainDefPtr dom, - virDomainNetDefPtr iface); - -typedef void -(*virDomainNetNotifyActualDeviceImpl)(virNetworkPtr net, - virDomainDefPtr dom, - virDomainNetDefPtr iface); - -typedef int -(*virDomainNetReleaseActualDeviceImpl)(virNetworkPtr net, - virDomainDefPtr dom, - virDomainNetDefPtr iface); - typedef bool (*virDomainNetBandwidthChangeAllowedImpl)(virDomainNetDefPtr iface, virNetDevBandwidthPtr newBandwidth); @@ -3647,10 +3633,7 @@ typedef int void -virDomainNetSetDeviceImpl(virDomainNetAllocateActualDeviceImpl allocate, - virDomainNetNotifyActualDeviceImpl notify, - virDomainNetReleaseActualDeviceImpl release, - virDomainNetBandwidthChangeAllowedImpl bandwidthChangeAllowed, +virDomainNetSetDeviceImpl(virDomainNetBandwidthChangeAllowedImpl bandwidthChangeAllowed, virDomainNetBandwidthUpdateImpl bandwidthUpdate); int diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 8401b72bc8..a8d89a4b4d 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -4765,52 +4765,6 @@ networkAllocatePort(virNetworkObjPtr obj, } -static int -networkAllocateActualDevice(virNetworkPtr net, - virDomainDefPtr dom, - virDomainNetDefPtr iface) -{ - virNetworkDriverStatePtr driver = networkGetDriver(); - virNetworkPortDefPtr port = NULL; - virNetworkObjPtr obj; - int ret = -1; - - obj = virNetworkObjFindByName(driver->networks, net->name); - if (!obj) { - virReportError(VIR_ERR_NO_NETWORK, - _("no network with matching name '%s'"), - net->name); - return -1; - } - - if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Expected a interface for a virtual network")); - goto cleanup; - } - - if (!(port = virDomainNetDefToNetworkPort(dom, iface))) - goto cleanup; - - if (networkAllocatePort(obj, port) < 0) - goto cleanup; - - VIR_DEBUG("Populating net def"); - if (virDomainNetDefActualFromNetworkPort(iface, port) < 0) - goto cleanup; - - ret = 0; - cleanup: - if (ret < 0) { - virDomainActualNetDefFree(iface->data.network.actual); - iface->data.network.actual = NULL; - } - virNetworkPortDefFree(port); - virNetworkObjEndAPI(&obj); - return ret; -} - - /* networkNotifyPort: * @obj: the network to notify * @port: the port definition to notify @@ -5007,72 +4961,6 @@ networkNotifyPort(virNetworkObjPtr obj, } -static void -networkNotifyActualDevice(virNetworkPtr net, - virDomainDefPtr dom, - virDomainNetDefPtr iface) -{ - virNetworkDriverStatePtr driver = networkGetDriver(); - virDomainNetType actualType = virDomainNetGetActualType(iface); - virNetworkObjPtr obj; - virNetworkDefPtr netdef; - virNetworkPortDefPtr port = NULL; - - obj = virNetworkObjFindByName(driver->networks, net->name); - if (!obj) { - virReportError(VIR_ERR_NO_NETWORK, - _("no network with matching name '%s'"), - net->name); - goto cleanup; - } - - if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Expected a interface for a virtual network")); - goto cleanup; - } - - netdef = virNetworkObjGetDef(obj); - - if (!virNetworkObjIsActive(obj)) { - virReportError(VIR_ERR_OPERATION_INVALID, - _("network '%s' is not active"), - netdef->name); - goto cleanup; - } - - /* if we're restarting libvirtd after an upgrade from a version - * that didn't save bridge name in actualNetDef for - * actualType==network, we need to copy it in so that it will be - * available in all cases - */ - if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE && - !iface->data.network.actual->data.bridge.brname && - (VIR_STRDUP(iface->data.network.actual->data.bridge.brname, - netdef->bridge) < 0)) - goto cleanup; - - /* Older libvirtd uses actualType==network, but we now - * just use actualType==bridge, as nothing needs to - * distinguish the two cases, and this simplifies virt - * drive code */ - if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK) { - iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_BRIDGE; - actualType = VIR_DOMAIN_NET_TYPE_BRIDGE; - } - - if (!(port = virDomainNetDefActualToNetworkPort(dom, iface))) - goto cleanup; - - if (networkNotifyPort(obj, port) < 0) - goto cleanup; - - cleanup: - virNetworkObjEndAPI(&obj); - virNetworkPortDefFree(port); -} - - /* networkReleasePort: * @obj: the network to release from * @port: the port definition to release @@ -5188,63 +5076,6 @@ networkReleasePort(virNetworkObjPtr obj, } -/* networkReleaseActualDevice: - * @dom: domain definition that @iface belongs to - * @iface: a domain's NetDef (interface definition) - * - * Given a domain <interface> element that previously had its <actual> - * element filled in (and possibly a physical device allocated to it), - * free up the physical device for use by someone else, and free the - * virDomainActualNetDef. - * - * Returns 0 on success, -1 on failure. - */ -static int -networkReleaseActualDevice(virNetworkPtr net, - virDomainDefPtr dom, - virDomainNetDefPtr iface) -{ - virNetworkDriverStatePtr driver = networkGetDriver(); - virNetworkObjPtr obj; - virNetworkPortDefPtr port = NULL; - int ret = -1; - - obj = virNetworkObjFindByName(driver->networks, net->name); - if (!obj) { - virReportError(VIR_ERR_NO_NETWORK, - _("no network with matching name '%s'"), - net->name); - goto cleanup; - } - - if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Expected a interface for a virtual network")); - goto cleanup; - } - - if (iface->data.network.actual == NULL) { - ret = 0; - goto cleanup; - } - - if (!(port = virDomainNetDefActualToNetworkPort(dom, iface))) - goto cleanup; - - if (networkReleasePort(obj, port) < 0) - goto cleanup; - - ret = 0; - cleanup: - virNetworkObjEndAPI(&obj); - if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK) { - virDomainActualNetDefFree(iface->data.network.actual); - iface->data.network.actual = NULL; - } - virNetworkPortDefFree(port); - return ret; -} - /** * networkCheckBandwidth: @@ -5966,9 +5797,6 @@ networkRegister(void) return -1; virDomainNetSetDeviceImpl( - networkAllocateActualDevice, - networkNotifyActualDevice, - networkReleaseActualDevice, networkBandwidthChangeAllowed, networkBandwidthUpdate); -- 2.19.2

Hi, This series was run against 'syntax-check' test by patchew.org, which failed, please find the details below: Message-id: 20181224145915.8700-1-berrange@redhat.com Subject: [libvirt] [PATCH 00/27] network: refactor to decouple virt drivers from network driver Type: series === TEST SCRIPT BEGIN === #!/bin/bash # Testing script will be invoked under the git checkout with # HEAD pointing to a commit that has the patches applied on top of "base" # branch time bash -c './autogen.sh && make syntax-check' === TEST SCRIPT END === Updating bcb55ab053bc79561b55d0394490f4b64e0f2d01 Switched to a new branch 'test' 6ff9157 conf: switch over to use network port APIs for virt drivers 09db5a1 network: add implementation of network port APIs a9302df conf: support recording ports against virNetworkObjPtr f07a12d virsh: add support for network port APIs 5cf732b remote: add support for new network port APIs cd0c580 access: add permissions for network port objects b7f01ee network: add public APIs for network port object a24767a network: introduce networkReleasePort a07f0c2 network: introduce networkNotifyPort ca0d7e1 network: introduce networkAllocatePort 81869c3 network: convert hook script to take a network port XML f6a273a network: convert networkReleaseActualDevice to virNetworkPortDef 0892c21 network: convert networkNotifyActualDevice to virNetworkPortDef 78e836d network: convert networkAllocateActualDevice to virNetworkPortDef be6c472 conf: add APIs to convert virDomainNetDef to virNetworkPortDef 658ce38 util: add API for copying virtual port profile data e418f23 network: make networkLogAllocation independent of domain conf 4df9034 network: stop passing virDomainNetDefPtr into bandwidth functions 588f5e2 conf: introduce virNetworkPortDefPtr struct and XML support 47cf653 network: unconditionally merge port profiles f784aeb virt drivers: don't handle type=network after resolving actual network type 4b80e83 network: use 'bridge' as actual type instead of 'network' 3734f38 network: add missing bandwidth limits for bridge forward type 0611b44 conf: simplify link from hostdev back to network device 42cf25f network: pass a virNetworkPtr to port management APIs 097cf5b network: restrict usage of port management APIs 280f627 conf: make virPCIDeviceAddressFormat void === OUTPUT BEGIN === Updating submodules... Submodule 'gnulib' (https://git.savannah.gnu.org/git/gnulib.git/) registered for path '.gnulib' Submodule 'keycodemapdb' (https://gitlab.com/keycodemap/keycodemapdb.git) registered for path 'src/keycodemapdb' Cloning into '.gnulib'... Submodule path '.gnulib': checked out '4652c7bafa60332145f1e05a7de5f48e1bc56226' Cloning into 'src/keycodemapdb'... Submodule path 'src/keycodemapdb': checked out '16e5b0787687d8904dad2c026107409eb9bfcb95' Running bootstrap... ./bootstrap: Bootstrapping from checked-out libvirt sources... ./bootstrap: consider installing git-merge-changelog from gnulib ./bootstrap: getting gnulib files... running: libtoolize --install --copy libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, `build-aux'. libtoolize: copying file `build-aux/config.guess' libtoolize: copying file `build-aux/config.sub' libtoolize: copying file `build-aux/install-sh' libtoolize: copying file `build-aux/ltmain.sh' libtoolize: putting macros in AC_CONFIG_MACRO_DIR, `m4'. libtoolize: copying file `m4/libtool.m4' libtoolize: copying file `m4/ltoptions.m4' libtoolize: copying file `m4/ltsugar.m4' libtoolize: copying file `m4/ltversion.m4' libtoolize: copying file `m4/lt~obsolete.m4' ./bootstrap: .gnulib/gnulib-tool --no-changelog --aux-dir=build-aux --doc-base=doc --lib=libgnu --m4-base=m4/ --source-base=gnulib/lib/ --tests-base=gnulib/tests --local-dir=gnulib/local --lgpl=2 --with-tests --makefile-name=gnulib.mk --avoid=pt_chown --avoid=lock-tests --libtool --import ... Module list with included dependencies (indented): absolute-header accept accept-tests alloca alloca-opt alloca-opt-tests allocator areadlink areadlink-tests arpa_inet arpa_inet-tests assure autobuild base64 base64-tests binary-io binary-io-tests bind bind-tests bitrotate bitrotate-tests btowc btowc-tests builtin-expect byteswap byteswap-tests c-ctype c-ctype-tests c-strcase c-strcase-tests c-strcasestr c-strcasestr-tests calloc-posix canonicalize-lgpl canonicalize-lgpl-tests careadlinkat chown chown-tests clock-time cloexec cloexec-tests close close-tests configmake connect connect-tests count-leading-zeros count-leading-zeros-tests count-one-bits count-one-bits-tests ctype ctype-tests dirname-lgpl dosname double-slash-root dup dup-tests dup2 dup2-tests environ environ-tests errno errno-tests error execinfo exitfail extensions extern-inline fatal-signal fclose fclose-tests fcntl fcntl-h fcntl-h-tests fcntl-tests fd-hook fdatasync fdatasync-tests fdopen fdopen-tests fflush fflush-tests ffs ffs-tests ffsl ffsl-tests fgetc-tests filename flexmember float float-tests fnmatch fnmatch-h fnmatch-h-tests fnmatch-tests fpieee fpucw fpurge fpurge-tests fputc-tests fread-tests freading freading-tests fseek fseek-tests fseeko fseeko-tests fstat fstat-tests fsync fsync-tests ftell ftell-tests ftello ftello-tests ftruncate ftruncate-tests func func-tests fwrite-tests getaddrinfo getaddrinfo-tests getcwd-lgpl getcwd-lgpl-tests getdelim getdelim-tests getdtablesize getdtablesize-tests getgroups getgroups-tests gethostname gethostname-tests getline getline-tests getopt-posix getopt-posix-tests getpagesize getpass getpeername getpeername-tests getprogname getprogname-tests getsockname getsockname-tests getsockopt getsockopt-tests gettext-h gettimeofday gettimeofday-tests getugroups gitlog-to-changelog gnumakefile grantpt grantpt-tests hard-locale havelib hostent ignore-value ignore-value-tests include_next inet_ntop inet_ntop-tests inet_pton inet_pton-tests intprops intprops-tests inttypes inttypes-incomplete inttypes-tests ioctl ioctl-tests isatty isatty-tests isblank isblank-tests isnand-nolibm isnand-nolibm-tests isnanf-nolibm isnanf-nolibm-tests isnanl-nolibm isnanl-nolibm-tests langinfo langinfo-tests largefile ldexp ldexp-tests libc-config limits-h limits-h-tests listen listen-tests localcharset localcharset-tests locale locale-tests localeconv localeconv-tests localename localename-tests localtime-buffer lock lseek lseek-tests lstat lstat-tests maintainer-makefile malloc-posix malloca malloca-tests manywarnings math math-tests mbrtowc mbrtowc-tests mbsinit mbsinit-tests mbsrtowcs mbsrtowcs-tests mbtowc memchr memchr-tests mgetgroups mkdir mkdir-tests mkdtemp mkostemp mkostemps mktempd mktime mktime-internal msvc-inval msvc-nothrow multiarch nanosleep nanosleep-tests net_if net_if-tests netdb netdb-tests netinet_in netinet_in-tests nl_langinfo nl_langinfo-tests nocrash nonblocking nonblocking-pipe-tests nonblocking-socket-tests nonblocking-tests open open-tests openpty openpty-tests passfd passfd-tests pathmax pathmax-tests perror perror-tests physmem pipe-posix pipe-posix-tests pipe2 pipe2-tests poll poll-h poll-h-tests poll-tests posix-shell posix_openpt posix_openpt-tests posix_spawn-internal posix_spawn_file_actions_addclose posix_spawn_file_actions_addclose-tests posix_spawn_file_actions_adddup2 posix_spawn_file_actions_adddup2-tests posix_spawn_file_actions_addopen posix_spawn_file_actions_addopen-tests posix_spawn_file_actions_destroy posix_spawn_file_actions_init posix_spawnattr_destroy posix_spawnattr_init posix_spawnattr_setflags posix_spawnattr_setsigmask posix_spawnp posix_spawnp-tests pthread pthread_sigmask pthread_sigmask-tests ptsname ptsname-tests ptsname_r ptsname_r-tests pty pty-tests putenv raise raise-tests rawmemchr rawmemchr-tests read read-tests readlink readlink-tests realloc-posix recv recv-tests regex regex-tests same-inode sched sched-tests secure_getenv select select-tests send send-tests servent setenv setenv-tests setlocale setlocale-tests setsockopt setsockopt-tests sh-filename sigaction sigaction-tests signal-h signal-h-tests signbit signbit-tests sigpipe sigpipe-tests sigprocmask sigprocmask-tests size_max sleep sleep-tests snippet/_Noreturn snippet/arg-nonnull snippet/c++defs snippet/unused-parameter snippet/warn-on-use snprintf snprintf-tests socket socketlib sockets sockets-tests socklen spawn spawn-tests ssize_t stat stat-tests stat-time stat-time-tests stdalign stdalign-tests stdarg stdbool stdbool-tests stddef stddef-tests stdint stdint-tests stdio stdio-tests stdlib stdlib-tests stpcpy strcase strchrnul strchrnul-tests strdup-posix streq strerror strerror-override strerror-tests strerror_r-posix strerror_r-posix-tests string string-tests strings strings-tests strndup strnlen strnlen-tests strnlen1 strptime strsep strtok_r symlink symlink-tests sys_ioctl sys_ioctl-tests sys_select sys_select-tests sys_socket sys_socket-tests sys_stat sys_stat-tests sys_time sys_time-tests sys_types sys_types-tests sys_uio sys_uio-tests sys_utsname sys_utsname-tests sys_wait sys_wait-tests tempname termios termios-tests test-framework-sh test-framework-sh-tests thread thread-tests threadlib time time-tests time_r timegm ttyname_r ttyname_r-tests uname uname-tests unistd unistd-tests unitypes uniwidth/base uniwidth/width uniwidth/width-tests unlockpt unlockpt-tests unsetenv unsetenv-tests useless-if-before-free usleep usleep-tests vasnprintf vasnprintf-tests vasprintf vasprintf-tests vc-list-files vc-list-files-tests verify verify-tests vsnprintf vsnprintf-tests wait-process waitpid warnings wchar wchar-tests wcrtomb wcrtomb-tests wctob wctomb wctype-h wctype-h-tests wcwidth wcwidth-tests write write-tests xalloc xalloc-die xalloc-die-tests xalloc-oversized xsize Notice from module vasprintf: If you are using GNU gettext version 0.16.1 or older, add the following options to XGETTEXT_OPTIONS in your po/Makevars: --flag=asprintf:2:c-format --flag=vasprintf:2:c-format File list: build-aux/config.rpath build-aux/gitlog-to-changelog build-aux/mktempd build-aux/useless-if-before-free build-aux/vc-list-files lib/_Noreturn.h lib/accept.c lib/alloca.c lib/alloca.in.h lib/allocator.c lib/allocator.h lib/areadlink.c lib/areadlink.h lib/arg-nonnull.h lib/arpa_inet.in.h lib/asnprintf.c lib/asprintf.c lib/assure.h lib/base64.c lib/base64.h lib/basename-lgpl.c lib/binary-io.c lib/binary-io.h lib/bind.c lib/bitrotate.c lib/bitrotate.h lib/btowc.c lib/byteswap.in.h lib/c++defs.h lib/c-ctype.c lib/c-ctype.h lib/c-strcase.h lib/c-strcasecmp.c lib/c-strcasestr.c lib/c-strcasestr.h lib/c-strncasecmp.c lib/calloc.c lib/canonicalize-lgpl.c lib/careadlinkat.c lib/careadlinkat.h lib/cdefs.h lib/chown.c lib/cloexec.c lib/cloexec.h lib/close.c lib/connect.c lib/count-leading-zeros.c lib/count-leading-zeros.h lib/count-one-bits.c lib/count-one-bits.h lib/dirname-lgpl.c lib/dirname.h lib/dosname.h lib/dup2.c lib/errno.in.h lib/execinfo.c lib/execinfo.in.h lib/fchown-stub.c lib/fclose.c lib/fcntl.c lib/fcntl.in.h lib/fd-hook.c lib/fd-hook.h lib/fdatasync.c lib/fflush.c lib/ffs.c lib/ffsl.c lib/ffsl.h lib/filename.h lib/flexmember.h lib/float+.h lib/float.c lib/float.in.h lib/fnmatch.c lib/fnmatch.in.h lib/fnmatch_loop.c lib/fpurge.c lib/freading.c lib/freading.h lib/fseek.c lib/fseeko.c lib/fstat.c lib/fsync.c lib/ftell.c lib/ftello.c lib/gai_strerror.c lib/getaddrinfo.c lib/getcwd-lgpl.c lib/getdelim.c lib/getdtablesize.c lib/getgroups.c lib/gethostname.c lib/getline.c lib/getopt-cdefs.in.h lib/getopt-core.h lib/getopt-ext.h lib/getopt-pfx-core.h lib/getopt-pfx-ext.h lib/getopt.c lib/getopt.in.h lib/getopt1.c lib/getopt_int.h lib/getpass.c lib/getpass.h lib/getpeername.c lib/getsockname.c lib/gettext.h lib/gettimeofday.c lib/getugroups.c lib/getugroups.h lib/glthread/lock.c lib/glthread/lock.h lib/glthread/threadlib.c lib/hard-locale.c lib/hard-locale.h lib/ignore-value.h lib/inet_ntop.c lib/inet_pton.c lib/intprops.h lib/ioctl.c lib/isatty.c lib/itold.c lib/langinfo.in.h lib/libc-config.h lib/limits.in.h lib/listen.c lib/localcharset.c lib/localcharset.h lib/locale.in.h lib/localeconv.c lib/localtime-buffer.c lib/localtime-buffer.h lib/lseek.c lib/lstat.c lib/malloc.c lib/malloca.c lib/malloca.h lib/mbrtowc.c lib/mbsinit.c lib/mbsrtowcs-impl.h lib/mbsrtowcs-state.c lib/mbsrtowcs.c lib/mbtowc-impl.h lib/mbtowc.c lib/memchr.c lib/memchr.valgrind lib/mgetgroups.c lib/mgetgroups.h lib/mkdir.c lib/mkdtemp.c lib/mkostemp.c lib/mkostemps.c lib/mktime-internal.h lib/mktime.c lib/msvc-inval.c lib/msvc-inval.h lib/msvc-nothrow.c lib/msvc-nothrow.h lib/net_if.in.h lib/netdb.in.h lib/netinet_in.in.h lib/nl_langinfo.c lib/nonblocking.c lib/nonblocking.h lib/open.c lib/openpty.c lib/passfd.c lib/passfd.h lib/pathmax.h lib/perror.c lib/physmem.c lib/physmem.h lib/pipe.c lib/pipe2.c lib/poll.c lib/poll.in.h lib/posix_openpt.c lib/printf-args.c lib/printf-args.h lib/printf-parse.c lib/printf-parse.h lib/pthread.c lib/pthread.in.h lib/pthread_sigmask.c lib/pty.in.h lib/raise.c lib/rawmemchr.c lib/rawmemchr.valgrind lib/readlink.c lib/realloc.c lib/recv.c lib/regcomp.c lib/regex.c lib/regex.h lib/regex_internal.c lib/regex_internal.h lib/regexec.c lib/sched.in.h lib/secure_getenv.c lib/select.c lib/send.c lib/setenv.c lib/setsockopt.c lib/sig-handler.c lib/sig-handler.h lib/sigaction.c lib/signal.in.h lib/sigprocmask.c lib/size_max.h lib/sleep.c lib/snprintf.c lib/socket.c lib/sockets.c lib/sockets.h lib/stat-time.c lib/stat-time.h lib/stat-w32.c lib/stat-w32.h lib/stat.c lib/stdalign.in.h lib/stdarg.in.h lib/stdbool.in.h lib/stddef.in.h lib/stdint.in.h lib/stdio-impl.h lib/stdio-read.c lib/stdio-write.c lib/stdio.in.h lib/stdlib.in.h lib/stpcpy.c lib/str-two-way.h lib/strcasecmp.c lib/strchrnul.c lib/strchrnul.valgrind lib/strdup.c lib/streq.h lib/strerror-override.c lib/strerror-override.h lib/strerror.c lib/strerror_r.c lib/string.in.h lib/strings.in.h lib/stripslash.c lib/strncasecmp.c lib/strndup.c lib/strnlen.c lib/strnlen1.c lib/strnlen1.h lib/strptime.c lib/strsep.c lib/strtok_r.c lib/sys_ioctl.in.h lib/sys_select.in.h lib/sys_socket.c lib/sys_socket.in.h lib/sys_stat.in.h lib/sys_time.in.h lib/sys_types.in.h lib/sys_uio.in.h lib/sys_utsname.in.h lib/sys_wait.in.h lib/tempname.c lib/tempname.h lib/termios.in.h lib/time.in.h lib/time_r.c lib/timegm.c lib/ttyname_r.c lib/uname.c lib/unistd.c lib/unistd.in.h lib/unitypes.in.h lib/uniwidth.in.h lib/uniwidth/cjk.h lib/uniwidth/width.c lib/unsetenv.c lib/unused-parameter.h lib/usleep.c lib/vasnprintf.c lib/vasnprintf.h lib/vasprintf.c lib/verify.h lib/vsnprintf.c lib/w32sock.h lib/waitpid.c lib/warn-on-use.h lib/wchar.in.h lib/wcrtomb.c lib/wctype-h.c lib/wctype.in.h lib/wcwidth.c lib/xalloc-oversized.h lib/xsize.c lib/xsize.h m4/00gnulib.m4 m4/__inline.m4 m4/absolute-header.m4 m4/alloca.m4 m4/arpa_inet_h.m4 m4/asm-underscore.m4 m4/autobuild.m4 m4/base64.m4 m4/btowc.m4 m4/builtin-expect.m4 m4/byteswap.m4 m4/calloc.m4 m4/canonicalize.m4 m4/chown.m4 m4/clock_time.m4 m4/close.m4 m4/codeset.m4 m4/configmake.m4 m4/count-leading-zeros.m4 m4/count-one-bits.m4 m4/ctype.m4 m4/dirname.m4 m4/double-slash-root.m4 m4/dup.m4 m4/dup2.m4 m4/eealloc.m4 m4/environ.m4 m4/errno_h.m4 m4/error.m4 m4/execinfo.m4 m4/exponentd.m4 m4/exponentf.m4 m4/exponentl.m4 m4/extensions.m4 m4/extern-inline.m4 m4/fatal-signal.m4 m4/fclose.m4 m4/fcntl-o.m4 m4/fcntl.m4 m4/fcntl_h.m4 m4/fdatasync.m4 m4/fdopen.m4 m4/fflush.m4 m4/ffs.m4 m4/ffsl.m4 m4/flexmember.m4 m4/float_h.m4 m4/fnmatch.m4 m4/fnmatch_h.m4 m4/fpieee.m4 m4/fpurge.m4 m4/freading.m4 m4/fseek.m4 m4/fseeko.m4 m4/fstat.m4 m4/fsync.m4 m4/ftell.m4 m4/ftello.m4 m4/ftruncate.m4 m4/func.m4 m4/getaddrinfo.m4 m4/getcwd.m4 m4/getdelim.m4 m4/getdtablesize.m4 m4/getgroups.m4 m4/gethostname.m4 m4/getline.m4 m4/getopt.m4 m4/getpagesize.m4 m4/getpass.m4 m4/getprogname.m4 m4/gettimeofday.m4 m4/getugroups.m4 m4/glibc21.m4 m4/gnulib-common.m4 m4/grantpt.m4 m4/host-cpu-c-abi.m4 m4/hostent.m4 m4/include_next.m4 m4/inet_ntop.m4 m4/inet_pton.m4 m4/intl-thread-locale.m4 m4/intlmacosx.m4 m4/intmax_t.m4 m4/inttypes-pri.m4 m4/inttypes.m4 m4/inttypes_h.m4 m4/ioctl.m4 m4/isatty.m4 m4/isblank.m4 m4/isnand.m4 m4/isnanf.m4 m4/isnanl.m4 m4/langinfo_h.m4 m4/largefile.m4 m4/lcmessage.m4 m4/ldexp.m4 m4/lib-ld.m4 m4/lib-link.m4 m4/lib-prefix.m4 m4/libunistring-base.m4 m4/limits-h.m4 m4/localcharset.m4 m4/locale-fr.m4 m4/locale-ja.m4 m4/locale-tr.m4 m4/locale-zh.m4 m4/locale_h.m4 m4/localeconv.m4 m4/localename.m4 m4/localtime-buffer.m4 m4/lock.m4 m4/longlong.m4 m4/lseek.m4 m4/lstat.m4 m4/malloc.m4 m4/malloca.m4 m4/manywarnings-c++.m4 m4/manywarnings.m4 m4/math_h.m4 m4/mbrtowc.m4 m4/mbsinit.m4 m4/mbsrtowcs.m4 m4/mbstate_t.m4 m4/mbtowc.m4 m4/memchr.m4 m4/mgetgroups.m4 m4/mkdir.m4 m4/mkdtemp.m4 m4/mkostemp.m4 m4/mkostemps.m4 m4/mktime.m4 m4/mmap-anon.m4 m4/mode_t.m4 m4/msvc-inval.m4 m4/msvc-nothrow.m4 m4/multiarch.m4 m4/nanosleep.m4 m4/net_if_h.m4 m4/netdb_h.m4 m4/netinet_in_h.m4 m4/nl_langinfo.m4 m4/nocrash.m4 m4/nonblocking.m4 m4/off_t.m4 m4/open-cloexec.m4 m4/open.m4 m4/passfd.m4 m4/pathmax.m4 m4/perror.m4 m4/physmem.m4 m4/pipe.m4 m4/pipe2.m4 m4/poll.m4 m4/poll_h.m4 m4/posix-shell.m4 m4/posix_openpt.m4 m4/posix_spawn.m4 m4/printf.m4 m4/pthread.m4 m4/pthread_rwlock_rdlock.m4 m4/pthread_sigmask.m4 m4/ptsname.m4 m4/ptsname_r.m4 m4/pty.m4 m4/pty_h.m4 m4/putenv.m4 m4/raise.m4 m4/rawmemchr.m4 m4/read.m4 m4/readlink.m4 m4/realloc.m4 m4/regex.m4 m4/sched_h.m4 m4/secure_getenv.m4 m4/select.m4 m4/servent.m4 m4/setenv.m4 m4/setlocale.m4 m4/sh-filename.m4 m4/sig_atomic_t.m4 m4/sigaction.m4 m4/signal_h.m4 m4/signalblocking.m4 m4/signbit.m4 m4/sigpipe.m4 m4/size_max.m4 m4/sleep.m4 m4/snprintf.m4 m4/socketlib.m4 m4/sockets.m4 m4/socklen.m4 m4/sockpfaf.m4 m4/spawn_h.m4 m4/ssize_t.m4 m4/stat-time.m4 m4/stat.m4 m4/stdalign.m4 m4/stdarg.m4 m4/stdbool.m4 m4/stddef_h.m4 m4/stdint.m4 m4/stdint_h.m4 m4/stdio_h.m4 m4/stdlib_h.m4 m4/stpcpy.m4 m4/strcase.m4 m4/strchrnul.m4 m4/strdup.m4 m4/strerror.m4 m4/strerror_r.m4 m4/string_h.m4 m4/strings_h.m4 m4/strndup.m4 m4/strnlen.m4 m4/strptime.m4 m4/strsep.m4 m4/strtok_r.m4 m4/symlink.m4 m4/sys_ioctl_h.m4 m4/sys_select_h.m4 m4/sys_socket_h.m4 m4/sys_stat_h.m4 m4/sys_time_h.m4 m4/sys_types_h.m4 m4/sys_uio_h.m4 m4/sys_utsname_h.m4 m4/sys_wait_h.m4 m4/tempname.m4 m4/termios_h.m4 m4/thread.m4 m4/threadlib.m4 m4/time_h.m4 m4/time_r.m4 m4/timegm.m4 m4/tm_gmtoff.m4 m4/ttyname_r.m4 m4/uname.m4 m4/ungetc.m4 m4/unistd_h.m4 m4/unlockpt.m4 m4/usleep.m4 m4/vasnprintf.m4 m4/vasprintf.m4 m4/vsnprintf.m4 m4/wait-process.m4 m4/waitpid.m4 m4/warn-on-use.m4 m4/warnings.m4 m4/wchar_h.m4 m4/wchar_t.m4 m4/wcrtomb.m4 m4/wctob.m4 m4/wctomb.m4 m4/wctype_h.m4 m4/wcwidth.m4 m4/wint_t.m4 m4/write.m4 m4/xalloc.m4 m4/xsize.m4 tests/infinity.h tests/init.sh tests/macros.h tests/minus-zero.h tests/nan.h tests/nap.h tests/null-ptr.h tests/randomd.c tests/signature.h tests/socket-client.h tests/socket-server.h tests/test-accept.c tests/test-alloca-opt.c tests/test-areadlink.c tests/test-areadlink.h tests/test-arpa_inet.c tests/test-base64.c tests/test-binary-io.c tests/test-binary-io.sh tests/test-bind.c tests/test-bitrotate.c tests/test-btowc.c tests/test-btowc1.sh tests/test-btowc2.sh tests/test-byteswap.c tests/test-c-ctype.c tests/test-c-strcase.sh tests/test-c-strcasecmp.c tests/test-c-strcasestr.c tests/test-c-strncasecmp.c tests/test-canonicalize-lgpl.c tests/test-chown.c tests/test-chown.h tests/test-cloexec.c tests/test-close.c tests/test-connect.c tests/test-count-leading-zeros.c tests/test-count-one-bits.c tests/test-ctype.c tests/test-dup.c tests/test-dup2.c tests/test-environ.c tests/test-errno.c tests/test-fclose.c tests/test-fcntl-h.c tests/test-fcntl.c tests/test-fdatasync.c tests/test-fdopen.c tests/test-fflush.c tests/test-fflush2.c tests/test-fflush2.sh tests/test-ffs.c tests/test-ffsl.c tests/test-fgetc.c tests/test-float.c tests/test-fnmatch-h.c tests/test-fnmatch.c tests/test-fpurge.c tests/test-fputc.c tests/test-fread.c tests/test-freading.c tests/test-fseek.c tests/test-fseek.sh tests/test-fseek2.sh tests/test-fseeko.c tests/test-fseeko.sh tests/test-fseeko2.sh tests/test-fseeko3.c tests/test-fseeko3.sh tests/test-fseeko4.c tests/test-fseeko4.sh tests/test-fstat.c tests/test-fsync.c tests/test-ftell.c tests/test-ftell.sh tests/test-ftell2.sh tests/test-ftell3.c tests/test-ftello.c tests/test-ftello.sh tests/test-ftello2.sh tests/test-ftello3.c tests/test-ftello4.c tests/test-ftello4.sh tests/test-ftruncate.c tests/test-ftruncate.sh tests/test-func.c tests/test-fwrite.c tests/test-getaddrinfo.c tests/test-getcwd-lgpl.c tests/test-getdelim.c tests/test-getdtablesize.c tests/test-getgroups.c tests/test-gethostname.c tests/test-getline.c tests/test-getopt-main.h tests/test-getopt-posix.c tests/test-getopt.h tests/test-getpeername.c tests/test-getprogname.c tests/test-getsockname.c tests/test-getsockopt.c tests/test-gettimeofday.c tests/test-grantpt.c tests/test-ignore-value.c tests/test-inet_ntop.c tests/test-inet_pton.c tests/test-init.sh tests/test-intprops.c tests/test-inttypes.c tests/test-ioctl.c tests/test-isatty.c tests/test-isblank.c tests/test-isnand-nolibm.c tests/test-isnand.h tests/test-isnanf-nolibm.c tests/test-isnanf.h tests/test-isnanl-nolibm.c tests/test-isnanl.h tests/test-langinfo.c tests/test-ldexp.c tests/test-ldexp.h tests/test-limits-h.c tests/test-listen.c tests/test-localcharset.c tests/test-locale.c tests/test-localeconv.c tests/test-localename.c tests/test-lseek.c tests/test-lseek.sh tests/test-lstat.c tests/test-lstat.h tests/test-malloca.c tests/test-math.c tests/test-mbrtowc-w32-1.sh tests/test-mbrtowc-w32-2.sh tests/test-mbrtowc-w32-3.sh tests/test-mbrtowc-w32-4.sh tests/test-mbrtowc-w32-5.sh tests/test-mbrtowc-w32.c tests/test-mbrtowc.c tests/test-mbrtowc1.sh tests/test-mbrtowc2.sh tests/test-mbrtowc3.sh tests/test-mbrtowc4.sh tests/test-mbrtowc5.sh tests/test-mbsinit.c tests/test-mbsinit.sh tests/test-mbsrtowcs.c tests/test-mbsrtowcs1.sh tests/test-mbsrtowcs2.sh tests/test-mbsrtowcs3.sh tests/test-mbsrtowcs4.sh tests/test-memchr.c tests/test-mkdir.c tests/test-mkdir.h tests/test-nanosleep.c tests/test-net_if.c tests/test-netdb.c tests/test-netinet_in.c tests/test-nl_langinfo.c tests/test-nl_langinfo.sh tests/test-nonblocking-misc.h tests/test-nonblocking-pipe-child.c tests/test-nonblocking-pipe-main.c tests/test-nonblocking-pipe.h tests/test-nonblocking-pipe.sh tests/test-nonblocking-reader.h tests/test-nonblocking-socket-child.c tests/test-nonblocking-socket-main.c tests/test-nonblocking-socket.h tests/test-nonblocking-socket.sh tests/test-nonblocking-writer.h tests/test-nonblocking.c tests/test-open.c tests/test-open.h tests/test-openpty.c tests/test-passfd.c tests/test-pathmax.c tests/test-perror.c tests/test-perror.sh tests/test-perror2.c tests/test-pipe.c tests/test-pipe2.c tests/test-poll-h.c tests/test-poll.c tests/test-posix_openpt.c tests/test-posix_spawn1.c tests/test-posix_spawn1.in.sh tests/test-posix_spawn2.c tests/test-posix_spawn2.in.sh tests/test-posix_spawn_file_actions_addclose.c tests/test-posix_spawn_file_actions_adddup2.c tests/test-posix_spawn_file_actions_addopen.c tests/test-pthread_sigmask1.c tests/test-pthread_sigmask2.c tests/test-ptsname.c tests/test-ptsname_r.c tests/test-raise.c tests/test-rawmemchr.c tests/test-read.c tests/test-readlink.c tests/test-readlink.h tests/test-recv.c tests/test-regex.c tests/test-sched.c tests/test-select-fd.c tests/test-select-in.sh tests/test-select-out.sh tests/test-select-stdin.c tests/test-select.c tests/test-select.h tests/test-send.c tests/test-setenv.c tests/test-setlocale1.c tests/test-setlocale1.sh tests/test-setlocale2.c tests/test-setlocale2.sh tests/test-setsockopt.c tests/test-sigaction.c tests/test-signal-h.c tests/test-signbit.c tests/test-sigpipe.c tests/test-sigpipe.sh tests/test-sigprocmask.c tests/test-sleep.c tests/test-snprintf.c tests/test-sockets.c tests/test-spawn.c tests/test-stat-time.c tests/test-stat.c tests/test-stat.h tests/test-stdalign.c tests/test-stdbool.c tests/test-stddef.c tests/test-stdint.c tests/test-stdio.c tests/test-stdlib.c tests/test-strchrnul.c tests/test-strerror.c tests/test-strerror_r.c tests/test-string.c tests/test-strings.c tests/test-strnlen.c tests/test-symlink.c tests/test-symlink.h tests/test-sys_ioctl.c tests/test-sys_select.c tests/test-sys_socket.c tests/test-sys_stat.c tests/test-sys_time.c tests/test-sys_types.c tests/test-sys_uio.c tests/test-sys_utsname.c tests/test-sys_wait.c tests/test-sys_wait.h tests/test-termios.c tests/test-thread_create.c tests/test-thread_self.c tests/test-time.c tests/test-ttyname_r.c tests/test-uname.c tests/test-unistd.c tests/test-unlockpt.c tests/test-unsetenv.c tests/test-usleep.c tests/test-vasnprintf.c tests/test-vasprintf.c tests/test-vc-list-files-cvs.sh tests/test-vc-list-files-git.sh tests/test-verify-try.c tests/test-verify.c tests/test-verify.sh tests/test-vsnprintf.c tests/test-wchar.c tests/test-wcrtomb-w32-1.sh tests/test-wcrtomb-w32-2.sh tests/test-wcrtomb-w32-3.sh tests/test-wcrtomb-w32-4.sh tests/test-wcrtomb-w32-5.sh tests/test-wcrtomb-w32.c tests/test-wcrtomb.c tests/test-wcrtomb.sh tests/test-wctype-h.c tests/test-wcwidth.c tests/test-write.c tests/test-xalloc-die.c tests/test-xalloc-die.sh tests/uniwidth/test-uc_width.c tests/uniwidth/test-uc_width2.c tests/uniwidth/test-uc_width2.sh tests/zerosize-ptr.h lib/_Noreturn.h -> tests/_Noreturn.h lib/arg-nonnull.h -> tests/arg-nonnull.h lib/c++defs.h -> tests/c++defs.h lib/ctype.in.h -> tests/ctype.in.h lib/dup.c -> tests/dup.c lib/error.c -> tests/error.c lib/error.h -> tests/error.h lib/exitfail.c -> tests/exitfail.c lib/exitfail.h -> tests/exitfail.h lib/fatal-signal.c -> tests/fatal-signal.c lib/fatal-signal.h -> tests/fatal-signal.h lib/fdopen.c -> tests/fdopen.c lib/float+.h -> tests/float+.h lib/fpucw.h -> tests/fpucw.h lib/ftruncate.c -> tests/ftruncate.c lib/getpagesize.c -> tests/getpagesize.c lib/getprogname.c -> tests/getprogname.c lib/getprogname.h -> tests/getprogname.h lib/getsockopt.c -> tests/getsockopt.c lib/glthread/thread.c -> tests/glthread/thread.c lib/glthread/thread.h -> tests/glthread/thread.h lib/grantpt.c -> tests/grantpt.c lib/inttypes.in.h -> tests/inttypes.in.h lib/isblank.c -> tests/isblank.c lib/isnan.c -> tests/isnan.c lib/isnand-nolibm.h -> tests/isnand-nolibm.h lib/isnand.c -> tests/isnand.c lib/isnanf-nolibm.h -> tests/isnanf-nolibm.h lib/isnanf.c -> tests/isnanf.c lib/isnanl-nolibm.h -> tests/isnanl-nolibm.h lib/isnanl.c -> tests/isnanl.c lib/localename-table.c -> tests/localename-table.c lib/localename-table.h -> tests/localename-table.h lib/localename.c -> tests/localename.c lib/localename.h -> tests/localename.h lib/math.c -> tests/math.c lib/math.in.h -> tests/math.in.h lib/nanosleep.c -> tests/nanosleep.c lib/ptsname.c -> tests/ptsname.c lib/ptsname_r.c -> tests/ptsname_r.c lib/pty-private.h -> tests/pty-private.h lib/putenv.c -> tests/putenv.c lib/read.c -> tests/read.c lib/same-inode.h -> tests/same-inode.h lib/setlocale.c -> tests/setlocale.c lib/signbitd.c -> tests/signbitd.c lib/signbitf.c -> tests/signbitf.c lib/signbitl.c -> tests/signbitl.c lib/spawn.in.h -> tests/spawn.in.h lib/spawn_faction_addclose.c -> tests/spawn_faction_addclose.c lib/spawn_faction_adddup2.c -> tests/spawn_faction_adddup2.c lib/spawn_faction_addopen.c -> tests/spawn_faction_addopen.c lib/spawn_faction_destroy.c -> tests/spawn_faction_destroy.c lib/spawn_faction_init.c -> tests/spawn_faction_init.c lib/spawn_int.h -> tests/spawn_int.h lib/spawnattr_destroy.c -> tests/spawnattr_destroy.c lib/spawnattr_init.c -> tests/spawnattr_init.c lib/spawnattr_setflags.c -> tests/spawnattr_setflags.c lib/spawnattr_setsigmask.c -> tests/spawnattr_setsigmask.c lib/spawni.c -> tests/spawni.c lib/spawnp.c -> tests/spawnp.c lib/symlink.c -> tests/symlink.c lib/unlockpt.c -> tests/unlockpt.c lib/unused-parameter.h -> tests/unused-parameter.h lib/w32sock.h -> tests/w32sock.h lib/wait-process.c -> tests/wait-process.c lib/wait-process.h -> tests/wait-process.h lib/warn-on-use.h -> tests/warn-on-use.h lib/wctob.c -> tests/wctob.c lib/wctomb-impl.h -> tests/wctomb-impl.h lib/wctomb.c -> tests/wctomb.c lib/write.c -> tests/write.c lib/xalloc-die.c -> tests/xalloc-die.c lib/xalloc.h -> tests/xalloc.h lib/xmalloc.c -> tests/xmalloc.c top/GNUmakefile top/maint.mk Creating directory ./gnulib/lib/glthread Creating directory ./gnulib/lib/uniwidth Creating directory ./gnulib/tests/glthread Creating directory ./gnulib/tests/uniwidth Copying file GNUmakefile Copying file build-aux/config.rpath Copying file build-aux/gitlog-to-changelog Copying file build-aux/mktempd Copying file build-aux/useless-if-before-free Copying file build-aux/vc-list-files Copying file gnulib/lib/_Noreturn.h Copying file gnulib/lib/accept.c Copying file gnulib/lib/alloca.c Copying file gnulib/lib/alloca.in.h Copying file gnulib/lib/allocator.c Copying file gnulib/lib/allocator.h Copying file gnulib/lib/areadlink.c Copying file gnulib/lib/areadlink.h Copying file gnulib/lib/arg-nonnull.h Copying file gnulib/lib/arpa_inet.in.h Copying file gnulib/lib/asnprintf.c Copying file gnulib/lib/asprintf.c Copying file gnulib/lib/assure.h Copying file gnulib/lib/base64.c Copying file gnulib/lib/base64.h Copying file gnulib/lib/basename-lgpl.c Copying file gnulib/lib/binary-io.c Copying file gnulib/lib/binary-io.h Copying file gnulib/lib/bind.c Copying file gnulib/lib/bitrotate.c Copying file gnulib/lib/bitrotate.h Copying file gnulib/lib/btowc.c Copying file gnulib/lib/byteswap.in.h Copying file gnulib/lib/c++defs.h Copying file gnulib/lib/c-ctype.c Copying file gnulib/lib/c-ctype.h Copying file gnulib/lib/c-strcase.h Copying file gnulib/lib/c-strcasecmp.c Copying file gnulib/lib/c-strcasestr.c Copying file gnulib/lib/c-strcasestr.h Copying file gnulib/lib/c-strncasecmp.c Copying file gnulib/lib/calloc.c Copying file gnulib/lib/canonicalize-lgpl.c Copying file gnulib/lib/careadlinkat.c Copying file gnulib/lib/careadlinkat.h Copying file gnulib/lib/cdefs.h Copying file gnulib/lib/chown.c Copying file gnulib/lib/cloexec.c Copying file gnulib/lib/cloexec.h Copying file gnulib/lib/close.c Copying file gnulib/lib/connect.c Copying file gnulib/lib/count-leading-zeros.c Copying file gnulib/lib/count-leading-zeros.h Copying file gnulib/lib/count-one-bits.c Copying file gnulib/lib/count-one-bits.h Copying file gnulib/lib/dirname-lgpl.c Copying file gnulib/lib/dirname.h Copying file gnulib/lib/dosname.h Copying file gnulib/lib/dup2.c Copying file gnulib/lib/errno.in.h Copying file gnulib/lib/execinfo.c Copying file gnulib/lib/execinfo.in.h Copying file gnulib/lib/fchown-stub.c Copying file gnulib/lib/fclose.c Copying file gnulib/lib/fcntl.c Copying file gnulib/lib/fcntl.in.h Copying file gnulib/lib/fd-hook.c Copying file gnulib/lib/fd-hook.h Copying file gnulib/lib/fdatasync.c Copying file gnulib/lib/fflush.c Copying file gnulib/lib/ffs.c Copying file gnulib/lib/ffsl.c Copying file gnulib/lib/ffsl.h Copying file gnulib/lib/filename.h Copying file gnulib/lib/flexmember.h Copying file gnulib/lib/float+.h Copying file gnulib/lib/float.c Copying file gnulib/lib/float.in.h Copying file gnulib/lib/fnmatch.c Copying file gnulib/lib/fnmatch.in.h Copying file gnulib/lib/fnmatch_loop.c Copying file gnulib/lib/fpurge.c Copying file gnulib/lib/freading.c Copying file gnulib/lib/freading.h Copying file gnulib/lib/fseek.c Copying file gnulib/lib/fseeko.c Copying file gnulib/lib/fstat.c Copying file gnulib/lib/fsync.c Copying file gnulib/lib/ftell.c Copying file gnulib/lib/ftello.c Copying file gnulib/lib/gai_strerror.c Copying file gnulib/lib/getaddrinfo.c Copying file gnulib/lib/getcwd-lgpl.c Copying file gnulib/lib/getdelim.c Copying file gnulib/lib/getdtablesize.c Copying file gnulib/lib/getgroups.c Copying file gnulib/lib/gethostname.c Copying file gnulib/lib/getline.c Copying file gnulib/lib/getopt-cdefs.in.h Copying file gnulib/lib/getopt-core.h Copying file gnulib/lib/getopt-ext.h Copying file gnulib/lib/getopt-pfx-core.h Copying file gnulib/lib/getopt-pfx-ext.h Copying file gnulib/lib/getopt.c Copying file gnulib/lib/getopt.in.h Copying file gnulib/lib/getopt1.c Copying file gnulib/lib/getopt_int.h Copying file gnulib/lib/getpass.c Copying file gnulib/lib/getpass.h Copying file gnulib/lib/getpeername.c Copying file gnulib/lib/getsockname.c Copying file gnulib/lib/gettext.h Copying file gnulib/lib/gettimeofday.c Copying file gnulib/lib/getugroups.c Copying file gnulib/lib/getugroups.h Copying file gnulib/lib/glthread/lock.c Copying file gnulib/lib/glthread/lock.h Copying file gnulib/lib/glthread/threadlib.c Copying file gnulib/lib/hard-locale.c Copying file gnulib/lib/hard-locale.h Copying file gnulib/lib/ignore-value.h Copying file gnulib/lib/inet_ntop.c Copying file gnulib/lib/inet_pton.c Copying file gnulib/lib/intprops.h Copying file gnulib/lib/ioctl.c Copying file gnulib/lib/isatty.c Copying file gnulib/lib/itold.c Copying file gnulib/lib/langinfo.in.h Copying file gnulib/lib/libc-config.h Copying file gnulib/lib/limits.in.h Copying file gnulib/lib/listen.c Copying file gnulib/lib/localcharset.c Copying file gnulib/lib/localcharset.h Copying file gnulib/lib/locale.in.h Copying file gnulib/lib/localeconv.c Copying file gnulib/lib/localtime-buffer.c Copying file gnulib/lib/localtime-buffer.h Copying file gnulib/lib/lseek.c Copying file gnulib/lib/lstat.c Copying file gnulib/lib/malloc.c Copying file gnulib/lib/malloca.c Copying file gnulib/lib/malloca.h Copying file gnulib/lib/mbrtowc.c Copying file gnulib/lib/mbsinit.c Copying file gnulib/lib/mbsrtowcs-impl.h Copying file gnulib/lib/mbsrtowcs-state.c Copying file gnulib/lib/mbsrtowcs.c Copying file gnulib/lib/mbtowc-impl.h Copying file gnulib/lib/mbtowc.c Copying file gnulib/lib/memchr.c Copying file gnulib/lib/memchr.valgrind Copying file gnulib/lib/mgetgroups.c Copying file gnulib/lib/mgetgroups.h Copying file gnulib/lib/mkdir.c Copying file gnulib/lib/mkdtemp.c Copying file gnulib/lib/mkostemp.c Copying file gnulib/lib/mkostemps.c Copying file gnulib/lib/mktime-internal.h Copying file gnulib/lib/mktime.c Copying file gnulib/lib/msvc-inval.c Copying file gnulib/lib/msvc-inval.h Copying file gnulib/lib/msvc-nothrow.c Copying file gnulib/lib/msvc-nothrow.h Copying file gnulib/lib/net_if.in.h Copying file gnulib/lib/netdb.in.h Copying file gnulib/lib/netinet_in.in.h Copying file gnulib/lib/nl_langinfo.c Copying file gnulib/lib/nonblocking.c Copying file gnulib/lib/nonblocking.h Copying file gnulib/lib/open.c Copying file gnulib/lib/openpty.c Copying file gnulib/lib/passfd.c Copying file gnulib/lib/passfd.h Copying file gnulib/lib/pathmax.h Copying file gnulib/lib/perror.c Copying file gnulib/lib/physmem.c Copying file gnulib/lib/physmem.h Copying file gnulib/lib/pipe.c Copying file gnulib/lib/pipe2.c Copying file gnulib/lib/poll.c Copying file gnulib/lib/poll.in.h Copying file gnulib/lib/posix_openpt.c Copying file gnulib/lib/printf-args.c Copying file gnulib/lib/printf-args.h Copying file gnulib/lib/printf-parse.c Copying file gnulib/lib/printf-parse.h Copying file gnulib/lib/pthread.c Copying file gnulib/lib/pthread.in.h Copying file gnulib/lib/pthread_sigmask.c Copying file gnulib/lib/pty.in.h Copying file gnulib/lib/raise.c Copying file gnulib/lib/rawmemchr.c Copying file gnulib/lib/rawmemchr.valgrind Copying file gnulib/lib/readlink.c Copying file gnulib/lib/realloc.c Copying file gnulib/lib/recv.c Copying file gnulib/lib/regcomp.c Copying file gnulib/lib/regex.c Copying file gnulib/lib/regex.h Copying file gnulib/lib/regex_internal.c Copying file gnulib/lib/regex_internal.h Copying file gnulib/lib/regexec.c Copying file gnulib/lib/sched.in.h Copying file gnulib/lib/secure_getenv.c Copying file gnulib/lib/select.c Copying file gnulib/lib/send.c Copying file gnulib/lib/setenv.c Copying file gnulib/lib/setsockopt.c Copying file gnulib/lib/sig-handler.c Copying file gnulib/lib/sig-handler.h Copying file gnulib/lib/sigaction.c Copying file gnulib/lib/signal.in.h Copying file gnulib/lib/sigprocmask.c Copying file gnulib/lib/size_max.h Copying file gnulib/lib/sleep.c Copying file gnulib/lib/snprintf.c Copying file gnulib/lib/socket.c Copying file gnulib/lib/sockets.c Copying file gnulib/lib/sockets.h Copying file gnulib/lib/stat-time.c Copying file gnulib/lib/stat-time.h Copying file gnulib/lib/stat-w32.c Copying file gnulib/lib/stat-w32.h Copying file gnulib/lib/stat.c Copying file gnulib/lib/stdalign.in.h Copying file gnulib/lib/stdarg.in.h Copying file gnulib/lib/stdbool.in.h Copying file gnulib/lib/stddef.in.h Copying file gnulib/lib/stdint.in.h Copying file gnulib/lib/stdio-impl.h Copying file gnulib/lib/stdio-read.c Copying file gnulib/lib/stdio-write.c Copying file gnulib/lib/stdio.in.h Copying file gnulib/lib/stdlib.in.h Copying file gnulib/lib/stpcpy.c Copying file gnulib/lib/str-two-way.h Copying file gnulib/lib/strcasecmp.c Copying file gnulib/lib/strchrnul.c Copying file gnulib/lib/strchrnul.valgrind Copying file gnulib/lib/strdup.c Copying file gnulib/lib/streq.h Copying file gnulib/lib/strerror-override.c Copying file gnulib/lib/strerror-override.h Copying file gnulib/lib/strerror.c Copying file gnulib/lib/strerror_r.c Copying file gnulib/lib/string.in.h Copying file gnulib/lib/strings.in.h Copying file gnulib/lib/stripslash.c Copying file gnulib/lib/strncasecmp.c Copying file gnulib/lib/strndup.c Copying file gnulib/lib/strnlen.c Copying file gnulib/lib/strnlen1.c Copying file gnulib/lib/strnlen1.h Copying file gnulib/lib/strptime.c Copying file gnulib/lib/strsep.c Copying file gnulib/lib/strtok_r.c Copying file gnulib/lib/sys_ioctl.in.h Copying file gnulib/lib/sys_select.in.h Copying file gnulib/lib/sys_socket.c Copying file gnulib/lib/sys_socket.in.h Copying file gnulib/lib/sys_stat.in.h Copying file gnulib/lib/sys_time.in.h Copying file gnulib/lib/sys_types.in.h Copying file gnulib/lib/sys_uio.in.h Copying file gnulib/lib/sys_utsname.in.h Copying file gnulib/lib/sys_wait.in.h Copying file gnulib/lib/tempname.c Copying file gnulib/lib/tempname.h Copying file gnulib/lib/termios.in.h Copying file gnulib/lib/time.in.h Copying file gnulib/lib/time_r.c Copying file gnulib/lib/timegm.c Copying file gnulib/lib/ttyname_r.c Copying file gnulib/lib/uname.c Copying file gnulib/lib/unistd.c Copying file gnulib/lib/unistd.in.h Copying file gnulib/lib/unitypes.in.h Copying file gnulib/lib/uniwidth.in.h Copying file gnulib/lib/uniwidth/cjk.h Copying file gnulib/lib/uniwidth/width.c Copying file gnulib/lib/unsetenv.c Copying file gnulib/lib/unused-parameter.h Copying file gnulib/lib/usleep.c Copying file gnulib/lib/vasnprintf.c Copying file gnulib/lib/vasnprintf.h Copying file gnulib/lib/vasprintf.c Copying file gnulib/lib/verify.h Copying file gnulib/lib/vsnprintf.c Copying file gnulib/lib/w32sock.h Copying file gnulib/lib/waitpid.c Copying file gnulib/lib/warn-on-use.h Copying file gnulib/lib/wchar.in.h Copying file gnulib/lib/wcrtomb.c Copying file gnulib/lib/wctype-h.c Copying file gnulib/lib/wctype.in.h Copying file gnulib/lib/wcwidth.c Copying file gnulib/lib/xalloc-oversized.h Copying file gnulib/lib/xsize.c Copying file gnulib/lib/xsize.h Copying file gnulib/tests/_Noreturn.h Copying file gnulib/tests/arg-nonnull.h Copying file gnulib/tests/c++defs.h Copying file gnulib/tests/ctype.in.h Copying file gnulib/tests/dup.c Copying file gnulib/tests/error.c Copying file gnulib/tests/error.h Copying file gnulib/tests/exitfail.c Copying file gnulib/tests/exitfail.h Copying file gnulib/tests/fatal-signal.c Copying file gnulib/tests/fatal-signal.h Copying file gnulib/tests/fdopen.c Copying file gnulib/tests/float+.h Copying file gnulib/tests/fpucw.h Copying file gnulib/tests/ftruncate.c Copying file gnulib/tests/getpagesize.c Copying file gnulib/tests/getprogname.c Copying file gnulib/tests/getprogname.h Copying file gnulib/tests/getsockopt.c Copying file gnulib/tests/glthread/thread.c Copying file gnulib/tests/glthread/thread.h Copying file gnulib/tests/grantpt.c Copying file gnulib/tests/infinity.h Copying file gnulib/tests/init.sh Copying file gnulib/tests/inttypes.in.h Copying file gnulib/tests/isblank.c Copying file gnulib/tests/isnan.c Copying file gnulib/tests/isnand-nolibm.h Copying file gnulib/tests/isnand.c Copying file gnulib/tests/isnanf-nolibm.h Copying file gnulib/tests/isnanf.c Copying file gnulib/tests/isnanl-nolibm.h Copying file gnulib/tests/isnanl.c Copying file gnulib/tests/localename-table.c Copying file gnulib/tests/localename-table.h Copying file gnulib/tests/localename.c Copying file gnulib/tests/localename.h Copying file gnulib/tests/macros.h Copying file gnulib/tests/math.c Copying file gnulib/tests/math.in.h Copying file gnulib/tests/minus-zero.h Copying file gnulib/tests/nan.h Copying file gnulib/tests/nanosleep.c Copying file gnulib/tests/nap.h Copying file gnulib/tests/null-ptr.h Copying file gnulib/tests/ptsname.c Copying file gnulib/tests/ptsname_r.c Copying file gnulib/tests/pty-private.h Copying file gnulib/tests/putenv.c Copying file gnulib/tests/randomd.c Copying file gnulib/tests/read.c Copying file gnulib/tests/same-inode.h Copying file gnulib/tests/setlocale.c Copying file gnulib/tests/signature.h Copying file gnulib/tests/signbitd.c Copying file gnulib/tests/signbitf.c Copying file gnulib/tests/signbitl.c Copying file gnulib/tests/socket-client.h Copying file gnulib/tests/socket-server.h Copying file gnulib/tests/spawn.in.h Copying file gnulib/tests/spawn_faction_addclose.c Copying file gnulib/tests/spawn_faction_adddup2.c Copying file gnulib/tests/spawn_faction_addopen.c Copying file gnulib/tests/spawn_faction_destroy.c Copying file gnulib/tests/spawn_faction_init.c Copying file gnulib/tests/spawn_int.h Copying file gnulib/tests/spawnattr_destroy.c Copying file gnulib/tests/spawnattr_init.c Copying file gnulib/tests/spawnattr_setflags.c Copying file gnulib/tests/spawnattr_setsigmask.c Copying file gnulib/tests/spawni.c Copying file gnulib/tests/spawnp.c Copying file gnulib/tests/symlink.c Copying file gnulib/tests/test-accept.c Copying file gnulib/tests/test-alloca-opt.c Copying file gnulib/tests/test-areadlink.c Copying file gnulib/tests/test-areadlink.h Copying file gnulib/tests/test-arpa_inet.c Copying file gnulib/tests/test-base64.c Copying file gnulib/tests/test-binary-io.c Copying file gnulib/tests/test-binary-io.sh Copying file gnulib/tests/test-bind.c Copying file gnulib/tests/test-bitrotate.c Copying file gnulib/tests/test-btowc.c Copying file gnulib/tests/test-btowc1.sh Copying file gnulib/tests/test-btowc2.sh Copying file gnulib/tests/test-byteswap.c Copying file gnulib/tests/test-c-ctype.c Copying file gnulib/tests/test-c-strcase.sh Copying file gnulib/tests/test-c-strcasecmp.c Copying file gnulib/tests/test-c-strcasestr.c Copying file gnulib/tests/test-c-strncasecmp.c Copying file gnulib/tests/test-canonicalize-lgpl.c Copying file gnulib/tests/test-chown.c Copying file gnulib/tests/test-chown.h Copying file gnulib/tests/test-cloexec.c Copying file gnulib/tests/test-close.c Copying file gnulib/tests/test-connect.c Copying file gnulib/tests/test-count-leading-zeros.c Copying file gnulib/tests/test-count-one-bits.c Copying file gnulib/tests/test-ctype.c Copying file gnulib/tests/test-dup.c Copying file gnulib/tests/test-dup2.c Copying file gnulib/tests/test-environ.c Copying file gnulib/tests/test-errno.c Copying file gnulib/tests/test-fclose.c Copying file gnulib/tests/test-fcntl-h.c Copying file gnulib/tests/test-fcntl.c Copying file gnulib/tests/test-fdatasync.c Copying file gnulib/tests/test-fdopen.c Copying file gnulib/tests/test-fflush.c Copying file gnulib/tests/test-fflush2.c Copying file gnulib/tests/test-fflush2.sh Copying file gnulib/tests/test-ffs.c Copying file gnulib/tests/test-ffsl.c Copying file gnulib/tests/test-fgetc.c Copying file gnulib/tests/test-float.c Copying file gnulib/tests/test-fnmatch-h.c Copying file gnulib/tests/test-fnmatch.c Copying file gnulib/tests/test-fpurge.c Copying file gnulib/tests/test-fputc.c Copying file gnulib/tests/test-fread.c Copying file gnulib/tests/test-freading.c Copying file gnulib/tests/test-fseek.c Copying file gnulib/tests/test-fseek.sh Copying file gnulib/tests/test-fseek2.sh Copying file gnulib/tests/test-fseeko.c Copying file gnulib/tests/test-fseeko.sh Copying file gnulib/tests/test-fseeko2.sh Copying file gnulib/tests/test-fseeko3.c Copying file gnulib/tests/test-fseeko3.sh Copying file gnulib/tests/test-fseeko4.c Copying file gnulib/tests/test-fseeko4.sh Copying file gnulib/tests/test-fstat.c Copying file gnulib/tests/test-fsync.c Copying file gnulib/tests/test-ftell.c Copying file gnulib/tests/test-ftell.sh Copying file gnulib/tests/test-ftell2.sh Copying file gnulib/tests/test-ftell3.c Copying file gnulib/tests/test-ftello.c Copying file gnulib/tests/test-ftello.sh Copying file gnulib/tests/test-ftello2.sh Copying file gnulib/tests/test-ftello3.c Copying file gnulib/tests/test-ftello4.c Copying file gnulib/tests/test-ftello4.sh Copying file gnulib/tests/test-ftruncate.c Copying file gnulib/tests/test-ftruncate.sh Copying file gnulib/tests/test-func.c Copying file gnulib/tests/test-fwrite.c Copying file gnulib/tests/test-getaddrinfo.c Copying file gnulib/tests/test-getcwd-lgpl.c Copying file gnulib/tests/test-getdelim.c Copying file gnulib/tests/test-getdtablesize.c Copying file gnulib/tests/test-getgroups.c Copying file gnulib/tests/test-gethostname.c Copying file gnulib/tests/test-getline.c Copying file gnulib/tests/test-getopt-main.h Copying file gnulib/tests/test-getopt-posix.c Copying file gnulib/tests/test-getopt.h Copying file gnulib/tests/test-getpeername.c Copying file gnulib/tests/test-getprogname.c Copying file gnulib/tests/test-getsockname.c Copying file gnulib/tests/test-getsockopt.c Copying file gnulib/tests/test-gettimeofday.c Copying file gnulib/tests/test-grantpt.c Copying file gnulib/tests/test-ignore-value.c Copying file gnulib/tests/test-inet_ntop.c Copying file gnulib/tests/test-inet_pton.c Copying file gnulib/tests/test-init.sh Copying file gnulib/tests/test-intprops.c Copying file gnulib/tests/test-inttypes.c Copying file gnulib/tests/test-ioctl.c Copying file gnulib/tests/test-isatty.c Copying file gnulib/tests/test-isblank.c Copying file gnulib/tests/test-isnand-nolibm.c Copying file gnulib/tests/test-isnand.h Copying file gnulib/tests/test-isnanf-nolibm.c Copying file gnulib/tests/test-isnanf.h Copying file gnulib/tests/test-isnanl-nolibm.c Copying file gnulib/tests/test-isnanl.h Copying file gnulib/tests/test-langinfo.c Copying file gnulib/tests/test-ldexp.c Copying file gnulib/tests/test-ldexp.h Copying file gnulib/tests/test-limits-h.c Copying file gnulib/tests/test-listen.c Copying file gnulib/tests/test-localcharset.c Copying file gnulib/tests/test-locale.c Copying file gnulib/tests/test-localeconv.c Copying file gnulib/tests/test-localename.c Copying file gnulib/tests/test-lseek.c Copying file gnulib/tests/test-lseek.sh Copying file gnulib/tests/test-lstat.c Copying file gnulib/tests/test-lstat.h Copying file gnulib/tests/test-malloca.c Copying file gnulib/tests/test-math.c Copying file gnulib/tests/test-mbrtowc-w32-1.sh Copying file gnulib/tests/test-mbrtowc-w32-2.sh Copying file gnulib/tests/test-mbrtowc-w32-3.sh Copying file gnulib/tests/test-mbrtowc-w32-4.sh Copying file gnulib/tests/test-mbrtowc-w32-5.sh Copying file gnulib/tests/test-mbrtowc-w32.c Copying file gnulib/tests/test-mbrtowc.c Copying file gnulib/tests/test-mbrtowc1.sh Copying file gnulib/tests/test-mbrtowc2.sh Copying file gnulib/tests/test-mbrtowc3.sh Copying file gnulib/tests/test-mbrtowc4.sh Copying file gnulib/tests/test-mbrtowc5.sh Copying file gnulib/tests/test-mbsinit.c Copying file gnulib/tests/test-mbsinit.sh Copying file gnulib/tests/test-mbsrtowcs.c Copying file gnulib/tests/test-mbsrtowcs1.sh Copying file gnulib/tests/test-mbsrtowcs2.sh Copying file gnulib/tests/test-mbsrtowcs3.sh Copying file gnulib/tests/test-mbsrtowcs4.sh Copying file gnulib/tests/test-memchr.c Copying file gnulib/tests/test-mkdir.c Copying file gnulib/tests/test-mkdir.h Copying file gnulib/tests/test-nanosleep.c Copying file gnulib/tests/test-net_if.c Copying file gnulib/tests/test-netdb.c Copying file gnulib/tests/test-netinet_in.c Copying file gnulib/tests/test-nl_langinfo.c Copying file gnulib/tests/test-nl_langinfo.sh Copying file gnulib/tests/test-nonblocking-misc.h Copying file gnulib/tests/test-nonblocking-pipe-child.c Copying file gnulib/tests/test-nonblocking-pipe-main.c Copying file gnulib/tests/test-nonblocking-pipe.h Copying file gnulib/tests/test-nonblocking-pipe.sh Copying file gnulib/tests/test-nonblocking-reader.h Copying file gnulib/tests/test-nonblocking-socket-child.c Copying file gnulib/tests/test-nonblocking-socket-main.c Copying file gnulib/tests/test-nonblocking-socket.h Copying file gnulib/tests/test-nonblocking-socket.sh Copying file gnulib/tests/test-nonblocking-writer.h Copying file gnulib/tests/test-nonblocking.c Copying file gnulib/tests/test-open.c Copying file gnulib/tests/test-open.h Copying file gnulib/tests/test-openpty.c Copying file gnulib/tests/test-passfd.c Copying file gnulib/tests/test-pathmax.c Copying file gnulib/tests/test-perror.c Copying file gnulib/tests/test-perror.sh Copying file gnulib/tests/test-perror2.c Copying file gnulib/tests/test-pipe.c Copying file gnulib/tests/test-pipe2.c Copying file gnulib/tests/test-poll-h.c Copying file gnulib/tests/test-poll.c Copying file gnulib/tests/test-posix_openpt.c Copying file gnulib/tests/test-posix_spawn1.c Copying file gnulib/tests/test-posix_spawn1.in.sh Copying file gnulib/tests/test-posix_spawn2.c Copying file gnulib/tests/test-posix_spawn2.in.sh Copying file gnulib/tests/test-posix_spawn_file_actions_addclose.c Copying file gnulib/tests/test-posix_spawn_file_actions_adddup2.c Copying file gnulib/tests/test-posix_spawn_file_actions_addopen.c Copying file gnulib/tests/test-pthread_sigmask1.c Copying file gnulib/tests/test-pthread_sigmask2.c Copying file gnulib/tests/test-ptsname.c Copying file gnulib/tests/test-ptsname_r.c Copying file gnulib/tests/test-raise.c Copying file gnulib/tests/test-rawmemchr.c Copying file gnulib/tests/test-read.c Copying file gnulib/tests/test-readlink.c Copying file gnulib/tests/test-readlink.h Copying file gnulib/tests/test-recv.c Copying file gnulib/tests/test-regex.c Copying file gnulib/tests/test-sched.c Copying file gnulib/tests/test-select-fd.c Copying file gnulib/tests/test-select-in.sh Copying file gnulib/tests/test-select-out.sh Copying file gnulib/tests/test-select-stdin.c Copying file gnulib/tests/test-select.c Copying file gnulib/tests/test-select.h Copying file gnulib/tests/test-send.c Copying file gnulib/tests/test-setenv.c Copying file gnulib/tests/test-setlocale1.c Copying file gnulib/tests/test-setlocale1.sh Copying file gnulib/tests/test-setlocale2.c Copying file gnulib/tests/test-setlocale2.sh Copying file gnulib/tests/test-setsockopt.c Copying file gnulib/tests/test-sigaction.c Copying file gnulib/tests/test-signal-h.c Copying file gnulib/tests/test-signbit.c Copying file gnulib/tests/test-sigpipe.c Copying file gnulib/tests/test-sigpipe.sh Copying file gnulib/tests/test-sigprocmask.c Copying file gnulib/tests/test-sleep.c Copying file gnulib/tests/test-snprintf.c Copying file gnulib/tests/test-sockets.c Copying file gnulib/tests/test-spawn.c Copying file gnulib/tests/test-stat-time.c Copying file gnulib/tests/test-stat.c Copying file gnulib/tests/test-stat.h Copying file gnulib/tests/test-stdalign.c Copying file gnulib/tests/test-stdbool.c Copying file gnulib/tests/test-stddef.c Copying file gnulib/tests/test-stdint.c Copying file gnulib/tests/test-stdio.c Copying file gnulib/tests/test-stdlib.c Copying file gnulib/tests/test-strchrnul.c Copying file gnulib/tests/test-strerror.c Copying file gnulib/tests/test-strerror_r.c Copying file gnulib/tests/test-string.c Copying file gnulib/tests/test-strings.c Copying file gnulib/tests/test-strnlen.c Copying file gnulib/tests/test-symlink.c Copying file gnulib/tests/test-symlink.h Copying file gnulib/tests/test-sys_ioctl.c Copying file gnulib/tests/test-sys_select.c Copying file gnulib/tests/test-sys_socket.c Copying file gnulib/tests/test-sys_stat.c Copying file gnulib/tests/test-sys_time.c Copying file gnulib/tests/test-sys_types.c Copying file gnulib/tests/test-sys_uio.c Copying file gnulib/tests/test-sys_utsname.c Copying file gnulib/tests/test-sys_wait.c Copying file gnulib/tests/test-sys_wait.h Copying file gnulib/tests/test-termios.c Copying file gnulib/tests/test-thread_create.c Copying file gnulib/tests/test-thread_self.c Copying file gnulib/tests/test-time.c Copying file gnulib/tests/test-ttyname_r.c Copying file gnulib/tests/test-uname.c Copying file gnulib/tests/test-unistd.c Copying file gnulib/tests/test-unlockpt.c Copying file gnulib/tests/test-unsetenv.c Copying file gnulib/tests/test-usleep.c Copying file gnulib/tests/test-vasnprintf.c Copying file gnulib/tests/test-vasprintf.c Copying file gnulib/tests/test-vc-list-files-cvs.sh Copying file gnulib/tests/test-vc-list-files-git.sh Copying file gnulib/tests/test-verify-try.c Copying file gnulib/tests/test-verify.c Copying file gnulib/tests/test-verify.sh Copying file gnulib/tests/test-vsnprintf.c Copying file gnulib/tests/test-wchar.c Copying file gnulib/tests/test-wcrtomb-w32-1.sh Copying file gnulib/tests/test-wcrtomb-w32-2.sh Copying file gnulib/tests/test-wcrtomb-w32-3.sh Copying file gnulib/tests/test-wcrtomb-w32-4.sh Copying file gnulib/tests/test-wcrtomb-w32-5.sh Copying file gnulib/tests/test-wcrtomb-w32.c Copying file gnulib/tests/test-wcrtomb.c Copying file gnulib/tests/test-wcrtomb.sh Copying file gnulib/tests/test-wctype-h.c Copying file gnulib/tests/test-wcwidth.c Copying file gnulib/tests/test-write.c Copying file gnulib/tests/test-xalloc-die.c Copying file gnulib/tests/test-xalloc-die.sh Copying file gnulib/tests/uniwidth/test-uc_width.c Copying file gnulib/tests/uniwidth/test-uc_width2.c Copying file gnulib/tests/uniwidth/test-uc_width2.sh Copying file gnulib/tests/unlockpt.c Copying file gnulib/tests/unused-parameter.h Copying file gnulib/tests/w32sock.h Copying file gnulib/tests/wait-process.c Copying file gnulib/tests/wait-process.h Copying file gnulib/tests/warn-on-use.h Copying file gnulib/tests/wctob.c Copying file gnulib/tests/wctomb-impl.h Copying file gnulib/tests/wctomb.c Copying file gnulib/tests/write.c Copying file gnulib/tests/xalloc-die.c Copying file gnulib/tests/xalloc.h Copying file gnulib/tests/xmalloc.c Copying file gnulib/tests/zerosize-ptr.h Copying file m4/00gnulib.m4 Copying file m4/__inline.m4 Copying file m4/absolute-header.m4 Copying file m4/alloca.m4 Copying file m4/arpa_inet_h.m4 Copying file m4/asm-underscore.m4 Copying file m4/autobuild.m4 Copying file m4/base64.m4 Copying file m4/btowc.m4 Copying file m4/builtin-expect.m4 Copying file m4/byteswap.m4 Copying file m4/calloc.m4 Copying file m4/canonicalize.m4 Copying file m4/chown.m4 Copying file m4/clock_time.m4 Copying file m4/close.m4 Copying file m4/codeset.m4 Copying file m4/configmake.m4 Copying file m4/count-leading-zeros.m4 Copying file m4/count-one-bits.m4 Copying file m4/ctype.m4 Copying file m4/dirname.m4 Copying file m4/double-slash-root.m4 Copying file m4/dup.m4 Copying file m4/dup2.m4 Copying file m4/eealloc.m4 Copying file m4/environ.m4 Copying file m4/errno_h.m4 Copying file m4/error.m4 Copying file m4/execinfo.m4 Copying file m4/exponentd.m4 Copying file m4/exponentf.m4 Copying file m4/exponentl.m4 Copying file m4/extensions.m4 Copying file m4/extern-inline.m4 Copying file m4/fatal-signal.m4 Copying file m4/fclose.m4 Copying file m4/fcntl-o.m4 Copying file m4/fcntl.m4 Copying file m4/fcntl_h.m4 Copying file m4/fdatasync.m4 Copying file m4/fdopen.m4 Copying file m4/fflush.m4 Copying file m4/ffs.m4 Copying file m4/ffsl.m4 Copying file m4/flexmember.m4 Copying file m4/float_h.m4 Copying file m4/fnmatch.m4 Copying file m4/fnmatch_h.m4 Copying file m4/fpieee.m4 Copying file m4/fpurge.m4 Copying file m4/freading.m4 Copying file m4/fseek.m4 Copying file m4/fseeko.m4 Copying file m4/fstat.m4 Copying file m4/fsync.m4 Copying file m4/ftell.m4 Copying file m4/ftello.m4 Copying file m4/ftruncate.m4 Copying file m4/func.m4 Copying file m4/getaddrinfo.m4 Copying file m4/getcwd.m4 Copying file m4/getdelim.m4 Copying file m4/getdtablesize.m4 Copying file m4/getgroups.m4 Copying file m4/gethostname.m4 Copying file m4/getline.m4 Copying file m4/getopt.m4 Copying file m4/getpagesize.m4 Copying file m4/getpass.m4 Copying file m4/getprogname.m4 Copying file m4/gettimeofday.m4 Copying file m4/getugroups.m4 Copying file m4/glibc21.m4 Copying file m4/gnulib-common.m4 Copying file m4/gnulib-tool.m4 Copying file m4/grantpt.m4 Copying file m4/host-cpu-c-abi.m4 Copying file m4/hostent.m4 Copying file m4/include_next.m4 Copying file m4/inet_ntop.m4 Copying file m4/inet_pton.m4 Copying file m4/intl-thread-locale.m4 Copying file m4/intlmacosx.m4 Copying file m4/intmax_t.m4 Copying file m4/inttypes-pri.m4 Copying file m4/inttypes.m4 Copying file m4/inttypes_h.m4 Copying file m4/ioctl.m4 Copying file m4/isatty.m4 Copying file m4/isblank.m4 Copying file m4/isnand.m4 Copying file m4/isnanf.m4 Copying file m4/isnanl.m4 Copying file m4/langinfo_h.m4 Copying file m4/largefile.m4 Copying file m4/lcmessage.m4 Copying file m4/ldexp.m4 Copying file m4/lib-ld.m4 Copying file m4/lib-link.m4 Copying file m4/lib-prefix.m4 Copying file m4/libunistring-base.m4 Copying file m4/limits-h.m4 Copying file m4/localcharset.m4 Copying file m4/locale-fr.m4 Copying file m4/locale-ja.m4 Copying file m4/locale-tr.m4 Copying file m4/locale-zh.m4 Copying file m4/locale_h.m4 Copying file m4/localeconv.m4 Copying file m4/localename.m4 Copying file m4/localtime-buffer.m4 Copying file m4/lock.m4 Copying file m4/longlong.m4 Copying file m4/lseek.m4 Copying file m4/lstat.m4 Copying file m4/malloc.m4 Copying file m4/malloca.m4 Copying file m4/manywarnings-c++.m4 Copying file m4/manywarnings.m4 Copying file m4/math_h.m4 Copying file m4/mbrtowc.m4 Copying file m4/mbsinit.m4 Copying file m4/mbsrtowcs.m4 Copying file m4/mbstate_t.m4 Copying file m4/mbtowc.m4 Copying file m4/memchr.m4 Copying file m4/mgetgroups.m4 Copying file m4/mkdir.m4 Copying file m4/mkdtemp.m4 Copying file m4/mkostemp.m4 Copying file m4/mkostemps.m4 Copying file m4/mktime.m4 Copying file m4/mmap-anon.m4 Copying file m4/mode_t.m4 Copying file m4/msvc-inval.m4 Copying file m4/msvc-nothrow.m4 Copying file m4/multiarch.m4 Copying file m4/nanosleep.m4 Copying file m4/net_if_h.m4 Copying file m4/netdb_h.m4 Copying file m4/netinet_in_h.m4 Copying file m4/nl_langinfo.m4 Copying file m4/nocrash.m4 Copying file m4/nonblocking.m4 Copying file m4/off_t.m4 Copying file m4/open-cloexec.m4 Copying file m4/open.m4 Copying file m4/passfd.m4 Copying file m4/pathmax.m4 Copying file m4/perror.m4 Copying file m4/physmem.m4 Copying file m4/pipe.m4 Copying file m4/pipe2.m4 Copying file m4/poll.m4 Copying file m4/poll_h.m4 Copying file m4/posix-shell.m4 Copying file m4/posix_openpt.m4 Copying file m4/posix_spawn.m4 Copying file m4/printf.m4 Copying file m4/pthread.m4 Copying file m4/pthread_rwlock_rdlock.m4 Copying file m4/pthread_sigmask.m4 Copying file m4/ptsname.m4 Copying file m4/ptsname_r.m4 Copying file m4/pty.m4 Copying file m4/pty_h.m4 Copying file m4/putenv.m4 Copying file m4/raise.m4 Copying file m4/rawmemchr.m4 Copying file m4/read.m4 Copying file m4/readlink.m4 Copying file m4/realloc.m4 Copying file m4/regex.m4 Copying file m4/sched_h.m4 Copying file m4/secure_getenv.m4 Copying file m4/select.m4 Copying file m4/servent.m4 Copying file m4/setenv.m4 Copying file m4/setlocale.m4 Copying file m4/sh-filename.m4 Copying file m4/sig_atomic_t.m4 Copying file m4/sigaction.m4 Copying file m4/signal_h.m4 Copying file m4/signalblocking.m4 Copying file m4/signbit.m4 Copying file m4/sigpipe.m4 Copying file m4/size_max.m4 Copying file m4/sleep.m4 Copying file m4/snprintf.m4 Copying file m4/socketlib.m4 Copying file m4/sockets.m4 Copying file m4/socklen.m4 Copying file m4/sockpfaf.m4 Copying file m4/spawn_h.m4 Copying file m4/ssize_t.m4 Copying file m4/stat-time.m4 Copying file m4/stat.m4 Copying file m4/stdalign.m4 Copying file m4/stdarg.m4 Copying file m4/stdbool.m4 Copying file m4/stddef_h.m4 Copying file m4/stdint.m4 Copying file m4/stdint_h.m4 Copying file m4/stdio_h.m4 Copying file m4/stdlib_h.m4 Copying file m4/stpcpy.m4 Copying file m4/strcase.m4 Copying file m4/strchrnul.m4 Copying file m4/strdup.m4 Copying file m4/strerror.m4 Copying file m4/strerror_r.m4 Copying file m4/string_h.m4 Copying file m4/strings_h.m4 Copying file m4/strndup.m4 Copying file m4/strnlen.m4 Copying file m4/strptime.m4 Copying file m4/strsep.m4 Copying file m4/strtok_r.m4 Copying file m4/symlink.m4 Copying file m4/sys_ioctl_h.m4 Copying file m4/sys_select_h.m4 Copying file m4/sys_socket_h.m4 Copying file m4/sys_stat_h.m4 Copying file m4/sys_time_h.m4 Copying file m4/sys_types_h.m4 Copying file m4/sys_uio_h.m4 Copying file m4/sys_utsname_h.m4 Copying file m4/sys_wait_h.m4 Copying file m4/tempname.m4 Copying file m4/termios_h.m4 Copying file m4/thread.m4 Copying file m4/threadlib.m4 Copying file m4/time_h.m4 Copying file m4/time_r.m4 Copying file m4/timegm.m4 Copying file m4/tm_gmtoff.m4 Copying file m4/ttyname_r.m4 Copying file m4/uname.m4 Copying file m4/ungetc.m4 Copying file m4/unistd_h.m4 Copying file m4/unlockpt.m4 Copying file m4/usleep.m4 Copying file m4/vasnprintf.m4 Copying file m4/vasprintf.m4 Copying file m4/vsnprintf.m4 Copying file m4/wait-process.m4 Copying file m4/waitpid.m4 Copying file m4/warn-on-use.m4 Copying file m4/warnings.m4 Copying file m4/wchar_h.m4 Copying file m4/wchar_t.m4 Copying file m4/wcrtomb.m4 Copying file m4/wctob.m4 Copying file m4/wctomb.m4 Copying file m4/wctype_h.m4 Copying file m4/wcwidth.m4 Copying file m4/wint_t.m4 Copying file m4/write.m4 Copying file m4/xalloc.m4 Copying file m4/xsize.m4 Copying file maint.mk Creating gnulib/lib/gnulib.mk Creating m4/gnulib-cache.m4 Creating m4/gnulib-comp.m4 Creating gnulib/tests/gnulib.mk Updating ./build-aux/.gitignore (backup in ./build-aux/.gitignore~) Creating ./gnulib/lib/.gitignore Creating ./gnulib/lib/glthread/.gitignore Creating ./gnulib/lib/uniwidth/.gitignore Creating ./gnulib/tests/.gitignore Creating ./gnulib/tests/glthread/.gitignore Creating ./gnulib/tests/uniwidth/.gitignore Updating ./m4/.gitignore (backup in ./m4/.gitignore~) Finished. You may need to add #include directives for the following .h files. #include <arpa/inet.h> #include <byteswap.h> #include <execinfo.h> #include <fcntl.h> #include <fnmatch.h> #include <locale.h> #include <math.h> #include <net/if.h> #include <netdb.h> #include <poll.h> #include <pthread.h> #include <pty.h> #include <regex.h> #include <sched.h> #include <signal.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/utsname.h> #include <sys/wait.h> #include <termios.h> #include <time.h> #include <unistd,h> #include <unistd.h> #include <wchar.h> /* Include only after all system include files. */ #include "areadlink.h" #include "base64.h" #include "bitrotate.h" #include "c-ctype.h" #include "c-strcase.h" #include "c-strcasestr.h" #include "configmake.h" #include "count-leading-zeros.h" #include "count-one-bits.h" #include "dirname.h" #include "ignore-value.h" #include "intprops.h" #include "mgetgroups.h" #include "nonblocking.h" #include "passfd.h" #include "physmem.h" #include "stat-time.h" #include "verify.h" You may need to use the following Makefile variables when linking. Use them in <program>_LDADD when linking a program, or in <library>_a_LDFLAGS or <library>_la_LDFLAGS when linking a library. $(GETADDRINFO_LIB) $(GETHOSTNAME_LIB) $(HOSTENT_LIB) $(INET_NTOP_LIB) $(INET_PTON_LIB) $(LDEXP_LIBM) $(LIBSOCKET) $(LIB_CLOCK_GETTIME) $(LIB_EXECINFO) $(LIB_FDATASYNC) $(LIB_POLL) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) $(LIB_SELECT) $(LTLIBINTL) when linking with libtool, $(LIBINTL) otherwise $(LTLIBTHREAD) when linking with libtool, $(LIBTHREAD) otherwise $(PTY_LIB) $(SERVENT_LIB) Don't forget to - "include gnulib.mk" from within "gnulib/lib/Makefile.am", - "include gnulib.mk" from within "gnulib/tests/Makefile.am", - mention "-I m4" in ACLOCAL_AMFLAGS in Makefile.am, - mention "m4/gnulib-cache.m4" in EXTRA_DIST in Makefile.am, - invoke gl_EARLY in ./configure.ac, right after AC_PROG_CC, - invoke gl_INIT in ./configure.ac. running: AUTOPOINT=true LIBTOOLIZE=true autoreconf --verbose --install --force -I m4 --no-recursive autoreconf: Entering directory `.' autoreconf: configure.ac: not using Gettext autoreconf: running: aclocal -I m4 --force -I m4 autoreconf: configure.ac: tracing autoreconf: running: true --copy --force autoreconf: running: /usr/bin/autoconf --include=m4 --force autoreconf: running: /usr/bin/autoheader --include=m4 --force autoreconf: running: automake --add-missing --copy --force-missing configure.ac:126: installing 'build-aux/compile' configure.ac:27: installing 'build-aux/missing' Makefile.am: installing './INSTALL' examples/Makefile.am: installing 'build-aux/depcomp' parallel-tests: installing 'build-aux/test-driver' autoreconf: Leaving directory `.' ./bootstrap: ln -fs ../.gnulib/build-aux/install-sh build-aux/install-sh ./bootstrap: ln -fs ../.gnulib/build-aux/depcomp build-aux/depcomp ./bootstrap: ln -fs ../.gnulib/build-aux/config.guess build-aux/config.guess ./bootstrap: ln -fs ../.gnulib/build-aux/config.sub build-aux/config.sub ./bootstrap: ln -fs .gnulib/doc/INSTALL INSTALL ./bootstrap: done. Now you can run './configure'. I am going to run configure with no arguments - if you wish to pass any to it, please specify them on the ./autogen.sh command line. checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking for a thread-safe mkdir -p... /usr/bin/mkdir -p checking for gawk... gawk checking whether make sets $(MAKE)... yes checking whether make supports nested variables... yes checking how to create a pax tar archive... gnutar checking whether make supports nested variables... (cached) yes checking build system type... x86_64-pc-linux-gnu checking host system type... x86_64-pc-linux-gnu checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.out checking for suffix of executables... checking whether we are cross compiling... no checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed checking for style of include used by make... GNU checking dependency style of gcc... gcc3 checking how to run the C preprocessor... gcc -E checking for grep that handles long lines and -e... /usr/bin/grep checking for egrep... /usr/bin/grep -E checking for ANSI C header files... yes checking for sys/types.h... yes checking for sys/stat.h... yes checking for stdlib.h... yes checking for string.h... yes checking for memory.h... yes checking for strings.h... yes checking for inttypes.h... yes checking for stdint.h... yes checking for unistd.h... yes checking minix/config.h usability... no checking minix/config.h presence... no checking for minix/config.h... no checking whether it is safe to define __EXTENSIONS__... yes checking whether _XOPEN_SOURCE should be defined... no checking for Minix Amsterdam compiler... no checking for ar... ar checking for ranlib... ranlib checking whether gcc and cc understand -c and -o together... yes checking for _LARGEFILE_SOURCE value needed for large files... no checking for special C compiler options needed for large files... no checking for _FILE_OFFSET_BITS value needed for large files... no checking for gcc option to accept ISO C99... -std=gnu99 checking for gcc -std=gnu99 option to accept ISO Standard C... (cached) -std=gnu99 configure: autobuild project... libvirt configure: autobuild revision... v2.1.0-rc1-7924-g6ff9157 configure: autobuild hostname... virtlab205.virt.lab.eng.bos.redhat.com configure: autobuild timestamp... 20190102T041253Z checking for sys/socket.h... yes checking for arpa/inet.h... yes checking for features.h... yes checking for sys/param.h... yes checking for unistd.h... (cached) yes checking for execinfo.h... yes checking for fnmatch.h... yes checking for wctype.h... yes checking for sys/stat.h... (cached) yes checking for netdb.h... yes checking for netinet/in.h... yes checking for getopt.h... yes checking for sys/cdefs.h... yes checking for stdio_ext.h... yes checking for termios.h... yes checking for sys/time.h... yes checking for grp.h... yes checking for langinfo.h... yes checking for limits.h... yes checking for xlocale.h... yes checking for sys/mman.h... yes checking for pty.h... yes checking for poll.h... yes checking for sys/ioctl.h... yes checking for sys/filio.h... no checking for pthread.h... yes checking for malloc.h... yes checking for sys/select.h... yes checking for wchar.h... yes checking for stdint.h... (cached) yes checking for strings.h... (cached) yes checking for sys/uio.h... yes checking for sys/utsname.h... yes checking for sys/wait.h... yes checking for crtdefs.h... no checking for inttypes.h... (cached) yes checking for math.h... yes checking for sys/types.h... (cached) yes checking for spawn.h... yes checking whether the preprocessor supports include_next... yes checking whether system header files limit the line length... no checking whether <sys/socket.h> is self-contained... yes checking for shutdown... yes checking whether <sys/socket.h> defines the SHUT_* macros... yes checking for struct sockaddr_storage... yes checking for sa_family_t... yes checking for struct sockaddr_storage.ss_family... yes checking for size_t... yes checking for working alloca.h... yes checking for alloca... yes checking for C/C++ restrict keyword... __restrict checking whether <wchar.h> uses 'inline' correctly... yes checking for btowc... yes checking for canonicalize_file_name... yes checking for getcwd... yes checking for readlink... yes checking for realpath... yes checking for readlinkat... yes checking for chown... yes checking for fchown... yes checking for _set_invalid_parameter_handler... no checking for fcntl... yes checking for symlink... yes checking for ffsl... yes checking for fnmatch... yes checking for isblank... yes checking for iswctype... yes checking for mbsrtowcs... yes checking for mempcpy... yes checking for wmemchr... yes checking for wmemcpy... yes checking for wmempcpy... yes checking for fpurge... no checking for __fpurge... yes checking for __freading... yes checking for fsync... yes checking for getdelim... yes checking for getdtablesize... yes checking for getpass... yes checking for __fsetlocking... yes checking for gettimeofday... yes checking for lstat... yes checking for mbsinit... yes checking for mbrtowc... yes checking for mprotect... yes checking for getgrouplist... yes checking for mkostemp... yes checking for mkostemps... yes checking for tzset... yes checking for nl_langinfo... yes checking for recvmsg... yes checking for sendmsg... yes checking for strerror_r... yes checking for __xpg_strerror_r... yes checking for pipe... yes checking for pipe2... yes checking for posix_openpt... yes checking for pthread_sigmask... no checking for secure_getenv... yes checking for getuid... yes checking for geteuid... yes checking for getgid... yes checking for getegid... yes checking for setenv... yes checking for sigaction... yes checking for sigaltstack... yes checking for siginterrupt... yes checking for sleep... yes checking for snprintf... yes checking for strdup... yes checking for catgets... yes checking for strndup... yes checking for strptime... yes checking for localtime_r... yes checking for timegm... yes checking for usleep... yes checking for vasnprintf... no checking for wcrtomb... yes checking for iswcntrl... yes checking for wcwidth... yes checking for ftruncate... yes checking for getprogname... no checking for getexecname... no checking for newlocale... yes checking for uselocale... yes checking for duplocale... yes checking for freelocale... yes checking for socketpair... yes checking for ptsname_r... yes checking for shutdown... (cached) yes checking for wctob... yes checking for cfmakeraw... yes checking for fallocate... yes checking for getifaddrs... yes checking for getmntent_r... yes checking for getpwuid_r... yes checking for getrlimit... yes checking for if_indextoname... yes checking for mmap... yes checking for posix_fallocate... yes checking for posix_memalign... yes checking for prlimit... yes checking for sched_getaffinity... yes checking for sched_setscheduler... yes checking for setgroups... yes checking for setns... yes checking for setrlimit... yes checking for sysctlbyname... no checking for unshare... yes checking for nl_langinfo and CODESET... yes checking for a traditional french locale... fr_FR checking whether malloc, realloc, calloc are POSIX compliant... yes checking whether // is distinct from /... no checking whether realpath works... yes checking for uid_t in sys/types.h... yes checking for unistd.h... (cached) yes checking for working chown... yes checking whether chown dereferences symlinks... yes checking whether chown honors trailing slash... yes checking whether chown always updates ctime... yes checking for unsigned long long int... yes checking if environ is properly declared... yes checking for complete errno.h... yes checking for working fcntl.h... yes checking for pid_t... yes checking for mode_t... yes checking whether fdatasync is declared... yes checking for mbstate_t... yes checking whether stdin defaults to large file offsets... yes checking whether fseeko is declared... yes checking for fseeko... yes checking whether fflush works on input streams... no checking whether stat file-mode macros are broken... no checking for nlink_t... yes checking whether ftello is declared... yes checking for ftello... yes checking whether ftello works... yes checking for library containing gethostbyname... none required checking for gethostbyname... yes checking for library containing getservbyname... none required checking for getservbyname... yes checking for library containing inet_ntop... none required checking whether inet_ntop is declared... yes checking for IPv4 sockets... yes checking for IPv6 sockets... yes checking whether getcwd (NULL, 0) allocates memory for result... yes checking for getcwd with POSIX signature... yes checking whether getdelim is declared... yes checking whether getdtablesize is declared... yes checking type of array argument to getgroups... gid_t checking whether getline is declared... yes checking whether getopt is POSIX compatible... yes checking whether fflush_unlocked is declared... yes checking whether flockfile is declared... yes checking whether fputs_unlocked is declared... yes checking whether funlockfile is declared... yes checking whether putc_unlocked is declared... yes checking for struct timeval... yes checking for wide-enough struct timeval.tv_sec member... yes checking whether ldexp() can be used without linking with libm... yes checking whether limits.h has LLONG_MAX, WORD_BIT, ULLONG_WIDTH etc.... no checking for wchar_t... yes checking for good max_align_t... no checking whether NULL can be used in arbitrary expressions... yes checking for ld used by gcc -std=gnu99... /usr/bin/ld checking if the linker (/usr/bin/ld) is GNU ld... yes checking for shared library run path origin... done checking 32-bit host C ABI... no checking for the common suffixes of directories in the library search path... lib64,lib64 checking whether imported symbols can be declared weak... yes checking whether the linker supports --as-needed... yes checking whether the linker supports --push-state... yes checking for pthread.h... (cached) yes checking for multithread API to use... posix checking whether lstat correctly handles trailing slash... yes checking for a sed that does not truncate output... /usr/bin/sed checking for stdlib.h... (cached) yes checking for GNU libc compatible malloc... yes checking for long long int... yes checking for a traditional japanese locale... ja_JP checking for a transitional chinese locale... zh_CN.GB18030 checking for a french Unicode locale... fr_FR.UTF-8 checking for inline... inline checking for mmap... (cached) yes checking for MAP_ANONYMOUS... yes checking whether memchr works... yes checking whether time_t is signed... yes checking whether alarm is declared... yes checking for working mktime... yes checking whether C symbols are prefixed with underscore at the linker level... no checking for O_CLOEXEC... yes checking for promoted mode_t type... mode_t checking for library containing forkpty... -lutil checking whether strerror(0) succeeds... yes checking for strerror_r with POSIX signature... no checking whether __xpg_strerror_r works... yes checking whether strerror_r is declared... yes checking for external symbol _system_configuration... no checking for library containing setsockopt... none needed checking for sigset_t... yes checking for SIGPIPE... yes checking whether we are using the GNU C Library >= 2.1 or uClibc... yes checking whether <sys/select.h> is self-contained... yes checking whether setenv is declared... yes checking search.h usability... yes checking search.h presence... yes checking for search.h... yes checking for tsearch... yes checking whether snprintf returns a byte count as in C99... yes checking whether snprintf is declared... yes checking for stdbool.h that conforms to C99... yes checking for _Bool... yes checking for wint_t... yes checking whether wint_t is too small... no checking whether stdint.h conforms to C99... yes checking whether stdint.h predates C++11... no checking whether stdint.h has UINTMAX_WIDTH etc.... no checking whether strdup is declared... yes checking whether strndup is declared... yes checking whether strnlen is declared... yes checking for struct tm.tm_gmtoff... yes checking whether strtok_r is declared... yes checking for struct timespec in <time.h>... yes checking whether ttyname_r is declared... yes checking whether unsetenv is declared... yes checking for inttypes.h... yes checking for stdint.h... yes checking for intmax_t... yes checking where to find the exponent in a 'double'... word 1 bit 20 checking for snprintf... (cached) yes checking for strnlen... yes checking for wcslen... yes checking for wcsnlen... yes checking for mbrtowc... (cached) yes checking for wcrtomb... (cached) yes checking whether _snprintf is declared... no checking whether vsnprintf is declared... yes checking whether strerror_r is declared... (cached) yes checking for strerror_r... (cached) yes checking whether strerror_r returns char *... yes checking for sig_atomic_t... yes checking whether ungetc works on arbitrary bytes... yes checking for inttypes.h... (cached) yes checking whether the inttypes.h PRIxNN macros are broken... no checking where to find the exponent in a 'float'... word 0 bit 23 checking whether byte ordering is bigendian... no checking whether long double and double are the same... no checking for LC_MESSAGES... yes checking whether uselocale works... yes checking for fake locale system (OpenBSD)... no checking for Solaris 11.4 locale system... no checking for getlocalename_l... no checking for CFPreferencesCopyAppValue... no checking for CFLocaleCopyCurrent... no checking for CFLocaleCopyPreferredLanguages... no checking for library containing posix_spawn... none required checking for posix_spawn... yes checking whether posix_spawn works... yes checking whether posix_spawnattr_setschedpolicy is supported... yes checking whether posix_spawnattr_setschedparam is supported... yes checking sys/mkdev.h usability... no checking sys/mkdev.h presence... no checking for sys/mkdev.h... no checking sys/sysmacros.h usability... yes checking sys/sysmacros.h presence... yes checking for sys/sysmacros.h... yes checking for alloca as a compiler built-in... yes checking whether btowc(0) is correct... yes checking whether btowc(EOF) is correct... yes checking for __builtin_expect... yes checking byteswap.h usability... yes checking byteswap.h presence... yes checking for byteswap.h... yes checking for library containing clock_gettime... none required checking for clock_gettime... yes checking for clock_settime... yes checking whether // is distinct from /... (cached) no checking whether dup2 works... yes checking for library containing backtrace_symbols_fd... none required checking whether fflush works on input streams... (cached) no checking whether fcntl handles F_DUPFD correctly... yes checking whether fcntl understands F_DUPFD_CLOEXEC... needs runtime check checking for library containing fdatasync... none required checking whether fflush works on input streams... (cached) no checking for ffs... yes checking for flexible array member... yes checking whether conversion from 'int' to 'long double' works... yes checking for working POSIX fnmatch... yes checking whether fpurge is declared... no checking for fseeko... (cached) yes checking whether fflush works on input streams... (cached) no checking for _fseeki64... no checking for ftello... (cached) yes checking whether ftello works... (cached) yes checking whether __func__ is available... yes checking how to do getaddrinfo, freeaddrinfo and getnameinfo... checking for library containing getaddrinfo... none required checking for getaddrinfo... yes checking whether gai_strerror is declared... yes checking whether gai_strerrorA is declared... no checking for gai_strerror with POSIX signature... yes checking for struct sockaddr.sa_len... no checking whether getaddrinfo is declared... yes checking whether freeaddrinfo is declared... yes checking whether getnameinfo is declared... yes checking for struct addrinfo... yes checking for working getdelim function... yes checking whether getdtablesize works... yes checking for getgroups... yes checking for working getgroups... yes checking whether getgroups handles negative values... yes checking for gethostname... yes checking for HOST_NAME_MAX... yes checking for getline... yes checking for working getline function... yes checking whether gettimeofday clobbers localtime buffer... no checking for gettimeofday with POSIX signature... almost checking for library containing gethostbyname... (cached) none required checking for gethostbyname... (cached) yes checking for library containing inet_ntop... (cached) none required checking whether inet_ntop is declared... (cached) yes checking for library containing inet_pton... none required checking whether inet_pton is declared... yes checking for ioctl... yes checking for ioctl with POSIX signature... no checking whether langinfo.h defines CODESET... yes checking whether langinfo.h defines T_FMT_AMPM... yes checking whether langinfo.h defines ALTMON_1... no checking whether langinfo.h defines ERA... yes checking whether langinfo.h defines YESEXPR... yes checking whether the compiler supports the __inline keyword... yes checking whether locale.h conforms to POSIX:2001... yes checking whether locale.h defines locale_t... yes checking whether struct lconv is properly defined... yes checking for pthread_rwlock_t... yes checking whether pthread_rwlock_rdlock prefers a writer to a reader... no checking whether lseek detects pipes... yes checking whether mbrtowc handles incomplete characters... yes checking whether mbrtowc works as well as mbtowc... yes checking whether mbrtowc handles a NULL pwc argument... yes checking whether mbrtowc handles a NULL string argument... yes checking whether mbrtowc has a correct return value... yes checking whether mbrtowc returns 0 when parsing a NUL character... yes checking whether mbrtowc works on empty input... no checking whether the C locale is free of encoding errors... no checking whether mbrtowc handles incomplete characters... (cached) yes checking whether mbrtowc works as well as mbtowc... (cached) yes checking whether mbrtowc handles incomplete characters... (cached) yes checking whether mbrtowc works as well as mbtowc... (cached) yes checking whether mbsrtowcs works... yes checking whether mkdir handles trailing slash... yes checking whether mkdir handles trailing dot... yes checking for mkdtemp... yes checking for __mktime_internal... no checking whether <net/if.h> is self-contained... yes checking whether <netinet/in.h> is self-contained... yes checking whether YESEXPR works... yes checking whether open recognizes a trailing slash... yes checking whether openpty is declared... yes checking for const-safe openpty signature... yes checking for struct msghdr.msg_accrights... no checking whether perror matches strerror... yes checking for sys/pstat.h... no checking for sys/sysmp.h... no checking for sys/sysinfo.h... yes checking for machine/hal_sysinfo.h... no checking for sys/table.h... no checking for sys/param.h... (cached) yes checking for sys/systemcfg.h... no checking for sys/sysctl.h... yes checking for pstat_getstatic... no checking for pstat_getdynamic... no checking for sysmp... no checking for getsysinfo... no checking for sysctl... yes checking for table... no checking for sysinfo... yes checking for struct sysinfo.mem_unit... yes checking for poll... yes checking for a shell that conforms to POSIX... /bin/sh checking whether <pthread.h> pollutes the namespace... no checking for pthread_t... yes checking for pthread_spinlock_t... yes checking for library containing pthread_create and pthread_join... -pthread checking for pthread_sigmask in -pthread -Wl,--push-state -Wl,--no-as-needed -lpthread -Wl,--pop-state... yes checking whether pthread_sigmask is only a macro... no checking whether pthread_sigmask returns error numbers... yes checking whether pthread_sigmask unblocks signals correctly... guessing yes checking for raise... yes checking for sigprocmask... yes checking for rawmemchr... yes checking whether readlink signature is correct... yes checking whether readlink handles trailing slash correctly... yes checking for working re_compile_pattern... no checking libintl.h usability... yes checking libintl.h presence... yes checking for libintl.h... yes checking whether isblank is declared... yes checking whether select supports a 0 argument... yes checking whether select detects invalid fds... yes checking for library containing getservbyname... (cached) none required checking for getservbyname... (cached) yes checking whether setenv validates arguments... yes checking for struct sigaction.sa_sigaction... yes checking for volatile sig_atomic_t... yes checking for sighandler_t... yes checking for sigprocmask... (cached) yes checking for stdint.h... (cached) yes checking for SIZE_MAX... yes checking whether sleep is declared... yes checking for working sleep... yes checking for snprintf... (cached) yes checking whether snprintf respects a size of 1... yes checking whether printf supports POSIX/XSI format strings with positions... yes checking for socklen_t... yes checking for ssize_t... yes checking whether stat handles trailing slashes on files... yes checking for struct stat.st_atim.tv_nsec... yes checking whether struct stat.st_atim is of type struct timespec... yes checking for struct stat.st_birthtimespec.tv_nsec... no checking for struct stat.st_birthtimensec... no checking for struct stat.st_birthtim.tv_nsec... no checking for working stdalign.h... yes checking for va_copy... yes checking for good max_align_t... (cached) no checking whether NULL can be used in arbitrary expressions... (cached) yes checking which flavor of printf attribute matches inttypes macros... system checking for stpcpy... yes checking for strcasecmp... yes checking for strncasecmp... yes checking whether strncasecmp is declared... yes checking for strchrnul... yes checking whether strchrnul works... yes checking for working strerror function... yes checking for working strndup... yes checking for working strnlen... yes checking for strsep... yes checking for strtok_r... yes checking whether strtok_r works... yes checking whether <sys/ioctl.h> declares ioctl... yes checking for nlink_t... (cached) yes checking for struct utsname... yes checking whether localtime_r is declared... yes checking whether localtime_r is compatible with its POSIX signature... yes checking for ttyname_r... yes checking whether ttyname_r is compatible with its POSIX signature... yes checking whether ttyname_r works with small buffers... guessing yes checking for uname... yes checking for unsetenv... yes checking for unsetenv() return type... int checking whether unsetenv obeys POSIX... yes checking for useconds_t... yes checking whether usleep allows large arguments... yes checking for ptrdiff_t... yes checking for vasprintf... yes checking for vsnprintf... yes checking whether snprintf respects a size of 1... (cached) yes checking whether printf supports POSIX/XSI format strings with positions... (cached) yes checking whether mbrtowc handles incomplete characters... (cached) yes checking whether mbrtowc works as well as mbtowc... (cached) yes checking whether wcrtomb return value is correct... yes checking whether iswcntrl works... yes checking for towlower... yes checking for wctype_t... yes checking for wctrans_t... yes checking whether wcwidth is declared... yes checking whether wcwidth works reasonably in UTF-8 locales... yes checking for stdint.h... (cached) yes checking for a traditional french locale... (cached) fr_FR checking for a french Unicode locale... (cached) fr_FR.UTF-8 checking for a traditional french locale... (cached) fr_FR checking for a turkish Unicode locale... tr_TR.UTF-8 checking whether dup works... yes checking for error_at_line... yes checking whether fdopen sets errno... yes checking for getpagesize... yes checking whether getpagesize is declared... yes checking whether program_invocation_name is declared... yes checking whether program_invocation_short_name is declared... yes checking whether __argv is declared... no checking for grantpt... yes checking whether byte ordering is bigendian... (cached) no checking whether byte ordering is bigendian... (cached) no checking whether INT32_MAX < INTMAX_MAX... yes checking whether INT64_MAX == LONG_MAX... yes checking whether UINT32_MAX < UINTMAX_MAX... yes checking whether UINT64_MAX == ULONG_MAX... yes checking whether isnan(double) can be used without linking with libm... yes checking where to find the exponent in a 'double'... (cached) word 1 bit 20 checking whether isnan(float) can be used without linking with libm... yes checking whether isnan(float) works... yes checking where to find the exponent in a 'float'... (cached) word 0 bit 23 checking whether isnan(long double) can be used without linking with libm... yes checking whether isnanl works... yes checking where to find the exponent in a 'long double'... word 2 bit 0 checking for setlocale... yes checking whether NAN macro works... yes checking whether HUGE_VAL works... yes checking for a traditional french locale... (cached) fr_FR checking for a french Unicode locale... (cached) fr_FR.UTF-8 checking for a traditional japanese locale... (cached) ja_JP checking for a transitional chinese locale... (cached) zh_CN.GB18030 checking for a french Unicode locale... (cached) fr_FR.UTF-8 checking for a traditional french locale... (cached) fr_FR checking for a french Unicode locale... (cached) fr_FR.UTF-8 checking for a traditional japanese locale... (cached) ja_JP checking for a transitional chinese locale... (cached) zh_CN.GB18030 checking for mmap... (cached) yes checking for MAP_ANONYMOUS... yes checking for library containing nanosleep... none required checking for working nanosleep... no (mishandles large arguments) checking for library containing if_nameindex... none required checking for a traditional french locale... (cached) fr_FR checking for a french Unicode locale... (cached) fr_FR.UTF-8 checking whether posix_spawn_file_actions_addclose works... yes checking whether posix_spawn_file_actions_adddup2 works... yes checking whether posix_spawn_file_actions_addopen works... yes checking for ptsname... yes checking whether ptsname sets errno on failure... yes checking whether ptsname_r has the same signature as in glibc... yes checking for putenv compatible with GNU and SVID... yes checking for mmap... (cached) yes checking for MAP_ANONYMOUS... yes checking for a traditional french locale... (cached) fr_FR checking for a french Unicode locale... (cached) fr_FR.UTF-8 checking for a traditional japanese locale... (cached) ja_JP checking for a transitional chinese locale... (cached) zh_CN.GB18030 checking for signbit macro... yes checking for signbit compiler built-ins... yes checking for posix_spawnattr_t... yes checking for posix_spawn_file_actions_t... yes checking for mmap... (cached) yes checking for MAP_ANONYMOUS... yes checking whether symlink handles trailing slash correctly... yes checking for pthread_atfork... yes checking for unlockpt... yes checking for waitid... yes checking for a traditional french locale... (cached) fr_FR checking for a french Unicode locale... (cached) fr_FR.UTF-8 checking for a traditional japanese locale... (cached) ja_JP checking for a transitional chinese locale... (cached) zh_CN.GB18030 checking whether wctob works... yes checking whether wctob is declared... yes checking for uid_t in sys/types.h... (cached) yes checking for sys/mkdev.h... (cached) no checking for sys/sysmacros.h... (cached) yes checking how to print strings... printf checking for a sed that does not truncate output... (cached) /usr/bin/sed checking for fgrep... /usr/bin/grep -F checking for ld used by gcc -std=gnu99... /usr/bin/ld checking if the linker (/usr/bin/ld) is GNU ld... yes checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -B checking the name lister (/usr/bin/nm -B) interface... BSD nm checking whether ln -s works... yes checking the maximum length of command line arguments... 1572864 checking whether the shell understands some XSI constructs... yes checking whether the shell understands "+="... yes checking how to convert x86_64-pc-linux-gnu file names to x86_64-pc-linux-gnu format... func_convert_file_noop checking how to convert x86_64-pc-linux-gnu file names to toolchain format... func_convert_file_noop checking for /usr/bin/ld option to reload object files... -r checking for objdump... objdump checking how to recognize dependent libraries... pass_all checking for dlltool... dlltool checking how to associate runtime and link libraries... printf %s\n checking for archiver @FILE support... @ checking for strip... strip checking for ranlib... (cached) ranlib checking command to parse /usr/bin/nm -B output from gcc -std=gnu99 object... ok checking for sysroot... no checking for mt... no checking if : is a manifest tool... no checking for dlfcn.h... yes checking for objdir... .libs checking if gcc -std=gnu99 supports -fno-rtti -fno-exceptions... no checking for gcc -std=gnu99 option to produce PIC... -fPIC -DPIC checking if gcc -std=gnu99 PIC flag -fPIC -DPIC works... yes checking if gcc -std=gnu99 static flag -static works... no checking if gcc -std=gnu99 supports -c -o file.o... yes checking if gcc -std=gnu99 supports -c -o file.o... (cached) yes checking whether the gcc -std=gnu99 linker (/usr/bin/ld -m elf_x86_64) supports shared libraries... yes checking whether -lc should be explicitly linked in... no checking dynamic linker characteristics... GNU/Linux ld.so checking how to hardcode library paths into programs... immediate checking whether stripping libraries is possible... yes checking if libtool supports shared libraries... yes checking whether to build shared libraries... yes checking whether to build static libraries... no checking for ld used by gcc -std=gnu99... (cached) /usr/bin/ld checking if the linker (/usr/bin/ld) is GNU ld... (cached) yes checking for how to mark DSO non-deletable at runtime... -Wl,-z -Wl,nodelete checking for how to set DSO symbol versions... -Wl,--version-script= checking whether C compiler handles -Werror -Wunknown-warning-option... no checking whether the C compiler's -Wformat allows NULL strings... yes checking whether pragma GCC diagnostic push works... yes checking whether the C compiler's -Wlogical-op gives bogus warnings... no checking whether gcc gives bogus warnings for -Wlogical-op... no checking whether clang gives bogus warnings for -Wdouble-promotion... no checking whether -Wno-missing-field-initializers is supported... yes checking whether -Wno-missing-field-initializers is needed... no checking whether -Wuninitialized is supported... yes checking max safe object size... 9223372036854775807 checking whether C compiler handles -Wframe-larger-than=4096... yes checking whether C compiler handles -Wframe-larger-than=32768... yes checking whether C compiler handles -fno-common... yes checking whether C compiler handles -W... yes checking whether C compiler handles -Waddress... yes checking whether C compiler handles -Waggressive-loop-optimizations... yes checking whether C compiler handles -Wall... yes checking whether C compiler handles -Wattribute-alias... no checking whether C compiler handles -Wattributes... yes checking whether C compiler handles -Wbad-function-cast... yes checking whether C compiler handles -Wbool-compare... no checking whether C compiler handles -Wbool-operation... no checking whether C compiler handles -Wbuiltin-declaration-mismatch... no checking whether C compiler handles -Wbuiltin-macro-redefined... yes checking whether C compiler handles -Wcast-align... yes checking whether C compiler handles -Wcast-align=strict... no checking whether C compiler handles -Wcast-function-type... no checking whether C compiler handles -Wchar-subscripts... yes checking whether C compiler handles -Wclobbered... yes checking whether C compiler handles -Wcomment... yes checking whether C compiler handles -Wcomments... yes checking whether C compiler handles -Wcoverage-mismatch... yes checking whether C compiler handles -Wcpp... yes checking whether C compiler handles -Wdangling-else... no checking whether C compiler handles -Wdate-time... no checking whether C compiler handles -Wdeprecated-declarations... yes checking whether C compiler handles -Wdesignated-init... no checking whether C compiler handles -Wdiscarded-array-qualifiers... no checking whether C compiler handles -Wdiscarded-qualifiers... no checking whether C compiler handles -Wdiv-by-zero... yes checking whether C compiler handles -Wdouble-promotion... yes checking whether C compiler handles -Wduplicated-cond... no checking whether C compiler handles -Wduplicate-decl-specifier... no checking whether C compiler handles -Wempty-body... yes checking whether C compiler handles -Wendif-labels... yes checking whether C compiler handles -Wexpansion-to-defined... no checking whether C compiler handles -Wextra... yes checking whether C compiler handles -Wformat-contains-nul... yes checking whether C compiler handles -Wformat-extra-args... yes checking whether C compiler handles -Wformat-security... yes checking whether C compiler handles -Wformat-y2k... yes checking whether C compiler handles -Wformat-zero-length... yes checking whether C compiler handles -Wframe-address... no checking whether C compiler handles -Wfree-nonheap-object... yes checking whether C compiler handles -Whsa... no checking whether C compiler handles -Wif-not-aligned... no checking whether C compiler handles -Wignored-attributes... no checking whether C compiler handles -Wignored-qualifiers... yes checking whether C compiler handles -Wimplicit... yes checking whether C compiler handles -Wimplicit-function-declaration... yes checking whether C compiler handles -Wimplicit-int... yes checking whether C compiler handles -Wincompatible-pointer-types... no checking whether C compiler handles -Winit-self... yes checking whether C compiler handles -Winline... yes checking whether C compiler handles -Wint-conversion... no checking whether C compiler handles -Wint-in-bool-context... no checking whether C compiler handles -Wint-to-pointer-cast... yes checking whether C compiler handles -Winvalid-memory-model... yes checking whether C compiler handles -Winvalid-pch... yes checking whether C compiler handles -Wlogical-not-parentheses... no checking whether C compiler handles -Wlogical-op... yes checking whether C compiler handles -Wmain... yes checking whether C compiler handles -Wmaybe-uninitialized... yes checking whether C compiler handles -Wmemset-elt-size... no checking whether C compiler handles -Wmemset-transposed-args... no checking whether C compiler handles -Wmisleading-indentation... no checking whether C compiler handles -Wmissing-attributes... no checking whether C compiler handles -Wmissing-braces... yes checking whether C compiler handles -Wmissing-declarations... yes checking whether C compiler handles -Wmissing-field-initializers... yes checking whether C compiler handles -Wmissing-include-dirs... yes checking whether C compiler handles -Wmissing-parameter-type... yes checking whether C compiler handles -Wmissing-prototypes... yes checking whether C compiler handles -Wmultichar... yes checking whether C compiler handles -Wmultistatement-macros... no checking whether C compiler handles -Wnarrowing... yes checking whether C compiler handles -Wnested-externs... yes checking whether C compiler handles -Wnonnull... yes checking whether C compiler handles -Wnonnull-compare... no checking whether C compiler handles -Wnull-dereference... no checking whether C compiler handles -Wodr... no checking whether C compiler handles -Wold-style-declaration... yes checking whether C compiler handles -Wold-style-definition... yes checking whether C compiler handles -Wopenmp-simd... no checking whether C compiler handles -Woverflow... yes checking whether C compiler handles -Woverride-init... yes checking whether C compiler handles -Wpacked-bitfield-compat... yes checking whether C compiler handles -Wpacked-not-aligned... no checking whether C compiler handles -Wparentheses... yes checking whether C compiler handles -Wpointer-arith... yes checking whether C compiler handles -Wpointer-compare... no checking whether C compiler handles -Wpointer-sign... yes checking whether C compiler handles -Wpointer-to-int-cast... yes checking whether C compiler handles -Wpragmas... yes checking whether C compiler handles -Wpsabi... yes checking whether C compiler handles -Wrestrict... no checking whether C compiler handles -Wreturn-local-addr... yes checking whether C compiler handles -Wreturn-type... yes checking whether C compiler handles -Wscalar-storage-order... no checking whether C compiler handles -Wsequence-point... yes checking whether C compiler handles -Wshadow... yes checking whether C compiler handles -Wshift-count-negative... no checking whether C compiler handles -Wshift-count-overflow... no checking whether C compiler handles -Wshift-negative-value... no checking whether C compiler handles -Wsizeof-array-argument... no checking whether C compiler handles -Wsizeof-pointer-div... no checking whether C compiler handles -Wsizeof-pointer-memaccess... yes checking whether C compiler handles -Wstrict-aliasing... yes checking whether C compiler handles -Wstrict-prototypes... yes checking whether C compiler handles -Wstringop-truncation... no checking whether C compiler handles -Wsuggest-attribute=cold... no checking whether C compiler handles -Wsuggest-attribute=const... yes checking whether C compiler handles -Wsuggest-attribute=format... yes checking whether C compiler handles -Wsuggest-attribute=malloc... no checking whether C compiler handles -Wsuggest-attribute=noreturn... yes checking whether C compiler handles -Wsuggest-attribute=pure... yes checking whether C compiler handles -Wsuggest-final-methods... no checking whether C compiler handles -Wsuggest-final-types... no checking whether C compiler handles -Wswitch... yes checking whether C compiler handles -Wswitch-bool... no checking whether C compiler handles -Wswitch-unreachable... no checking whether C compiler handles -Wsync-nand... yes checking whether C compiler handles -Wtautological-compare... no checking whether C compiler handles -Wtrampolines... yes checking whether C compiler handles -Wtrigraphs... yes checking whether C compiler handles -Wtype-limits... yes checking whether C compiler handles -Wuninitialized... yes checking whether C compiler handles -Wunknown-pragmas... yes checking whether C compiler handles -Wunused... yes checking whether C compiler handles -Wunused-but-set-parameter... yes checking whether C compiler handles -Wunused-but-set-variable... yes checking whether C compiler handles -Wunused-function... yes checking whether C compiler handles -Wunused-label... yes checking whether C compiler handles -Wunused-local-typedefs... yes checking whether C compiler handles -Wunused-parameter... yes checking whether C compiler handles -Wunused-result... yes checking whether C compiler handles -Wunused-value... yes checking whether C compiler handles -Wunused-variable... yes checking whether C compiler handles -Wvarargs... yes checking whether C compiler handles -Wvariadic-macros... yes checking whether C compiler handles -Wvector-operation-performance... yes checking whether C compiler handles -Wvolatile-register-var... yes checking whether C compiler handles -Wwrite-strings... yes checking whether C compiler handles -Walloc-size-larger-than=9223372036854775807... no checking whether C compiler handles -Warray-bounds=2... no checking whether C compiler handles -Wformat-overflow=2... no checking whether C compiler handles -Wformat-truncation=2... no checking whether C compiler handles -Wimplicit-fallthrough=5... no checking whether C compiler handles -Wnormalized=nfc... yes checking whether C compiler handles -Wshift-overflow=2... no checking whether C compiler handles -Wstringop-overflow=2... no checking whether C compiler handles -Wunused-const-variable=2... no checking whether C compiler handles -Wvla-larger-than=4031... no checking whether C compiler handles -Wno-sign-compare... yes checking whether C compiler handles -Wno-cast-function-type... no checking whether C compiler handles -Wjump-misses-init... yes checking whether C compiler handles -Wswitch-enum... yes checking whether C compiler handles -Wno-format-nonliteral... yes checking whether C compiler handles -Wno-format-truncation... no checking whether C compiler handles -fstack-protector-strong... yes checking whether C compiler handles -fexceptions... yes checking whether C compiler handles -fasynchronous-unwind-tables... yes checking whether C compiler handles -fipa-pure-const... yes checking whether C compiler handles -Wno-suggest-attribute=pure... yes checking whether C compiler handles -Wno-suggest-attribute=const... yes checking whether C compiler handles -Werror... yes checking whether C compiler handles -fPIE -DPIE -pie... yes checking for how to force completely read-only GOT table... -Wl,-z -Wl,relro -Wl,-z -Wl,now checking for how to avoid indirect lib deps... -Wl,--no-copy-dt-needed-entries checking for how to stop undefined symbols at link time... -Wl,-z -Wl,defs checking sys/acl.h usability... yes checking sys/acl.h presence... yes checking for sys/acl.h... yes checking for aa_change_profile in -lapparmor... no checking for pthread_mutexattr_init... yes checking for pthread.h... (cached) yes checking whether pthread_sigmask does anything... yes checking for atomic ops implementation... gcc checking for getxattr in -lattr... yes checking sys/xattr.h usability... yes checking sys/xattr.h presence... yes checking for sys/xattr.h... yes checking for audit_encode_nv_string in -laudit... yes checking libaudit.h usability... yes checking libaudit.h presence... yes checking for libaudit.h... yes checking for pkg-config... /usr/bin/pkg-config checking pkg-config is at least version 0.9.0... yes checking for AVAHI... yes checking for library containing tgetent... -lncurses checking whether rl_completion_quote_character is declared... yes checking for readline in -lreadline... yes checking readline/readline.h usability... yes checking readline/readline.h presence... yes checking for readline/readline.h... yes checking for rl_initialize in -lreadline... yes checking for BASH_COMPLETION... no checking for BLKID... yes checking for capng_updatev in -lcap-ng... yes checking cap-ng.h usability... yes checking cap-ng.h presence... yes checking for cap-ng.h... yes checking for CURL... yes checking for DBUS... yes checking for dbus_watch_get_unix_fd... yes checking for DBusBasicValue... yes checking for DEVMAPPER... yes checking for dlfcn.h... (cached) yes checking for library containing dlopen... -ldl checking for FUSE... yes checking for GLUSTERFS... yes checking for GNUTLS... yes checking for HAL... no checking for LIBISCSI... no checking for NETCF... yes checking for ncf_change_begin... yes checking whether to compile with macvtap support... yes checking whether MACVLAN_MODE_PASSTHRU is declared... yes checking for LIBNL... yes checking for LIBNL_ROUTE3... yes checking for LIBPARTED... yes checking for parted... /sbin/parted checking libpcap pcap-config >= 1.0.0 ... yes checking for LIBSSH... no checking for LIBXML... yes checking for struct _xmlURI.query_raw... yes checking whether to compile with macvtap support... yes checking whether MACVLAN_MODE_PASSTHRU is declared... (cached) yes checking for NETCF... yes checking for ncf_change_begin... (cached) yes checking for gettext... yes checking for libintl.h... (cached) yes checking for xgettext... xgettext checking for msgfmt... msgfmt checking for msgmerge... msgmerge checking msgfmt is GNU tool... yes checking for numa_available in -lnuma... yes checking numa.h usability... yes checking numa.h presence... yes checking for numa.h... yes checking for numa_bitmask_isbitset in -lnuma... yes checking for OPENWSMAN... no checking for PCIACCESS... yes checking for init script type... systemd checking for pkcheck... /usr/bin/pkcheck checking for pthread_mutexattr_init... (cached) yes checking for pthread.h... (cached) yes checking whether pthread_sigmask does anything... (cached) yes checking for library containing tgetent... (cached) -lncurses checking whether rl_completion_quote_character is declared... (cached) yes checking for readline in -lreadline... (cached) yes checking for readline/readline.h... (cached) yes checking for rl_initialize in -lreadline... (cached) yes checking for sanlock_init in -lsanlock_client... yes checking sanlock.h usability... yes checking sanlock.h presence... yes checking for sanlock.h... yes checking whether SANLK_INQ_WAIT is declared... yes checking for sanlock_killpath in -lsanlock_client... yes checking for sanlock_inq_lockspace in -lsanlock_client... yes checking for sanlock_write_lockspace in -lsanlock_client... yes checking for sanlock_strerror in -lsanlock_client... yes checking for sasl_client_init in -lsasl2... yes checking sasl/sasl.h usability... yes checking sasl/sasl.h presence... yes checking for sasl/sasl.h... yes checking for fgetfilecon_raw in -lselinux... yes checking selinux/selinux.h usability... yes checking selinux/selinux.h presence... yes checking for selinux/selinux.h... yes checking for selinux setcon parameter type... const checking for selinux selabel_open parameter type... const checking SELinux mount point... /sys/fs/selinux checking selinux/label.h usability... yes checking selinux/label.h presence... yes checking for selinux/label.h... yes checking for SSH2... no checking for UDEV... yes checking for udev_monitor_set_receive_buffer_size... yes checking whether to compile with virtual port support... yes checking for WIRESHARK_DISSECTOR... no checking for xdrmem_create in -lportablexdr... no checking for library containing xdrmem_create... none required checking for xdr_u_int64_t... no checking where to find <rpc/rpc.h>... none checking for qemu-kvm... no checking for qemu... no checking for kvm... no checking for qemu-system-x86_64... no checking for yajl_parse_complete in -lyajl... no checking for yajl_tree_parse in -lyajl... yes checking yajl/yajl_common.h usability... yes checking yajl/yajl_common.h presence... yes checking for yajl/yajl_common.h... yes checking size of long... 8 checking ifaddrs.h usability... yes checking ifaddrs.h presence... yes checking for ifaddrs.h... yes checking libtasn1.h usability... yes checking libtasn1.h presence... yes checking for libtasn1.h... yes checking linux/magic.h usability... yes checking linux/magic.h presence... yes checking for linux/magic.h... yes checking mntent.h usability... yes checking mntent.h presence... yes checking for mntent.h... yes checking net/ethernet.h usability... yes checking net/ethernet.h presence... yes checking for net/ethernet.h... yes checking netinet/tcp.h usability... yes checking netinet/tcp.h presence... yes checking for netinet/tcp.h... yes checking pwd.h usability... yes checking pwd.h presence... yes checking for pwd.h... yes checking stdarg.h usability... yes checking stdarg.h presence... yes checking for stdarg.h... yes checking syslog.h usability... yes checking syslog.h presence... yes checking for syslog.h... yes checking sys/mount.h usability... yes checking sys/mount.h presence... yes checking for sys/mount.h... yes checking sys/syscall.h usability... yes checking sys/syscall.h presence... yes checking for sys/syscall.h... yes checking for sys/sysctl.h... (cached) yes checking sys/ucred.h usability... no checking sys/ucred.h presence... no checking for sys/ucred.h... no checking sys/un.h usability... yes checking sys/un.h presence... yes checking for sys/un.h... yes checking whether htole64 is declared... yes checking for stat... yes checking for stat64... yes checking for __xstat... yes checking for __xstat64... yes checking for lstat... (cached) yes checking for lstat64... yes checking for __lxstat... yes checking for __lxstat64... yes checking for struct ifreq... yes checking for struct sockpeercred... no checking whether ETH_FLAG_TXVLAN is declared... yes checking whether ETH_FLAG_NTUPLE is declared... yes checking whether ETH_FLAG_RXHASH is declared... yes checking whether ETH_FLAG_LRO is declared... yes checking whether ETHTOOL_GGSO is declared... yes checking whether ETHTOOL_GGRO is declared... yes checking whether ETHTOOL_GFLAGS is declared... yes checking whether ETHTOOL_GFEATURES is declared... yes checking whether ETHTOOL_SCOALESCE is declared... yes checking whether ETHTOOL_GCOALESCE is declared... yes checking whether SEEK_HOLE is declared... yes checking for gettext in -lintl... no checking for rpcgen... /usr/bin/rpcgen checking for xmllint... /usr/bin/xmllint checking for xsltproc... /usr/bin/xsltproc checking for augparse... /usr/bin/augparse checking whether ln -s works... yes checking for dmidecode... /sbin/dmidecode checking for dnsmasq... /sbin/dnsmasq checking for radvd... /sbin/radvd checking for tc... /sbin/tc checking for udevadm... /usr/bin/udevadm checking for udevsettle... no checking for modprobe... /sbin/modprobe checking for rmmod... /sbin/rmmod checking for mm-ctl... mm-ctl checking for ovs-vsctl... ovs-vsctl checking for scrub... /usr/bin/scrub checking for addr2line... /usr/bin/addr2line checking for ip... /sbin/ip checking for iptables... /sbin/iptables checking for ip6tables... /sbin/ip6tables checking for ebtables... /sbin/ebtables checking for qemu-bridge-helper... /usr/libexec/qemu-bridge-helper checking for qemu-pr-helper... /usr/bin/qemu-pr-helper checking for xen_vm_start in -lxenserver... no checking for LIBXL... no checking for libxl_cpupool_cpuadd_cpumap in -lxenlight... no checking whether LIBXL_DOMAIN_TYPE_PVH is declared... no checking for PARALLELS_SDK... no checking for bhyve... no checking for bhyvectl... no checking for bhyveload... no checking for dtrace... /usr/bin/dtrace checking for numad... /usr/bin/numad checking for init script type... systemd checking for whether to install sysctl config... yes checking nss.h usability... yes checking nss.h presence... yes checking for nss.h... yes checking for struct gaih_addrtuple... yes checking for ns_mtab... no checking for nss_module_unregister_fn... no checking linux/kvm.h usability... yes checking linux/kvm.h presence... yes checking for linux/kvm.h... yes checking whether <linux/*.h> and <netinet/*.h> headers are compatible... yes checking for linux/param.h... yes checking for linux/sockios.h... yes checking for linux/if_bridge.h... yes checking for linux/if_tun.h... yes checking for pkg-config... (cached) /usr/bin/pkg-config checking pkg-config is at least version 0.9.0... yes checking for selinux_virtual_domain_context_path... yes checking for selinux_virtual_image_context_path... yes checking for selinux_lxc_contexts_path... yes checking for mntent.h... (cached) yes checking for mount... /usr/bin/mount checking for umount... /usr/bin/umount checking for mkfs... /sbin/mkfs checking for showmount... /sbin/showmount checking for pvcreate... /sbin/pvcreate checking for vgcreate... /sbin/vgcreate checking for lvcreate... /sbin/lvcreate checking for pvremove... /sbin/pvremove checking for vgremove... /sbin/vgremove checking for lvremove... /sbin/lvremove checking for lvchange... /sbin/lvchange checking for vgchange... /sbin/vgchange checking for vgscan... /sbin/vgscan checking for pvs... /sbin/pvs checking for vgs... /sbin/vgs checking for lvs... /sbin/lvs checking for iscsiadm... /sbin/iscsiadm checking rbd/librbd.h usability... yes checking rbd/librbd.h presence... yes checking for rbd/librbd.h... yes checking for rbd_get_features... yes checking for collie... no checking for dog... no checking for zfs... no checking for zpool... no checking for vstorage... no checking for vstorage-mount... no checking for umount... (cached) /usr/bin/umount checking linux/btrfs.h usability... yes checking linux/btrfs.h presence... yes checking for linux/btrfs.h... yes checking xfs/xfs.h usability... no checking xfs/xfs.h presence... no checking for xfs/xfs.h... no checking linux/devlink.h usability... yes checking linux/devlink.h presence... yes checking for linux/devlink.h... yes checking whether DEVLINK_CMD_ESWITCH_GET is declared... yes checking whether VHOST_VSOCK_SET_GUEST_CID is declared... yes checking for python3... /usr/bin/python3 checking for perl... /usr/bin/perl checking Whether to build test suite by default... yes checking whether GET_VLAN_VID_CMD is declared... yes checking for struct ifreq.ifr_newname... yes checking for struct ifreq.ifr_ifindex... yes checking for struct ifreq.ifr_index... no checking for struct ifreq.ifr_hwaddr... yes checking whether BRDGSFD is declared... no checking whether BRDGADD is declared... no checking whether BRDGDEL is declared... no checking whether cpuset_getaffinity is declared... no checking for struct if_data.ifi_oqdrops... no checking whether clock_serv_t is declared... no checking whether host_get_clock_service is declared... no checking whether clock_get_time is declared... no checking whether this build is done by a static analysis tool... no checking that generated files are newer than configure... done configure: creating ./config.status config.status: creating run config.status: creating Makefile config.status: creating src/Makefile config.status: creating include/libvirt/Makefile config.status: creating docs/Makefile config.status: creating gnulib/lib/Makefile config.status: creating gnulib/tests/Makefile config.status: creating .color_coded config.status: creating .ycm_extra_conf.py config.status: creating libvirt.pc config.status: creating libvirt-qemu.pc config.status: creating libvirt-lxc.pc config.status: creating libvirt-admin.pc config.status: creating src/libvirt.pc config.status: creating src/libvirt-qemu.pc config.status: creating src/libvirt-lxc.pc config.status: creating libvirt.spec config.status: creating mingw-libvirt.spec config.status: creating po/Makefile config.status: creating include/libvirt/libvirt-common.h config.status: creating examples/Makefile config.status: creating tests/Makefile config.status: creating tools/Makefile config.status: creating config.h config.status: executing depfiles commands config.status: executing libtool commands configure: configure: Configuration summary configure: ===================== configure: configure: Drivers configure: configure: QEMU: yes configure: OpenVZ: yes configure: VMware: yes configure: VBox: yes configure: XenAPI: no configure: libxl: no configure: LXC: yes configure: PHYP: no configure: ESX: yes configure: Hyper-V: no configure: vz: no configure: Bhyve: no configure: Test: yes configure: Remote: yes configure: Network: yes configure: Libvirtd: yes configure: Interface: yes configure: configure: Storage Drivers configure: configure: Dir: yes configure: FS: yes configure: NetFS: yes configure: LVM: yes configure: iSCSI: yes configure: iscsi-direct: no configure: SCSI: yes configure: mpath: yes configure: Disk: yes configure: RBD: yes configure: Sheepdog: no configure: Gluster: yes configure: ZFS: no configure: Virtuozzo storage: no configure: configure: Security Drivers configure: configure: SELinux: yes configure: AppArmor: no configure: configure: Driver Loadable Modules configure: configure: driver_modules: yes (CFLAGS='' LIBS='-ldl') configure: configure: Libraries configure: configure: acl: yes (CFLAGS='' LIBS='-lacl') configure: apparmor: no configure: attr: yes (CFLAGS='' LIBS='-lattr') configure: audit: yes (CFLAGS='' LIBS='-laudit') configure: avahi: yes (CFLAGS='-D_REENTRANT ' LIBS='-lavahi-common -lavahi-client ') configure: bash_completion: no configure: blkid: yes (CFLAGS='-I/usr/include/blkid -I/usr/include/uuid ' LIBS='-lblkid ') configure: capng: yes (CFLAGS='' LIBS='-lcap-ng') configure: curl: yes (CFLAGS='-DCURL_DISABLE_TYPECHECK ' LIBS='-lcurl ') configure: dbus: yes (CFLAGS='-I/usr/include/dbus-1.0 -I/usr/lib64/dbus-1.0/include ' LIBS='-ldbus-1 ') configure: dlopen: yes (CFLAGS='' LIBS='-ldl') configure: firewalld: yes (CFLAGS='' LIBS='') configure: fuse: yes (CFLAGS='-D_FILE_OFFSET_BITS=64 -I/usr/include/fuse ' LIBS='-pthread -lfuse ') configure: glusterfs: yes (CFLAGS='-D_FILE_OFFSET_BITS=64 -D__USE_FILE_OFFSET64 -DUSE_POSIX_ACLS=1 -I/usr/include/glusterfs -I/usr/include/uuid ' LIBS='-lacl -lgfapi -lglusterfs -lgfrpc -lgfxdr -luuid ') configure: gnutls: yes (CFLAGS='-I/usr/include/p11-kit-1 ' LIBS='-lgnutls ') configure: hal: no configure: libiscsi: no configure: libnl: yes (CFLAGS='-I/usr/include/libnl3 -I/usr/include/libnl3 ' LIBS='-lnl-3 -lnl-route-3 -lnl-3 ') configure: libpcap: yes (CFLAGS='' LIBS='-lpcap') configure: libssh: no configure: libxl: no configure: libxml: yes (CFLAGS='-I/usr/include/libxml2 ' LIBS='-lxml2 ') configure: macvtap: yes (CFLAGS='' LIBS='') configure: netcf: yes (CFLAGS=' ' LIBS='-lnetcf ') configure: NLS: yes configure: nss: yes configure: numactl: yes (CFLAGS='' LIBS='-lnuma') configure: openwsman: no configure: pciaccess: yes (CFLAGS=' ' LIBS='-lpciaccess ') configure: pm_utils: no configure: polkit: yes configure: rbd: yes (CFLAGS='' LIBS='-lrbd -lrados') configure: readline: yes (CFLAGS='-D_FUNCTION_DEF ' LIBS='-lreadline') configure: sanlock: yes (CFLAGS='' LIBS='-lsanlock_client') configure: sasl: yes (CFLAGS='' LIBS='-lsasl2') configure: selinux: yes (CFLAGS='' LIBS='-lselinux') configure: ssh2: no configure: udev: yes (CFLAGS=' ' LIBS='-ludev ') configure: virtualport: yes (CFLAGS='' LIBS='') configure: xdr: yes (CFLAGS='' LIBS='') configure: xenapi: no configure: yajl: yes (CFLAGS='' LIBS='-lyajl') configure: configure: Windows configure: configure: Cygwin: no configure: MinGW: no configure: MSVC: no configure: windres: no configure: configure: Test suite configure: configure: Coverage: no configure: Alloc OOM: no configure: configure: Miscellaneous configure: configure: Debug: yes configure: Use -Werror: yes configure: Warning Flags: -fno-common -W -Waddress -Waggressive-loop-optimizations -Wall -Wattributes -Wbad-function-cast -Wbuiltin-macro-redefined -Wcast-align -Wchar-subscripts -Wclobbered -Wcomment -Wcomments -Wcoverage-mismatch -Wcpp -Wdeprecated-declarations -Wdiv-by-zero -Wdouble-promotion -Wempty-body -Wendif-labels -Wextra -Wformat-contains-nul -Wformat-extra-args -Wformat-security -Wformat-y2k -Wformat-zero-length -Wfree-nonheap-object -Wignored-qualifiers -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Winit-self -Winline -Wint-to-pointer-cast -Winvalid-memory-model -Winvalid-pch -Wlogical-op -Wmain -Wmaybe-uninitialized -Wmissing-braces -Wmissing-declarations -Wmissing-field-initializers -Wmissing-include-dirs -Wmissing-parameter-type -Wmissing-prototypes -Wmultichar -Wnarrowing -Wnested-externs -Wnonnull -Wold-style-declaration -Wold-style-definition -Woverflow -Woverride-init -Wpacked-bitfield-compat -Wparentheses -Wpointer-arith -Wpointer-sign -Wpointer-to-int-cast -Wpragmas -Wpsabi -Wreturn-local-addr -Wreturn-type -Wsequence-point -Wshadow -Wsizeof-pointer-memaccess -Wstrict-aliasing -Wstrict-prototypes -Wsuggest-attribute=const -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure -Wswitch -Wsync-nand -Wtrampolines -Wtrigraphs -Wtype-limits -Wuninitialized -Wunknown-pragmas -Wunused -Wunused-but-set-parameter -Wunused-but-set-variable -Wunused-function -Wunused-label -Wunused-local-typedefs -Wunused-parameter -Wunused-result -Wunused-value -Wunused-variable -Wvarargs -Wvariadic-macros -Wvector-operation-performance -Wvolatile-register-var -Wwrite-strings -Wnormalized=nfc -Wno-sign-compare -Wjump-misses-init -Wswitch-enum -Wno-format-nonliteral -fstack-protector-strong -fexceptions -fasynchronous-unwind-tables -fipa-pure-const -Wno-suggest-attribute=pure -Wno-suggest-attribute=const -Werror configure: DTrace: yes configure: numad: yes configure: Init script: systemd configure: Char device locks: /var/lock configure: Default Editor: vi configure: Loader/NVRAM: configure: virt-login-shell: yes configure: virt-host-validate: yes configure: TLS priority: NORMAL configure: configure: Developer Tools configure: configure: wireshark_dissector: no configure: configure: Privileges configure: configure: QEMU: root:root configure: Now type 'make' to compile libvirt. GEN spacing-check GEN test-wrap-argv GEN prohibit-duplicate-header GEN mock-noinline GEN group-qemu-caps GEN header-ifdef GFDL_version 5.36 GFDL_version TAB_in_indentation 0.59 TAB_in_indentation Wundef_boolean 0.19 Wundef_boolean avoid_attribute_unused_in_header 0.22 avoid_attribute_unused_in_header avoid_ctype_macros 0.55 avoid_ctype_macros avoid_if_before_free 4.57 avoid_if_before_free avoid_strcase 0.76 avoid_strcase avoid_write 0.34 avoid_write bindtextdomain 0.13 bindtextdomain cast_of_argument_to_free 0.89 cast_of_argument_to_free cast_of_x_alloc_return_value 0.74 cast_of_x_alloc_return_value changelog 0.20 changelog const_long_option 0.75 const_long_option copyright_check 0.55 copyright_check copyright_format 2.17 copyright_format copyright_usage 1.74 copyright_usage correct_id_types 0.91 correct_id_types curly_braces_style 0.58 curly_braces_style error_message_period 0.56 error_message_period error_message_warn_fatal 0.52 error_message_warn_fatal flags_debug 1.31 flags_debug flags_usage 1.25 flags_usage forbid_const_pointer_typedef 1.55 forbid_const_pointer_typedef forbid_manual_xml_indent 0.72 forbid_manual_xml_indent gettext_init 0.19 gettext_init libvirt_unmarked_diagnostics 1.36 libvirt_unmarked_diagnostics m4_quote_check 0.16 m4_quote_check makefile_TAB_only_indentation 0.18 makefile_TAB_only_indentation makefile_at_at_check 0.14 makefile_at_at_check makefile_conditionals 0.20 makefile_conditionals make -C src remote/remote_daemon_dispatch_stubs.h make[1]: Entering directory `/var/tmp/patchew-tester-tmp-ihkkxt3p/src/src' GEN remote/remote_daemon_dispatch_stubs.h make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-ihkkxt3p/src/src' make -C src remote/remote_daemon_dispatch_qemu_stubs.h make[1]: Entering directory `/var/tmp/patchew-tester-tmp-ihkkxt3p/src/src' GEN remote/remote_daemon_dispatch_qemu_stubs.h make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-ihkkxt3p/src/src' make -C src remote/remote_client_bodies.h make[1]: Entering directory `/var/tmp/patchew-tester-tmp-ihkkxt3p/src/src' GEN remote/remote_client_bodies.h make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-ihkkxt3p/src/src' make -C src admin/admin_server_dispatch_stubs.h make[1]: Entering directory `/var/tmp/patchew-tester-tmp-ihkkxt3p/src/src' GEN admin/admin_server_dispatch_stubs.h make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-ihkkxt3p/src/src' make -C src admin/admin_client.h make[1]: Entering directory `/var/tmp/patchew-tester-tmp-ihkkxt3p/src/src' GEN admin/admin_client.h make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-ihkkxt3p/src/src' po_check 0.01 po_check preprocessor_indentation maint.mk: skipping test sc_preprocessor_indentation: cppi not installed 0.01 preprocessor_indentation prohibit_HAVE_MBRTOWC 0.69 prohibit_HAVE_MBRTOWC prohibit_PATH_MAX 0.75 prohibit_PATH_MAX prohibit_VIR_ERR_NO_MEMORY 0.76 prohibit_VIR_ERR_NO_MEMORY prohibit_access_xok 0.56 prohibit_access_xok prohibit_always-defined_macros 1.24 prohibit_always-defined_macros prohibit_always_true_header_tests 0.72 prohibit_always_true_header_tests prohibit_argmatch_without_use 0.22 prohibit_argmatch_without_use prohibit_asprintf 1.46 prohibit_asprintf prohibit_assert_without_use 0.32 prohibit_assert_without_use prohibit_atoi 0.79 prohibit_atoi prohibit_author 0.83 prohibit_author prohibit_backslash_alignment 0.51 prohibit_backslash_alignment prohibit_backup_files 0.06 prohibit_backup_files prohibit_c_ctype_without_use 0.26 prohibit_c_ctype_without_use prohibit_canonicalize_file_name 0.75 prohibit_canonicalize_file_name prohibit_canonicalize_without_use 0.28 prohibit_canonicalize_without_use prohibit_cloexec_without_use 0.29 prohibit_cloexec_without_use prohibit_close 1.49 prohibit_close prohibit_close_stream_without_use 0.28 prohibit_close_stream_without_use prohibit_config_h_in_headers 0.12 prohibit_config_h_in_headers prohibit_cross_inclusion 6.20 prohibit_cross_inclusion prohibit_ctype_h 0.76 prohibit_ctype_h prohibit_cvs_keyword 0.93 prohibit_cvs_keyword prohibit_defined_have_decl_tests 0.63 prohibit_defined_have_decl_tests prohibit_devname 0.73 prohibit_devname prohibit_diagnostic_without_format 1.39 prohibit_diagnostic_without_format prohibit_dirent_without_use 0.28 prohibit_dirent_without_use prohibit_double_semicolon 0.52 prohibit_double_semicolon prohibit_doubled_word 10.31 prohibit_doubled_word prohibit_empty_first_line 1.01 prohibit_empty_first_line prohibit_empty_lines_at_EOF 0.43 prohibit_empty_lines_at_EOF prohibit_error_without_use 0.31 prohibit_error_without_use prohibit_exit_in_tests 0.22 prohibit_exit_in_tests prohibit_fork_wrappers 0.95 prohibit_fork_wrappers prohibit_getenv 0.65 prohibit_getenv prohibit_gethostname 0.53 prohibit_gethostname prohibit_getopt_without_use 0.31 prohibit_getopt_without_use prohibit_gettext_markup 0.74 prohibit_gettext_markup prohibit_gettext_noop 0.73 prohibit_gettext_noop prohibit_hash_pjw_without_use 0.22 prohibit_hash_pjw_without_use prohibit_have_config_h 0.71 prohibit_have_config_h prohibit_http_urls 0.75 prohibit_http_urls prohibit_ignore_value_without_use 0.27 prohibit_ignore_value_without_use prohibit_include_public_headers_brackets 0.36 prohibit_include_public_headers_brackets prohibit_include_public_headers_quote 0.37 prohibit_include_public_headers_quote prohibit_int_assign_bool 0.88 prohibit_int_assign_bool prohibit_int_ijk 0.80 prohibit_int_ijk prohibit_int_index 0.82 prohibit_int_index prohibit_internal_functions 0.79 prohibit_internal_functions prohibit_intprops_without_use 0.28 prohibit_intprops_without_use prohibit_inttostr_without_use 0.27 prohibit_inttostr_without_use prohibit_libgen 0.96 prohibit_libgen prohibit_long_lines 0.45 prohibit_long_lines prohibit_long_options_without_use 0.27 prohibit_long_options_without_use prohibit_loop_iijjkk 0.95 prohibit_loop_iijjkk prohibit_loop_var_decl 0.25 prohibit_loop_var_decl prohibit_magic_number_exit 0.81 prohibit_magic_number_exit prohibit_mixed_case_abbreviations 0.43 prohibit_mixed_case_abbreviations prohibit_mkstemp 0.79 prohibit_mkstemp prohibit_newline_at_end_of_diagnostic 0.67 prohibit_newline_at_end_of_diagnostic prohibit_nonreentrant 0.29 prohibit_nonreentrant prohibit_not_streq 0.75 prohibit_not_streq prohibit_obj_free_apis_in_virsh 0.16 prohibit_obj_free_apis_in_virsh prohibit_openat_without_use 0.31 prohibit_openat_without_use prohibit_paren_brace 0.41 prohibit_paren_brace prohibit_path_max_allocation 0.50 prohibit_path_max_allocation prohibit_posixver_without_use 0.27 prohibit_posixver_without_use prohibit_pthread_create 0.31 prohibit_pthread_create prohibit_raw_allocation 0.85 prohibit_raw_allocation prohibit_raw_virclassnew 0.60 prohibit_raw_virclassnew prohibit_readdir 0.77 prohibit_readdir prohibit_readlink 0.81 prohibit_readlink prohibit_return_as_function 0.83 prohibit_return_as_function prohibit_reversed_compare_failure 0.52 prohibit_reversed_compare_failure prohibit_risky_id_promotion 0.75 prohibit_risky_id_promotion prohibit_root_dev_ino_without_use 0.26 prohibit_root_dev_ino_without_use prohibit_safe_read_without_use 0.22 prohibit_safe_read_without_use prohibit_same_without_use 0.20 prohibit_same_without_use prohibit_select 0.74 prohibit_select prohibit_semicolon_at_eol_in_python 0.16 prohibit_semicolon_at_eol_in_python prohibit_setuid 0.86 prohibit_setuid prohibit_signal_without_use 0.25 prohibit_signal_without_use prohibit_space_in_label 0.31 prohibit_space_in_label prohibit_sprintf 0.79 prohibit_sprintf prohibit_static_zero_init 0.23 prohibit_static_zero_init prohibit_stddef_without_use 0.20 prohibit_stddef_without_use prohibit_stdio--_without_use 0.23 prohibit_stdio--_without_use prohibit_stdio-safer_without_use 0.27 prohibit_stdio-safer_without_use prohibit_strcmp 0.74 prohibit_strcmp prohibit_strdup 0.83 prohibit_strdup prohibit_strings_without_use 0.27 prohibit_strings_without_use prohibit_strncmp 0.75 prohibit_strncmp prohibit_strncpy 0.76 prohibit_strncpy prohibit_strtol 1.58 prohibit_strtol prohibit_sysconf_pagesize 0.60 prohibit_sysconf_pagesize prohibit_system_error_with_vir_err 0.75 prohibit_system_error_with_vir_err prohibit_test_double_equal 0.56 prohibit_test_double_equal prohibit_test_minus_ao 0.94 prohibit_test_minus_ao prohibit_unbounded_arrays_in_rpc 0.15 prohibit_unbounded_arrays_in_rpc prohibit_unsigned_pid 0.82 prohibit_unsigned_pid prohibit_useless_translation 1.51 prohibit_useless_translation prohibit_verbose_strcat 0.23 prohibit_verbose_strcat prohibit_verify_without_use 0.31 prohibit_verify_without_use prohibit_virBufferAdd_with_string_literal 0.69 prohibit_virBufferAdd_with_string_literal prohibit_virBufferAsprintf_with_string_literal 0.71 prohibit_virBufferAsprintf_with_string_literal prohibit_virConnectOpen_in_virsh 0.16 prohibit_virConnectOpen_in_virsh prohibit_virSecurity 0.15 prohibit_virSecurity prohibit_virXXXFree 0.35 prohibit_virXXXFree prohibit_windows_special_chars_in_filename 0.12 prohibit_windows_special_chars_in_filename prohibit_wrong_filename_in_comment in tests/virnetworkportxml2xmltest.c: virnetworkportdeftest.c mentioned in comments maint.mk: The file name in comments must match the actual file name make: *** [sc_prohibit_wrong_filename_in_comment] Error 1 real 12m41.540s user 10m21.425s sys 4m20.587s === OUTPUT END === Test command exited with code: 2 --- Email generated automatically by Patchew [http://patchew.org/]. Please send your feedback to patchew-devel@redhat.com

On 12/24/18 3:58 PM, Daniel P. Berrangé wrote:
Currently the network driver registers a set of callbacks with the virt driver in order to handle allocating/releasing network ports associated with guest NICs.
This series introduces a virNetworkPortPtr object and associated XML that describes a network port. The virt drivers now call public APIs associated with this new object to create/delete ports for guest NICs.
There are some parts that are not yet addressed by this series
- The live updating of bandwidth limits on network ports - The old code would re-connect VIFs to bridges, and/or change bridges during startup. This code is deleted right now as it doesn't belong in the network driver. It needs to move to the virt drivers in some (to be determined) manner.
Daniel P. Berrangé (27): conf: make virPCIDeviceAddressFormat void network: restrict usage of port management APIs network: pass a virNetworkPtr to port management APIs conf: simplify link from hostdev back to network device network: add missing bandwidth limits for bridge forward type network: use 'bridge' as actual type instead of 'network' virt drivers: don't handle type=network after resolving actual network type network: unconditionally merge port profiles conf: introduce virNetworkPortDefPtr struct and XML support network: stop passing virDomainNetDefPtr into bandwidth functions network: make networkLogAllocation independent of domain conf util: add API for copying virtual port profile data conf: add APIs to convert virDomainNetDef to virNetworkPortDef network: convert networkAllocateActualDevice to virNetworkPortDef network: convert networkNotifyActualDevice to virNetworkPortDef network: convert networkReleaseActualDevice to virNetworkPortDef network: convert hook script to take a network port XML network: introduce networkAllocatePort network: introduce networkNotifyPort network: introduce networkReleasePort network: add public APIs for network port object access: add permissions for network port objects remote: add support for new network port APIs virsh: add support for network port APIs conf: support recording ports against virNetworkObjPtr network: add implementation of network port APIs conf: switch over to use network port APIs for virt drivers
include/libvirt/libvirt-network.h | 49 + include/libvirt/virterror.h | 3 + src/access/genpolkit.pl | 2 +- src/access/viraccessdriver.h | 6 + src/access/viraccessdrivernop.c | 11 + src/access/viraccessdriverpolkit.c | 26 + src/access/viraccessdriverstack.c | 25 + src/access/viraccessmanager.c | 16 + src/access/viraccessmanager.h | 6 + src/access/viraccessperm.c | 8 +- src/access/viraccessperm.h | 38 + src/conf/Makefile.inc.am | 2 + src/conf/device_conf.c | 3 +- src/conf/device_conf.h | 6 +- src/conf/domain_conf.c | 413 ++++++- src/conf/domain_conf.h | 46 +- src/conf/network_conf.c | 7 +- src/conf/storage_adapter_conf.c | 4 +- src/conf/virnetworkobj.c | 303 +++++ src/conf/virnetworkobj.h | 30 + src/conf/virnetworkportdef.c | 497 ++++++++ src/conf/virnetworkportdef.h | 112 ++ src/datatypes.c | 60 + src/datatypes.h | 41 + src/driver-network.h | 27 + src/libvirt-network.c | 351 ++++++ src/libvirt_private.syms | 21 + src/libvirt_public.syms | 14 + src/libxl/libxl_conf.c | 21 +- src/libxl/libxl_domain.c | 28 +- src/libxl/libxl_driver.c | 27 +- src/lxc/lxc_driver.c | 37 +- src/lxc/lxc_process.c | 21 +- src/network/bridge_driver.c | 1069 +++++++++-------- src/qemu/qemu_command.c | 11 +- src/qemu/qemu_domain_address.c | 4 +- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_hotplug.c | 84 +- src/qemu/qemu_hotplug.h | 2 +- src/qemu/qemu_interface.c | 12 +- src/qemu/qemu_process.c | 32 +- src/remote/remote_daemon_dispatch.c | 25 + src/remote/remote_driver.c | 28 + src/remote/remote_protocol.x | 89 +- src/remote_protocol-structs | 47 + src/rpc/gendispatch.pl | 18 +- src/util/virerror.c | 9 + src/util/virhook.c | 4 +- src/util/virhook.h | 4 +- src/util/virhostdev.c | 17 +- src/util/virnetdevvportprofile.c | 16 + src/util/virnetdevvportprofile.h | 2 + tests/Makefile.am | 7 + .../plug-bridge-mactbl.xml | 9 + .../virnetworkportxml2xmldata/plug-bridge.xml | 9 + .../virnetworkportxml2xmldata/plug-direct.xml | 12 + .../plug-hostdev-pci.xml | 12 + tests/virnetworkportxml2xmldata/plug-none.xml | 8 + tests/virnetworkportxml2xmltest.c | 104 ++ tools/virsh-completer.c | 51 + tools/virsh-completer.h | 4 + tools/virsh-network.c | 399 +++++- tools/virsh-network.h | 5 + 63 files changed, 3681 insertions(+), 675 deletions(-) create mode 100644 src/conf/virnetworkportdef.c create mode 100644 src/conf/virnetworkportdef.h create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge-mactbl.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-direct.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-none.xml create mode 100644 tests/virnetworkportxml2xmltest.c
There are few problem with these patches (not the idea). The idea is sound. The first is that "<plug type='bridge' bridge='virbr0'/>" is lost from 'virsh net-port-dumpxml --network default --port $UUID' on daemon restart. The second is that a running domain is lost on daemon restart because of the bandwidth problem I'm mentioning in 09/27: 2019-01-08 16:11:44.945+0000: 127017: error : virNetDevBandwidthParse:174 : unsupported configuration: floor attribute is supported only for interfaces of type network 2019-01-08 16:11:44.945+0000: 127017: error : virDomainObjListLoadAllConfigs:628 : Failed to load config for domain 'fedora' The third is that if there is a domain already running that was starter prior applying these patches I see the following error on daemon restart (the domain is gone too): 2019-01-08 16:11:44.946+0000: 127017: error : virDomainActualNetDefParseXML:10789 : internal error: unsupported type 'user' in interface's <actual> element 2019-01-08 16:11:44.946+0000: 127017: error : virDomainObjListLoadAllConfigs:628 : Failed to load config for domain 'gentoo' Michal
participants (3)
-
Daniel P. Berrangé
-
Michal Privoznik
-
no-reply@patchew.org