This patch moves backend setup code from qemudDomainAttachNetDevice and qemudDomainDetachNetDevice into separate functions. While the intent is to allow the new functions to be called separately without affecting VM NIC devices, this is arguably a worthwhile refactoring on its own. Signed-off-by: Ed Swierk <eswierk@xxxxxxxxxxxxxxxxxx> --- Move the code that creates and destroys the network backend and connects it to qemu from the code that creates the virtual NIC. Index: libvirt-0.7.7/src/qemu/qemu_driver.c =================================================================== --- libvirt-0.7.7.orig/src/qemu/qemu_driver.c +++ libvirt-0.7.7/src/qemu/qemu_driver.c @@ -141,6 +141,16 @@ static int qemuDetectVcpuPIDs(struct qem static int qemuUpdateActivePciHostdevs(struct qemud_driver *driver, virDomainDefPtr def); +static int qemudDomainConnectNetBackend(virConnectPtr conn, + struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainNetDefPtr net, + unsigned long long qemuCmdFlags); + +static int qemudDomainDisconnectNetBackend(struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainNetDefPtr net); + static struct qemud_driver *qemu_driver = NULL; @@ -6231,20 +6241,17 @@ error: } -/* XXX conn required for network -> bridge resolution */ -static int qemudDomainAttachNetDevice(virConnectPtr conn, - struct qemud_driver *driver, - virDomainObjPtr vm, - virDomainNetDefPtr net, - unsigned long long qemuCmdFlags) +static int qemudDomainConnectNetBackend(virConnectPtr conn, + struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainNetDefPtr net, + unsigned long long qemuCmdFlags) { qemuDomainObjPrivatePtr priv = vm->privateData; char *tapfd_name = NULL; int tapfd = -1; - char *nicstr = NULL; char *netstr = NULL; int ret = -1; - virDomainDevicePCIAddress guestAddr; int vlan; if (!(qemuCmdFlags & QEMUD_CMD_FLAG_HOST_NET_ADD)) { @@ -6253,36 +6260,84 @@ static int qemudDomainAttachNetDevice(vi return -1; } + if (priv->monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) { + qemuReportError(VIR_ERR_NO_SUPPORT, + _("network device type '%s' cannot be attached: " + "qemu is not using a unix socket monitor"), + virDomainNetTypeToString(net->type)); + return -1; + } + + if ((vlan = qemuDomainNetVLAN(net)) < 0) { + qemuReportError(VIR_ERR_NO_SUPPORT, "%s", + _("Unable to connect network backend without vlan")); + goto out; + } + if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE || net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { - if (priv->monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) { - qemuReportError(VIR_ERR_NO_SUPPORT, - _("network device type '%s' cannot be attached: " - "qemu is not using a unix socket monitor"), - virDomainNetTypeToString(net->type)); - return -1; - } - - if ((tapfd = qemudNetworkIfaceConnect(conn, driver, net, qemuCmdFlags)) < 0) - return -1; + tapfd = qemudNetworkIfaceConnect(conn, driver, net, qemuCmdFlags); } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) { - if (priv->monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) { - qemuReportError(VIR_ERR_NO_SUPPORT, - _("network device type '%s' cannot be attached: " - "qemu is not using a unix socket monitor"), - virDomainNetTypeToString(net->type)); - return -1; - } + tapfd = qemudPhysIfaceConnect(conn, driver, net, + net->data.direct.linkdev, + net->data.direct.mode, + qemuCmdFlags); + } + if (tapfd < 0) + return -1; - if ((tapfd = qemudPhysIfaceConnect(conn, driver, net, - net->data.direct.linkdev, - net->data.direct.mode, - qemuCmdFlags)) < 0) - return -1; + if (virAsprintf(&tapfd_name, "fd-%s", net->info.alias) < 0) { + virReportOOMError(); + close(tapfd); + return -1; + } + + if (!(netstr = qemuBuildHostNetStr(net, ' ', + vlan, tapfd_name))) { + VIR_FREE(tapfd_name); + close(tapfd); + return -1; + } + + qemuDomainObjEnterMonitorWithDriver(driver, vm); + + if (qemuMonitorSendFileHandle(priv->mon, tapfd_name, tapfd) < 0) + goto out; + + if (qemuMonitorAddHostNetwork(priv->mon, netstr) < 0) { + if (qemuMonitorCloseFileHandle(priv->mon, tapfd_name) < 0) + VIR_WARN(_("Failed to close tapfd with '%s'"), tapfd_name); + goto out; } - if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets+1) < 0) - goto no_memory; + ret = 0; + +out: + qemuDomainObjExitMonitorWithDriver(driver, vm); + VIR_FREE(netstr); + VIR_FREE(tapfd_name); + close(tapfd); + return ret; +} + + +/* XXX conn required for network -> bridge resolution */ +static int qemudDomainAttachNetDevice(virConnectPtr conn, + struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainNetDefPtr net, + unsigned long long qemuCmdFlags) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + char *nicstr = NULL; + int ret = -1; + virDomainDevicePCIAddress guestAddr; + int vlan; + + if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets+1) < 0) { + virReportOOMError(); + return -1; + } if ((qemuCmdFlags & QEMUD_CMD_FLAG_NET_NAME) || (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) { @@ -6294,40 +6349,16 @@ static int qemudDomainAttachNetDevice(vi qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0) goto cleanup; - vlan = qemuDomainNetVLAN(net); - - if (vlan < 0) { + if ((vlan = qemuDomainNetVLAN(net)) < 0) { qemuReportError(VIR_ERR_NO_SUPPORT, "%s", _("Unable to attach network devices without vlan")); goto cleanup; } - if (tapfd != -1) { - if (virAsprintf(&tapfd_name, "fd-%s", net->info.alias) < 0) - goto no_memory; - - qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (qemuMonitorSendFileHandle(priv->mon, tapfd_name, tapfd) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - goto cleanup; - } - qemuDomainObjExitMonitorWithDriver(driver, vm); - } - - if (!(netstr = qemuBuildHostNetStr(net, ' ', - vlan, tapfd_name))) - goto try_tapfd_close; - - qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (qemuMonitorAddHostNetwork(priv->mon, netstr) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - goto try_tapfd_close; + if (qemudDomainConnectNetBackend(conn, driver, vm, net, qemuCmdFlags) < 0) { + VIR_WARN0(_("Failed to connect network backend")); + goto cleanup; } - qemuDomainObjExitMonitorWithDriver(driver, vm); - - if (tapfd != -1) - close(tapfd); - tapfd = -1; if (!(nicstr = qemuBuildNicStr(net, NULL, vlan))) goto try_remove; @@ -6342,9 +6373,13 @@ static int qemudDomainAttachNetDevice(vi memcpy(&net->info.addr.pci, &guestAddr, sizeof(guestAddr)); qemuDomainObjExitMonitorWithDriver(driver, vm); + vm->def->nets[vm->def->nnets++] = net; ret = 0; + goto cleanup; - vm->def->nets[vm->def->nnets++] = net; +try_remove: + if (qemudDomainDisconnectNetBackend(driver, vm, net) < 0) + VIR_WARN0("Unable to disconnect network backend"); cleanup: if ((ret != 0) && @@ -6352,44 +6387,8 @@ cleanup: (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) && qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &net->info) < 0) VIR_WARN0("Unable to release PCI address on NIC"); - VIR_FREE(nicstr); - VIR_FREE(netstr); - VIR_FREE(tapfd_name); - if (tapfd != -1) - close(tapfd); - return ret; - -try_remove: - if (vlan < 0) { - VIR_WARN0(_("Unable to remove network backend")); - } else { - char *hostnet_name; - if (virAsprintf(&hostnet_name, "host%s", net->info.alias) < 0) - goto no_memory; - qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) - VIR_WARN(_("Failed to remove network backend for vlan %d, net %s"), - vlan, hostnet_name); - qemuDomainObjExitMonitorWithDriver(driver, vm); - VIR_FREE(hostnet_name); - } - goto cleanup; - -try_tapfd_close: - if (tapfd_name) { - qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (qemuMonitorCloseFileHandle(priv->mon, tapfd_name) < 0) - VIR_WARN(_("Failed to close tapfd with '%s'"), tapfd_name); - qemuDomainObjExitMonitorWithDriver(driver, vm); - } - - goto cleanup; - -no_memory: - virReportOOMError(); - goto cleanup; } @@ -6887,18 +6886,50 @@ cleanup: return ret; } -static int -qemudDomainDetachNetDevice(struct qemud_driver *driver, - virDomainObjPtr vm, - virDomainDeviceDefPtr dev, - unsigned long long qemuCmdFlags) +static int qemudDomainDisconnectNetBackend(struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainNetDefPtr detach) { - int i, ret = -1; - virDomainNetDefPtr detach = NULL; qemuDomainObjPrivatePtr priv = vm->privateData; int vlan; char *hostnet_name = NULL; + if ((vlan = qemuDomainNetVLAN(detach)) < 0) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("unable to determine original VLAN")); + return -1; + } + + if (virAsprintf(&hostnet_name, "host%s", detach->info.alias) < 0) { + virReportOOMError(); + return -1; + } + + qemuDomainObjEnterMonitorWithDriver(driver, vm); + if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) + VIR_WARN0("Failed to remove host network"); + qemuDomainObjExitMonitorWithDriver(driver, vm); + +#if WITH_MACVTAP + if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT) { + if (detach->ifname) + delMacvtap(detach->ifname); + } +#endif + + VIR_FREE(hostnet_name); + return 0; +} + +static int qemudDomainDetachNetDevice(struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev, + unsigned long long qemuCmdFlags) +{ + int i; + virDomainNetDefPtr detach = NULL; + qemuDomainObjPrivatePtr priv = vm->privateData; + for (i = 0 ; i < vm->def->nnets ; i++) { virDomainNetDefPtr net = vm->def->nets[i]; @@ -6914,53 +6945,33 @@ qemudDomainDetachNetDevice(struct qemud_ dev->data.net->mac[0], dev->data.net->mac[1], dev->data.net->mac[2], dev->data.net->mac[3], dev->data.net->mac[4], dev->data.net->mac[5]); - goto cleanup; + return -1; } if (!virDomainDeviceAddressIsValid(&detach->info, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("device cannot be detached without a PCI address")); - goto cleanup; - } - - if ((vlan = qemuDomainNetVLAN(detach)) < 0) { - qemuReportError(VIR_ERR_OPERATION_FAILED, - "%s", _("unable to determine original VLAN")); - goto cleanup; - } - - if (virAsprintf(&hostnet_name, "host%s", detach->info.alias) < 0) { - virReportOOMError(); - goto cleanup; + return -1; } qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { - qemuDomainObjExitMonitor(vm); - goto cleanup; + qemuDomainObjExitMonitorWithDriver(driver, vm); + return -1; } } else { if (qemuMonitorRemovePCIDevice(priv->mon, &detach->info.addr.pci) < 0) { qemuDomainObjExitMonitorWithDriver(driver, vm); - goto cleanup; + return -1; } } - - if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - goto cleanup; - } qemuDomainObjExitMonitorWithDriver(driver, vm); -#if WITH_MACVTAP - if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT) { - if (detach->ifname) - delMacvtap(detach->ifname); - } -#endif + if (qemudDomainDisconnectNetBackend(driver, vm, detach) < 0) + VIR_WARN0("Failed to disconnect network backend"); if ((driver->macFilter) && (detach->ifname != NULL)) { if ((errno = networkDisallowMacOnPort(driver, @@ -6987,11 +6998,7 @@ qemudDomainDetachNetDevice(struct qemud_ } virDomainNetDefFree(detach); - ret = 0; - -cleanup: - VIR_FREE(hostnet_name); - return ret; + return 0; } static int qemudDomainDetachHostPciDevice(struct qemud_driver *driver, -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list