]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - Documentation/lguest/lguest.c
lguest: Tell Guest net not to notify us on every packet xmit
[linux-2.6-omap-h63xx.git] / Documentation / lguest / lguest.c
index 3be8ab2a886acf98e2b0a45ab3690fd20fc8bedc..018472cee1515cee293267c0c5e00d0c3108d80a 100644 (file)
 #include <sched.h>
 #include <limits.h>
 #include <stddef.h>
+#include <signal.h>
 #include "linux/lguest_launcher.h"
 #include "linux/virtio_config.h"
 #include "linux/virtio_net.h"
 #include "linux/virtio_blk.h"
 #include "linux/virtio_console.h"
+#include "linux/virtio_rng.h"
 #include "linux/virtio_ring.h"
 #include "asm-x86/bootparam.h"
 /*L:110 We can ignore the 39 include files we need for this program, but I do
@@ -80,6 +82,8 @@ static int waker_fd;
 static void *guest_base;
 /* The maximum guest physical address allowed, and maximum possible. */
 static unsigned long guest_limit, guest_max;
+/* The pipe for signal hander to write to. */
+static int timeoutpipe[2];
 
 /* a per-cpu variable indicating whose vcpu is currently running */
 static unsigned int __thread cpu_id;
@@ -155,8 +159,14 @@ struct virtqueue
        /* Last available index we saw. */
        u16 last_avail_idx;
 
-       /* The routine to call when the Guest pings us. */
-       void (*handle_output)(int fd, struct virtqueue *me);
+       /* The routine to call when the Guest pings us, or timeout. */
+       void (*handle_output)(int fd, struct virtqueue *me, bool timeout);
+
+       /* Outstanding buffers */
+       unsigned int inflight;
+
+       /* Is this blocked awaiting a timer? */
+       bool blocked;
 };
 
 /* Remember the arguments to the program so we can "reboot" */
@@ -187,6 +197,9 @@ static void *_convert(struct iovec *iov, size_t size, size_t align,
        return iov->iov_base;
 }
 
+/* Wrapper for the last available index.  Makes it easier to change. */
+#define lg_last_avail(vq)      ((vq)->last_avail_idx)
+
 /* The virtio configuration space is defined to be little-endian.  x86 is
  * little-endian too, but it's nice to be explicit so we have these helpers. */
 #define cpu_to_le16(v16) (v16)
@@ -196,6 +209,33 @@ static void *_convert(struct iovec *iov, size_t size, size_t align,
 #define le32_to_cpu(v32) (v32)
 #define le64_to_cpu(v64) (v64)
 
+/* Is this iovec empty? */
+static bool iov_empty(const struct iovec iov[], unsigned int num_iov)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_iov; i++)
+               if (iov[i].iov_len)
+                       return false;
+       return true;
+}
+
+/* Take len bytes from the front of this iovec. */
+static void iov_consume(struct iovec iov[], unsigned num_iov, unsigned len)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_iov; i++) {
+               unsigned int used;
+
+               used = iov[i].iov_len < len ? iov[i].iov_len : len;
+               iov[i].iov_base += used;
+               iov[i].iov_len -= used;
+               len -= used;
+       }
+       assert(len == 0);
+}
+
 /* The device virtqueue descriptors are followed by feature bitmasks. */
 static u8 *get_feature_bits(struct device *dev)
 {
@@ -251,6 +291,7 @@ static void *map_zeroed_pages(unsigned int num)
                    PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0);
        if (addr == MAP_FAILED)
                err(1, "Mmaping %u pages of /dev/zero", num);
+       close(fd);
 
        return addr;
 }
