diff options
author | Sven van Ashbrook <svenva@chromium.org> | 2022-08-30 07:59:39 +0300 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2022-09-01 00:55:50 +0300 |
commit | 7305b78ae45f2ce19fbb9e83d7a8c45214d2cdc9 (patch) | |
tree | 228cf5a5ea80c11a8c39e67727fc4833db0e9621 /drivers/net/usb/r8152.c | |
parent | f029c781dd6d8e2f13593c927c66db7e8826ed28 (diff) | |
download | linux-7305b78ae45f2ce19fbb9e83d7a8c45214d2cdc9.tar.xz |
r8152: allow userland to disable multicast
The rtl8152 driver does not disable multicasting when userspace asks
it to. For example:
$ ifconfig eth0 -multicast -allmulti
$ tcpdump -p -i eth0 # will still capture multicast frames
Fix by clearing the device multicast filter table when multicast and
allmulti are both unset.
Tested as follows:
- Set multicast on eth0 network interface
- verify that multicast packets are coming in:
$ tcpdump -p -i eth0
- Clear multicast and allmulti on eth0 network interface
- verify that no more multicast packets are coming in:
$ tcpdump -p -i eth0
Signed-off-by: Sven van Ashbrook <svenva@chromium.org>
Acked-by: Hayes Wang <hayeswang@realtek.com>
Link: https://lore.kernel.org/r/20220830045923.net-next.v1.1.I4fee0ac057083d4f848caf0fa3a9fd466fc374a0@changeid
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/usb/r8152.c')
-rw-r--r-- | drivers/net/usb/r8152.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 45dcc3fc526d..dca6f71c4bfe 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -2727,22 +2727,26 @@ static void _rtl8152_set_rx_mode(struct net_device *netdev) ocp_data |= RCR_AM | RCR_AAP; mc_filter[1] = 0xffffffff; mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(netdev) > multicast_filter_limit) || - (netdev->flags & IFF_ALLMULTI)) { + } else if ((netdev->flags & IFF_MULTICAST && + netdev_mc_count(netdev) > multicast_filter_limit) || + (netdev->flags & IFF_ALLMULTI)) { /* Too many to filter perfectly -- accept all multicasts. */ ocp_data |= RCR_AM; mc_filter[1] = 0xffffffff; mc_filter[0] = 0xffffffff; } else { - struct netdev_hw_addr *ha; - mc_filter[1] = 0; mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, netdev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - ocp_data |= RCR_AM; + if (netdev->flags & IFF_MULTICAST) { + struct netdev_hw_addr *ha; + + netdev_for_each_mc_addr(ha, netdev) { + int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; + + mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); + ocp_data |= RCR_AM; + } } } |