From patchwork Tue Feb 10 21:28:47 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 6522 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n1ALV8li008969 for ; Tue, 10 Feb 2009 21:31:09 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755535AbZBJVbG (ORCPT ); Tue, 10 Feb 2009 16:31:06 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755537AbZBJVbG (ORCPT ); Tue, 10 Feb 2009 16:31:06 -0500 Received: from g4t0017.houston.hp.com ([15.201.24.20]:4813 "EHLO g4t0017.houston.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755535AbZBJVbF (ORCPT ); Tue, 10 Feb 2009 16:31:05 -0500 Received: from g4t0018.houston.hp.com (g4t0018.houston.hp.com [16.234.32.27]) by g4t0017.houston.hp.com (Postfix) with ESMTP id AD4F4380B8; Tue, 10 Feb 2009 21:31:03 +0000 (UTC) Received: from ldl.fc.hp.com (ldl.fc.hp.com [15.11.146.30]) by g4t0018.houston.hp.com (Postfix) with ESMTP id 8BD8F10064; Tue, 10 Feb 2009 21:31:03 +0000 (UTC) Received: from localhost (ldl.fc.hp.com [127.0.0.1]) by ldl.fc.hp.com (Postfix) with ESMTP id 4314A39C06E; Tue, 10 Feb 2009 14:31:03 -0700 (MST) X-Virus-Scanned: Debian amavisd-new at ldl.fc.hp.com Received: from ldl.fc.hp.com ([127.0.0.1]) by localhost (ldl.fc.hp.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id fn12-xU-3368; Tue, 10 Feb 2009 14:31:01 -0700 (MST) Received: from kvm.aw (lart.fc.hp.com [15.11.146.31]) by ldl.fc.hp.com (Postfix) with ESMTP id 5CD8C39C00E; Tue, 10 Feb 2009 14:31:01 -0700 (MST) From: Alex Williamson Subject: [PATCH 1/4] qemu:net: Add infrastructure for setting an RX filter through the vlan To: qemu-devel@nongnu.org Cc: kvm@vger.kernel.org, alex.williamson@hp.com Date: Tue, 10 Feb 2009 14:28:47 -0700 Message-ID: <20090210212847.9760.45879.stgit@kvm.aw> In-Reply-To: <20090210212841.9760.96780.stgit@kvm.aw> References: <20090210212841.9760.96780.stgit@kvm.aw> User-Agent: StGIT/0.14.2 MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Some interfaces, such as tap, can set a filter to prevent unwanted packets from interrupting qemu. This patch adds infrastructure for vlan clients to request a set of filtering parameters. The main client interface for this is the new qemu_vlan_rxfilter() function. For simplicity, we restrict the topology that can make use of a filter to exactly two clients on a vlan. To handle hotplug devices, we add vlan_client_added/removed notifiers which can automatically revert back to a shared media protocol. Devices providing filtering can do so via the new fd_rxfilter() interface. Signed-off-by: Alex Williamson --- net.c | 43 ++++++++++++++++++++++++++++++++++++++++++- net.h | 14 ++++++++++++++ 2 files changed, 56 insertions(+), 1 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/net.c b/net.c index e7c097e..e68cb40 100644 --- a/net.c +++ b/net.c @@ -345,8 +345,11 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan, vc->next = NULL; pvc = &vlan->first_client; - while (*pvc != NULL) + while (*pvc != NULL) { + if ((*pvc)->vlan_client_added) + (*pvc)->vlan_client_added((*pvc)->opaque); pvc = &(*pvc)->next; + } *pvc = vc; return vc; } @@ -364,6 +367,12 @@ void qemu_del_vlan_client(VLANClientState *vc) break; } else pvc = &(*pvc)->next; + + /* Notify other clients after removal for dependencies on new topology */ + pvc = &vc->vlan->first_client; + while (*pvc != NULL) + if ((*pvc)->vlan_client_removed) + (*pvc)->vlan_client_removed((*pvc)->opaque); } int qemu_can_send_packet(VLANClientState *vc1) @@ -458,6 +467,38 @@ ssize_t qemu_sendv_packet(VLANClientState *vc1, const struct iovec *iov, return max_len; } +/* + * This function allows a qemu vlan client to request filtering on + * it's receiving interface. We only use this for the typical case + * of having exactly two clients on the vlan. Clients making use + * of this function should also implement a vlan_client_added() + * function to be notified when they need to fall back to their own + * filtering or disable filtering setup for a single consumer. + * + * A return value of 1 indicates the entire requested filter set + * is handled by the provided filter. + */ +int qemu_vlan_rxfilter(VLANClientState *vc1, int flags, int count, + uint8_t *buf) +{ + VLANState *vlan = vc1->vlan; + VLANClientState *vc; + + if (vlan->first_client == NULL || vlan->first_client->next == NULL || + vlan->first_client->next->next != NULL) + return 0; + + if (vlan->first_client == vc1) + vc = vc1->next; + else + vc = vlan->first_client; + + if (vc->fd_rxfilter) + return (vc->fd_rxfilter(vc->opaque, flags, count, buf) == count); + + return 0; +} + #if defined(CONFIG_SLIRP) /* slirp network adapter */ diff --git a/net.h b/net.h index 291807a..2090111 100644 --- a/net.h +++ b/net.h @@ -11,13 +11,22 @@ typedef struct VLANClientState VLANClientState; typedef void (LinkStatusChanged)(VLANClientState *); +typedef int (IORXFilter)(void *, unsigned int , int , uint8_t *); + +typedef void (VLANClientAdded)(void *); + +typedef void (VLANClientRemoved)(void *); + struct VLANClientState { IOReadHandler *fd_read; IOReadvHandler *fd_readv; /* Packets may still be sent if this returns zero. It's used to rate-limit the slirp code. */ IOCanRWHandler *fd_can_read; + IORXFilter *fd_rxfilter; LinkStatusChanged *link_status_changed; + VLANClientAdded *vlan_client_added; + VLANClientRemoved *vlan_client_removed; int link_down; void *opaque; struct VLANClientState *next; @@ -51,10 +60,15 @@ void qemu_check_nic_model(NICInfo *nd, const char *model); void qemu_check_nic_model_list(NICInfo *nd, const char * const *models, const char *default_model); void qemu_handler_true(void *opaque); +int qemu_vlan_rxfilter(VLANClientState *vc1, int flags, int count, + uint8_t *buf); void do_info_network(void); int do_set_link(const char *name, const char *up_or_down); +#define QEMU_NET_PROMISC 1 +#define QEMU_NET_ALLMULTI 2 + /* NIC info */ #define MAX_NICS 8