From patchwork Wed Jan 7 18:06:02 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 1215 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 n07I2bg5026512 for ; Wed, 7 Jan 2009 10:02:37 -0800 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754342AbZAGSGF (ORCPT ); Wed, 7 Jan 2009 13:06:05 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754433AbZAGSGF (ORCPT ); Wed, 7 Jan 2009 13:06:05 -0500 Received: from g5t0006.atlanta.hp.com ([15.192.0.43]:43667 "EHLO g5t0006.atlanta.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753649AbZAGSGD (ORCPT ); Wed, 7 Jan 2009 13:06:03 -0500 Received: from g5t0029.atlanta.hp.com (g5t0029.atlanta.hp.com [16.228.8.141]) by g5t0006.atlanta.hp.com (Postfix) with ESMTP id 42E0BC5F3; Wed, 7 Jan 2009 18:06:01 +0000 (UTC) Received: from ldl.fc.hp.com (ldl.fc.hp.com [15.11.146.30]) by g5t0029.atlanta.hp.com (Postfix) with ESMTP id 0DAA81003A; Wed, 7 Jan 2009 18:05:36 +0000 (UTC) Received: from localhost (ldl.fc.hp.com [127.0.0.1]) by ldl.fc.hp.com (Postfix) with ESMTP id B292639C008; Wed, 7 Jan 2009 11:05:35 -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 15gfV284UdhV; Wed, 7 Jan 2009 11:05:32 -0700 (MST) Received: from [10.91.73.10] (lart.fc.hp.com [15.11.146.31]) by ldl.fc.hp.com (Postfix) with ESMTP id 17E4F39C010; Wed, 7 Jan 2009 11:05:32 -0700 (MST) Subject: [PATCH 1/2][RFC] virtio_net: Enable setting MAC, promisc, and allmulti mode From: Alex Williamson To: Rusty Russell Cc: kvm , netdev , Mark McLoughlin Organization: OSLO R&D Date: Wed, 07 Jan 2009 11:06:02 -0700 Message-Id: <1231351562.7109.129.camel@lappy> Mime-Version: 1.0 X-Mailer: Evolution 2.24.2 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org virtio_net: Enable setting MAC, promisc, and allmulti mode Signed-off-by: Alex Williamson --- drivers/net/virtio_net.c | 79 ++++++++++++++++++++++++++++++++++++++++---- include/linux/virtio_net.h | 11 ++++++ 2 files changed, 82 insertions(+), 8 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/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 3af5e33..f502edd 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -41,7 +41,14 @@ struct virtnet_info struct virtqueue *rvq, *svq; struct net_device *dev; struct napi_struct napi; - unsigned int status; + union { + u16 raw; + struct { + u16 link:1; + u16 promisc:1; + u16 allmulti:1; + } bits; + } status; /* The skb we couldn't send because buffers were full. */ struct sk_buff *last_xmit_skb; @@ -476,6 +483,54 @@ static int virtnet_set_tx_csum(struct net_device *dev, u32 data) return ethtool_op_set_tx_hw_csum(dev, data); } +static int virtnet_set_mac_address(struct net_device *dev, void *p) +{ + struct virtnet_info *vi = netdev_priv(dev); + struct virtio_device *vdev = vi->vdev; + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + vdev->config->set(vdev, offsetof(struct virtio_net_config, mac), + dev->dev_addr, dev->addr_len); + + return 0; +} + +static void virtnet_set_rx_mode(struct net_device *dev) +{ + struct virtnet_info *vi = netdev_priv(dev); + struct virtio_device *vdev = vi->vdev; + u16 status = vi->status.raw; + + if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) + return; + + if (dev->flags & IFF_PROMISC) + status |= VIRTIO_NET_S_PROMISC; + else + status &= ~VIRTIO_NET_S_PROMISC; + + if (dev->flags & IFF_ALLMULTI) + status |= VIRTIO_NET_S_ALLMULTI; + else + status &= ~VIRTIO_NET_S_ALLMULTI; + + if (dev->uc_count) + status |= VIRTIO_NET_S_PROMISC; + if (dev->mc_count) + status |= VIRTIO_NET_S_ALLMULTI; + + if (status != vi->status.raw) { + vi->status.raw = status; + vdev->config->set(vdev, offsetof(struct virtio_net_config, + status), &vi->status, sizeof(vi->status)); + } +} + static struct ethtool_ops virtnet_ethtool_ops = { .set_tx_csum = virtnet_set_tx_csum, .set_sg = ethtool_op_set_sg, @@ -494,14 +549,15 @@ static void virtnet_update_status(struct virtnet_info *vi) &v, sizeof(v)); /* Ignore unknown (future) status bits */ - v &= VIRTIO_NET_S_LINK_UP; + v &= VIRTIO_NET_S_LINK_UP | VIRTIO_NET_S_PROMISC | + VIRTIO_NET_S_ALLMULTI; - if (vi->status == v) + if (vi->status.raw == v) return; - vi->status = v; + vi->status.raw = v; - if (vi->status & VIRTIO_NET_S_LINK_UP) { + if (vi->status.bits.link) { netif_carrier_on(vi->dev); netif_wake_queue(vi->dev); } else { @@ -563,8 +619,17 @@ static int virtnet_probe(struct virtio_device *vdev) vdev->config->get(vdev, offsetof(struct virtio_net_config, mac), dev->dev_addr, dev->addr_len); - } else + } else { + struct sockaddr addr; + random_ether_addr(dev->dev_addr); + memset(&addr, 0, sizeof(addr)); + memcpy(&addr.sa_data, dev->dev_addr, dev->addr_len); + virtnet_set_mac_address(dev, &addr); + } + + dev->set_mac_address = virtnet_set_mac_address; + dev->set_rx_mode = virtnet_set_rx_mode; /* Set up our device-specific information */ vi = netdev_priv(dev); @@ -621,7 +686,7 @@ static int virtnet_probe(struct virtio_device *vdev) goto unregister; } - vi->status = VIRTIO_NET_S_LINK_UP; + vi->status.raw = VIRTIO_NET_S_LINK_UP; virtnet_update_status(vi); pr_debug("virtnet: registered device %s\n", dev->name); diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index d9174be..5a70edb 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -23,6 +23,8 @@ #define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ +#define VIRTIO_NET_S_PROMISC 2 /* Promiscuous mode */ +#define VIRTIO_NET_S_ALLMULTI 4 /* All-multicast mode */ struct virtio_net_config { @@ -30,7 +32,14 @@ struct virtio_net_config __u8 mac[6]; /* Status supplied by host; see VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* * bits above */ - __u16 status; + union { + __u16 raw; + struct { + __u16 link:1; + __u16 promisc:1; + __u16 allmulti:1; + } bits; + } status; } __attribute__((packed)); /* This is the first element of the scatter-gather list. If you don't