@@ -658,19 +699,22 @@ static unsigned get_vq_desc(struct virtqueue *vq,
                            unsigned int *out_num, unsigned int *in_num)
 {
        unsigned int i, head;
+       u16 last_avail;
 
        /* Check it isn't doing very strange things with descriptor numbers. */
-       if ((u16)(vq->vring.avail->idx - vq->last_avail_idx) > vq->vring.num)
+       last_avail = lg_last_avail(vq);
+       if ((u16)(vq->vring.avail->idx - last_avail) > vq->vring.num)
                errx(1, "Guest moved used index from %u to %u",
-                    vq->last_avail_idx, vq->vring.avail->idx);
+                    last_avail, vq->vring.avail->idx);
 
        /* If there's nothing new since last we looked, return invalid. */
-       if (vq->vring.avail->idx == vq->last_avail_idx)
+       if (vq->vring.avail->idx == last_avail)
                return vq->vring.num;
 
        /* Grab the next descriptor number they're advertising, and increment
         * the index we've seen. */
-       head = vq->vring.avail->ring[vq->last_avail_idx++ % vq->vring.num];
+       head = vq->vring.avail->ring[last_avail % vq->vring.num];
+       lg_last_avail(vq)++;
 
        /* If their number is silly, that's a fatal mistake. */
        if (head >= vq->vring.num)
@@ -702,6 +746,7 @@ static unsigned get_vq_desc(struct virtqueue *vq,
                        errx(1, "Looped descriptor");
        } while ((i = next_desc(vq, i)) != vq->vring.num);
 
+       vq->inflight++;
        return head;
 }
 
@@ -719,6 +764,7 @@ static void add_used(struct virtqueue *vq, unsigned int head, int len)
        /* Make sure buffer is written before we update index. */
        wmb();
        vq->vring.used->idx++;
+       vq->inflight--;
 }
 
 /* This actually sends the interrupt for this virtqueue */
@@ -726,8 +772,9 @@ static void trigger_irq(int fd, struct virtqueue *vq)
 {
        unsigned long buf[] = { LHREQ_IRQ, vq->config.irq };
 
-       /* If they don't want an interrupt, don't send one. */
-       if (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
+       /* If they don't want an interrupt, don't send one, unless empty. */
+       if ((vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
+           && vq->inflight)
                return;
 
        /* Send the Guest an interrupt tell them we used something up. */
@@ -833,7 +880,7 @@ static bool handle_console_input(int fd, struct device *dev)
 
 /* Handling output for console is simple: we just get all the output buffers
  * and write them to stdout. */
-static void handle_console_output(int fd, struct virtqueue *vq)
+static void handle_console_output(int fd, struct virtqueue *vq, bool timeout)
 {
        unsigned int head, out, in;
        int len;
@@ -848,6 +895,21 @@ static void handle_console_output(int fd, struct virtqueue *vq)
        }
 }
 
+static void block_vq(struct virtqueue *vq)
+{
+       struct itimerval itm;
+
+       vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+       vq->blocked = true;
+
+       itm.it_interval.tv_sec = 0;
+       itm.it_interval.tv_usec = 0;
+       itm.it_value.tv_sec = 0;
+       itm.it_value.tv_usec = 500;
+
+       setitimer(ITIMER_REAL, &itm, NULL);
+}
+
 /*
  * The Network
  *
@@ -855,9 +917,9 @@ static void handle_console_output(int fd, struct virtqueue *vq)
  * and write them (ignoring the first element) to this device's file descriptor
  * (/dev/net/tun).
  */
-static void handle_net_output(int fd, struct virtqueue *vq)
+static void handle_net_output(int fd, struct virtqueue *vq, bool timeout)
 {
-       unsigned int head, out, in;
+       unsigned int head, out, in, num = 0;
        int len;
        struct iovec iov[vq->vring.num];
 
@@ -871,7 +933,12 @@ static void handle_net_output(int fd, struct virtqueue *vq)
                (void)convert(&iov[0], struct virtio_net_hdr);
                len = writev(vq->dev->fd, iov+1, out-1);
                add_used_and_trigger(fd, vq, head, len);
+               num++;
        }
+
+       /* Block further kicks and set up a timer if we saw anything. */
+       if (!timeout && num)
+               block_vq(vq);
 }
 
 /* This is where we handle a packet coming in from the tun device to our
@@ -892,6 +959,11 @@ static bool handle_tun_input(int fd, struct device *dev)
                /* FIXME: Actually want DRIVER_ACTIVE here. */
                if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK)
                        warn("network: no dma buffer!");
