
On Mon, May 20, 2019 at 09:44:04PM -0400, Laine Stump wrote:
On 5/14/19 11:48 AM, 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@redhat.com> --- 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/formatnetworkport.html.in b/docs/formatnetworkport.html.in new file mode 100644 index 0000000000..0211518a6a --- /dev/null +++ b/docs/formatnetworkport.html.in
+ <dl> + <dt><code>bandwidth</code></dt> + <dd>This part of the network port XML provides setting quality of service. + Incoming and outgoing traffic can be shaped independently. + The <code>bandwidth</code> element and its child elements are described + in the <a href="formatnetwork.html#elementQoS">QoS</a> section of + the Network XML. In addition the <code>classID</code> attribute may + exist provide the ID of the traffic shaping class that is active. + </dd> + <dt><code>rxfilters</code></dt> + <dd>The <code>rxfilters</code> element property + <code>trustGuestRxFilters</code> provides the
Earlier you referred to this as "trustGuest" (also looks like that's what the parser/formatter use)
Yes, copy & paste mistake
+ 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 <code>yes</code>. The default + setting for the attribute is <code>no</code> 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. + </dd> + <dt><code>virtualport</code></dt> + <dd>The <code>virtualport</code> element describes metadata that + needs to be provided to the underlying network subsystem. It + is described in the domain XML + <a href="formatdomain.html#elementsNICS">interface documentation</a>. + </dd> + </dl> + + + <h3><a id="elementsPlug">Plugs</a></h3> + + <p> + The <code>plug</code> element has varying content depending + on the value of the <code>type</code> attribute. + </p> + + <h4><a id="elementsPlugNetwork">Network</a></h4> + + <p> + The <code>network</code> plug type refers to a managed virtual + network plug that is based on a traditional software bridge + device privately managed by libvirt. + </p>
Your patches essentially take the same items that are in the virActualNetDef and put them into virNetworkPortDef. I think this is the right way to approach the task of changing the infrastructure - makes it more straightforward to get all the same functionality working with the new intra-driver communication method. The one thing that bothers me, though, is that this ends up replicating design mistakes that we ("I" :-P - most of it was good, I just added in some things that were kind of screwed up...) made with the original. I'm hoping that there will also be a path to correcting those mistakes after the fact so that we don't have to live with them forever.
I don't see any viable alternative. We have to be able to convert between the virActualNetDef & virNetworkPortDef in both directions without loosing information. This inherantly means replicating the same concepts.
In particular, we've been using "type='network' to imply that the network supports a bandwidth floor setting (and who knows what else). Although we made this mistake with <interface> status, I would really prefer if we don't (permanently at least) propagate the mistake to networkport. What "type='network' really means is a tap device connected to a bridge that probably has a routed connection and supports bandwidth floor setting). But what if network port was instead something like:
<plug type='tap' forward='route' bridge='virbr0'/>
<plug type='tap' forward='bridge' bridge='br0'/>
<plug type='direct' dev='ens3' mode='vepa'/>
(maybe if we use "type='tap'", we should also use "type='macvtap'"?. Hmm, and of course if we're going to spell out "tap", then for container-ish connections that use a veth pair, we would have to say "type='veth'"...)
You raised this same point in an earlier review of this same series. This is not desirable as it is refering to a specific implementation choice of the QEMU backend. The LXC driver doesn't use tap devices or macvtap devices, instead it uses veth devices and macvlan devices.
Anyway, like I said, I think it *is* better to change the infrastructure without changing the attributes right now, but will we be able to change it in the future?
I don't believe we should change it, as the current concepts are intentionally independant of a specific implementation choice.
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 @@ +<?xml version="1.0"?> +<!-- A Relax NG schema for the libvirt network port XML format --> +<grammar xmlns="http://relaxng.org/ns/structure/1.0" + datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> + <include href='basictypes.rng'/> + <include href='networkcommon.rng'/> + + <start> + <ref name="networkport"/> + </start> + + <define name="networkport"> + <element name="networkport"> + <interleave> + <element name="uuid"> + <ref name="UUID"/> + </element> + <ref name="owner"/> + <ref name="mac"/> + <optional> + <ref name="group"/> + </optional> + <optional> + <ref name="class"/> + </optional>
I thought in the previous patch you had integrated <class id='blah'/> into the bandwidth element as a classID attribute. Did you just forget to remove it from the rng?
Yeah, I forgot to update the schema.
+ <define name="plughostdevpci"> + <attribute name="type"> + <value>hostdev-pci</value> + </attribute> + <optional> + <attribute name="managed"> + <ref name="virYesNo"/> + </attribute> + </optional> + <optional> + <element name="driver"> + <attribute name="name"> + <choice> + <value>kvm</value>
We *really* need to get rid of <driver name='kvm'/> for hostdev - it's been deprecated for 5 years, and removing it would eliminate ugly code.
Regardless of whether the code uses it or not, it is in the domain schema and for purposes of doing a bi-directional conversion, it better to have it in the network port XML too. It isn't the network port XML parser's job to decide if its used or not - that's upto the QEMU driver
+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; + char *class_id = 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; + }
I'm curious why you made name and uuid subelements of owner, rather than attributes. Just for consistency with the name element we use in other places? Or are you expecting it might need qualifying attributes? Or just because the <owner> line would be too long if they were attributes?
This mirrors what is done with the nwfilter binding XML schema.
+ 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; + }
Yeah, the more I think about this, the more I think it's unnecessary (and that we should also consider removing it from other places it's used, since non-VFIO device assignment hasn't worked in Linux since RHEL6 days).
Again, from XML parsing pov it is preferrable to have it present so that conversion to/from the actual network def avoids any special cases. If QEMU driver wants to reject it later that's fine
+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;
For other objects, when they are saved to a "status" file, the xml is enclosed in a "<blahstatus>" element, e.g. <domstatus>, <networkstatus>, etc. I guess this is done in case there are other things about the state of the object that aren't contained directly in virBlahDef. Did you not do that here on purpose (maybe because the entire point of this object is to keep track of the state of a particular connection, so of course there is nothing extra?), or was it an oversite?
Essentially the network port XML is always a "status" file, since this object only ever exists for a running VM. There shouldn't be any info we record in the network port that isn't part of the public schema. Thus there's no need to wrap it in a extra status XML schema. This is the same as the nwfilter binding XML which is also a runtime only XML doc. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|