From: Thomas Bogendoerfer <tbogendoerfer@suse.de>
Subject: mlx5: kabi protect lag_mp
Patch-mainline: Never, kABI workaround
References: git-fixes
Commits 27b0420fd959 ("net/mlx5e: Lag, Fix use-after-free in fib event
handler") and 4a2a664ed879 ("net/mlx5e: Lag, Don't skip fib events on
current dst") extend struct lag_mp, which breaks KABI. Since lag_mp
is embedded into struct mlx5_lag we introduce a new struct holding
the new fields, place them kabi protected inside struct mlx5_lag and
change all code referencing them.
Signed-off-by: homas Bogendoerfer <tbogendoerfer@suse.de>
---
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h | 3 +
drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c | 38 ++++++++++++----------
drivers/net/ethernet/mellanox/mlx5/core/lag/mp.h | 15 +++++---
3 files changed, 33 insertions(+), 23 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
@@ -54,6 +54,9 @@ struct mlx5_lag {
struct notifier_block nb;
struct lag_mp lag_mp;
struct mlx5_lag_port_sel port_sel;
+#ifndef __GENKSYMS__
+ struct lag_mp_fib lag_mp_fib;
+#endif
};
static inline struct mlx5_lag *
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
@@ -100,12 +100,15 @@ static void mlx5_lag_fib_event_flush(str
flush_workqueue(mp->wq);
}
-static void mlx5_lag_fib_set(struct lag_mp *mp, struct fib_info *fi, u32 dst, int dst_len)
+static void mlx5_lag_fib_set(struct mlx5_lag *ldev, struct fib_info *fi, u32 dst, int dst_len)
{
- mp->fib.mfi = fi;
- mp->fib.priority = fi->fib_priority;
- mp->fib.dst = dst;
- mp->fib.dst_len = dst_len;
+ struct lag_mp *mp = &ldev->lag_mp;
+ struct lag_mp_fib *mp_fib = &ldev->lag_mp_fib;
+
+ mp->mfi = fi;
+ mp_fib->priority = fi->fib_priority;
+ mp_fib->dst = dst;
+ mp_fib->dst_len = dst_len;
}
struct mlx5_fib_event_work {
@@ -123,21 +126,22 @@ static void mlx5_lag_fib_route_event(str
{
struct fib_info *fi = fen_info->fi;
struct lag_mp *mp = &ldev->lag_mp;
+ struct lag_mp_fib *mp_fib = &ldev->lag_mp_fib;
struct fib_nh *fib_nh0, *fib_nh1;
unsigned int nhs;
/* Handle delete event */
if (event == FIB_EVENT_ENTRY_DEL) {
/* stop track */
- if (mp->fib.mfi == fi)
- mp->fib.mfi = NULL;
+ if (mp->mfi == fi)
+ mp->mfi = NULL;
return;
}
/* Handle multipath entry with lower priority value */
- if (mp->fib.mfi && mp->fib.mfi != fi &&
- (mp->fib.dst != fen_info->dst || mp->fib.dst_len != fen_info->dst_len) &&
- fi->fib_priority >= mp->fib.priority)
+ if (mp->mfi && mp->mfi != fi &&
+ (mp_fib->dst != fen_info->dst || mp_fib->dst_len != fen_info->dst_len) &&
+ fi->fib_priority >= mp_fib->priority)
return;
/* Handle add/replace event */
@@ -153,7 +157,7 @@ static void mlx5_lag_fib_route_event(str
i++;
mlx5_lag_set_port_affinity(ldev, i);
- mlx5_lag_fib_set(mp, fi, fen_info->dst, fen_info->dst_len);
+ mlx5_lag_fib_set(ldev, fi, fen_info->dst, fen_info->dst_len);
}
return;
@@ -175,7 +179,7 @@ static void mlx5_lag_fib_route_event(str
}
/* First time we see multipath route */
- if (!mp->fib.mfi && !__mlx5_lag_is_active(ldev)) {
+ if (!mp->mfi && !__mlx5_lag_is_active(ldev)) {
struct lag_tracker tracker;
tracker = ldev->tracker;
@@ -183,7 +187,7 @@ static void mlx5_lag_fib_route_event(str
}
mlx5_lag_set_port_affinity(ldev, MLX5_LAG_NORMAL_AFFINITY);
- mlx5_lag_fib_set(mp, fi, fen_info->dst, fen_info->dst_len);
+ mlx5_lag_fib_set(ldev, fi, fen_info->dst, fen_info->dst_len);
}
static void mlx5_lag_fib_nexthop_event(struct mlx5_lag *ldev,
@@ -194,7 +198,7 @@ static void mlx5_lag_fib_nexthop_event(s
struct lag_mp *mp = &ldev->lag_mp;
/* Check the nh event is related to the route */
- if (!mp->fib.mfi || mp->fib.mfi != fi)
+ if (!mp->mfi || mp->mfi != fi)
return;
/* nh added/removed */
@@ -323,7 +327,7 @@ void mlx5_lag_mp_reset(struct mlx5_lag *
/* Clear mfi, as it might become stale when a route delete event
* has been missed, see mlx5_lag_fib_route_event().
*/
- ldev->lag_mp.fib.mfi = NULL;
+ ldev->lag_mp.mfi = NULL;
}
int mlx5_lag_mp_init(struct mlx5_lag *ldev)
@@ -334,7 +338,7 @@ int mlx5_lag_mp_init(struct mlx5_lag *ld
/* always clear mfi, as it might become stale when a route delete event
* has been missed
*/
- mp->fib.mfi = NULL;
+ mp->mfi = NULL;
if (mp->fib_nb.notifier_call)
return 0;
@@ -364,5 +368,5 @@ void mlx5_lag_mp_cleanup(struct mlx5_lag
unregister_fib_notifier(&init_net, &mp->fib_nb);
destroy_workqueue(mp->wq);
mp->fib_nb.notifier_call = NULL;
- mp->fib.mfi = NULL;
+ mp->mfi = NULL;
}
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.h
@@ -15,15 +15,18 @@ enum mlx5_lag_port_affinity {
struct lag_mp {
struct notifier_block fib_nb;
- struct {
- const void *mfi; /* used in tracking fib events */
- u32 priority;
- u32 dst;
- int dst_len;
- } fib;
+ struct fib_info *mfi; /* used in tracking fib events */
struct workqueue_struct *wq;
};
+#ifndef __GENKSYMS__
+struct lag_mp_fib {
+ u32 priority;
+ u32 dst;
+ int dst_len;
+};
+#endif
+
#ifdef CONFIG_MLX5_ESWITCH
void mlx5_lag_mp_reset(struct mlx5_lag *ldev);