Skip to content

Commit 965fa8e

Browse files
idoschdavem330
authored andcommitted
mlxsw: spectrum_router: Make RIF deletion more robust
In the past we had multiple instances where RIFs were not properly deleted. One of the reasons for leaking a RIF was that at the time when IP addresses were flushed from the respective netdev (prompting the destruction of the RIF), the netdev was no longer a mlxsw upper. This caused the inet{,6}addr notification blocks to ignore the NETDEV_DOWN event and leak the RIF. Instead of checking whether the netdev is our upper when an IP address is removed, we can instead check if the netdev has a RIF configured. To look up a RIF we need to access mlxsw private data, so the patch stores the notification blocks inside a mlxsw struct. This then allows us to use container_of() and extract the required private data. Signed-off-by: Ido Schimmel <[email protected]> Reviewed-by: Petr Machata <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 21ffedb commit 965fa8e

File tree

3 files changed

+31
-36
lines changed

3 files changed

+31
-36
lines changed

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

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5414,18 +5414,10 @@ static struct notifier_block mlxsw_sp_inetaddr_valid_nb __read_mostly = {
54145414
.notifier_call = mlxsw_sp_inetaddr_valid_event,
54155415
};
54165416

5417-
static struct notifier_block mlxsw_sp_inetaddr_nb __read_mostly = {
5418-
.notifier_call = mlxsw_sp_inetaddr_event,
5419-
};
5420-
54215417
static struct notifier_block mlxsw_sp_inet6addr_valid_nb __read_mostly = {
54225418
.notifier_call = mlxsw_sp_inet6addr_valid_event,
54235419
};
54245420

5425-
static struct notifier_block mlxsw_sp_inet6addr_nb __read_mostly = {
5426-
.notifier_call = mlxsw_sp_inet6addr_event,
5427-
};
5428-
54295421
static const struct pci_device_id mlxsw_sp1_pci_id_table[] = {
54305422
{PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0},
54315423
{0, },
@@ -5451,9 +5443,7 @@ static int __init mlxsw_sp_module_init(void)
54515443
int err;
54525444

54535445
register_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
5454-
register_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
54555446
register_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
5456-
register_inet6addr_notifier(&mlxsw_sp_inet6addr_nb);
54575447

54585448
err = mlxsw_core_driver_register(&mlxsw_sp1_driver);
54595449
if (err)
@@ -5480,9 +5470,7 @@ static int __init mlxsw_sp_module_init(void)
54805470
err_sp2_core_driver_register:
54815471
mlxsw_core_driver_unregister(&mlxsw_sp1_driver);
54825472
err_sp1_core_driver_register:
5483-
unregister_inet6addr_notifier(&mlxsw_sp_inet6addr_nb);
54845473
unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
5485-
unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
54865474
unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
54875475
return err;
54885476
}
@@ -5493,9 +5481,7 @@ static void __exit mlxsw_sp_module_exit(void)
54935481
mlxsw_pci_driver_unregister(&mlxsw_sp1_pci_driver);
54945482
mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
54955483
mlxsw_core_driver_unregister(&mlxsw_sp1_driver);
5496-
unregister_inet6addr_notifier(&mlxsw_sp_inet6addr_nb);
54975484
unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
5498-
unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
54995485
unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
55005486
}
55015487

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -458,12 +458,8 @@ int mlxsw_sp_netdevice_router_port_event(struct net_device *dev,
458458
unsigned long event, void *ptr);
459459
void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
460460
const struct net_device *macvlan_dev);
461-
int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
462-
unsigned long event, void *ptr);
463461
int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
464462
unsigned long event, void *ptr);
465-
int mlxsw_sp_inet6addr_event(struct notifier_block *unused,
466-
unsigned long event, void *ptr);
467463
int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
468464
unsigned long event, void *ptr);
469465
int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,

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

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ struct mlxsw_sp_router {
7171
bool aborted;
7272
struct notifier_block fib_nb;
7373
struct notifier_block netevent_nb;
74+
struct notifier_block inetaddr_nb;
75+
struct notifier_block inet6addr_nb;
7476
const struct mlxsw_sp_rif_ops **rif_ops_arr;
7577
const struct mlxsw_sp_ipip_ops **ipip_ops_arr;
7678
};
@@ -6778,28 +6780,25 @@ static int __mlxsw_sp_inetaddr_event(struct mlxsw_sp *mlxsw_sp,
67786780
return 0;
67796781
}
67806782

6781-
int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
6782-
unsigned long event, void *ptr)
6783+
static int mlxsw_sp_inetaddr_event(struct notifier_block *nb,
6784+
unsigned long event, void *ptr)
67836785
{
67846786
struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
67856787
struct net_device *dev = ifa->ifa_dev->dev;
6786-
struct mlxsw_sp *mlxsw_sp;
6788+
struct mlxsw_sp_router *router;
67876789
struct mlxsw_sp_rif *rif;
67886790
int err = 0;
67896791

67906792
/* NETDEV_UP event is handled by mlxsw_sp_inetaddr_valid_event */
67916793
if (event == NETDEV_UP)
67926794
goto out;
67936795

6794-
mlxsw_sp = mlxsw_sp_lower_get(dev);
6795-
if (!mlxsw_sp)
6796-
goto out;
6797-
6798-
rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
6796+
router = container_of(nb, struct mlxsw_sp_router, inetaddr_nb);
6797+
rif = mlxsw_sp_rif_find_by_dev(router->mlxsw_sp, dev);
67996798
if (!mlxsw_sp_rif_should_config(rif, dev, event))
68006799
goto out;
68016800

6802-
err = __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, NULL);
6801+
err = __mlxsw_sp_inetaddr_event(router->mlxsw_sp, dev, event, NULL);
68036802
out:
68046803
return notifier_from_errno(err);
68056804
}
@@ -6833,6 +6832,7 @@ int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
68336832

