From nobody Wed May 8 20:24:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1557848935; cv=none; d=zoho.com; s=zohoarc; b=oYvkBhnsU/KYeKXA2LfEw7/nJmCPmh4mnzLDKYqXuNiq9qs2a/1z+t+FqSFEzTRsK88WKE/xfOrKfmSBzc9UrRJHjoWy/FhJCEWjMgM8OYms/DBYxI0ON8aD0fNfSLUaAHx44MNLG7CeT8cUedNe/y5Vhjgc7DxyTJiSlsimkBI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557848935; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=e42ZdY/IVOmV0GmCp131jyEmBZTGlkzZHTWAbSeN8Tc=; b=hLno3Mmldn36Vh7yjB4l0If1hOBWpu8gyniSEl9HLsexBbLEpMgZ8leXhF/7HB4CYffAHWAY57MtPLpBFPPL5vai13kUHfiliBLTfW3xPyJXC45AywKEryEdoRDo9AvY6kbITTRkwnZoCTlFW/wiMR0TXgu+XfmI9eudRESbvjI= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1557848935180479.85408222037177; Tue, 14 May 2019 08:48:55 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 40B7059479; Tue, 14 May 2019 15:48:53 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E44135D730; Tue, 14 May 2019 15:48:52 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 84CDF3FB10; Tue, 14 May 2019 15:48:52 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x4EFmhwB031732 for ; Tue, 14 May 2019 11:48:43 -0400 Received: by smtp.corp.redhat.com (Postfix) id C6B912B9E3; Tue, 14 May 2019 15:48:43 +0000 (UTC) Received: from dhcp-17-248.lcy.redhat.com (unknown [10.42.17.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id D0FE363B86; Tue, 14 May 2019 15:48:40 +0000 (UTC) From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Date: Tue, 14 May 2019 16:48:14 +0100 Message-Id: <20190514154836.6427-3-berrange@redhat.com> In-Reply-To: <20190514154836.6427-1-berrange@redhat.com> References: <20190514154836.6427-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com Cc: Laine Stump Subject: [libvirt] [PATCH v5 02/24] conf: introduce virNetworkPortDefPtr struct and XML support X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Tue, 14 May 2019 15:48:53 +0000 (UTC) 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=C3=A9 Reviewed-by: Laine Stump --- docs/docs.html.in | 1 + docs/formatnetworkport.html.in | 212 ++++++++ docs/schemas/networkport.rng | 165 ++++++ src/conf/Makefile.inc.am | 2 + src/conf/virnetworkportdef.c | 509 ++++++++++++++++++ src/conf/virnetworkportdef.h | 113 ++++ src/libvirt_private.syms | 10 + tests/Makefile.am | 7 + .../plug-bridge-mactbl.xml | 9 + .../virnetworkportxml2xmldata/plug-bridge.xml | 15 + .../virnetworkportxml2xmldata/plug-direct.xml | 12 + .../plug-hostdev-pci.xml | 12 + .../plug-network.xml | 16 + tests/virnetworkportxml2xmldata/plug-none.xml | 8 + tests/virnetworkportxml2xmltest.c | 104 ++++ tests/virschematest.c | 1 + 16 files changed, 1196 insertions(+) create mode 100644 docs/formatnetworkport.html.in create mode 100644 docs/schemas/networkport.rng 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-network.xml create mode 100644 tests/virnetworkportxml2xmldata/plug-none.xml create mode 100644 tests/virnetworkportxml2xmltest.c diff --git a/docs/docs.html.in b/docs/docs.html.in index d0ff844d0c..c8674e1457 100644 --- a/docs/docs.html.in +++ b/docs/docs.html.in @@ -72,6 +72,7 @@
Description of the XML schemas for domains, networks, + network ports, network filtering, storage, storage encryption, diff --git a/docs/formatnetworkport.html.in b/docs/formatnetworkport.html.in new file mode 100644 index 0000000000..0211518a6a --- /dev/null +++ b/docs/formatnetworkport.html.in @@ -0,0 +1,212 @@ + + + + +

Network XML format

+ +
    +
+ +

+ This page provides an introduction to the network port XML format. + This stores information about the connection between an virtual + interface on a virtual domain's, and the virtual network it is + attached to. +

+ +

Element and attribute overview

+ +

+ The root element required for all virtual network ports is + named networkport and has no configurable attributes + The network port XML format is available since + 5.4.0 +

+ +

General metadata

+ +

+ The first elements provide basic metadata about the virtual + network port. +

+ +
+<networkport
+  <uuid>7ae63b5f-fe96-4af0-a7c3-da04ba1b3f54</uuid>
+  <owner>
+    <uuid>06578fc1-c686-46fa-bc2c-220893b466a6</uuid>
+    <name>myguest<name>
+  </owner>
+  <group>webfront<group>
+  <mac address=3D'52:54:0:7b:35:93'/>
+  ...
+ +
+
uuid
+
The content of the uuid element provides + a globally unique identifier for the virtual network port. + The format must be RFC 4122 compliant, eg 3e3fce45-4f53-4fa7= -bb32-11f34168b82b. + If omitted when defining/creating a new network port, a random + UUID is generated.
+
The owner node records the domain object that + is the owner of the network port. It contains two child nodes: +
+
uuid
+
The content of the uuid element provides + a globally unique identifier for the virtual domain.
+
name
+
The unique name of the virtual domain
+
+
+
group
+
The port group in the virtual network to which the + port belongs. Can be omitted if no port groups are + defined on the network.
+
mac
+
The address attribute provides the MAC + address of the virtual port that will be see by the + guest. The MAC address must not start with 0xFE as this + byte is reserved for use on the host side of the port. +
+
+ +

Common elements

+ +

+ The following elements are common to one of more of the plug + types listed later +

+ +
+  ...
+  <bandwidth>
+    <inbound average=3D'1000' peak=3D'5000' floor=3D'200' burst=3D'1024=
'/>
+    <outbound average=3D'128' peak=3D'256' burst=3D'256'/>
+  </bandwidth>
+  <rxfilters trustGuest=3D'yes'/>
+  <virtualport type=3D'802.1Qbg'>
+    <parameters managerid=3D'11' typeid=3D'1193047' typeidversion=3D'2'=
/>
+  </virtualport>
+  ...
+ +
+
bandwidth
+
This part of the network port XML provides setting quality of se= rvice. + Incoming and outgoing traffic can be shaped independently. + The bandwidth element and its child elements are desc= ribed + in the QoS section of + the Network XML. In addition the classID attribute may + exist provide the ID of the traffic shaping class that is active. +
+
rxfilters
+
The rxfilters element property + trustGuestRxFilters provides the + capability for the host to detect and trust reports from the + guest regarding changes to the interface mac address and receive + filters by setting the attribute to yes. The default + setting for the attribute is no for security + reasons and support depends on the guest network device model as + well as the type of connection on the host - currently it is + only supported for the virtio device model and for macvtap + connections on the host. +
+
virtualport
+
The virtualport element describes metadata that + needs to be provided to the underlying network subsystem. It + is described in the domain XML + interface documentation= . +
+
+ + +

Plugs

+ +

+ The plug element has varying content depending + on the value of the type attribute. +

+ +

Network

+ +

+ The network plug type refers to a managed virtual + network plug that is based on a traditional software bridge + device privately managed by libvirt. +

+ +
+  ...
+  <plug type=3D'network' bridge=3D'virbr0'>
+  ...
+ +

+ The bridge attribute provides the name of the + privately managed bridge device associated with the virtual + network. +

+ +

Bridge

+ +

+ The bridge plug type refers to an externally + managed traditional software bridge. +

+ +
+  ...
+  <plug type=3D'bridge' bridge=3D'br2'>
+  ...
+ +

+ The bridge attribute provides the name of the + externally managed bridge device associated with the virtual + network. +

+ +

Direct

+ +

+ The direct plug type refers to an connection + directly to a physical network interface. +

+ +
+  ...
+  <plug type=3D'direct' dev=3D'ens3' mode=3D'vepa'/>
+  ...
+ +

+ The dev attribute provides the name of the + physical network interface to which the port will be + connected. The mode attribute describes + how the connection will be setup and takes the same + values described in the + domain XML. +

+ +

Host PCI

+ +

+ The hostdev-pci plug type refers to the + passthrough of a physical PCI device rather than emulation. +

+ +
+  ...
+  <plug type=3D'hostdev-pci' managed=3D'yes'>
+    <driver name=3D'vfio'/>
+    <address domain=3D'0x0001' bus=3D'0x02' slot=3D'0x03' function=3D'0=
x4'/>
+  </plug>
+  ...
+ +

+ The managed attribute indicates who is responsible for + managing the PCI device in the host. When set to the value yes= + libvirt is responsible for automatically detaching the device from h= ost + drivers and resetting it if needed. If the value is no, + some other party must ensure the device is not attached to any + host drivers. +

+ + + diff --git a/docs/schemas/networkport.rng b/docs/schemas/networkport.rng new file mode 100644 index 0000000000..8192f6efc4 --- /dev/null +++ b/docs/schemas/networkport.rng @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + network + + + + + + + + + + + + + + bridge + + + + + + + + + + + + + + direct + + + + + + + bridge + passthrough + private + vepa + + + + + + + hostdev-pci + + + + + + + + + + + kvm + vfio + + + + + + + + + + + diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am index 3e9fdd1aea..6b52ba674b 100644 --- a/src/conf/Makefile.inc.am +++ b/src/conf/Makefile.inc.am @@ -7,6 +7,8 @@ NETDEV_CONF_SOURCES =3D \ conf/netdev_vport_profile_conf.c \ conf/netdev_vlan_conf.h \ conf/netdev_vlan_conf.c \ + conf/virnetworkportdef.h \ + conf/virnetworkportdef.c \ $(NULL) =20 DOMAIN_CONF_SOURCES =3D \ diff --git a/src/conf/virnetworkportdef.c b/src/conf/virnetworkportdef.c new file mode 100644 index 0000000000..6c896968ce --- /dev/null +++ b/src/conf/virnetworkportdef.c @@ -0,0 +1,509 @@ +/* + * 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 + * . + */ + +#include + +#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", "network", "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_NETWORK: + 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 =3D NULL; + xmlNodePtr virtPortNode; + xmlNodePtr vlanNode; + xmlNodePtr bandwidthNode; + xmlNodePtr addressNode; + char *trustGuestRxFilters =3D NULL; + char *mac =3D NULL; + char *macmgr =3D NULL; + char *mode =3D NULL; + char *plugtype =3D NULL; + char *managed =3D NULL; + char *driver =3D NULL; + char *class_id =3D NULL; + + if (VIR_ALLOC(def) < 0) + return NULL; + + uuid =3D 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 =3D 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 =3D 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 =3D virXPathString("string(./group)", ctxt); + + virtPortNode =3D virXPathNode("./virtualport", ctxt); + if (virtPortNode && + (!(def->virtPortProfile =3D virNetDevVPortProfileParse(virtPortNod= e, 0)))) { + goto error; + } + + mac =3D 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 =3D virXPathNode("./bandwidth", ctxt); + /* + * We don't know if the port will allow the "floor" param or + * not at this stage, so we must just tell virNetDevBandwidthParse + * to allow it regardless. Any bad config must be reported at + * time of use instead. + */ + if (bandwidthNode && + virNetDevBandwidthParse(&def->bandwidth, &def->class_id, + bandwidthNode, true) < 0) + goto error; + + vlanNode =3D virXPathNode("./vlan", ctxt); + if (vlanNode && virNetDevVlanParse(vlanNode, ctxt, &def->vlan) < 0) + goto error; + + + trustGuestRxFilters + =3D virXPathString("string(./rxfilters/@trustGuest)", ctxt); + if (trustGuestRxFilters) { + if ((def->trustGuestRxFilters + =3D virTristateBoolTypeFromString(trustGuestRxFilters)) <=3D = 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid guest rx filters trust setting '%s' = "), + trustGuestRxFilters); + goto error; + } + } + + plugtype =3D virXPathString("string(./plug/@type)", ctxt); + + if (plugtype && + (def->plugtype =3D 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_NETWORK: + case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE: + if (!(def->plug.bridge.brname =3D virXPathString("string(./plug/@b= ridge)", ctxt))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing network port bridge name")); + goto error; + } + macmgr =3D virXPathString("string(./plug/@macTableManager)", ctxt); + if (macmgr && + (def->plug.bridge.macTableManager =3D + virNetworkBridgeMACTableManagerTypeFromString(macmgr)) <=3D 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 =3D virXPathString("string(./plug/@= dev)", ctxt))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing network port link device name")); + goto error; + } + mode =3D virXPathString("string(./plug/@mode)", ctxt); + if (mode && + (def->plug.direct.mode =3D + 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 =3D virXPathString("string(./plug/@managed)", ctxt); + if (managed && + (def->plug.hostdevpci.managed =3D + virTristateBoolTypeFromString(managed)) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid managed setting '%s' in network port= "), mode); + goto error; + } + driver =3D virXPathString("string(./plug/driver/@name)", ctxt); + if (driver && + (def->plug.hostdevpci.driver =3D + virNetworkForwardDriverNameTypeFromString(driver)) <=3D 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing network port driver name")); + goto error; + } + if (!(addressNode =3D 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(class_id); + 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 =3D NULL; + goto cleanup; +} + + +virNetworkPortDefPtr +virNetworkPortDefParseNode(xmlDocPtr xml, + xmlNodePtr root) +{ + xmlXPathContextPtr ctxt =3D NULL; + virNetworkPortDefPtr def =3D NULL; + + if (STRNEQ((const char *)root->name, "networkport")) { + virReportError(VIR_ERR_XML_ERROR, + "%s", + _("unknown root element for network port")); + goto cleanup; + } + + ctxt =3D xmlXPathNewContext(xml); + if (ctxt =3D=3D NULL) { + virReportOOMError(); + goto cleanup; + } + + ctxt->node =3D root; + def =3D virNetworkPortDefParseXML(ctxt); + + cleanup: + xmlXPathFreeContext(ctxt); + return def; +} + + +static virNetworkPortDefPtr +virNetworkPortDefParse(const char *xmlStr, + const char *filename) +{ + virNetworkPortDefPtr def =3D NULL; + xmlDocPtr xml; + + if ((xml =3D virXMLParse(filename, xmlStr, _("(networkport_definition)= ")))) { + def =3D 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 =3D 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, "\n"); + + virBufferAdjustIndent(buf, 2); + + virUUIDFormat(def->uuid, uuid); + virBufferAsprintf(buf, "%s\n", uuid); + + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + virBufferEscapeString(buf, "%s\n", def->ownername); + virUUIDFormat(def->owneruuid, uuid); + virBufferAsprintf(buf, "%s\n", uuid); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + + if (def->group) + virBufferEscapeString(buf, "%s\n", def->group); + + virMacAddrFormat(&def->mac, macaddr); + virBufferAsprintf(buf, "\n", macaddr); + + if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0) + return -1; + if (def->bandwidth) + virNetDevBandwidthFormat(def->bandwidth, def->class_id, buf); + if (virNetDevVlanFormat(&def->vlan, buf) < 0) + return -1; + if (def->trustGuestRxFilters) + virBufferAsprintf(buf, "\n", + virTristateBoolTypeToString(def->trustGuestRxFil= ters)); + + if (def->plugtype !=3D VIR_NETWORK_PORT_PLUG_TYPE_NONE) { + virBufferAsprintf(buf, "plugtype)); + + switch (def->plugtype) { + case VIR_NETWORK_PORT_PLUG_TYPE_NONE: + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_NETWORK: + case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE: + virBufferEscapeString(buf, " bridge=3D'%s'", def->plug.bridge.= brname); + if (def->plug.bridge.macTableManager) + virBufferAsprintf(buf, " macTableManager=3D'%s'", + virNetworkBridgeMACTableManagerTypeToStr= ing( + def->plug.bridge.macTableManager)); + virBufferAddLit(buf, "/>\n"); + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT: + virBufferEscapeString(buf, " dev=3D'%s'", def->plug.direct.lin= kdev); + virBufferAsprintf(buf, " mode=3D'%s'", + virNetDevMacVLanModeTypeToString( + def->plug.direct.mode)); + virBufferAddLit(buf, "/>\n"); + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI: + virBufferAsprintf(buf, " managed=3D'%s'>\n", + def->plug.hostdevpci.managed ? "yes" : "no"); + virBufferAdjustIndent(buf, 2); + if (def->plug.hostdevpci.driver) + virBufferEscapeString(buf, "\n", + virNetworkForwardDriverNameTypeToStr= ing( + def->plug.hostdevpci.driver)); + + virPCIDeviceAddressFormat(buf, def->plug.hostdevpci.addr, fals= e); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + break; + + case VIR_NETWORK_PORT_PLUG_TYPE_LAST: + default: + virReportEnumRangeError(virNetworkPortPlugType, def->plugtype); + return -1; + } + } + + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + + return 0; +} + + +static char * +virNetworkPortDefConfigFile(const char *dir, + const char *name) +{ + char *ret =3D 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 =3D NULL; + int ret =3D -1; + + virUUIDFormat(def->uuid, uuidstr); + + if (virFileMakePath(dir) < 0) + goto cleanup; + + if (!(path =3D virNetworkPortDefConfigFile(dir, uuidstr))) + goto cleanup; + + if (!(xml =3D virNetworkPortDefFormat(def))) + goto cleanup; + + if (virXMLSaveFile(path, uuidstr, "net-port-create", xml) < 0) + goto cleanup; + + ret =3D 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 =3D -1; + + virUUIDFormat(def->uuid, uuidstr); + + if (!(path =3D virNetworkPortDefConfigFile(dir, uuidstr))) + goto cleanup; + + if (unlink(path) < 0 && errno !=3D ENOENT) { + virReportSystemError(errno, + _("Unable to delete %s"), path); + goto cleanup; + } + + ret =3D 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..94b2fabf6b --- /dev/null +++ b/src/conf/virnetworkportdef.h @@ -0,0 +1,113 @@ +/* + * 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 + * . + * + */ + +#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_NETWORK, + 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 virNetworkBridgeMACTableManagerTy= pe */ + } bridge; /* For TYPE_NETWORK & TYPE_BRIDGE */ + struct { + char *linkdev; + int mode; /* enum virNetDevMacVLanMode from util/virnetdevmacv= lan.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 909975750c..62a07c094e 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1075,6 +1075,16 @@ virNetworkObjUpdate; virNetworkObjUpdateAssignDef; =20 =20 +# conf/virnetworkportdef.h +virNetworkPortDefFormat; +virNetworkPortDefFormatBuf; +virNetworkPortDefFree; +virNetworkPortDefParseFile; +virNetworkPortDefParseNode; +virNetworkPortDefParseString; +virNetworkPortDefSaveStatus; + + # conf/virnodedeviceobj.h virNodeDeviceObjEndAPI; virNodeDeviceObjGetDef; diff --git a/tests/Makefile.am b/tests/Makefile.am index 46d94d2236..6865ee946e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -149,6 +149,7 @@ EXTRA_DIST =3D \ virmockstathelpers.c \ virnetdaemondata \ virnetdevtestdata \ + virnetworkportxml2xmldata \ virnwfilterbindingxml2xmldata \ virpcitestdata \ virscsidata \ @@ -335,6 +336,7 @@ endif WITH_YAJL test_programs +=3D \ networkxml2xmltest \ networkxml2xmlupdatetest \ + virnetworkportxml2xmltest \ $(NULL) =20 if WITH_NETWORK @@ -832,6 +834,11 @@ networkxml2xmlupdatetest_SOURCES =3D \ testutils.c testutils.h networkxml2xmlupdatetest_LDADD =3D $(LDADDS) =20 +virnetworkportxml2xmltest_SOURCES =3D \ + virnetworkportxml2xmltest.c \ + testutils.c testutils.h +virnetworkportxml2xmltest_LDADD =3D $(LDADDS) + if WITH_NETWORK networkxml2conftest_SOURCES =3D \ 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 @@ + + 5d744f21-ba4a-4d6e-bdb2-30a35ff3207d + + memtest + d54df46f-1ab5-4a22-8618-4560ef5fac2c + + + + diff --git a/tests/virnetworkportxml2xmldata/plug-bridge.xml b/tests/virnet= workportxml2xmldata/plug-bridge.xml new file mode 100644 index 0000000000..e09fc45a9d --- /dev/null +++ b/tests/virnetworkportxml2xmldata/plug-bridge.xml @@ -0,0 +1,15 @@ + + 5d744f21-ba4a-4d6e-bdb2-30a35ff3207d + + memtest + d54df46f-1ab5-4a22-8618-4560ef5fac2c + + web1 + + + + + + + + diff --git a/tests/virnetworkportxml2xmldata/plug-direct.xml b/tests/virnet= workportxml2xmldata/plug-direct.xml new file mode 100644 index 0000000000..81554b4579 --- /dev/null +++ b/tests/virnetworkportxml2xmldata/plug-direct.xml @@ -0,0 +1,12 @@ + + 5d744f21-ba4a-4d6e-bdb2-30a35ff3207d + + memtest + d54df46f-1ab5-4a22-8618-4560ef5fac2c + + + + + + + diff --git a/tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml b/tests/v= irnetworkportxml2xmldata/plug-hostdev-pci.xml new file mode 100644 index 0000000000..cc4419f3fd --- /dev/null +++ b/tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml @@ -0,0 +1,12 @@ + + 5d744f21-ba4a-4d6e-bdb2-30a35ff3207d + + memtest + d54df46f-1ab5-4a22-8618-4560ef5fac2c + + + + +
+ + diff --git a/tests/virnetworkportxml2xmldata/plug-network.xml b/tests/virne= tworkportxml2xmldata/plug-network.xml new file mode 100644 index 0000000000..7b08ca295a --- /dev/null +++ b/tests/virnetworkportxml2xmldata/plug-network.xml @@ -0,0 +1,16 @@ + + 5d744f21-ba4a-4d6e-bdb2-30a35ff3207d + + memtest + d54df46f-1ab5-4a22-8618-4560ef5fac2c + + web1 + + + + + + + + + diff --git a/tests/virnetworkportxml2xmldata/plug-none.xml b/tests/virnetwo= rkportxml2xmldata/plug-none.xml new file mode 100644 index 0000000000..ed7199ec8c --- /dev/null +++ b/tests/virnetworkportxml2xmldata/plug-none.xml @@ -0,0 +1,8 @@ + + 5d744f21-ba4a-4d6e-bdb2-30a35ff3207d + + memtest + d54df46f-1ab5-4a22-8618-4560ef5fac2c + + + diff --git a/tests/virnetworkportxml2xmltest.c b/tests/virnetworkportxml2xm= ltest.c new file mode 100644 index 0000000000..bb0ae8a8d5 --- /dev/null +++ b/tests/virnetworkportxml2xmltest.c @@ -0,0 +1,104 @@ +/* + * virnetworkportxml2xmltest.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 + * . + */ + +#include + +#include + +#include +#include + +#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 =3D NULL; + int ret =3D -1; + virNetworkPortDefPtr dev =3D NULL; + + if (!(dev =3D virNetworkPortDefParseFile(expected))) + goto cleanup; + + if (!(actual =3D virNetworkPortDefFormat(dev))) + goto cleanup; + + if (virTestCompareToFile(actual, expected) < 0) + goto cleanup; + + ret =3D 0; + cleanup: + VIR_FREE(actual); + virNetworkPortDefFree(dev); + return ret; +} + +struct testInfo { + const char *name; +}; + +static int +testCompareXMLToXMLHelper(const void *data) +{ + const struct testInfo *info =3D data; + int ret =3D -1; + char *xml =3D NULL; + + if (virAsprintf(&xml, "%s/virnetworkportxml2xmldata/%s.xml", + abs_srcdir, info->name) < 0) + goto cleanup; + + ret =3D testCompareXMLToXMLFiles(xml); + + cleanup: + VIR_FREE(xml); + + return ret; +} + +static int +mymain(void) +{ + int ret =3D 0; + +#define DO_TEST(name) \ + do { \ + const struct testInfo info =3D {name}; \ + if (virTestRun("virnetworkportdeftest " name, \ + testCompareXMLToXMLHelper, &info) < 0) \ + ret =3D -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 =3D=3D 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIR_TEST_MAIN(mymain) diff --git a/tests/virschematest.c b/tests/virschematest.c index 56bdcb2f88..13c30acc30 100644 --- a/tests/virschematest.c +++ b/tests/virschematest.c @@ -227,6 +227,7 @@ mymain(void) DO_TEST_DIR("interface.rng", "interfaceschemadata"); DO_TEST_DIR("network.rng", "../src/network", "networkxml2xmlin", "networkxml2xmlout", "networkxml2confdata"); + DO_TEST_DIR("networkport.rng", "virnetworkportxml2xmldata"); DO_TEST_DIR("nodedev.rng", "nodedevschemadata"); DO_TEST_DIR("nwfilter.rng", "nwfilterxml2xmlout", "../examples/xml/nwf= ilter"); DO_TEST_DIR("nwfilterbinding.rng", "virnwfilterbindingxml2xmldata"); --=20 2.21.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list