These classes can borrow unused bandwidth. Basically,
only egress qdsics can have classes, therefore we can
do this kind of traffic shaping only on host's outgoing,
that is domain's incoming traffic.
---
src/lxc/lxc_driver.c | 3 ++-
src/network/bridge_driver.c | 4 +++-
src/qemu/qemu_command.c | 3 ++-
src/qemu/qemu_driver.c | 2 +-
src/util/virnetdevbandwidth.c | 26 ++++++++++++++++++++------
src/util/virnetdevbandwidth.h | 4 +++-
src/util/virnetdevmacvlan.c | 2 +-
7 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 3baff19..1c91680 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1221,7 +1221,8 @@ static int lxcSetupInterfaceBridged(virConnectPtr conn,
goto cleanup;
if (virNetDevBandwidthSet(net->ifname,
- virDomainNetGetActualBandwidth(net)) < 0) {
+ virDomainNetGetActualBandwidth(net),
+ false) < 0) {
lxcError(VIR_ERR_INTERNAL_ERROR,
_("cannot set bandwidth limits on %s"),
net->ifname);
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 5d0d528..057c955 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1826,7 +1826,9 @@ networkStartNetworkVirtual(struct network_driver *driver,
if (v6present && networkStartRadvd(network) < 0)
goto err4;
- if (virNetDevBandwidthSet(network->def->bridge, network->def->bandwidth)
< 0) {
+ if (virNetDevBandwidthSet(network->def->bridge,
+ network->def->bandwidth,
+ true) < 0) {
networkReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot set bandwidth limits on %s"),
network->def->bridge);
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index d051305..22cebe6 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -265,7 +265,8 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
if (tapfd >= 0 &&
virNetDevBandwidthSet(net->ifname,
- virDomainNetGetActualBandwidth(net)) < 0) {
+ virDomainNetGetActualBandwidth(net),
+ false) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot set bandwidth limits on %s"),
net->ifname);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 712f1fc..faf4258 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -8005,7 +8005,7 @@ qemuDomainSetInterfaceParameters(virDomainPtr dom,
sizeof(*newBandwidth->out));
}
- if (virNetDevBandwidthSet(net->ifname, newBandwidth) < 0) {
+ if (virNetDevBandwidthSet(net->ifname, newBandwidth, false) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot set bandwidth limits on %s"),
device);
diff --git a/src/util/virnetdevbandwidth.c b/src/util/virnetdevbandwidth.c
index d23d600..ac3a93d 100644
--- a/src/util/virnetdevbandwidth.c
+++ b/src/util/virnetdevbandwidth.c
@@ -46,17 +46,19 @@ virNetDevBandwidthFree(virNetDevBandwidthPtr def)
* virNetDevBandwidthSet:
* @ifname: on which interface
* @bandwidth: rates to set (may be NULL)
+ * @create_child_class: TRUE iff @ifname is bridge
*
* This function enables QoS on specified interface
* and set given traffic limits for both, incoming
- * and outgoing traffic. Any previous setting get
+ * and outgoing traffic. Any previous setting gets
* overwritten.
*
* Return 0 on success, -1 otherwise.
*/
int
virNetDevBandwidthSet(const char *ifname,
- virNetDevBandwidthPtr bandwidth)
+ virNetDevBandwidthPtr bandwidth,
+ bool create_child_class)
{
int ret = -1;
virCommandPtr cmd = NULL;
@@ -84,16 +86,28 @@ virNetDevBandwidthSet(const char *ifname,
cmd = virCommandNew(TC);
virCommandAddArgList(cmd, "qdisc", "add", "dev",
ifname, "root",
- "handle", "1:", "htb",
"default", "1", NULL);
+ "handle", "1:", "htb",
"default",
+ create_child_class ? "2" : "1", NULL);
if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
+ if (create_child_class) {
+ virCommandFree(cmd);
+ cmd = virCommandNew(TC);
+ virCommandAddArgList(cmd, "class", "add",
"dev", ifname, "parent",
+ "1:", "classid", "1:1",
"htb", "rate",
+ average, "ceil", peak ? peak : average,
NULL);
+
+ if (virCommandRun(cmd, NULL) < 0)
+ goto cleanup;
+ }
+
virCommandFree(cmd);
cmd = virCommandNew(TC);
virCommandAddArgList(cmd,"class", "add", "dev",
ifname, "parent",
- "1:", "classid", "1:1",
"htb", NULL);
- virCommandAddArgList(cmd, "rate", average, NULL);
-
+ create_child_class ? "1:1" : "1:",
"classid",
+ create_child_class ? "1:2" : "1:1",
"htb",
+ "rate", average, NULL);
if (peak)
virCommandAddArgList(cmd, "ceil", peak, NULL);
if (burst)
diff --git a/src/util/virnetdevbandwidth.h b/src/util/virnetdevbandwidth.h
index 8551caa..1e7d46d 100644
--- a/src/util/virnetdevbandwidth.h
+++ b/src/util/virnetdevbandwidth.h
@@ -42,7 +42,9 @@ struct _virNetDevBandwidth {
void virNetDevBandwidthFree(virNetDevBandwidthPtr def);
-int virNetDevBandwidthSet(const char *ifname, virNetDevBandwidthPtr bandwidth)
+int virNetDevBandwidthSet(const char *ifname,
+ virNetDevBandwidthPtr bandwidth,
+ bool create_child_class)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
int virNetDevBandwidthClear(const char *ifname)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
index 5e55b72..f496290 100644
--- a/src/util/virnetdevmacvlan.c
+++ b/src/util/virnetdevmacvlan.c
@@ -578,7 +578,7 @@ create_name:
rc = 0;
}
- if (virNetDevBandwidthSet(cr_ifname, bandwidth) < 0) {
+ if (virNetDevBandwidthSet(cr_ifname, bandwidth, false) < 0) {
virNetDevError(VIR_ERR_INTERNAL_ERROR,
_("cannot set bandwidth limits on %s"),
cr_ifname);
--
1.7.3.4