On 11/24/2014 12:48 PM, Laine Stump wrote:
When the actualType of a virDomainNetDef is "network", it
means that
we are connecting to a libvirt-managed network (routed, natted, or
isolated) which does use a bridge device (created by libvirt). In the
past we have required drivers such as qemu to call the public API to
retrieve the bridge name in this case (even though it is available in
the NetDef's ActualNetDef if the actualType is "bridge" (i.e., an
externally-created bridge that isn't managed by libvirt). There is no
real reason for this difference, and as a matter of fact it
complicates things for qemu. Also, there is another bridge-related
attribute (promiscLinks) that will need to be available in both cases,
so this makes things consistent.
Along with making the bridge name available in the internal object, it
is also now reported in the <source> element of the <interface> state
XML (or the <actual> subelement in the internally-stored format).
The one oddity about this change is that usually there is a separate
union for every different "type" in a higher level object (e.g. in the
case of a virDomainNetDef there are separate "network" and "bridge"
members of the union that pivots on the type), but in this case
network and bridge types both have exactly the same attributes, so the
"bridge" member is used for both type==network and type==bridge.
---
src/conf/domain_conf.c | 102 +++++++++++++++++++++++---------------------
src/network/bridge_driver.c | 9 ++++
2 files changed, 62 insertions(+), 49 deletions(-)
I'm happy someone understands the comings and goings of actual!
Seems reasonable... Is there any concern vis-a-vis migration (or similar
guest state saving activities) with respect to having a <source> element
in the output for actual that wouldn't have been there before? (if I'm
reading the tea leaves correctly - that's what's happening here).
ACK in general - nothing jumps out at me other than the display/saving
of the <source>
John
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 68eef54..932bb1c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1352,6 +1352,7 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def)
switch (def->type) {
case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
VIR_FREE(def->data.bridge.brname);
break;
case VIR_DOMAIN_NET_TYPE_DIRECT:
@@ -7074,9 +7075,12 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
goto error;
}
VIR_FREE(class_id);
- } else if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+ }
+ if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+ actual->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
char *brname = virXPathString("string(./source/@bridge)", ctxt);
- if (!brname) {
+
+ if (!brname && actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing <source> element with bridge name in
"
"interface's <actual> element"));
@@ -17015,60 +17019,59 @@ virDomainHostdevDefFormatCaps(virBufferPtr buf,
static int
virDomainActualNetDefContentsFormat(virBufferPtr buf,
virDomainNetDefPtr def,
- const char *typeStr,
bool inSubelement,
unsigned int flags)
{
- const char *mode;
-
- switch (virDomainNetGetActualType(def)) {
- case VIR_DOMAIN_NET_TYPE_BRIDGE:
- virBufferEscapeString(buf, "<source bridge='%s'/>\n",
- virDomainNetGetActualBridgeName(def));
- break;
-
- case VIR_DOMAIN_NET_TYPE_DIRECT:
- virBufferAddLit(buf, "<source");
- virBufferEscapeString(buf, " dev='%s'",
- virDomainNetGetActualDirectDev(def));
+ int actualType = virDomainNetGetActualType(def);
- mode = virNetDevMacVLanModeTypeToString(virDomainNetGetActualDirectMode(def));
- if (!mode) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("unexpected source mode %d"),
- virDomainNetGetActualDirectMode(def));
- return -1;
- }
- virBufferAsprintf(buf, " mode='%s'/>\n", mode);
- break;
-
- case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+ if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
if (virDomainHostdevDefFormatSubsys(buf, virDomainNetGetActualHostdev(def),
flags, true) < 0) {
return -1;
}
- break;
-
- case VIR_DOMAIN_NET_TYPE_NETWORK:
- if (!inSubelement) {
- /* the <source> element isn't included in <actual>
- * (i.e. when we're putting our output into a subelement
- * rather than inline) because the main element has the
- * same info already. If we're outputting inline, though,
- * we *do* need to output <source>, because the caller
- * won't have done it.
+ } else {
+ virBufferAddLit(buf, "<source");
+ if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK && !inSubelement) {
+ /* When we're putting our output into the <actual>
+ * subelement rather than the main <interface>, the
+ * network name isn't included in the <source> because the
+ * main interface element's <source> has the same info
+ * already. If we've been called to output directly into
+ * the main element's <source> though (the case here -
+ * "!inSubElement"), we *do* need to output the network
+ * name, because the caller won't have done it).
*/
- virBufferEscapeString(buf, "<source
network='%s'/>\n",
- def->data.network.name);
+ virBufferEscapeString(buf, " network='%s'",
def->data.network.name);
}
- if (def->data.network.actual &&
def->data.network.actual->class_id)
- virBufferAsprintf(buf, "<class id='%u'/>\n",
- def->data.network.actual->class_id);
- break;
- default:
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("unexpected actual net type %s"), typeStr);
- return -1;
+ if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+ actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
+ /* actualType == NETWORK includes the name of the bridge
+ * that is used by the network, whether we are
+ * "inSubElement" or not.
+ */
+ virBufferEscapeString(buf, " bridge='%s'",
+ virDomainNetGetActualBridgeName(def));
+ } else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ const char *mode;
+
+ virBufferEscapeString(buf, " dev='%s'",
+ virDomainNetGetActualDirectDev(def));
+ mode =
virNetDevMacVLanModeTypeToString(virDomainNetGetActualDirectMode(def));
+ if (!mode) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected source mode %d"),
+ virDomainNetGetActualDirectMode(def));
+ return -1;
+ }
+ virBufferAsprintf(buf, " mode='%s'", mode);
+ }
+
+ virBufferAddLit(buf, "/>\n");
+ }
+ if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT &&
+ def->data.network.actual && def->data.network.actual->class_id)
{
+ virBufferAsprintf(buf, "<class id='%u'/>\n",
+ def->data.network.actual->class_id);
}
if (virNetDevVlanFormat(virDomainNetGetActualVlan(def), buf) < 0)
@@ -17116,7 +17119,7 @@ virDomainActualNetDefFormat(virBufferPtr buf,
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2);
- if (virDomainActualNetDefContentsFormat(buf, def, typeStr, true, flags) < 0)
+ if (virDomainActualNetDefContentsFormat(buf, def, true, flags) < 0)
return -1;
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</actual>\n");
@@ -17287,7 +17290,7 @@ virDomainNetDefFormat(virBufferPtr buf,
* the standard place... (this is for public reporting of
* interface status)
*/
- if (virDomainActualNetDefContentsFormat(buf, def, typeStr, false, flags) <
0)
+ if (virDomainActualNetDefContentsFormat(buf, def, false, flags) < 0)
return -1;
} else {
/* ...but if we've asked for the inactive XML (rather than
@@ -20638,7 +20641,8 @@ virDomainNetGetActualBridgeName(virDomainNetDefPtr iface)
return iface->data.bridge.brname;
if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
iface->data.network.actual &&
- iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE)
+ (iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+ iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_NETWORK))
return iface->data.network.actual->data.bridge.brname;
return NULL;
}
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 6cb421c..92efd7e 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -3771,6 +3771,15 @@ networkAllocateActualDevice(virDomainDefPtr dom,
*/
iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_NETWORK;
+ /* we also store the bridge device
+ * 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)
+ goto error;
+
if (networkPlugBandwidth(network, iface) < 0)
goto error;