[libvirt] [PATCH v7] vepa: parsing for 802.1Qb{g|h} XML

Stefan Berger stefanb at linux.vnet.ibm.com
Sat May 22 16:30:13 UTC 2010


On Fri, 2010-05-21 at 16:46 -0700, Chris Wright wrote:
> * Stefan Berger (stefanb at linux.vnet.ibm.com) wrote:
> > Below is David Alan's original patch with lots of changes. 
> > 
> > In particular, it now parses the following two XML descriptions, one
> > for 802.1Qbg and 802.1Qbh and stored the data internally. The actual
> > triggering of the switch setup protocol has not been implemented
> > here but the relevant code to do that should go into the functions 
> > associatePortProfileId() and disassociatePortProfileId().
> 
> For future work, have you thought about preassociate on migration?

You mean first to do a preassociate and then after migration has
succeeded a (full) associate. I had thought about it. I believe the
current code would need to know what the actual cause was for it being
called. We currently handle it I believe correctly for

- 'direct' type of interface creation and destruction
- resume after a suspend

Now if we wanted to pre-associate on migration on the destination host,
we would need to know that the function was called due to a migration
operation in order not to call the associate function but rather the
pre-associate one. The I believe upon failure of migration the
disassociate would still be call-able on the target host, but in
addition we would need to call the associate function after the
migration was successful. We're not doing this. I suppose also that
nothing would be allowed to go wrong once one switches from
pre-associate to associate in such a scenario since the migration
succeeded and a failure to associate couldn't be handled gracefully
anymore (by failing migration).

[...]
> > 
> > Some of the changes from V1 to V2:
> > - parser and XML generator have been separated into their own
> >   functions so they can be re-used elsewhere (passthrough case
> >   for example)
> > - Adapted XML parser and generator support the above shown type
> >   (802.1Qbg, 802.1Qbh).
> > - Adapted schema to above XML
> > - Adapted test XML to above XML
> > - Passing through the VM's UUID which seems to be necessary for
> >   802.1Qbh -- sorry no host UUID
> > - adding virtual function ID to association function, in case it's
> >   necessary to use (for SR-IOV)
> > 
> > Signed-off-by: Stefan Berger <stefanb at us.ibm.com>
> 
> This is looking like pretty complete infrastructure to me.  Have you
> been able generate test (dis)associate messages through this framework w/
> the vsi patches?  Pending that (I can see you are able to at least
> generate debug messages showing the thing work), and some minor nits
> below.

I have been able to communicate with a self-hacked dummy server for
802.1Qbg that receives a netlink message and responds with a netlink
message via unicast to libvirt. With that server I am currently sending
the response immediately to the RTM_SETLINK message, which I believe
isn't what the kernel is doing. Rather it should send it back upon
RTM_GETLINK. If that server is missing or indicates failure to start, I
am timing out and fail the start of the VM. The disassociate part is in
the path of the tear down code and is being invoked as well. I haven't
tested much with that for 802.1Qbg.

> 
> Acked-by: Chris Wright <chrisw at redhat.com>
> 
> > >From a945107f047c7cd71f9c1b74fd74c47d8cdc3670 Mon Sep 17 00:00:00 2001
> > From: David Allan <dallan at redhat.com>
> > Date: Fri, 12 Mar 2010 13:25:04 -0500
> > Subject: [PATCH 1/1] POC of port profile id support
> > 
> > * Modified schema per DanPB's feedback
> > * Added test for modified schema
> > ---
> >  docs/schemas/domain.rng                |   69 ++++++++++++++
> >  src/conf/domain_conf.c                 |  155 +++++++++++++++++++++++++++++++++
> >  src/conf/domain_conf.h                 |   35 +++++++
> >  src/qemu/qemu_conf.c                   |   18 +--
> >  src/qemu/qemu_conf.h                   |    5 -
> >  src/qemu/qemu_driver.c                 |   17 +--
> >  src/util/macvtap.c                     |  151 +++++++++++++++++++++++++++-----
> >  src/util/macvtap.h                     |   10 +-
> >  tests/domainschemadata/portprofile.xml |   36 +++++++
> >  9 files changed, 446 insertions(+), 50 deletions(-)
> >  create mode 100644 tests/domainschemadata/portprofile.xml
> > 

