virnetdevbandwidth: Don't generate burst outside of boundaries

When generating TC rules for domain's outbound traffic, Libvirt
will use the 'average' as the default for 'burst' - it's been
this way since the feature introduction in v0.9.4-rc1~22. The
reason is that 'average' considers 'burst' for policing. However,
when parsing its command line TC uses an unsigned int (with
overflow detection) to store the 'burst' size. This means, that
the upper limit for the value is UINT_MAX, well UINT_MAX / 1024
because we are putting the value in KiB onto the command line.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1912210
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Laine Stump <laine@redhat.com>
This commit is contained in:
Michal Privoznik 2021-03-05 10:13:36 +01:00
parent 6564cb01e1
commit 01e206c3e3
2 changed files with 26 additions and 1 deletions

View File

@ -358,7 +358,17 @@ virNetDevBandwidthSet(const char *ifname,
if (rx) {
average = g_strdup_printf("%llukbps", rx->average);
burst = g_strdup_printf("%llukb", rx->burst ? rx->burst : rx->average);
if (rx->burst) {
burst = g_strdup_printf("%llukb", rx->burst);
} else {
/* Internally, tc uses uint to store burst size (in bytes).
* Therefore, the largest value we can set is UINT_MAX bytes.
* We're outputting the vale in KiB though. */
unsigned long long avg = MIN(rx->average, UINT_MAX / 1024);
burst = g_strdup_printf("%llukb", avg);
}
virCommandFree(cmd);
cmd = virCommandNew(TC);

View File

@ -156,6 +156,21 @@ mymain(void)
TC " filter add dev eth0 parent ffff: protocol all u32 match u32 0 0 "
"police rate 5kbps burst 7kb mtu 64kb drop flowid :1\n"));
DO_TEST_SET(("<bandwidth>"
" <inbound average='4294967295'/>"
" <outbound average='4294967295'/>"
"</bandwidth>"),
(TC " qdisc del dev eth0 root\n"
TC " qdisc del dev eth0 ingress\n"
TC " qdisc add dev eth0 root handle 1: htb default 1\n"
TC " class add dev eth0 parent 1: classid 1:1 htb rate 4294967295kbps quantum 366503875\n"
TC " qdisc add dev eth0 parent 1:1 handle 2: sfq perturb 10\n"
TC " filter add dev eth0 parent 1:0 protocol all prio 1 handle 1 fw flowid 1\n"
TC " qdisc add dev eth0 ingress\n"
TC " filter add dev eth0 parent ffff: protocol all u32 match "
"u32 0 0 police rate 4294967295kbps burst 4194303kb mtu 64kb "
"drop flowid :1\n"));
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}