Features/VirtIORNG
Summary
VirtIO RNG is a paravirtualized device that is exposed as a hardware RNG device to the guest. On the host side, it can be wired up to one of several sources of entropy, including a real hardware RNG device as well as the host's /dev/random if hardware support doesn't exist.
Status
Support for the VirtIO RNG device has been added to the QEMU sources starting from commit a9b7b2ad7b075dba5495271706670e5c6b1304bc. This is part of the QEMU 1.3 release. The Linux kernel contains the guest driver for the device since version 2.6.26.
Invocation
Just adding
-device virtio-rng-pci
to the QEMU invocation will add the device with a default host backend. As of QEMU 1.3, the default backend is to use the host's /dev/random as a source of entropy.
To modify this source to a real hardware RNG on the host, use:
-object rng-random,filename=/dev/hwrng,id=rng0 \ -device virtio-rng-pci,rng=rng0
This passes on any data received from the hardware RNG (via /dev/hwrng) directly to the guest.
Optional parameters to limit the rate of data sent to the guest are inlucded:
-device virtio-rng-pci,max-bytes=1024,period=1000
This restricts the data sent to the guest at 1KB per second. This is useful to not let a guest starve the host of entropy.
Effect of the period parameter
(by Amos Kong <akong AT redhat.com>) When we set a fixed rate speed, we can use different periods. The period still effect the stable of system IO. If the period is too large, and we set a higher speed, then IO will wave. Example: the IO max speed is 20 M/s, and we test 5 mins it clear that the first period is better _Theory_ Condition: * period 1: 20M / 1s from 0 ~ 20 second, read packets, from 21 ~ 100 second, wait ... from 0 ~ 20 second, read packets, from 21 ~ 100 second, wait ... from 260 ~ 281 second, read packets, from 281 ~ 300 second, wait ... * period 2: 100M / 5 from 0 ~ 60 second, read packets, from 61 ~ 300 second, wait ... Smaller period is better, but smaller period will cause more timer expired, and IO wave will be balance by scheduling other process.
Communicating with the EGD Protocol
# ./readbytes (listen 1024 port, read data from some source, and send to remote client socket) # qemu-kvm ...... \ -chardev socket,host=10.66.4.212,port=1024,id=chr0 \ -object rng-egd,chardev=chr0,id=rng0 \ -device virtio-rng-pci,rng=rng0
usage of real rng device(QNG PQ4000KU)
Config the real rng device(QNG PQ4000KU), read data from the device by libqwqng API. Transfer data to qemu (w/ virt-rng EGD backend) by a socket.
More detail: Features/Real rng device
Testing
On the host
Test if the host device is opened when qemu is started. In the default case, when /dev/random is used, check the output of
lsof /dev/random
Before starting QEMU, the output of the previous command shouldn't show qemu. After starting the guest, the output of the command should show the qemu instance, like:
$ lsof /dev/random COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME qemu-syst 9075 amit 12r CHR 1,8 0t0 1032 /dev/random
On the guest
Check if the hardware RNG core has detected virtio-rng as a source of entropy:
$ cat /sys/devices/virtual/misc/hw_random/rng_available virtio
Check what is the current hwrng device in use by the kernel:
$ cat /sys/devices/virtual/misc/hw_random/rng_current virtio
If the current source is virtio, just reading from the hwrng device will fetch the data from the host:
# cat /dev/hwrng
Without virtio-rng, the /dev/hwrng file won't be available. With virtio-rng, the file will be available, and will show some output. Output may be slow to arrive, as this depends on the amount of entropy the host has to give. Doing mouse, keyboard, network, block activity on the host will accelerate the speed with which the host can give out data to the default /dev/random source.
Next, hook up the virtio-rng hwrng to the guest's entropy pool by running rngd:
# rngd -r /dev/hwrng
Compare the results of
$ cat /dev/random
inside a guest with and without the virtio rng device. The data should flow faster when the virtio rng device is present.
TODO
Intel CPUs will introduce an RDRAND instruction that can give random bytes. This instruction can be directly made available to guests, so the guests won't have to rely on virtio-rng. However, announcing the availability of the RDRAND instruction on the host may not be desirable due to live migration constraints. Using RDRAND on the host, if available, as a source of entropy to pass on to the guest via virtio-rng is better than the current /dev/random source. The RDSEED instruction, in a future Intel processor, will output real entropy (instead of just random numbers that the RDRAND outputs). Using RDSEED as a source is equivalent to using a real hardware rng. This has the advantage of not depleting the host's entropy pool, as well as passing real entropy to the guest instead of CSPRNG.
The performance rng-egd backend is very bad, the request queue doesn't work actually. Another request will come when the first request is processed by chr_read(). I have a solution to improve the performance, we can use a cache queue to pre-read randome data, when request is coming, it give quick feedback if the data is prepared. We can use the space time to fill the cache queue. In my testing, the read speed can be improved from 0.9k/s to 500k/s
More Information
There is some more information on this feature, and testing instructions at these links: