static void
qemuMigrationCookieNetworkXMLFormat(virBufferPtr buf,
                                    qemuMigrationCookieNetworkPtr optr)
{
    size_t i;
    bool empty = true;

    for (i = 0; i < optr->nnets; i++) {
        /* If optr->net[i].vporttype is not set, there is nothing to transfer */
        if (optr->net[i].vporttype != VIR_NETDEV_VPORT_PROFILE_NONE) {
            if (empty) {
                virBufferAddLit(buf, "<network>\n");
                virBufferAdjustIndent(buf, 2);
                empty = false;
            }
            virBufferAsprintf(buf, "<interface index='%zu' vporttype='%s'",
                              i, virNetDevVPortTypeToString(optr->net[i].vporttype));
            if (optr->net[i].portdata) {
                virBufferAddLit(buf, ">\n");
                virBufferAdjustIndent(buf, 2);
                virBufferEscapeString(buf, "<portdata>%s</portdata>\n",
                                      optr->net[i].portdata);
                virBufferAdjustIndent(buf, -2);
                virBufferAddLit(buf, "</interface>\n");
            } else {
                virBufferAddLit(buf, "/>\n");
            }
        }
    }
    if (!empty) {
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</network>\n");
    }
}
int
virNetDevVPortProfileFormat(virNetDevVPortProfilePtr virtPort,
                            virBufferPtr buf)
{
    char uuidstr[VIR_UUID_STRING_BUFLEN];

    if (!virtPort || virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)
        return 0;

    virBufferAsprintf(buf, "<virtualport type='%s'>\n",
                      virNetDevVPortTypeToString(virtPort->virtPortType));

    switch (virtPort->virtPortType) {
    case VIR_NETDEV_VPORT_PROFILE_8021QBG:
        virUUIDFormat(virtPort->u.virtPort8021Qbg.instanceID,
                      uuidstr);
        virBufferAsprintf(buf,
                          "  <parameters managerid='%d' typeid='%d' "
                          "typeidversion='%d' instanceid='%s'/>\n",
                          virtPort->u.virtPort8021Qbg.managerID,
                          virtPort->u.virtPort8021Qbg.typeID,
                          virtPort->u.virtPort8021Qbg.typeIDVersion,
                          uuidstr);
        break;

    case VIR_NETDEV_VPORT_PROFILE_8021QBH:
        virBufferAsprintf(buf,
                          "  <parameters profileid='%s'/>\n",
                          virtPort->u.virtPort8021Qbh.profileID);
        break;

    case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
        virUUIDFormat(virtPort->u.openvswitch.interfaceID,
                      uuidstr);
        if (virtPort->u.openvswitch.profileID[0] == '\0') {
            virBufferAsprintf(buf, "  <parameters interfaceid='%s'/>\n",
                              uuidstr);
        } else {
            virBufferAsprintf(buf, "  <parameters interfaceid='%s' "
                              "profileid='%s'/>\n", uuidstr,
                              virtPort->u.openvswitch.profileID);
        }

        break;

    default:
        virReportError(VIR_ERR_XML_ERROR,
                       _("unexpected virtualport type %d"), virtPort->virtPortType);
        return -1;
    }

    virBufferAddLit(buf, "</virtualport>\n");
    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;
}
static int
qemuDomainHostdevNetConfigVirtPortProfile(const char *linkdev, int vf,
                                          virNetDevVPortProfilePtr virtPort,
                                          const virMacAddrPtr macaddr,
                                          const unsigned char *uuid,
                                          int associate)
{
    int ret = -1;

    if (!virtPort)
        return ret;

    switch(virtPort->virtPortType) {
    case VIR_NETDEV_VPORT_PROFILE_NONE:
    case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
    case VIR_NETDEV_VPORT_PROFILE_8021QBG:
    case VIR_NETDEV_VPORT_PROFILE_LAST:
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("virtualport type %s is "
                         "currently not supported on interfaces of type "
                         "hostdev"),
                       virNetDevVPortTypeToString(virtPort->virtPortType));
        break;

    case VIR_NETDEV_VPORT_PROFILE_8021QBH:
        if (associate)
            ret = virNetDevVPortProfileAssociate(NULL, virtPort, macaddr,
                                                 linkdev, vf, uuid,
                                                 VIR_NETDEV_VPORT_PROFILE_OP_CREATE, false);
        else
            ret = virNetDevVPortProfileDisassociate(NULL, virtPort,
                                                    macaddr, linkdev, vf,
                                                    VIR_NETDEV_VPORT_PROFILE_OP_DESTROY);
        break;
    }

    return ret;
}
int
qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev,
                                  const unsigned char *uuid,
                                  char *stateDir)
{
    char *linkdev = NULL;
    virNetDevVlanPtr vlan;
    virNetDevVPortProfilePtr virtPort;
    int ret = -1;
    int vf = -1;
    int vlanid = -1;
    int port_profile_associate = 1;
    int isvf;

    isvf = qemuDomainHostdevIsVirtualFunction(hostdev);
    if (isvf <= 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Interface type hostdev is currently supported on"
                         " SR-IOV Virtual Functions only"));
        return ret;
    }

    if (qemuDomainHostdevNetDevice(hostdev, &linkdev, &vf) < 0)
        return ret;

    vlan = virDomainNetGetActualVlan(hostdev->parent.data.net);
    virtPort = virDomainNetGetActualVirtPortProfile(
                                 hostdev->parent.data.net);
    if (virtPort) {
        if (vlan) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("direct setting of the vlan tag is not allowed "
                             "for hostdev devices using %s mode"),
                           virNetDevVPortTypeToString(virtPort->virtPortType));
            goto cleanup;
        }
        ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf,
                            virtPort, &hostdev->parent.data.net->mac, uuid,
                            port_profile_associate);
    } else {
        /* Set only mac and vlan */
        if (vlan) {
            if (vlan->nTags != 1 || vlan->trunk) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("vlan trunking is not supported "
                                 "by SR-IOV network devices"));
                goto cleanup;
            }
            if (vf == -1) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("vlan can only be set for SR-IOV VFs, but "
                                 "%s is not a VF"), linkdev);
                goto cleanup;
            }
            vlanid = vlan->tag[0];
        } else  if (vf >= 0) {
            vlanid = 0; /* assure any current vlan tag is reset */
        }

        ret = virNetDevReplaceNetConfig(linkdev, vf,
                                        &hostdev->parent.data.net->mac,
                                        vlanid, stateDir);
    }
