[libvirt] [PATCH 09/27] conf: introduce virNetworkPortDefPtr struct and XML support

Daniel P. Berrangé berrange at redhat.com
Mon Dec 24 14:58:57 UTC 2018


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 at 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




More information about the libvir-list mailing list