From patchwork Tue Jan 13 21:24:02 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 2223 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n0DLKkou012171 for ; Tue, 13 Jan 2009 13:20:47 -0800 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753806AbZAMVY1 (ORCPT ); Tue, 13 Jan 2009 16:24:27 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754190AbZAMVY1 (ORCPT ); Tue, 13 Jan 2009 16:24:27 -0500 Received: from g5t0009.atlanta.hp.com ([15.192.0.46]:4289 "EHLO g5t0009.atlanta.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753806AbZAMVYZ (ORCPT ); Tue, 13 Jan 2009 16:24:25 -0500 Received: from g4t0009.houston.hp.com (g4t0009.houston.hp.com [16.234.32.26]) by g5t0009.atlanta.hp.com (Postfix) with ESMTP id 303EA300BB; Tue, 13 Jan 2009 21:24:25 +0000 (UTC) Received: from ldl.fc.hp.com (ldl.fc.hp.com [15.11.146.30]) by g4t0009.houston.hp.com (Postfix) with ESMTP id EC9D7C0B4; Tue, 13 Jan 2009 21:24:24 +0000 (UTC) Received: from localhost (ldl.fc.hp.com [127.0.0.1]) by ldl.fc.hp.com (Postfix) with ESMTP id A0BFB39C017; Tue, 13 Jan 2009 14:24:24 -0700 (MST) X-Virus-Scanned: Debian amavisd-new at ldl.fc.hp.com Received: from ldl.fc.hp.com ([127.0.0.1]) by localhost (ldl.fc.hp.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Ds6WroohWMSg; Tue, 13 Jan 2009 14:24:22 -0700 (MST) Received: from [192.168.1.60] (squirrel.fc.hp.com [15.11.146.57]) by ldl.fc.hp.com (Postfix) with ESMTP id 64E4939C001; Tue, 13 Jan 2009 14:24:22 -0700 (MST) Subject: [PATCH 5/5] virtio-net: Add additional MACs via a filter table From: Alex Williamson To: kvm Cc: qemu-devel , Mark McLoughlin Organization: HP OSLO R&D Date: Tue, 13 Jan 2009 14:24:02 -0700 Message-Id: <1231881842.9095.196.camel@bling> Mime-Version: 1.0 X-Mailer: Evolution 2.24.2 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Signed-off-by: Alex Williamson --- qemu/hw/virtio-net.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++- qemu/hw/virtio-net.h | 4 +++ 2 files changed, 77 insertions(+), 1 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 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