virtPortProfile is now used by 4 different types of network devices
(NETWORK, BRIDGE, DIRECT, and HOSTDEV), and it's getting cumbersome to
replicate so much code in 4 different places just because each type
has the virtPortProfile in a slightly different place. This patch puts
a single virtPortProfile in a common place (outside the type-specific
union) in both virDomainNetDef and virDomainActualNetDef, and adjusts
the parse and format code (and the few other places where it is used)
accordingly.
Note that when a <virtualport> element is found, the parse functions
verify that the interface is of a type that supports one, otherwise an
error is generated (CONFIG_UNSUPPORTED in the case of <interface>, and
INTERNAL in the case of <actual>, since the contents of <actual> are
always generated by libvirt itself).
---
src/conf/domain_conf.c | 125 +++++++++++++++-----------------------------
src/conf/domain_conf.h | 10 ++--
src/network/bridge_driver.c | 16 +++---
src/qemu/qemu_driver.c | 2 +-
src/qemu/qemu_hotplug.c | 19 +++----
5 files changed, 63 insertions(+), 109 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 58603a3..a3fb1e7 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1003,20 +1003,18 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def)
switch (def->type) {
case VIR_DOMAIN_NET_TYPE_BRIDGE:
VIR_FREE(def->data.bridge.brname);
- VIR_FREE(def->data.bridge.virtPortProfile);
break;
case VIR_DOMAIN_NET_TYPE_DIRECT:
VIR_FREE(def->data.direct.linkdev);
- VIR_FREE(def->data.direct.virtPortProfile);
break;
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
virDomainHostdevDefClear(&def->data.hostdev.def);
- VIR_FREE(def->data.hostdev.virtPortProfile);
break;
default:
break;
}
+ VIR_FREE(def->virtPortProfile);
virNetDevBandwidthFree(def->bandwidth);
VIR_FREE(def);
@@ -1044,14 +1042,12 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
case VIR_DOMAIN_NET_TYPE_NETWORK:
VIR_FREE(def->data.network.name);
VIR_FREE(def->data.network.portgroup);
- VIR_FREE(def->data.network.virtPortProfile);
virDomainActualNetDefFree(def->data.network.actual);
break;
case VIR_DOMAIN_NET_TYPE_BRIDGE:
VIR_FREE(def->data.bridge.brname);
VIR_FREE(def->data.bridge.ipaddr);
- VIR_FREE(def->data.bridge.virtPortProfile);
break;
case VIR_DOMAIN_NET_TYPE_INTERNAL:
@@ -1060,12 +1056,10 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
case VIR_DOMAIN_NET_TYPE_DIRECT:
VIR_FREE(def->data.direct.linkdev);
- VIR_FREE(def->data.direct.virtPortProfile);
break;
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
virDomainHostdevDefClear(&def->data.hostdev.def);
- VIR_FREE(def->data.hostdev.virtPortProfile);
break;
case VIR_DOMAIN_NET_TYPE_USER:
@@ -1073,6 +1067,7 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
break;
}
+ VIR_FREE(def->virtPortProfile);
VIR_FREE(def->script);
VIR_FREE(def->ifname);
@@ -4376,6 +4371,7 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
int ret = -1;
xmlNodePtr save_ctxt = ctxt->node;
xmlNodePtr bandwidth_node = NULL;
+ xmlNodePtr virtPortNode;
char *type = NULL;
char *mode = NULL;
char *addrtype = NULL;
@@ -4408,15 +4404,24 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
goto error;
}
- if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
- xmlNodePtr virtPortNode = virXPathNode("./virtualport", ctxt);
- if (virtPortNode &&
- (!(actual->data.bridge.virtPortProfile =
- virNetDevVPortProfileParse(virtPortNode))))
+ virtPortNode = virXPathNode("./virtualport", ctxt);
+ if (virtPortNode) {
+ if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+ actual->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
+ actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+ if (!(actual->virtPortProfile
+ = virNetDevVPortProfileParse(virtPortNode))) {
+ goto error;
+ }
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("<virtualport> element unsupported for
type='%s'"
+ " in interface's <actual> element"),
type);
goto error;
- } else if (actual->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
- xmlNodePtr virtPortNode;
+ }
+ }
+ if (actual->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
actual->data.direct.linkdev =
virXPathString("string(./source[1]/@dev)", ctxt);
mode = virXPathString("string(./source[1]/@mode)", ctxt);
@@ -4430,14 +4435,7 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
}
actual->data.direct.mode = m;
}
-
- virtPortNode = virXPathNode("./virtualport", ctxt);
- if (virtPortNode &&
- (!(actual->data.direct.virtPortProfile =
- virNetDevVPortProfileParse(virtPortNode))))
- goto error;
} else if (actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
- xmlNodePtr virtPortNode = virXPathNode("./virtualport", ctxt);
virDomainHostdevDefPtr hostdev = &actual->data.hostdev.def;
hostdev->parent.type = VIR_DOMAIN_DEVICE_NET;
@@ -4458,12 +4456,6 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
hostdev, flags) < 0) {
goto error;
}
-
- if (virtPortNode &&
- (!(actual->data.hostdev.virtPortProfile =
- virNetDevVPortProfileParse(virtPortNode)))) {
- goto error;
- }
}
bandwidth_node = virXPathNode("./bandwidth", ctxt);
@@ -4523,7 +4515,6 @@ virDomainNetDefParseXML(virCapsPtr caps,
char *linkstate = NULL;
char *addrtype = NULL;
virNWFilterHashTablePtr filterparams = NULL;
- virNetDevVPortProfilePtr virtPort = NULL;
virDomainActualNetDefPtr actual = NULL;
xmlNodePtr oldnode = ctxt->node;
int ret;
@@ -4570,14 +4561,22 @@ virDomainNetDefParseXML(virCapsPtr caps,
xmlStrEqual(cur->name, BAD_CAST "source")) {
dev = virXMLPropString(cur, "dev");
mode = virXMLPropString(cur, "mode");
- } else if (!virtPort &&
- (def->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
- def->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
- def->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
- def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) &&
- xmlStrEqual(cur->name, BAD_CAST "virtualport")) {
- if (!(virtPort = virNetDevVPortProfileParse(cur)))
+ } else if (!def->virtPortProfile
+ && xmlStrEqual(cur->name, BAD_CAST
"virtualport")) {
+ if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
+ def->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+ def->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
+ def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+ if (!(def->virtPortProfile
+ = virNetDevVPortProfileParse(cur))) {
+ goto error;
+ }
+ } else {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("<virtualport> element unsupported
for"
+ " <interface type='%s'>"),
type);
goto error;
+ }
} else if (!network &&
(def->type == VIR_DOMAIN_NET_TYPE_SERVER ||
def->type == VIR_DOMAIN_NET_TYPE_CLIENT ||
@@ -4694,8 +4693,6 @@ virDomainNetDefParseXML(virCapsPtr caps,
network = NULL;
def->data.network.portgroup = portgroup;
portgroup = NULL;
- def->data.network.virtPortProfile = virtPort;
- virtPort = NULL;
def->data.network.actual = actual;
actual = NULL;
break;
@@ -4724,8 +4721,6 @@ virDomainNetDefParseXML(virCapsPtr caps,
def->data.bridge.ipaddr = address;
address = NULL;
}
- def->data.bridge.virtPortProfile = virtPort;
- virtPort = NULL;
break;
case VIR_DOMAIN_NET_TYPE_CLIENT:
@@ -4789,8 +4784,6 @@ virDomainNetDefParseXML(virCapsPtr caps,
def->data.direct.mode = VIR_NETDEV_MACVLAN_MODE_VEPA;
}
- def->data.direct.virtPortProfile = virtPort;
- virtPort = NULL;
def->data.direct.linkdev = dev;
dev = NULL;
@@ -4819,8 +4812,6 @@ virDomainNetDefParseXML(virCapsPtr caps,
hostdev, flags) < 0) {
goto error;
}
- def->data.hostdev.virtPortProfile = virtPort;
- virtPort = NULL;
break;
case VIR_DOMAIN_NET_TYPE_USER:
@@ -4943,7 +4934,6 @@ cleanup:
VIR_FREE(port);
VIR_FREE(ifname);
VIR_FREE(dev);
- VIR_FREE(virtPort);
virDomainActualNetDefFree(actual);
VIR_FREE(script);
VIR_FREE(bridge);
@@ -11588,12 +11578,6 @@ virDomainActualNetDefFormat(virBufferPtr buf,
case VIR_DOMAIN_NET_TYPE_BRIDGE:
virBufferEscapeString(buf, " <source
bridge='%s'/>\n",
def->data.bridge.brname);
- if (def->data.bridge.virtPortProfile) {
- virBufferAdjustIndent(buf, 6);
- if (virNetDevVPortProfileFormat(def->data.bridge.virtPortProfile, buf)
< 0)
- return -1;
- virBufferAdjustIndent(buf, -6);
- }
break;
case VIR_DOMAIN_NET_TYPE_DIRECT:
@@ -11610,10 +11594,6 @@ virDomainActualNetDefFormat(virBufferPtr buf,
return ret;
}
virBufferAsprintf(buf, " mode='%s'/>\n", mode);
- virBufferAdjustIndent(buf, 8);
- if (virNetDevVPortProfileFormat(def->data.direct.virtPortProfile, buf) <
0)
- goto error;
- virBufferAdjustIndent(buf, -8);
break;
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
@@ -11622,10 +11602,6 @@ virDomainActualNetDefFormat(virBufferPtr buf,
flags, true) < 0) {
return -1;
}
- if (virNetDevVPortProfileFormat(def->data.hostdev.virtPortProfile,
- buf) < 0) {
- return -1;
- }
virBufferAdjustIndent(buf, -8);
break;
@@ -11638,6 +11614,8 @@ virDomainActualNetDefFormat(virBufferPtr buf,
}
virBufferAdjustIndent(buf, 8);
+ if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0)
+ return -1;
if (virNetDevBandwidthFormat(def->bandwidth, buf) < 0)
goto error;
virBufferAdjustIndent(buf, -8);
@@ -11681,10 +11659,6 @@ virDomainNetDefFormat(virBufferPtr buf,
virBufferEscapeString(buf, " portgroup='%s'",
def->data.network.portgroup);
virBufferAddLit(buf, "/>\n");
- virBufferAdjustIndent(buf, 6);
- if (virNetDevVPortProfileFormat(def->data.network.virtPortProfile, buf) <
0)
- return -1;
- virBufferAdjustIndent(buf, -6);
if ((flags & VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET) &&
(virDomainActualNetDefFormat(buf, def->data.network.actual, flags) <
0))
return -1;
@@ -11704,12 +11678,6 @@ virDomainNetDefFormat(virBufferPtr buf,
if (def->data.bridge.ipaddr)
virBufferAsprintf(buf, " <ip address='%s'/>\n",
def->data.bridge.ipaddr);
- if (def->data.bridge.virtPortProfile) {
- virBufferAdjustIndent(buf, 6);
- if (virNetDevVPortProfileFormat(def->data.bridge.virtPortProfile, buf)
< 0)
- return -1;
- virBufferAdjustIndent(buf, -6);
- }
break;
case VIR_DOMAIN_NET_TYPE_SERVER:
@@ -11734,10 +11702,6 @@ virDomainNetDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " mode='%s'",
virNetDevMacVLanModeTypeToString(def->data.direct.mode));
virBufferAddLit(buf, "/>\n");
- virBufferAdjustIndent(buf, 6);
- if (virNetDevVPortProfileFormat(def->data.direct.virtPortProfile, buf) <
0)
- return -1;
- virBufferAdjustIndent(buf, -6);
break;
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
@@ -11746,10 +11710,6 @@ virDomainNetDefFormat(virBufferPtr buf,
flags, true) < 0) {
return -1;
}
- if (virNetDevVPortProfileFormat(def->data.hostdev.virtPortProfile,
- buf) < 0) {
- return -1;
- }
virBufferAdjustIndent(buf, -6);
break;
@@ -11758,6 +11718,11 @@ virDomainNetDefFormat(virBufferPtr buf,
break;
}
+ virBufferAdjustIndent(buf, 6);
+ if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0)
+ return -1;
+ virBufferAdjustIndent(buf, -6);
+
virBufferEscapeString(buf, " <script path='%s'/>\n",
def->script);
if (def->ifname &&
@@ -15090,21 +15055,17 @@ virDomainNetGetActualVirtPortProfile(virDomainNetDefPtr iface)
{
switch (iface->type) {
case VIR_DOMAIN_NET_TYPE_DIRECT:
- return iface->data.direct.virtPortProfile;
case VIR_DOMAIN_NET_TYPE_BRIDGE:
- return iface->data.bridge.virtPortProfile;
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
- return iface->data.hostdev.virtPortProfile;
+ return iface->virtPortProfile;
case VIR_DOMAIN_NET_TYPE_NETWORK:
if (!iface->data.network.actual)
return NULL;
switch (iface->data.network.actual->type) {
case VIR_DOMAIN_NET_TYPE_DIRECT:
- return iface->data.network.actual->data.direct.virtPortProfile;
case VIR_DOMAIN_NET_TYPE_BRIDGE:
- return iface->data.network.actual->data.bridge.virtPortProfile;
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
- return iface->data.network.actual->data.hostdev.virtPortProfile;
+ return iface->data.network.actual->virtPortProfile;
default:
return NULL;
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index f4c43c6..dc8c009 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -769,18 +769,16 @@ struct _virDomainActualNetDef {
union {
struct {
char *brname;
- virNetDevVPortProfilePtr virtPortProfile;
} bridge;
struct {
char *linkdev;
int mode; /* enum virMacvtapMode from util/macvtap.h */
- virNetDevVPortProfilePtr virtPortProfile;
} direct;
struct {
virDomainHostdevDef def;
- virNetDevVPortProfilePtr virtPortProfile;
} hostdev;
} data;
+ virNetDevVPortProfilePtr virtPortProfile;
virNetDevBandwidthPtr bandwidth;
};
@@ -809,7 +807,6 @@ struct _virDomainNetDef {
struct {
char *name;
char *portgroup;
- virNetDevVPortProfilePtr virtPortProfile;
/* actual has info about the currently used physical
* device (if the network is of type
* bridge/private/vepa/passthrough). This is saved in the
@@ -823,7 +820,6 @@ struct _virDomainNetDef {
struct {
char *brname;
char *ipaddr;
- virNetDevVPortProfilePtr virtPortProfile;
} bridge;
struct {
char *name;
@@ -831,13 +827,13 @@ struct _virDomainNetDef {
struct {
char *linkdev;
int mode; /* enum virMacvtapMode from util/macvtap.h */
- virNetDevVPortProfilePtr virtPortProfile;
} direct;
struct {
virDomainHostdevDef def;
- virNetDevVPortProfilePtr virtPortProfile;
} hostdev;
} data;
+ /* virtPortProfile is used by network/bridge/direct/hostdev */
+ virNetDevVPortProfilePtr virtPortProfile;
struct {
bool sndbuf_specified;
unsigned long sndbuf;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index a5046f1..d9646fb 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -2854,8 +2854,8 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
}
/* Find the most specific virtportprofile and copy it */
- if (iface->data.network.virtPortProfile) {
- virtport = iface->data.network.virtPortProfile;
+ if (iface->virtPortProfile) {
+ virtport = iface->virtPortProfile;
} else {
if (portgroup)
virtport = portgroup->virtPortProfile;
@@ -2863,14 +2863,14 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
virtport = netdef->virtPortProfile;
}
if (virtport) {
- if (VIR_ALLOC(iface->data.network.actual->data.direct.virtPortProfile)
< 0) {
+ if (VIR_ALLOC(iface->data.network.actual->virtPortProfile) < 0) {
virReportOOMError();
goto cleanup;
}
/* There are no pointers in a virtualPortProfile, so a shallow copy
* is sufficient
*/
- *iface->data.network.actual->data.direct.virtPortProfile = *virtport;
+ *iface->data.network.actual->virtPortProfile = *virtport;
}
/* If there is only a single device, just return it (caller will detect
@@ -2935,8 +2935,8 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
}
}
} else if ((netdef->forwardType == VIR_NETWORK_FORWARD_PRIVATE)
&&
- iface->data.network.actual->data.direct.virtPortProfile
&&
-
(iface->data.network.actual->data.direct.virtPortProfile->virtPortType
+ iface->data.network.actual->virtPortProfile &&
+
(iface->data.network.actual->virtPortProfile->virtPortType
== VIR_NETDEV_VPORT_PROFILE_8021QBH)) {
/* pick first dev with 0 usageCount */
@@ -3068,8 +3068,8 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
if ((dev->usageCount > 0) &&
((netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH) ||
((netdef->forwardType == VIR_NETWORK_FORWARD_PRIVATE) &&
- iface->data.network.actual->data.direct.virtPortProfile &&
-
(iface->data.network.actual->data.direct.virtPortProfile->virtPortType
+ iface->data.network.actual->virtPortProfile &&
+ (iface->data.network.actual->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"),
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 369e8ed..77f6741 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4732,7 +4732,6 @@ static char *qemuDomainXMLToNative(virConnectPtr conn,
}
} else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
VIR_FREE(net->data.direct.linkdev);
- VIR_FREE(net->data.direct.virtPortProfile);
memset(net, 0, sizeof(*net));
@@ -4752,6 +4751,7 @@ static char *qemuDomainXMLToNative(virConnectPtr conn,
net->data.ethernet.dev = brname;
net->data.ethernet.ipaddr = ipaddr;
}
+ VIR_FREE(net->virtPortProfile);
net->info.bootIndex = bootIndex;
}
for (i = 0 ; i < def->ngraphics ; i++) {
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 71ec484..8cddf7d 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1329,6 +1329,11 @@ int qemuDomainChangeNet(struct qemud_driver *driver,
return -1;
}
+ if (!virNetDevVPortProfileEqual(olddev->virtPortProfile, dev->virtPortProfile))
{
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("cannot change <virtualport> settings"));
+ }
+
switch (olddev->type) {
case VIR_DOMAIN_NET_TYPE_USER:
break;
@@ -1356,8 +1361,7 @@ int qemuDomainChangeNet(struct qemud_driver *driver,
case VIR_DOMAIN_NET_TYPE_NETWORK:
if (STRNEQ_NULLABLE(olddev->data.network.name, dev->data.network.name) ||
- STRNEQ_NULLABLE(olddev->data.network.portgroup,
dev->data.network.portgroup) ||
- !virNetDevVPortProfileEqual(olddev->data.network.virtPortProfile,
dev->data.network.virtPortProfile)) {
+ STRNEQ_NULLABLE(olddev->data.network.portgroup,
dev->data.network.portgroup)) {
virReportError(VIR_ERR_NO_SUPPORT, "%s",
_("cannot modify network device configuration"));
return -1;
@@ -1366,13 +1370,7 @@ int qemuDomainChangeNet(struct qemud_driver *driver,
break;
case VIR_DOMAIN_NET_TYPE_BRIDGE:
- /* allow changing brname, but not portprofile */
- if (!virNetDevVPortProfileEqual(olddev->data.bridge.virtPortProfile,
- dev->data.bridge.virtPortProfile)) {
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("cannot modify bridge network device
configuration"));
- return -1;
- }
+ /* allow changing brname */
break;
case VIR_DOMAIN_NET_TYPE_INTERNAL:
@@ -1385,8 +1383,7 @@ int qemuDomainChangeNet(struct qemud_driver *driver,
case VIR_DOMAIN_NET_TYPE_DIRECT:
if (STRNEQ_NULLABLE(olddev->data.direct.linkdev, dev->data.direct.linkdev)
||
- olddev->data.direct.mode != dev->data.direct.mode ||
- !virNetDevVPortProfileEqual(olddev->data.direct.virtPortProfile,
dev->data.direct.virtPortProfile)) {
+ olddev->data.direct.mode != dev->data.direct.mode) {
virReportError(VIR_ERR_NO_SUPPORT, "%s",
_("cannot modify direct network device
configuration"));
return -1;
--
1.7.11.2