On Fri, Apr 17, 2015 at 04:53:06PM +0800, Chen Fan wrote: > via initialize callback to create bond device. > > Signed-off-by: Chen Fan <chen.fan.fnst@xxxxxxxxxxxxxx> > --- > src/qemu/qemu_agent.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++ > src/qemu/qemu_agent.h | 10 ++++ > src/qemu/qemu_domain.c | 70 ++++++++++++++++++++++++++++ > src/qemu/qemu_domain.h | 7 +++ > src/qemu/qemu_process.c | 4 ++ > 5 files changed, 209 insertions(+) > > diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c > index cee0f8b..b8eba01 100644 > --- a/src/qemu/qemu_agent.c > +++ b/src/qemu/qemu_agent.c > @@ -2169,3 +2169,121 @@ qemuAgentGetInterfaces(qemuAgentPtr mon, > > goto cleanup; > } > + > +static virDomainInterfacePtr > +findInterfaceByMac(virDomainInterfacePtr *info, > + size_t len, > + const char *macstr) > +{ > + size_t i; > + bool found = false; > + > + for (i = 0; i < len; i++) { > + if (info[i]->hwaddr && > + STREQ(info[i]->hwaddr, macstr)) { > + found = true; > + break; > + } > + } > + > + if (found) { > + return info[i]; > + } > + > + return NULL; > +} > + I think PCI addresses are a better way to identify the devices for this purpose. This will mean softmac doesn't break this functionality. See anything wrong with it? > +/* > + * qemuAgentSetInterface: > + */ > +int > +qemuAgentCreateBond(qemuAgentPtr mon, > + virDomainHostdevSubsysPCIPtr pcisrc) > +{ > + int ret = -1; > + virJSONValuePtr cmd = NULL; > + virJSONValuePtr reply = NULL; > + size_t i; > + char macstr[VIR_MAC_STRING_BUFLEN]; > + virDomainInterfacePtr *interfaceInfo = NULL; > + virDomainInterfacePtr interface; > + virJSONValuePtr new_interface = NULL; > + virJSONValuePtr subInterfaces = NULL; > + virJSONValuePtr subInterface = NULL; > + int len; > + > + if (!(pcisrc->nmac || pcisrc->macs)) > + return ret; > + > + len = qemuAgentGetInterfaces(mon, &interfaceInfo); > + if (len < 0) > + return ret; > + > + if (!(new_interface = virJSONValueNewObject())) > + goto cleanup; > + > + if (virJSONValueObjectAppendString(new_interface, "type", "bond") < 0) > + goto cleanup; > + > + if (virJSONValueObjectAppendString(new_interface, "name", "bond0") < 0) > + goto cleanup; > + > + if (virJSONValueObjectAppendString(new_interface, "onboot", "onboot") < 0) > + goto cleanup; > + > + if (!(subInterfaces = virJSONValueNewArray())) > + goto cleanup; > + > + for (i = 0; i < pcisrc->nmac; i++) { > + virMacAddrFormat(&pcisrc->macs[i], macstr); > + interface = findInterfaceByMac(interfaceInfo, len, macstr); > + if (!interface) { > + goto cleanup; > + } > + > + if (!(subInterface = virJSONValueNewObject())) > + goto cleanup; > + > + if (virJSONValueObjectAppendString(subInterface, "name", interface->name) < 0) > + goto cleanup; > + > + if (virJSONValueArrayAppend(subInterfaces, subInterface) < 0) > + goto cleanup; > + > + subInterface = NULL; > + } > + > + if (i && virJSONValueObjectAppend(new_interface, "subInterfaces", subInterfaces) < 0) > + goto cleanup; > + > + cmd = qemuAgentMakeCommand("guest-network-set-interface", > + "a:interface", new_interface, > + NULL); > + > + if (!cmd) > + goto cleanup; > + > + subInterfaces = NULL; > + new_interface = NULL; > + > + if (qemuAgentCommand(mon, cmd, &reply, true, > + VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0) > + goto cleanup; > + > + if (virJSONValueObjectGetNumberInt(reply, "return", &ret) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("malformed return value")); > + } > + > + cleanup: > + virJSONValueFree(subInterfaces); > + virJSONValueFree(subInterface); > + virJSONValueFree(new_interface); > + virJSONValueFree(cmd); > + virJSONValueFree(reply); > + if (interfaceInfo) > + for (i = 0; i < len; i++) > + virDomainInterfaceFree(interfaceInfo[i]); > + VIR_FREE(interfaceInfo); > + return ret; > +} > diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h > index 42414a7..744cb0a 100644 > --- a/src/qemu/qemu_agent.h > +++ b/src/qemu/qemu_agent.h > @@ -97,6 +97,13 @@ struct _qemuAgentCPUInfo { > bool offlinable; /* true if the CPU can be offlined */ > }; > > +typedef struct _qemuAgentInterfaceInfo qemuAgentInterfaceInfo; > +typedef qemuAgentInterfaceInfo *qemuAgentInterfaceInfoPtr; > +struct _qemuAgentInterfaceInfo { > + char *name; > + char *hardware_address; > +}; > + > int qemuAgentGetVCPUs(qemuAgentPtr mon, qemuAgentCPUInfoPtr *info); > int qemuAgentSetVCPUs(qemuAgentPtr mon, qemuAgentCPUInfoPtr cpus, size_t ncpus); > int qemuAgentUpdateCPUInfo(unsigned int nvcpus, > @@ -114,4 +121,7 @@ int qemuAgentSetTime(qemuAgentPtr mon, > int qemuAgentGetInterfaces(qemuAgentPtr mon, > virDomainInterfacePtr **ifaces); > > +int qemuAgentCreateBond(qemuAgentPtr mon, > + virDomainHostdevSubsysPCIPtr pcisrc); > + > #endif /* __QEMU_AGENT_H__ */ > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > index 603360f..584fefb 100644 > --- a/src/qemu/qemu_domain.c > +++ b/src/qemu/qemu_domain.c > @@ -2722,6 +2722,46 @@ qemuDomainCleanupRun(virQEMUDriverPtr driver, > priv->ncleanupCallbacks_max = 0; > } > > +/* > + * The vm must be locked when any of the following init functions is > + * called. > + */ > +int > +qemuDomainInitAdd(virDomainObjPtr vm, > + qemuDomainInitCallback cb) > +{ > + qemuDomainObjPrivatePtr priv = vm->privateData; > + size_t i; > + > + VIR_DEBUG("vm=%s, cb=%p", vm->def->name, cb); > + > + for (i = 0; i < priv->nInitCallbacks; i++) { > + if (priv->initCallbacks[i] == cb) > + return 0; > + } > + > + if (VIR_RESIZE_N(priv->initCallbacks, > + priv->nInitCallbacks_max, > + priv->nInitCallbacks, 1) < 0) > + return -1; > + > + priv->initCallbacks[priv->nInitCallbacks++] = cb; > + return 0; > +} > + > +void > +qemuDomainInitCleanup(virDomainObjPtr vm) > +{ > + qemuDomainObjPrivatePtr priv = vm->privateData; > + > + VIR_DEBUG("vm=%s", vm->def->name); > + > + VIR_FREE(priv->cleanupCallbacks); > + priv->ncleanupCallbacks = 0; > + priv->ncleanupCallbacks_max = 0; > +} > + > + > static void > qemuDomainGetImageIds(virQEMUDriverConfigPtr cfg, > virDomainObjPtr vm, > @@ -3083,3 +3123,33 @@ qemuDomainSupportsBlockJobs(virDomainObjPtr vm, > > return 0; > } > + > +void > +qemuDomainPrepareHostdevInit(virDomainObjPtr vm) > +{ > + qemuDomainObjPrivatePtr priv = vm->privateData; > + virDomainDefPtr def = vm->def; > + int i; > + > + if (!def->nhostdevs) > + return; > + > + if (!qemuDomainAgentAvailable(vm, false)) > + return; > + > + if (!virDomainObjIsActive(vm)) > + return; > + > + for (i = 0; i < def->nhostdevs; i++) { > + virDomainHostdevDefPtr hostdev = def->hostdevs[i]; > + virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci; > + > + if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && > + hostdev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO && > + hostdev->source.subsys.u.pci.device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) { > + qemuDomainObjEnterAgent(vm); > + qemuAgentCreateBond(priv->agent, pcisrc); > + qemuDomainObjExitAgent(vm); > + } > + } > +} > diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h > index 19f4b27..3244ca0 100644 > --- a/src/qemu/qemu_domain.h > +++ b/src/qemu/qemu_domain.h > @@ -403,6 +403,10 @@ void qemuDomainCleanupRemove(virDomainObjPtr vm, > void qemuDomainCleanupRun(virQEMUDriverPtr driver, > virDomainObjPtr vm); > > +int qemuDomainInitAdd(virDomainObjPtr vm, > + qemuDomainInitCallback cb); > +void qemuDomainInitCleanup(virDomainObjPtr vm); > + > extern virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks; > extern virDomainXMLNamespace virQEMUDriverDomainXMLNamespace; > extern virDomainDefParserConfig virQEMUDriverDomainDefParserConfig; > @@ -444,4 +448,7 @@ void qemuDomObjEndAPI(virDomainObjPtr *vm); > int qemuDomainAlignMemorySizes(virDomainDefPtr def); > void qemuDomainMemoryDeviceAlignSize(virDomainMemoryDefPtr mem); > > +void > +qemuDomainPrepareHostdevInit(virDomainObjPtr vm); > + > #endif /* __QEMU_DOMAIN_H__ */ > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c > index fcc0566..0a72aca 100644 > --- a/src/qemu/qemu_process.c > +++ b/src/qemu/qemu_process.c > @@ -4444,6 +4444,9 @@ int qemuProcessStart(virConnectPtr conn, > hostdev_flags) < 0) > goto cleanup; > > + if (qemuDomainInitAdd(vm, qemuDomainPrepareHostdevInit)) > + goto cleanup; > + > VIR_DEBUG("Preparing chr devices"); > if (virDomainChrDefForeach(vm->def, > true, > @@ -5186,6 +5189,7 @@ void qemuProcessStop(virQEMUDriverPtr driver, > VIR_QEMU_PROCESS_KILL_NOCHECK)); > > qemuDomainCleanupRun(driver, vm); > + qemuDomainInitCleanup(vm); > > /* Stop autodestroy in case guest is restarted */ > qemuProcessAutoDestroyRemove(driver, vm); > -- > 1.9.3 > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list