/** * 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; }
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); const char *linkdev = virDomainNetGetActualDirectDev(net); unsigned int macvlan_create_flags = VIR_NETDEV_MACVLAN_CREATE_IFUP; /* 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, linkdev, virDomainNetGetActualDirectMode(net), false, def->uuid, prof, &res_ifname, VIR_NETDEV_VPORT_PROFILE_OP_CREATE, cfg->stateDir, macvlan_create_flags) < 0) goto cleanup; ret = res_ifname; cleanup: virObjectUnref(cfg); return ret; }
/** * qemuInterfaceDirectConnect: * @def: the definition of the VM (needed by 802.1Qbh and audit) * @driver: pointer to the driver instance * @net: pointer to the VM's interface description with direct device type * @tapfd: array of file descriptor return value for the new device * @tapfdSize: number of file descriptors in @tapfd * @vmop: VM operation type * * Returns 0 on success or -1 in case of error. */ int qemuInterfaceDirectConnect(virDomainDefPtr def, virQEMUDriverPtr driver, virDomainNetDefPtr net, int *tapfd, size_t tapfdSize, virNetDevVPortProfileOp vmop) { int ret = -1; char *res_ifname = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); unsigned int macvlan_create_flags = VIR_NETDEV_MACVLAN_CREATE_WITH_TAP; if (net->model && STREQ(net->model, "virtio")) macvlan_create_flags |= VIR_NETDEV_MACVLAN_VNET_HDR; if (virNetDevMacVLanCreateWithVPortProfile(net->ifname, &net->mac, virDomainNetGetActualDirectDev(net), virDomainNetGetActualDirectMode(net), virDomainNetGetActualVlan(net), def->uuid, virDomainNetGetActualVirtPortProfile(net), &res_ifname, vmop, cfg->stateDir, tapfd, tapfdSize, macvlan_create_flags) < 0) goto cleanup; virDomainAuditNetDevice(def, net, res_ifname, true); VIR_FREE(net->ifname); net->ifname = res_ifname; ret = 0; cleanup: if (ret < 0) { while (tapfdSize--) VIR_FORCE_CLOSE(tapfd[tapfdSize]); } virObjectUnref(cfg); 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; }