Skip to content

Commit

Permalink
net: aquantia: correctly handle macvlan and multicast coexistence
Browse files Browse the repository at this point in the history
macvlan and multicast handling is now mixed up.
The explicit issue is that macvlan interface gets broken (no traffic)
after clearing MULTICAST flag on the real interface.

We now do separate logic and consider both ALLMULTI and MULTICAST
flags on the device.

Fixes: 11ba961 ("net: aquantia: Fix IFF_ALLMULTI flag functionality")
Signed-off-by: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Dmitry Bogdanov authored and David S. Miller committed Oct 15, 2019
1 parent d08b9a0 commit 9f051db
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 22 deletions.
4 changes: 1 addition & 3 deletions drivers/net/ethernet/aquantia/atlantic/aq_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,7 @@ static void aq_ndev_set_multicast_settings(struct net_device *ndev)
{
struct aq_nic_s *aq_nic = netdev_priv(ndev);

aq_nic_set_packet_filter(aq_nic, ndev->flags);

aq_nic_set_multicast_list(aq_nic, ndev);
(void)aq_nic_set_multicast_list(aq_nic, ndev);
}

static int aq_ndo_vlan_rx_add_vid(struct net_device *ndev, __be16 proto,
Expand Down
32 changes: 16 additions & 16 deletions drivers/net/ethernet/aquantia/atlantic/aq_nic.c
Original file line number Diff line number Diff line change
Expand Up @@ -631,39 +631,39 @@ int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags)

int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev)
{
unsigned int packet_filter = self->packet_filter;
const struct aq_hw_ops *hw_ops = self->aq_hw_ops;
struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
unsigned int packet_filter = ndev->flags;
struct netdev_hw_addr *ha = NULL;
unsigned int i = 0U;
int err = 0;

self->mc_list.count = 0;
if (netdev_uc_count(ndev) > AQ_HW_MULTICAST_ADDRESS_MAX) {
packet_filter |= IFF_PROMISC;
} else {
netdev_for_each_uc_addr(ha, ndev) {
ether_addr_copy(self->mc_list.ar[i++], ha->addr);

if (i >= AQ_HW_MULTICAST_ADDRESS_MAX)
break;
}
}

if (i + netdev_mc_count(ndev) > AQ_HW_MULTICAST_ADDRESS_MAX) {
packet_filter |= IFF_ALLMULTI;
} else {
netdev_for_each_mc_addr(ha, ndev) {
ether_addr_copy(self->mc_list.ar[i++], ha->addr);

if (i >= AQ_HW_MULTICAST_ADDRESS_MAX)
break;
cfg->is_mc_list_enabled = !!(packet_filter & IFF_MULTICAST);
if (cfg->is_mc_list_enabled) {
if (i + netdev_mc_count(ndev) > AQ_HW_MULTICAST_ADDRESS_MAX) {
packet_filter |= IFF_ALLMULTI;
} else {
netdev_for_each_mc_addr(ha, ndev) {
ether_addr_copy(self->mc_list.ar[i++],
ha->addr);
}
}
}

if (i > 0 && i <= AQ_HW_MULTICAST_ADDRESS_MAX) {
packet_filter |= IFF_MULTICAST;
self->mc_list.count = i;
self->aq_hw_ops->hw_multicast_list_set(self->aq_hw,
self->mc_list.ar,
self->mc_list.count);
err = hw_ops->hw_multicast_list_set(self->aq_hw,
self->mc_list.ar,
self->mc_list.count);
}
return aq_nic_set_packet_filter(self, packet_filter);
}
Expand Down
7 changes: 4 additions & 3 deletions drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
Original file line number Diff line number Diff line change
Expand Up @@ -818,14 +818,15 @@ static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self,
cfg->is_vlan_force_promisc);

hw_atl_rpfl2multicast_flr_en_set(self,
IS_FILTER_ENABLED(IFF_ALLMULTI), 0);
IS_FILTER_ENABLED(IFF_ALLMULTI) &&
IS_FILTER_ENABLED(IFF_MULTICAST), 0);

hw_atl_rpfl2_accept_all_mc_packets_set(self,
IS_FILTER_ENABLED(IFF_ALLMULTI));
IS_FILTER_ENABLED(IFF_ALLMULTI) &&
IS_FILTER_ENABLED(IFF_MULTICAST));

hw_atl_rpfl2broadcast_en_set(self, IS_FILTER_ENABLED(IFF_BROADCAST));

cfg->is_mc_list_enabled = IS_FILTER_ENABLED(IFF_MULTICAST);

for (i = HW_ATL_B0_MAC_MIN; i < HW_ATL_B0_MAC_MAX; ++i)
hw_atl_rpfl2_uc_flr_en_set(self,
Expand Down

0 comments on commit 9f051db

Please sign in to comment.