From patchwork Sun Feb 1 20:05:20 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 21508 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id EA0E0DDF44 for ; Mon, 2 Feb 2009 07:08:16 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753598AbZBAUIL (ORCPT ); Sun, 1 Feb 2009 15:08:11 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753699AbZBAUII (ORCPT ); Sun, 1 Feb 2009 15:08:08 -0500 Received: from g4t0015.houston.hp.com ([15.201.24.18]:40965 "EHLO g4t0015.houston.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753233AbZBAUIF (ORCPT ); Sun, 1 Feb 2009 15:08:05 -0500 Received: from g1t0039.austin.hp.com (g1t0039.austin.hp.com [16.236.32.45]) by g4t0015.houston.hp.com (Postfix) with ESMTP id 077F381E1; Sun, 1 Feb 2009 20:08:04 +0000 (UTC) Received: from ldl.fc.hp.com (ldl.fc.hp.com [15.11.146.30]) by g1t0039.austin.hp.com (Postfix) with ESMTP id BF16F3402A; Sun, 1 Feb 2009 20:08:04 +0000 (UTC) Received: from localhost (ldl.fc.hp.com [127.0.0.1]) by ldl.fc.hp.com (Postfix) with ESMTP id 6AD4B39C011; Sun, 1 Feb 2009 13:08:04 -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 ET623z-vsRvG; Sun, 1 Feb 2009 13:08:04 -0700 (MST) Received: from debian.lart (lart.fc.hp.com [15.11.146.31]) by ldl.fc.hp.com (Postfix) with ESMTP id 1D54339C001; Sun, 1 Feb 2009 13:08:04 -0700 (MST) From: Alex Williamson Subject: [PATCH v3 3/4] virtio_net: Add a MAC filter table To: rusty@rustcorp.com.au Cc: markmc@redhat.com, netdev@vger.kernel.org, kvm@vger.kernel.org Date: Sun, 01 Feb 2009 13:05:20 -0700 Message-ID: <20090201200520.8183.3168.stgit@debian.lart> In-Reply-To: <20090201200504.8183.58421.stgit@debian.lart> References: <20090201200504.8183.58421.stgit@debian.lart> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Make use of the MAC control virtqueue class to support a MAC filter table. The filter table is managed by the hypervisor. We consider the table to be available if the CTRL_RX feature bit is set. We leave it to the hypervisor to manage the table and enable promiscuous or all-multi mode as necessary depending on the resources available to it. Signed-off-by: Alex Williamson --- drivers/net/virtio_net.c | 53 ++++++++++++++++++++++++++++++++++++++------ include/linux/virtio_net.h | 25 ++++++++++++++++++++- 2 files changed, 70 insertions(+), 8 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe netdev" 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/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index f43b9d3..e03eebf 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -675,31 +675,70 @@ static int virtnet_set_tx_csum(struct net_device *dev, u32 data) static void virtnet_set_rx_mode(struct net_device *dev) { struct virtnet_info *vi = netdev_priv(dev); - struct scatterlist sg; + struct scatterlist sg[2]; u8 promisc, allmulti; + struct virtio_net_ctrl_mac *mac_data; + struct dev_addr_list *addr; + void *buf; + int i; /* We can't dynamicaly set ndo_set_rx_mode, so return gracefully */ if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) return; - promisc = ((dev->flags & IFF_PROMISC) != 0 || dev->uc_count > 0); - allmulti = ((dev->flags & IFF_ALLMULTI) != 0 || dev->mc_count > 0); + promisc = ((dev->flags & IFF_PROMISC) != 0); + allmulti = ((dev->flags & IFF_ALLMULTI) != 0); - sg_set_buf(&sg, &promisc, sizeof(promisc)); + sg_set_buf(sg, &promisc, sizeof(promisc)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, VIRTIO_NET_CTRL_RX_PROMISC, - &sg, 1, 0)) + sg, 1, 0)) dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", promisc ? "en" : "dis"); - sg_set_buf(&sg, &allmulti, sizeof(allmulti)); + sg_set_buf(sg, &allmulti, sizeof(allmulti)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, VIRTIO_NET_CTRL_RX_ALLMULTI, - &sg, 1, 0)) + sg, 1, 0)) dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", allmulti ? "en" : "dis"); + + /* MAC filter - use one buffer for both lists */ + mac_data = buf = kzalloc(((dev->uc_count + dev->mc_count) * ETH_ALEN) + + (2 * sizeof(mac_data->entries)), GFP_ATOMIC); + if (!buf) { + dev_warn(&dev->dev, "No memory for MAC address buffer\n"); + return; + } + + /* Store the unicast list and count in the front of the buffer */ + mac_data->entries = dev->uc_count; + addr = dev->uc_list; + for (i = 0; i < dev->uc_count; i++, addr = addr->next) + memcpy(&mac_data->macs[i * ETH_ALEN], addr->da_addr, ETH_ALEN); + + sg_set_buf(&sg[0], mac_data, + sizeof(mac_data->entries) + (dev->uc_count * ETH_ALEN)); + + /* multicast list and count fill the end */ + mac_data = (void *)&mac_data->macs[dev->uc_count * ETH_ALEN]; + + mac_data->entries = dev->mc_count; + addr = dev->mc_list; + for (i = 0; i < dev->mc_count; i++, addr = addr->next) + memcpy(&mac_data->macs[i * ETH_ALEN], addr->da_addr, ETH_ALEN); + + sg_set_buf(&sg[1], mac_data, + sizeof(mac_data->entries) + (dev->mc_count * ETH_ALEN)); + + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC, + VIRTIO_NET_CTRL_MAC_TABLE_SET, + sg, 2, 0)) + dev_warn(&dev->dev, "Failed to set MAC fitler table.\n"); + + kfree(buf); } static struct ethtool_ops virtnet_ethtool_ops = { diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 69569e1..06d9dd6 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -77,7 +77,7 @@ typedef __u8 virtio_net_ctrl_ack; #define VIRTIO_NET_OK 0 #define VIRTIO_NET_ERR 1 -#define VIRTIO_NET_MAX_CTRL_ARGS 3 +#define VIRTIO_NET_MAX_CTRL_ARGS 4 /* * Control the RX mode, ie. promisucous and allmulti. PROMISC and @@ -89,4 +89,27 @@ typedef __u8 virtio_net_ctrl_ack; #define VIRTIO_NET_CTRL_RX_PROMISC 0 #define VIRTIO_NET_CTRL_RX_ALLMULTI 1 +/* + * Control the MAC filter table. + * + * The MAC filter table is managed by the hypervisor, the guest should + * assume the size is infinite. Filtering should be considered + * non-perfect, ie. based on hypervisor resources, the guest may + * received packets from sources not specified in the filter list. + * + * In addition to the class/cmd header, the TABLE_SET command requires + * two out scatterlists. Each contains a 4 byte count of entries followed + * by a concatenated byte stream of the ETH_ALEN MAC addresses. The + * first sg list contains unicast addresses, the second is for multicast. + * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature + * is available. + */ +struct virtio_net_ctrl_mac { + __u32 entries; + __u8 macs[]; +} __attribute__((packed)); + +#define VIRTIO_NET_CTRL_MAC 1 + #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 + #endif /* _LINUX_VIRTIO_NET_H */