[libvirt] [PATCH 0/2] Xen: Support vif outging bandwidth QoS

Happy Holidays! :-) This small series adds support for specifying vif outgoing rate limits in Xen. The first patch adds support for converting rate limits between xl/xm config and domXML, along with introducing a test for the conversion logic. The second patch adds outgoing rate limiting to the libxl driver. Jim Fehlig (2): xenconfig: support parsing and formatting vif bandwidth libxl: support vif outgoing bandwidth QoS src/libxl/libxl_conf.c | 39 ++++++++++++++++++ src/xenconfig/xen_common.c | 77 ++++++++++++++++++++++++++++++++++++ tests/xlconfigdata/test-vif-rate.cfg | 26 ++++++++++++ tests/xlconfigdata/test-vif-rate.xml | 57 ++++++++++++++++++++++++++ tests/xlconfigtest.c | 1 + 5 files changed, 200 insertions(+) create mode 100644 tests/xlconfigdata/test-vif-rate.cfg create mode 100644 tests/xlconfigdata/test-vif-rate.xml -- 2.1.4

Both xm and xl config have long supported specifying vif rate limiting, e.g. vif = [ 'mac=00:16:3E:74:3d:76,bridge=br0,rate=10MB/s' ] Add support for mapping rate to and from <bandwidth> in the xenconfig parser and formatter. rate is mapped to the required 'average' attribute of the <outbound> element, e.g. <interface type='bridge'> ... <bandwidth> <outbound average='10240'/> </bandwidth> </interface> Also add a unit test to check the conversion logic. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- I used a bit of code from libxlu_vif.c to implement xenParseVifRate() instead of using the libxlutil lib directly, since in theory rate limiting applies to the old xen driver (no libxl) as well. src/xenconfig/xen_common.c | 77 ++++++++++++++++++++++++++++++++++++ tests/xlconfigdata/test-vif-rate.cfg | 26 ++++++++++++ tests/xlconfigdata/test-vif-rate.xml | 57 ++++++++++++++++++++++++++ tests/xlconfigtest.c | 1 + 4 files changed, 161 insertions(+) diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index 54f5791..b9f0344 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -28,6 +28,8 @@ #include <config.h> +#include <regex.h> + #include "internal.h" #include "virerror.h" #include "virconf.h" @@ -803,6 +805,46 @@ xenParseCharDev(virConfPtr conf, virDomainDefPtr def) } +static const char *vif_bytes_per_sec_re = "^[0-9]+[GMK]?[Bb]/s$"; + +static int +xenParseVifRate(char *rate, unsigned long long *kbytes_per_sec) +{ + regex_t rec; + char *suffix; + unsigned long long tmp; + int ret = -1; + + regcomp(&rec, vif_bytes_per_sec_re, REG_EXTENDED|REG_NOSUB); + if (regexec(&rec, rate, 0, NULL, 0)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid rate '%s' specified"), rate); + goto cleanup; + } + + if (virStrToLong_ull(rate, &suffix, 10, &tmp)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to parse rate '%s'"), rate); + goto cleanup; + } + + if (*suffix == 'G') + tmp *= 1024 * 1024; + else if (*suffix == 'M') + tmp *= 1024; + + if (*suffix == 'b' || *(suffix + 1) == 'b') + tmp /= 8; + + *kbytes_per_sec = tmp; + ret = 0; + + cleanup: + regfree(&rec); + return ret; +} + + static int xenParseVif(virConfPtr conf, virDomainDefPtr def) { @@ -819,6 +861,7 @@ xenParseVif(virConfPtr conf, virDomainDefPtr def) char mac[18]; char bridge[50]; char vifname[50]; + char rate[50]; char *key; bridge[0] = '\0'; @@ -827,6 +870,7 @@ xenParseVif(virConfPtr conf, virDomainDefPtr def) model[0] = '\0'; type[0] = '\0'; vifname[0] = '\0'; + rate[0] = '\0'; if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) goto skipnic; @@ -892,6 +936,13 @@ xenParseVif(virConfPtr conf, virDomainDefPtr def) _("IP %s too big for destination"), data); goto skipnic; } + } else if (STRPREFIX(key, "rate=")) { + int len = nextkey ? (nextkey - data) : sizeof(rate) - 1; + if (virStrncpy(rate, data, len, sizeof(rate)) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("rate %s too big for destination"), data); + goto skipnic; + } } while (nextkey && (nextkey[0] == ',' || @@ -942,6 +993,29 @@ xenParseVif(virConfPtr conf, virDomainDefPtr def) VIR_STRDUP(net->ifname, vifname) < 0) goto cleanup; + if (rate[0]) { + char *p; + virNetDevBandwidthPtr bandwidth; + unsigned long long kbytes_per_sec; + + p = strchr(rate, '@'); + if (p != NULL) + *p = 0; + + if (xenParseVifRate(rate, &kbytes_per_sec) < 0) + goto cleanup; + + if (VIR_ALLOC(bandwidth) < 0) + goto cleanup; + if (VIR_ALLOC(bandwidth->out) < 0) { + VIR_FREE(bandwidth); + goto cleanup; + } + + bandwidth->out->average = kbytes_per_sec; + net->bandwidth = bandwidth; + } + if (VIR_APPEND_ELEMENT(def->nets, def->nnets, net) < 0) goto cleanup; @@ -1184,6 +1258,9 @@ xenFormatNet(virConnectPtr conn, virBufferAsprintf(&buf, ",vifname=%s", net->ifname); + if (net->bandwidth && net->bandwidth->out && net->bandwidth->out->average) + virBufferAsprintf(&buf, ",rate=%lluKB/s", net->bandwidth->out->average); + if (virBufferCheckError(&buf) < 0) goto cleanup; diff --git a/tests/xlconfigdata/test-vif-rate.cfg b/tests/xlconfigdata/test-vif-rate.cfg new file mode 100644 index 0000000..c5484dc --- /dev/null +++ b/tests/xlconfigdata/test-vif-rate.cfg @@ -0,0 +1,26 @@ +name = "XenGuest2" +uuid = "c7a5fdb2-cdaf-9455-926a-d65c16db1809" +maxmem = 579 +memory = 394 +vcpus = 1 +pae = 1 +acpi = 1 +apic = 1 +hap = 0 +viridian = 0 +rtc_timeoffset = 0 +localtime = 0 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +device_model = "/usr/lib/xen/bin/qemu-dm" +sdl = 0 +vnc = 1 +vncunused = 1 +vnclisten = "127.0.0.1" +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000,rate=10240KB/s" ] +parallel = "none" +serial = "none" +builder = "hvm" +boot = "d" +disk = [ "/dev/HostVG/XenGuest2,raw,hda,w,backendtype=phy", "/var/lib/libvirt/images/XenGuest2-home,qcow2,hdb,w,backendtype=qdisk", "/root/boot.iso,raw,hdc,r,backendtype=qdisk,devtype=cdrom" ] diff --git a/tests/xlconfigdata/test-vif-rate.xml b/tests/xlconfigdata/test-vif-rate.xml new file mode 100644 index 0000000..29f0f79 --- /dev/null +++ b/tests/xlconfigdata/test-vif-rate.xml @@ -0,0 +1,57 @@ +<domain type='xen'> + <name>XenGuest2</name> + <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>592896</memory> + <currentMemory unit='KiB'>403456</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> + <boot dev='cdrom'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='variable' adjustment='0' basis='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <disk type='block' device='disk'> + <driver name='phy' type='raw'/> + <source dev='/dev/HostVG/XenGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/var/lib/libvirt/images/XenGuest2-home'/> + <target dev='hdb' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='1'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/root/boot.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + <address type='drive' controller='0' bus='1' target='0' unit='0'/> + </disk> + <interface type='bridge'> + <mac address='00:16:3e:66:92:9c'/> + <source bridge='xenbr1'/> + <bandwidth> + <outbound average='10240'/> + </bandwidth> + <script path='vif-bridge'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + </devices> +</domain> diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c index 1db11e7..e997009 100644 --- a/tests/xlconfigtest.c +++ b/tests/xlconfigtest.c @@ -196,6 +196,7 @@ mymain(void) DO_TEST("new-disk"); DO_TEST("spice"); DO_TEST("spice-features"); + DO_TEST("vif-rate"); #ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST DO_TEST("fullvirt-multiusb"); -- 2.1.4

