This helper changes the root qdisc on given interface.
Ideally, it would be written using netlink but my attempts to
write the code were not successful and thus I've fallen back to
virCommand() + tc.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virnetdev.c | 46 ++++++++++++++++++++++++++++++++++++++++
src/util/virnetdev.h | 3 +++
3 files changed, 50 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 7cf8bea962..0778bc6d5b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2581,6 +2581,7 @@ virNetDevSetOnline;
virNetDevSetPromiscuous;
virNetDevSetRcvAllMulti;
virNetDevSetRcvMulti;
+virNetDevSetRootQDisc;
virNetDevSetupControl;
virNetDevSysfsFile;
virNetDevValidateConfig;
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index e711a6dc8a..5c7660dab4 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -3394,3 +3394,49 @@ virNetDevRunEthernetScript(const char *ifname, const char *script)
return virCommandRun(cmd, NULL);
}
+
+
+/**
+ * virNetDevSetRootQDisc:
+ * @ifname: the interface name
+ * @qdisc: queueing discipline to set
+ *
+ * For given interface @ifname set its root queueing discipline
+ * to @qdisc. This can be used to replace the default qdisc
+ * (usually pfifo_fast or whatever is set in
+ * /proc/sys/net/core/default_qdisc) with different qdisc.
+ *
+ * Returns: 0 on success,
+ * -1 if failed to exec tc (with error reported)
+ * -2 if tc failed (with no error reported)
+ */
+int
+virNetDevSetRootQDisc(const char *ifname,
+ const char *qdisc)
+{
+ g_autoptr(virCommand) cmd = NULL;
+ g_autofree char *outbuf = NULL;
+ g_autofree char *errbuf = NULL;
+ int status;
+
+ /* Ideally, we would have a netlink implementation and just
+ * call it here. But honestly, I tried and failed miserably.
+ * Fallback to spawning tc. */
+ cmd = virCommandNewArgList(TC, "qdisc", "add", "dev",
ifname,
+ "root", "handle", "0:",
qdisc,
+ NULL);
+
+ virCommandAddEnvString(cmd, "LC_ALL=C");
+ virCommandSetOutputBuffer(cmd, &outbuf);
+ virCommandSetErrorBuffer(cmd, &errbuf);
+
+ if (virCommandRun(cmd, &status) < 0)
+ return -1;
+
+ if (status != 0) {
+ VIR_DEBUG("Setting qdisc failed: output='%s' err='%s'",
outbuf, errbuf);
+ return -2;
+ }
+
+ return 0;
+}
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
index 5f581323ed..82943b8e08 100644
--- a/src/util/virnetdev.h
+++ b/src/util/virnetdev.h
@@ -312,4 +312,7 @@ int virNetDevSysfsFile(char **pf_sysfs_device_link,
int virNetDevRunEthernetScript(const char *ifname, const char *script)
G_GNUC_NO_INLINE;
+int virNetDevSetRootQDisc(const char *ifname,
+ const char *qdisc);
+
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virNetDevRxFilter, virNetDevRxFilterFree);
--
2.26.2