@@ -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);
@@ -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
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