Qemu's implementation of virtio RNG supports rate limiting of the
entropy used. This patch exposes the option to tune this fucntionality.
This patch is based on qemu commit 904d6f588063fb5ad2b61998acdf1e73fb4
The rate limiting is exported in the XML as:
<devices>
...
<rng model='virtio'>
<rate period='1234'>4321</rate>
<backend model='random'/>
</rng>
...
---
Notes:
This series would benefit from the per-driver XML parsing checks to verify
that rate > 8bits, otherwise it will be rounded down to 0 bytes. I will
follow up with that change as soon as the per-driver callbacks get in.
Version 3:
- State the time unit in docs
Version 2:
- Qemu uses bytes/period, adapt the value according to that
docs/formatdomain.html.in | 10 ++++++++++
docs/schemas/domaincommon.rng | 18 +++++++++++++++++-
src/conf/domain_conf.c | 17 +++++++++++++++++
src/conf/domain_conf.h | 2 ++
src/qemu/qemu_command.c | 9 +++++++++
.../qemuxml2argv-virtio-rng-random.args | 2 +-
.../qemuxml2argv-virtio-rng-random.xml | 1 +
7 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 2a60f61..220884c 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -4294,6 +4294,7 @@ qemu-kvm -net nic,model=? /dev/null
...
<devices>
<rng model='virtio'>
+ <rate period="2000">1234</rate>
<backend model='random'>/dev/random</backend>
<!-- OR -->
<backend model='egd' type='udp'>
@@ -4316,6 +4317,15 @@ qemu-kvm -net nic,model=? /dev/null
<li>'virtio' — supported by qemu and virtio-rng kernel
module</li>
</ul>
</dd>
+ <dt><code>rate</code></dt>
+ <dd>
+ <p>
+ The rate element allows to limit the rate that the entropy can be
+ read from the source. The value is in bits that the device is allowed
+ to read in the selected period. The period is represented in miliseconds.
+ The default period is 1000ms or 1 second.
+ </p>
+ </dd>
<dt><code>backend</code></dt>
<dd>
<p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 8330a50..da53095 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3522,7 +3522,12 @@
<value>virtio</value>
</choice>
</attribute>
- <ref name="rng-backend"/>
+ <interleave>
+ <ref name="rng-backend"/>
+ <optional>
+ <ref name="rng-rate"/>
+ </optional>
+ </interleave>
</element>
</define>
@@ -3546,6 +3551,17 @@
</element>
</define>
+ <define name="rng-rate">
+ <element name="rate">
+ <optional>
+ <attribute name="period">
+ <ref name="positiveInteger"/>
+ </attribute>
+ </optional>
+ <ref name="positiveInteger"/>
+ </element>
+ </define>
+
<define name="usbmaster">
<element name="master">
<attribute name="startport">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 40eded6..0e2f1a9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -7506,6 +7506,17 @@ virDomainRNGDefParseXML(const xmlNodePtr node,
ctxt->node = node;
+ if (virXPathUInt("string(./rate)", ctxt, &def->rate) < -1) {
+ virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid RNG rate
value"));
+ goto error;
+ }
+
+ if (def->rate > 0 &&
+ virXPathUInt("string(./rate/@period)", ctxt, &def->period) <
-1) {
+ virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid RNG period
value"));
+ goto error;
+ }
+
if ((nbackends = virXPathNodeSet("./backend", ctxt, &backends)) <
0)
goto error;
@@ -13812,6 +13823,12 @@ virDomainRNGDefFormat(virBufferPtr buf,
const char *backend = virDomainRNGBackendTypeToString(def->backend);
virBufferAsprintf(buf, " <rng model='%s'>\n", model);
+ if (def->rate) {
+ virBufferAddLit(buf, " <rate");
+ if (def->period)
+ virBufferAsprintf(buf, " period='%u'", def->period);
+ virBufferAsprintf(buf, ">%u</rate>\n", def->rate);
+ }
virBufferAsprintf(buf, " <backend model='%s'", backend);
switch ((enum virDomainRNGBackend) def->backend) {
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 5dc3400..92130f0 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1736,6 +1736,8 @@ enum virDomainRNGBackend {
struct _virDomainRNGDef {
int model;
int backend;
+ unsigned int rate;
+ unsigned int period;
union {
char *file; /* file name for 'random' source */
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 9270258..4899ccf 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4256,6 +4256,15 @@ qemuBuildRNGDeviceArgs(virCommandPtr cmd,
virBufferAsprintf(&buf, "virtio-rng-pci,rng=%s", dev->info.alias);
+ if (dev->rate > 0) {
+ /* qemu uses bytes */
+ virBufferAsprintf(&buf, ",max-bytes=%u", dev->rate / 8);
+ if (dev->period)
+ virBufferAsprintf(&buf, ",period=%u", dev->period);
+ else
+ virBufferAddLit(&buf, ",period=1000");
+ }
+
if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0)
goto cleanup;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.args
b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.args
index 4611ae5..ced11db 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.args
@@ -1 +1 @@
-LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214
-smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot
c -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 -object
rng-random,id=rng0,filename=/test/phile -device
virtio-rng-pci,rng=rng0,bus=pci.0,addr=0x4
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214
-smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot
c -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 -object
rng-random,id=rng0,filename=/test/phile -device
virtio-rng-pci,rng=rng0,max-bytes=100,period=1234,bus=pci.0,addr=0x4
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.xml
b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.xml
index ab1f38c..26ddd38 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.xml
@@ -17,6 +17,7 @@
<controller type='usb' index='0'/>
<memballoon model='virtio'/>
<rng model='virtio'>
+ <rate period='1234'>800</rate>
<backend model='random'>/test/phile</backend>
</rng>
</devices>
--
1.8.1.1