[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