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@xxxxxxxxxx> > --- > 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list