Qemu's implementation of virtio RNG supports rate limiting of the
entropy used. This patch exposes the option to tune this functionality.
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:
Version 6:
- use just attributes in XML instead of mixed attribute/contents
- switch rate unit to bytes
- tweak the rest to comply with the changes
Version 5:
- adjust after forbiding arbitrary name passthrough
- rebase to master
Version 4:
- Reword docs
- state it is available since 1.0.4 as the tree is frozen and this was actually never
acked before
Version 3:
- State the time unit in docs
Version 2:
- qemu uses bytes/period, adapt the value according to that
docs/formatdomain.html.in | 13 +++++++++++++
docs/schemas/domaincommon.rng | 21 ++++++++++++++++++++-
src/conf/domain_conf.c | 19 +++++++++++++++++++
src/conf/domain_conf.h | 2 ++
src/qemu/qemu_command.c | 8 ++++++++
.../qemuxml2argv-virtio-rng-random.args | 2 +-
.../qemuxml2argv-virtio-rng-random.xml | 1 +
7 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 35b47f2..1ef80b0 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" bytes="1234"/>
<backend model='random'>/dev/random</backend>
<!-- OR -->
<backend model='egd' type='udp'>
@@ -4316,6 +4317,18 @@ 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 optional <code>rate</code> element allows limiting the rate at
+ which entropy can be consumed from the source. The mandatory
+ attribute <code>bytes</code> specifies how many bytes are
permitted
+ to be consumed per period. An optional <code>period</code>
attribute
+ specifies the duration of a period in milliseconds; if omitted, the
+ period is taken as 1000 milliseconds (1 second).
+ <span class='since'>Since 1.0.4</span>
+ </p>
+ </dd>
<dt><code>backend</code></dt>
<dd>
<p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index c40263c..9792065 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>
@@ -3550,6 +3555,20 @@
</element>
</define>
+ <define name="rng-rate">
+ <element name="rate">
+ <attribute name="bytes">
+ <ref name="positiveInteger"/>
+ </attribute>
+ <optional>
+ <attribute name="period">
+ <ref name="positiveInteger"/>
+ </attribute>
+ </optional>
+ <empty/>
+ </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 95d2ff2..3278e9c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -7570,6 +7570,19 @@ virDomainRNGDefParseXML(const xmlNodePtr node,
ctxt->node = node;
+ if (virXPathUInt("string(./rate/@bytes)", ctxt, &def->rate) < -1)
{
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("invalid RNG rate bytes value"));
+ goto error;
+ }
+
+ if (def->rate > 0 &&
+ virXPathUInt("string(./rate/@period)", ctxt, &def->period) <
-1) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("invalid RNG rate period value"));
+ goto error;
+ }
+
if ((nbackends = virXPathNodeSet("./backend", ctxt, &backends)) <
0)
goto error;
@@ -13897,6 +13910,12 @@ virDomainRNGDefFormat(virBufferPtr buf,
const char *backend = virDomainRNGBackendTypeToString(def->backend);
virBufferAsprintf(buf, " <rng model='%s'>\n", model);
+ if (def->rate) {
+ virBufferAsprintf(buf, " <rate bytes='%u'",
def->rate);
+ if (def->period)
+ virBufferAsprintf(buf, " period='%u'", def->period);
+ virBufferAddLit(buf, "/>\n");
+ }
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 0fe43c5..96f11ba 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; /* bytes per period */
+ unsigned int period; /* milliseconds */
union {
char *file; /* file name for 'random' source */
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index e7f2325..78c5cfc 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4492,6 +4492,14 @@ qemuBuildRNGDeviceArgs(virCommandPtr cmd,
virBufferAsprintf(&buf, "virtio-rng-pci,rng=%s", dev->info.alias);
+ if (dev->rate > 0) {
+ virBufferAsprintf(&buf, ",max-bytes=%u", dev->rate);
+ 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 7ab9dbc..5d296e8 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.args
@@ -3,4 +3,4 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
-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=/dev/hwrng \
--device virtio-rng-pci,rng=rng0,bus=pci.0,addr=0x4
+-device virtio-rng-pci,rng=rng0,max-bytes=123,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 1e2c4be..354ae42 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 bytes='123' period='1234'/>
<backend model='random'>/dev/hwrng</backend>
</rng>
</devices>
--
1.8.1.5