int qemuConnectCgroup(virQEMUDriverPtr driver, virDomainObjPtr vm) { virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); qemuDomainObjPrivatePtr priv = vm->privateData; int ret = -1; if (!virQEMUDriverIsPrivileged(driver)) goto done; if (!virCgroupAvailable()) goto done; virCgroupFree(&priv->cgroup); if (virCgroupNewDetectMachine(vm->def->name, "qemu", vm->pid, cfg->cgroupControllers, &priv->cgroup) < 0) goto cleanup; qemuRestoreCgroupState(vm); done: ret = 0; cleanup: virObjectUnref(cfg); return ret; }
static int qemuInitCgroup(virDomainObjPtr vm, size_t nnicindexes, int *nicindexes) { int ret = -1; qemuDomainObjPrivatePtr priv = vm->privateData; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(priv->driver); if (!virQEMUDriverIsPrivileged(priv->driver)) goto done; if (!virCgroupAvailable()) goto done; virCgroupFree(&priv->cgroup); if (!vm->def->resource) { virDomainResourceDefPtr res; if (VIR_ALLOC(res) < 0) goto cleanup; if (VIR_STRDUP(res->partition, "/machine") < 0) { VIR_FREE(res); goto cleanup; } vm->def->resource = res; } if (vm->def->resource->partition[0] != '/') { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Resource partition '%s' must start with '/'"), vm->def->resource->partition); goto cleanup; } if (virCgroupNewMachine(priv->machineName, "qemu", vm->def->uuid, NULL, vm->pid, false, nnicindexes, nicindexes, vm->def->resource->partition, cfg->cgroupControllers, &priv->cgroup) < 0) { if (virCgroupNewIgnoreError()) goto done; goto cleanup; } done: ret = 0; cleanup: virObjectUnref(cfg); return ret; }
int qemuRemoveCgroup(virQEMUDriverPtr driver, virDomainObjPtr vm) { qemuDomainObjPrivatePtr priv = vm->privateData; if (priv->cgroup == NULL) return 0; /* Not supported, so claim success */ if (virCgroupTerminateMachine(vm->def->name, "qemu", virQEMUDriverIsPrivileged(driver)) < 0) { if (!virCgroupNewIgnoreError()) VIR_DEBUG("Failed to terminate cgroup for %s", vm->def->name); } return virCgroupRemove(priv->cgroup); }
/* qemuInterfaceBridgeConnect: * @def: the definition of the VM * @driver: qemu driver data * @net: pointer to the VM's interface description * @tapfd: array of file descriptor return value for the new device * @tapfdsize: number of file descriptors in @tapfd * * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_NETWORK or * VIR_DOMAIN_NET_TYPE_BRIDGE (i.e. if the connection is made with a tap * device connecting to a bridge device) */ int qemuInterfaceBridgeConnect(virDomainDefPtr def, virQEMUDriverPtr driver, virDomainNetDefPtr net, int *tapfd, size_t *tapfdSize) { const char *brname; int ret = -1; unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP; bool template_ifname = false; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); const char *tunpath = "/dev/net/tun"; if (net->backend.tap) { tunpath = net->backend.tap; if (!(virQEMUDriverIsPrivileged(driver))) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("cannot use custom tap device in session mode")); goto cleanup; } } if (!(brname = virDomainNetGetActualBridgeName(net))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing bridge name")); goto cleanup; } if (!net->ifname || STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) || strchr(net->ifname, '%')) { VIR_FREE(net->ifname); if (VIR_STRDUP(net->ifname, VIR_NET_GENERATED_PREFIX "%d") < 0) goto cleanup; /* avoid exposing vnet%d in getXMLDesc or error outputs */ template_ifname = true; } if (net->model && STREQ(net->model, "virtio")) tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR; if (virQEMUDriverIsPrivileged(driver)) { if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac, def->uuid, tunpath, tapfd, *tapfdSize, virDomainNetGetActualVirtPortProfile(net), virDomainNetGetActualVlan(net), tap_create_flags) < 0) { virDomainAuditNetDevice(def, net, tunpath, false); goto cleanup; } if (virDomainNetGetActualBridgeMACTableManager(net) == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) { /* libvirt is managing the FDB of the bridge this device * is attaching to, so we need to turn off learning and * unicast_flood on the device to prevent the kernel from * adding any FDB entries for it. We will add add an fdb * entry ourselves (during qemuInterfaceStartDevices(), * using the MAC address from the interface config. */ if (virNetDevBridgePortSetLearning(brname, net->ifname, false) < 0) goto cleanup; if (virNetDevBridgePortSetUnicastFlood(brname, net->ifname, false) < 0) goto cleanup; } } else { if (qemuCreateInBridgePortWithHelper(cfg, brname, &net->ifname, tapfd, tap_create_flags) < 0) { virDomainAuditNetDevice(def, net, tunpath, false); goto cleanup; } /* qemuCreateInBridgePortWithHelper can only create a single FD */ if (*tapfdSize > 1) { VIR_WARN("Ignoring multiqueue network request"); *tapfdSize = 1; } } virDomainAuditNetDevice(def, net, tunpath, true); if (cfg->macFilter && ebtablesAddForwardAllowIn(driver->ebtables, net->ifname, &net->mac) < 0) goto cleanup; if (net->filter && virDomainConfNWFilterInstantiate(def->uuid, net) < 0) { goto cleanup; } ret = 0; cleanup: if (ret < 0) { size_t i; for (i = 0; i < *tapfdSize && tapfd[i] >= 0; i++) VIR_FORCE_CLOSE(tapfd[i]); if (template_ifname) VIR_FREE(net->ifname); } virObjectUnref(cfg); return ret; }
/* qemuInterfaceEthernetConnect: * @def: the definition of the VM * @driver: qemu driver data * @net: pointer to the VM's interface description * @tapfd: array of file descriptor return value for the new device * @tapfdsize: number of file descriptors in @tapfd * * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_ETHERNET * (i.e. if the connection is made with a tap device) */ int qemuInterfaceEthernetConnect(virDomainDefPtr def, virQEMUDriverPtr driver, virDomainNetDefPtr net, int *tapfd, size_t tapfdSize) { virMacAddr tapmac; int ret = -1; unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP; bool template_ifname = false; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); const char *tunpath = "/dev/net/tun"; if (net->backend.tap) { tunpath = net->backend.tap; if (!virQEMUDriverIsPrivileged(driver)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("cannot use custom tap device in session mode")); goto cleanup; } } if (!net->ifname || STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) || strchr(net->ifname, '%')) { VIR_FREE(net->ifname); if (VIR_STRDUP(net->ifname, VIR_NET_GENERATED_PREFIX "%d") < 0) goto cleanup; /* avoid exposing vnet%d in getXMLDesc or error outputs */ template_ifname = true; } if (net->model && STREQ(net->model, "virtio")) tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR; if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize, tap_create_flags) < 0) { virDomainAuditNetDevice(def, net, tunpath, false); goto cleanup; } virDomainAuditNetDevice(def, net, tunpath, true); virMacAddrSet(&tapmac, &net->mac); tapmac.addr[0] = 0xFE; if (virNetDevSetMAC(net->ifname, &tapmac) < 0) goto cleanup; if (virNetDevSetOnline(net->ifname, true) < 0) goto cleanup; if (net->script && virNetDevRunEthernetScript(net->ifname, net->script) < 0) goto cleanup; if (cfg->macFilter && ebtablesAddForwardAllowIn(driver->ebtables, net->ifname, &net->mac) < 0) goto cleanup; if (net->filter && virDomainConfNWFilterInstantiate(def->uuid, net) < 0) { goto cleanup; } ret = 0; cleanup: if (ret < 0) { size_t i; for (i = 0; i < tapfdSize && tapfd[i] >= 0; i++) VIR_FORCE_CLOSE(tapfd[i]); if (template_ifname) VIR_FREE(net->ifname); } virObjectUnref(cfg); return ret; }