From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LX0CO-0001UM-SW for qemu-devel@nongnu.org; Tue, 10 Feb 2009 16:31:20 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LX0CN-0001TF-Tx for qemu-devel@nongnu.org; Tue, 10 Feb 2009 16:31:20 -0500 Received: from [199.232.76.173] (port=44793 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LX0CN-0001T0-H9 for qemu-devel@nongnu.org; Tue, 10 Feb 2009 16:31:19 -0500 Received: from g1t0028.austin.hp.com ([15.216.28.35]:14422) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LX0CN-0004WH-2X for qemu-devel@nongnu.org; Tue, 10 Feb 2009 16:31:19 -0500 From: Alex Williamson Date: Tue, 10 Feb 2009 14:29:02 -0700 Message-ID: <20090210212902.9760.6747.stgit@kvm.aw> In-Reply-To: <20090210212841.9760.96780.stgit@kvm.aw> References: <20090210212841.9760.96780.stgit@kvm.aw> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH 4/4] qemu:e1000: Add support for qemu_vlan_rxfilter Reply-To: qemu-devel@nongnu.org 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, kvm@vger.kernel.org Make use of qemu_vlan_rxfilter so that we can filter at a lower level. We implement callbacks for devices being added and removed so that we can fall back to our own filtering or make another attempt to push filtering off to someone else. Signed-off-by: Alex Williamson --- hw/e1000.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 60 insertions(+), 0 deletions(-) diff --git a/hw/e1000.c b/hw/e1000.c index 6f841d6..7855a91 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -85,6 +85,7 @@ typedef struct E1000State_st { uint32_t rxbuf_size; uint32_t rxbuf_min_shift; int check_rxov; + int vlan_rxfilter; struct e1000_tx { unsigned char header[256]; unsigned char vlan_header[4]; @@ -143,6 +144,53 @@ static const char phy_regcap[0x20] = { [PHY_ID2] = PHY_R, [M88E1000_PHY_SPEC_STATUS] = PHY_R }; +static void e1000_set_vlan_rxfilter(E1000State *s) +{ + static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + uint32_t rctl = s->mac_reg[RCTL], ra[2], *rp; + uint8_t *buf; + int i, flags = 0; + + if (rctl & E1000_RCTL_UPE) + flags |= QEMU_NET_PROMISC; + if (rctl & E1000_RCTL_MPE) + flags |= QEMU_NET_ALLMULTI; + + /* Allocate for maximum size, 16 + bcast */ + buf = qemu_mallocz(17 * 6); + + for (i = 0, rp = s->mac_reg + RA; rp < s->mac_reg + RA + 32; rp += 2) { + if (!(rp[1] & E1000_RAH_AV)) + continue; + ra[0] = cpu_to_le32(rp[0]); + ra[1] = cpu_to_le32(rp[1]); + memcpy(&buf[i * 6], (uint8_t *)ra, 6); + i++; + } + + if (rctl & E1000_RCTL_BAM) { + memcpy(&buf[i * 6], bcast, 6); + i++; + } + + s->vlan_rxfilter = qemu_vlan_rxfilter(s->vc, flags, i, buf); + qemu_free(buf); +} + +static void e1000_vlan_client_added(void *opaque) +{ + E1000State *s = opaque; + + s->vlan_rxfilter = 0; +} + +static void e1000_vlan_client_removed(void *opaque) +{ + E1000State *s = opaque; + + e1000_set_vlan_rxfilter(s); +} + static void ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr, uint32_t size, int type) @@ -198,6 +246,7 @@ set_rx_control(E1000State *s, int index, uint32_t val) s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1; DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT], s->mac_reg[RCTL]); + e1000_set_vlan_rxfilter(s); } static void @@ -532,6 +581,9 @@ receive_filter(E1000State *s, const uint8_t *buf, int size) return 0; } + if (s->vlan_rxfilter) + return 1; + if (rctl & E1000_RCTL_UPE) // promiscuous return 1; @@ -712,6 +764,9 @@ static void mac_writereg(E1000State *s, int index, uint32_t val) { s->mac_reg[index] = val; + + if (index >= E1000_RA && index < E1000_RA + 32) + e1000_set_vlan_rxfilter(s); } static void @@ -964,6 +1019,9 @@ nic_load(QEMUFile *f, void *opaque, int version_id) for (j = 0; j < mac_regarraystosave[i].size; j++) qemu_get_be32s(f, s->mac_reg + mac_regarraystosave[i].array0 + j); + + e1000_set_vlan_rxfilter(s); + return 0; } @@ -1088,6 +1146,8 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn) d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, e1000_receive, e1000_can_receive, d); d->vc->link_status_changed = e1000_set_link_status; + d->vc->vlan_client_added = e1000_vlan_client_added; + d->vc->vlan_client_removed = e1000_vlan_client_removed; qemu_format_nic_info_str(d->vc, d->nd->macaddr);