]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools: Make virtio net work with user mode network
authorAsias He <asias.hejun@gmail.com>
Wed, 29 Jun 2011 08:47:33 +0000 (16:47 +0800)
committerPekka Enberg <penberg@kernel.org>
Thu, 30 Jun 2011 07:42:46 +0000 (10:42 +0300)
- Call uip_rx() and uip_tx() in virtio_net_rx_thread() and
  virtio_net_tx_thread() if user mode network is enabled.

- Initialize uip in virtio_net__init() if user mode network is enabled.

Signed-off-by: Asias He <asias.hejun@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/virtio/net.c

index 38f0c9b3d34b5c9def10a56eeeff1d6d1dae1c76..98d412041818eaf90eb80781e11e90b5f501cdba 100644 (file)
@@ -1,5 +1,5 @@
-#include "kvm/virtio-net.h"
 #include "kvm/virtio-pci-dev.h"
+#include "kvm/virtio-net.h"
 #include "kvm/virtio.h"
 #include "kvm/ioport.h"
 #include "kvm/types.h"
@@ -8,6 +8,7 @@
 #include "kvm/kvm.h"
 #include "kvm/pci.h"
 #include "kvm/irq.h"
+#include "kvm/uip.h"
 #include "kvm/ioeventfd.h"
 
 #include <linux/virtio_net.h>
@@ -66,6 +67,7 @@ struct net_dev {
 
        int                             mode;
 
+       struct uip_info                 info;
 };
 
 
@@ -84,6 +86,12 @@ static struct net_dev ndev = {
                                        | 1UL << VIRTIO_NET_F_GUEST_UFO
                                        | 1UL << VIRTIO_NET_F_GUEST_TSO4
                                        | 1UL << VIRTIO_NET_F_GUEST_TSO6,
+       .info = {
+               .host_mac.addr          = {0x00, 0x01, 0x01, 0x01, 0x01, 0x01},
+               .guest_mac.addr         = {0x00, 0x15, 0x15, 0x15, 0x15, 0x15},
+               .host_ip                = 0xc0a82101,
+               .buf_nr                 = 20,
+       }
 };
 
 static void *virtio_net_rx_thread(void *p)
@@ -99,14 +107,21 @@ static void *virtio_net_rx_thread(void *p)
        vq      = &ndev.vqs[VIRTIO_NET_RX_QUEUE];
 
        while (1) {
+
                mutex_lock(&ndev.io_rx_lock);
                if (!virt_queue__available(vq))
                        pthread_cond_wait(&ndev.io_rx_cond, &ndev.io_rx_lock);
                mutex_unlock(&ndev.io_rx_lock);
 
                while (virt_queue__available(vq)) {
+
                        head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
-                       len  = readv(ndev.tap_fd, iov, in);
+
+                       if (ndev.mode == NET_MODE_TAP)
+                               len = readv(ndev.tap_fd, iov, in);
+                       else
+                               len = uip_rx(iov, in, &ndev.info);
+
                        virt_queue__set_used_elem(vq, head, len);
 
                        /* We should interrupt guest right now, otherwise latency is huge. */
@@ -139,8 +154,14 @@ static void *virtio_net_tx_thread(void *p)
                mutex_unlock(&ndev.io_tx_lock);
 
                while (virt_queue__available(vq)) {
+
                        head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
-                       len  = writev(ndev.tap_fd, iov, out);
+
+                       if (ndev.mode == NET_MODE_TAP)
+                               len = writev(ndev.tap_fd, iov, out);
+                       else
+                               len = uip_tx(iov, out, &ndev.info);
+
                        virt_queue__set_used_elem(vq, head, len);
                }
 
@@ -216,18 +237,16 @@ static bool virtio_net_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 por
 static void virtio_net_handle_callback(struct kvm *kvm, u16 queue_index)
 {
        switch (queue_index) {
-       case VIRTIO_NET_TX_QUEUE: {
+       case VIRTIO_NET_TX_QUEUE:
                mutex_lock(&ndev.io_tx_lock);
                pthread_cond_signal(&ndev.io_tx_cond);
                mutex_unlock(&ndev.io_tx_lock);
                break;
-       }
-       case VIRTIO_NET_RX_QUEUE: {
+       case VIRTIO_NET_RX_QUEUE:
                mutex_lock(&ndev.io_rx_lock);
                pthread_cond_signal(&ndev.io_rx_cond);
                mutex_unlock(&ndev.io_rx_lock);
                break;
-       }
        default:
                pr_warning("Unknown queue index %u", queue_index);
        }
@@ -395,37 +414,40 @@ static void virtio_net__io_thread_init(struct kvm *kvm)
 
 void virtio_net__init(const struct virtio_net_parameters *params)
 {
-       if (virtio_net__tap_init(params)) {
-               u8 dev, line, pin;
-               u16 net_base_addr;
-               u64 i;
-               struct ioevent ioevent;
-
-               if (irq__register_device(VIRTIO_ID_NET, &dev, &pin, &line) < 0)
-                       return;
-
-               pci_header.irq_pin      = pin;
-               pci_header.irq_line     = line;
-               net_base_addr           = ioport__register(IOPORT_EMPTY, &virtio_net_io_ops, IOPORT_SIZE, NULL);
-               pci_header.bar[0]       = net_base_addr | PCI_BASE_ADDRESS_SPACE_IO;
-               ndev.base_addr          = net_base_addr;
-
-               pci__register(&pci_header, dev);
-
-               virtio_net__io_thread_init(params->kvm);
-
-               for (i = 0; i < VIRTIO_NET_NUM_QUEUES; i++) {
-                       ioevent = (struct ioevent) {
-                               .io_addr                = net_base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
-                               .io_len                 = sizeof(u16),
-                               .fn                     = ioevent_callback,
-                               .datamatch              = i,
-                               .fn_ptr                 = (void *)(long)i,
-                               .fn_kvm                 = params->kvm,
-                               .fd                     = eventfd(0, 0),
-                       };
-
-                       ioeventfd__add_event(&ioevent);
-               }
+       struct ioevent ioevent;
+       u8 dev, line, pin;
+       u16 net_base_addr;
+       int i;
+
+       if (irq__register_device(VIRTIO_ID_NET, &dev, &pin, &line) < 0)
+               return;
+
+       pci_header.irq_pin  = pin;
+       pci_header.irq_line = line;
+       net_base_addr       = ioport__register(IOPORT_EMPTY, &virtio_net_io_ops, IOPORT_SIZE, NULL);
+       pci_header.bar[0]   = net_base_addr | PCI_BASE_ADDRESS_SPACE_IO;
+       ndev.base_addr      = net_base_addr;
+       pci__register(&pci_header, dev);
+
+       ndev.mode = params->mode;
+       if (ndev.mode == NET_MODE_TAP)
+               virtio_net__tap_init(params);
+       else
+               uip_init(&ndev.info);
+
+       virtio_net__io_thread_init(params->kvm);
+
+       for (i = 0; i < VIRTIO_NET_NUM_QUEUES; i++) {
+               ioevent = (struct ioevent) {
+                       .io_addr        = net_base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
+                       .io_len         = sizeof(u16),
+                       .fn             = ioevent_callback,
+                       .datamatch      = i,
+                       .fn_ptr         = (void *)(long)i,
+                       .fn_kvm         = params->kvm,
+                       .fd             = eventfd(0, 0),
+               };
+
+               ioeventfd__add_event(&ioevent);
        }
 }