/** * 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); }
/* * 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; }
/** * 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; }
/** * 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; }
/* 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; }
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; }
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; }
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 }
/* * 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; }
/** * 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; }