From: Alex Williamson <alex.williamson@hp.com>
To: qemu-devel@nongnu.org
Cc: alex.williamson@hp.com, kvm@vger.kernel.org
Subject: [Qemu-devel] [PATCH 4/4] qemu:e1000: Add support for qemu_vlan_rxfilter
Date: Wed, 11 Feb 2009 10:11:35 -0700 [thread overview]
Message-ID: <20090211170957.13756.38106.stgit@kvm.aw> (raw)
In-Reply-To: <20090210212902.9760.6747.stgit@kvm.aw>
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 <alex.williamson@hp.com>
---
Updated to address e1000 multicast hash table.
hw/e1000.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 79 insertions(+), 2 deletions(-)
diff --git a/hw/e1000.c b/hw/e1000.c
index 6f841d6..e3e5fa5 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,66 @@ 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 the guest has encoded anything in the multicast hash table,
+ * we're stuck doing the filtering ourselves. This should only
+ * happen if the guest has already consumed the RAR table.
+ */
+ for (i = 0; i < 128; i++) {
+ if (s->mac_reg[MTA + i]) {
+ qemu_vlan_rxfilter(s->vc, QEMU_NET_PROMISC, 0, NULL);
+ s->vlan_rxfilter = 0;
+ return;
+ }
+ }
+
+ 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 +259,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 +594,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;
@@ -715,6 +780,13 @@ mac_writereg(E1000State *s, int index, uint32_t val)
}
static void
+mac_writereg_rx(E1000State *s, int index, uint32_t val)
+{
+ s->mac_reg[index] = val;
+ e1000_set_vlan_rxfilter(s);
+}
+
+static void
set_rdt(E1000State *s, int index, uint32_t val)
{
s->check_rxov = 0;
@@ -790,8 +862,8 @@ static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
[TDH] = set_16bit, [RDH] = set_16bit, [RDT] = set_rdt,
[IMC] = set_imc, [IMS] = set_ims, [ICR] = set_icr,
[EECD] = set_eecd, [RCTL] = set_rx_control,
- [RA ... RA+31] = &mac_writereg,
- [MTA ... MTA+127] = &mac_writereg,
+ [RA ... RA+31] = &mac_writereg_rx,
+ [MTA ... MTA+127] = &mac_writereg_rx,
[VFTA ... VFTA+127] = &mac_writereg,
};
enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) };
@@ -964,6 +1036,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 +1163,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);
next prev parent reply other threads:[~2009-02-11 17:13 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-02-10 21:28 [Qemu-devel] [PATCH 0/4] qemu: TAP filtering support Alex Williamson
2009-02-10 21:28 ` [Qemu-devel] [PATCH 1/4] qemu:net: Add infrastructure for setting an RX filter through the vlan Alex Williamson
2009-02-10 21:28 ` [Qemu-devel] [PATCH 2/4] qemu:net: Add TAP support for RX filtering on Linux Alex Williamson
2009-02-10 21:28 ` [Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter Alex Williamson
2009-02-12 16:26 ` Paul Brook
2009-02-12 16:36 ` Alex Williamson
2009-02-12 17:05 ` Paul Brook
2009-02-12 18:21 ` Alex Williamson
2009-02-12 20:26 ` Jamie Lokier
2009-02-13 12:40 ` Paul Brook
2009-02-13 16:00 ` Jamie Lokier
2009-02-13 16:17 ` Paul Brook
2009-02-13 16:46 ` Jamie Lokier
2009-02-13 17:04 ` Paul Brook
2009-02-13 20:38 ` Jamie Lokier
2009-02-15 16:25 ` Paul Brook
2009-02-10 21:29 ` [Qemu-devel] [PATCH 4/4] qemu:e1000: " Alex Williamson
2009-02-11 15:11 ` [Qemu-devel] " Alex Williamson
2009-02-11 17:11 ` Alex Williamson [this message]
2009-02-11 19:31 ` [Qemu-devel] Re: [PATCH 0/4] qemu: TAP filtering support Mark McLoughlin
2009-02-11 19:43 ` Anthony Liguori
2009-02-11 19:51 ` Alex Williamson
2009-02-11 20:19 ` Mark McLoughlin
2009-02-11 20:37 ` Alex Williamson
2009-02-12 19:57 ` Jamie Lokier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090211170957.13756.38106.stgit@kvm.aw \
--to=alex.williamson@hp.com \
--cc=kvm@vger.kernel.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).