[libvirt] [PATCH v2] 802.1Qbg: use pre-associate state at beginning of incoming migration

roprabhu roprabhu at cisco.com
Fri Nov 26 22:37:18 UTC 2010


Hi Stefan,

Sorry about the delay. I verified your patch for 802.1Qbh. Its all fine. No
side-effects.

Thanks,
Roopa



On 11/24/10 5:39 AM, "Stefan Berger" <stefanb at linux.vnet.ibm.com> wrote:

> -v2:
>      - changing the vmOpStr array and vmOperation enum to use
> VIR_ENUM_IMPL and VIR_ENUM_DECL. Renaming the enum to virVMOperationType
> and adapting the name of the enum constants.
> 
> This patch introduces the usage of the pre-associate state of the IEEE
> 802.1Qbg standard on incoming VM migration on the target host. It is in
> response to bugzilla entry 632750.
> 
> https://bugzilla.redhat.com/show_bug.cgi?id=632750
> 
> For being able to differentiate the exact reason as to why a macvtap
> device is being created, either due to a VM creation or an incoming VM
> migration, I needed to pass that reason as a parameter from wherever
> qemudStartVMDaemon is being called in order to determine whether to send
> an ASSOCIATE (VM creation) or a PRE-ASSOCIATE (incoming VM migration)
> towards lldpad.
> 
> I am also fixing a problem with the virsh domainxml-to-native call on
> the way.
> 
> Gerhard successfully tested the patch with a recent blade network
> 802.1Qbg-compliant switch.
> 
> The patch should not have any side-effects on the 802.1Qbh support in
> libvirt, but Roopa (cc'ed) may want to verify this.
> 
> Signed-off-by: Stefan Berger <stefanb at us.ibm.com>
> Signed-off-by: Gerhard Stenzel <gerhard.stenzel at de.ibm.com>
> 
> ---
>   src/libvirt_macvtap.syms |    2 +
>   src/qemu/qemu_conf.c     |   12 +++++--
>   src/qemu/qemu_conf.h     |    7 +++-
>   src/qemu/qemu_driver.c   |   72
> +++++++++++++++++++++++++++++++++++++----------
>   src/util/macvtap.c       |   54 ++++++++++++++++++++++++++++++-----
>   src/util/macvtap.h       |   20 +++++++++++--
>   6 files changed, 137 insertions(+), 30 deletions(-)
> 
> Index: libvirt-acl/src/qemu/qemu_conf.c
> ===================================================================
> --- libvirt-acl.orig/src/qemu/qemu_conf.c
> +++ libvirt-acl/src/qemu/qemu_conf.c
> @@ -1642,7 +1642,8 @@ qemudPhysIfaceConnect(virConnectPtr conn
>                         struct qemud_driver *driver,
>                         virDomainNetDefPtr net,
>                         unsigned long long qemuCmdFlags,
> -                      const unsigned char *vmuuid)
> +                      const unsigned char *vmuuid,
> +                      enum virVMOperationType vmop)
>   {
>       int rc;
>   #if WITH_MACVTAP
> @@ -1656,7 +1657,8 @@ qemudPhysIfaceConnect(virConnectPtr conn
> 
>       rc = openMacvtapTap(net->ifname, net->mac, net->data.direct.linkdev,
>                           net->data.direct.mode, vnet_hdr, vmuuid,
> - &net->data.direct.virtPortProfile, &res_ifname);
> + &net->data.direct.virtPortProfile, &res_ifname,
> +                        vmop);
>       if (rc >= 0) {
>           VIR_FREE(net->ifname);
>           net->ifname = res_ifname;
> @@ -3953,7 +3955,8 @@ int qemudBuildCommandLine(virConnectPtr
>                             int **vmfds,
>                             int *nvmfds,
>                             const char *migrateFrom,
> -                          virDomainSnapshotObjPtr current_snapshot)
> +                          virDomainSnapshotObjPtr current_snapshot,
> +                          enum virVMOperationType vmop)
>   {
>       int i;
>       char memory[50];
> @@ -4796,7 +4799,8 @@ int qemudBuildCommandLine(virConnectPtr
>               } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
>                   int tapfd = qemudPhysIfaceConnect(conn, driver, net,
>                                                     qemuCmdFlags,
> -                                                  def->uuid);
> +                                                  def->uuid,
> +                                                  vmop);
>                   if (tapfd < 0)
>                       goto error;
> 
> Index: libvirt-acl/src/qemu/qemu_conf.h
> ===================================================================
> --- libvirt-acl.orig/src/qemu/qemu_conf.h
> +++ libvirt-acl/src/qemu/qemu_conf.h
> @@ -40,6 +40,7 @@
>   # include "cpu_conf.h"
>   # include "driver.h"
>   # include "bitmap.h"
> +# include "macvtap.h"
> 
>   # define qemudDebug(fmt, ...) do {} while(0)
> 
> @@ -238,7 +239,8 @@ int         qemudBuildCommandLine
>                                            int **vmfds,
>                                            int *nvmfds,
>                                            const char *migrateFrom,
> -                                         virDomainSnapshotObjPtr
> current_snapshot)
> +                                         virDomainSnapshotObjPtr
> current_snapshot,
> +                                         enum virVMOperationType vmop)
>       ATTRIBUTE_NONNULL(1);
> 
>   /* With vlan == -1, use netdev syntax, else old hostnet */
> @@ -317,7 +319,8 @@ int qemudPhysIfaceConnect(virConnectPtr
>                             struct qemud_driver *driver,
>                             virDomainNetDefPtr net,
>                             unsigned long long qemuCmdFlags,
> -                          const unsigned char *vmuuid);
> +                          const unsigned char *vmuuid,
> +                          enum virVMOperationType vmop);
> 
>   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
> @@ -163,7 +163,8 @@ static int qemudStartVMDaemon(virConnect
>                                 const char *migrateFrom,
>                                 bool start_paused,
>                                 int stdin_fd,
> -                              const char *stdin_path);
> +                              const char *stdin_path,
> +                              enum virVMOperationType vmop);
> 
>   static void qemudShutdownVMDaemon(struct qemud_driver *driver,
>                                     virDomainObjPtr vm,
> @@ -3864,7 +3865,8 @@ static int qemudStartVMDaemon(virConnect
>                                 const char *migrateFrom,
>                                 bool start_paused,
>                                 int stdin_fd,
> -                              const char *stdin_path) {
> +                              const char *stdin_path,
> +                              enum virVMOperationType vmop) {
>       const char **argv = NULL, **tmp;
>       const char **progenv = NULL;
>       int i, ret, runflags;
> @@ -4065,7 +4067,7 @@ static int qemudStartVMDaemon(virConnect
>       if (qemudBuildCommandLine(conn, driver, vm->def, priv->monConfig,
>                                 priv->monJSON, qemuCmdFlags, &argv,
> &progenv,
> &vmfds, &nvmfds, migrateFrom,
> -                              vm->current_snapshot) < 0)
> +                              vm->current_snapshot, vmop) < 0)
>           goto cleanup;
> 
>       if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir) < 0)
> @@ -4879,7 +4881,7 @@ static virDomainPtr qemudDomainCreate(vi
> 
>       if (qemudStartVMDaemon(conn, driver, vm, NULL,
>                              (flags & VIR_DOMAIN_START_PAUSED) != 0,
> -                           -1, NULL) < 0) {
> +                           -1, NULL, VIR_VM_OP_CREATE) < 0) {
>           qemuDomainStartAudit(vm, "booted", false);
>           if (qemuDomainObjEndJob(vm) > 0)
>               virDomainRemoveInactive(&driver->domains,
> @@ -7015,7 +7017,8 @@ qemudDomainSaveImageStartVM(virConnectPt
>       }
> 
>       /* Set the migration source and start it up. */
> -    ret = qemudStartVMDaemon(conn, driver, vm, "stdio", true, fd, path);
> +    ret = qemudStartVMDaemon(conn, driver, vm, "stdio", true, fd, path,
> +                             VIR_VM_OP_RESTORE);
> 
>       if (intermediate_pid != -1) {
>           /* Wait for intermediate process to exit */
> @@ -7334,14 +7337,15 @@ static char *qemuDomainXMLToNative(virCo
>       if (!def)
>           goto cleanup;
> 
> -    /* Since we're just exporting args, we can't do bridge/network
> -     * setups, since libvirt will normally create TAP devices
> +    /* Since we're just exporting args, we can't do bridge/network/direct
> +     * setups, since libvirt will normally create TAP/macvtap devices
>        * directly. We convert those configs into generic 'ethernet'
>        * config and assume the user has suitable 'ifup-qemu' scripts
>        */
>       for (i = 0 ; i < def->nnets ; i++) {
>           virDomainNetDefPtr net = def->nets[i];
> -        if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
> +        if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
> +            net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
>               VIR_FREE(net->data.network.name);
> 
>               memset(net, 0, sizeof *net);
> @@ -7397,7 +7401,8 @@ static char *qemuDomainXMLToNative(virCo
> &monConfig, 0, qemuCmdFlags,
> &retargv, &retenv,
>                                 NULL, NULL, /* Don't want it to create
> TAP devices */
> -                              NULL, NULL) < 0) {
> +                              NULL, NULL,
> +                              VIR_VM_OP_NO_OP) < 0) {
>           goto cleanup;
>       }
> 
> @@ -7484,7 +7489,8 @@ static int qemudDomainObjStart(virConnec
>               goto cleanup;
>       }
> 
> -    ret = qemudStartVMDaemon(conn, driver, vm, NULL, start_paused, -1,
> NULL);
> +    ret = qemudStartVMDaemon(conn, driver, vm, NULL, start_paused, -1,
> NULL,
> +                             VIR_VM_OP_CREATE);
>       qemuDomainStartAudit(vm, "booted", ret >= 0);
>       if (ret >= 0) {
>           virDomainEventPtr event =
> @@ -8327,7 +8333,8 @@ static int qemudDomainAttachNetDevice(vi
> 
>           if ((tapfd = qemudPhysIfaceConnect(conn, driver, net,
>                                              qemuCmdFlags,
> -                                           vm->def->uuid)) < 0)
> +                                           vm->def->uuid,
> +                                           VIR_VM_OP_CREATE)) < 0)
>               return -1;
>       }
> 
> @@ -11001,7 +11008,7 @@ qemudDomainMigratePrepareTunnel(virConne
>        * -incoming unix:/path/to/file or exec:nc -U /path/to/file
>        */
>       internalret = qemudStartVMDaemon(dconn, driver, vm, migrateFrom, true,
> -                                     -1, NULL);
> +                                     -1, NULL, VIR_VM_OP_MIGRATE_IN_START);
>       VIR_FREE(migrateFrom);
>       if (internalret < 0) {
>           qemuDomainStartAudit(vm, "migrated", false);
> @@ -11247,7 +11254,7 @@ qemudDomainMigratePrepare2 (virConnectPt
>        */
>       snprintf (migrateFrom, sizeof (migrateFrom), "tcp:0.0.0.0:%d",
> this_port);
>       if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, true,
> -                            -1, NULL) < 0) {
> +                            -1, NULL, VIR_VM_OP_MIGRATE_IN_START) < 0) {
>           qemuDomainStartAudit(vm, "migrated", false);
>           /* Note that we don't set an error here because qemudStartVMDaemon
>            * should have already done that.
> @@ -11862,6 +11869,41 @@ cleanup:
>       return ret;
>   }
> 
> +static void
> +qemudVPAssociatePortProfiles(virDomainDefPtr def) {
> +    int i;
> +    int last_good_net = -1;
> +    virDomainNetDefPtr net;
> +
> +    for (i = 0; i < def->nnets; i++) {
> +        net = def->nets[i];
> +        if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
> +            if (vpAssociatePortProfileId(net->ifname,
> +                                         net->mac,
> +                                         net->data.direct.linkdev,
> + &net->data.direct.virtPortProfile,
> +                                         def->uuid,
> +                                         VIR_VM_OP_MIGRATE_IN_FINISH) != 0)
> +                goto err_exit;
> +        }
> +        last_good_net = i;
> +    }
> +
> +    return;
> +
> +err_exit:
> +    for (i = 0; i < last_good_net; i++) {
> +        net = def->nets[i];
> +        if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
> +            vpDisassociatePortProfileId(net->ifname,
> +                                        net->mac,
> +                                        net->data.direct.linkdev,
> + &net->data.direct.virtPortProfile,
> +                                        VIR_VM_OP_MIGRATE_IN_FINISH);
> +        }
> +    }
> +}
> +
>   /* Finish is the third and final step, and it runs on the destination
> host. */
>   static virDomainPtr
>   qemudDomainMigrateFinish2 (virConnectPtr dconn,
> @@ -11922,6 +11964,8 @@ qemudDomainMigrateFinish2 (virConnectPtr
>               goto cleanup;
>           }
> 
> +        qemudVPAssociatePortProfiles(vm->def);
> +
>           if (flags & VIR_MIGRATE_PERSIST_DEST) {
>               if (vm->persistent)
>                   newVM = 0;
> @@ -12814,7 +12858,7 @@ static int qemuDomainRevertToSnapshot(vi
>                   goto endjob;
> 
>               rc = qemudStartVMDaemon(snapshot->domain->conn, driver,
> vm, NULL,
> -                                    false, -1, NULL);
> +                                    false, -1, NULL, VIR_VM_OP_CREATE);
>               qemuDomainStartAudit(vm, "from-snapshot", rc >= 0);
>               if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir)
> < 0)
>                   goto endjob;
> Index: libvirt-acl/src/util/macvtap.c
> ===================================================================
> --- libvirt-acl.orig/src/util/macvtap.c
> +++ libvirt-acl/src/util/macvtap.c
> @@ -77,9 +77,21 @@
>   # define LLDPAD_PID_FILE  "/var/run/lldpad.pid"
> 
> 
> +VIR_ENUM_IMPL(virVMOperation, VIR_VM_OP_LAST,
> +    "create",
> +    "save",
> +    "restore",
> +    "destroy",
> +    "migrate out",
> +    "migrate in start",
> +    "migrate in finish",
> +    "no-op")
> +
> +
>   enum virVirtualPortOp {
>       ASSOCIATE = 0x1,
>       DISASSOCIATE = 0x2,
> +    PREASSOCIATE = 0x3,
>   };
> 
> 
> @@ -551,7 +563,8 @@ openMacvtapTap(const char *tgifname,
>                  int vnet_hdr,
>                  const unsigned char *vmuuid,
>                  virVirtualPortProfileParamsPtr virtPortProfile,
> -               char **res_ifname)
> +               char **res_ifname,
> +               enum virVMOperationType vmOp)
>   {
>       const char *type = "macvtap";
>       int c, rc;
> @@ -563,6 +576,8 @@ openMacvtapTap(const char *tgifname,
> 
>       *res_ifname = NULL;
> 
> +    VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__,
> virVMOperationTypeToString(vmOp));
> +
>       if (tgifname) {
>           if(ifaceGetIndex(false, tgifname, &ifindex) == 0) {
>               if (STRPREFIX(tgifname,
> @@ -601,7 +616,7 @@ create_name:
>                                    macaddress,
>                                    linkdev,
>                                    virtPortProfile,
> -                                 vmuuid) != 0) {
> +                                 vmuuid, vmOp) != 0) {
>           rc = -1;
>           goto link_del_exit;
>       }
> @@ -634,7 +649,8 @@ disassociate_exit:
>       vpDisassociatePortProfileId(cr_ifname,
>                                   macaddress,
>                                   linkdev,
> -                                virtPortProfile);
> +                                virtPortProfile,
> +                                vmOp);
> 
>   link_del_exit:
>       link_del(cr_ifname);
> @@ -662,7 +678,8 @@ delMacvtap(const char *ifname,
>       if (ifname) {
>           vpDisassociatePortProfileId(ifname, macaddr,
>                                       linkdev,
> -                                    virtPortProfile);
> +                                    virtPortProfile,
> +                                    VIR_VM_OP_DESTROY);
>           link_del(ifname);
>       }
>   }
> @@ -1320,6 +1337,9 @@ doPortProfileOp8021Qbg(const char *ifnam
>       portVsi.vsi_type_id[0] = virtPort->u.virtPort8021Qbg.typeID;
> 
>       switch (virtPortOp) {
> +    case PREASSOCIATE:
> +        op = PORT_REQUEST_PREASSOCIATE;
> +        break;
>       case ASSOCIATE:
>           op = PORT_REQUEST_ASSOCIATE;
>           break;
> @@ -1484,6 +1504,7 @@ err_exit:
>    * @macvtap_ifname: The name of the macvtap device
>    * @virtPort: pointer to the object holding port profile parameters
>    * @vmuuid : the UUID of the virtual machine
> + * @vmOp : The VM operation (i.e., create, no-op)
>    *
>    * Associate a port on a swtich with a profile. This function
>    * may notify a kernel driver or an external daemon to run
> @@ -1499,13 +1520,19 @@ vpAssociatePortProfileId(const char *mac
>                            const unsigned char *macvtap_macaddr,
>                            const char *linkdev,
>                            const virVirtualPortProfileParamsPtr virtPort,
> -                         const unsigned char *vmuuid)
> +                         const unsigned char *vmuuid,
> +                         enum virVMOperationType vmOp)
>   {
>       int rc = 0;
> 
>       VIR_DEBUG("Associating port profile '%p' on link device '%s'",
>                 virtPort, macvtap_ifname);
> 
> +    VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__,
> virVMOperationTypeToString(vmOp));
> +
> +    if (vmOp == VIR_VM_OP_NO_OP)
> +        return 0;
> +
>       switch (virtPort->virtPortType) {
>       case VIR_VIRTUALPORT_NONE:
>       case VIR_VIRTUALPORT_TYPE_LAST:
> @@ -1513,10 +1540,16 @@ vpAssociatePortProfileId(const char *mac
> 
>       case VIR_VIRTUALPORT_8021QBG:
>           rc = doPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr,
> -                                    virtPort, ASSOCIATE);
> +                                    virtPort,
> +                                    (vmOp == VIR_VM_OP_MIGRATE_IN_START)
> +                                      ? PREASSOCIATE
> +                                      : ASSOCIATE);
>           break;
> 
>       case VIR_VIRTUALPORT_8021QBH:
> +        /* avoid associating twice */
> +        if (vmOp == VIR_VM_OP_MIGRATE_IN_FINISH)
> +            break;
>           rc = doPortProfileOp8021Qbh(linkdev, virtPort,
>                                       vmuuid,
>                                       ASSOCIATE);
> @@ -1542,13 +1575,16 @@ int
>   vpDisassociatePortProfileId(const char *macvtap_ifname,
>                               const unsigned char *macvtap_macaddr,
>                               const char *linkdev,
> -                            const virVirtualPortProfileParamsPtr virtPort)
> +                            const virVirtualPortProfileParamsPtr virtPort,
> +                            enum virVMOperationType vmOp)
>   {
>       int rc = 0;
> 
>       VIR_DEBUG("Disassociating port profile id '%p' on link device '%s' ",
>                 virtPort, macvtap_ifname);
> 
> +    VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__,
> virVMOperationTypeToString(vmOp));
> +
>       switch (virtPort->virtPortType) {
>       case VIR_VIRTUALPORT_NONE:
>       case VIR_VIRTUALPORT_TYPE_LAST:
> @@ -1560,6 +1596,9 @@ vpDisassociatePortProfileId(const char *
>           break;
> 
>       case VIR_VIRTUALPORT_8021QBH:
> +        /* avoid disassociating twice */
> +        if (vmOp == VIR_VM_OP_MIGRATE_IN_FINISH)
> +            break;
>           rc = doPortProfileOp8021Qbh(linkdev, virtPort,
>                                       NULL,
>                                       DISASSOCIATE);
> Index: libvirt-acl/src/util/macvtap.h
> ===================================================================
> --- libvirt-acl.orig/src/util/macvtap.h
> +++ libvirt-acl/src/util/macvtap.h
> @@ -62,6 +62,19 @@ struct _virVirtualPortProfileParams {
> 
>   #  include "internal.h"
> 
> +enum virVMOperationType {
> +    VIR_VM_OP_CREATE,
> +    VIR_VM_OP_SAVE,
> +    VIR_VM_OP_RESTORE,
> +    VIR_VM_OP_DESTROY,
> +    VIR_VM_OP_MIGRATE_OUT,
> +    VIR_VM_OP_MIGRATE_IN_START,
> +    VIR_VM_OP_MIGRATE_IN_FINISH,
> +    VIR_VM_OP_NO_OP,
> +
> +    VIR_VM_OP_LAST
> +};
> +
>   int openMacvtapTap(const char *ifname,
>                      const unsigned char *macaddress,
>                      const char *linkdev,
> @@ -69,7 +82,8 @@ int openMacvtapTap(const char *ifname,
>                      int vnet_hdr,
>                      const unsigned char *vmuuid,
>                      virVirtualPortProfileParamsPtr virtPortProfile,
> -                   char **res_ifname);
> +                   char **res_ifname,
> +                   enum virVMOperationType vmop);
> 
>   void delMacvtap(const char *ifname,
>                   const unsigned char *macaddress,
> @@ -86,13 +100,16 @@ int vpAssociatePortProfileId(const char
>                                const unsigned char *macvtap_macaddr,
>                                const char *linkdev,
>                                const virVirtualPortProfileParamsPtr
> virtPort,
> -                             const unsigned char *vmuuid);
> +                             const unsigned char *vmuuid,
> +                             enum virVMOperationType vmOp);
> 
>   int vpDisassociatePortProfileId(const char *macvtap_ifname,
>                                   const unsigned char *macvtap_macaddr,
>                                   const char *linkdev,
> -                                const virVirtualPortProfileParamsPtr
> virtPort);
> +                                const virVirtualPortProfileParamsPtr
> virtPort,
> +                                enum virVMOperationType vmOp);
> 
>   VIR_ENUM_DECL(virVirtualPort)
> +VIR_ENUM_DECL(virVMOperation)
> 
>   #endif /* __UTIL_MACVTAP_H__ */
> Index: libvirt-acl/src/libvirt_macvtap.syms
> ===================================================================
> --- libvirt-acl.orig/src/libvirt_macvtap.syms
> +++ libvirt-acl/src/libvirt_macvtap.syms
> @@ -3,3 +3,7 @@
>   # macvtap.h
>   openMacvtapTap;
>   delMacvtap;
> +vpAssociatePortProfileId;
> +vpDisassociatePortProfileId;
> +virVMOperationTypeToString;
> +virVMOperationTypeFromString;
> 
> 




More information about the libvir-list mailing list