diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 35b47f2dd7..1ef80b06ca 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
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index c40263c76b..97920653df 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3522,7 +3522,12 @@
virtio
-
+
+
+
+
+
+
@@ -3550,6 +3555,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 95d2ff22b8..3278e9c15e 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, " \n", model);
+ if (def->rate) {
+ virBufferAsprintf(buf, " rate);
+ if (def->period)
+ virBufferAsprintf(buf, " period='%u'", def->period);
+ virBufferAddLit(buf, "/>\n");
+ }
virBufferAsprintf(buf, " backend) {
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 0fe43c5869..96f11ba76d 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 e7f232579a..78c5cfc4f5 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 7ab9dbc0c0..5d296e825e 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 1e2c4be95a..354ae42932 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.xml
@@ -17,6 +17,7 @@
+
/dev/hwrng