[5/5,RFC] virtio-net: Add additional MACs via a filter table
diff mbox

Message ID 1231349866.7109.84.camel@lappy
State Accepted, archived
Headers show

Commit Message

Alex Williamson Jan. 7, 2009, 5:37 p.m. UTC
virtio-net: Add additional MACs via a filter table

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

 hw/virtio-net.c |   27 +++++++++++++++++++++++++--
 hw/virtio-net.h |    4 ++++
 2 files changed, 29 insertions(+), 2 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/hw/virtio-net.c b/hw/virtio-net.c
index fa8e71c..f7cc36f 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -16,7 +16,7 @@ 
 #include "qemu-timer.h"
 #include "virtio-net.h"
 
-#define VIRTIO_VM_VERSION	2
+#define VIRTIO_VM_VERSION	3
 
 typedef struct VirtIONet
 {
@@ -28,6 +28,7 @@  typedef struct VirtIONet
             uint16_t link:1;
             uint16_t promisc:1;
             uint16_t allmulti:1;
+            uint16_t mac_table:1;
         } bits;
     } status;
     VirtQueue *rx_vq;
@@ -36,6 +37,7 @@  typedef struct VirtIONet
     QEMUTimer *tx_timer;
     int tx_timer_active;
     int mergeable_rx_bufs;
+    uint64_t mac_table[16];
 } VirtIONet;
 
 /* TODO
@@ -54,6 +56,7 @@  static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
 
     netcfg.status.raw = n->status.raw;
     memcpy(netcfg.mac, n->mac, 6);
+    memcpy(netcfg.mac_table, n->mac_table, sizeof(netcfg.mac_table));
     memcpy(config, &netcfg, sizeof(netcfg));
 }
 
@@ -77,7 +80,12 @@  static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
             n->status.bits.promisc = netcfg.status.bits.promisc;
 	if (netcfg.status.bits.allmulti != n->status.bits.allmulti)
             n->status.bits.allmulti = netcfg.status.bits.allmulti;
+	if (netcfg.status.bits.mac_table != n->status.bits.mac_table)
+            n->status.bits.mac_table = netcfg.status.bits.mac_table;
     }
+
+    if (memcmp(n->mac_table, netcfg.mac_table, sizeof(n->mac_table)))
+        memcpy(n->mac_table, netcfg.mac_table, sizeof(n->mac_table));
 }
 
 static void virtio_net_set_link_status(VLANClientState *vc)
@@ -92,7 +100,8 @@  static void virtio_net_set_link_status(VLANClientState *vc)
 
 static uint32_t virtio_net_get_features(VirtIODevice *vdev)
 {
-    uint32_t features = (1 << VIRTIO_NET_F_MAC) | (1 << VIRTIO_NET_F_STATUS);
+    uint32_t features = (1 << VIRTIO_NET_F_MAC) | (1 << VIRTIO_NET_F_STATUS) |
+                        (1 << VIRTIO_NET_F_MAC_TABLE);
 
     return features;
 }
@@ -170,6 +179,7 @@  static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt,
 static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
 {
     static uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+    int i;
 
     if (n->status.bits.promisc)
         return 1;
@@ -183,6 +193,15 @@  static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
     if (!memcmp(buf, n->mac, 6))
         return 1;
 
+    if (n->status.bits.mac_table) {
+        for (i = 0; i < 16; i++) {
+            uint8_t *mac = (uint8_t *)&n->mac_table[i];
+
+            if (mac[7] && !memcmp(buf, mac, 6))
+                return 1;
+        }
+    }
+
     return 0;
 }
 
@@ -342,6 +361,7 @@  static void virtio_net_save(QEMUFile *f, void *opaque)
     qemu_put_buffer(f, n->mac, 6);
     qemu_put_be32(f, n->tx_timer_active);
     qemu_put_be16(f, n->status.raw);
+    qemu_put_buffer(f, (uint8_t *)n->mac_table, sizeof(n->mac_table));
 }
 
 static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
@@ -361,6 +381,9 @@  static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
     else
         n->status.raw |= (VIRTIO_NET_S_PROMISC | VIRTIO_NET_S_ALLMULTI);
 
+    if (version_id >= 3)
+    	qemu_get_buffer(f, (uint8_t *)n->mac_table, sizeof(n->mac_table));
+
     if (n->tx_timer_active) {
         qemu_mod_timer(n->tx_timer,
                        qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index 74f1595..532c7c4 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -38,10 +38,12 @@ 
 #define VIRTIO_NET_F_HOST_UFO   14      /* Host can handle UFO in. */
 #define VIRTIO_NET_F_MRG_RXBUF  15      /* Host can merge receive buffers. */
 #define VIRTIO_NET_F_STATUS     16      /* virtio_net_config.status available */
+#define VIRTIO_NET_F_MAC_TABLE  17      /* Additional MAC addresses */
 
 #define VIRTIO_NET_S_LINK_UP    1       /* Link is up */
 #define VIRTIO_NET_S_PROMISC    2       /* Promiscuous mode */
 #define VIRTIO_NET_S_ALLMULTI   4       /* All-multicast mode */
+#define VIRTIO_NET_S_MAC_TABLE  8       /* Enable MAC filter table */
 
 #define TX_TIMER_INTERVAL 150000 /* 150 us */
 
@@ -59,8 +61,10 @@  struct virtio_net_config
             uint16_t link:1;
             uint16_t promisc:1;
             uint16_t allmulti:1;
+            uint16_t mac_table:1;
         } bits;
     } status;
+    uint64_t mac_table[16];
 } __attribute__((packed));
 
 /* This is the first element of the scatter-gather list.  If you don't