qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter
Date: Tue, 10 Feb 2009 14:28:57 -0700	[thread overview]
Message-ID: <20090210212857.9760.31288.stgit@kvm.aw> (raw)
In-Reply-To: <20090210212841.9760.96780.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>
---

 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);
 

  parent reply	other threads:[~2009-02-10 21:31 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 ` Alex Williamson [this message]
2009-02-12 16:26   ` [Qemu-devel] [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter 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   ` [Qemu-devel] " Alex Williamson
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=20090210212857.9760.31288.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).