Example #1
0
/**
 * ebtablesRemoveForwardAllowIn:
 * @ctx: pointer to the EB table context
 * @iface: the output interface name
 * @physdev: the physical input device or NULL
 *
 * Remove rules from the EB table context hence forbidding the traffic
 * on the @physdev device to be forwarded to interface @iface. This
 * stops the inbound traffic on a bridge.
 *
 * Returns 0 in case of success or an error code otherwise
 */
int
ebtablesRemoveForwardAllowIn(ebtablesContext *ctx,
                             const char *iface,
                             const virMacAddr *mac)
{
    char macaddr[VIR_MAC_STRING_BUFLEN];

    virMacAddrFormat(mac, macaddr);
    return ebtablesForwardAllowIn(ctx, iface, macaddr, REMOVE);
}
Example #2
0
/*
 * Output only lxc.net.x
 */
int lxctoolsSetNetConfig(lxctoolsConffilePtr conffile, virDomainDefPtr def)
{
    int ret = -1;
    char *mac_str = NULL;
 
    // Remove old net config
    if (lxctoolsConffileRemoveItems(conffile, "lxc.net.") < 0)
        goto cleanup;
    if (lxctoolsConffileRemoveItems(conffile, "lxc.network.") < 0)
        goto cleanup;

    // Insert new net config
    if (lxctoolsConffileAddComment(conffile, "begin: generated network configuration") < 0)
        goto cleanup;
    for (size_t i = 0; i != def->nnets; i++) {
        if (def->nets[i]->type != VIR_DOMAIN_NET_TYPE_BRIDGE) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("only network type bridge is currently supported."));
            goto cleanup;
        }
        if (lxctoolsConffileAddItemEnumerated(conffile, "lxc.net.%zu.type", "veth", i) < 0) {
            VIR_ERROR("Failed to set lxc.net.%zu.type to veth", i);
            goto cleanup;
        }
        if (VIR_ALLOC_N(mac_str, VIR_MAC_STRING_BUFLEN) < 0)
            goto cleanup;
        virMacAddrFormat(&def->nets[i]->mac, mac_str);
        if (lxctoolsConffileAddItemEnumerated(conffile, "lxc.net.%zu.hwaddr", mac_str, i) < 0) {
            VIR_ERROR("Failed to set lxc.net.%zu.hwaddr", i);
            goto cleanup;
        }
        if (lxctoolsConffileAddItemEnumerated(conffile, "lxc.net.%zu.link", def->nets[i]->data.bridge.brname, i) < 0) {
            VIR_ERROR("failed to set lxc.net.%zu.link", i);
            goto cleanup;
        }
        if (def->nets[i]->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP) {
            if (lxctoolsConffileAddItemEnumerated(conffile, "lxc.net.%zu.flags", "up", i) < 0)
                goto cleanup;
        }
    }
    if (lxctoolsConffileAddComment(conffile, "end: generated network configuration") < 0)
        goto cleanup;
    ret = 0;
 cleanup:
    VIR_FREE(mac_str);
    return ret;
}
Example #3
0
/**
 * virNetDevMacVLanCreate:
 *
 * @ifname: The name the interface is supposed to have; optional parameter
 * @type: The type of device, i.e., "macvtap", "macvlan"
 * @macaddress: The MAC address of the device
 * @srcdev: The name of the 'link' device
 * @macvlan_mode: The macvlan mode to use
 * @retry: Pointer to integer that will be '1' upon return if an interface
 *         with the same name already exists and it is worth to try
 *         again with a different name
 *
 * Create a macvtap device with the given properties.
 *
 * Returns 0 on success, -1 on fatal error.
 */
