[libvirt] [PATCH v5 02/24] conf: introduce virNetworkPortDefPtr struct and XML support

Daniel P. Berrangé berrange at redhat.com
Wed May 22 10:29:37 UTC 2019


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




More information about the libvir-list mailing list