char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn, virDomainDefPtr def, virDomainNetDefPtr net) { char *ret = NULL; char *res_ifname = NULL; virLXCDriverPtr driver = conn->privateData; virNetDevBandwidthPtr bw; virNetDevVPortProfilePtr prof; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); /* XXX how todo bandwidth controls ? * Since the 'net-ifname' is about to be moved to a different * namespace & renamed, there will be no host side visible * interface for the container to attach rules to */ bw = virDomainNetGetActualBandwidth(net); if (bw) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Unable to set network bandwidth on direct interfaces")); return NULL; } /* XXX how todo port profiles ? * Although we can do the association during container * startup, at shutdown we are unable to disassociate * because the macvlan device was moved to the container * and automagically dies when the container dies. So * we have no dev to perform disassociation with. */ prof = virDomainNetGetActualVirtPortProfile(net); if (prof) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Unable to set port profile on direct interfaces")); return NULL; } if (virNetDevMacVLanCreateWithVPortProfile( net->ifname, &net->mac, virDomainNetGetActualDirectDev(net), virDomainNetGetActualDirectMode(net), false, false, def->uuid, virDomainNetGetActualVirtPortProfile(net), &res_ifname, VIR_NETDEV_VPORT_PROFILE_OP_CREATE, cfg->stateDir, virDomainNetGetActualBandwidth(net)) < 0) goto cleanup; ret = res_ifname; cleanup: virObjectUnref(cfg); return ret; }
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; }
void virDomainClearNetBandwidth(virDomainObjPtr vm) { size_t i; virDomainNetType type; for (i = 0; i < vm->def->nnets; i++) { type = virDomainNetGetActualType(vm->def->nets[i]); if (virDomainNetGetActualBandwidth(vm->def->nets[i]) && virNetDevSupportBandwidth(type)) virNetDevBandwidthClear(vm->def->nets[i]->ifname); } }
/** * virLXCProcessSetupInterfaces: * @conn: pointer to connection * @def: pointer to virtual machine structure * @nveths: number of interfaces * @veths: interface names * * Sets up the container interfaces by creating the veth device pairs and * attaching the parent end to the appropriate bridge. The container end * will moved into the container namespace later after clone has been called. * * Returns 0 on success or -1 in case of error */ static int virLXCProcessSetupInterfaces(virConnectPtr conn, virDomainDefPtr def, size_t *nveths, char ***veths) { int ret = -1; size_t i; size_t niface = 0; virDomainNetDefPtr net; virDomainNetType type; for (i = 0; i < def->nnets; i++) { char *veth = NULL; virNetDevBandwidthPtr actualBandwidth; /* If appropriate, grab a physical device from the configured * network's pool of devices, or resolve bridge device name * to the one defined in the network definition. */ net = def->nets[i]; if (networkAllocateActualDevice(def, net) < 0) goto cleanup; if (VIR_EXPAND_N(*veths, *nveths, 1) < 0) goto cleanup; type = virDomainNetGetActualType(net); switch (type) { case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_BRIDGE: { const char *brname = virDomainNetGetActualBridgeName(net); if (!brname) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("No bridge name specified")); goto cleanup; } if (!(veth = virLXCProcessSetupInterfaceBridged(def, net, brname))) goto cleanup; } break; case VIR_DOMAIN_NET_TYPE_DIRECT: if (!(veth = virLXCProcessSetupInterfaceDirect(conn, def, net))) goto cleanup; break; case VIR_DOMAIN_NET_TYPE_ETHERNET: 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_INTERNAL: case VIR_DOMAIN_NET_TYPE_LAST: case VIR_DOMAIN_NET_TYPE_HOSTDEV: virReportError(VIR_ERR_INTERNAL_ERROR, _("Unsupported network type %s"), virDomainNetTypeToString(type)); goto cleanup; } /* Set bandwidth or warn if requested and not supported. */ actualBandwidth = virDomainNetGetActualBandwidth(net); if (actualBandwidth) { if (virNetDevSupportBandwidth(type)) { if (virNetDevBandwidthSet(net->ifname, actualBandwidth, false) < 0) goto cleanup; } else { VIR_WARN("setting bandwidth on interfaces of " "type '%s' is not implemented yet", virDomainNetTypeToString(type)); } } (*veths)[(*nveths)-1] = veth; if (VIR_STRDUP(def->nets[i]->ifname_guest_actual, veth) < 0) goto cleanup; /* Make sure all net definitions will have a name in the container */ if (!net->ifname_guest) { if (virAsprintf(&net->ifname_guest, "eth%zu", niface) < 0) return -1; niface++; } } ret = 0; cleanup: if (ret < 0) { for (i = 0; i < def->nnets; i++) { virDomainNetDefPtr iface = def->nets[i]; virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(iface); if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) ignore_value(virNetDevOpenvswitchRemovePort( virDomainNetGetActualBridgeName(iface), iface->ifname)); networkReleaseActualDevice(def, iface); } } return ret; }