int
virNetDevMacVLanCreate(const char *ifname,
                       const char *type,
                       const virMacAddr *macaddress,
                       const char *srcdev,
                       uint32_t macvlan_mode,
                       int *retry)
{
    int rc = -1;
    struct nlmsghdr *resp = NULL;
    struct nlmsgerr *err;
    struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
    int ifindex;
    unsigned int recvbuflen;
    struct nl_msg *nl_msg;
    struct nlattr *linkinfo, *info_data;
    char macstr[VIR_MAC_STRING_BUFLEN];

    if (virNetDevGetIndex(srcdev, &ifindex) < 0)
        return -1;

    *retry = 0;

    nl_msg = nlmsg_alloc_simple(RTM_NEWLINK,
                                NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
    if (!nl_msg) {
        virReportOOMError();
        return -1;
    }

    if (nlmsg_append(nl_msg,  &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0)
        goto buffer_too_small;

    if (nla_put_u32(nl_msg, IFLA_LINK, ifindex) < 0)
        goto buffer_too_small;

    if (nla_put(nl_msg, IFLA_ADDRESS, VIR_MAC_BUFLEN, macaddress) < 0)
        goto buffer_too_small;

    if (ifname &&
        nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0)
        goto buffer_too_small;

    if (!(linkinfo = nla_nest_start(nl_msg, IFLA_LINKINFO)))
        goto buffer_too_small;

    if (nla_put(nl_msg, IFLA_INFO_KIND, strlen(type), type) < 0)
        goto buffer_too_small;

    if (macvlan_mode > 0) {
        if (!(info_data = nla_nest_start(nl_msg, IFLA_INFO_DATA)))
            goto buffer_too_small;

        if (nla_put(nl_msg, IFLA_MACVLAN_MODE, sizeof(macvlan_mode),
                    &macvlan_mode) < 0)
            goto buffer_too_small;

        nla_nest_end(nl_msg, info_data);
    }

    nla_nest_end(nl_msg, linkinfo);

    if (virNetlinkCommand(nl_msg, &resp, &recvbuflen, 0, 0,
                          NETLINK_ROUTE, 0) < 0) {
        goto cleanup;
    }

    if (recvbuflen < NLMSG_LENGTH(0) || resp == NULL)
        goto malformed_resp;

    switch (resp->nlmsg_type) {
    case NLMSG_ERROR:
        err = (struct nlmsgerr *)NLMSG_DATA(resp);
        if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
            goto malformed_resp;

        switch (err->error) {

        case 0:
            break;

        case -EEXIST:
            *retry = 1;
            goto cleanup;

        default:
            virReportSystemError(-err->error,
                                 _("error creating %s interface %s@%s (%s)"),
                                 type, ifname, srcdev,
                                 virMacAddrFormat(macaddress, macstr));
            goto cleanup;
        }
        break;

    case NLMSG_DONE:
        break;

    default:
        goto malformed_resp;
    }

    rc = 0;
 cleanup:
    nlmsg_free(nl_msg);
    VIR_FREE(resp);
    return rc;

 malformed_resp:
    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                   _("malformed netlink response message"));
    goto cleanup;

 buffer_too_small:
    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                   _("allocated netlink buffer is too small"));
    goto cleanup;
}
Example #4
0
/**
 * virNetDevOpenvswitchAddPort:
 * @brname: the bridge name
 * @ifname: the network interface name
 * @macaddr: the mac address of the virtual interface
 * @vmuuid: the Domain UUID that has this interface
 * @ovsport: the ovs specific fields
 *
 * Add an interface to the OVS bridge
 *
 * Returns 0 in case of success or -1 in case of failure.
 */
