Skip to content

Commit 4d8fcf2

Browse files
alaahlSaeed Mahameed
authored andcommitted
net/mlx5e: Avoid unbounded peer devices when unpairing TC hairpin rules
If the peer device was already unbound, then do not attempt to modify it's resources, otherwise we will crash on dereferencing non-existing device. Fixes: 5c65c56 ("net/mlx5e: Support offloading TC NIC hairpin flows") Signed-off-by: Alaa Hleihel <[email protected]> Reviewed-by: Or Gerlitz <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent 43955a4 commit 4d8fcf2

File tree

6 files changed

+71
-3
lines changed

6 files changed

+71
-3
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include "en_stats.h"
5555
#include "en/fs.h"
5656

57+
extern const struct net_device_ops mlx5e_netdev_ops;
5758
struct page_pool;
5859

5960
#define MLX5E_METADATA_ETHER_TYPE (0x8CE4)

drivers/net/ethernet/mellanox/mlx5/core/en/fs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ struct mlx5e_tc_table {
1616

1717
DECLARE_HASHTABLE(mod_hdr_tbl, 8);
1818
DECLARE_HASHTABLE(hairpin_tbl, 8);
19+
20+
struct notifier_block netdevice_nb;
1921
};
2022

2123
struct mlx5e_flow_table {

drivers/net/ethernet/mellanox/mlx5/core/en_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4315,7 +4315,7 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
43154315
}
43164316
}
43174317

4318-
static const struct net_device_ops mlx5e_netdev_ops = {
4318+
const struct net_device_ops mlx5e_netdev_ops = {
43194319
.ndo_open = mlx5e_open,
43204320
.ndo_stop = mlx5e_close,
43214321
.ndo_start_xmit = mlx5e_xmit,

drivers/net/ethernet/mellanox/mlx5/core/en_tc.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2946,14 +2946,71 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
29462946
return 0;
29472947
}
29482948

2949+
static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv,
2950+
struct mlx5e_priv *peer_priv)
2951+
{
2952+
struct mlx5_core_dev *peer_mdev = peer_priv->mdev;
2953+
struct mlx5e_hairpin_entry *hpe;
2954+
u16 peer_vhca_id;
2955+
int bkt;
2956+
2957+
if (!same_hw_devs(priv, peer_priv))
2958+
return;
2959+
2960+
peer_vhca_id = MLX5_CAP_GEN(peer_mdev, vhca_id);
2961+
2962+
hash_for_each(priv->fs.tc.hairpin_tbl, bkt, hpe, hairpin_hlist) {
2963+
if (hpe->peer_vhca_id == peer_vhca_id)
2964+
hpe->hp->pair->peer_gone = true;
2965+
}
2966+
}
2967+
2968+
static int mlx5e_tc_netdev_event(struct notifier_block *this,
2969+
unsigned long event, void *ptr)
2970+
{
2971+
struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
2972+
struct mlx5e_flow_steering *fs;
2973+
struct mlx5e_priv *peer_priv;
2974+
struct mlx5e_tc_table *tc;
2975+
struct mlx5e_priv *priv;
2976+
2977+
if (ndev->netdev_ops != &mlx5e_netdev_ops ||
2978+
event != NETDEV_UNREGISTER ||
2979+
ndev->reg_state == NETREG_REGISTERED)
2980+
return NOTIFY_DONE;
2981+
2982+
tc = container_of(this, struct mlx5e_tc_table, netdevice_nb);
2983+
fs = container_of(tc, struct mlx5e_flow_steering, tc);
2984+
priv = container_of(fs, struct mlx5e_priv, fs);
2985+
peer_priv = netdev_priv(ndev);
2986+
if (priv == peer_priv ||
2987+
!(priv->netdev->features & NETIF_F_HW_TC))
2988+
return NOTIFY_DONE;
2989+
2990+
mlx5e_tc_hairpin_update_dead_peer(priv, peer_priv);
2991+
2992+
return NOTIFY_DONE;
2993+
}
2994+
29492995
int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
29502996
{
29512997
struct mlx5e_tc_table *tc = &priv->fs.tc;
2998+
int err;
29522999

29533000
hash_init(tc->mod_hdr_tbl);
29543001
hash_init(tc->hairpin_tbl);
29553002

2956-
return rhashtable_init(&tc->ht, &tc_ht_params);
3003+
err = rhashtable_init(&tc->ht, &tc_ht_params);
3004+
if (err)
3005+
return err;
3006+
3007+
tc->netdevice_nb.notifier_call = mlx5e_tc_netdev_event;
3008+
if (register_netdevice_notifier(&tc->netdevice_nb)) {
3009+
tc->netdevice_nb.notifier_call = NULL;
3010+
mlx5_core_warn(priv->mdev, "Failed to register netdev notifier\n");
3011+
}
3012+
3013+
return err;
29573014
}
29583015

29593016
static void _mlx5e_tc_del_flow(void *ptr, void *arg)
@@ -2969,6 +3026,9 @@ void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv)
29693026
{
29703027
struct mlx5e_tc_table *tc = &priv->fs.tc;
29713028

3029+
if (tc->netdevice_nb.notifier_call)
3030+
unregister_netdevice_notifier(&tc->netdevice_nb);
3031+
29723032
rhashtable_free_and_destroy(&tc->ht, _mlx5e_tc_del_flow, NULL);
29733033

29743034
if (!IS_ERR_OR_NULL(tc->t)) {

drivers/net/ethernet/mellanox/mlx5/core/transobj.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,8 @@ static void mlx5_hairpin_destroy_queues(struct mlx5_hairpin *hp)
475475

476476
for (i = 0; i < hp->num_channels; i++) {
477477
mlx5_core_destroy_rq(hp->func_mdev, hp->rqn[i]);
478-
mlx5_core_destroy_sq(hp->peer_mdev, hp->sqn[i]);
478+
if (!hp->peer_gone)
479+
mlx5_core_destroy_sq(hp->peer_mdev, hp->sqn[i]);
479480
}
480481
}
481482

@@ -567,6 +568,8 @@ static void mlx5_hairpin_unpair_queues(struct mlx5_hairpin *hp)
567568
MLX5_RQC_STATE_RST, 0, 0);
568569

569570
/* unset peer SQs */
571+
if (hp->peer_gone)
572+
return;
570573
for (i = 0; i < hp->num_channels; i++)
571574
mlx5_hairpin_modify_sq(hp->peer_mdev, hp->sqn[i], MLX5_SQC_STATE_RDY,
572575
MLX5_SQC_STATE_RST, 0, 0);

include/linux/mlx5/transobj.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ struct mlx5_hairpin {
9090

9191
u32 *rqn;
9292
u32 *sqn;
93+
94+
bool peer_gone;
9395
};
9496

9597
struct mlx5_hairpin *

0 commit comments

Comments
 (0)