diff --git a/cfg.mk b/cfg.mk
index 0a624f1592b0bcc0f74ad07c42eea14e69e60ffc..3024181e2f034bfabca547ae683e13347eed9e4c 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -97,6 +97,7 @@ useless_free_options = \
--name=virCommandFree \
--name=virConfFreeList \
--name=virConfFreeValue \
+ --name=virDomainActualNetDefFree \
--name=virDomainChrDefFree \
--name=virDomainChrSourceDefFree \
--name=virDomainControllerDefFree \
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 8c5c4c996522121fe6d551056ecff7c0c7e69bc7..83146ed7cfbd3cb2a369c8b631828019dea664ac 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1391,24 +1391,55 @@
This is the recommended config for general guest connectivity on
- hosts with dynamic / wireless networking configs
+ hosts with dynamic / wireless networking configs (or multi-host
+ environments where the host hardware details are described
+ separately in a <network>
+ definition Since 0.9.4 ).
- Provides a virtual network using a bridge device in the host.
- Depending on the virtual network configuration, the network may be
- totally isolated, NAT'ing to an explicit network device, or NAT'ing to
- the default route. DHCP and DNS are provided on the virtual network in
- all cases and the IP range can be determined by examining the virtual
- network config with 'virsh net-dumpxml [networkname]
'.
- There is one virtual network called 'default' setup out
- of the box which does NAT'ing to the default route and has an IP range of
- 192.168.122.0/255.255.255.0
. Each guest will have an
- associated tun device created with a name of vnetN, which can also be
- overridden with the <target> element (see
+
+ Provides a connection whose details are described by the named
+ network definition. Depending on the virtual network's "forward
+ mode" configuration, the network may be totally isolated
+ (no <forward>
element given), NAT'ing to an
+ explicit network device or to the default route
+ (<forward mode='nat'>
), routed with no NAT
+ (<forward mode='route'/>
), or connected
+ directly to one of the host's network interfaces (via macvtap)
+ or bridge devices ((<forward
+ mode='bridge|private|vepa|passthrough'/>
Since
+ 0.9.4 )
+
+
+ For networks with a forward mode of bridge, private, vepa, and
+ passthrough, it is assumed that the host has any necessary DNS
+ and DHCP services already setup outside the scope of libvirt. In
+ the case of isolated, nat, and routed networks, DHCP and DNS are
+ provided on the virtual network by libvirt, and the IP range can
+ be determined by examining the virtual network config with
+ 'virsh net-dumpxml [networkname]
'. There is one
+ virtual network called 'default' setup out of the box which does
+ NAT'ing to the default route and has an IP range
+ of 192.168.122.0/255.255.255.0
. Each guest will
+ have an associated tun device created with a name of vnetN,
+ which can also be overridden with the <target> element
+ (see
overriding the target element ).
+
+ When the source of an interface is a network,
+ a portgroup
can be specified along with the name of
+ the network; one network may have multiple portgroups defined,
+ with each portgroup containing slightly different configuration
+ information for different classes of network
+ connections. Since 0.9.4 ). Also,
+ similar to direct
network connections (described
+ below), a connection of type network
may specify
+ a virtportprofile
element, with configuration data
+ to be forwarded to a vepa or 802.1Qbh compliant switch.
+
...
@@ -1418,9 +1449,13 @@
</interface>
...
<interface type='network'>
- <source network='default'/>
+ <source network='default' portgroup='engineering'/>
<target dev='vnet7'/>
<mac address="00:11:22:33:44:55"/>
+ <virtualport type='802.1Qbg'>
+ <parameters managerid='11' typeid='1193047' typeidversion='2' instanceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/>
+ </virtualport>
+
</interface>
</devices>
...
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 564ff68420773c5aac1f0c1afdd47f3e75f028f5..43326ab05af591874eddf6051515a223847df89e 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -1036,8 +1036,16 @@
+
+
+
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 039b47897c60fd3c44671107661ba35344019a64..919a75a76299afe573674e10934dafd0d7dad6e7 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -56,10 +56,11 @@
* verify that it doesn't overflow an unsigned int when shifting */
verify(VIR_DOMAIN_VIRT_LAST <= 32);
-/* Private flag used internally by virDomainSaveStatus and
- * virDomainObjParseFile. */
+/* Private flags used internally by virDomainSaveStatus and
+ * virDomainLoadStatus. */
typedef enum {
VIR_DOMAIN_XML_INTERNAL_STATUS = (1<<16), /* dump internal domain status information */
+ VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET = (1<<17), /* dump/parse element */
} virDomainXMLInternalFlags;
VIR_ENUM_IMPL(virDomainTaint, VIR_DOMAIN_TAINT_LAST,
@@ -734,6 +735,27 @@ void virDomainFSDefFree(virDomainFSDefPtr def)
VIR_FREE(def);
}
+void
+virDomainActualNetDefFree(virDomainActualNetDefPtr def)
+{
+ if (!def)
+ return;
+
+ switch (def->type) {
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ VIR_FREE(def->data.bridge.brname);
+ break;
+ case VIR_DOMAIN_NET_TYPE_DIRECT:
+ VIR_FREE(def->data.direct.linkdev);
+ VIR_FREE(def->data.direct.virtPortProfile);
+ break;
+ default:
+ break;
+ }
+
+ VIR_FREE(def);
+}
+
void virDomainNetDefFree(virDomainNetDefPtr def)
{
if (!def)
@@ -756,6 +778,9 @@ 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:
@@ -2586,6 +2611,81 @@ cleanup:
goto cleanup;
}
+static int
+virDomainActualNetDefParseXML(xmlNodePtr node,
+ xmlXPathContextPtr ctxt,
+ virDomainActualNetDefPtr *def)
+{
+ virDomainActualNetDefPtr actual = NULL;
+ int ret = -1;
+ xmlNodePtr save_ctxt = ctxt->node;
+ char *type = NULL;
+ char *mode = NULL;
+
+ if (VIR_ALLOC(actual) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ ctxt->node = node;
+
+ type = virXMLPropString(node, "type");
+ if (!type) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing type attribute in interface's element"));
+ goto error;
+ }
+ if ((actual->type = virDomainNetTypeFromString(type)) < 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unknown type '%s' in interface's element"), type);
+ goto error;
+ }
+ if (actual->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
+ actual->type != VIR_DOMAIN_NET_TYPE_DIRECT) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unsupported type '%s' in interface's element"),
+ type);
+ goto error;
+ }
+
+ if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+ actual->data.bridge.brname = virXPathString("string(./source[1]/@bridge)", ctxt);
+ } else if (actual->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ xmlNodePtr virtPortNode;
+
+ actual->data.direct.linkdev = virXPathString("string(./source[1]/@dev)", ctxt);
+
+ mode = virXPathString("string(./source[1]/@mode)", ctxt);
+ if (mode) {
+ int m;
+ if ((m = virMacvtapModeTypeFromString(mode)) < 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unkown mode '%s' in interface element"),
+ mode);
+ goto error;
+ }
+ actual->data.direct.mode = m;
+ }
+
+ virtPortNode = virXPathNode("./virtualport", ctxt);
+ if (virtPortNode &&
+ virVirtualPortProfileParseXML(virtPortNode,
+ &actual->data.direct.virtPortProfile) < 0) {
+ goto error;
+ }
+ }
+
+ *def = actual;
+ actual = NULL;
+ ret = 0;
+error:
+ VIR_FREE(type);
+ VIR_FREE(mode);
+ virDomainActualNetDefFree(actual);
+
+ ctxt->node = save_ctxt;
+ return ret;
+}
/* Parse the XML definition for a network interface
* @param node XML nodeset to parse for net definition
@@ -2603,6 +2703,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
char *macaddr = NULL;
char *type = NULL;
char *network = NULL;
+ char *portgroup = NULL;
char *bridge = NULL;
char *dev = NULL;
char *ifname = NULL;
@@ -2619,6 +2720,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
char *mode = NULL;
virNWFilterHashTablePtr filterparams = NULL;
virVirtualPortProfileParamsPtr virtPort = NULL;
+ virDomainActualNetDefPtr actual = NULL;
xmlNodePtr oldnode = ctxt->node;
int ret;
@@ -2650,6 +2752,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
(def->type == VIR_DOMAIN_NET_TYPE_NETWORK) &&
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
network = virXMLPropString(cur, "network");
+ portgroup = virXMLPropString(cur, "portgroup");
} else if ((internal == NULL) &&
(def->type == VIR_DOMAIN_NET_TYPE_INTERNAL) &&
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
@@ -2665,7 +2768,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
dev = virXMLPropString(cur, "dev");
mode = virXMLPropString(cur, "mode");
} else if ((virtPort == NULL) &&
- (def->type == VIR_DOMAIN_NET_TYPE_DIRECT) &&
+ ((def->type == VIR_DOMAIN_NET_TYPE_DIRECT) ||
+ (def->type == VIR_DOMAIN_NET_TYPE_NETWORK)) &&
xmlStrEqual(cur->name, BAD_CAST "virtualport")) {
if (virVirtualPortProfileParseXML(cur, &virtPort) < 0)
goto error;
@@ -2713,6 +2817,12 @@ virDomainNetDefParseXML(virCapsPtr caps,
if (virDomainDeviceBootParseXML(cur, &def->bootIndex,
bootMap))
goto error;
+ } else if ((actual == NULL) &&
+ (flags & VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET) &&
+ (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) &&
+ xmlStrEqual(cur->name, BAD_CAST "actual")) {
+ if (virDomainActualNetDefParseXML(cur, ctxt, &actual) < 0)
+ goto error;
}
}
cur = cur->next;
@@ -2761,6 +2871,12 @@ virDomainNetDefParseXML(virCapsPtr caps,
}
def->data.network.name = network;
network = NULL;
+ def->data.network.portgroup = portgroup;
+ portgroup = NULL;
+ def->data.network.virtPortProfile = virtPort;
+ virtPort = NULL;
+ def->data.network.actual = actual;
+ actual = NULL;
break;
case VIR_DOMAIN_NET_TYPE_ETHERNET:
@@ -2956,11 +3072,13 @@ cleanup:
ctxt->node = oldnode;
VIR_FREE(macaddr);
VIR_FREE(network);
+ VIR_FREE(portgroup);
VIR_FREE(address);
VIR_FREE(port);
VIR_FREE(ifname);
VIR_FREE(dev);
VIR_FREE(virtPort);
+ virDomainActualNetDefFree(actual);
VIR_FREE(script);
VIR_FREE(bridge);
VIR_FREE(model);
@@ -8536,6 +8654,67 @@ virDomainFSDefFormat(virBufferPtr buf,
return 0;
}
+static int
+virDomainActualNetDefFormat(virBufferPtr buf,
+ virDomainActualNetDefPtr def)
+{
+ int ret = -1;
+ const char *type;
+ const char *mode;
+
+ if (!def)
+ return 0;
+
+ type = virDomainNetTypeToString(def->type);
+ if (!type) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected net type %d"), def->type);
+ return ret;
+ }
+
+ if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
+ def->type != VIR_DOMAIN_NET_TYPE_DIRECT) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected net type %s"), type);
+ goto error;
+ }
+ virBufferAsprintf(buf, " \n", type);
+
+ switch (def->type) {
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ if (def->data.bridge.brname) {
+ virBufferEscapeString(buf, " \n",
+ def->data.bridge.brname);
+ }
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_DIRECT:
+ virBufferAddLit(buf, " data.direct.linkdev)
+ virBufferEscapeString(buf, " dev='%s'",
+ def->data.direct.linkdev);
+
+ mode = virMacvtapModeTypeToString(def->data.direct.mode);
+ if (!mode) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected source mode %d"),
+ def->data.direct.mode);
+ return ret;
+ }
+ virBufferAsprintf(buf, " mode='%s'/>\n", mode);
+ virVirtualPortProfileFormat(buf, def->data.direct.virtPortProfile,
+ " ");
+ break;
+ default:
+ break;
+ }
+ virBufferAddLit(buf, " \n");
+
+ ret = 0;
+error:
+ return ret;
+}
+
static int
virDomainNetDefFormat(virBufferPtr buf,
virDomainNetDefPtr def,
@@ -8559,8 +8738,18 @@ virDomainNetDefFormat(virBufferPtr buf,
switch (def->type) {
case VIR_DOMAIN_NET_TYPE_NETWORK:
- virBufferEscapeString(buf, " \n",
+ virBufferEscapeString(buf, " data.network.name);
+ if (def->data.network.portgroup) {
+ virBufferEscapeString(buf, " portgroup='%s'",
+ def->data.network.portgroup);
+ }
+ virBufferAddLit(buf, "/>\n");
+ virVirtualPortProfileFormat(buf, def->data.network.virtPortProfile,
+ " ");
+ if ((flags & VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET) &&
+ (virDomainActualNetDefFormat(buf, def->data.network.actual) < 0))
+ return -1;
break;
case VIR_DOMAIN_NET_TYPE_ETHERNET:
@@ -9445,9 +9634,11 @@ virDomainHostdevDefFormat(virBufferPtr buf,
VIR_DOMAIN_XML_INACTIVE | \
VIR_DOMAIN_XML_UPDATE_CPU)
-verify((VIR_DOMAIN_XML_INTERNAL_STATUS & DUMPXML_FLAGS) == 0);
+verify(((VIR_DOMAIN_XML_INTERNAL_STATUS |
+ VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET)
+ & DUMPXML_FLAGS) == 0);
-/* This internal version can accept VIR_DOMAIN_XML_INTERNAL_STATUS,
+/* This internal version can accept VIR_DOMAIN_XML_INTERNAL_*,
* whereas the public version cannot. */
static char *
virDomainDefFormatInternal(virDomainDefPtr def,
@@ -9459,7 +9650,10 @@ virDomainDefFormatInternal(virDomainDefPtr def,
const char *type = NULL;
int n, allones = 1;
- virCheckFlags(DUMPXML_FLAGS | VIR_DOMAIN_XML_INTERNAL_STATUS, NULL);
+ virCheckFlags(DUMPXML_FLAGS |
+ VIR_DOMAIN_XML_INTERNAL_STATUS |
+ VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET,
+ NULL);
if (!(type = virDomainVirtTypeToString(def->virtType))) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
@@ -10024,7 +10218,10 @@ int virDomainSaveStatus(virCapsPtr caps,
const char *statusDir,
virDomainObjPtr obj)
{
- unsigned int flags = VIR_DOMAIN_XML_SECURE|VIR_DOMAIN_XML_INTERNAL_STATUS;
+ unsigned int flags = (VIR_DOMAIN_XML_SECURE |
+ VIR_DOMAIN_XML_INTERNAL_STATUS |
+ VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET);
+
int ret = -1;
char *xml;
@@ -10115,7 +10312,8 @@ static virDomainObjPtr virDomainLoadStatus(virCapsPtr caps,
goto error;
if (!(obj = virDomainObjParseFile(caps, statusFile, expectedVirtTypes,
- VIR_DOMAIN_XML_INTERNAL_STATUS)))
+ VIR_DOMAIN_XML_INTERNAL_STATUS |
+ VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET)))
goto error;
virUUIDFormat(obj->def->uuid, uuidstr);
@@ -11112,3 +11310,68 @@ virDomainStateReasonFromString(virDomainState state, const char *reason)
return -1;
}
+
+
+/* Some access functions to gloss over the difference between NetDef
+ * () and ActualNetDef (). If the NetDef has an
+ * ActualNetDef, return the requested value from the ActualNetDef,
+ * otherwise return the value from the NetDef.
+ */
+
+int
+virDomainNetGetActualType(virDomainNetDefPtr iface)
+{
+ if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
+ return iface->type;
+ if (!iface->data.network.actual)
+ return iface->type;
+ return iface->data.network.actual->type;
+}
+
+char *
+virDomainNetGetActualBridgeName(virDomainNetDefPtr iface)
+{
+ if (iface->type == VIR_DOMAIN_NET_TYPE_BRIDGE)
+ return iface->data.bridge.brname;
+ if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
+ return NULL;
+ if (!iface->data.network.actual)
+ return NULL;
+ return iface->data.network.actual->data.bridge.brname;
+}
+
+char *
+virDomainNetGetActualDirectDev(virDomainNetDefPtr iface)
+{
+ if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT)
+ return iface->data.direct.linkdev;
+ if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
+ return NULL;
+ if (!iface->data.network.actual)
+ return NULL;
+ return iface->data.network.actual->data.direct.linkdev;
+}
+
+int
+virDomainNetGetActualDirectMode(virDomainNetDefPtr iface)
+{
+ if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT)
+ return iface->data.direct.mode;
+ if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
+ return 0;
+ if (!iface->data.network.actual)
+ return 0;
+ return iface->data.network.actual->data.direct.mode;
+}
+
+virVirtualPortProfileParamsPtr
+virDomainNetGetActualDirectVirtPortProfile(virDomainNetDefPtr iface)
+{
+ if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT)
+ return iface->data.direct.virtPortProfile;
+ if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
+ return NULL;
+ if (!iface->data.network.actual)
+ return NULL;
+ return iface->data.network.actual->data.direct.virtPortProfile;
+}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 0e6354bfced1dfc1f470ac87ae578bec12f44a6c..551946b79b798a29192e94ed7c73ea8093a48295 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -343,6 +343,27 @@ enum virDomainNetVirtioTxModeType {
VIR_DOMAIN_NET_VIRTIO_TX_MODE_LAST,
};
+/* Config that was actually used to bring up interface, after
+ * resolving network reference. This is private data, only used within
+ * libvirt, but still must maintain backward compatibility, because
+ * different versions of libvirt may read the same data file.
+ */
+typedef struct _virDomainActualNetDef virDomainActualNetDef;
+typedef virDomainActualNetDef *virDomainActualNetDefPtr;
+struct _virDomainActualNetDef {
+ int type; /* enum virDomainNetType */
+ union {
+ struct {
+ char *brname;
+ } bridge;
+ struct {
+ char *linkdev;
+ int mode; /* enum virMacvtapMode from util/macvtap.h */
+ virVirtualPortProfileParamsPtr virtPortProfile;
+ } direct;
+ } data;
+};
+
/* Stores the virtual network interface configuration */
typedef struct _virDomainNetDef virDomainNetDef;
typedef virDomainNetDef *virDomainNetDefPtr;
@@ -369,6 +390,17 @@ struct _virDomainNetDef {
} socket; /* any of NET_CLIENT or NET_SERVER or NET_MCAST */
struct {
char *name;
+ char *portgroup;
+ virVirtualPortProfileParamsPtr 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
+ * domain state, but never written to persistent config,
+ * since it needs to be re-allocated whenever the domain
+ * is restarted. It is also never shown to the user, and
+ * the user cannot specify it in XML documents.
+ */
+ virDomainActualNetDefPtr actual;
} network;
struct {
char *brname;
@@ -1340,6 +1372,7 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def);
void virDomainDiskHostDefFree(virDomainDiskHostDefPtr def);
void virDomainControllerDefFree(virDomainControllerDefPtr def);
void virDomainFSDefFree(virDomainFSDefPtr def);
+void virDomainActualNetDefFree(virDomainActualNetDefPtr def);
void virDomainNetDefFree(virDomainNetDefPtr def);
void virDomainSmartcardDefFree(virDomainSmartcardDefPtr def);
void virDomainChrDefFree(virDomainChrDefPtr def);
@@ -1450,6 +1483,13 @@ int virDomainNetIndexByMac(virDomainDefPtr def, const unsigned char *mac);
int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net);
int virDomainNetRemoveByMac(virDomainDefPtr def, const unsigned char *mac);
+int virDomainNetGetActualType(virDomainNetDefPtr iface);
+char *virDomainNetGetActualBridgeName(virDomainNetDefPtr iface);
+char *virDomainNetGetActualDirectDev(virDomainNetDefPtr iface);
+int virDomainNetGetActualDirectMode(virDomainNetDefPtr iface);
+virVirtualPortProfileParamsPtr
+virDomainNetGetActualDirectVirtPortProfile(virDomainNetDefPtr iface);
+
int virDomainControllerInsert(virDomainDefPtr def,
virDomainControllerDefPtr controller);
void virDomainControllerInsertPreAlloced(virDomainDefPtr def,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index f96fbb9ffdaa1e6e22be95f8b590fec0a810841c..f8b6abfa3347819948bfbc9e254fcc7b6e87f778 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -228,6 +228,7 @@ virDomainAuditVcpu;
# domain_conf.h
virDiskNameToBusDeviceIndex;
virDiskNameToIndex;
+virDomainActualNetDefFree;
virDomainAssignDef;
virDomainChrConsoleTargetTypeFromString;
virDomainChrConsoleTargetTypeToString;
@@ -334,6 +335,11 @@ virDomainLoadAllConfigs;
virDomainMemballoonModelTypeFromString;
virDomainMemballoonModelTypeToString;
virDomainNetDefFree;
+virDomainNetGetActualBridgeName;
+virDomainNetGetActualDirectDev;
+virDomainNetGetActualDirectMode;
+virDomainNetGetActualType;
+virDomainNetGetActualDirectVirtPortProfile;
virDomainNetIndexByMac;
virDomainNetInsert;
virDomainNetRemoveByMac;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0f6e0764c5fdc206ccb11d3f8b5186416fa8bea6
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml
@@ -0,0 +1,33 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 1
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index f22872f6d97a3b833571c5ad3c093c4476c8630f..6b1fbf501863518737eafa7159a2b3471a9df8ea 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -158,6 +158,7 @@ mymain(void)
DO_TEST("net-virtio-device");
DO_TEST("net-eth");
DO_TEST("net-eth-ifname");
+ DO_TEST("net-virtio-network-portgroup");
DO_TEST("sound");
DO_TEST("serial-vc");