From 8f8e581a17922520be32df0e574aea5fdf034471 Mon Sep 17 00:00:00 2001 From: Laine Stump Date: Feb 20 2015 20:06:30 +0000 Subject: network: allow together with /
in network status The function that parses the subelement of a network used to fail/log an error if the network definition contained both a element as well as at least one or
element. That check was present because the configuration of a network should have either one , one or more , or one or more
, but never combinations of multiple kinds. This caused a problem when libvirtd was restarted with a network already active - when a network with a element is started, the referenced PF (Physical Function of an SRIOV-capable network card) is checked for VFs (Virtual Functions), and the is filled in with a list of all VFs for that PF either in the form of their PCI addresses (a list of
) or their netdev names (a list of ); the element is not removed though. When libvirtd is restarted, it parses the network status and finds both the original from the config, as well as the list of either
or , fails the parse, and the network is not added to the active list. This failure is often obscured because the network is marked as autostart so libvirt immediately restarts it. It seems odd to me that and
are stored in the same array rather than keeping two separate arrays, and having separate arrays would have made the check much simpler. However, changing to use two separate arrays would have required changes in more places, potentially creating more conflicts and (more importantly) more possible regressions in the event of a backport, so I chose to keep the existing data structure in order to localize the change. It appears that this problem has been in the code ever since support for was added (0.9.10), but until commit 34cc3b2f106e296df5e64309620c79d16fd76c85 (first in libvirt 1.2.4) networks with interface pools were not properly marked as active on restart anyway, so there is no point in backporting this patch any further than that. --- diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index f947d89..dce3360 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -1,7 +1,7 @@ /* * network_conf.c: network XML handling * - * Copyright (C) 2006-2014 Red Hat, Inc. + * Copyright (C) 2006-2015 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -1638,14 +1638,6 @@ virNetworkForwardDefParseXML(const char *networkName, goto cleanup; } - if (((nForwardIfs > 0) + (nForwardAddrs > 0) + (nForwardPfs > 0)) > 1) { - virReportError(VIR_ERR_XML_ERROR, - _("
, , and elements in " - "of network %s are mutually exclusive"), - networkName); - goto cleanup; - } - forwardDev = virXPathString("string(./@dev)", ctxt); if (forwardDev && (nForwardAddrs > 0 || nForwardPfs > 0)) { virReportError(VIR_ERR_XML_ERROR, "%s", diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 404e90b..f240d3b 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2734,6 +2734,7 @@ networkValidate(virNetworkDefPtr def, virNetworkIpDefPtr ipdef; bool ipv4def = false, ipv6def = false; bool bandwidthAllowed = true; + bool usesInterface = false, usesAddress = false; /* check for duplicate networks */ if (virNetworkObjIsDuplicate(&driver->networks, def, check_active) < 0) @@ -2798,6 +2799,40 @@ networkValidate(virNetworkDefPtr def, bandwidthAllowed = false; } + /* we support configs with a single PF defined: + * + * or with a list of netdev names: + * + * OR a list of PCI addresses + *
+ * but not any combination of those. + * + * Since and
are for some strange reason + * stored in the same array, we need to cycle through it and check + * the type of each. + */ + for (i = 0; i < def->forward.nifs; i++) { + switch ((virNetworkForwardHostdevDeviceType) + def->forward.ifs[i].type) { + case VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV: + usesInterface = true; + break; + case VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI: + usesAddress = true; + break; + case VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NONE: + case VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST: + break; + } + } + if ((def->forward.npfs > 0) + usesInterface + usesAddress > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("
, , and elements of " + " in network %s are mutually exclusive"), + def->name); + return -1; + } + /* We only support dhcp on one IPv4 address and * on one IPv6 address per defined network */