+
+               /* Now tell it we want to know if new things appear. */
+               dev->vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+               wmb();
+
                /* We'll turn this back on if input buffers are registered. */
                return false;
        } else if (out_num)
@@ -921,13 +993,20 @@ static bool handle_tun_input(int fd, struct device *dev)
 /*L:215 This is the callback attached to the network and console input
  * virtqueues: it ensures we try again, in case we stopped console or net
  * delivery because Guest didn't have any buffers. */
-static void enable_fd(int fd, struct virtqueue *vq)
+static void enable_fd(int fd, struct virtqueue *vq, bool timeout)
 {
        add_device_fd(vq->dev->fd);
        /* Tell waker to listen to it again */
        write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd));
 }
 
+static void net_enable_fd(int fd, struct virtqueue *vq, bool timeout)
+{
+       /* We don't need to know again when Guest refills receive buffer. */
+       vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+       enable_fd(fd, vq, timeout);
+}
+
 /* When the Guest tells us they updated the status field, we handle it. */
 static void update_device_status(struct device *dev)
 {
@@ -945,7 +1024,7 @@ static void update_device_status(struct device *dev)
                for (vq = dev->vq; vq; vq = vq->next) {
                        memset(vq->vring.desc, 0,
                               vring_size(vq->config.num, getpagesize()));
-                       vq->last_avail_idx = 0;
+                       lg_last_avail(vq) = 0;
                }
        } else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) {
                warnx("Device %s configuration FAILED", dev->name);
@@ -954,10 +1033,10 @@ static void update_device_status(struct device *dev)
 
                verbose("Device %s OK: offered", dev->name);
                for (i = 0; i < dev->desc->feature_len; i++)
-                       verbose(" %08x", get_feature_bits(dev)[i]);
+                       verbose(" %02x", get_feature_bits(dev)[i]);
                verbose(", accepted");
                for (i = 0; i < dev->desc->feature_len; i++)
-                       verbose(" %08x", get_feature_bits(dev)
+                       verbose(" %02x", get_feature_bits(dev)
                                [dev->desc->feature_len+i]);
 
                if (dev->ready)
@@ -994,7 +1073,7 @@ static void handle_output(int fd, unsigned long addr)
                        if (strcmp(vq->dev->name, "console") != 0)
                                verbose("Output to %s\n", vq->dev->name);
                        if (vq->handle_output)
-                               vq->handle_output(fd, vq);
+                               vq->handle_output(fd, vq, false);
                        return;
                }
        }
@@ -1008,6 +1087,29 @@ static void handle_output(int fd, unsigned long addr)
              strnlen(from_guest_phys(addr), guest_limit - addr));
 }
 
+static void handle_timeout(int fd)
+{
+       char buf[32];
+       struct device *i;
+       struct virtqueue *vq;
+
+       /* Clear the pipe */
+       read(timeoutpipe[0], buf, sizeof(buf));
+
+       /* Check each device and virtqueue: flush blocked ones. */
+       for (i = devices.dev; i; i = i->next) {
+               for (vq = i->vq; vq; vq = vq->next) {
+                       if (!vq->blocked)
+                               continue;
+
+                       vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+                       vq->blocked = false;
+                       if (vq->handle_output)
+                               vq->handle_output(fd, vq, true);
+               }
+       }
+}
+
 /* This is called when the Waker wakes us up: check for incoming file
  * descriptors. */
 static void handle_input(int fd)