On 29.12.2015 02:09, Jim Fehlig wrote:
Both xm and xl config have long supported specifying vif rate limiting, e.g.
vif = [ 'mac=00:16:3E:74:3d:76,bridge=br0,rate=10MB/s' ]
Add support for mapping rate to and from <bandwidth> in the xenconfig parser and formatter. rate is mapped to the required 'average' attribute of the <outbound> element, e.g.
<interface type='bridge'> ... <bandwidth> <outbound average='10240'/> </bandwidth> </interface>
Also add a unit test to check the conversion logic.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
I used a bit of code from libxlu_vif.c to implement xenParseVifRate() instead of using the libxlutil lib directly, since in theory rate limiting applies to the old xen driver (no libxl) as well.
src/xenconfig/xen_common.c | 77 ++++++++++++++++++++++++++++++++++++ tests/xlconfigdata/test-vif-rate.cfg | 26 ++++++++++++ tests/xlconfigdata/test-vif-rate.xml | 57 ++++++++++++++++++++++++++ tests/xlconfigtest.c | 1 + 4 files changed, 161 insertions(+)
ACK Michal

On 01/07/2016 07:48 AM, Michal Privoznik wrote:
On 29.12.2015 02:09, Jim Fehlig wrote:
Both xm and xl config have long supported specifying vif rate limiting, e.g.
vif = [ 'mac=00:16:3E:74:3d:76,bridge=br0,rate=10MB/s' ]
Add support for mapping rate to and from <bandwidth> in the xenconfig parser and formatter. rate is mapped to the required 'average' attribute of the <outbound> element, e.g.
<interface type='bridge'> ... <bandwidth> <outbound average='10240'/> </bandwidth> </interface>
Also add a unit test to check the conversion logic.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
I used a bit of code from libxlu_vif.c to implement xenParseVifRate() instead of using the libxlutil lib directly, since in theory rate limiting applies to the old xen driver (no libxl) as well.
src/xenconfig/xen_common.c | 77 ++++++++++++++++++++++++++++++++++++ tests/xlconfigdata/test-vif-rate.cfg | 26 ++++++++++++ tests/xlconfigdata/test-vif-rate.xml | 57 ++++++++++++++++++++++++++ tests/xlconfigtest.c | 1 + 4 files changed, 161 insertions(+) ACK
Hi Michal, Thanks a lot for taking a look at this series! Note that I posted a V2 earlier this week which includes support for parsing/formatting vif bandwidth in sexpr config too https://www.redhat.com/archives/libvir-list/2016-January/msg00045.html Unfortunately it results in some changes to this patch, so I think it would be best to peek at the V2 series before pushing it. Regards, Jim

