From patchwork Wed Jan 12 17:53:26 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Michael S. Tsirkin" X-Patchwork-Id: 474481 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0CHs2m0002658 for ; Wed, 12 Jan 2011 17:54:02 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755193Ab1ALRx6 (ORCPT ); Wed, 12 Jan 2011 12:53:58 -0500 Received: from mx1.redhat.com ([209.132.183.28]:22216 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754487Ab1ALRx5 (ORCPT ); Wed, 12 Jan 2011 12:53:57 -0500 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id p0CHrjIa010141 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 12 Jan 2011 12:53:45 -0500 Received: from redhat.com (vpn-200-17.tlv.redhat.com [10.35.200.17]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p0CHreAC002969; Wed, 12 Jan 2011 12:53:41 -0500 Date: Wed, 12 Jan 2011 19:53:26 +0200 From: "Michael S. Tsirkin" To: Dragos Tatulea Cc: alex.williamson@redhat.com, paul@codesourcery.com, anthony@codemonkey.ws, qemu-devel@nongnu.org, kvm@vger.kernel.org Subject: Re: [PATCH][RFC] qemu:virtio-net: Use TUNSETTXFILTER for MAC filteringlogin register about Message-ID: <20110112175326.GC1242@redhat.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Wed, 12 Jan 2011 17:54:02 +0000 (UTC) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 1d61f19..7892ca9 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -343,6 +343,15 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, n->mac_table.multi_overflow = 1; } } + if (n->nic->nc.peer && n->nic->nc.peer->info->set_rx_filter) { + n->nic->nc.peer->info->set_rx_filter(n->nic->nc.peer, + n->promisc, + n->allmulti, + n->nobcast, + n->mac, + n->mac_table.in_use, + n->mac_table.macs); + } return VIRTIO_NET_OK; } diff --git a/net.h b/net.h index 44c31a9..9e164b9 100644 --- a/net.h +++ b/net.h @@ -42,6 +42,8 @@ typedef ssize_t (NetReceive)(VLANClientState *, const uint8_t *, size_t); typedef ssize_t (NetReceiveIOV)(VLANClientState *, const struct iovec *, int); typedef void (NetCleanup) (VLANClientState *); typedef void (LinkStatusChanged)(VLANClientState *); +typedef int (NetRXFilter)(VLANClientState *, bool allmulti, bool promisc, + bool nobcast, uint8_t *, int , uint8_t *); typedef struct NetClientInfo { net_client_type type; @@ -50,6 +52,7 @@ typedef struct NetClientInfo { NetReceive *receive_raw; NetReceiveIOV *receive_iov; NetCanReceive *can_receive; + NetRXFilter *set_rx_filter; NetCleanup *cleanup; LinkStatusChanged *link_status_changed; NetPoll *poll; diff --git a/net/tap-aix.c b/net/tap-aix.c index e19aaba..4cf5ad9 100644 --- a/net/tap-aix.c +++ b/net/tap-aix.c @@ -59,3 +59,9 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { } + +int tap_fd_set_rx_filter(int fd, bool allmulti, bool promisc, bool nobcast, + uint8_t *mac, int count, uint8_t *macs) +{ + return -1; +} diff --git a/net/tap-bsd.c b/net/tap-bsd.c index efccfe0..d092c6f 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -125,3 +125,9 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { } + +int tap_fd_set_rx_filter(int fd, bool allmulti, bool promisc, bool nobcast, + uint8_t *mac, int count, uint8_t *macs) +{ + return -1; +} diff --git a/net/tap-haiku.c b/net/tap-haiku.c index 91dda8e..8117c03 100644 --- a/net/tap-haiku.c +++ b/net/tap-haiku.c @@ -59,3 +59,9 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { } + +int tap_fd_set_rx_filter(int fd, bool allmulti, bool promisc, bool nobcast, + uint8_t *mac, int count, uint8_t *macs) +{ + return -1; +} diff --git a/net/tap-linux.c b/net/tap-linux.c index f7aa904..19d05c6 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -188,3 +188,41 @@ void tap_fd_set_offload(int fd, int csum, int tso4, } } } + +int tap_fd_set_rx_filter(int fd, bool allmulti, bool promisc, bool nobcast, + uint8_t *mac, int count, uint8_t *list) +{ + struct tun_filter *filter; + int ret; + int len = TAP_LINUX_ETH_ALEN * (promisc ? 0 : (count + 2)); + + filter = qemu_mallocz(offsetof(struct tun_filter, addr) + len); + if (!filter) { + return -1; + } + + if (!promisc) { + memcpy(filter->addr, mac, TAP_LINUX_ETH_ALEN); + filter->count += 1; + + memcpy(&filter->addr[filter->count], list, count * TAP_LINUX_ETH_ALEN); + filter->count += count; + } + + if (!promisc && !allmulti && !nobcast) { + /* If enabled and not included implicitly by promisc or all multicast + * mode, add all ones - the broadcast address. */ + memset(&filter->addr[filter->count], 0xff, TAP_LINUX_ETH_ALEN); + filter->count += 1; + } + + if (allmulti) { + filter->flags |= TUN_FLT_ALLMULTI; + } + + ret = ioctl(fd, TUNSETTXFILTER, filter); + + qemu_free(filter); + + return ret; +} diff --git a/net/tap-linux.h b/net/tap-linux.h index 659e981..6e53562 100644 --- a/net/tap-linux.h +++ b/net/tap-linux.h @@ -25,6 +25,7 @@ #define TUNSETIFF _IOW('T', 202, int) #define TUNGETFEATURES _IOR('T', 207, unsigned int) #define TUNSETOFFLOAD _IOW('T', 208, unsigned int) +#define TUNSETTXFILTER _IOW('T', 209, unsigned int) #define TUNGETIFF _IOR('T', 210, unsigned int) #define TUNSETSNDBUF _IOW('T', 212, int) #define TUNGETVNETHDRSZ _IOR('T', 215, int) @@ -44,6 +45,24 @@ #define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */ #define TUN_F_UFO 0x10 /* I can handle UFO packets */ +/* + * Filter spec (used for SETXXFILTER ioctls) + * This stuff is applicable only to the TAP (Ethernet) devices. + * If the count is zero the filter is disabled and the driver accepts + * all packets (promisc mode). + * If the filter is enabled in order to accept broadcast packets + * broadcast addr must be explicitly included in the addr list. + */ +#define TUN_FLT_ALLMULTI 0x0001 /* Accept all multicast packets */ + +#define TAP_LINUX_ETH_ALEN 6 + +struct tun_filter { + uint16_t flags; /* TUN_FLT_ flags see above */ + uint16_t count; /* Number of addresses */ + uint8_t addr[0][TAP_LINUX_ETH_ALEN]; +}; + struct virtio_net_hdr { uint8_t flags; diff --git a/net/tap-solaris.c b/net/tap-solaris.c index c216d28..2a1d065 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -225,3 +225,9 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { } + +int tap_fd_set_rx_filter(int fd, bool allmulti, bool promisc, bool nobcast, + uint8_t *mac, int count, uint8_t *macs) +{ + return -1; +} diff --git a/net/tap-win32.c b/net/tap-win32.c index 081904e..333846b 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -749,3 +749,9 @@ struct vhost_net *tap_get_vhost_net(VLANClientState *nc) { return NULL; } + +int tap_fd_set_rx_filter(int fd, bool allmulti, bool promisc, bool nobcast, + uint8_t *mac, int count, uint8_t *macs) +{ + return -1; +} diff --git a/net/tap.c b/net/tap.c index eada34a..7bc47f8 100644 --- a/net/tap.c +++ b/net/tap.c @@ -310,6 +310,13 @@ int tap_get_fd(VLANClientState *nc) return s->fd; } +static int tap_set_rx_filter(VLANClientState *nc, bool allmulti, bool promisc, + bool nobcast, uint8_t *mac, int count, uint8_t *list) +{ + TAPState *s = DO_UPCAST(TAPState, nc, nc); + return tap_fd_set_rx_filter(s->fd, allmulti, promisc, nobcast, mac, count, list); +} + /* fd support */ static NetClientInfo net_tap_info = { @@ -318,6 +325,7 @@ static NetClientInfo net_tap_info = { .receive = tap_receive, .receive_raw = tap_receive_raw, .receive_iov = tap_receive_iov, + .set_rx_filter = tap_set_rx_filter, .poll = tap_poll, .cleanup = tap_cleanup, }; diff --git a/net/tap.h b/net/tap.h index e44bd2b..0cf820c 100644 --- a/net/tap.h +++ b/net/tap.h @@ -51,6 +51,8 @@ int tap_probe_vnet_hdr_len(int fd, int len); int tap_probe_has_ufo(int fd); void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo); void tap_fd_set_vnet_hdr_len(int fd, int len); +int tap_fd_set_rx_filter(int fd, bool allmulti, bool promisc, bool nobcast, + uint8_t *, int , uint8_t *); int tap_get_fd(VLANClientState *vc);