@@ -1018,9 +1120,14 @@ static void handle_input(int fd)
        for (;;) {
                struct device *i;
                fd_set fds = devices.infds;
+               int num;
 
+               num = select(devices.max_infd+1, &fds, NULL, NULL, &poll);
+               /* Could get interrupted */
+               if (num < 0)
+                       continue;
                /* If nothing is ready, we're done. */
-               if (select(devices.max_infd+1, &fds, NULL, NULL, &poll) == 0)
+               if (num == 0)
                        break;
 
                /* Otherwise, call the device(s) which have readable file
@@ -1044,6 +1151,10 @@ static void handle_input(int fd)
                                write(waker_fd, &dev_fd, sizeof(dev_fd));
                        }
                }
+
+               /* Is this the timeout fd? */
+               if (FD_ISSET(timeoutpipe[0], &fds))
+                       handle_timeout(fd);
        }
 }
 
@@ -1092,7 +1203,7 @@ static struct lguest_device_desc *new_dev_desc(u16 type)
 /* Each device descriptor is followed by the description of its virtqueues.  We
  * specify how many descriptors the virtqueue is to have. */
 static void add_virtqueue(struct device *dev, unsigned int num_descs,
-                         void (*handle_output)(int fd, struct virtqueue *me))
+                         void (*handle_output)(int, struct virtqueue *, bool))
 {
        unsigned int pages;
        struct virtqueue **i, *vq = malloc(sizeof(*vq));
@@ -1107,6 +1218,8 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs,
        vq->next = NULL;
        vq->last_avail_idx = 0;
        vq->dev = dev;
+       vq->inflight = 0;
+       vq->blocked = false;
 
        /* Initialize the configuration. */
        vq->config.num = num_descs;
@@ -1239,6 +1352,24 @@ static void setup_console(void)
 }
 /*:*/
 
+static void timeout_alarm(int sig)
+{
+       write(timeoutpipe[1], "", 1);
+}
+
+static void setup_timeout(void)
+{
+       if (pipe(timeoutpipe) != 0)
+               err(1, "Creating timeout pipe");
+
+       if (fcntl(timeoutpipe[1], F_SETFL,
+                 fcntl(timeoutpipe[1], F_GETFL) | O_NONBLOCK) != 0)
+               err(1, "Making timeout pipe nonblocking");
+
+       add_device_fd(timeoutpipe[0]);
+       signal(SIGALRM, timeout_alarm);
+}
+
 /*M:010 Inter-guest networking is an interesting area.  Simplest is to have a
  * --sharenet=<name> option which opens or creates a named pipe.  This can be
  * used to send packets to another guest in a 1:1 manner.
@@ -1257,10 +1388,25 @@ static void setup_console(void)
 
 static u32 str2ip(const char *ipaddr)
 {
-       unsigned int byte[4];
+       unsigned int b[4];
+
+       if (sscanf(ipaddr, "%u.%u.%u.%u", &b[0], &b[1], &b[2], &b[3]) != 4)
+               errx(1, "Failed to parse IP address '%s'", ipaddr);
+       return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
+}
 
-       sscanf(ipaddr, "%u.%u.%u.%u", &byte[0], &byte[1], &byte[2], &byte[3]);
-       return (byte[0] << 24) | (byte[1] << 16) | (byte[2] << 8) | byte[3];
+static void str2mac(const char *macaddr, unsigned char mac[6])
+{
+       unsigned int m[6];
+       if (sscanf(macaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
+                  &m[0], &m[1], &m[2], &m[3], &m[4], &m[5]) != 6)
+               errx(1, "Failed to parse mac address '%s'", macaddr);
+       mac[0] = m[0];
+       mac[1] = m[1];
+       mac[2] = m[2];
+       mac[3] = m[3];
+       mac[4] = m[4];
+       mac[5] = m[5];
 }
 
 /* This code is "adapted" from libbridge: it attaches the Host end of the
@@ -1281,6 +1427,7 @@ static void add_to_bridge(int fd, const char *if_name, const char *br_name)
                errx(1, "interface %s does not exist!", if_name);
 
        strncpy(ifr.ifr_name, br_name, IFNAMSIZ);
+       ifr.ifr_name[IFNAMSIZ-1] = '\0';
        ifr.ifr_ifindex = ifidx;
        if (ioctl(fd, SIOCBRADDIF, &ifr) < 0)
                err(1, "can't add %s to bridge %s", if_name, br_name);
@@ -1289,64 +1436,86 @@ static void add_to_bridge(int fd, const char *if_name, const char *br_name)
 /* This sets up the Host end of the network device with an IP address, brings
  * it up so packets will flow, the copies the MAC address into the hwaddr
  * pointer. */
