Commit 7c33e739 authored by Maor Dickman's avatar Maor Dickman Committed by Saeed Mahameed

net/mlx5e: multipath, support routes with more than 2 nexthops

Today multipath offload is only supported when the number of
nexthops is 2 which block the use of it in case of system with
2 NICs.

This patch solve it by enabling multipath offload per NIC if
2 nexthops of the route are its uplinks.
Signed-off-by: default avatarMaor Dickman <maord@nvidia.com>
Reviewed-by: default avatarRoi Dayan <roid@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent 6fda078d
...@@ -118,13 +118,41 @@ struct mlx5_fib_event_work { ...@@ -118,13 +118,41 @@ struct mlx5_fib_event_work {
}; };
}; };
static struct net_device*
mlx5_lag_get_next_fib_dev(struct mlx5_lag *ldev,
struct fib_info *fi,
struct net_device *current_dev)
{
struct net_device *fib_dev;
int i, ldev_idx, nhs;
nhs = fib_info_num_path(fi);
i = 0;
if (current_dev) {
for (; i < nhs; i++) {
fib_dev = fib_info_nh(fi, i)->fib_nh_dev;
if (fib_dev == current_dev) {
i++;
break;
}
}
}
for (; i < nhs; i++) {
fib_dev = fib_info_nh(fi, i)->fib_nh_dev;
ldev_idx = mlx5_lag_dev_get_netdev_idx(ldev, fib_dev);
if (ldev_idx >= 0)
return ldev->pf[ldev_idx].netdev;
}
return NULL;
}
static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event, static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event,
struct fib_entry_notifier_info *fen_info) struct fib_entry_notifier_info *fen_info)
{ {
struct net_device *nh_dev0, *nh_dev1;
struct fib_info *fi = fen_info->fi; struct fib_info *fi = fen_info->fi;
struct lag_mp *mp = &ldev->lag_mp; struct lag_mp *mp = &ldev->lag_mp;
struct fib_nh *fib_nh0, *fib_nh1;
unsigned int nhs;
/* Handle delete event */ /* Handle delete event */
if (event == FIB_EVENT_ENTRY_DEL) { if (event == FIB_EVENT_ENTRY_DEL) {
...@@ -140,16 +168,25 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event, ...@@ -140,16 +168,25 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event,
fi->fib_priority >= mp->fib.priority) fi->fib_priority >= mp->fib.priority)
return; return;
nh_dev0 = mlx5_lag_get_next_fib_dev(ldev, fi, NULL);
nh_dev1 = mlx5_lag_get_next_fib_dev(ldev, fi, nh_dev0);
/* Handle add/replace event */ /* Handle add/replace event */
nhs = fib_info_num_path(fi); if (!nh_dev0) {
if (nhs == 1) { if (mp->fib.dst == fen_info->dst && mp->fib.dst_len == fen_info->dst_len)
if (__mlx5_lag_is_active(ldev)) { mp->fib.mfi = NULL;
struct fib_nh *nh = fib_info_nh(fi, 0); return;
struct net_device *nh_dev = nh->fib_nh_dev; }
int i = mlx5_lag_dev_get_netdev_idx(ldev, nh_dev);
if (i < 0) if (nh_dev0 == nh_dev1) {
return; mlx5_core_warn(ldev->pf[MLX5_LAG_P1].dev,
"Multipath offload doesn't support routes with multiple nexthops of the same device");
return;
}
if (!nh_dev1) {
if (__mlx5_lag_is_active(ldev)) {
int i = mlx5_lag_dev_get_netdev_idx(ldev, nh_dev0);
i++; i++;
mlx5_lag_set_port_affinity(ldev, i); mlx5_lag_set_port_affinity(ldev, i);
...@@ -159,21 +196,6 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event, ...@@ -159,21 +196,6 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event,
return; return;
} }
if (nhs != 2)
return;
/* Verify next hops are ports of the same hca */
fib_nh0 = fib_info_nh(fi, 0);
fib_nh1 = fib_info_nh(fi, 1);
if (!(fib_nh0->fib_nh_dev == ldev->pf[MLX5_LAG_P1].netdev &&
fib_nh1->fib_nh_dev == ldev->pf[MLX5_LAG_P2].netdev) &&
!(fib_nh0->fib_nh_dev == ldev->pf[MLX5_LAG_P2].netdev &&
fib_nh1->fib_nh_dev == ldev->pf[MLX5_LAG_P1].netdev)) {
mlx5_core_warn(ldev->pf[MLX5_LAG_P1].dev,
"Multipath offload require two ports of the same HCA\n");
return;
}
/* First time we see multipath route */ /* First time we see multipath route */
if (!mp->fib.mfi && !__mlx5_lag_is_active(ldev)) { if (!mp->fib.mfi && !__mlx5_lag_is_active(ldev)) {
struct lag_tracker tracker; struct lag_tracker tracker;
...@@ -268,7 +290,6 @@ static int mlx5_lag_fib_event(struct notifier_block *nb, ...@@ -268,7 +290,6 @@ static int mlx5_lag_fib_event(struct notifier_block *nb,
struct mlx5_fib_event_work *fib_work; struct mlx5_fib_event_work *fib_work;
struct fib_entry_notifier_info *fen_info; struct fib_entry_notifier_info *fen_info;
struct fib_nh_notifier_info *fnh_info; struct fib_nh_notifier_info *fnh_info;
struct net_device *fib_dev;
struct fib_info *fi; struct fib_info *fi;
if (info->family != AF_INET) if (info->family != AF_INET)
...@@ -285,11 +306,7 @@ static int mlx5_lag_fib_event(struct notifier_block *nb, ...@@ -285,11 +306,7 @@ static int mlx5_lag_fib_event(struct notifier_block *nb,
fi = fen_info->fi; fi = fen_info->fi;
if (fi->nh) if (fi->nh)
return NOTIFY_DONE; return NOTIFY_DONE;
fib_dev = fib_info_nh(fen_info->fi, 0)->fib_nh_dev;
if (fib_dev != ldev->pf[MLX5_LAG_P1].netdev &&
fib_dev != ldev->pf[MLX5_LAG_P2].netdev) {
return NOTIFY_DONE;
}
fib_work = mlx5_lag_init_fib_work(ldev, event); fib_work = mlx5_lag_init_fib_work(ldev, event);
if (!fib_work) if (!fib_work)
return NOTIFY_DONE; return NOTIFY_DONE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment