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

Chris Wright chrisw at redhat.com
Fri May 21 23:46:47 UTC 2010


* 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?

>    <interface type='direct'>
>       <source dev='eth0.100' mode='vepa'/>
>       <model type='virtio'/>
>       <virtualport type='802.1Qbg'>
>         <parameters managerid='12' typeid='0x123456' typeidversion='1'
>          instanceid='fa9b7fff-b0a0-4893-8e0e-beef4ff18f8f'/>
>       </virtualport>
>       <filterref filter='clean-traffic'/>
>     </interface>
> 
>     <interface type='direct'>
>       <source dev='eth0.100' mode='vepa'/>
>       <model type='virtio'/>
>       <virtualport type='802.1Qbh'>
>         <parameters profileid='my_profile'/>
>       </virtualport>
>     </interface>
> 
> I'd suggest to use this patch as a base for triggering the setup
> protocol with the 802.1Qb{g|h} switch.
> 
> Changes from V6 to V7:
> - make sure that the error code returned by openMacvtapTap() is a negative number
>   in case the associatePortProfileId() function failed.
> 
> Changes from V5 to V6:
> - renaming vsi in the XML to virtualport
> - replace all occurrences of vsi in the source as well
> 
> Changes from V4 to V5:
> - removing mode and MAC address parameters from the functions that
>   will communicate with the hareware diretctly or indirectly
> 
> Changes from V3 to V4:
> - moving the associate and disassociate functions to the end of the
>   file for subsequent patches to easier make them generally available
>   for export
> - passing the macvtap interface name rather than the link device since
>   this otherwise gives funny side effects when using netlink messages
>   where IFLA_IFNAME and IFLA_ADDRESS are specified and the link dev
>   all of a sudden gets the MAC address of the macvtap interface.
> - Removing rc = -1 error indications in the case of 802.1Qbg|h setup in case
>   we wanted to use hook scripts for the setup and so the setup doesn't fail
>   here.
> 
> Changes from V2 to V3:
> - if instance ID UUID is not supplied it will automatically be generated
>   - adapted schema to make instance ID UUID optional
>   - added test case
> 
> 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.

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/docs/schemas/domain.rng
> ===================================================================
> --- libvirt-acl.orig/docs/schemas/domain.rng
> +++ libvirt-acl/docs/schemas/domain.rng
> @@ -817,6 +817,9 @@
>                </optional>
>                <empty/>
>              </element>
> +            <optional>
> +              <ref name="virtualPortProfile"/>
> +            </optional>
>              <ref name="interface-options"/>
>            </interleave>
>          </group>
> @@ -902,6 +905,45 @@
>        </optional>
>      </interleave>
>    </define>
> +  <define name="virtualPortProfile">
> +    <choice>
> +      <group>
> +        <element name="virtualport">
> +          <attribute name="type">
> +            <value>802.1Qbg</value>
> +          </attribute>
> +          <element name="parameters">
> +            <attribute name="managerid">
> +              <ref name="uint8range"/>
> +            </attribute>
> +            <attribute name="typeid">
> +              <ref name="uint24range"/>
> +            </attribute>
> +            <attribute name="typeidversion">
> +              <ref name="uint8range"/>
> +            </attribute>
> +            <optional>
> +              <attribute name="instanceid">
> +                <ref name="UUID"/>
> +              </attribute>
> +            </optional>
> +          </element>
> +        </element>
> +      </group>
> +      <group>
> +        <element name="virtualport">
> +          <attribute name="type">
> +            <value>802.1Qbh</value>
> +          </attribute>
> +          <element name="parameters">
> +            <attribute name="profileid">
> +              <ref name="virtualPortProfileID"/>
> +            </attribute>
> +          </element>
> +        </element>
> +      </group>
> +    </choice>
> +  </define>
>    <!--
>        An emulator description is just a path to the binary used for the task
>      -->
> @@ -1769,4 +1811,31 @@
>        <param name="pattern">[a-zA-Z0-9_\.:]+</param>
>      </data>
>    </define>
> +  <define name="uint8range">
> +    <choice>
> +      <data type="string">
> +        <param name="pattern">0x[0-9a-fA-F]{1,2}</param>
> +      </data>
> +      <data type="int">
> +        <param name="minInclusive">0</param>
> +        <param name="maxInclusive">255</param>
> +      </data>
> +    </choice>
> +  </define>
> +  <define name="uint24range">
> +    <choice>
> +      <data type="string">
> +        <param name="pattern">0x[0-9a-fA-F]{1,6}</param>
> +      </data>
> +      <data type="int">
> +        <param name="minInclusive">0</param>
> +        <param name="maxInclusive">16777215</param>
> +      </data>
> +    </choice>
> +  </define>
> +  <define name="virtualPortProfileID">
> +    <data type="string">
> +      <param name="maxLength">39</param>
> +    </data>
> +  </define>
>  </grammar>
> 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?