-static void configure_device(int fd, const char *devname, u32 ipaddr,
-                            unsigned char hwaddr[6])
+static void configure_device(int fd, const char *tapif, u32 ipaddr)
 {
        struct ifreq ifr;
        struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
 
-       /* Don't read these incantations.  Just cut & paste them like I did! */
        memset(&ifr, 0, sizeof(ifr));
-       strcpy(ifr.ifr_name, devname);
+       strcpy(ifr.ifr_name, tapif);
+
+       /* Don't read these incantations.  Just cut & paste them like I did! */
        sin->sin_family = AF_INET;
        sin->sin_addr.s_addr = htonl(ipaddr);
        if (ioctl(fd, SIOCSIFADDR, &ifr) != 0)
-               err(1, "Setting %s interface address", devname);
+               err(1, "Setting %s interface address", tapif);
        ifr.ifr_flags = IFF_UP;
        if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0)
-               err(1, "Bringing interface %s up", devname);
+               err(1, "Bringing interface %s up", tapif);
+}
+
+static void get_mac(int fd, const char *tapif, unsigned char hwaddr[6])
+{
+       struct ifreq ifr;
+
+       memset(&ifr, 0, sizeof(ifr));
+       strcpy(ifr.ifr_name, tapif);
 
        /* SIOC stands for Socket I/O Control.  G means Get (vs S for Set
         * above).  IF means Interface, and HWADDR is hardware address.
         * Simple! */
        if (ioctl(fd, SIOCGIFHWADDR, &ifr) != 0)
-               err(1, "getting hw address for %s", devname);
+               err(1, "getting hw address for %s", tapif);
        memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, 6);
 }
 