cleanup:
    VIR_FREE(linkdev);
    return ret;
}
/* 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) == NULL) {
            /* 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;
}
/* 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;
}
int
virNetDevVPortProfileFormat(virNetDevVPortProfilePtr virtPort,
                            virBufferPtr buf)
{
    enum virNetDevVPortProfile type;
    bool noParameters;

    if (!virtPort)
        return 0;

    noParameters = !(virtPort->managerID_specified ||
                     virtPort->typeID_specified ||
                     virtPort->typeIDVersion_specified ||
                     virtPort->instanceID_specified ||
                     virtPort->profileID[0] ||
                     virtPort->interfaceID_specified);

    type = virtPort->virtPortType;
    if (type == VIR_NETDEV_VPORT_PROFILE_NONE) {
        if (noParameters)
            return 0;
        virBufferAddLit(buf, "<virtualport>\n");
    } else {
        if (noParameters) {
            virBufferAsprintf(buf, "<virtualport type='%s'/>\n",
                              virNetDevVPortTypeToString(type));
            return 0;
        } else {
            virBufferAsprintf(buf, "<virtualport type='%s'>\n",
                              virNetDevVPortTypeToString(type));
        }
    }
    virBufferAddLit(buf, "  <parameters");

    if (virtPort->managerID_specified &&
        (type == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        virBufferAsprintf(buf, " managerid='%d'", virtPort->managerID);
    }
    if (virtPort->typeID_specified &&
        (type == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        virBufferAsprintf(buf, " typeid='%d'", virtPort->typeID);
    }
    if (virtPort->typeIDVersion_specified &&
        (type == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        virBufferAsprintf(buf, " typeidversion='%d'",
                          virtPort->typeIDVersion);
    }
    if (virtPort->instanceID_specified &&
        (type == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(virtPort->instanceID, uuidstr);
        virBufferAsprintf(buf, " instanceid='%s'", uuidstr);
    }
    if (virtPort->interfaceID_specified &&
        (type == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
         type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(virtPort->interfaceID, uuidstr);
        virBufferAsprintf(buf, " interfaceid='%s'", uuidstr);
    }
    if (virtPort->profileID[0] &&
        (type == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
         type == VIR_NETDEV_VPORT_PROFILE_8021QBH ||
         type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        virBufferAsprintf(buf, " profileid='%s'", virtPort->profileID);
    }

    virBufferAddLit(buf, "/>\n");
    virBufferAddLit(buf, "</virtualport>\n");
    return 0;
}