Beispiel #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;
}
Beispiel #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;
}
Beispiel #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;
}
Beispiel #4
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;
}
Beispiel #5
0
/* 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;
}
Beispiel #6
0
static int
umlConnectTapDevice(virConnectPtr conn,
                    virDomainNetDefPtr net,
                    const char *bridge)
{
    brControl *brctl = NULL;
    int template_ifname = 0;
    int err;
    unsigned char tapmac[VIR_MAC_BUFLEN];

    if ((err = brInit(&brctl))) {
        virReportSystemError(err, "%s",
                             _("cannot initialize bridge support"));
        goto error;
    }

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

    memcpy(tapmac, net->mac, VIR_MAC_BUFLEN);
    tapmac[0] = 0xFE; /* Discourage bridge from using TAP dev MAC */
    if ((err = brAddTap(brctl,
                        bridge,
                        &net->ifname,
                        tapmac,
                        0,
                        true,
                        NULL))) {
        if (err == ENOTSUP) {
            /* In this particular case, give a better diagnostic. */
            umlReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to add tap interface to bridge. "
                             "%s is not a bridge device"), bridge);
        } else if (err == ENOENT) {
            virReportSystemError(err, "%s",
                    _("Failed to add tap interface to bridge. Your kernel "
                      "is missing the 'tun' module or CONFIG_TUN, or you need "
                      "to add the /dev/net/tun device node."));
        } else if (template_ifname) {
            virReportSystemError(err,
                                 _("Failed to add tap interface to bridge '%s'"),
                                 bridge);
        } else {
            virReportSystemError(err,
                                 _("Failed to add tap interface '%s' to bridge '%s'"),
                                 net->ifname, bridge);
        }
        if (template_ifname)
            VIR_FREE(net->ifname);
        goto error;
    }

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

    brShutdown(brctl);

    return 0;

no_memory:
    virReportOOMError();
error:
    brShutdown(brctl);
    return -1;
}