int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname,
                                   const virMacAddr *macaddr,
                                   const unsigned char *vmuuid,
                                   virNetDevVPortProfilePtr ovsport,
                                   virNetDevVlanPtr virtVlan)
{
    int ret = -1;
    size_t i = 0;
    virCommandPtr cmd = NULL;
    char macaddrstr[VIR_MAC_STRING_BUFLEN];
    char ifuuidstr[VIR_UUID_STRING_BUFLEN];
    char vmuuidstr[VIR_UUID_STRING_BUFLEN];
    char *attachedmac_ex_id = NULL;
    char *ifaceid_ex_id = NULL;
    char *profile_ex_id = NULL;
    char *vmid_ex_id = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virMacAddrFormat(macaddr, macaddrstr);
    virUUIDFormat(ovsport->interfaceID, ifuuidstr);
    virUUIDFormat(vmuuid, vmuuidstr);

    if (virAsprintf(&attachedmac_ex_id, "external-ids:attached-mac=\"%s\"",
                    macaddrstr) < 0)
        goto cleanup;
    if (virAsprintf(&ifaceid_ex_id, "external-ids:iface-id=\"%s\"",
                    ifuuidstr) < 0)
        goto cleanup;
    if (virAsprintf(&vmid_ex_id, "external-ids:vm-id=\"%s\"",
                    vmuuidstr) < 0)
        goto cleanup;
    if (ovsport->profileID[0] != '\0') {
        if (virAsprintf(&profile_ex_id, "external-ids:port-profile=\"%s\"",
                        ovsport->profileID) < 0)
            goto cleanup;
    }

    cmd = virCommandNew(OVSVSCTL);

    virCommandAddArgList(cmd, "--timeout=5", "--", "--if-exists", "del-port",
                         ifname, "--", "add-port", brname, ifname, NULL);

    if (virtVlan && virtVlan->nTags > 0) {

        switch (virtVlan->nativeMode) {
        case VIR_NATIVE_VLAN_MODE_TAGGED:
            virCommandAddArg(cmd, "vlan_mode=native-tagged");
            virCommandAddArgFormat(cmd, "tag=%d", virtVlan->nativeTag);
            break;
        case VIR_NATIVE_VLAN_MODE_UNTAGGED:
            virCommandAddArg(cmd, "vlan_mode=native-untagged");
            virCommandAddArgFormat(cmd, "tag=%d", virtVlan->nativeTag);
            break;
        case VIR_NATIVE_VLAN_MODE_DEFAULT:
        default:
            break;
        }

        if (virtVlan->trunk) {
            virBufferAddLit(&buf, "trunk=");

            /*
             * Trunk ports have at least one VLAN. Do the first one
             * outside the "for" loop so we can put a "," at the
             * start of the for loop if there are more than one VLANs
             * on this trunk port.
             */
            virBufferAsprintf(&buf, "%d", virtVlan->tag[i]);

            for (i = 1; i < virtVlan->nTags; i++) {
                virBufferAddLit(&buf, ",");
                virBufferAsprintf(&buf, "%d", virtVlan->tag[i]);
            }

            if (virBufferCheckError(&buf) < 0)
                goto cleanup;
            virCommandAddArg(cmd, virBufferCurrentContent(&buf));
        } else if (virtVlan->nTags) {
            virCommandAddArgFormat(cmd, "tag=%d", virtVlan->tag[0]);
        }
    }

    if (ovsport->profileID[0] == '\0') {
        virCommandAddArgList(cmd,
                        "--", "set", "Interface", ifname, attachedmac_ex_id,
                        "--", "set", "Interface", ifname, ifaceid_ex_id,
                        "--", "set", "Interface", ifname, vmid_ex_id,
                        "--", "set", "Interface", ifname,
                        "external-ids:iface-status=active",
                        NULL);
    } else {
        virCommandAddArgList(cmd,
                        "--", "set", "Interface", ifname, attachedmac_ex_id,
                        "--", "set", "Interface", ifname, ifaceid_ex_id,
                        "--", "set", "Interface", ifname, vmid_ex_id,
                        "--", "set", "Interface", ifname, profile_ex_id,
                        "--", "set", "Interface", ifname,
                        "external-ids:iface-status=active",
                        NULL);
    }

    if (virCommandRun(cmd, NULL) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unable to add port %s to OVS bridge %s"),
                       ifname, brname);
        goto cleanup;
    }

    ret = 0;
 cleanup:
    virBufferFreeAndReset(&buf);
    VIR_FREE(attachedmac_ex_id);
    VIR_FREE(ifaceid_ex_id);
    VIR_FREE(vmid_ex_id);
    VIR_FREE(profile_ex_id);
    virCommandFree(cmd);
    return ret;
}
Example #5
0
/* Create a VM record from the XML description */
int
createVMRecordFromXml(virConnectPtr conn, virDomainDefPtr def,
                      xen_vm_record **record, xen_vm *vm)
{
    char uuidStr[VIR_UUID_STRING_BUFLEN];
    xen_string_string_map *strings = NULL;
    int device_number = 0;
    size_t i;

    *record = xen_vm_record_alloc();
    if (VIR_STRDUP((*record)->name_label, def->name) < 0)
        goto error;
    if (def->uuid) {
        virUUIDFormat(def->uuid, uuidStr);
        if (VIR_STRDUP((*record)->uuid, uuidStr) < 0)
            goto error;
    }
    if (STREQ(def->os.type, "hvm")) {
        char *boot_order = NULL;
        if (VIR_STRDUP((*record)->hvm_boot_policy, "BIOS order") < 0)
            goto error;
        if (def->os.nBootDevs != 0)
            boot_order = createXenAPIBootOrderString(def->os.nBootDevs, &def->os.bootDevs[0]);
        if (boot_order != NULL) {
            xen_string_string_map *hvm_boot_params = NULL;
            allocStringMap(&hvm_boot_params, (char *)"order", boot_order);
            (*record)->hvm_boot_params = hvm_boot_params;
            VIR_FREE(boot_order);
        }
    } else if (STREQ(def->os.type, "xen")) {
        if (VIR_STRDUP((*record)->pv_bootloader, "pygrub") < 0)
            goto error;
        if (def->os.kernel) {
            if (VIR_STRDUP((*record)->pv_kernel, def->os.kernel) < 0)
                goto error;
        }
        if (def->os.initrd) {
            if (VIR_STRDUP((*record)->pv_ramdisk, def->os.initrd) < 0)
                goto error;
        }
        if (def->os.cmdline) {
            if (VIR_STRDUP((*record)->pv_args, def->os.cmdline) < 0)
                goto error;
        }
        (*record)->hvm_boot_params = xen_string_string_map_alloc(0);
    }
    if (def->os.bootloaderArgs)
        if (VIR_STRDUP((*record)->pv_bootloader_args, def->os.bootloaderArgs) < 0)
            goto error;

    if (def->mem.cur_balloon)
        (*record)->memory_static_max = (int64_t) (def->mem.cur_balloon * 1024);
    if (def->mem.max_balloon)
        (*record)->memory_dynamic_max = (int64_t) (def->mem.max_balloon * 1024);
    else
        (*record)->memory_dynamic_max = (*record)->memory_static_max;

    if (def->maxvcpus) {
        (*record)->vcpus_max = (int64_t) def->maxvcpus;
        (*record)->vcpus_at_startup = (int64_t) def->vcpus;
    }
    if (def->onPoweroff)
        (*record)->actions_after_shutdown = actionShutdownLibvirt2XenapiEnum(def->onPoweroff);
    if (def->onReboot)
        (*record)->actions_after_reboot = actionShutdownLibvirt2XenapiEnum(def->onReboot);
    if (def->onCrash)
        (*record)->actions_after_crash = actionCrashLibvirt2XenapiEnum(def->onCrash);

    if (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_DOMAIN_FEATURE_STATE_ON)
        allocStringMap(&strings, (char *)"acpi", (char *)"true");
    if (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_DOMAIN_FEATURE_STATE_ON)
        allocStringMap(&strings, (char *)"apic", (char *)"true");
    if (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_DOMAIN_FEATURE_STATE_ON)
        allocStringMap(&strings, (char *)"pae", (char *)"true");
    if (def->features[VIR_DOMAIN_FEATURE_HAP] == VIR_DOMAIN_FEATURE_STATE_ON)
        allocStringMap(&strings, (char *)"hap", (char *)"true");
    if (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] == VIR_DOMAIN_FEATURE_STATE_ON)
        allocStringMap(&strings, (char *)"viridian", (char *)"true");
    if (strings != NULL)
        (*record)->platform = strings;

    (*record)->vcpus_params = xen_string_string_map_alloc(0);
    (*record)->other_config = xen_string_string_map_alloc(0);
    (*record)->last_boot_cpu_flags = xen_string_string_map_alloc(0);
    (*record)->xenstore_data = xen_string_string_map_alloc(0);
    (*record)->hvm_shadow_multiplier = 1.000;
    if (!xen_vm_create(((struct _xenapiPrivate *)(conn->privateData))->session,
                        vm, *record)) {
        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
        return -1;
    }

    for (i = 0; i < def->nnets; i++) {
        if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
            def->nets[i]->data.bridge.brname) {
            char *mac;

            if (VIR_ALLOC_N(mac, VIR_MAC_STRING_BUFLEN) < 0)
                goto error;
            virMacAddrFormat(&def->nets[i]->mac, mac);

            if (createVifNetwork(conn, *vm, device_number,
                                 def->nets[i]->data.bridge.brname,
                                 mac) < 0) {
                VIR_FREE(mac);
                virReportOOMError();
                goto error;
            }
            device_number++;
        }
    }
    return 0;

  error:
    xen_vm_record_free(*record);
    return -1;
}
Example #6
0
static char *
umlBuildCommandLineNet(virConnectPtr conn,
                       virDomainDefPtr vm,
                       virDomainNetDefPtr def,
                       int idx)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char macaddr[VIR_MAC_STRING_BUFLEN];

    /* General format:  ethNN=type,options */

    virBufferAsprintf(&buf, "eth%d=", idx);

    switch (def->type) {
    case VIR_DOMAIN_NET_TYPE_USER:
        /* ethNNN=slirp,macaddr */
        virBufferAddLit(&buf, "slirp");
        break;

    case VIR_DOMAIN_NET_TYPE_ETHERNET:
        /* ethNNN=tuntap,tapname,macaddr,gateway */
        virBufferAddLit(&buf, "tuntap,");
        if (def->ifname)
            virBufferAdd(&buf, def->ifname, -1);
        if (def->nips > 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("IP address not supported for ethernet interface"));
            goto error;
        }
        break;

    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("vhostuser networking type not supported"));
        goto error;

    case VIR_DOMAIN_NET_TYPE_SERVER:
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("TCP server networking type not supported"));
        goto error;

    case VIR_DOMAIN_NET_TYPE_CLIENT:
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("TCP client networking type not supported"));
        goto error;

    case VIR_DOMAIN_NET_TYPE_MCAST:
        /* ethNNN=tuntap,macaddr,ipaddr,port */
        virBufferAddLit(&buf, "mcast");
        break;

    case VIR_DOMAIN_NET_TYPE_NETWORK:
    {
        char *bridge;
        virNetworkPtr network = virNetworkLookupByName(conn,
                                                       def->data.network.name);
        if (!network) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Network '%s' not found"),
                           def->data.network.name);
            goto error;
        }
        bridge = virNetworkGetBridgeName(network);
        virObjectUnref(network);
        if (bridge == NULL)
            goto error;

        if (umlConnectTapDevice(vm, def, bridge) < 0) {
            VIR_FREE(bridge);
            goto error;
        }

        /* ethNNN=tuntap,tapname,macaddr,gateway */
        virBufferAsprintf(&buf, "tuntap,%s", def->ifname);
        break;
    }

    case VIR_DOMAIN_NET_TYPE_BRIDGE:
        if (umlConnectTapDevice(vm, def,
                                def->data.bridge.brname) < 0)
            goto error;

        /* ethNNN=tuntap,tapname,macaddr,gateway */
        virBufferAsprintf(&buf, "tuntap,%s", def->ifname);
        break;

    case VIR_DOMAIN_NET_TYPE_INTERNAL:
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("internal networking type not supported"));
        goto error;

    case VIR_DOMAIN_NET_TYPE_DIRECT:
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("direct networking type not supported"));
        goto error;

    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("hostdev networking type not supported"));
        goto error;

    case VIR_DOMAIN_NET_TYPE_LAST:
        break;
    }

    if (def->script) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("interface script execution not supported by this driver"));
        goto error;
    }

    virBufferAsprintf(&buf, ",%s", virMacAddrFormat(&def->mac, macaddr));

    if (def->type == VIR_DOMAIN_NET_TYPE_MCAST) {
        virBufferAsprintf(&buf, ",%s,%d",
                          def->data.socket.address,
                          def->data.socket.port);
    }

    if (virBufferCheckError(&buf) < 0)
        return NULL;

    return virBufferContentAndReset(&buf);

 error:
    virBufferFreeAndReset(&buf);
    return NULL;
}
Example #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;
}
Example #8
0
static int
openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
                       virDomainNetDefPtr net,
                       virBufferPtr configBuf)
{
    int rc = 0, narg;
    const char *prog[OPENVZ_MAX_ARG];
    char macaddr[VIR_MAC_STRING_BUFLEN];
    unsigned char host_mac[VIR_MAC_BUFLEN];
    char host_macaddr[VIR_MAC_STRING_BUFLEN];
    struct openvz_driver *driver =  conn->privateData;
    char *opt = NULL;

#define ADD_ARG_LIT(thisarg)                                            \
    do {                                                                \
        if (narg >= OPENVZ_MAX_ARG)                                             \
                 goto no_memory;                                        \
        if ((prog[narg++] = strdup(thisarg)) == NULL)                   \
            goto no_memory;                                             \
    } while (0)


    if (net == NULL)
       return 0;
    if (vpsid == NULL) {
        openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("Container ID is not specified"));
        return -1;
    }

    for (narg = 0; narg < OPENVZ_MAX_ARG; narg++)
        prog[narg] = NULL;

    narg = 0;

    if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
        net->type == VIR_DOMAIN_NET_TYPE_ETHERNET) {
        ADD_ARG_LIT(VZCTL);
        ADD_ARG_LIT("--quiet");
        ADD_ARG_LIT("set");
        ADD_ARG_LIT(vpsid);
    }

    virMacAddrFormat(net->mac, macaddr);
    virCapabilitiesGenerateMac(driver->caps, host_mac);
    virMacAddrFormat(host_mac, host_macaddr);

    if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
        (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
         net->data.ethernet.ipaddr == NULL)) {
        virBuffer buf = VIR_BUFFER_INITIALIZER;
        int veid = openvzGetVEID(vpsid);

        /* --netif_add ifname[,mac,host_ifname,host_mac] */
        ADD_ARG_LIT("--netif_add") ;

        /* if user doesn't specify guest interface name,
         * then we need to generate it */
        if (net->data.ethernet.dev == NULL) {
            net->data.ethernet.dev = openvzGenerateContainerVethName(veid);
            if (net->data.ethernet.dev == NULL) {
               openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Could not generate eth name for container"));
               rc = -1;
               goto exit;
            }
        }

        /* if user doesn't specified host interface name,
         * than we need to generate it */
        if (net->ifname == NULL) {
            net->ifname = openvzGenerateVethName(veid, net->data.ethernet.dev);
            if (net->ifname == NULL) {
               openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Could not generate veth name"));
               rc = -1;
               goto exit;
            }
        }

        virBufferAdd(&buf, net->data.ethernet.dev, -1); /* Guest dev */
        virBufferAsprintf(&buf, ",%s", macaddr); /* Guest dev mac */
        virBufferAsprintf(&buf, ",%s", net->ifname); /* Host dev */
        virBufferAsprintf(&buf, ",%s", host_macaddr); /* Host dev mac */

        if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
            if (driver->version >= VZCTL_BRIDGE_MIN_VERSION) {
                virBufferAsprintf(&buf, ",%s", net->data.bridge.brname); /* Host bridge */
            } else {
                virBufferAsprintf(configBuf, "ifname=%s", net->data.ethernet.dev);
                virBufferAsprintf(configBuf, ",mac=%s", macaddr); /* Guest dev mac */
                virBufferAsprintf(configBuf, ",host_ifname=%s", net->ifname); /* Host dev */
                virBufferAsprintf(configBuf, ",host_mac=%s", host_macaddr); /* Host dev mac */
                virBufferAsprintf(configBuf, ",bridge=%s", net->data.bridge.brname); /* Host bridge */
            }
        }

        if (!(opt = virBufferContentAndReset(&buf)))
            goto no_memory;

        ADD_ARG_LIT(opt) ;
        VIR_FREE(opt);
    } else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
              net->data.ethernet.ipaddr != NULL) {
        /* --ipadd ip */
        ADD_ARG_LIT("--ipadd") ;
        ADD_ARG_LIT(net->data.ethernet.ipaddr) ;
    }

    /* TODO: processing NAT and physical device */

    if (prog[0] != NULL) {
        ADD_ARG_LIT("--save");
        if (virRun(prog, NULL) < 0) {
           rc = -1;
           goto exit;
        }
    }

 exit:
    cmdExecFree(prog);
    return rc;

 no_memory:
    VIR_FREE(opt);
    openvzError(VIR_ERR_INTERNAL_ERROR,
                _("Could not put argument to %s"), VZCTL);
    cmdExecFree(prog);
    return -1;

