mlxsw: spectrum_router: Update nexthop RIF on update
The function mlxsw_sp_nexthop_rif_update() walks the list of nexthops
associated with a RIF, and updates the corresponding entries in the
switch. It is used in particular when a tunnel underlay netdevice moves
to a different VRF, and all the nexthops are migrated over to a new RIF.
The problem is that each nexthop holds a reference to its RIF, and that
is not updated. So after the old RIF is gone, further activity on these
nexthops (such as downing the underlay netdevice) dereferences a
dangling pointer.
Fix the issue by updating rif of impacted nexthops before calling
mlxsw_sp_nexthop_rif_update().
Fixes: 0c5f1cd5ba
("mlxsw: spectrum_router: Generalize __mlxsw_sp_ipip_entry_update_tunnel()")
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
d97cda5f46
commit
09dbf6297f
|
@ -1370,8 +1370,9 @@ static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp *mlxsw_sp,
|
|||
mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp, ipip_entry);
|
||||
}
|
||||
|
||||
static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_rif *rif);
|
||||
static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_rif *old_rif,
|
||||
struct mlxsw_sp_rif *new_rif);
|
||||
static int
|
||||
mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_ipip_entry *ipip_entry,
|
||||
|
@ -1389,17 +1390,18 @@ mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp,
|
|||
return PTR_ERR(new_lb_rif);
|
||||
ipip_entry->ol_lb = new_lb_rif;
|
||||
|
||||
if (keep_encap) {
|
||||
list_splice_init(&old_lb_rif->common.nexthop_list,
|
||||
&new_lb_rif->common.nexthop_list);
|
||||
mlxsw_sp_nexthop_rif_update(mlxsw_sp, &new_lb_rif->common);
|
||||
}
|
||||
if (keep_encap)
|
||||
mlxsw_sp_nexthop_rif_migrate(mlxsw_sp, &old_lb_rif->common,
|
||||
&new_lb_rif->common);
|
||||
|
||||
mlxsw_sp_rif_destroy(&old_lb_rif->common);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_rif *rif);
|
||||
|
||||
/**
|
||||
* Update the offload related to an IPIP entry. This always updates decap, and
|
||||
* in addition to that it also:
|
||||
|
@ -3560,6 +3562,18 @@ static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
|
|||
}
|
||||
}
|
||||
|
||||
static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_rif *old_rif,
|
||||
struct mlxsw_sp_rif *new_rif)
|
||||
{
|
||||
struct mlxsw_sp_nexthop *nh;
|
||||
|
||||
list_splice_init(&old_rif->nexthop_list, &new_rif->nexthop_list);
|
||||
list_for_each_entry(nh, &new_rif->nexthop_list, rif_list_node)
|
||||
nh->rif = new_rif;
|
||||
mlxsw_sp_nexthop_rif_update(mlxsw_sp, new_rif);
|
||||
}
|
||||
|
||||
static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_rif *rif)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue