[libvirt] [PATCHv2 4/9] util: utility functions for virNetDevVPortProfile

Viktor Mihajlovski mihajlov at linux.vnet.ibm.com
Wed Aug 15 14:44:14 UTC 2012


On 08/14/2012 09:04 AM, Laine Stump wrote:
> This patch adds three utility functions that operate on
> virNetDevVPortProfile objects.
>
> * virNetDevVPortProfileCheckComplete() - verifies that all attributes
>      required for the type of the given virtport are specified.
>
> * virNetDevVPortProfileCheckNoExtras() - verifies that there are no
>      attributes specified which are inappropriate for the type of the
>      given virtport.
>
> * virNetDevVPortProfileMerge3() - merges 3 virtports into a single,
>      newly allocated virtport. If any attributes are specified in
>      more than one of the three sources, and do not exactly match,
>      an error is logged and the function fails.
>
> These new functions depend on new fields in the virNetDevVPortProfile
> object that keep track of whether or not each attribute was
> specified. Since the higher level parse function doesn't yet set those
> fields, these functions are not actually usable yet (but that's okay,
> because they also aren't yet used - all of that functionality comes in
> a later patch.)
>
> Note that these three functions return 0 on success and -1 on
> failure. This may seem odd for the first two Check functions, since
> they could also easily return true/false, but since they actually log
> an error when the requested condition isn't met (and should result in
> a failure of the calling function), I thought 0/-1 was more
> appropriate.
> ---
>   src/libvirt_private.syms         |   3 +
>   src/util/virnetdevvportprofile.c | 313 +++++++++++++++++++++++++++++++++++++++
>   src/util/virnetdevvportprofile.h |  17 ++-
>   3 files changed, 332 insertions(+), 1 deletion(-)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index c023dbf..89fb1f4 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -1427,8 +1427,11 @@ virNetDevVethDelete;
>
>   # virnetdevvportprofile.h
>   virNetDevVPortProfileAssociate;
> +virNetDevVPortProfileCheckComplete;
> +virNetDevVPortProfileCheckNoExtras;
>   virNetDevVPortProfileDisassociate;
>   virNetDevVPortProfileEqual;
> +virNetDevVPortProfileMerge3;
>   virNetDevVPortProfileOpTypeFromString;
>   virNetDevVPortProfileOpTypeToString;
>
> diff --git a/src/util/virnetdevvportprofile.c b/src/util/virnetdevvportprofile.c
> index 6db04f7..e686fd9 100644
> --- a/src/util/virnetdevvportprofile.c
> +++ b/src/util/virnetdevvportprofile.c
> @@ -120,6 +120,319 @@ virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a, virNetDevVPortProfilePtr
>       return true;
>   }
>
> +/* virNetDevVPortProfileCheckComplete() checks that all attributes
> + * required for the type of virtport are specified. When
> + * generateMissing is true, any missing attribute that can be
> + * autogenerated, will be (instanceid, interfaceid). If virtport ==
> + * NULL or virtPortType == NONE, then the result is always 0
> + * (success). If a required attribute is missing, an error is logged
> + * and -1 is returned.
> + */
> +int
> +virNetDevVPortProfileCheckComplete(virNetDevVPortProfilePtr virtport,
> +                                   bool generateMissing)
> +{
> +    const char *missing = NULL;
> +
> +    if (!virtport || virtport->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)
> +        return 0;
> +
> +    switch (virtport->virtPortType) {
> +    case VIR_NETDEV_VPORT_PROFILE_8021QBG:
> +        if (!virtport->managerID_specified) {
> +            missing = "managerid";
> +        } else if (!virtport->typeID_specified) {
> +            missing = "typeid";
> +        } else if (!virtport->typeIDVersion_specified) {
> +            missing = "typeidversion";
> +        } else if (!virtport->instanceID_specified) {
> +            if (generateMissing) {
> +                if (virUUIDGenerate(virtport->instanceID) < 0) {
> +                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                                   _("cannot generate a random uuid for instanceid"));
> +                    return -1;
> +                }
> +                virtport->instanceID_specified = true;
> +            } else {
> +                missing = "instanceid";
> +            }
> +        }
> +        break;
> +
> +    case VIR_NETDEV_VPORT_PROFILE_8021QBH:
> +        if (!virtport->profileID[0])
> +            missing = "profileid";
> +        break;
> +
> +    case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
> +        /* profileid is optional for openvswitch */
> +        if (!virtport->interfaceID_specified) {
> +            if (generateMissing) {
> +                if (virUUIDGenerate(virtport->interfaceID) < 0) {
> +                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                                   _("cannot generate a random uuid for interfaceid"));
> +                    return -1;
> +                }
> +                virtport->interfaceID_specified = true;
> +            } else {
> +                missing = "interfaceid";
> +            }
> +        }
> +        break;
> +    }
> +
> +    if (missing) {
> +        virReportError(VIR_ERR_XML_ERROR,
> +                       _("missing %s in <virtualport type='%s'>"), missing,
> +                       virNetDevVPortTypeToString(virtport->virtPortType));
> +        return -1;
> +    }
> +
> +    return 0;
> +}
> +
> +/* virNetDevVPortProfileCheckNoExtras() checks that there are no
> + * attributes specified in this virtport that are inappropriate for
> + * the type. if virtport == NULL or virtPortType == NONE, then the
> + * result is always 0 (success). If an extra attribute is present,
> + * an error is logged and -1 is returned.
> + */
> +int
> +virNetDevVPortProfileCheckNoExtras(virNetDevVPortProfilePtr virtport)
> +{
> +    const char *extra = NULL;
> +
> +    if (!virtport || virtport->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)
> +        return 0;
> +
> +    switch (virtport->virtPortType) {
> +    case VIR_NETDEV_VPORT_PROFILE_8021QBG:
> +        if (virtport->profileID[0])
> +            extra = "profileid";
> +        else if (virtport->interfaceID_specified)
> +            extra = "interfaceid";
> +        break;
> +
> +    case VIR_NETDEV_VPORT_PROFILE_8021QBH:
> +        if (virtport->managerID_specified)
> +            extra = "managerid";
> +        else if (virtport->typeID_specified)
> +            extra = "typeid";
> +        else if (virtport->typeIDVersion_specified)
> +            extra = "typeidversion";
> +        else if (virtport->instanceID_specified)
> +            extra = "instanceid";
> +        else if (virtport->interfaceID_specified)
> +            extra = "interfaceid";
> +        break;
> +
> +    case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
> +        if (virtport->managerID_specified)
> +            extra = "managerid";
> +        else if (virtport->typeID_specified)
> +            extra = "typeid";
> +        else if (virtport->typeIDVersion_specified)
> +            extra = "typeidversion";
> +        else if (virtport->instanceID_specified)
> +            extra = "instanceid";
> +        break;
> +    }
> +
> +    if (extra) {
> +        virReportError(VIR_ERR_XML_ERROR,
> +                       _("extra %s unsupported in <virtualport type='%s'>"),
> +                       extra,
> +                       virNetDevVPortTypeToString(virtport->virtPortType));
> +        return -1;
> +    }
> +
> +    return 0;
> +}
> +
> +/* virNetDevVPortProfileMerge() - merge the attributes in mods into
> + * orig. If anything that is set in mods has already been set in orig
> + * *and doesn't match*, log an error and return -1, otherwise return 0.
> + */
> +static int
> +virNetDevVPortProfileMerge(virNetDevVPortProfilePtr orig,
> +                           virNetDevVPortProfilePtr mods)
> +{
> +    enum virNetDevVPortProfile otype;
> +
> +    if (!orig || !mods)
> +        return 0;
> +
> +    otype = orig->virtPortType;
> +
> +    if (mods->virtPortType != VIR_NETDEV_VPORT_PROFILE_NONE) {
> +        if (otype != VIR_NETDEV_VPORT_PROFILE_NONE &&
> +            otype != mods->virtPortType) {
> +            virReportError(VIR_ERR_XML_ERROR,
> +                           _("attempt to merge virtualports "
> +                             "with mismatched types (%s and %s)"),
> +                           virNetDevVPortTypeToString(otype),
> +                           virNetDevVPortTypeToString(mods->virtPortType));
> +            return -1;
> +        }
> +        otype = orig->virtPortType = mods->virtPortType;
> +    }
> +
> +    if (mods->managerID_specified &&
> +        (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
> +         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
> +        if (orig->managerID_specified &&
> +            (orig->managerID != mods->managerID)) {
> +            virReportError(VIR_ERR_XML_ERROR,
> +                           _("attempt to merge virtualports "
> +                             "with mismatched managerids (%d and %d)"),
> +                           orig->managerID, mods->managerID);
> +            return -1;
> +        }
> +        orig->managerID = mods->managerID;
> +        orig->managerID_specified = true;
> +    }
> +
> +    if (mods->typeID_specified &&
> +        (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
> +         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
> +        if (orig->typeID_specified &&
> +            (orig->typeID != mods->typeID)) {
> +            virReportError(VIR_ERR_XML_ERROR,
> +                           _("attempt to merge virtualports "
> +                             "with mismatched typeids (%d and %d)"),
> +                           orig->typeID, mods->typeID);
> +            return -1;
> +        }
> +        orig->typeID = mods->typeID;
> +        orig->typeID_specified = true;
> +    }
> +
> +    if (mods->typeIDVersion_specified &&
> +        (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
> +         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
> +        if (orig->typeIDVersion_specified &&
> +            (orig->typeIDVersion != mods->typeIDVersion)) {
> +            virReportError(VIR_ERR_XML_ERROR,
> +                           _("attempt to merge virtualports with "
> +                             "mismatched typeidversions (%d and %d)"),
> +                           orig->typeIDVersion, mods->typeIDVersion);
> +            return -1;
> +        }
> +        orig->typeIDVersion = mods->typeIDVersion;
> +        orig->typeIDVersion_specified = true;
> +    }
> +
> +    if (mods->instanceID_specified &&
> +        (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
> +         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
> +        if (orig->instanceID_specified &&
> +            memcmp(orig->instanceID, mods->instanceID,
> +                   sizeof(orig->instanceID))) {
> +            char origuuid[VIR_UUID_STRING_BUFLEN];
> +            char modsuuid[VIR_UUID_STRING_BUFLEN];
> +
> +            virReportError(VIR_ERR_XML_ERROR,
> +                           _("attempt to merge virtualports with "
> +                             "mismatched instanceids ('%s' and '%s')"),
> +                           virUUIDFormat(orig->instanceID, origuuid),
> +                           virUUIDFormat(mods->instanceID, modsuuid));
> +            return -1;
> +        }
> +        memcpy(orig->instanceID, mods->instanceID, sizeof(orig->instanceID));
> +        orig->instanceID_specified = true;
> +    }
> +
> +    if (mods->interfaceID_specified &&
> +        (otype == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
> +         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
> +        if (orig->interfaceID_specified &&
> +            memcmp(orig->interfaceID, mods->interfaceID,
> +                   sizeof(orig->interfaceID))) {
> +            char origuuid[VIR_UUID_STRING_BUFLEN];
> +            char modsuuid[VIR_UUID_STRING_BUFLEN];
> +
> +            virReportError(VIR_ERR_XML_ERROR,
> +                           _("attempt to merge virtualports with "
> +                             "mismatched interfaceids ('%s' and '%s')"),
> +                           virUUIDFormat(orig->interfaceID, origuuid),
> +                           virUUIDFormat(mods->interfaceID, modsuuid));
> +            return -1;
> +        }
> +        memcpy(orig->interfaceID, mods->interfaceID, sizeof(orig->interfaceID));
> +        orig->interfaceID_specified = true;
> +    }
> +
> +    if (mods->profileID[0] &&
> +        (otype == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
> +         otype == VIR_NETDEV_VPORT_PROFILE_8021QBH ||
> +         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
> +        if (orig->profileID[0] &&
> +            STRNEQ(orig->profileID, mods->profileID)) {
> +            virReportError(VIR_ERR_XML_ERROR,
> +                           _("attempt to merge virtualports with "
> +                             "mismatched profileids ('%s' and '%s')"),
> +                           orig->profileID, mods->profileID);
> +            return -1;
> +        }
> +        if (virStrcpyStatic(orig->profileID, mods->profileID)) {
> +            /* this should never happen - it indicates mods->profileID
> +             * isn't properly null terminated. */
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                           _("corrupted profileid string"));
> +            return -1;
> +        }
> +    }
> +    return 0;
> +}
> +
> +/* virNetDevVPortProfileMerge3() - create a new virNetDevVPortProfile
> + * that is a combination of the three input profiles. fromInterface is
> + * highest priority and fromPortgroup is lowest. As lower priority
> + * objects' attributes are merged in, if the attribute is unset in the
> + * result object, it is set from the lower priority object, but if it
> + * is already set in the result and the lower priority object wants to
> + * change it, that is an error.
> + */
> +
> +int virNetDevVPortProfileMerge3(virNetDevVPortProfilePtr *result,
> +                                virNetDevVPortProfilePtr fromInterface,
> +                                virNetDevVPortProfilePtr fromNetwork,
> +                                virNetDevVPortProfilePtr fromPortgroup)
> +{
> +    int ret = -1;
> +    *result = NULL;
> +
> +    if ((!fromInterface || (fromInterface->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)) &&
> +        (!fromNetwork   || (fromNetwork->virtPortType   == VIR_NETDEV_VPORT_PROFILE_NONE)) &&
> +        (!fromPortgroup || (fromPortgroup->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE))) {
> +        return 0;
> +    }
> +
> +    /* at least one of the source profiles is non-empty */
> +    if (VIR_ALLOC(*result) < 0) {
I get a compile error here:
cc1: warnings being treated as errors
../../src/util/virnetdevvportprofile.c: In function 
'virNetDevVPortProfileMerge3':
../../src/util/virnetdevvportprofile.c:412: error: implicit declaration 
of function 'VIR_ALLOC' [-Wimplicit-function-declaration]
../../src/util/virnetdevvportprofile.c:412: error: nested extern 
declaration of 'VIR_ALLOC' [-Wnested-externs]
> +        virReportOOMError();
> +        return ret;
> +    }
> +
> +    /* start with the interface's profile. There are no pointers in a
> +     * virtualPortProfile, so a shallow copy is sufficient.
> +     */
> +    if (fromInterface)
> +        **result = *fromInterface;
> +
> +    if (virNetDevVPortProfileMerge(*result, fromNetwork) < 0)
> +        goto error;
> +    if (virNetDevVPortProfileMerge(*result, fromPortgroup) < 0)
> +        goto error;
> +
> +    ret = 0;
> +
> +error:
> +    if (ret < 0)
> +        VIR_FREE(*result);
and here ...
../../src/util/virnetdevvportprofile.c:432: error: implicit declaration 
of function 'VIR_FREE' [-Wimplicit-function-declaration]
../../src/util/virnetdevvportprofile.c:432: error: nested extern 
declaration of 'VIR_FREE' [-Wnested-externs]
> +    return ret;
> +}
> +
>
>   #if WITH_VIRTUALPORT
>
> diff --git a/src/util/virnetdevvportprofile.h b/src/util/virnetdevvportprofile.h
> index 3c16bfe..d23c284 100644
> --- a/src/util/virnetdevvportprofile.h
> +++ b/src/util/virnetdevvportprofile.h
> @@ -58,18 +58,24 @@ VIR_ENUM_DECL(virNetDevVPortProfileOp)
>   typedef struct _virNetDevVPortProfile virNetDevVPortProfile;
>   typedef virNetDevVPortProfile *virNetDevVPortProfilePtr;
>   struct _virNetDevVPortProfile {
> -    enum virNetDevVPortProfile   virtPortType;
> +    int           virtPortType; /* enum virNetDevVPortProfile */
>       /* these members are used when virtPortType == 802.1Qbg */
>       uint8_t       managerID;
> +    bool          managerID_specified;
>       uint32_t      typeID; /* 24 bit valid */
> +    bool          typeID_specified;
>       uint8_t       typeIDVersion;
> +    bool          typeIDVersion_specified;
>       unsigned char instanceID[VIR_UUID_BUFLEN];
> +    bool          instanceID_specified;
>
>       /* this member is used when virtPortType == 802.1Qbh|openvswitch */
> +    /* this is a null-terminated character string */
>       char          profileID[LIBVIRT_IFLA_VF_PORT_PROFILE_MAX];
>
>       /* this member is used when virtPortType == openvswitch */
>       unsigned char interfaceID[VIR_UUID_BUFLEN];
> +    bool          interfaceID_specified;
>       /* NB - if virtPortType == NONE, any/all of the items could be used */
>   };
>
> @@ -77,6 +83,15 @@ struct _virNetDevVPortProfile {
>   bool virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a,
>                                   virNetDevVPortProfilePtr b);
>
> +int virNetDevVPortProfileCheckComplete(virNetDevVPortProfilePtr virtport,
> +                                       bool generateMissing);
> +int virNetDevVPortProfileCheckNoExtras(virNetDevVPortProfilePtr virtport);
> +
> +int virNetDevVPortProfileMerge3(virNetDevVPortProfilePtr *result,
> +                                virNetDevVPortProfilePtr fromInterface,
> +                                virNetDevVPortProfilePtr fromNetwork,
> +                                virNetDevVPortProfilePtr fromPortgroup);
> +
>   int virNetDevVPortProfileAssociate(const char *ifname,
>                                      const virNetDevVPortProfilePtr virtPort,
>                                      const virMacAddrPtr macaddr,
>


-- 

Mit freundlichen Grüßen/Kind Regards
    Viktor Mihajlovski

IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Martin Jetter
Geschäftsführung: Dirk Wittkopp
Sitz der Gesellschaft: Böblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294




More information about the libvir-list mailing list