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; +} + +/* + * 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