[3/5] virtio-net: Add promiscuous and all-multicast mode status bits
diff mbox

Message ID 1231881833.9095.193.camel@bling
State Accepted, archived
Headers show

Commit Message

Alex Williamson Jan. 13, 2009, 9:23 p.m. UTC
Set via control virtqueue.  For compatibility with older guest drivers
we need to default to promiscuous.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
---

 qemu/hw/virtio-net.c |   41 ++++++++++++++++++++++++++++++++++++++---
 qemu/hw/virtio-net.h |    4 ++++
 2 files changed, 42 insertions(+), 3 deletions(-)



--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch
diff mbox

diff --git a/qemu/hw/virtio-net.c b/qemu/hw/virtio-net.c
index 99f91f2..c5d9952 100644
--- a/qemu/hw/virtio-net.c
+++ b/qemu/hw/virtio-net.c
@@ -21,6 +21,8 @@ 
 
 #define TAP_VNET_HDR
 
+#define VIRTIO_VM_VERSION       3
+
 typedef struct VirtIONet
 {
     VirtIODevice vdev;
@@ -32,6 +34,8 @@  typedef struct VirtIONet
     QEMUTimer *tx_timer;
     int tx_timer_active;
     int mergeable_rx_bufs;
+    int promisc;
+    int allmulti;
 } VirtIONet;
 
 /* TODO
@@ -113,6 +117,7 @@  static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
 
 static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
 {
+    VirtIONet *n = to_virtio_net(vdev);
     struct {
         uint8_t class;
         uint8_t cmd;
@@ -134,7 +139,27 @@  static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
 
         ctrl = (void *)elem.out_sg[0].iov_base;
         status = (void *)elem.in_sg[elem.in_num - 1].iov_base;
-        *status = VIRTIO_NET_ERR;
+        *status = VIRTIO_NET_OK;
+
+        if (ctrl->class == VIRTIO_NET_CTRL_RX_MODE) {
+            uint8_t *on;
+
+            if (elem.out_num != 2 || elem.out_sg[1].iov_len != sizeof(*on)) {
+                fprintf(stderr, "virtio-net ctrl invalid rx mode command\n");
+                exit(1);
+            }
+
+            on = (void *)elem.out_sg[1].iov_base;
+
+            if (ctrl->cmd == VIRTIO_NET_CTRL_RX_MODE_PROMISC)
+                n->promisc = *on;
+            else if (ctrl->cmd == VIRTIO_NET_CTRL_RX_MODE_ALLMULTI)
+                n->allmulti = *on;
+            else
+                *status = VIRTIO_NET_ERR;
+        } else {
+            *status = VIRTIO_NET_ERR;
+        }
 
         virtqueue_push(vq, &elem, sizeof(*status));
         virtio_notify(vdev, vq);
@@ -409,13 +434,15 @@  static void virtio_net_save(QEMUFile *f, void *opaque)
 #ifdef TAP_VNET_HDR
     qemu_put_be32(f, tap_has_vnet_hdr(n->vc->vlan->first_client));
 #endif
+    qemu_put_be32(f, n->promisc);
+    qemu_put_be32(f, n->allmulti);
 }
 
 static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIONet *n = opaque;
 
-    if (version_id != 2)
+    if (version_id < 2 || version_id > VIRTIO_VM_VERSION)
         return -EINVAL;
 
     virtio_load(&n->vdev, f);
@@ -429,6 +456,13 @@  static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
         tap_using_vnet_hdr(n->vc->vlan->first_client, 1);
 #endif
 
+    if (version_id >= 3) {
+        n->promisc = qemu_get_be32(f);
+        n->allmulti = qemu_get_be32(f);
+    } else {
+        n->promisc = 1;
+    }
+
     if (n->tx_timer_active) {
         qemu_mod_timer(n->tx_timer,
                        qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
@@ -465,8 +499,9 @@  PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
     n->tx_timer = qemu_new_timer(vm_clock, virtio_net_tx_timer, n);
     n->tx_timer_active = 0;
     n->mergeable_rx_bufs = 0;
+    n->promisc = 1; /* for compatibility */
 
-    register_savevm("virtio-net", virtio_net_id++, 2,
+    register_savevm("virtio-net", virtio_net_id++, VIRTIO_VM_VERSION,
                     virtio_net_save, virtio_net_load, n);
 
     return (PCIDevice *)n;
diff --git a/qemu/hw/virtio-net.h b/qemu/hw/virtio-net.h
index 1f13123..beae4a4 100644
--- a/qemu/hw/virtio-net.h
+++ b/qemu/hw/virtio-net.h
@@ -80,4 +80,8 @@  PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);
 #define VIRTIO_NET_OK     0
 #define VIRTIO_NET_ERR    1
 
+#define VIRTIO_NET_CTRL_RX_MODE    0
+ #define VIRTIO_NET_CTRL_RX_MODE_PROMISC      0
+ #define VIRTIO_NET_CTRL_RX_MODE_ALLMULTI     1
+
 #endif