From patchwork Wed Sep 29 19:59:55 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Weil X-Patchwork-Id: 66093 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id E5325B6F11 for ; Thu, 30 Sep 2010 06:00:45 +1000 (EST) Received: from localhost ([127.0.0.1]:53272 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1P12pW-0003pf-FS for incoming@patchwork.ozlabs.org; Wed, 29 Sep 2010 16:00:42 -0400 Received: from [140.186.70.92] (port=59306 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1P12ot-0003oB-Rm for qemu-devel@nongnu.org; Wed, 29 Sep 2010 16:00:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1P12os-0004DC-Aj for qemu-devel@nongnu.org; Wed, 29 Sep 2010 16:00:03 -0400 Received: from moutng.kundenserver.de ([212.227.17.10]:62277) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1P12or-0004Bp-SW for qemu-devel@nongnu.org; Wed, 29 Sep 2010 16:00:02 -0400 Received: from flocke.weilnetz.de (p54ADB7D0.dip.t-dialin.net [84.173.183.208]) by mrelayeu.kundenserver.de (node=mreu1) with ESMTP (Nemesis) id 0Lgc09-1OO9kW2Rgj-00oYoR; Wed, 29 Sep 2010 21:59:57 +0200 Received: from stefan by flocke.weilnetz.de with local (Exim 4.72) (envelope-from ) id 1P12om-0006dB-OH; Wed, 29 Sep 2010 21:59:56 +0200 From: Stefan Weil To: QEMU Developers Date: Wed, 29 Sep 2010 21:59:55 +0200 Message-Id: <1285790395-25460-1-git-send-email-weil@mail.berlios.de> X-Mailer: git-send-email 1.7.1 In-Reply-To: <4CA38D83.9040106@mail.berlios.de> References: <4CA38D83.9040106@mail.berlios.de> X-Provags-ID: V02:K0:ukz0TubCTYKNfovNLSKBktPd1deiK1F59M4XK0UNO3w +J69OPkd8hhJuvd+KLTv+6cheBUuSovheAkDgdSA4tDYH0wrvd 2FNQdsUM1ABkHQGZkN8Xwf5vFE6Ejvoo9Sl8F+yTKCxqO1Nt/T 1+BDvilDy9xQ2O8qejKfAnNqnY/4g5FHgCRAunTDuwNR6xy5FR 9BAAmFRyMgeNi8c0pgYEHVNDTj9hqW85ZSs+mVuhWzw9/DhZ/m GAHIQxtV7Pl39 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Cc: "Michael S. Tsirkin" Subject: [Qemu-devel] [PATCH] eepro100: Add support for multiple individual addresses (multiple IA) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org I reviewed the latest sources of Linux, FreeBSD and NetBSD. They all reset the multiple IA bit (multi_ia in BSD) to zero, but I did not find code which sets this bit to one (like it is done by some routers). Running Windows guests also did not set this bit. Intel's Open Source Software Developer Manual does not give much information on the semantics related to this bit, so I had to guess how it works. The guess was good enough to make the router emulation work. Related changes in this patch: * Update naming and documentation of the internal hash register. It is not limited to multicast, but also used for multiple IA. * Dump complete configuration register when debug traces are enabled. * Debug output when multiple IA bit is set during CmdConfigure. * Debug output when frames are received because multiple IA bit is set, or when they are ignored although it is set. Cc: Michael S. Tsirkin Signed-off-by: Stefan Weil --- hw/eepro100.c | 30 +++++++++++++++++++++--------- 1 files changed, 21 insertions(+), 9 deletions(-) diff --git a/hw/eepro100.c b/hw/eepro100.c index 2b75c8f..5f6dcb6 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -219,7 +219,8 @@ typedef enum { typedef struct { PCIDevice dev; - uint8_t mult[8]; /* multicast mask array */ + /* Hash register (multicast mask array, multiple individual addresses). */ + uint8_t mult[8]; int mmio_index; NICState *nic; NICConf conf; @@ -599,7 +600,7 @@ static void nic_reset(void *opaque) { EEPRO100State *s = opaque; TRACE(OTHER, logout("%p\n", s)); - /* TODO: Clearing of multicast table for selective reset, too? */ + /* TODO: Clearing of hash register for selective reset, too? */ memset(&s->mult[0], 0, sizeof(s->mult)); nic_selective_reset(s); } @@ -851,7 +852,14 @@ static void action_command(EEPRO100State *s) case CmdConfigure: cpu_physical_memory_read(s->cb_address + 8, &s->configuration[0], sizeof(s->configuration)); - TRACE(OTHER, logout("configuration: %s\n", nic_dump(&s->configuration[0], 16))); + TRACE(OTHER, logout("configuration: %s\n", + nic_dump(&s->configuration[0], 16))); + TRACE(OTHER, logout("configuration: %s\n", + nic_dump(&s->configuration[16], + ARRAY_SIZE(s->configuration) - 16))); + if (s->configuration[20] & BIT(6)) { + TRACE(OTHER, logout("Multiple IA bit\n")); + } break; case CmdMulticastList: set_multicast_list(s); @@ -1647,12 +1655,6 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size static const uint8_t broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - /* TODO: check multiple IA bit. */ - if (s->configuration[20] & BIT(6)) { - missing("Multiple IA bit"); - return -1; - } - if (s->configuration[8] & 0x80) { /* CSMA is disabled. */ logout("%p received while CSMA is disabled\n", s); @@ -1702,6 +1704,16 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size /* Promiscuous: receive all. */ TRACE(RXTX, logout("%p received frame in promiscuous mode, len=%zu\n", s, size)); rfd_status |= 0x0004; + } else if (s->configuration[20] & BIT(6)) { + /* Multiple IA bit set. */ + unsigned mcast_idx = compute_mcast_idx(buf); + assert(mcast_idx < 64); + if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) { + TRACE(RXTX, logout("%p accepted, multiple IA bit set\n", s)); + } else { + TRACE(RXTX, logout("%p frame ignored, multiple IA bit set\n", s)); + return -1; + } } else { TRACE(RXTX, logout("%p received frame, ignored, len=%zu,%s\n", s, size, nic_dump(buf, size)));