From 01559528e5de106ae044eb753039385896265431 Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Thu, 8 Oct 2020 14:37:54 +0200 Subject: [PATCH] virnetdev: Introduce virNetDevSetRootQDisc() 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 Reviewed-by: Daniel Henrique Barboza --- 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 d773aee571..52e9c6313f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2580,6 +2580,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);