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);