> > Index: libvirt-acl/src/conf/domain_conf.c
> > ===================================================================
> > --- libvirt-acl.orig/src/conf/domain_conf.c
> > +++ libvirt-acl/src/conf/domain_conf.c
> > @@ -242,6 +242,11 @@ VIR_ENUM_IMPL(virDomainNetdevMacvtap, VI
> >                "private",
> >                "bridge")
> >  
> > +VIR_ENUM_IMPL(virVirtualPort, VIR_VIRTUALPORT_TYPE_LAST,
> > +              "none",
> > +              "802.1Qbg",
> > +              "802.1Qbh")
> > +
> >  VIR_ENUM_IMPL(virDomainClockOffset, VIR_DOMAIN_CLOCK_OFFSET_LAST,
> >                "utc",
> >                "localtime",
> > @@ -1807,6 +1812,145 @@ cleanup:
> >  }
> >  
> >  
> > +static void
> 
> static int so we can capture an error?

Ok.

> 
> > +virVirtualPortProfileDefParseXML(xmlNodePtr node,
> > +                                virVirtualPortProfileDefPtr virtPort)
> > +{
> > +    char *virtPortType;
> > +    char *virtPortManagerID = NULL;
> > +    char *virtPortTypeID = NULL;
> > +    char *virtPortTypeIDVersion = NULL;
> > +    char *virtPortInstanceID = NULL;
> > +    char *virtPortProfileID = NULL;
> > +    xmlNodePtr cur = node->children;
> 
> int ret = -1;
> 
> > +
> > +    virtPortType = virXMLPropString(node, "type");
> > +    if (!virtPortType)
> > +        return;
> > +
> > +    while (cur != NULL) {
> > +        if (xmlStrEqual(cur->name, BAD_CAST "parameters")) {
> > +
> > +            virtPortManagerID = virXMLPropString(cur, "managerid");
> > +            virtPortTypeID = virXMLPropString(cur, "typeid");
> > +            virtPortTypeIDVersion = virXMLPropString(cur, "typeidversion");
> > +            virtPortInstanceID = virXMLPropString(cur, "instanceid");
> > +            virtPortProfileID = virXMLPropString(cur, "profileid");
> > +
> > +            break;
> 
> s/break/goto out/
> 
> > +        }
> > +
> > +        cur = cur->next;
> > +    }
> > +
> > +    virtPort->virtPortType = VIR_VIRTUALPORT_NONE;
> > +
> > +    switch (virVirtualPortTypeFromString(virtPortType)) {
> > +
> > +    case VIR_VIRTUALPORT_8021QBG:
> > +        if (virtPortManagerID     != NULL && virtPortTypeID     != NULL &&
> > +            virtPortTypeIDVersion != NULL) {
> > +            unsigned int val;
> > +
> > +            if ((virStrToLong_ui(virtPortManagerID, NULL, 10, &val) &&
> > +                 virStrToLong_ui(virtPortManagerID, NULL, 16, &val)   ) ||
> 
> Why not a baseless strtol (0 instead of 10 and 16)?  And I think this
> should give some virDomainReportError() so that we can figure out what's
> happening when the xml is incorrect.

Done.

> 
> Ditto for parsing the whole thing...
> 
> > +                val > 0xff)
> > +                break;
> 
> s/break/goto out/
>

Ok.

> > +
> > +            virtPort->u.virtPort8021Qbg.managerID = (uint8_t)val;
> > +
> > +            if ((virStrToLong_ui(virtPortTypeID, NULL, 10, &val) &&
> > +                 virStrToLong_ui(virtPortTypeID, NULL, 16, &val)   ) ||
> > +                val > 0xffffff)
> > +                break;
> > +
> > +            virtPort->u.virtPort8021Qbg.typeID = (uint32_t)val;
> > +
> > +            if ((virStrToLong_ui(virtPortTypeIDVersion, NULL, 10, &val) &&
> > +                 virStrToLong_ui(virtPortTypeIDVersion, NULL, 16, &val)   ) ||
> > +                val > 0xff)
> > +                break;
> > +
> > +            virtPort->u.virtPort8021Qbg.typeIDVersion = (uint8_t)val;
> > +
> > +            if (virtPortInstanceID != NULL) {
> > +                if (virUUIDParse(virtPortInstanceID, virtPort->u.virtPort8021Qbg.instanceID))
> > +                    break;
> > +            } else {
> > +                if (virUUIDGenerate(virtPort->u.virtPort8021Qbg.instanceID))
> > +                    break;
> > +            }
> > +
> > +            virtPort->virtPortType = VIR_VIRTUALPORT_8021QBG;
> > +        }
> > +    break;
> > +
> > +    case VIR_VIRTUALPORT_8021QBH:
> > +        if (virtPortProfileID != NULL) {
> > +            if (virStrcpyStatic(virtPort->u.virtPort8021Qbh.profileID,
> > +                                virtPortProfileID) != NULL)
> > +                virtPort->virtPortType = VIR_VIRTUALPORT_8021QBH;
> > +        }
> > +    break;
> > +
> > +
> > +    default:
> > +    case VIR_VIRTUALPORT_NONE:
> > +    case VIR_VIRTUALPORT_TYPE_LAST:
> > +    break;
> 
> error cases, no?  goto out

Ok. However, I'd still allow the omission of <virtualport/> so I can
start a macvtap without having to have a (future) switch.

> 
> > +    }
> > +
> 
>        ret = 0;
> 
> out:
> 
> > +    VIR_FREE(virtPortManagerID);
> > +    VIR_FREE(virtPortTypeID);
> > +    VIR_FREE(virtPortTypeIDVersion);
> > +    VIR_FREE(virtPortInstanceID);
> > +    VIR_FREE(virtPortProfileID);
> > +    VIR_FREE(virtPortType);
> 
>        return ret;

Ok.

> > +}
> > +
> > +
> > +static void
> > +virVirtualPortProfileFormat(virBufferPtr buf, virVirtualPortProfileDefPtr virtPort,
> > +                            const char *indent)
> > +{
> > +    char uuidstr[VIR_UUID_STRING_BUFLEN];
> > +
> > +    if (virtPort->virtPortType == VIR_VIRTUALPORT_NONE)
> > +        return;
> > +
> > +    virBufferVSprintf(buf, "%s<virtualport type='%s'>\n",
> > +                      indent, virVirtualPortTypeToString(virtPort->virtPortType));
> > +
> > +    switch (virtPort->virtPortType) {
> > +    case VIR_VIRTUALPORT_NONE:
> > +    case VIR_VIRTUALPORT_TYPE_LAST:
> > +        break;
> > +
> > +    case VIR_VIRTUALPORT_8021QBG:
> > +        virUUIDFormat(virtPort->u.virtPort8021Qbg.instanceID,
> > +                      uuidstr);
> > +        virBufferVSprintf(buf,
> > +                          "%s  <parameters managerid='%d' typeid='%d' "
> > +                          "typeidversion='%d' instanceid='%s'/>\n",
> > +                          indent,
> > +                          virtPort->u.virtPort8021Qbg.managerID,
> > +                          virtPort->u.virtPort8021Qbg.typeID,
> > +                          virtPort->u.virtPort8021Qbg.typeIDVersion,
> > +                          uuidstr);
> > +        break;
> > +
> > +    case VIR_VIRTUALPORT_8021QBH:
> > +        virBufferVSprintf(buf,
> > +                          "%s  <parameters profileid='%s'/>\n",
> > +                          indent,
> > +                          virtPort->u.virtPort8021Qbh.profileID);
> > +        break;
> > +    }
> > +
> > +    virBufferVSprintf(buf, "%s</virtualport>\n", indent);
> > +}
> > +
> > +
> >  /* Parse the XML definition for a network interface
> >   * @param node XML nodeset to parse for net definition
> >   * @return 0 on success, -1 on failure
> > @@ -1832,6 +1976,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
> >      char *devaddr = NULL;
> >      char *mode = NULL;
> >      virNWFilterHashTablePtr filterparams = NULL;
> > +    virVirtualPortProfileDef virtPort;
> > +    bool virtPortParsed = false;
> >  
> >      if (VIR_ALLOC(def) < 0) {
> >          virReportOOMError();
> > @@ -1873,6 +2019,11 @@ virDomainNetDefParseXML(virCapsPtr caps,
> >                         xmlStrEqual(cur->name, BAD_CAST "source")) {
> >                  dev  = virXMLPropString(cur, "dev");
> >                  mode = virXMLPropString(cur, "mode");
> > +            } else if ((virtPortParsed == false) &&
> > +                       (def->type == VIR_DOMAIN_NET_TYPE_DIRECT) &&
> > +                       xmlStrEqual(cur->name, BAD_CAST "virtualport")) {
> > +                virVirtualPortProfileDefParseXML(cur, &virtPort);
> > +                virtPortParsed = true;
> >              } else if ((network == NULL) &&
> >                         ((def->type == VIR_DOMAIN_NET_TYPE_SERVER) ||
> >                          (def->type == VIR_DOMAIN_NET_TYPE_CLIENT) ||
> > @@ -2048,6 +2199,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
> >          } else
> >              def->data.direct.mode = VIR_DOMAIN_NETDEV_MACVTAP_MODE_VEPA;
> >  
> > +        def->data.direct.virtPortProfile = virtPort;
> > +
> >          def->data.direct.linkdev = dev;
> >          dev = NULL;
> >  
> > @@ -5140,6 +5293,8 @@ virDomainNetDefFormat(virBufferPtr buf,
> >          virBufferVSprintf(buf, " mode='%s'",
> >                     virDomainNetdevMacvtapTypeToString(def->data.direct.mode));
> >          virBufferAddLit(buf, "/>\n");
> > +        virVirtualPortProfileFormat(buf, &def->data.direct.virtPortProfile,
> > +                            "      ");
> >          break;
> >  
> >      case VIR_DOMAIN_NET_TYPE_USER:
> > Index: libvirt-acl/src/conf/domain_conf.h
> > ===================================================================
> > --- libvirt-acl.orig/src/conf/domain_conf.h
> > +++ libvirt-acl/src/conf/domain_conf.h
> > @@ -259,6 +259,39 @@ enum virDomainNetdevMacvtapType {
> >  };
> >  
> >  
> > +enum virVirtualPortType {
> > +    VIR_VIRTUALPORT_NONE,
> > +    VIR_VIRTUALPORT_8021QBG,
> > +    VIR_VIRTUALPORT_8021QBH,
> > +
> > +    VIR_VIRTUALPORT_TYPE_LAST,
> > +};
> > +
> > +# ifdef IFLA_VF_PORT_PROFILE_MAX
> > +#  define LIBVIRT_IFLA_VF_PORT_PROFILE_MAX IFLA_VF_PORT_PROFILE_MAX
> > +# else
> > +#  define LIBVIRT_IFLA_VF_PORT_PROFILE_MAX 40
> > +# endif
> > +
> > +/* profile data for macvtap (VEPA) */
> > +typedef struct _virVirtualPortProfileDef virVirtualPortProfileDef;
> > +typedef virVirtualPortProfileDef *virVirtualPortProfileDefPtr;
> > +struct _virVirtualPortProfileDef {
> > +    enum virVirtualPortType   virtPortType;
> > +    union {
> > +        struct {
> > +            uint8_t       managerID;
> > +            uint32_t      typeID; // 24 bit valid
> > +            uint8_t       typeIDVersion;
> > +            unsigned char instanceID[VIR_UUID_BUFLEN];
> > +        } virtPort8021Qbg;
> > +        struct {
> > +            char          profileID[LIBVIRT_IFLA_VF_PORT_PROFILE_MAX];
> > +        } virtPort8021Qbh;
> > +    } u;
> > +};
> > +
> > +
> >  /* Stores the virtual network interface configuration */
> >  typedef struct _virDomainNetDef virDomainNetDef;
> >  typedef virDomainNetDef *virDomainNetDefPtr;
> > @@ -290,6 +323,7 @@ struct _virDomainNetDef {
> >          struct {
> >              char *linkdev;
> >              int mode;
> > +            virVirtualPortProfileDef virtPortProfile;
> >          } direct;
> >      } data;
> >      char *ifname;
> > @@ -1089,6 +1123,7 @@ VIR_ENUM_DECL(virDomainSeclabel)
> >  VIR_ENUM_DECL(virDomainClockOffset)
> >  
> >  VIR_ENUM_DECL(virDomainNetdevMacvtap)
> > +VIR_ENUM_DECL(virVirtualPort)
> >  
> >  VIR_ENUM_DECL(virDomainTimerName)
> >  VIR_ENUM_DECL(virDomainTimerTrack)
> > Index: libvirt-acl/src/util/macvtap.c
> > ===================================================================
> > --- libvirt-acl.orig/src/util/macvtap.c
> > +++ libvirt-acl/src/util/macvtap.c
> > @@ -43,6 +43,7 @@
> >  
> >  # include "util.h"
> >  # include "memory.h"
> > +# include "logging.h"
> >  # include "macvtap.h"
> >  # include "interface.h"
> >  # include "conf/domain_conf.h"
> > @@ -57,6 +58,16 @@
> >  # define MACVTAP_NAME_PREFIX	"macvtap"
> >  # define MACVTAP_NAME_PATTERN	"macvtap%d"
> >  
> > +
> > +static int associatePortProfileId(const char *macvtap_ifname,
> > +                                  const virVirtualPortProfileDefPtr virtPort,
> > +                                  int vf,
> > +                                  const unsigned char *vmuuid);
> > +
> > +static int disassociatePortProfileId(const char *macvtap_ifname,
> > +                                     const virVirtualPortProfileDefPtr virtPort);
> > +
> > +
> >  static int nlOpen(void)
> >  {
> >      int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
> > @@ -567,39 +578,38 @@ configMacvtapTap(int tapfd, int vnet_hdr
> >  
> >      return 0;
> >  }
> > -
> > -
> >  /**
> >   * openMacvtapTap:
> >   * Create an instance of a macvtap device and open its tap character
> >   * device.
> >   * @tgifname: Interface name that the macvtap is supposed to have. May
> >   *    be NULL if this function is supposed to choose a name
> > - * @macaddress: The MAC address for the macvtap device
> > - * @linkdev: The interface name of the NIC to connect to the external bridge
> > - * @mode_str: String describing the mode. Valid are 'bridge', 'vepa' and
> > - *     'private'.
> > + * @net: pointer to the virDomainNetDef object describing the direct
> > + *       type if an interface
> >   * @res_ifname: Pointer to a string pointer where the actual name of the
> >   *     interface will be stored into if everything succeeded. It is up
> >   *     to the caller to free the string.
> > + * @vnet_hdr: Whether to enable IFF_VNET_HDR on the interface
> > + * @vmuuid: The (raw) UUID of the VM
> >   *
> >   * Returns file descriptor of the tap device in case of success,
> >   * negative value otherwise with error reported.
> >   *
> > + * Open a macvtap device and trigger the switch setup protocol
> > + * if valid port profile parameters were provided.
> >   */
> >  int
> >  openMacvtapTap(const char *tgifname,
> > -               const unsigned char *macaddress,
> > -               const char *linkdev,
> > -               int mode,
> > +               virDomainNetDefPtr net,
> 
> Any reason to keep tgifname now that you're passing full virDomainNetDefPtr?

True. Next would be to hanlde the **res_ifname in this function, but
that I'd leave to a separate patch.

> 
> >                 char **res_ifname,
> > -               int vnet_hdr)
> > +               int vnet_hdr,
> > +               const unsigned char *vmuuid)
> >  {
> >      const char *type = "macvtap";
> >      int c, rc;
> >      char ifname[IFNAMSIZ];
> >      int retries, do_retry = 0;
> > -    uint32_t macvtapMode = macvtapModeFromInt(mode);
> > +    uint32_t macvtapMode = macvtapModeFromInt(net->data.direct.mode);
> >      const char *cr_ifname;
> >      int ifindex;
> >  
> > @@ -616,7 +626,7 @@ openMacvtapTap(const char *tgifname,
> >              return -1;
> >          }
> >          cr_ifname = tgifname;
> > -        rc = link_add(type, macaddress, 6, tgifname, linkdev,
> > +        rc = link_add(type, net->mac, 6, tgifname, net->data.direct.linkdev,
> >                        macvtapMode, &do_retry);
> >          if (rc)
> >              return -1;
> > @@ -626,7 +636,8 @@ create_name:
> >          for (c = 0; c < 8192; c++) {
> >              snprintf(ifname, sizeof(ifname), MACVTAP_NAME_PATTERN, c);
> >              if (ifaceGetIndex(false, ifname, &ifindex) == ENODEV) {
> > -                rc = link_add(type, macaddress, 6, ifname, linkdev,
> > +                rc = link_add(type, net->mac, 6, ifname,
> > +                              net->data.direct.linkdev,
> >                                macvtapMode, &do_retry);
> >                  if (rc == 0)
> >                      break;
> > @@ -639,6 +650,14 @@ create_name:
> >          cr_ifname = ifname;
> >      }
> >  
> > +    if (associatePortProfileId(cr_ifname,
> > +                               &net->data.direct.virtPortProfile,
> > +                               -1,
> > +                               vmuuid) != 0) {
> > +        rc = -1;
> > +        goto link_del_exit;
> > +    }
> > +
> >      rc = ifaceUp(cr_ifname);
> >      if (rc != 0) {
> >          virReportSystemError(errno,
> > @@ -647,7 +666,7 @@ create_name:
> >                               "MAC address"),
> >                               cr_ifname);
> >          rc = -1;
> > -        goto link_del_exit;
> > +        goto disassociate_exit;
> >      }
> >  
> >      rc = openTap(cr_ifname, 10);
> > @@ -656,14 +675,18 @@ create_name:
> >          if (configMacvtapTap(rc, vnet_hdr) < 0) {
> >              close(rc);
> >              rc = -1;
> > -            goto link_del_exit;
> > +            goto disassociate_exit;
> >          }
> >          *res_ifname = strdup(cr_ifname);
> >      } else
> > -        goto link_del_exit;
> > +        goto disassociate_exit;
> >  
> >      return rc;
> >  
> > +disassociate_exit:
> > +    disassociatePortProfileId(cr_ifname,
> > +                              &net->data.direct.virtPortProfile);
> > +
> >  link_del_exit:
> >      link_del(cr_ifname);
> >  
> > @@ -673,14 +696,102 @@ link_del_exit:
> >  
> >  /**
> >   * delMacvtap:
> > - * @ifname : The name of the macvtap interface
> > + * @net: pointer to virDomainNetDef object
> >   *
> > - * Delete an interface given its name.
> > + * Delete an interface given its name. Disassociate
> > + * it with the switch if port profile parameters
> > + * were provided.
> >   */
> >  void
> > -delMacvtap(const char *ifname)
> > +delMacvtap(virDomainNetDefPtr net)
> >  {
> > -    link_del(ifname);
> > +    if (net->ifname) {
> > +        disassociatePortProfileId(net->ifname,
> > +                                  &net->data.direct.virtPortProfile);
> > +        link_del(net->ifname);
> > +    }
> >  }
> >  
> >  #endif
> > +
> > +
> > +/**
> > + * associatePortProfile
> > + *
> > + * @macvtap_ifname: The name of the macvtap device
> > + * @virtPort: pointer to the object holding port profile parameters
> > + * @vf: virtual function number, -1 if to be ignored
> > + * @vmuuid : the UUID of the virtual machine
> > + *
> > + * Associate a port on a swtich with a profile. This function
> > + * may notify a kernel driver or an external daemon to run
> > + * the setup protocol. If profile parameters were not supplied
> > + * by the user, then this function returns without doing
> > + * anything.
> > + *
> > + * Returns 0 in case of success, != 0 otherwise with error
> > + * having been reported.
> > + */
> > +static int
> > +associatePortProfileId(const char *macvtap_ifname,
> > +                       const virVirtualPortProfileDefPtr virtPort,
> > +                       int vf,
> > +                       const unsigned char *vmuuid)
> > +{
> > +    int rc = 0;
> > +    VIR_DEBUG("Associating port profile '%p' on link device '%s'",
> > +              virtPort, macvtap_ifname);
> > +    (void)vf;
> > +    (void)vmuuid;
> > +
> > +    switch (virtPort->virtPortType) {
> > +    case VIR_VIRTUALPORT_NONE:
> > +    case VIR_VIRTUALPORT_TYPE_LAST:
> > +        break;
> 
> If we capture these on parsing and error out, then these could be
> invalid here.

They would not even appear here. Problem is just I cannot even test
anything with macvtap anymore without having a profile which then in
turn requires either a daemon or an enic kernel driver.

> 
> > +
> > +    case VIR_VIRTUALPORT_8021QBG:
> > +
> > +        break;
> > +
> > +    case VIR_VIRTUALPORT_8021QBH:
> > +
> > +        break;
> > +    }
> > +
> > +    return rc;
> > +}
> > +
> > +
> > +/**
> > + * disassociatePortProfile
> > + *
> > + * @macvtap_ifname: The name of the macvtap device
> > + * @virtPort: point to object holding port profile parameters
> > + *
> > + * Returns 0 in case of success, != 0 otherwise with error
> > + * having been reported.
> > + */
> > +static int
> > +disassociatePortProfileId(const char *macvtap_ifname,
> > +                          const virVirtualPortProfileDefPtr virtPort)
> > +{
> > +    int rc = 0;
> > +    VIR_DEBUG("Disassociating port profile id '%p' on link device '%s' ",
> > +              virtPort, macvtap_ifname);
> > +
> > +    switch (virtPort->virtPortType) {
> > +    case VIR_VIRTUALPORT_NONE:
> > +    case VIR_VIRTUALPORT_TYPE_LAST:
> > +        break;
> 
> If we capture these on parsing and error out, then these could be
> invalid here.
> 

If I do that then please send me hardware :-)

I'll post v8 after some testing - while I still can :-)

   Stefan





More information about the libvir-list mailing list