> +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.

Ditto for parsing the whole thing...

> +                val > 0xff)
> +                break;

s/break/goto out/

> +
> +            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

> +    }
> +

       ret = 0;

out:

> +    VIR_FREE(virtPortManagerID);
> +    VIR_FREE(virtPortTypeID);
> +    VIR_FREE(virtPortTypeIDVersion);
> +    VIR_FREE(virtPortInstanceID);
> +    VIR_FREE(virtPortProfileID);
> +    VIR_FREE(virtPortType);

       return ret;
> +}
> +
> +
> +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?

>                 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.

> +
> +    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.

> +    case VIR_VIRTUALPORT_8021QBG:
> +
> +        break;
> +
> +    case VIR_VIRTUALPORT_8021QBH:
> +
> +        break;
> +    }
> +
> +    return rc;
> +}
> Index: libvirt-acl/src/util/macvtap.h
> ===================================================================
> --- libvirt-acl.orig/src/util/macvtap.h
> +++ libvirt-acl/src/util/macvtap.h
> @@ -27,15 +27,15 @@
>  # if defined(WITH_MACVTAP)
>  
>  #  include "internal.h"
> +#  include "conf/domain_conf.h"
>  
>  int openMacvtapTap(const char *ifname,
> -                   const unsigned char *macaddress,
> -                   const char *linkdev,
> -                   int mode,
> +                   virDomainNetDefPtr net,
>                     char **res_ifname,
> -                   int vnet_hdr);
> +                   int vnet_hdr,
> +                   const unsigned char *vmuuid);
>  
> -void delMacvtap(const char *ifname);
> +void delMacvtap(virDomainNetDefPtr net);
>  
>  # endif /* WITH_MACVTAP */
>  
> Index: libvirt-acl/tests/domainschemadata/portprofile.xml
> ===================================================================
> --- /dev/null
> +++ libvirt-acl/tests/domainschemadata/portprofile.xml
> @@ -0,0 +1,36 @@
> +<domain type='lxc'>
> +  <name>portprofile</name>
> +  <uuid>00000000-0000-0000-0000-000000000000</uuid>
> +  <memory>1048576</memory>
> +    <os>
> +        <type>exe</type>
> +        <init>/sh</init>
> +    </os>
> +  <devices>
> +    <interface type='direct'>
> +      <source dev='eth0' mode='vepa'/>
> +      <virtualport type='802.1Qbg'>
> +        <parameters managerid='12' typeid='1193046' typeidversion='1'
> +                    instanceid='fa9b7fff-b0a0-4893-8e0e-beef4ff18f8f'/>
> +      </virtualport>
> +    </interface>
> +    <interface type='direct'>
> +      <source dev='eth0' mode='vepa'/>
> +      <virtualport type='802.1Qbg'>
> +        <parameters managerid='12' typeid='1193046' typeidversion='1'/>
> +      </virtualport>
> +    </interface>
> +    <interface type='direct'>
> +      <source dev='eth0' mode='vepa'/>
> +      <virtualport type='802.1Qbh'>
> +        <parameters profileid='my_profile'/>
> +      </virtualport>
> +    </interface>
> +    <interface type='direct'>
> +      <source dev='eth0' mode='vepa'/>
> +    </interface>
> +    <interface type='direct'>
> +      <source dev='eth0' mode='vepa'/>
> +    </interface>
> +  </devices>
> +</domain>
> Index: libvirt-acl/src/qemu/qemu_conf.h
> ===================================================================
> --- libvirt-acl.orig/src/qemu/qemu_conf.h
> +++ libvirt-acl/src/qemu/qemu_conf.h
> @@ -274,9 +274,8 @@ qemudOpenVhostNet(virDomainNetDefPtr net
>  int qemudPhysIfaceConnect(virConnectPtr conn,
>                            struct qemud_driver *driver,
>                            virDomainNetDefPtr net,
> -                          char *linkdev,
> -                          int brmode,
> -                          unsigned long long qemuCmdFlags);
> +                          unsigned long long qemuCmdFlags,
> +                          const unsigned char *vmuuid);
>  
>  int         qemudProbeMachineTypes      (const char *binary,
>                                           virCapsGuestMachinePtr **machines,
> Index: libvirt-acl/src/qemu/qemu_driver.c
> ===================================================================
> --- libvirt-acl.orig/src/qemu/qemu_driver.c
> +++ libvirt-acl/src/qemu/qemu_driver.c
> @@ -3702,10 +3702,8 @@ static void qemudShutdownVMDaemon(struct
>      def = vm->def;
>      for (i = 0; i < def->nnets; i++) {
>          virDomainNetDefPtr net = def->nets[i];
> -        if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
> -            if (net->ifname)
> -                delMacvtap(net->ifname);
> -        }
> +        if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT)
> +            delMacvtap(net);
>      }
>  #endif
>  
> @@ -7464,9 +7462,8 @@ static int qemudDomainAttachNetDevice(vi
>          }
>  
>          if ((tapfd = qemudPhysIfaceConnect(conn, driver, net,
> -                                           net->data.direct.linkdev,
> -                                           net->data.direct.mode,
> -                                           qemuCmdFlags)) < 0)
> +                                           qemuCmdFlags,
> +                                           vm->def->uuid)) < 0)
>              return -1;
>      }
>  
> @@ -8509,10 +8506,8 @@ qemudDomainDetachNetDevice(struct qemud_
>      virNWFilterTearNWFilter(detach);
>  
>  #if WITH_MACVTAP
> -    if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
> -        if (detach->ifname)
> -            delMacvtap(detach->ifname);
> -    }
> +    if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT)
> +        delMacvtap(detach);
>  #endif
>  
>      if ((driver->macFilter) && (detach->ifname != NULL)) {
> Index: libvirt-acl/src/qemu/qemu_conf.c
> ===================================================================
> --- libvirt-acl.orig/src/qemu/qemu_conf.c
> +++ libvirt-acl/src/qemu/qemu_conf.c
> @@ -1470,9 +1470,8 @@ int
>  qemudPhysIfaceConnect(virConnectPtr conn,
>                        struct qemud_driver *driver,
>                        virDomainNetDefPtr net,
> -                      char *linkdev,
> -                      int brmode,
> -                      unsigned long long qemuCmdFlags)
> +                      unsigned long long qemuCmdFlags,
> +                      const unsigned char *vmuuid)
>  {
>      int rc;
>  #if WITH_MACVTAP
> @@ -1484,8 +1483,7 @@ qemudPhysIfaceConnect(virConnectPtr conn
>          net->model && STREQ(net->model, "virtio"))
>          vnet_hdr = 1;
>  
> -    rc = openMacvtapTap(net->ifname, net->mac, linkdev, brmode,
> -                        &res_ifname, vnet_hdr);
> +    rc = openMacvtapTap(net->ifname, net, &res_ifname, vnet_hdr, vmuuid);
>      if (rc >= 0) {
>          VIR_FREE(net->ifname);
>          net->ifname = res_ifname;
> @@ -1505,17 +1503,16 @@ qemudPhysIfaceConnect(virConnectPtr conn
>              if (err) {
>                  close(rc);
>                  rc = -1;
> -                delMacvtap(net->ifname);
> +                delMacvtap(net);
>              }
>          }
>      }
>  #else
>      (void)conn;
>      (void)net;
> -    (void)linkdev;
> -    (void)brmode;
>      (void)qemuCmdFlags;
>      (void)driver;
> +    (void)vmuuid;
>      qemuReportError(VIR_ERR_INTERNAL_ERROR,
>                      "%s", _("No support for macvtap device"));
>      rc = -1;
> @@ -4135,9 +4132,8 @@ int qemudBuildCommandLine(virConnectPtr 
>                      goto no_memory;
>              } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
>                  int tapfd = qemudPhysIfaceConnect(conn, driver, net,
> -                                                  net->data.direct.linkdev,
> -                                                  net->data.direct.mode,
> -                                                  qemuCmdFlags);
> +                                                  qemuCmdFlags,
> +                                                  def->uuid);
>                  if (tapfd < 0)
>                      goto error;
>  
> 
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list




More information about the libvir-list mailing list