[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfi
From: |
Alex Williamson |
Subject: |
[Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter |
Date: |
Tue, 10 Feb 2009 14:28:57 -0700 |
User-agent: |
StGIT/0.14.2 |
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 <address@hidden>
---
hw/virtio-net.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 62153e9..3e4f526 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -35,6 +35,7 @@ typedef struct VirtIONet
int mergeable_rx_bufs;
int promisc;
int allmulti;
+ int vlan_rxfilter;
struct {
int in_use;
uint8_t *macs;
@@ -51,6 +52,43 @@ static VirtIONet *to_virtio_net(VirtIODevice *vdev)
return (VirtIONet *)vdev;
}
+static void virtio_net_set_vlan_rxfilter(VirtIONet *n)
+{
+ static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ uint8_t *buf;
+ int flags = 0;
+
+ if (n->promisc)
+ flags |= QEMU_NET_PROMISC;
+ if (n->allmulti)
+ flags |= QEMU_NET_ALLMULTI;
+
+ buf = qemu_mallocz((n->mac_table.in_use + 2) * ETH_ALEN);
+
+ memcpy(&buf[ETH_ALEN*0], n->mac, ETH_ALEN);
+ memcpy(&buf[ETH_ALEN*1], n->mac_table.macs, n->mac_table.in_use *
ETH_ALEN);
+ /* broadcast is a multicast addr, so add it at the end */
+ memcpy(&buf[ETH_ALEN*(n->mac_table.in_use + 1)], bcast, ETH_ALEN);
+
+ n->vlan_rxfilter = qemu_vlan_rxfilter(n->vc, flags,
+ n->mac_table.in_use + 2, buf);
+ qemu_free(buf);
+}
+
+static void virtio_net_vlan_client_added(void *opaque)
+{
+ VirtIONet *n = opaque;
+
+ n->vlan_rxfilter = 0;
+}
+
+static void virtio_net_vlan_client_removed(void *opaque)
+{
+ VirtIONet *n = opaque;
+
+ virtio_net_set_vlan_rxfilter(n);
+}
+
static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
{
VirtIONet *n = to_virtio_net(vdev);
@@ -70,6 +108,7 @@ static void virtio_net_set_config(VirtIODevice *vdev, const
uint8_t *config)
if (memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
memcpy(n->mac, netcfg.mac, ETH_ALEN);
+ virtio_net_set_vlan_rxfilter(n);
qemu_format_nic_info_str(n->vc, n->mac);
}
}
@@ -99,6 +138,7 @@ static void virtio_net_reset(VirtIODevice *vdev)
/* Flush any MAC and VLAN filter table state */
n->mac_table.in_use = 0;
memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
+ virtio_net_set_vlan_rxfilter(n);
memset(n->vlans, 0, MAX_VLAN >> 3);
}
@@ -247,6 +287,10 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev,
VirtQueue *vq)
virtqueue_push(vq, &elem, sizeof(status));
virtio_notify(vdev, vq);
+
+ if (ctrl.class == VIRTIO_NET_CTRL_RX_MODE ||
+ ctrl.class == VIRTIO_NET_CTRL_MAC)
+ virtio_net_set_vlan_rxfilter(n);
}
}
@@ -334,15 +378,19 @@ static int receive_filter(VirtIONet *n, const uint8_t
*buf, int size)
return 0;
}
- if ((ptr[0] & 1) && n->allmulti)
+ /* If hw filtering is complete, no need to continue */
+ if (n->vlan_rxfilter)
return 1;
- if (!memcmp(ptr, bcast, sizeof(bcast)))
+ if ((ptr[0] & 1) && n->allmulti)
return 1;
if (!memcmp(ptr, n->mac, ETH_ALEN))
return 1;
+ if (!memcmp(ptr, bcast, sizeof(bcast)))
+ 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;
@@ -552,6 +600,8 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int
version_id)
if (version_id >= 6)
qemu_get_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3);
+ virtio_net_set_vlan_rxfilter(n);
+
if (n->tx_timer_active) {
qemu_mod_timer(n->tx_timer,
qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
@@ -589,6 +639,8 @@ void virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
virtio_net_receive, virtio_net_can_receive,
n);
n->vc->link_status_changed = virtio_net_set_link_status;
+ n->vc->vlan_client_added = virtio_net_vlan_client_added;
+ n->vc->vlan_client_removed = virtio_net_vlan_client_removed;
qemu_format_nic_info_str(n->vc, n->mac);
- [Qemu-devel] [PATCH 0/4] qemu: TAP filtering support, Alex Williamson, 2009/02/10
- [Qemu-devel] [PATCH 1/4] qemu:net: Add infrastructure for setting an RX filter through the vlan, Alex Williamson, 2009/02/10
- [Qemu-devel] [PATCH 2/4] qemu:net: Add TAP support for RX filtering on Linux, Alex Williamson, 2009/02/10
- [Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter,
Alex Williamson <=
- Re: [Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter, Paul Brook, 2009/02/12
- Re: [Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter, Alex Williamson, 2009/02/12
- Re: [Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter, Paul Brook, 2009/02/12
- Re: [Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter, Alex Williamson, 2009/02/12
- Re: [Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter, Jamie Lokier, 2009/02/12
- Re: [Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter, Paul Brook, 2009/02/13
- Re: [Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter, Jamie Lokier, 2009/02/13
- Re: [Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter, Paul Brook, 2009/02/13
- Re: [Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter, Jamie Lokier, 2009/02/13
- Re: [Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter, Paul Brook, 2009/02/13