On 12/24/18 3:58 PM, Daniel P. Berrangé wrote:
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(a)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)
This must not be -1. The bandwidth corresponds to the interface not the
bridge. If this is -1 then 'floor' is disallowed, which is not what we
want. Maybe we need to change the @net_type argument of
virNetDevBandwidthParse() so that it is bool which allows/denies 'floor'.
+ 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);
+ }
+
+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'/>",
Add "\n" here.
+
virTristateBoolTypeToString(def->trustGuestRxFilters));
+
Michal