-/*L:195 Our network is a Host<->Guest network.  This can either use bridging or
- * routing, but the principle is the same: it uses the "tun" device to inject
- * packets into the Host as if they came in from a normal network card.  We
- * just shunt packets between the Guest and the tun device. */
-static void setup_tun_net(const char *arg)
+static int get_tun_device(char tapif[IFNAMSIZ])
 {
-       struct device *dev;
        struct ifreq ifr;
-       int netfd, ipfd;
-       u32 ip;
-       const char *br_name = NULL;
-       struct virtio_net_config conf;
+       int netfd;
+
+       /* Start with this zeroed.  Messy but sure. */
+       memset(&ifr, 0, sizeof(ifr));
 
        /* We open the /dev/net/tun device and tell it we want a tap device.  A
         * tap device is like a tun device, only somehow different.  To tell
         * the truth, I completely blundered my way through this code, but it
         * works now! */
        netfd = open_or_die("/dev/net/tun", O_RDWR);
-       memset(&ifr, 0, sizeof(ifr));
        ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
        strcpy(ifr.ifr_name, "tap%d");
        if (ioctl(netfd, TUNSETIFF, &ifr) != 0)
                err(1, "configuring /dev/net/tun");
+
        /* We don't need checksums calculated for packets coming in this
         * device: trust us! */
        ioctl(netfd, TUNSETNOCSUM, 1);
 
+       memcpy(tapif, ifr.ifr_name, IFNAMSIZ);
+       return netfd;
+}
+
+/*L:195 Our network is a Host<->Guest network.  This can either use bridging or
+ * routing, but the principle is the same: it uses the "tun" device to inject
+ * packets into the Host as if they came in from a normal network card.  We
+ * just shunt packets between the Guest and the tun device. */
+static void setup_tun_net(char *arg)
+{
+       struct device *dev;
+       int netfd, ipfd;
+       u32 ip = INADDR_ANY;
+       bool bridging = false;
+       char tapif[IFNAMSIZ], *p;
+       struct virtio_net_config conf;
+
+       netfd = get_tun_device(tapif);
+
        /* First we create a new network device. */
        dev = new_device("net", VIRTIO_ID_NET, netfd, handle_tun_input);
 
        /* Network devices need a receive and a send queue, just like
         * console. */
-       add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd);
+       add_virtqueue(dev, VIRTQUEUE_NUM, net_enable_fd);
        add_virtqueue(dev, VIRTQUEUE_NUM, handle_net_output);
 
        /* We need a socket to perform the magic network ioctls to bring up the
@@ -1357,27 +1526,46 @@ static void setup_tun_net(const char *arg)
 
        /* If the command line was --tunnet=bridge:<name> do bridging. */
        if (!strncmp(BRIDGE_PFX, arg, strlen(BRIDGE_PFX))) {
-               ip = INADDR_ANY;
-               br_name = arg + strlen(BRIDGE_PFX);
-               add_to_bridge(ipfd, ifr.ifr_name, br_name);
-       } else /* It is an IP address to set up the device with */
+               arg += strlen(BRIDGE_PFX);
+               bridging = true;
+       }
+
+       /* A mac address may follow the bridge name or IP address */
+       p = strchr(arg, ':');
+       if (p) {
+               str2mac(p+1, conf.mac);
+               *p = '\0';
+       } else {
+               p = arg + strlen(arg);
+               /* None supplied; query the randomly assigned mac. */
+               get_mac(ipfd, tapif, conf.mac);
+       }
+
+       /* arg is now either an IP address or a bridge name */
+       if (bridging)
+               add_to_bridge(ipfd, tapif, arg);
+       else
                ip = str2ip(arg);
 
-       /* Set up the tun device, and get the mac address for the interface. */
-       configure_device(ipfd, ifr.ifr_name, ip, conf.mac);
+       /* Set up the tun device. */
+       configure_device(ipfd, tapif, ip);
 
        /* Tell Guest what MAC address to use. */
        add_feature(dev, VIRTIO_NET_F_MAC);
+       add_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY);
        set_config(dev, sizeof(conf), &conf);
 
        /* We don't need the socket any more; setup is done. */
        close(ipfd);
 
-       verbose("device %u: tun net %u.%u.%u.%u\n",
-               devices.device_num++,
-               (u8)(ip>>24),(u8)(ip>>16),(u8)(ip>>8),(u8)ip);
-       if (br_name)
-               verbose("attached to bridge: %s\n", br_name);
+       devices.device_num++;
+
+       if (bridging)
+               verbose("device %u: tun %s attached to bridge: %s\n",
+                       devices.device_num, tapif, arg);
+       else
+               verbose("device %u: tun %s: %s\n",
+                       devices.device_num, tapif, arg);
 }
 
 /* Our block (disk) device should be really simple: the Guest asks for a block
@@ -1542,7 +1730,7 @@ static bool handle_io_finish(int fd, struct device *dev)
 }
 
 /* When the Guest submits some I/O, we just need to wake the I/O thread. */
-static void handle_virtblk_output(int fd, struct virtqueue *vq)
+static void handle_virtblk_output(int fd, struct virtqueue *vq, bool timeout)
 {
        struct vblk_info *vblk = vq->dev->priv;
        char c = 0;
@@ -1613,6 +1801,64 @@ static void setup_block_file(const char *filename)
        verbose("device %u: virtblock %llu sectors\n",
                devices.device_num, le64_to_cpu(conf.capacity));
 }
