Skip to content

Commit 7a3ce80

Browse files
w1ldptrSaeed Mahameed
authored andcommitted
net/mlx5: Bridge, fix peer entry ageing in LAG mode
With current implementation in single FDB LAG mode all packets are processed by eswitch 0 rules. As such, 'peer' FDB entries receive the packets for rules of other eswitches and are responsible for updating the main entry by sending SWITCHDEV_FDB_ADD_TO_BRIDGE notification from their background update wq task. However, this introduces a race condition when non-zero eswitch instance decides to delete a FDB entry, sends SWITCHDEV_FDB_DEL_TO_BRIDGE notification, but another eswitch's update task refreshes the same entry concurrently while its async delete work is still pending on the workque. In such case another SWITCHDEV_FDB_ADD_TO_BRIDGE event may be generated and entry will remain stuck in FDB marked as 'offloaded' since no more SWITCHDEV_FDB_DEL_TO_BRIDGE notifications are sent for deleting the peer entries. Fix the issue by synchronously marking deleted entries with MLX5_ESW_BRIDGE_FLAG_DELETED flag and skipping them in background update job. Signed-off-by: Vlad Buslov <vladbu@nvidia.com> Reviewed-by: Jianbo Liu <jianbol@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
1 parent 7624e58 commit 7a3ce80

4 files changed

Lines changed: 39 additions & 1 deletion

File tree

drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,17 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb,
467467
/* only handle the event on peers */
468468
if (mlx5_esw_bridge_is_local(dev, rep, esw))
469469
break;
470+
471+
fdb_info = container_of(info,
472+
struct switchdev_notifier_fdb_info,
473+
info);
474+
/* Mark for deletion to prevent the update wq task from
475+
* spuriously refreshing the entry which would mark it again as
476+
* offloaded in SW bridge. After this fallthrough to regular
477+
* async delete code.
478+
*/
479+
mlx5_esw_bridge_fdb_mark_deleted(dev, vport_num, esw_owner_vhca_id, br_offloads,
480+
fdb_info);
470481
fallthrough;
471482
case SWITCHDEV_FDB_ADD_TO_DEVICE:
472483
case SWITCHDEV_FDB_DEL_TO_DEVICE:

drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1748,6 +1748,28 @@ void mlx5_esw_bridge_fdb_update_used(struct net_device *dev, u16 vport_num, u16
17481748
entry->lastuse = jiffies;
17491749
}
17501750

1751+
void mlx5_esw_bridge_fdb_mark_deleted(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
1752+
struct mlx5_esw_bridge_offloads *br_offloads,
1753+
struct switchdev_notifier_fdb_info *fdb_info)
1754+
{
1755+
struct mlx5_esw_bridge_fdb_entry *entry;
1756+
struct mlx5_esw_bridge *bridge;
1757+
1758+
bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1759+
if (!bridge)
1760+
return;
1761+
1762+
entry = mlx5_esw_bridge_fdb_lookup(bridge, fdb_info->addr, fdb_info->vid);
1763+
if (!entry) {
1764+
esw_debug(br_offloads->esw->dev,
1765+
"FDB mark deleted entry with specified key not found (MAC=%pM,vid=%u,vport=%u)\n",
1766+
fdb_info->addr, fdb_info->vid, vport_num);
1767+
return;
1768+
}
1769+
1770+
entry->flags |= MLX5_ESW_BRIDGE_FLAG_DELETED;
1771+
}
1772+
17511773
void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
17521774
struct mlx5_esw_bridge_offloads *br_offloads,
17531775
struct switchdev_notifier_fdb_info *fdb_info)
@@ -1810,7 +1832,8 @@ void mlx5_esw_bridge_update(struct mlx5_esw_bridge_offloads *br_offloads)
18101832
unsigned long lastuse =
18111833
(unsigned long)mlx5_fc_query_lastuse(entry->ingress_counter);
18121834

1813-
if (entry->flags & MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER)
1835+
if (entry->flags & (MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER |
1836+
MLX5_ESW_BRIDGE_FLAG_DELETED))
18141837
continue;
18151838

18161839
if (time_after(lastuse, entry->lastuse))

drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ int mlx5_esw_bridge_vport_peer_unlink(struct net_device *br_netdev, u16 vport_nu
6262
void mlx5_esw_bridge_fdb_update_used(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
6363
struct mlx5_esw_bridge_offloads *br_offloads,
6464
struct switchdev_notifier_fdb_info *fdb_info);
65+
void mlx5_esw_bridge_fdb_mark_deleted(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
66+
struct mlx5_esw_bridge_offloads *br_offloads,
67+
struct switchdev_notifier_fdb_info *fdb_info);
6568
void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
6669
struct mlx5_esw_bridge_offloads *br_offloads,
6770
struct switchdev_notifier_fdb_info *fdb_info);

drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ struct mlx5_esw_bridge_mdb_key {
133133
enum {
134134
MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER = BIT(0),
135135
MLX5_ESW_BRIDGE_FLAG_PEER = BIT(1),
136+
MLX5_ESW_BRIDGE_FLAG_DELETED = BIT(2),
136137
};
137138

138139
enum {

0 commit comments

Comments
 (0)