#undef ADD_ARG_LIT
}
Example #9
0
/*
 * virNetDevBandwidthPlug:
 * @brname: name of the bridge
 * @net_bandwidth: QoS settings on @brname
 * @ifmac: MAC of interface
 * @bandwidth: QoS settings for interface
 * @id: unique ID (MUST be greater than 2)
 *
 * Set bridge part of interface QoS settings, e.g. guaranteed
 * bandwidth.  @id is an unique ID (among @brname) from which
 * other identifiers for class, qdisc and filter are derived.
 * However, two classes were already set up (by
 * virNetDevBandwidthSet). That's why this @id MUST be greater
 * than 2. You may want to keep passed @id, as it is used later
 * by virNetDevBandwidthUnplug.
 *
 * Returns:
 * 0 if QoS set successfully
 * -1 otherwise.
 */
int
virNetDevBandwidthPlug(const char *brname,
                       virNetDevBandwidthPtr net_bandwidth,
                       const virMacAddrPtr ifmac_ptr,
                       virNetDevBandwidthPtr bandwidth,
                       unsigned int id)
{
    int ret = -1;
    virCommandPtr cmd = NULL;
    char *class_id = NULL;
    char *qdisc_id = NULL;
    char *filter_id = NULL;
    char *floor = NULL;
    char *ceil = NULL;
    unsigned char ifmac[VIR_MAC_BUFLEN];
    char ifmacStr[VIR_MAC_STRING_BUFLEN];
    char *mac[2] = {NULL, NULL};

    if (id <= 2) {
        virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid class ID %d"), id);
        return -1;
    }

    virMacAddrGetRaw(ifmac_ptr, ifmac);
    virMacAddrFormat(ifmac_ptr, ifmacStr);

    if (!net_bandwidth || !net_bandwidth->in) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Bridge '%s' has no QoS set, therefore "
                         "unable to set 'floor' on '%s'"),
                       brname, ifmacStr);
        return -1;
    }

    if (virAsprintf(&class_id, "1:%x", id) < 0 ||
        virAsprintf(&qdisc_id, "%x:", id) < 0 ||
        virAsprintf(&filter_id, "%u", id) < 0 ||
        virAsprintf(&mac[0], "0x%02x%02x%02x%02x", ifmac[2],
                    ifmac[3], ifmac[4], ifmac[5]) < 0 ||
        virAsprintf(&mac[1], "0x%02x%02x", ifmac[0], ifmac[1]) < 0 ||
        virAsprintf(&floor, "%llukbps", bandwidth->in->floor) < 0 ||
        virAsprintf(&ceil, "%llukbps", net_bandwidth->in->peak ?
                    net_bandwidth->in->peak :
                    net_bandwidth->in->average) < 0) {
        virReportOOMError();
        goto cleanup;
    }

    cmd = virCommandNew(TC);
    virCommandAddArgList(cmd, "class", "add", "dev", brname, "parent", "1:1",
                         "classid", class_id, "htb", "rate", floor,
                         "ceil", ceil, NULL);

    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    virCommandFree(cmd);
    cmd = virCommandNew(TC);
    virCommandAddArgList(cmd, "qdisc", "add", "dev", brname, "parent",
                         class_id, "handle", qdisc_id, "sfq", "perturb",
                         "10", NULL);

    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    virCommandFree(cmd);
    cmd = virCommandNew(TC);
    /* Okay, this not nice. But since libvirt does not know anything about
     * interface IP address(es), and tc fw filter simply refuse to use ebtables
     * marks, we need to use u32 selector to match MAC address.
     * If libvirt will ever know something, remove this FIXME
     */
    virCommandAddArgList(cmd, "filter", "add", "dev", brname, "protocol", "ip",
                         "prio", filter_id, "u32",
                         "match", "u16", "0x0800", "0xffff", "at", "-2",
                         "match", "u32", mac[0], "0xffffffff", "at", "-12",
                         "match", "u16", mac[1], "0xffff", "at", "-14",
                         "flowid", class_id, NULL);

    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    ret = 0;