+
+/* Our random number generator device reads from /dev/random into the Guest's
+ * input buffers.  The usual case is that the Guest doesn't want random numbers
+ * and so has no buffers although /dev/random is still readable, whereas
+ * console is the reverse.
+ *
+ * The same logic applies, however. */
+static bool handle_rng_input(int fd, struct device *dev)
+{
+       int len;
+       unsigned int head, in_num, out_num, totlen = 0;
+       struct iovec iov[dev->vq->vring.num];
+
+       /* First we need a buffer from the Guests's virtqueue. */
+       head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
+
+       /* If they're not ready for input, stop listening to this file
+        * descriptor.  We'll start again once they add an input buffer. */
+       if (head == dev->vq->vring.num)
+               return false;
+
+       if (out_num)
+               errx(1, "Output buffers in rng?");
+
+       /* This is why we convert to iovecs: the readv() call uses them, and so
+        * it reads straight into the Guest's buffer.  We loop to make sure we
+        * fill it. */
+       while (!iov_empty(iov, in_num)) {
+               len = readv(dev->fd, iov, in_num);
+               if (len <= 0)
+                       err(1, "Read from /dev/random gave %i", len);
+               iov_consume(iov, in_num, len);
+               totlen += len;
+       }
+
+       /* Tell the Guest about the new input. */
+       add_used_and_trigger(fd, dev->vq, head, totlen);
+
+       /* Everything went OK! */
+       return true;
+}
+
+/* And this creates a "hardware" random number device for the Guest. */
+static void setup_rng(void)
+{
+       struct device *dev;
+       int fd;
+
+       fd = open_or_die("/dev/random", O_RDONLY);
+
+       /* The device responds to return from I/O thread. */
+       dev = new_device("rng", VIRTIO_ID_RNG, fd, handle_rng_input);
+
+       /* The device has one virtqueue, where the Guest places inbufs. */
+       add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd);
+
+       verbose("device %u: rng\n", devices.device_num++);
+}
 /* That's the end of device setup. */
 
 /*L:230 Reboot is pretty easy: clean up and exec() the Launcher afresh. */
@@ -1655,7 +1901,7 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd)
                /* ERESTART means that we need to reboot the guest */
                } else if (errno == ERESTART) {
                        restart_guest();
-               /* EAGAIN means the Waker wanted us to look at some input.
+               /* EAGAIN means a signal (timeout).
                 * Anything else means a bug or incompatible change. */
                } else if (errno != EAGAIN)
                        err(1, "Running guest failed");
@@ -1683,13 +1929,14 @@ static struct option opts[] = {
        { "verbose", 0, NULL, 'v' },
        { "tunnet", 1, NULL, 't' },
        { "block", 1, NULL, 'b' },
+       { "rng", 0, NULL, 'r' },
        { "initrd", 1, NULL, 'i' },
        { NULL },
 };
 static void usage(void)
 {
        errx(1, "Usage: lguest [--verbose] "
-            "[--tunnet=(<ipaddr>|bridge:<bridgename>)\n"
+            "[--tunnet=(<ipaddr>:<macaddr>|bridge:<bridgename>:<macaddr>)\n"
             "|--block=<filename>|--initrd=<filename>]...\n"
             "<mem-in-mb> vmlinux [args...]");
 }
@@ -1757,6 +2004,9 @@ int main(int argc, char *argv[])
                case 'b':
                        setup_block_file(optarg);
                        break;
+               case 'r':
+                       setup_rng();
+                       break;
                case 'i':
                        initrd_name = optarg;
                        break;
@@ -1775,6 +2025,9 @@ int main(int argc, char *argv[])
        /* We always have a console device */
        setup_console();
 
+       /* We can timeout waiting for Guest network transmit. */
+       setup_timeout();
+
        /* Now we load the kernel */
        start = load_kernel(open_or_die(argv[optind+1], O_RDONLY));