68346833
struct mlxsw_sp_inet6addr_event_work {
68356834
struct work_struct work;
6835+
struct mlxsw_sp *mlxsw_sp;
68366836
struct net_device *dev;
68376837
unsigned long event;
68386838
};
@@ -6841,15 +6841,12 @@ static void mlxsw_sp_inet6addr_event_work(struct work_struct *work)
68416841
{
68426842
struct mlxsw_sp_inet6addr_event_work *inet6addr_work =
68436843
container_of(work, struct mlxsw_sp_inet6addr_event_work, work);
6844+
struct mlxsw_sp *mlxsw_sp = inet6addr_work->mlxsw_sp;
68446845
struct net_device *dev = inet6addr_work->dev;
68456846
unsigned long event = inet6addr_work->event;
6846-
struct mlxsw_sp *mlxsw_sp;
68476847
struct mlxsw_sp_rif *rif;
68486848

68496849
rtnl_lock();
6850-
mlxsw_sp = mlxsw_sp_lower_get(dev);
6851-
if (!mlxsw_sp)
6852-
goto out;
68536850

68546851
rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
68556852
if (!mlxsw_sp_rif_should_config(rif, dev, event))
@@ -6863,25 +6860,25 @@ static void mlxsw_sp_inet6addr_event_work(struct work_struct *work)
68636860
}
68646861

68656862
/* Called with rcu_read_lock() */
6866-
int mlxsw_sp_inet6addr_event(struct notifier_block *unused,
6867-
unsigned long event, void *ptr)
6863+
static int mlxsw_sp_inet6addr_event(struct notifier_block *nb,
6864+
unsigned long event, void *ptr)
68686865
{
68696866
struct inet6_ifaddr *if6 = (struct inet6_ifaddr *) ptr;
68706867
struct mlxsw_sp_inet6addr_event_work *inet6addr_work;
68716868
struct net_device *dev = if6->idev->dev;
6869+
struct mlxsw_sp_router *router;
68726870

68736871
/* NETDEV_UP event is handled by mlxsw_sp_inet6addr_valid_event */
68746872
if (event == NETDEV_UP)
68756873
return NOTIFY_DONE;
68766874

6877-
if (!mlxsw_sp_port_dev_lower_find_rcu(dev))
6878-
return NOTIFY_DONE;
6879-
68806875
inet6addr_work = kzalloc(sizeof(*inet6addr_work), GFP_ATOMIC);
68816876
if (!inet6addr_work)
68826877
return NOTIFY_BAD;
68836878

6879+
router = container_of(nb, struct mlxsw_sp_router, inet6addr_nb);
68846880
INIT_WORK(&inet6addr_work->work, mlxsw_sp_inet6addr_event_work);
6881+
inet6addr_work->mlxsw_sp = router->mlxsw_sp;
68856882
inet6addr_work->dev = dev;
68866883
inet6addr_work->event = event;
68876884
dev_hold(dev);
@@ -7657,6 +7654,16 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
76577654
mlxsw_sp->router = router;
76587655
router->mlxsw_sp = mlxsw_sp;
76597656

7657+
router->inetaddr_nb.notifier_call = mlxsw_sp_inetaddr_event;
7658+
err = register_inetaddr_notifier(&router->inetaddr_nb);
7659+
if (err)
7660+
goto err_register_inetaddr_notifier;
7661+
7662+
router->inet6addr_nb.notifier_call = mlxsw_sp_inet6addr_event;
7663+
err = register_inet6addr_notifier(&router->inet6addr_nb);
7664+
if (err)
7665+
goto err_register_inet6addr_notifier;
7666+
76607667
INIT_LIST_HEAD(&mlxsw_sp->router->nexthop_neighs_list);
76617668
err = __mlxsw_sp_router_init(mlxsw_sp);
76627669
if (err)
@@ -7742,6 +7749,10 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
77427749
err_rifs_init:
77437750
__mlxsw_sp_router_fini(mlxsw_sp);
77447751
err_router_init:
7752+
unregister_inet6addr_notifier(&router->inet6addr_nb);
7753+
err_register_inet6addr_notifier:
7754+
unregister_inetaddr_notifier(&router->inetaddr_nb);
7755+
err_register_inetaddr_notifier:
77457756
kfree(mlxsw_sp->router);
77467757
return err;
77477758
}
@@ -7759,5 +7770,7 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
77597770
mlxsw_sp_ipips_fini(mlxsw_sp);
77607771
mlxsw_sp_rifs_fini(mlxsw_sp);
77617772
__mlxsw_sp_router_fini(mlxsw_sp);
7773+
unregister_inet6addr_notifier(&mlxsw_sp->router->inet6addr_nb);
7774+
unregister_inetaddr_notifier(&mlxsw_sp->router->inetaddr_nb);
77627775
kfree(mlxsw_sp->router);
77637776
}

0 commit comments

Comments
 (0)