diff options
author | Alex Williamson <alex.williamson@hp.com> | 2009-02-04 04:02:40 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-04 19:35:12 -0500 |
commit | 2af7698e2dd698d452ab9d63a9ca5956bbe8fc3b (patch) | |
tree | b4f767eb2b15d85b0f4ebe1cd560b296f44cc8a1 /drivers/net | |
parent | 2a41f71d3bd97dde3305b4e1c43ab0eca46e7c71 (diff) |
virtio_net: Add a set_rx_mode interface
Make use of the RX_MODE control virtqueue class to enable the
set_rx_mode netdev interface. This allows us to selectively
enable/disable promiscuous and allmulti mode so we don't see
packets we don't want. For now, we automatically enable these
as needed if additional unicast or multicast addresses are
requested.
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')
-rw-r--r-- | drivers/net/virtio_net.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 67bb583b7fc9..1abea9dc6f0f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -37,7 +37,7 @@ module_param(gso, bool, 0444); | |||
37 | #define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) | 37 | #define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) |
38 | #define GOOD_COPY_LEN 128 | 38 | #define GOOD_COPY_LEN 128 |
39 | 39 | ||
40 | #define VIRTNET_SEND_COMMAND_SG_MAX 0 | 40 | #define VIRTNET_SEND_COMMAND_SG_MAX 1 |
41 | 41 | ||
42 | struct virtnet_info | 42 | struct virtnet_info |
43 | { | 43 | { |
@@ -658,6 +658,36 @@ static int virtnet_set_tx_csum(struct net_device *dev, u32 data) | |||
658 | return ethtool_op_set_tx_hw_csum(dev, data); | 658 | return ethtool_op_set_tx_hw_csum(dev, data); |
659 | } | 659 | } |
660 | 660 | ||
661 | static void virtnet_set_rx_mode(struct net_device *dev) | ||
662 | { | ||
663 | struct virtnet_info *vi = netdev_priv(dev); | ||
664 | struct scatterlist sg; | ||
665 | u8 promisc, allmulti; | ||
666 | |||
667 | /* We can't dynamicaly set ndo_set_rx_mode, so return gracefully */ | ||
668 | if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) | ||
669 | return; | ||
670 | |||
671 | promisc = ((dev->flags & IFF_PROMISC) != 0 || dev->uc_count > 0); | ||
672 | allmulti = ((dev->flags & IFF_ALLMULTI) != 0 || dev->mc_count > 0); | ||
673 | |||
674 | sg_set_buf(&sg, &promisc, sizeof(promisc)); | ||
675 | |||
676 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, | ||
677 | VIRTIO_NET_CTRL_RX_PROMISC, | ||
678 | &sg, 1, 0)) | ||
679 | dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", | ||
680 | promisc ? "en" : "dis"); | ||
681 | |||
682 | sg_set_buf(&sg, &allmulti, sizeof(allmulti)); | ||
683 | |||
684 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, | ||
685 | VIRTIO_NET_CTRL_RX_ALLMULTI, | ||
686 | &sg, 1, 0)) | ||
687 | dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", | ||
688 | allmulti ? "en" : "dis"); | ||
689 | } | ||
690 | |||
661 | static struct ethtool_ops virtnet_ethtool_ops = { | 691 | static struct ethtool_ops virtnet_ethtool_ops = { |
662 | .set_tx_csum = virtnet_set_tx_csum, | 692 | .set_tx_csum = virtnet_set_tx_csum, |
663 | .set_sg = ethtool_op_set_sg, | 693 | .set_sg = ethtool_op_set_sg, |
@@ -682,6 +712,7 @@ static const struct net_device_ops virtnet_netdev = { | |||
682 | .ndo_start_xmit = start_xmit, | 712 | .ndo_start_xmit = start_xmit, |
683 | .ndo_validate_addr = eth_validate_addr, | 713 | .ndo_validate_addr = eth_validate_addr, |
684 | .ndo_set_mac_address = eth_mac_addr, | 714 | .ndo_set_mac_address = eth_mac_addr, |
715 | .ndo_set_rx_mode = virtnet_set_rx_mode, | ||
685 | .ndo_change_mtu = virtnet_change_mtu, | 716 | .ndo_change_mtu = virtnet_change_mtu, |
686 | #ifdef CONFIG_NET_POLL_CONTROLLER | 717 | #ifdef CONFIG_NET_POLL_CONTROLLER |
687 | .ndo_poll_controller = virtnet_netpoll, | 718 | .ndo_poll_controller = virtnet_netpoll, |
@@ -897,6 +928,7 @@ static unsigned int features[] = { | |||
897 | VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, | 928 | VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, |
898 | VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ | 929 | VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ |
899 | VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, | 930 | VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, |
931 | VIRTIO_NET_F_CTRL_RX, | ||
900 | VIRTIO_F_NOTIFY_ON_EMPTY, | 932 | VIRTIO_F_NOTIFY_ON_EMPTY, |
901 | }; | 933 | }; |
902 | 934 | ||