All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alex Williamson <alex.williamson@hp.com>
To: qemu-devel@nongnu.org
Cc: kvm@vger.kernel.org, alex.williamson@hp.com
Subject: [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 [PATCH 0/4] qemu: TAP filtering support Alex Williamson
2009-02-10 21:28 ` [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 ` [PATCH 3/4] qemu:virtio-net: Add support for qemu_vlan_rxfilter Alex Williamson
2009-02-12 16:26   ` [Qemu-devel] " 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 ` [PATCH 4/4] qemu:e1000: " Alex Williamson
2009-02-11 15:11   ` Alex Williamson
2009-02-11 17:11   ` Alex Williamson
2009-02-11 19:31 ` [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         ` [Qemu-devel] " 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.