[PATCH 5/7] bandwitdh: Implement functions to enable and disable QoS

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



These function executes 'tc' with appropriate arguments to set
desired QoS setting on interface or bridge during its creation.
---
 configure.ac                |    4 +
 src/libvirt_private.syms    |    2 +
 src/network/bridge_driver.c |    8 ++
 src/qemu/qemu_command.c     |    5 ++
 src/util/network.c          |  152 +++++++++++++++++++++++++++++++++++++++++++
 src/util/network.h          |    3 +
 6 files changed, 174 insertions(+), 0 deletions(-)

diff --git a/configure.ac b/configure.ac
index f816696..d563e94 100644
--- a/configure.ac
+++ b/configure.ac
@@ -165,6 +165,8 @@ AC_PATH_PROG([RADVD], [radvd], [radvd],
 	[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
 AC_PATH_PROG([BRCTL], [brctl], [brctl],
 	[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
+AC_PATH_PROG([TC], [tc], [tc],
+    [/sbin:/usr/sbin:/usr/local/sbin:$PATH])
 AC_PATH_PROG([UDEVADM], [udevadm], [],
 	[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
 AC_PATH_PROG([UDEVSETTLE], [udevsettle], [],
@@ -178,6 +180,8 @@ AC_DEFINE_UNQUOTED([RADVD],["$RADVD"],
         [Location or name of the radvd program])
 AC_DEFINE_UNQUOTED([BRCTL],["$BRCTL"],
         [Location or name of the brctl program (see bridge-utils)])
+AC_DEFINE_UNQUOTED([TC],["$TC"],
+        [Location or name of the tc profram (see iproute2)])
 if test -n "$UDEVADM"; then
   AC_DEFINE_UNQUOTED([UDEVADM],["$UDEVADM"],
         [Location or name of the udevadm program])
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6640cfb..adf9cb0 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -683,6 +683,8 @@ nlComm;
 # network.h
 virBandwidrhDefFormat;
 virBandwidthDefParseNode;
+virBandwidthDisable;
+virBandwidthEnable;
 virBpsToRate;
 virBtoSize;
 virSocketAddrBroadcast;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 4b94959..80f852f 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1745,6 +1745,9 @@ networkStartNetworkDaemon(struct network_driver *driver,
     if (v6present && networkStartRadvd(network) < 0)
         goto err4;
 
+    if (virBandwidthEnable(&network->def->bandwidth, network->def->bridge) < 0)
+        goto err5;
+
     /* Persist the live configuration now we have bridge info  */
     if (virNetworkSaveConfig(NETWORK_STATE_DIR, network->def) < 0) {
         goto err5;
@@ -1836,6 +1839,11 @@ static int networkShutdownNetworkDaemon(struct network_driver *driver,
     unlink(stateFile);
     VIR_FREE(stateFile);
 
+    if (virBandwidthDisable(network->def->bridge, true) < 0) {
+        VIR_WARN("Failed to disable QoS on %s",
+                 network->def->name);
+    }
+
     if (network->radvdPid > 0) {
         char *radvdpidbase;
 
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index b517e1a..5ef73ed 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -291,6 +291,11 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
         }
     }
 
+    if (virBandwidthEnable(&net->bandwidth, net->ifname) < 0) {
+        VIR_FORCE_CLOSE(tapfd);
+        goto cleanup;
+    }
+
     if (tapfd >= 0) {
         if ((net->filter) && (net->ifname)) {
             err = virDomainConfNWFilterInstantiate(conn, net);
diff --git a/src/util/network.c b/src/util/network.c
index b24f977..7bba60c 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -16,6 +16,7 @@
 #include "network.h"
 #include "util.h"
 #include "virterror_internal.h"
+#include "command.h"
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 #define virSocketError(code, ...)                                       \
@@ -1030,3 +1031,154 @@ virBandwidrhDefFormat(virBufferPtr buf,
 cleanup:
     return ret;
 }
+
+/**
+ * virBandwidthEnable:
+ * @bandwidth: rates to set
+ * @iface: on which interface
+ *
+ * This function enables QoS on specified interface
+ * and set given traffic limits for both, incoming
+ * and outgoing traffic. Any previous setting get
+ * overwritten.
+ *
+ * Return 0 on success, -1 otherwise.
+ */
+int
+virBandwidthEnable(virBandwidthPtr bandwidth,
+                   const char *iface)
+{
+    int ret = -1;
+    virCommandPtr cmd = NULL;
+    char *average = NULL;
+    char *peak = NULL;
+    char *burst = NULL;
+
+    if (!bandwidth || !iface)
+        return -1;
+
+    if (!bandwidth->in.average &&
+        !bandwidth->out.average) {
+        /* nothing to be enabled */
+        ret = 0;
+        goto cleanup;
+    }
+
+    if (virBandwidthDisable(iface, true) < 0)
+        goto cleanup;
+
+    if (bandwidth->in.average) {
+        if (virBpsToRate(&average, bandwidth->in.average) < 0)
+            goto cleanup;
+        if (bandwidth->in.peak &&
+            (virBpsToRate(&peak, bandwidth->in.peak) < 0))
+            goto cleanup;
+        if (bandwidth->in.burst &&
+            (virBtoSize(&burst, bandwidth->in.burst) < 0))
+            goto cleanup;
+
+        cmd = virCommandNew(TC);
+        virCommandAddArgList(cmd, "qdisc", "add", "dev", iface, "root", "handle", "1:", "htb", "default", "1", NULL);
+        if (virCommandRun(cmd, NULL) < 0)
+            goto cleanup;
+
+        virCommandFree(cmd);
+        cmd = virCommandNew(TC);
+            virCommandAddArgList(cmd,"class", "add", "dev", iface, "parent", "1:", "classid", "1:1", "htb", NULL);
+        virCommandAddArgList(cmd, "rate", average, NULL);
+
+        if (peak)
+            virCommandAddArgList(cmd, "ceil", peak, NULL);
+        if (burst)
+            virCommandAddArgList(cmd, "burst", burst, NULL);
+
+        if (virCommandRun(cmd, NULL) < 0)
+            goto cleanup;
+
+        virCommandFree(cmd);
+        cmd = virCommandNew(TC);
+            virCommandAddArgList(cmd,"filter", "add", "dev", iface, "parent", "1:0", "protocol", "ip", "handle", "1", "fw", "flowid", "1", NULL);
+
+        if (virCommandRun(cmd, NULL) < 0)
+            goto cleanup;
+
+        virCommandFree(cmd);
+        VIR_FREE(average);
+        VIR_FREE(peak);
+        VIR_FREE(burst);
+    }
+
+    if (bandwidth->out.average) {
+        if (virBpsToRate(&average, bandwidth->out.average) < 0)
+            goto cleanup;
+        if (virBtoSize(&burst, bandwidth->out.burst ? bandwidth->out.burst : bandwidth->out.average) < 0)
+            goto cleanup;
+
+        cmd = virCommandNew(TC);
+            virCommandAddArgList(cmd, "qdisc", "add", "dev", iface, "ingress", NULL);
+
+        if (virCommandRun(cmd, NULL) < 0)
+            goto cleanup;
+
+        virCommandFree(cmd);
+        cmd = virCommandNew(TC);
+        virCommandAddArgList(cmd, "filter", "add", "dev", iface, "parent", "ffff:", "protocol", "ip", "u32", "match", "ip", "src", "0.0.0.0/0", "police", "rate", average, "burst", burst, "drop", "flowid", ":1", NULL);
+
+        if (virCommandRun(cmd, NULL) < 0)
+            goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    virCommandFree(cmd);
+    VIR_FREE(average);
+    VIR_FREE(peak);
+    VIR_FREE(burst);
+    return ret;
+}
+
+/**
+ * virBandwidthDisable:
+ * @iface: on which interface
+ * @may_fail: should be unsuccessful disable considered fatal?
+ *
+ * This function tries to disable QoS on specified interface
+ * by deleting root and ingress qdisc. However, this may fail
+ * if we try to remove the default one.
+ *
+ * Return 0 on success, -1 otherwise.
+ */
+int
+virBandwidthDisable(const char *iface,
+                    bool may_fail)
+{
+    int ret = -1;
+    int status;
+    virCommandPtr cmd = NULL;
+
+    if (!iface)
+        return -1;
+
+    cmd = virCommandNew(TC);
+    virCommandAddArgList(cmd, "qdisc", "del", "dev", iface, "root", NULL);
+
+    if ((virCommandRun(cmd, &status) < 0) ||
+        (!may_fail && status))
+        goto cleanup;
+
+    virCommandFree(cmd);
+
+    cmd = virCommandNew(TC);
+    virCommandAddArgList(cmd, "qdisc",  "del", "dev", iface, "ingress", NULL);
+
+    if ((virCommandRun(cmd, &status) < 0) ||
+        (!may_fail && status))
+        goto cleanup;
+
+    ret = 0;
+
+cleanup:
+    virCommandFree(cmd);
+    return ret;
+}
diff --git a/src/util/network.h b/src/util/network.h
index f8cdc55..5a88e51 100644
--- a/src/util/network.h
+++ b/src/util/network.h
@@ -115,4 +115,7 @@ int virBandwidrhDefFormat(virBufferPtr buf,
 
 int virBpsToRate(char **buf, unsigned long rate);
 int virBtoSize(char **buf, unsigned long size);
+
+int virBandwidthEnable(virBandwidthPtr bandwidth, const char *iface);
+int virBandwidthDisable(const char *iface, bool may_fail);
 #endif /* __VIR_NETWORK_H__ */
-- 
1.7.5.rc3

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]