virtio-net: Add additional MACs via a filter table
RFC PATCH 5/5 virtio-net: Add additional MACs via a filter table
virtio-net: Add additional MACs via a filter table
Signed-off-by Alex Williamson <[email protected]>
---
hw/virtio-net.c | 27 +++++++++++++++++++++++++-- hw/virtio-net.h | 4 ++++ 2 files changed, 29 insertions(+), 2 deletions(-)
hw/virtio-net.c +25 -2
@@ -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 VirtIONetQEMUTimer *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 );
hw/virtio-net.h +4 -0
@@ -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