/** * qemuInterfaceStopDevice: * @net: net device to stop * * Based upon the type of device provided, perform the appropriate * work to deactivate the device so that packets aren't forwarded to * it from the rest of the network. */ int qemuInterfaceStopDevice(virDomainNetDefPtr net) { int ret = -1; virDomainNetType actualType = virDomainNetGetActualType(net); switch (actualType) { case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_NETWORK: if (virDomainNetGetActualBridgeMACTableManager(net) == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) { /* remove the FDB entries that were added during * qemuInterfaceStartDevices() */ if (virNetDevBridgeFDBDel(&net->mac, net->ifname, VIR_NETDEVBRIDGE_FDB_FLAG_MASTER | VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0) goto cleanup; } break; case VIR_DOMAIN_NET_TYPE_DIRECT: { const char *physdev = virDomainNetGetActualDirectDev(net); /* macvtap interfaces need to be marked !IFF_UP (ie "down") to * prevent any host-generated traffic sent from this interface * from putting bad info into the arp caches of other machines * on this network. */ if (virNetDevSetOnline(net->ifname, false) < 0) goto cleanup; /* also mark the physdev down for passthrough macvtap, as the * physdev has the same MAC address as the macvtap device. */ if (virDomainNetGetActualDirectMode(net) == VIR_NETDEV_MACVLAN_MODE_PASSTHRU && physdev && virNetDevSetOnline(physdev, false) < 0) goto cleanup; break; } case VIR_DOMAIN_NET_TYPE_ETHERNET: case VIR_DOMAIN_NET_TYPE_USER: case VIR_DOMAIN_NET_TYPE_VHOSTUSER: case VIR_DOMAIN_NET_TYPE_SERVER: case VIR_DOMAIN_NET_TYPE_CLIENT: case VIR_DOMAIN_NET_TYPE_MCAST: case VIR_DOMAIN_NET_TYPE_UDP: case VIR_DOMAIN_NET_TYPE_INTERNAL: case VIR_DOMAIN_NET_TYPE_HOSTDEV: case VIR_DOMAIN_NET_TYPE_LAST: /* these types all require no action */ break; } ret = 0; cleanup: return ret; }
/** * lxcContainerRenameAndEnableInterfaces: * @nveths: number of interfaces * @veths: interface names * * This function will rename the interfaces to ethN * with id ascending order from zero and enable the * renamed interfaces for this container. * * Returns 0 on success or nonzero in case of error */ static int lxcContainerRenameAndEnableInterfaces(unsigned int nveths, char **veths) { int rc = 0; unsigned int i; char *newname = NULL; for (i = 0 ; i < nveths ; i++) { if (virAsprintf(&newname, "eth%d", i) < 0) { virReportOOMError(); rc = -1; goto error_out; } VIR_DEBUG("Renaming %s to %s", veths[i], newname); rc = virNetDevSetName(veths[i], newname); if (rc < 0) goto error_out; VIR_DEBUG("Enabling %s", newname); rc = virNetDevSetOnline(newname, true); if (rc < 0) goto error_out; VIR_FREE(newname); } /* enable lo device only if there were other net devices */ if (veths) rc = virNetDevSetOnline("lo", true); error_out: VIR_FREE(newname); return rc; }
char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn, virDomainDefPtr vm, virDomainNetDefPtr net, const char *brname) { char *ret = NULL; char *parentVeth; char *containerVeth = NULL; virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(net); VIR_DEBUG("calling vethCreate()"); parentVeth = net->ifname; if (virNetDevVethCreate(&parentVeth, &containerVeth) < 0) goto cleanup; VIR_DEBUG("parentVeth: %s, containerVeth: %s", parentVeth, containerVeth); if (net->ifname == NULL) net->ifname = parentVeth; if (virNetDevSetMAC(containerVeth, &net->mac) < 0) goto cleanup; if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) { if (virNetDevOpenvswitchAddPort(brname, parentVeth, &net->mac, vm->uuid, vport, virDomainNetGetActualVlan(net)) < 0) goto cleanup; } else { if (virNetDevBridgeAddPort(brname, parentVeth) < 0) goto cleanup; } if (virNetDevSetOnline(parentVeth, true) < 0) goto cleanup; if (virNetDevBandwidthSet(net->ifname, virDomainNetGetActualBandwidth(net), false) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot set bandwidth limits on %s"), net->ifname); goto cleanup; } if (net->filter && virDomainConfNWFilterInstantiate(conn, vm->uuid, net) < 0) goto cleanup; ret = containerVeth; cleanup: return ret; }
/** * qemuInterfaceStartDevice: * @net: net device to start * * Based upon the type of device provided, perform the appropriate * work to completely activate the device and make it reachable from * the rest of the network. */ int qemuInterfaceStartDevice(virDomainNetDefPtr net) { int ret = -1; virDomainNetType actualType = virDomainNetGetActualType(net); switch (actualType) { case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_NETWORK: 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 have turned off learning and * unicast_flood on the device to prevent the kernel from * adding any FDB entries for it. This means we need to * add an fdb entry ourselves, using the MAC address from * the interface config. */ if (virNetDevBridgeFDBAdd(&net->mac, net->ifname, VIR_NETDEVBRIDGE_FDB_FLAG_MASTER | VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0) goto cleanup; } break; case VIR_DOMAIN_NET_TYPE_DIRECT: { const char *physdev = virDomainNetGetActualDirectDev(net); bool isOnline = true; /* set the physdev online if necessary. It may already be up, * in which case we shouldn't re-up it just in case that causes * some sort of "blip" in the physdev's status. */ if (physdev && virNetDevGetOnline(physdev, &isOnline) < 0) goto cleanup; if (!isOnline && virNetDevSetOnline(physdev, true) < 0) goto cleanup; /* macvtap devices share their MAC address with the guest * domain, and if they are set online prior to the domain CPUs * being started, the host may send out traffic from this * device that could confuse other entities on the network (in * particular, if this new domain is the destination of a * migration, and the source domain is still running, another * host may mistakenly direct traffic for the guest to the * destination domain rather than source domain). To prevent * this, we create the macvtap device with IFF_UP false * (i.e. "offline") then wait to bring it online until just as * we are starting the domain CPUs. */ if (virNetDevSetOnline(net->ifname, true) < 0) goto cleanup; break; } case VIR_DOMAIN_NET_TYPE_ETHERNET: if (virNetDevIPInfoAddToDev(net->ifname, &net->hostIP) < 0) goto cleanup; break; case VIR_DOMAIN_NET_TYPE_USER: case VIR_DOMAIN_NET_TYPE_VHOSTUSER: case VIR_DOMAIN_NET_TYPE_SERVER: case VIR_DOMAIN_NET_TYPE_CLIENT: case VIR_DOMAIN_NET_TYPE_MCAST: case VIR_DOMAIN_NET_TYPE_UDP: case VIR_DOMAIN_NET_TYPE_INTERNAL: case VIR_DOMAIN_NET_TYPE_HOSTDEV: case VIR_DOMAIN_NET_TYPE_LAST: /* these types all require no action */ break; } ret = 0; cleanup: 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; }
static int bhyveBuildNetArgStr(const virDomainDef *def, virDomainNetDefPtr net, virCommandPtr cmd, bool dryRun) { char macaddr[VIR_MAC_STRING_BUFLEN]; char *realifname = NULL; char *brname = NULL; int actualType = virDomainNetGetActualType(net); if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) { if (VIR_STRDUP(brname, virDomainNetGetActualBridgeName(net)) < 0) return -1; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Network type %d is not supported"), virDomainNetGetActualType(net)); return -1; } 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) { VIR_FREE(brname); return -1; } } if (!dryRun) { if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac, def->uuid, NULL, NULL, 0, virDomainNetGetActualVirtPortProfile(net), virDomainNetGetActualVlan(net), VIR_NETDEV_TAP_CREATE_IFUP | VIR_NETDEV_TAP_CREATE_PERSIST) < 0) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } realifname = virNetDevTapGetRealDeviceName(net->ifname); if (realifname == NULL) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } VIR_DEBUG("%s -> %s", net->ifname, realifname); /* hack on top of other hack: we need to set * interface to 'UP' again after re-opening to find its * name */ if (virNetDevSetOnline(net->ifname, true) != 0) { VIR_FREE(realifname); VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } } else { if (VIR_STRDUP(realifname, "tap0") < 0) return -1; } virCommandAddArg(cmd, "-s"); virCommandAddArgFormat(cmd, "%d:0,virtio-net,%s,mac=%s", net->info.addr.pci.slot, realifname, virMacAddrFormat(&net->mac, macaddr)); VIR_FREE(realifname); return 0; }
static int bhyveBuildNetArgStr(const virDomainDef *def, virCommandPtr cmd) { virDomainNetDefPtr net = NULL; char *brname = NULL; char *realifname = NULL; int *tapfd = NULL; if (def->nnets != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("domain should have one and only one net defined")); return -1; } net = def->nets[0]; if (net) { int actualType = virDomainNetGetActualType(net); if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) { if (VIR_STRDUP(brname, virDomainNetGetActualBridgeName(net)) < 0) return -1; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Network type %d is not supported"), virDomainNetGetActualType(net)); return -1; } 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) { VIR_FREE(brname); return -1; } } if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac, def->uuid, tapfd, 1, virDomainNetGetActualVirtPortProfile(net), virDomainNetGetActualVlan(net), VIR_NETDEV_TAP_CREATE_IFUP | VIR_NETDEV_TAP_CREATE_PERSIST) < 0) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } } realifname = virBhyveTapGetRealDeviceName(net->ifname); if (realifname == NULL) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } VIR_DEBUG("%s -> %s", net->ifname, realifname); /* hack on top of other hack: we need to set * interface to 'UP' again after re-opening to find its * name */ if (virNetDevSetOnline(net->ifname, true) != 0) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } virCommandAddArgList(cmd, "-s", "0:0,hostbridge", NULL); virCommandAddArg(cmd, "-s"); virCommandAddArgFormat(cmd, "1:0,virtio-net,%s", realifname); return 0; }
/** * virLXCProcessCleanup: * @driver: pointer to driver structure * @vm: pointer to VM to clean up * @reason: reason for switching the VM to shutoff state * * Cleanout resources associated with the now dead VM * */ static void virLXCProcessCleanup(virLXCDriverPtr driver, virDomainObjPtr vm, virDomainShutoffReason reason) { virCgroupPtr cgroup; int i; virLXCDomainObjPrivatePtr priv = vm->privateData; virNetDevVPortProfilePtr vport = NULL; VIR_DEBUG("Stopping VM name=%s pid=%d reason=%d", vm->def->name, (int)vm->pid, (int)reason); /* now that we know it's stopped call the hook if present */ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) { char *xml = virDomainDefFormat(vm->def, 0); /* we can't stop the operation even if the script raised an error */ virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name, VIR_HOOK_LXC_OP_STOPPED, VIR_HOOK_SUBOP_END, NULL, xml, NULL); VIR_FREE(xml); } /* Stop autodestroy in case guest is restarted */ virLXCProcessAutoDestroyRemove(driver, vm); if (priv->monitor) { virLXCMonitorClose(priv->monitor); virObjectUnref(priv->monitor); priv->monitor = NULL; } virPidFileDelete(driver->stateDir, vm->def->name); virDomainDeleteConfig(driver->stateDir, NULL, vm); virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason); vm->pid = -1; vm->def->id = -1; driver->nactive--; if (!driver->nactive && driver->inhibitCallback) driver->inhibitCallback(false, driver->inhibitOpaque); virLXCDomainReAttachHostDevices(driver, vm->def); for (i = 0 ; i < vm->def->nnets ; i++) { virDomainNetDefPtr iface = vm->def->nets[i]; vport = virDomainNetGetActualVirtPortProfile(iface); if (iface->ifname) { ignore_value(virNetDevSetOnline(iface->ifname, false)); if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) ignore_value(virNetDevOpenvswitchRemovePort( virDomainNetGetActualBridgeName(iface), iface->ifname)); ignore_value(virNetDevVethDelete(iface->ifname)); } networkReleaseActualDevice(iface); } virDomainConfVMNWFilterTeardown(vm); if (driver->cgroup && virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) == 0) { virCgroupRemove(cgroup); virCgroupFree(&cgroup); } /* now that we know it's stopped call the hook if present */ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) { char *xml = virDomainDefFormat(vm->def, 0); /* we can't stop the operation even if the script raised an error */ virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name, VIR_HOOK_LXC_OP_RELEASE, VIR_HOOK_SUBOP_END, NULL, xml, NULL); VIR_FREE(xml); } if (vm->newDef) { virDomainDefFree(vm->def); vm->def = vm->newDef; vm->def->id = -1; vm->newDef = NULL; } }