History

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.

Alaa Hleihel committed 8 years ago

Commit 4d8fcf21 parent 43955a46 files · +71 −3Browse files

Unified · Split

6 files
  1. drivers/net/ethernet/mellanox/mlx5/core/en.h +1 −0
  2. drivers/net/ethernet/mellanox/mlx5/core/en/fs.h +2 −0
  3. drivers/net/ethernet/mellanox/mlx5/core/en_main.c +1 −1
  4. drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +61 −1
  5. drivers/net/ethernet/mellanox/mlx5/core/transobj.c +4 −1
  6. include/linux/mlx5/transobj.h +2 −0
drivers/net/ethernet/mellanox/mlx5/core/en.h+1−0
@@ -54,6 +54,7 @@ · 53 unmodified lines
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+2−0
@@ -16,6 +16,8 @@ struct mlx5e_tc_table { · 15 unmodified lines
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+1−1
@@ -4315,7 +4315,7 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp) · 4314 unmodified lines
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+61−1
@@ -2946,14 +2946,71 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv, · 2945 unmodified lines
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) · 9 unmodified lines
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+4−1
@@ -475,7 +475,8 @@ static void mlx5_hairpin_destroy_queues(struct mlx5_hairpin *hp) · 474 unmodified lines
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) · 85 unmodified lines
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+2−0
@@ -90,6 +90,8 @@ struct mlx5_hairpin { · 89 unmodified lines
9090
9191 u32 *rqn;
9292 u32 *sqn;
93+
94+ bool peer_gone;
9395 };
9496
9597 struct mlx5_hairpin *

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t