Ethernet interfaces in libvirt currently do not support bandwidth setting.
For example, following xml file for an interface will not apply these
settings to corresponding qdiscs.
<interface type="ethernet">
<mac address="02:36:1d:18:2a:e4"/>
<model type="virtio"/>
<script path=""/>
<target dev="tap361d182a-e4"/>
<bandwidth>
<inbound average="984" peak="1024"
burst="64"/>
<outbound average="2000" peak="2048"
burst="128"/>
</bandwidth>
</interface>
Signed-off-by: Anirban Chakraborty <abchak(a)juniper.net>
---
src/conf/netdev_bandwidth_conf.c | 14 ++++++++++-
src/conf/netdev_bandwidth_conf.h | 25 +++++++++++++++++++
src/libvirt_private.syms | 1 +
src/lxc/lxc_driver.c | 8 +++++++
src/lxc/lxc_process.c | 52 +++++++++++++++++++++++-----------------
src/qemu/qemu_command.c | 16 ++++++++-----
src/qemu/qemu_hotplug.c | 12 ++++++++++
src/qemu/qemu_process.c | 4 ++++
src/util/virnetdevmacvlan.c | 10 --------
src/util/virnetdevmacvlan.h | 1 -
10 files changed, 103 insertions(+), 40 deletions(-)
diff --git a/src/conf/netdev_bandwidth_conf.c b/src/conf/netdev_bandwidth_conf.c
index 2e5b564..63a39e3 100644
--- a/src/conf/netdev_bandwidth_conf.c
+++ b/src/conf/netdev_bandwidth_conf.c
@@ -25,7 +25,6 @@
#include "netdev_bandwidth_conf.h"
#include "virerror.h"
#include "viralloc.h"
-#include "domain_conf.h"
#include "virstring.h"
#define VIR_FROM_THIS VIR_FROM_NONE
@@ -269,3 +268,16 @@ virNetDevBandwidthFormat(virNetDevBandwidthPtr def, virBufferPtr
buf)
cleanup:
return ret;
}
+
+void
+virDomainClearNetBandwidth(virDomainObjPtr vm)
+{
+ size_t i;
+ virDomainNetType type;
+
+ for (i = 0; i < vm->def->nnets; i++) {
+ type = virDomainNetGetActualType(vm->def->nets[i]);
+ if (virNetDevSupportBandwidth(type))
+ virNetDevBandwidthClear(vm->def->nets[i]->ifname);
+ }
+}
diff --git a/src/conf/netdev_bandwidth_conf.h b/src/conf/netdev_bandwidth_conf.h
index 23aaaf3..60dacc6 100644
--- a/src/conf/netdev_bandwidth_conf.h
+++ b/src/conf/netdev_bandwidth_conf.h
@@ -27,6 +27,7 @@
# include "virnetdevbandwidth.h"
# include "virbuffer.h"
# include "virxml.h"
+# include "domain_conf.h"
virNetDevBandwidthPtr virNetDevBandwidthParse(xmlNodePtr node,
int net_type)
@@ -35,4 +36,28 @@ int virNetDevBandwidthFormat(virNetDevBandwidthPtr def,
virBufferPtr buf)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+void virDomainClearNetBandwidth(virDomainObjPtr vm)
+ ATTRIBUTE_NONNULL(1);
+
+static inline bool virNetDevSupportBandwidth(virDomainNetType type)
+{
+ switch (type) {
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
+ case VIR_DOMAIN_NET_TYPE_DIRECT:
+ case VIR_DOMAIN_NET_TYPE_ETHERNET:
+ return true;
+ case VIR_DOMAIN_NET_TYPE_USER:
+ case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
+ case VIR_DOMAIN_NET_TYPE_SERVER:
+ case VIR_DOMAIN_NET_TYPE_CLIENT:
+ case VIR_DOMAIN_NET_TYPE_MCAST:
+ case VIR_DOMAIN_NET_TYPE_INTERNAL:
+ case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+ case VIR_DOMAIN_NET_TYPE_LAST:
+ break;
+ }
+ return false;
+}
+
#endif /* __VIR_NETDEV_BANDWIDTH_CONF_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0864618..1c0cfb1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -509,6 +509,7 @@ virInterfaceRemove;
# conf/netdev_bandwidth_conf.h
virNetDevBandwidthFormat;
virNetDevBandwidthParse;
+virDomainClearNetBandwidth;
# conf/netdev_vlan_conf.h
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index cf2a3c8..e9e0da3 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -72,6 +72,7 @@
#include "viraccessapicheck.h"
#include "viraccessapichecklxc.h"
#include "virhostdev.h"
+#include "netdev_bandwidth_conf.h"
#define VIR_FROM_THIS VIR_FROM_LXC
@@ -4213,6 +4214,11 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn,
_("Network device type is not supported"));
goto cleanup;
}
+ /* set network bandwidth */
+ if (virNetDevSupportBandwidth(actualType) &&
+ virNetDevBandwidthSet(net->ifname,
+ virDomainNetGetActualBandwidth(net), false) < 0)
+ goto cleanup;
if (virNetDevSetNamespace(veth, priv->initpid) < 0) {
virDomainAuditNet(vm, NULL, net, "attach", false);
@@ -4644,6 +4650,8 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm,
detach = vm->def->nets[detachidx];
+ virDomainClearNetBandwidth(vm);
+
switch (virDomainNetGetActualType(detach)) {
case VIR_DOMAIN_NET_TYPE_BRIDGE:
case VIR_DOMAIN_NET_TYPE_NETWORK:
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index 37ddbbc..5bbd696 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -51,6 +51,7 @@
#include "viratomic.h"
#include "virprocess.h"
#include "virsystemd.h"
+#include "netdev_bandwidth_conf.h"
#define VIR_FROM_THIS VIR_FROM_LXC
@@ -274,11 +275,6 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn,
if (virNetDevSetOnline(parentVeth, true) < 0)
goto cleanup;
- if (virNetDevBandwidthSet(net->ifname,
- virDomainNetGetActualBandwidth(net),
- false) < 0)
- goto cleanup;
-
if (net->filter &&
virDomainConfNWFilterInstantiate(conn, vm->uuid, net) < 0)
goto cleanup;
@@ -300,6 +296,7 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn,
virNetDevBandwidthPtr bw;
virNetDevVPortProfilePtr prof;
virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
+ const char *linkdev = virDomainNetGetActualDirectDev(net);
/* XXX how todo bandwidth controls ?
* Since the 'net-ifname' is about to be moved to a different
@@ -329,14 +326,13 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn,
if (virNetDevMacVLanCreateWithVPortProfile(
net->ifname, &net->mac,
- virDomainNetGetActualDirectDev(net),
+ linkdev,
virDomainNetGetActualDirectMode(net),
false, def->uuid,
- virDomainNetGetActualVirtPortProfile(net),
+ prof,
&res_ifname,
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
- cfg->stateDir,
- virDomainNetGetActualBandwidth(net), 0) < 0)
+ cfg->stateDir, 0) < 0)
goto cleanup;
ret = res_ifname;
@@ -368,6 +364,8 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
int ret = -1;
size_t i;
size_t niface = 0;
+ virDomainNetDefPtr net;
+ virDomainNetType type;
for (i = 0; i < def->nnets; i++) {
char *veth = NULL;
@@ -375,13 +373,15 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
* network's pool of devices, or resolve bridge device name
* to the one defined in the network definition.
*/
- if (networkAllocateActualDevice(def, def->nets[i]) < 0)
+ net = def->nets[i];
+ if (networkAllocateActualDevice(def, net) < 0)
goto cleanup;
if (VIR_EXPAND_N(*veths, *nveths, 1) < 0)
goto cleanup;
- switch (virDomainNetGetActualType(def->nets[i])) {
+ type = virDomainNetGetActualType(net);
+ switch (type) {
case VIR_DOMAIN_NET_TYPE_NETWORK: {
virNetworkPtr network;
char *brname = NULL;
@@ -389,7 +389,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
virErrorPtr errobj;
if (!(network = virNetworkLookupByName(conn,
-
def->nets[i]->data.network.name)))
+ net->data.network.name)))
goto cleanup;
if (!(brname = virNetworkGetBridgeName(network)))
fail = true;
@@ -405,7 +405,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
if (!(veth = virLXCProcessSetupInterfaceBridged(conn,
def,
- def->nets[i],
+ net,
brname))) {
VIR_FREE(brname);
goto cleanup;
@@ -414,7 +414,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
break;
}
case VIR_DOMAIN_NET_TYPE_BRIDGE: {
- const char *brname = virDomainNetGetActualBridgeName(def->nets[i]);
+ const char *brname = virDomainNetGetActualBridgeName(net);
if (!brname) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("No bridge name specified"));
@@ -422,7 +422,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
}
if (!(veth = virLXCProcessSetupInterfaceBridged(conn,
def,
- def->nets[i],
+ net,
brname)))
goto cleanup;
} break;
@@ -430,31 +430,39 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
case VIR_DOMAIN_NET_TYPE_DIRECT:
if (!(veth = virLXCProcessSetupInterfaceDirect(conn,
def,
- def->nets[i])))
+ net)))
goto cleanup;
break;
- case VIR_DOMAIN_NET_TYPE_USER:
case VIR_DOMAIN_NET_TYPE_ETHERNET:
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_USER:
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_LAST:
+ case VIR_DOMAIN_NET_TYPE_HOSTDEV:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unsupported network type %s"),
- virDomainNetTypeToString(
- virDomainNetGetActualType(def->nets[i])
- ));
+ virDomainNetTypeToString(type));
goto cleanup;
+
}
+ /* set network bandwidth */
+ if (virNetDevSupportBandwidth(type) &&
+ virNetDevBandwidthSet(net->ifname,
+ virDomainNetGetActualBandwidth(net), false) < 0)
+ goto cleanup;
+
(*veths)[(*nveths)-1] = veth;
/* Make sure all net definitions will have a name in the container */
- if (!def->nets[i]->ifname_guest) {
- if (virAsprintf(&def->nets[i]->ifname_guest, "eth%zu",
niface) < 0)
+ if (!net->ifname_guest) {
+ if (virAsprintf(&net->ifname_guest, "eth%zu", niface) <
0)
return -1;
niface++;
}
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1399ce4..8025ff6 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -43,6 +43,7 @@
#include "domain_addr.h"
#include "domain_audit.h"
#include "domain_conf.h"
+#include "netdev_bandwidth_conf.h"
#include "snapshot_conf.h"
#include "storage_conf.h"
#include "secret_conf.h"
@@ -192,7 +193,6 @@ qemuPhysIfaceConnect(virDomainDefPtr def,
virDomainNetGetActualVirtPortProfile(net),
&res_ifname,
vmop, cfg->stateDir,
- virDomainNetGetActualBandwidth(net),
macvlan_create_flags);
if (rc >= 0) {
virDomainAuditNetDevice(def, net, res_ifname, true);
@@ -372,11 +372,6 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
&net->mac) < 0)
goto cleanup;
- if (virNetDevBandwidthSet(net->ifname,
- virDomainNetGetActualBandwidth(net),
- false) < 0)
- goto cleanup;
-
if (net->filter &&
virDomainConfNWFilterInstantiate(conn, def->uuid, net) < 0) {
goto cleanup;
@@ -7501,6 +7496,15 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
goto cleanup;
}
+ /* Set Bandwidth */
+ if (net->ifname && strlen(net->ifname)) {
+ if (virNetDevSupportBandwidth(actualType) &&
+ virNetDevBandwidthSet(net->ifname,
+ virDomainNetGetActualBandwidth(net),
+ false) < 0)
+ goto cleanup;
+ }
+
if ((actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
actualType == VIR_DOMAIN_NET_TYPE_ETHERNET ||
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index b9a0cee..3e7b7da 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -31,6 +31,7 @@
#include "qemu_command.h"
#include "qemu_hostdev.h"
#include "domain_audit.h"
+#include "netdev_bandwidth_conf.h"
#include "domain_nwfilter.h"
#include "virlog.h"
#include "datatypes.h"
@@ -947,6 +948,12 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
goto cleanup;
}
+ /* Set Bandwidth */
+ if (virNetDevSupportBandwidth(actualType) &&
+ virNetDevBandwidthSet(net->ifname,
+ virDomainNetGetActualBandwidth(net), false) < 0)
+ goto cleanup;
+
for (i = 0; i < tapfdSize; i++) {
if (virSecurityManagerSetTapFDLabel(driver->securityManager,
vm->def, tapfd[i]) < 0)
@@ -3545,6 +3552,11 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
goto cleanup;
}
+ if (virNetDevSupportBandwidth(virDomainNetGetActualType(detach)) &&
+ virNetDevBandwidthClear(detach->ifname) < 0)
+ VIR_WARN("cannot clear bandwidth setting for device : %s",
+ detach->ifname);
+
qemuDomainMarkDeviceForRemoval(vm, &detach->info);
qemuDomainObjEnterMonitor(driver, vm);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 7518138..b782984 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -69,6 +69,7 @@
#include "storage/storage_driver.h"
#include "configmake.h"
#include "nwfilter_conf.h"
+#include "netdev_bandwidth_conf.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -4843,6 +4844,9 @@ void qemuProcessStop(virQEMUDriverPtr driver,
virStrerror(errno, ebuf, sizeof(ebuf)));
}
+ /* Clear network bandwidth */
+ virDomainClearNetBandwidth(vm);
+
virDomainConfVMNWFilterTeardown(vm);
if (cfg->macFilter) {
diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
index 89e221d..2ff24b1 100644
--- a/src/util/virnetdevmacvlan.c
+++ b/src/util/virnetdevmacvlan.c
@@ -810,7 +810,6 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname,
char **res_ifname,
virNetDevVPortProfileOp vmOp,
char *stateDir,
- virNetDevBandwidthPtr bandwidth,
unsigned int flags)
{
const char *type = (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ?
@@ -923,14 +922,6 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname,
rc = 0;
}
- if (virNetDevBandwidthSet(cr_ifname, bandwidth, false) < 0) {
- if (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP)
- VIR_FORCE_CLOSE(rc); /* sets rc to -1 */
- else
- rc = -1;
- goto disassociate_exit;
- }
-
if (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_CREATE ||
vmOp == VIR_NETDEV_VPORT_PROFILE_OP_RESTORE) {
/* Only directly register upon a create or restore (restarting
@@ -1073,7 +1064,6 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *ifname
ATTRIBUTE_UNUSED,
char **res_ifname ATTRIBUTE_UNUSED,
virNetDevVPortProfileOp vmop
ATTRIBUTE_UNUSED,
char *stateDir ATTRIBUTE_UNUSED,
- virNetDevBandwidthPtr bandwidth
ATTRIBUTE_UNUSED,
unsigned int flags)
{
virCheckFlags(0, -1);
diff --git a/src/util/virnetdevmacvlan.h b/src/util/virnetdevmacvlan.h
index 41aa4e2..f08d32b 100644
--- a/src/util/virnetdevmacvlan.h
+++ b/src/util/virnetdevmacvlan.h
@@ -68,7 +68,6 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *ifname,
char **res_ifname,
virNetDevVPortProfileOp vmop,
char *stateDir,
- virNetDevBandwidthPtr bandwidth,
unsigned int flags)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(6)
ATTRIBUTE_NONNULL(8) ATTRIBUTE_NONNULL(10) ATTRIBUTE_RETURN_CHECK;
--
1.9.1