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 2/4] qemu:net: Add TAP support for RX filtering on Linux
Date: Tue, 10 Feb 2009 14:28:52 -0700	[thread overview]
Message-ID: <20090210212852.9760.6710.stgit@kvm.aw> (raw)
In-Reply-To: <20090210212841.9760.96780.stgit@kvm.aw>

The Linux tap driver provides an ioctl to set a TX filter.  Setting
this restricts the packets received onto the vlan.  We provide a
hotplug callback to clear the filter when a new device gets added.
The new rxfilter=off option can be used to disable exporting this
feature to backend drivers.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
---

 net.c         |   56 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 qemu-doc.texi |    6 ++++--
 vl.c          |    3 ++-
 3 files changed, 56 insertions(+), 9 deletions(-)

diff --git a/net.c b/net.c
index e68cb40..973efea 100644
--- a/net.c
+++ b/net.c
@@ -724,6 +724,38 @@ static ssize_t tap_receive_iov(void *opaque, const struct iovec *iov,
 }
 #endif
 
+#ifdef TUNSETTXFILTER
+static int tap_rxfilter(void *opaque, unsigned int flags, int count,
+                         uint8_t *list)
+{
+    TAPState *s = opaque;
+    struct tun_filter *filter;
+    int ret;
+
+    if (flags & QEMU_NET_PROMISC)
+        count = 0;
+
+    filter = qemu_mallocz(sizeof(*filter) + (count * ETH_ALEN));
+
+    memcpy(filter->addr, list, count * ETH_ALEN);
+    filter->count = count;
+
+    if (flags & QEMU_NET_ALLMULTI)
+        filter->flags |= TUN_FLT_ALLMULTI;
+  
+    ret = ioctl(s->fd, TUNSETTXFILTER, filter);
+
+    qemu_free(filter);
+
+    return ret;
+}
+
+static void tap_vlan_client_added(void *opaque)
+{
+    tap_rxfilter(opaque, 0, 0, NULL);
+}
+#endif
+
 static void tap_receive(void *opaque, const uint8_t *buf, int size)
 {
     TAPState *s = opaque;
@@ -762,7 +794,7 @@ static void tap_send(void *opaque)
 static TAPState *net_tap_fd_init(VLANState *vlan,
                                  const char *model,
                                  const char *name,
-                                 int fd)
+                                 int fd, int rxfilter)
 {
     TAPState *s;
 
@@ -772,6 +804,12 @@ static TAPState *net_tap_fd_init(VLANState *vlan,
 #ifdef HAVE_IOVEC
     s->vc->fd_readv = tap_receive_iov;
 #endif
+#ifdef TUNSETTXFILTER
+    if (rxfilter) {
+        s->vc->fd_rxfilter = tap_rxfilter;
+        s->vc->vlan_client_added = tap_vlan_client_added;
+    }
+#endif
     qemu_set_fd_handler(s->fd, tap_send, NULL, s);
     snprintf(s->vc->info_str, sizeof(s->vc->info_str), "fd=%d", fd);
     return s;
@@ -1005,7 +1043,8 @@ static int launch_script(const char *setup_script, const char *ifname, int fd)
 
 static int net_tap_init(VLANState *vlan, const char *model,
                         const char *name, const char *ifname1,
-                        const char *setup_script, const char *down_script)
+                        const char *setup_script, const char *down_script,
+                        int rxfilter)
 {
     TAPState *s;
     int fd;
@@ -1025,7 +1064,7 @@ static int net_tap_init(VLANState *vlan, const char *model,
 	if (launch_script(setup_script, ifname, fd))
 	    return -1;
     }
-    s = net_tap_fd_init(vlan, model, name, fd);
+    s = net_tap_fd_init(vlan, model, name, fd, rxfilter);
     if (!s)
         return -1;
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
@@ -1663,13 +1702,18 @@ int net_client_init(const char *device, const char *p)
     if (!strcmp(device, "tap")) {
         char ifname[64];
         char setup_script[1024], down_script[1024];
-        int fd;
+        int fd, rxfilter = 1;
         vlan->nb_host_devs++;
+
+        if (get_param_value(buf, sizeof(buf), "rxfilter", p) > 0)
+            if (!strcmp(buf, "off"))
+                rxfilter = 0;
+        
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
             fd = strtol(buf, NULL, 0);
             fcntl(fd, F_SETFL, O_NONBLOCK);
             ret = -1;
-            if (net_tap_fd_init(vlan, device, name, fd))
+            if (net_tap_fd_init(vlan, device, name, fd, rxfilter))
                 ret = 0;
         } else {
             if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
@@ -1681,7 +1725,7 @@ int net_client_init(const char *device, const char *p)
             if (get_param_value(down_script, sizeof(down_script), "downscript", p) == 0) {
                 pstrcpy(down_script, sizeof(down_script), DEFAULT_NETWORK_DOWN_SCRIPT);
             }
-            ret = net_tap_init(vlan, device, name, ifname, setup_script, down_script);
+            ret = net_tap_init(vlan, device, name, ifname, setup_script, down_script, rxfilter);
         }
     } else
 #endif
diff --git a/qemu-doc.texi b/qemu-doc.texi
index efb88d2..9a3957c 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -643,7 +643,7 @@ Use the user mode network stack which requires no administrator
 privilege to run.  @option{hostname=name} can be used to specify the client
 hostname reported by the builtin DHCP server.
 
-@item -net tap[,vlan=@var{n}][,name=@var{name}][,fd=@var{h}][,ifname=@var{name}][,script=@var{file}][,downscript=@var{dfile}]
+@item -net tap[,vlan=@var{n}][,name=@var{name}][,fd=@var{h}][,ifname=@var{name}][,script=@var{file}][,downscript=@var{dfile}][,rxfilter=on|off]
 Connect the host TAP network interface @var{name} to VLAN @var{n}, use
 the network script @var{file} to configure it and the network script 
 @var{dfile} to deconfigure it. If @var{name} is not provided, the OS 
@@ -651,7 +651,9 @@ automatically provides one. @option{fd}=@var{h} can be used to specify
 the handle of an already opened host TAP interface. The default network 
 configure script is @file{/etc/qemu-ifup} and the default network 
 deconfigure script is @file{/etc/qemu-ifdown}. Use @option{script=no} 
-or @option{downscript=no} to disable script execution. Example:
+or @option{downscript=no} to disable script execution. The rxfilter
+(Linux-only) option enables or disables availability of the tap device
+MAC filtering (default on). Example:
 
 @example
 qemu linux.img -net nic -net tap
diff --git a/vl.c b/vl.c
index aff2b2c..96ab696 100644
--- a/vl.c
+++ b/vl.c
@@ -3909,12 +3909,13 @@ static void help(int exitcode)
            "-net tap[,vlan=n][,name=str],ifname=name\n"
            "                connect the host TAP network interface to VLAN 'n'\n"
 #else
-           "-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile]\n"
+           "-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,rxfilter=on|off]\n"
            "                connect the host TAP network interface to VLAN 'n' and use the\n"
            "                network scripts 'file' (default=%s)\n"
            "                and 'dfile' (default=%s);\n"
            "                use '[down]script=no' to disable script execution;\n"
            "                use 'fd=h' to connect to an already opened TAP interface\n"
+           "                rxfilter enables|disables use of the tap MAC filter (default on)\n"
 #endif
            "-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n"
            "                connect the vlan 'n' to another VLAN using a socket connection\n"

  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 ` Alex Williamson [this message]
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   ` [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=20090210212852.9760.6710.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).