From patchwork Tue Feb 3 19:26:06 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 21784 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 23548DDF81 for ; Wed, 4 Feb 2009 06:30:56 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753437AbZBCT3I (ORCPT ); Tue, 3 Feb 2009 14:29:08 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751387AbZBCT3F (ORCPT ); Tue, 3 Feb 2009 14:29:05 -0500 Received: from g5t0008.atlanta.hp.com ([15.192.0.45]:8551 "EHLO g5t0008.atlanta.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755909AbZBCT27 (ORCPT ); Tue, 3 Feb 2009 14:28:59 -0500 Received: from g4t0018.houston.hp.com (g4t0018.houston.hp.com [16.234.32.27]) by g5t0008.atlanta.hp.com (Postfix) with ESMTP id 59247246CD; Tue, 3 Feb 2009 19:28:58 +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 26AF810032; Tue, 3 Feb 2009 19:28:58 +0000 (UTC) Received: from localhost (ldl.fc.hp.com [127.0.0.1]) by ldl.fc.hp.com (Postfix) with ESMTP id D21AC39C07B; Tue, 3 Feb 2009 12:28:57 -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 XEz-SGZkj3Ix; Tue, 3 Feb 2009 12:28:56 -0700 (MST) Received: from debian.lart (lart.fc.hp.com [15.11.146.31]) by ldl.fc.hp.com (Postfix) with ESMTP id 0E4C239C00D; Tue, 3 Feb 2009 12:28:56 -0700 (MST) From: Alex Williamson Subject: [PATCH v4 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: Tue, 03 Feb 2009 12:26:06 -0700 Message-ID: <20090203192605.2678.87446.stgit@debian.lart> In-Reply-To: <20090203192550.2678.14498.stgit@debian.lart> References: <20090203192550.2678.14498.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 | 55 ++++++++++++++++++++++++++++++++++++++------ include/linux/virtio_net.h | 23 ++++++++++++++++++ 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 17058d7..937a256 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -37,7 +37,7 @@ module_param(gso, bool, 0444); #define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) #define GOOD_COPY_LEN 128 -#define VIRTNET_SEND_COMMAND_SG_MAX 1 +#define VIRTNET_SEND_COMMAND_SG_MAX 2 struct virtnet_info { @@ -677,31 +677,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][0], 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][0]; + + 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][0], 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 63b2461..ba82b65 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -88,4 +88,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[][ETH_ALEN]; +} __attribute__((packed)); + +#define VIRTIO_NET_CTRL_MAC 1 + #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 + #endif /* _LINUX_VIRTIO_NET_H */