Пример #1
0
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;
}
Пример #2
0
static int
umlConnectTapDevice(virDomainDefPtr vm,
                    virDomainNetDefPtr net,
                    const char *bridge)
{
    bool template_ifname = false;
    int tapfd = -1;

    if (!net->ifname ||
        STRPREFIX(net->ifname, VIR_NET_GENERATED_TAP_PREFIX) ||
        strchr(net->ifname, '%')) {
        VIR_FREE(net->ifname);
        if (VIR_STRDUP(net->ifname, VIR_NET_GENERATED_TAP_PREFIX "%d") < 0)
            goto error;
        /* avoid exposing vnet%d in getXMLDesc or error outputs */
        template_ifname = true;
    }

    if (virNetDevTapCreateInBridgePort(bridge, &net->ifname, &net->mac,
                                       vm->uuid, net->backend.tap, &tapfd, 1,
                                       virDomainNetGetActualVirtPortProfile(net),
                                       virDomainNetGetActualVlan(net),
                                       NULL, 0, NULL,
                                       VIR_NETDEV_TAP_CREATE_IFUP |
                                       VIR_NETDEV_TAP_CREATE_PERSIST) < 0) {
        if (template_ifname)
            VIR_FREE(net->ifname);
        goto error;
    }

    if (net->filter) {
        if (virDomainConfNWFilterInstantiate(vm->name, vm->uuid, net, false) < 0) {
            if (template_ifname)
                VIR_FREE(net->ifname);
            goto error;
        }
    }

    VIR_FORCE_CLOSE(tapfd);
    return 0;

 error:
    VIR_FORCE_CLOSE(tapfd);
    return -1;
}
Пример #3
0
static int
umlConnectTapDevice(virConnectPtr conn,
                    virDomainDefPtr vm,
                    virDomainNetDefPtr net,
                    const char *bridge)
{
    bool template_ifname = false;

    if (!net->ifname ||
            STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) ||
            strchr(net->ifname, '%')) {
        VIR_FREE(net->ifname);
        if (!(net->ifname = strdup(VIR_NET_GENERATED_PREFIX "%d")))
            goto no_memory;
        /* avoid exposing vnet%d in getXMLDesc or error outputs */
        template_ifname = true;
    }

    if (virNetDevTapCreateInBridgePort(bridge, &net->ifname, &net->mac,
                                       vm->uuid, NULL,
                                       virDomainNetGetActualVirtPortProfile(net),
                                       virDomainNetGetActualVlan(net),
                                       VIR_NETDEV_TAP_CREATE_IFUP |
                                       VIR_NETDEV_TAP_CREATE_PERSIST) < 0) {
        if (template_ifname)
            VIR_FREE(net->ifname);
        goto error;
    }

    if (net->filter) {
        if (virDomainConfNWFilterInstantiate(conn, vm->uuid, net) < 0) {
            if (template_ifname)
                VIR_FREE(net->ifname);
            goto error;
        }
    }

    return 0;

no_memory:
    virReportOOMError();
error:
    return -1;
}
Пример #4
0
/**
 * 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;
}
Пример #5
0
/* 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;
}
Пример #6
0
int
qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev,
                                  const unsigned char *uuid,
                                  char *stateDir)
{
    char *linkdev = NULL;
    virNetDevVlanPtr vlan;
    virNetDevVPortProfilePtr virtPort;
    int ret = -1;
    int vf = -1;
    int vlanid = -1;
    int port_profile_associate = 1;
    int isvf;

    isvf = qemuDomainHostdevIsVirtualFunction(hostdev);
    if (isvf <= 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Interface type hostdev is currently supported on"
                         " SR-IOV Virtual Functions only"));
        return ret;
    }

    if (qemuDomainHostdevNetDevice(hostdev, &linkdev, &vf) < 0)
        return ret;

    vlan = virDomainNetGetActualVlan(hostdev->parent.data.net);
    virtPort = virDomainNetGetActualVirtPortProfile(
                                 hostdev->parent.data.net);
    if (virtPort) {
        if (vlan) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("direct setting of the vlan tag is not allowed "
                             "for hostdev devices using %s mode"),
                           virNetDevVPortTypeToString(virtPort->virtPortType));
            goto cleanup;
        }
        ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf,
                            virtPort, &hostdev->parent.data.net->mac, uuid,
                            port_profile_associate);
    } else {
        /* Set only mac and vlan */
        if (vlan) {
            if (vlan->nTags != 1 || vlan->trunk) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("vlan trunking is not supported "
                                 "by SR-IOV network devices"));
                goto cleanup;
            }
            if (vf == -1) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("vlan can only be set for SR-IOV VFs, but "
                                 "%s is not a VF"), linkdev);
                goto cleanup;
            }
            vlanid = vlan->tag[0];
        } else  if (vf >= 0) {
            vlanid = 0; /* assure any current vlan tag is reset */
        }

        ret = virNetDevReplaceNetConfig(linkdev, vf,
                                        &hostdev->parent.data.net->mac,
                                        vlanid, stateDir);
    }
cleanup:
    VIR_FREE(linkdev);
    return ret;
}
Пример #7
0
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;
}
Пример #8
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;
}