aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@hp.com>2009-02-04 04:02:50 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-04 19:35:13 -0500
commit0bde95690d65653e420d04856c5d5783155c747c (patch)
tree480f2e23d6d5cf39af1bc86e209dd2cc68695301
parentf565a7c259d71cc186753653d978c646d2354b36 (diff)
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>
-rw-r--r--drivers/net/virtio_net.c31
-rw-r--r--include/linux/virtio_net.h14
2 files changed, 44 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)
727 kfree(buf); 727 kfree(buf);
728} 728}
729 729
730static void virnet_vlan_rx_add_vid(struct net_device *dev, u16 vid)
731{
732 struct virtnet_info *vi = netdev_priv(dev);
733 struct scatterlist sg;
734
735 sg_set_buf(&sg, &vid, sizeof(vid));
736
737 if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
738 VIRTIO_NET_CTRL_VLAN_ADD, &sg, 1, 0))
739 dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid);
740}
741
742static void virnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid)
743{
744 struct virtnet_info *vi = netdev_priv(dev);
745 struct scatterlist sg;
746
747 sg_set_buf(&sg, &vid, sizeof(vid));
748
749 if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
750 VIRTIO_NET_CTRL_VLAN_DEL, &sg, 1, 0))
751 dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid);
752}
753
730static struct ethtool_ops virtnet_ethtool_ops = { 754static struct ethtool_ops virtnet_ethtool_ops = {
731 .set_tx_csum = virtnet_set_tx_csum, 755 .set_tx_csum = virtnet_set_tx_csum,
732 .set_sg = ethtool_op_set_sg, 756 .set_sg = ethtool_op_set_sg,
@@ -753,6 +777,8 @@ static const struct net_device_ops virtnet_netdev = {
753 .ndo_set_mac_address = eth_mac_addr, 777 .ndo_set_mac_address = eth_mac_addr,
754 .ndo_set_rx_mode = virtnet_set_rx_mode, 778 .ndo_set_rx_mode = virtnet_set_rx_mode,
755 .ndo_change_mtu = virtnet_change_mtu, 779 .ndo_change_mtu = virtnet_change_mtu,
780 .ndo_vlan_rx_add_vid = virnet_vlan_rx_add_vid,
781 .ndo_vlan_rx_kill_vid = virnet_vlan_rx_kill_vid,
756#ifdef CONFIG_NET_POLL_CONTROLLER 782#ifdef CONFIG_NET_POLL_CONTROLLER
757 .ndo_poll_controller = virtnet_netpoll, 783 .ndo_poll_controller = virtnet_netpoll,
758#endif 784#endif
@@ -877,6 +903,9 @@ static int virtnet_probe(struct virtio_device *vdev)
877 err = PTR_ERR(vi->svq); 903 err = PTR_ERR(vi->svq);
878 goto free_send; 904 goto free_send;
879 } 905 }
906
907 if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN))
908 dev->features |= NETIF_F_HW_VLAN_FILTER;
880 } 909 }
881 910
882 /* Initialize our empty receive and send queues. */ 911 /* Initialize our empty receive and send queues. */
@@ -967,7 +996,7 @@ static unsigned int features[] = {
967 VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, 996 VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
968 VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ 997 VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */
969 VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, 998 VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
970 VIRTIO_NET_F_CTRL_RX, 999 VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
971 VIRTIO_F_NOTIFY_ON_EMPTY, 1000 VIRTIO_F_NOTIFY_ON_EMPTY,
972}; 1001};
973 1002
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index ba82b653cace..242348bb3766 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -25,6 +25,7 @@
25#define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ 25#define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */
26#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ 26#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */
27#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ 27#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */
28#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */
28 29
29#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ 30#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
30 31
@@ -111,4 +112,17 @@ struct virtio_net_ctrl_mac {
111#define VIRTIO_NET_CTRL_MAC 1 112#define VIRTIO_NET_CTRL_MAC 1
112 #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 113 #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0
113 114
115/*
116 * Control VLAN filtering
117 *
118 * The VLAN filter table is controlled via a simple ADD/DEL interface.
119 * VLAN IDs not added may be filterd by the hypervisor. Del is the
120 * opposite of add. Both commands expect an out entry containing a 2
121 * byte VLAN ID. VLAN filterting is available with the
122 * VIRTIO_NET_F_CTRL_VLAN feature bit.
123 */
124#define VIRTIO_NET_CTRL_VLAN 2
125 #define VIRTIO_NET_CTRL_VLAN_ADD 0
126 #define VIRTIO_NET_CTRL_VLAN_DEL 1
127
114#endif /* _LINUX_VIRTIO_NET_H */ 128#endif /* _LINUX_VIRTIO_NET_H */