summaryrefslogtreecommitdiff
path: root/drivers/net/virtio_net.c
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@hp.com>2009-02-04 12:02:50 +0300
committerDavid S. Miller <davem@davemloft.net>2009-02-05 03:35:13 +0300
commit0bde95690d65653e420d04856c5d5783155c747c (patch)
tree480f2e23d6d5cf39af1bc86e209dd2cc68695301 /drivers/net/virtio_net.c
parentf565a7c259d71cc186753653d978c646d2354b36 (diff)
downloadlinux-0bde95690d65653e420d04856c5d5783155c747c.tar.xz
virtio_net: Add support for VLAN filtering in the hypervisor
VLAN filtering allows the hypervisor to drop packets from VLANs that we're not a part of, further reducing the number of extraneous packets recieved. This makes use of the VLAN virtqueue command class. The CTRL_VLAN feature bit tells us whether the backend supports VLAN filtering. Signed-off-by: Alex Williamson <alex.williamson@hp.com> Acked-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r--drivers/net/virtio_net.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index daab9c9b0a40..e68813a246db 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -727,6 +727,30 @@ static void virtnet_set_rx_mode(struct net_device *dev)
kfree(buf);
}
+static void virnet_vlan_rx_add_vid(struct net_device *dev, u16 vid)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct scatterlist sg;
+
+ sg_set_buf(&sg, &vid, sizeof(vid));
+
+ if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
+ VIRTIO_NET_CTRL_VLAN_ADD, &sg, 1, 0))
+ dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid);
+}
+
+static void virnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct scatterlist sg;
+
+ sg_set_buf(&sg, &vid, sizeof(vid));
+
+ if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
+ VIRTIO_NET_CTRL_VLAN_DEL, &sg, 1, 0))
+ dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid);
+}
+
static struct ethtool_ops virtnet_ethtool_ops = {
.set_tx_csum = virtnet_set_tx_csum,
.set_sg = ethtool_op_set_sg,
@@ -753,6 +777,8 @@ static const struct net_device_ops virtnet_netdev = {
.ndo_set_mac_address = eth_mac_addr,
.ndo_set_rx_mode = virtnet_set_rx_mode,
.ndo_change_mtu = virtnet_change_mtu,
+ .ndo_vlan_rx_add_vid = virnet_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = virnet_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = virtnet_netpoll,
#endif
@@ -877,6 +903,9 @@ static int virtnet_probe(struct virtio_device *vdev)
err = PTR_ERR(vi->svq);
goto free_send;
}
+
+ if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN))
+ dev->features |= NETIF_F_HW_VLAN_FILTER;
}
/* Initialize our empty receive and send queues. */
@@ -967,7 +996,7 @@ static unsigned int features[] = {
VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */
VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
- VIRTIO_NET_F_CTRL_RX,
+ VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
VIRTIO_F_NOTIFY_ON_EMPTY,
};