The libxl_device_nic structure supports specifying an outgoing rate limit based on a time interval and bytes allowed per interval. In xl config a rate limit is specified as "<RATE>/s@<INTERVAL>". INTERVAL is optional and defaults to 50ms. libvirt expresses outgoing limits by average (required), peak, burst, and floor attributes in units of KB/s. This patch supports the outgoing bandwidth limit by converting the average KB/s to bytes per interval based on the same default interval (50ms) used by xl. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_conf.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 23c74e7..6320421 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1093,6 +1093,7 @@ libxlMakeNic(virDomainDefPtr def, { bool ioemu_nic = def->os.type == VIR_DOMAIN_OSTYPE_HVM; virDomainNetType actual_type = virDomainNetGetActualType(l_nic); + virNetDevBandwidthPtr actual_bw; /* TODO: Where is mtu stored? * @@ -1206,6 +1207,44 @@ libxlMakeNic(virDomainDefPtr def, #endif } + /* + * Set bandwidth. + * From $xen-sources/docs/misc/xl-network-configuration.markdown: + * + * + * Specifies the rate at which the outgoing traffic will be limited to. + * The default if this keyword is not specified is unlimited. + * + * The rate may be specified as "<RATE>/s" or optionally "<RATE>/s@<INTERVAL>". + * + * `RATE` is in bytes and can accept suffixes: + * GB, MB, KB, B for bytes. + * Gb, Mb, Kb, b for bits. + * `INTERVAL` is in microseconds and can accept suffixes: ms, us, s. + * It determines the frequency at which the vif transmission credit + * is replenished. The default is 50ms. + + * Vif rate limiting is credit-based. It means that for "1MB/s@20ms", + * the available credit will be equivalent of the traffic you would have + * done at "1MB/s" during 20ms. This will results in a credit of 20,000 + * bytes replenished every 20,000 us. + * + * + * libvirt doesn't support the notion of rate limiting over an interval. + * Similar to xl's behavior when interval is not specified, set a default + * interval of 50ms and calculate the number of bytes per interval based + * on the specified average bandwidth. + */ + actual_bw = virDomainNetGetActualBandwidth(l_nic); + if (actual_bw && actual_bw->out && actual_bw->out->average) { + uint64_t bytes_per_sec = actual_bw->out->average * 1024; + uint64_t bytes_per_interval = + (((uint64_t) bytes_per_sec * 50000UL) / 1000000UL); + + x_nic->rate_bytes_per_interval = bytes_per_interval; + x_nic->rate_interval_usecs = 50000UL; + } + return 0; } -- 2.1.4

On 29.12.2015 02:09, Jim Fehlig wrote:
The libxl_device_nic structure supports specifying an outgoing rate limit based on a time interval and bytes allowed per interval. In xl config a rate limit is specified as "<RATE>/s@<INTERVAL>". INTERVAL is optional and defaults to 50ms.
libvirt expresses outgoing limits by average (required), peak, burst, and floor attributes in units of KB/s. This patch supports the outgoing bandwidth limit by converting the average KB/s to bytes per interval based on the same default interval (50ms) used by xl.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_conf.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 23c74e7..6320421 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1093,6 +1093,7 @@ libxlMakeNic(virDomainDefPtr def, { bool ioemu_nic = def->os.type == VIR_DOMAIN_OSTYPE_HVM; virDomainNetType actual_type = virDomainNetGetActualType(l_nic); + virNetDevBandwidthPtr actual_bw;
/* TODO: Where is mtu stored? * @@ -1206,6 +1207,44 @@ libxlMakeNic(virDomainDefPtr def, #endif }
+ /* + * Set bandwidth. + * From $xen-sources/docs/misc/xl-network-configuration.markdown: + * + * + * Specifies the rate at which the outgoing traffic will be limited to. + * The default if this keyword is not specified is unlimited. + * + * The rate may be specified as "<RATE>/s" or optionally "<RATE>/s@<INTERVAL>". + * + * `RATE` is in bytes and can accept suffixes: + * GB, MB, KB, B for bytes. + * Gb, Mb, Kb, b for bits. + * `INTERVAL` is in microseconds and can accept suffixes: ms, us, s. + * It determines the frequency at which the vif transmission credit + * is replenished. The default is 50ms. + + * Vif rate limiting is credit-based. It means that for "1MB/s@20ms", + * the available credit will be equivalent of the traffic you would have + * done at "1MB/s" during 20ms. This will results in a credit of 20,000 + * bytes replenished every 20,000 us. + * + * + * libvirt doesn't support the notion of rate limiting over an interval. + * Similar to xl's behavior when interval is not specified, set a default + * interval of 50ms and calculate the number of bytes per interval based + * on the specified average bandwidth. + */ + actual_bw = virDomainNetGetActualBandwidth(l_nic); + if (actual_bw && actual_bw->out && actual_bw->out->average) { + uint64_t bytes_per_sec = actual_bw->out->average * 1024; + uint64_t bytes_per_interval = + (((uint64_t) bytes_per_sec * 50000UL) / 1000000UL); + + x_nic->rate_bytes_per_interval = bytes_per_interval; + x_nic->rate_interval_usecs = 50000UL; + } +
Interesting. I'd expect: x_nic->rate_bytes_per_interval = bytes_per_sec; x_nic->rate_interval_usecs = 1000*1000; I mean, if I understood the xl way of rate limiting correctly, one says how much bytes can be sent for how long. so for 1MB/s I'd expect to send 1024*1024 bytes each second. Or am I missing something? Michal

On 01/07/2016 07:48 AM, Michal Privoznik wrote:
On 29.12.2015 02:09, Jim Fehlig wrote:
The libxl_device_nic structure supports specifying an outgoing rate limit based on a time interval and bytes allowed per interval. In xl config a rate limit is specified as "<RATE>/s@<INTERVAL>". INTERVAL is optional and defaults to 50ms.
libvirt expresses outgoing limits by average (required), peak, burst, and floor attributes in units of KB/s. This patch supports the outgoing bandwidth limit by converting the average KB/s to bytes per interval based on the same default interval (50ms) used by xl.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_conf.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 23c74e7..6320421 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1093,6 +1093,7 @@ libxlMakeNic(virDomainDefPtr def, { bool ioemu_nic = def->os.type == VIR_DOMAIN_OSTYPE_HVM; virDomainNetType actual_type = virDomainNetGetActualType(l_nic); + virNetDevBandwidthPtr actual_bw;
/* TODO: Where is mtu stored? * @@ -1206,6 +1207,44 @@ libxlMakeNic(virDomainDefPtr def, #endif }
+ /* + * Set bandwidth. + * From $xen-sources/docs/misc/xl-network-configuration.markdown: + * + * + * Specifies the rate at which the outgoing traffic will be limited to. + * The default if this keyword is not specified is unlimited. + * + * The rate may be specified as "<RATE>/s" or optionally "<RATE>/s@<INTERVAL>". + * + * `RATE` is in bytes and can accept suffixes: + * GB, MB, KB, B for bytes. + * Gb, Mb, Kb, b for bits. + * `INTERVAL` is in microseconds and can accept suffixes: ms, us, s. + * It determines the frequency at which the vif transmission credit + * is replenished. The default is 50ms. + + * Vif rate limiting is credit-based. It means that for "1MB/s@20ms", + * the available credit will be equivalent of the traffic you would have + * done at "1MB/s" during 20ms. This will results in a credit of 20,000 + * bytes replenished every 20,000 us. + * + * + * libvirt doesn't support the notion of rate limiting over an interval. + * Similar to xl's behavior when interval is not specified, set a default + * interval of 50ms and calculate the number of bytes per interval based + * on the specified average bandwidth. + */ + actual_bw = virDomainNetGetActualBandwidth(l_nic); + if (actual_bw && actual_bw->out && actual_bw->out->average) { + uint64_t bytes_per_sec = actual_bw->out->average * 1024; + uint64_t bytes_per_interval = + (((uint64_t) bytes_per_sec * 50000UL) / 1000000UL); + + x_nic->rate_bytes_per_interval = bytes_per_interval; + x_nic->rate_interval_usecs = 50000UL; + } + Interesting. I'd expect:
x_nic->rate_bytes_per_interval = bytes_per_sec; x_nic->rate_interval_usecs = 1000*1000;
For the most part I mimicked the Xen code and wanted to stick with the default interval of 50ms, which has been the default for a long time. It is even mentioned in some old RHEL5 docs https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/5/htm... BTW, here is the Xen code that inspired this logic http://xenbits.xen.org/gitweb/?p=xen.git;a=blob;f=tools/libxl/libxlu_vif.c;h... rate_bytes_per_interval is set to (bytes/s * interval us)/1000000us I guess we are saying the same thing, you're just setting interval to 1s (thus rate_bytes_per_interval == bytes_per_sec) instead of the historical 50ms :-).
I mean, if I understood the xl way of rate limiting correctly, one says how much bytes can be sent for how long. so for 1MB/s I'd expect to send 1024*1024 bytes each second.
Or am I missing something?
Does the above explanation make sense? I might be missing something :-). CC'd a few Xen tools maintainer just in case. Regards, Jim

On 08.01.2016 06:11, Jim Fehlig wrote:
On 01/07/2016 07:48 AM, Michal Privoznik wrote:
On 29.12.2015 02:09, Jim Fehlig wrote:
The libxl_device_nic structure supports specifying an outgoing rate limit based on a time interval and bytes allowed per interval. In xl config a rate limit is specified as "<RATE>/s@<INTERVAL>". INTERVAL is optional and defaults to 50ms.
libvirt expresses outgoing limits by average (required), peak, burst, and floor attributes in units of KB/s. This patch supports the outgoing bandwidth limit by converting the average KB/s to bytes per interval based on the same default interval (50ms) used by xl.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_conf.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 23c74e7..6320421 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1093,6 +1093,7 @@ libxlMakeNic(virDomainDefPtr def, { bool ioemu_nic = def->os.type == VIR_DOMAIN_OSTYPE_HVM; virDomainNetType actual_type = virDomainNetGetActualType(l_nic); + virNetDevBandwidthPtr actual_bw;
/* TODO: Where is mtu stored? * @@ -1206,6 +1207,44 @@ libxlMakeNic(virDomainDefPtr def, #endif }
+ /* + * Set bandwidth. + * From $xen-sources/docs/misc/xl-network-configuration.markdown: + * + * + * Specifies the rate at which the outgoing traffic will be limited to. + * The default if this keyword is not specified is unlimited. + * + * The rate may be specified as "<RATE>/s" or optionally "<RATE>/s@<INTERVAL>". + * + * `RATE` is in bytes and can accept suffixes: + * GB, MB, KB, B for bytes. + * Gb, Mb, Kb, b for bits. + * `INTERVAL` is in microseconds and can accept suffixes: ms, us, s. + * It determines the frequency at which the vif transmission credit + * is replenished. The default is 50ms. + + * Vif rate limiting is credit-based. It means that for "1MB/s@20ms", + * the available credit will be equivalent of the traffic you would have + * done at "1MB/s" during 20ms. This will results in a credit of 20,000 + * bytes replenished every 20,000 us. + * + * + * libvirt doesn't support the notion of rate limiting over an interval. + * Similar to xl's behavior when interval is not specified, set a default + * interval of 50ms and calculate the number of bytes per interval based + * on the specified average bandwidth. + */ + actual_bw = virDomainNetGetActualBandwidth(l_nic); + if (actual_bw && actual_bw->out && actual_bw->out->average) { + uint64_t bytes_per_sec = actual_bw->out->average * 1024; + uint64_t bytes_per_interval = + (((uint64_t) bytes_per_sec * 50000UL) / 1000000UL); + + x_nic->rate_bytes_per_interval = bytes_per_interval; + x_nic->rate_interval_usecs = 50000UL; + } + Interesting. I'd expect:
x_nic->rate_bytes_per_interval = bytes_per_sec; x_nic->rate_interval_usecs = 1000*1000;
For the most part I mimicked the Xen code and wanted to stick with the default interval of 50ms, which has been the default for a long time. It is even mentioned in some old RHEL5 docs
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/5/htm...
BTW, here is the Xen code that inspired this logic
http://xenbits.xen.org/gitweb/?p=xen.git;a=blob;f=tools/libxl/libxlu_vif.c;h...
rate_bytes_per_interval is set to (bytes/s * interval us)/1000000us
I guess we are saying the same thing, you're just setting interval to 1s (thus rate_bytes_per_interval == bytes_per_sec) instead of the historical 50ms :-).
I mean, if I understood the xl way of rate limiting correctly, one says how much bytes can be sent for how long. so for 1MB/s I'd expect to send 1024*1024 bytes each second.
Or am I missing something?
Does the above explanation make sense? I might be missing something :-). CC'd a few Xen tools maintainer just in case.
Yep, it makes sense now. So let me review v2. Michal
participants (2)
-
Jim Fehlig
-
Michal Privoznik