Skip to content

Commit 28a04c7

Browse files
pmachatadavem330
authored andcommitted
mlxsw: spectrum_router: Move VRF refcounting
When creating a new RIF, bumping RIF count of the containing VR is the last thing to be done. Symmetrically, when destroying a RIF, RIF count is first dropped and only then the rest of the cleanup proceeds. That's a problem for loopback RIFs. Those hold two VR references: one for overlay and one for underlay. mlxsw_sp_rif_destroy() releases the overlay one, and the deconfigure() callback the underlay one. But if both overlay and underlay are the same, and if there are no other artifacts holding the VR alive, this put actually destroys the VR. Later on, when mlxsw_sp_rif_destroy() calls mlxsw_sp_vr_put() for the same VR, the VR will already have been released and the kernel crashes with NULL pointer dereference. The underlying problem is that the RIF under destruction ends up referencing the overlay VR much longer than it claims: all the way until the call to mlxsw_sp_vr_put(). So line up the reference counting properly to reflect this. Make corresponding changes in mlxsw_sp_rif_create() as well for symmetry. Fixes: 6ddb742 ("mlxsw: spectrum_router: Introduce loopback RIFs") Signed-off-by: Petr Machata <[email protected]> Reviewed-by: Ido Schimmel <[email protected]> Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8135961 commit 28a04c7

File tree

1 file changed

+3
-2
lines changed

1 file changed

+3
-2
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5068,6 +5068,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
50685068
vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN);
50695069
if (IS_ERR(vr))
50705070
return ERR_CAST(vr);
5071+
vr->rif_count++;
50715072

50725073
err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index);
50735074
if (err)
@@ -5099,7 +5100,6 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
50995100

51005101
mlxsw_sp_rif_counters_alloc(rif);
51015102
mlxsw_sp->router->rifs[rif_index] = rif;
5102-
vr->rif_count++;
51035103

51045104
return rif;
51055105

@@ -5110,6 +5110,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
51105110
kfree(rif);
51115111
err_rif_alloc:
51125112
err_rif_index_alloc:
5113+
vr->rif_count--;
51135114
mlxsw_sp_vr_put(vr);
51145115
return ERR_PTR(err);
51155116
}
@@ -5124,14 +5125,14 @@ void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
51245125
mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
51255126
vr = &mlxsw_sp->router->vrs[rif->vr_id];
51265127

5127-
vr->rif_count--;
51285128
mlxsw_sp->router->rifs[rif->rif_index] = NULL;
51295129
mlxsw_sp_rif_counters_free(rif);
51305130
ops->deconfigure(rif);
51315131
if (fid)
51325132
/* Loopback RIFs are not associated with a FID. */
51335133
mlxsw_sp_fid_put(fid);
51345134
kfree(rif);
5135+
vr->rif_count--;
51355136
mlxsw_sp_vr_put(vr);
51365137
}
51375138

0 commit comments

Comments
 (0)