| Author | Tokens | Token Proportion | Commits | Commit Proportion |
|---|---|---|---|---|
| Shay Drory | 972 | 73.19% | 12 | 40.00% |
| Eli Cohen | 122 | 9.19% | 3 | 10.00% |
| Rongwei Liu | 68 | 5.12% | 2 | 6.67% |
| Mark Bloch | 60 | 4.52% | 5 | 16.67% |
| Roi Dayan | 50 | 3.77% | 3 | 10.00% |
| Moshe Shemesh | 32 | 2.41% | 1 | 3.33% |
| Aviv Heller | 15 | 1.13% | 1 | 3.33% |
| Or Har-Toov | 5 | 0.38% | 1 | 3.33% |
| Rabie Loulou | 3 | 0.23% | 1 | 3.33% |
| Vlad Buslov | 1 | 0.08% | 1 | 3.33% |
| Total | 1328 | 30 |
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB /* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ #include <linux/netdevice.h> #include <linux/mlx5/driver.h> #include <linux/mlx5/eswitch.h> #include "mlx5_core.h" #include "lag.h" #include "eswitch.h" bool mlx5_lag_shared_fdb_supported_filter(struct mlx5_lag *ldev, u32 filter) { int idx = mlx5_lag_get_dev_index_by_seq_filter(ldev, MLX5_LAG_P1, filter); struct mlx5_core_dev *dev0, *dev; bool ret = false; int i; if (idx < 0) return false; dev0 = mlx5_lag_pf(ldev, idx)->dev; mlx5_lag_for_each(i, 0, ldev, filter) { if (i == idx) continue; dev = mlx5_lag_pf(ldev, i)->dev; if (is_mdev_switchdev_mode(dev) && mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) && MLX5_CAP_GEN(dev, lag_native_fdb_selection) && MLX5_CAP_ESW(dev, root_ft_on_other_esw) && mlx5_eswitch_is_peer(dev0->priv.eswitch, dev->priv.eswitch)) continue; return false; } if (is_mdev_switchdev_mode(dev0) && mlx5_eswitch_vport_match_metadata_enabled(dev0->priv.eswitch) && mlx5_esw_offloads_devcom_is_ready(dev0->priv.eswitch) && MLX5_CAP_ESW(dev0, esw_shared_ingress_acl)) ret = true; return ret; } bool mlx5_lag_shared_fdb_supported(struct mlx5_lag *ldev) { return mlx5_lag_shared_fdb_supported_filter(ldev, MLX5_LAG_FILTER_PORTS); } static int mlx5_lag_create_single_fdb_filter(struct mlx5_lag *ldev, u32 filter) { int master_idx = mlx5_lag_get_dev_index_by_seq_filter(ldev, MLX5_LAG_P1, filter); struct mlx5_eswitch *master_esw; struct mlx5_core_dev *dev0; int i, j; int err; if (master_idx < 0) return -EINVAL; dev0 = mlx5_lag_pf(ldev, master_idx)->dev; master_esw = dev0->priv.eswitch; mlx5_lag_for_each(i, 0, ldev, filter) { struct mlx5_eswitch *slave_esw; if (i == master_idx) continue; slave_esw = mlx5_lag_pf(ldev, i)->dev->priv.eswitch; err = mlx5_eswitch_offloads_single_fdb_add_one(master_esw, slave_esw, ldev->ports); if (err) goto err; } return 0; err: mlx5_lag_for_each_reverse(j, i - 1, 0, ldev, filter) { struct mlx5_eswitch *slave_esw; if (j == master_idx) continue; slave_esw = mlx5_lag_pf(ldev, j)->dev->priv.eswitch; mlx5_eswitch_offloads_single_fdb_del_one(master_esw, slave_esw); } return err; } int mlx5_lag_create_vport_lag(struct mlx5_lag *ldev, u32 group_id) { u32 filter = group_id ? group_id : MLX5_LAG_FILTER_ALL; int master_idx = mlx5_lag_get_dev_index_by_seq_filter(ldev, MLX5_LAG_P1, filter); struct mlx5_eswitch *master_esw; struct mlx5_core_dev *dev0; int i, j; int err; if (master_idx < 0) return -EINVAL; dev0 = mlx5_lag_pf(ldev, master_idx)->dev; master_esw = dev0->priv.eswitch; mlx5_lag_for_each(i, 0, ldev, filter) { struct mlx5_eswitch *slave_esw; if (i == master_idx) continue; slave_esw = mlx5_lag_pf(ldev, i)->dev->priv.eswitch; err = mlx5_eswitch_offloads_vport_lag_add_one(master_esw, slave_esw); if (err) goto err; } return 0; err: mlx5_lag_for_each_reverse(j, i - 1, 0, ldev, filter) { struct mlx5_eswitch *slave_esw; if (j == master_idx) continue; slave_esw = mlx5_lag_pf(ldev, j)->dev->priv.eswitch; mlx5_eswitch_offloads_vport_lag_del_one(master_esw, slave_esw); } return err; } int mlx5_lag_destroy_vport_lag(struct mlx5_lag *ldev, u32 group_id) { u32 filter = group_id ? group_id : MLX5_LAG_FILTER_ALL; int master_idx = mlx5_lag_get_dev_index_by_seq_filter(ldev, MLX5_LAG_P1, filter); struct mlx5_eswitch *master_esw; struct mlx5_core_dev *dev0; int i; if (master_idx < 0) return 0; dev0 = mlx5_lag_pf(ldev, master_idx)->dev; master_esw = dev0->priv.eswitch; mlx5_lag_for_each(i, 0, ldev, filter) { struct mlx5_core_dev *dev; if (i == master_idx) continue; dev = mlx5_lag_pf(ldev, i)->dev; mlx5_eswitch_offloads_vport_lag_del_one(master_esw, dev->priv.eswitch); } return 0; } static void mlx5_lag_destroy_single_fdb_filter(struct mlx5_lag *ldev, u32 filter) { int master_idx = mlx5_lag_get_dev_index_by_seq_filter(ldev, MLX5_LAG_P1, filter); struct mlx5_eswitch *master_esw; struct mlx5_eswitch *peer_esw; int i; if (master_idx < 0) return; master_esw = mlx5_lag_pf(ldev, master_idx)->dev->priv.eswitch; mlx5_lag_for_each(i, 0, ldev, filter) { if (i == master_idx) continue; peer_esw = mlx5_lag_pf(ldev, i)->dev->priv.eswitch; mlx5_eswitch_offloads_single_fdb_del_one(master_esw, peer_esw); } } int mlx5_lag_create_single_fdb(struct mlx5_lag *ldev) { return mlx5_lag_create_single_fdb_filter(ldev, MLX5_LAG_FILTER_ALL); } void mlx5_lag_destroy_single_fdb(struct mlx5_lag *ldev) { mlx5_lag_destroy_single_fdb_filter(ldev, MLX5_LAG_FILTER_ALL); } /** * mlx5_lag_shared_fdb_create - Create shared FDB LAG * @ldev: LAG device * @tracker: LAG tracker (NULL for SD) * @mode: LAG mode (unused for SD) * @group_id: SD group ID; 0 (MLX5_LAG_FILTER_PORTS) for ports LAG; * MLX5_LAG_FILTER_ALL for all-device (mpesw) LAG * * When group_id is 0 (MLX5_LAG_FILTER_PORTS) or MLX5_LAG_FILTER_ALL, * activates a FW LAG with shared FDB. * When group_id is a specific SD group ID, creates a software-only shared * FDB scoped to that group (no FW LAG commands). * * Return: 0 on success, negative error code on failure. */ int mlx5_lag_shared_fdb_create(struct mlx5_lag *ldev, struct lag_tracker *tracker, enum mlx5_lag_mode mode, u32 group_id) { u32 filter = group_id ? group_id : MLX5_LAG_FILTER_ALL; int idx = mlx5_lag_get_dev_index_by_seq_filter(ldev, MLX5_LAG_P1, filter); struct mlx5_core_dev *dev0; struct lag_func *pf; int err; int i; if (idx < 0) return -EINVAL; dev0 = mlx5_lag_pf(ldev, idx)->dev; mlx5_lag_remove_devices_filter(ldev, filter); if (filter == MLX5_LAG_FILTER_PORTS || filter == MLX5_LAG_FILTER_ALL) { err = mlx5_activate_lag(ldev, tracker, mode, true); if (err) { mlx5_core_warn(dev0, "Failed to create LAG in shared FDB mode (%d)\n", err); goto err_add_devices; } } else { err = mlx5_lag_create_single_fdb_filter(ldev, group_id); if (err) { mlx5_core_warn(dev0, "Failed to create SD shared FDB (%d)\n", err); goto err_add_devices; } mlx5_lag_for_each(i, 0, ldev, filter) { pf = mlx5_lag_pf(ldev, i); pf->sd_fdb_active = true; } BLOCKING_INIT_NOTIFIER_HEAD(&dev0->priv.lag_nh); } mlx5_lag_rescan_dev_locked(ldev, dev0, true); err = mlx5_lag_reload_ib_reps_from_locked(ldev, 0, filter, false); if (err) { mlx5_core_err(dev0, "Failed to enable lag\n"); goto err_rescan_drivers; } if (filter == MLX5_LAG_FILTER_PORTS || filter == MLX5_LAG_FILTER_ALL) mlx5_lag_set_vports_agg_speed(ldev); return 0; err_rescan_drivers: mlx5_lag_rescan_dev_locked(ldev, dev0, false); if (filter == MLX5_LAG_FILTER_PORTS || filter == MLX5_LAG_FILTER_ALL) { mlx5_deactivate_lag(ldev); } else { mlx5_lag_for_each(i, 0, ldev, filter) { pf = mlx5_lag_pf(ldev, i); pf->sd_fdb_active = false; } mlx5_lag_destroy_single_fdb_filter(ldev, group_id); } err_add_devices: mlx5_lag_add_devices_filter(ldev, filter); mlx5_lag_reload_ib_reps_from_locked(ldev, 0, filter, true); return err; } void mlx5_lag_shared_fdb_destroy(struct mlx5_lag *ldev, u32 group_id) { u32 filter = group_id ? group_id : MLX5_LAG_FILTER_ALL; struct lag_func *pf; int err; int i; mlx5_lag_remove_devices_filter(ldev, filter); if (filter == MLX5_LAG_FILTER_PORTS || filter == MLX5_LAG_FILTER_ALL) { err = mlx5_deactivate_lag(ldev); if (err) return; } else { mlx5_lag_for_each(i, 0, ldev, filter) { pf = mlx5_lag_pf(ldev, i); pf->sd_fdb_active = false; } mlx5_lag_destroy_single_fdb_filter(ldev, group_id); mlx5_lag_unload_reps_from_locked(ldev, filter); } mlx5_lag_add_devices_filter(ldev, filter); mlx5_lag_reload_ib_reps_from_locked(ldev, MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV, filter, true); }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1