From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LMqkP-0000uV-8T for qemu-devel@nongnu.org; Tue, 13 Jan 2009 16:24:29 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LMqkM-0000s4-VH for qemu-devel@nongnu.org; Tue, 13 Jan 2009 16:24:28 -0500 Received: from [199.232.76.173] (port=47242 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LMqkM-0000rc-NE for qemu-devel@nongnu.org; Tue, 13 Jan 2009 16:24:26 -0500 Received: from g5t0009.atlanta.hp.com ([15.192.0.46]:4288) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LMqkM-0000x0-8I for qemu-devel@nongnu.org; Tue, 13 Jan 2009 16:24:26 -0500 From: Alex Williamson Content-Type: text/plain Date: Tue, 13 Jan 2009 14:24:02 -0700 Message-Id: <1231881842.9095.196.camel@bling> Mime-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH 5/5] virtio-net: Add additional MACs via a filter table Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: kvm Cc: Mark McLoughlin , qemu-devel Signed-off-by: Alex Williamson --- qemu/hw/virtio-net.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++- qemu/hw/virtio-net.h | 4 +++ 2 files changed, 77 insertions(+), 1 deletions(-) diff --git a/qemu/hw/virtio-net.c b/qemu/hw/virtio-net.c index 99e582f..69b7511 100644 --- a/qemu/hw/virtio-net.c +++ b/qemu/hw/virtio-net.c @@ -21,7 +21,7 @@ #define TAP_VNET_HDR -#define VIRTIO_VM_VERSION 3 +#define VIRTIO_VM_VERSION 4 typedef struct VirtIONet { @@ -36,6 +36,11 @@ typedef struct VirtIONet int mergeable_rx_bufs; int promisc; int allmulti; + struct { + int entries; + int in_use; + uint8_t *macs; + } mac_table; } VirtIONet; /* TODO @@ -69,6 +74,17 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config) } } +static void virtio_net_reset(VirtIODevice *vdev) +{ + VirtIONet *n = to_virtio_net(vdev); + + /* Allow the MAC filter table to be re-allocated after a device reset */ + n->mac_table.in_use = 0; + n->mac_table.entries = 0; + qemu_free(n->mac_table.macs); + n->mac_table.macs = NULL; +} + static uint32_t virtio_net_get_features(VirtIODevice *vdev) { uint32_t features = (1 << VIRTIO_NET_F_MAC); @@ -157,10 +173,46 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) n->allmulti = *on; else *status = VIRTIO_NET_ERR; + + } else if (ctrl->class == VIRTIO_NET_CTRL_MAC_TABLE) { + if (ctrl->cmd == VIRTIO_NET_CTRL_MAC_TABLE_ALLOC) { + uint32_t *entries; + + if (n->mac_table.entries || elem.out_num != 2 || + elem.out_sg[1].iov_len != sizeof(*entries)) { + *status = VIRTIO_NET_ERR; + goto reply; + } + + entries = (void *)elem.out_sg[1].iov_base; + n->mac_table.macs = qemu_mallocz(*entries * 6); + if (!n->mac_table.macs) { + *status = VIRTIO_NET_ERR; + goto reply; + } + + n->mac_table.entries = *entries; + *status = VIRTIO_NET_OK; + } else if (ctrl->cmd == VIRTIO_NET_CTRL_MAC_TABLE_SET) { + if (!n->mac_table.entries || (elem.out_num == 2 && + (elem.out_sg[1].iov_len / 6) > n->mac_table.entries)) { + *status = VIRTIO_NET_ERR; + goto reply; + } + + if (elem.out_num == 2) { + memcpy(n->mac_table.macs, elem.out_sg[1].iov_base, + elem.out_sg[1].iov_len); + n->mac_table.in_use = elem.out_sg[1].iov_len / 6; + } else { + n->mac_table.in_use = 0; + } + } } else { *status = VIRTIO_NET_ERR; } +reply: virtqueue_push(vq, &elem, sizeof(*status)); virtio_notify(vdev, vq); } @@ -276,6 +328,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->promisc) return 1; @@ -289,6 +342,11 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) if (!memcmp(buf, n->mac, 6)) return 1; + for (i = 0; i < n->mac_table.in_use; i++) { + if (!memcmp(buf, &n->mac_table.macs[i * 6], 6)) + return 1; + } + return 0; } @@ -458,6 +516,10 @@ static void virtio_net_save(QEMUFile *f, void *opaque) #endif qemu_put_be32(f, n->promisc); qemu_put_be32(f, n->allmulti); + qemu_put_be32(f, n->mac_table.entries); + qemu_put_be32(f, n->mac_table.in_use); + if (n->mac_table.entries) + qemu_put_buffer(f, n->mac_table.macs, n->mac_table.entries * 6); } static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) @@ -485,6 +547,15 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) n->promisc = 1; } + if (version_id >= 4) { + n->mac_table.entries = qemu_get_be32(f); + n->mac_table.in_use = qemu_get_be32(f); + if (n->mac_table.entries) { + n->mac_table.macs = qemu_mallocz(n->mac_table.entries * 6); + qemu_get_buffer(f, n->mac_table.macs, n->mac_table.entries * 6); + } + } + if (n->tx_timer_active) { qemu_mod_timer(n->tx_timer, qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL); @@ -509,6 +580,7 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn) n->vdev.set_config = virtio_net_set_config; n->vdev.get_features = virtio_net_get_features; n->vdev.set_features = virtio_net_set_features; + n->vdev.reset = virtio_net_reset; n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx); n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx); n->ctrl_vq = virtio_add_queue(&n->vdev, 16, virtio_net_handle_ctrl); diff --git a/qemu/hw/virtio-net.h b/qemu/hw/virtio-net.h index beae4a4..4111036 100644 --- a/qemu/hw/virtio-net.h +++ b/qemu/hw/virtio-net.h @@ -84,4 +84,8 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn); #define VIRTIO_NET_CTRL_RX_MODE_PROMISC 0 #define VIRTIO_NET_CTRL_RX_MODE_ALLMULTI 1 +#define VIRTIO_NET_CTRL_MAC_TABLE 1 + #define VIRTIO_NET_CTRL_MAC_TABLE_ALLOC 0 + #define VIRTIO_NET_CTRL_MAC_TABLE_SET 1 + #endif