cleanup:
    VIR_FREE(mac[1]);
    VIR_FREE(mac[0]);
    VIR_FREE(ceil);
    VIR_FREE(floor);
    VIR_FREE(filter_id);
    VIR_FREE(qdisc_id);
    VIR_FREE(class_id);
    virCommandFree(cmd);
    return ret;
}
Example #10
0
/**
 * virNetDevOpenvswitchAddPort:
 * @brname: the bridge name
 * @ifname: the network interface name
 * @macaddr: the mac address of the virtual interface
 * @ovsport: the ovs specific fields
 *
 * Add an interface to the OVS bridge
 *
 * Returns 0 in case of success or -1 in case of failure.
 */
int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname,
                                   const unsigned char *macaddr,
                                   virNetDevVPortProfilePtr ovsport)
{
    int ret = -1;
    virCommandPtr cmd = NULL;
    char macaddrstr[VIR_MAC_STRING_BUFLEN];
    char uuidstr[VIR_UUID_STRING_BUFLEN];
    char *attachedmac_ex_id = NULL;
    char *ifaceid_ex_id = NULL;
    char *profile_ex_id = NULL;

    virMacAddrFormat(macaddr, macaddrstr);
    virUUIDFormat(ovsport->u.openvswitch.interfaceID, uuidstr);

    if (virAsprintf(&attachedmac_ex_id, "external-ids:attached-mac=\"%s\"",
                    macaddrstr) < 0)
        goto cleanup;
    if (virAsprintf(&ifaceid_ex_id, "external-ids:iface-id=\"%s\"",
                    uuidstr) < 0)
        goto cleanup;
    if (ovsport->u.openvswitch.profileID[0] != '\0') {
        if (virAsprintf(&profile_ex_id, "external-ids:port-profile=\"%s\"",
                        ovsport->u.openvswitch.profileID) < 0)
            goto cleanup;
    }

    cmd = virCommandNew(OVSVSCTL);
    if (ovsport->u.openvswitch.profileID[0] == '\0') {
        virCommandAddArgList(cmd, "--", "--may-exist", "add-port",
                        brname, ifname,
                        "--", "set", "Interface", ifname, attachedmac_ex_id,
                        "--", "set", "Interface", ifname, ifaceid_ex_id,
                        "--", "set", "Interface", ifname,
                        "external-ids:iface-status=active",
                        NULL);
    } else {
        virCommandAddArgList(cmd, "--", "--may-exist", "add-port",
                        brname, ifname,
                        "--", "set", "Interface", ifname, attachedmac_ex_id,
                        "--", "set", "Interface", ifname, ifaceid_ex_id,
                        "--", "set", "Interface", ifname, profile_ex_id,
                        "--", "set", "Interface", ifname,
                        "external-ids:iface-status=active",
                        NULL);
    }

    if (virCommandRun(cmd, NULL) < 0) {
        virReportSystemError(VIR_ERR_INTERNAL_ERROR,
                             _("Unable to add port %s to OVS bridge %s"),
                             ifname, brname);
        goto cleanup;
    }
    ret = 0;

    cleanup:
        VIR_FREE(attachedmac_ex_id);
        VIR_FREE(ifaceid_ex_id);
        VIR_FREE(profile_ex_id);
        virCommandFree(cmd);
        return ret;
}