From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MCgPM-0001u6-OT for qemu-devel@nongnu.org; Fri, 05 Jun 2009 16:53:00 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MCgPI-0001nc-Qv for qemu-devel@nongnu.org; Fri, 05 Jun 2009 16:53:00 -0400 Received: from [199.232.76.173] (port=38247 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MCgPI-0001nQ-H0 for qemu-devel@nongnu.org; Fri, 05 Jun 2009 16:52:56 -0400 Received: from g4t0014.houston.hp.com ([15.201.24.17]:42990) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1MCgPH-0005wC-Qw for qemu-devel@nongnu.org; Fri, 05 Jun 2009 16:52:56 -0400 Received: from g5t0030.atlanta.hp.com (g5t0030.atlanta.hp.com [16.228.8.142]) by g4t0014.houston.hp.com (Postfix) with ESMTP id AB2612414A for ; Fri, 5 Jun 2009 20:52:54 +0000 (UTC) From: Alex Williamson Date: Fri, 05 Jun 2009 14:47:13 -0600 Message-ID: <20090605204713.3355.5535.stgit@kvm.aw> In-Reply-To: <20090605204647.3355.81929.stgit@kvm.aw> References: <20090605204647.3355.81929.stgit@kvm.aw> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH 5/7] virtio-net: MAC filter optimization List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: alex.williamson@hp.com The MAC filter table is received from the guest as two separate buffers, one with unicast entries, the other with multicast entries. If we track the index dividing the two sets, we can avoid searching the part of the table with the wrong type of entries. We could store this index as part of the save image, but its trivially easy to discover it on load. Signed-off-by: Alex Williamson --- hw/virtio-net.c | 29 +++++++++++++++++++++++++---- 1 files changed, 25 insertions(+), 4 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 64515a3..5239cc0 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -37,6 +37,7 @@ typedef struct VirtIONet uint8_t allmulti; struct { int in_use; + int first_multi; uint8_t multi_overflow; uint8_t uni_overflow; uint8_t *macs; @@ -100,6 +101,7 @@ static void virtio_net_reset(VirtIODevice *vdev) /* Flush any MAC and VLAN filter table state */ n->mac_table.in_use = 0; + n->mac_table.first_multi = 0; n->mac_table.multi_overflow = 0; n->mac_table.uni_overflow = 0; memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN); @@ -172,6 +174,7 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, return VIRTIO_NET_ERR; n->mac_table.in_use = 0; + n->mac_table.first_multi = 0; n->mac_table.uni_overflow = 0; n->mac_table.multi_overflow = 0; memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN); @@ -190,6 +193,8 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, n->mac_table.uni_overflow = 1; } + n->mac_table.first_multi = n->mac_table.in_use; + mac_data.entries = ldl_le_p(elem->out_sg[2].iov_base); if (sizeof(mac_data.entries) + @@ -356,17 +361,24 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) } else if (n->allmulti || n->mac_table.multi_overflow) { return 1; } + + for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) { + if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) { + return 1; + } + } } else { // unicast if (n->mac_table.uni_overflow) { return 1; } else if (!memcmp(ptr, n->mac, ETH_ALEN)) { return 1; } - } - for (i = 0; i < n->mac_table.in_use; i++) { - if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) - return 1; + for (i = 0; i < n->mac_table.first_multi; i++) { + if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) { + return 1; + } + } } return 0; @@ -542,6 +554,7 @@ static void virtio_net_save(QEMUFile *f, void *opaque) static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) { VirtIONet *n = opaque; + int i; if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION) return -EINVAL; @@ -592,6 +605,14 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) n->mac_table.uni_overflow = qemu_get_byte(f); } + /* Find the first multicast entry in the saved MAC filter */ + for (i = 0; i < n->mac_table.in_use; i++) { + if (n->mac_table.macs[i * ETH_ALEN] & 1) { + break; + } + } + n->mac_table.first_multi = i; + if (n->tx_timer_active) { qemu_mod_timer(n->tx_timer, qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);