diff options
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 15 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 162 | ||||
-rw-r--r-- | drivers/net/ipvlan/ipvlan_main.c | 14 | ||||
-rw-r--r-- | include/linux/inetdevice.h | 1 | ||||
-rw-r--r-- | include/net/addrconf.h | 1 | ||||
-rw-r--r-- | net/ipv4/devinet.c | 8 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 129 | ||||
-rw-r--r-- | net/ipv6/addrconf_core.c | 9 |
9 files changed, 234 insertions, 109 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index e1e11c726c16..e6519f2906a4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c | |||
@@ -4521,9 +4521,16 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb, | |||
4521 | return notifier_from_errno(err); | 4521 | return notifier_from_errno(err); |
4522 | } | 4522 | } |
4523 | 4523 | ||
4524 | static struct notifier_block mlxsw_sp_inetaddr_valid_nb __read_mostly = { | ||
4525 | .notifier_call = mlxsw_sp_inetaddr_valid_event, | ||
4526 | }; | ||
4527 | |||
4524 | static struct notifier_block mlxsw_sp_inetaddr_nb __read_mostly = { | 4528 | static struct notifier_block mlxsw_sp_inetaddr_nb __read_mostly = { |
4525 | .notifier_call = mlxsw_sp_inetaddr_event, | 4529 | .notifier_call = mlxsw_sp_inetaddr_event, |
4526 | .priority = 10, /* Must be called before FIB notifier block */ | 4530 | }; |
4531 | |||
4532 | static struct notifier_block mlxsw_sp_inet6addr_valid_nb __read_mostly = { | ||
4533 | .notifier_call = mlxsw_sp_inet6addr_valid_event, | ||
4527 | }; | 4534 | }; |
4528 | 4535 | ||
4529 | static struct notifier_block mlxsw_sp_inet6addr_nb __read_mostly = { | 4536 | static struct notifier_block mlxsw_sp_inet6addr_nb __read_mostly = { |
@@ -4548,7 +4555,9 @@ static int __init mlxsw_sp_module_init(void) | |||
4548 | { | 4555 | { |
4549 | int err; | 4556 | int err; |
4550 | 4557 | ||
4558 | register_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb); | ||
4551 | register_inetaddr_notifier(&mlxsw_sp_inetaddr_nb); | 4559 | register_inetaddr_notifier(&mlxsw_sp_inetaddr_nb); |
4560 | register_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb); | ||
4552 | register_inet6addr_notifier(&mlxsw_sp_inet6addr_nb); | 4561 | register_inet6addr_notifier(&mlxsw_sp_inet6addr_nb); |
4553 | register_netevent_notifier(&mlxsw_sp_router_netevent_nb); | 4562 | register_netevent_notifier(&mlxsw_sp_router_netevent_nb); |
4554 | 4563 | ||
@@ -4567,7 +4576,9 @@ err_pci_driver_register: | |||
4567 | err_core_driver_register: | 4576 | err_core_driver_register: |
4568 | unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb); | 4577 | unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb); |
4569 | unregister_inet6addr_notifier(&mlxsw_sp_inet6addr_nb); | 4578 | unregister_inet6addr_notifier(&mlxsw_sp_inet6addr_nb); |
4579 | unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb); | ||
4570 | unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb); | 4580 | unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb); |
4581 | unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb); | ||
4571 | return err; | 4582 | return err; |
4572 | } | 4583 | } |
4573 | 4584 | ||
@@ -4577,7 +4588,9 @@ static void __exit mlxsw_sp_module_exit(void) | |||
4577 | mlxsw_core_driver_unregister(&mlxsw_sp_driver); | 4588 | mlxsw_core_driver_unregister(&mlxsw_sp_driver); |
4578 | unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb); | 4589 | unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb); |
4579 | unregister_inet6addr_notifier(&mlxsw_sp_inet6addr_nb); | 4590 | unregister_inet6addr_notifier(&mlxsw_sp_inet6addr_nb); |
4591 | unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb); | ||
4580 | unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb); | 4592 | unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb); |
4593 | unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb); | ||
4581 | } | 4594 | } |
4582 | 4595 | ||
4583 | module_init(mlxsw_sp_module_init); | 4596 | module_init(mlxsw_sp_module_init); |
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 28feb745a38a..2a2472a09d8c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h | |||
@@ -391,8 +391,12 @@ int mlxsw_sp_router_netevent_event(struct notifier_block *unused, | |||
391 | int mlxsw_sp_netdevice_router_port_event(struct net_device *dev); | 391 | int mlxsw_sp_netdevice_router_port_event(struct net_device *dev); |
392 | int mlxsw_sp_inetaddr_event(struct notifier_block *unused, | 392 | int mlxsw_sp_inetaddr_event(struct notifier_block *unused, |
393 | unsigned long event, void *ptr); | 393 | unsigned long event, void *ptr); |
394 | int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused, | ||
395 | unsigned long event, void *ptr); | ||
394 | int mlxsw_sp_inet6addr_event(struct notifier_block *unused, | 396 | int mlxsw_sp_inet6addr_event(struct notifier_block *unused, |
395 | unsigned long event, void *ptr); | 397 | unsigned long event, void *ptr); |
398 | int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused, | ||
399 | unsigned long event, void *ptr); | ||
396 | int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event, | 400 | int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event, |
397 | struct netdev_notifier_changeupper_info *info); | 401 | struct netdev_notifier_changeupper_info *info); |
398 | bool mlxsw_sp_netdev_is_ipip(const struct mlxsw_sp *mlxsw_sp, | 402 | bool mlxsw_sp_netdev_is_ipip(const struct mlxsw_sp *mlxsw_sp, |
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 3330120f2f8e..2420f69797a9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | |||
@@ -731,14 +731,17 @@ static struct mlxsw_sp_fib *mlxsw_sp_vr_fib(const struct mlxsw_sp_vr *vr, | |||
731 | } | 731 | } |
732 | 732 | ||
733 | static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp, | 733 | static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp, |
734 | u32 tb_id) | 734 | u32 tb_id, |
735 | struct netlink_ext_ack *extack) | ||
735 | { | 736 | { |
736 | struct mlxsw_sp_vr *vr; | 737 | struct mlxsw_sp_vr *vr; |
737 | int err; | 738 | int err; |
738 | 739 | ||
739 | vr = mlxsw_sp_vr_find_unused(mlxsw_sp); | 740 | vr = mlxsw_sp_vr_find_unused(mlxsw_sp); |
740 | if (!vr) | 741 | if (!vr) { |
742 | NL_SET_ERR_MSG(extack, "spectrum: Exceeded number of supported virtual routers"); | ||
741 | return ERR_PTR(-EBUSY); | 743 | return ERR_PTR(-EBUSY); |
744 | } | ||
742 | vr->fib4 = mlxsw_sp_fib_create(vr, MLXSW_SP_L3_PROTO_IPV4); | 745 | vr->fib4 = mlxsw_sp_fib_create(vr, MLXSW_SP_L3_PROTO_IPV4); |
743 | if (IS_ERR(vr->fib4)) | 746 | if (IS_ERR(vr->fib4)) |
744 | return ERR_CAST(vr->fib4); | 747 | return ERR_CAST(vr->fib4); |
@@ -775,14 +778,15 @@ static void mlxsw_sp_vr_destroy(struct mlxsw_sp_vr *vr) | |||
775 | vr->fib4 = NULL; | 778 | vr->fib4 = NULL; |
776 | } | 779 | } |
777 | 780 | ||
778 | static struct mlxsw_sp_vr *mlxsw_sp_vr_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id) | 781 | static struct mlxsw_sp_vr *mlxsw_sp_vr_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, |
782 | struct netlink_ext_ack *extack) | ||
779 | { | 783 | { |
780 | struct mlxsw_sp_vr *vr; | 784 | struct mlxsw_sp_vr *vr; |
781 | 785 | ||
782 | tb_id = mlxsw_sp_fix_tb_id(tb_id); | 786 | tb_id = mlxsw_sp_fix_tb_id(tb_id); |
783 | vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id); | 787 | vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id); |
784 | if (!vr) | 788 | if (!vr) |
785 | vr = mlxsw_sp_vr_create(mlxsw_sp, tb_id); | 789 | vr = mlxsw_sp_vr_create(mlxsw_sp, tb_id, extack); |
786 | return vr; | 790 | return vr; |
787 | } | 791 | } |
788 | 792 | ||
@@ -948,7 +952,8 @@ static u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev) | |||
948 | 952 | ||
949 | static struct mlxsw_sp_rif * | 953 | static struct mlxsw_sp_rif * |
950 | mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, | 954 | mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, |
951 | const struct mlxsw_sp_rif_params *params); | 955 | const struct mlxsw_sp_rif_params *params, |
956 | struct netlink_ext_ack *extack); | ||
952 | 957 | ||
953 | static struct mlxsw_sp_rif_ipip_lb * | 958 | static struct mlxsw_sp_rif_ipip_lb * |
954 | mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp *mlxsw_sp, | 959 | mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp *mlxsw_sp, |
@@ -966,7 +971,7 @@ mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp *mlxsw_sp, | |||
966 | .lb_config = ipip_ops->ol_loopback_config(mlxsw_sp, ol_dev), | 971 | .lb_config = ipip_ops->ol_loopback_config(mlxsw_sp, ol_dev), |
967 | }; | 972 | }; |
968 | 973 | ||
969 | rif = mlxsw_sp_rif_create(mlxsw_sp, &lb_params.common); | 974 | rif = mlxsw_sp_rif_create(mlxsw_sp, &lb_params.common, NULL); |
970 | if (IS_ERR(rif)) | 975 | if (IS_ERR(rif)) |
971 | return ERR_CAST(rif); | 976 | return ERR_CAST(rif); |
972 | return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common); | 977 | return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common); |
@@ -3836,7 +3841,7 @@ mlxsw_sp_fib_node_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, const void *addr, | |||
3836 | struct mlxsw_sp_vr *vr; | 3841 | struct mlxsw_sp_vr *vr; |
3837 | int err; | 3842 | int err; |
3838 | 3843 | ||
3839 | vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id); | 3844 | vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id, NULL); |
3840 | if (IS_ERR(vr)) | 3845 | if (IS_ERR(vr)) |
3841 | return ERR_CAST(vr); | 3846 | return ERR_CAST(vr); |
3842 | fib = mlxsw_sp_vr_fib(vr, proto); | 3847 | fib = mlxsw_sp_vr_fib(vr, proto); |
@@ -4875,7 +4880,7 @@ static int mlxsw_sp_router_fibmr_add(struct mlxsw_sp *mlxsw_sp, | |||
4875 | if (mlxsw_sp->router->aborted) | 4880 | if (mlxsw_sp->router->aborted) |
4876 | return 0; | 4881 | return 0; |
4877 | 4882 | ||
4878 | vr = mlxsw_sp_vr_get(mlxsw_sp, men_info->tb_id); | 4883 | vr = mlxsw_sp_vr_get(mlxsw_sp, men_info->tb_id, NULL); |
4879 | if (IS_ERR(vr)) | 4884 | if (IS_ERR(vr)) |
4880 | return PTR_ERR(vr); | 4885 | return PTR_ERR(vr); |
4881 | 4886 | ||
@@ -4908,7 +4913,7 @@ mlxsw_sp_router_fibmr_vif_add(struct mlxsw_sp *mlxsw_sp, | |||
4908 | if (mlxsw_sp->router->aborted) | 4913 | if (mlxsw_sp->router->aborted) |
4909 | return 0; | 4914 | return 0; |
4910 | 4915 | ||
4911 | vr = mlxsw_sp_vr_get(mlxsw_sp, ven_info->tb_id); | 4916 | vr = mlxsw_sp_vr_get(mlxsw_sp, ven_info->tb_id, NULL); |
4912 | if (IS_ERR(vr)) | 4917 | if (IS_ERR(vr)) |
4913 | return PTR_ERR(vr); | 4918 | return PTR_ERR(vr); |
4914 | 4919 | ||
@@ -5471,7 +5476,8 @@ const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif) | |||
5471 | 5476 | ||
5472 | static struct mlxsw_sp_rif * | 5477 | static struct mlxsw_sp_rif * |
5473 | mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, | 5478 | mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, |
5474 | const struct mlxsw_sp_rif_params *params) | 5479 | const struct mlxsw_sp_rif_params *params, |
5480 | struct netlink_ext_ack *extack) | ||
5475 | { | 5481 | { |
5476 | u32 tb_id = l3mdev_fib_table(params->dev); | 5482 | u32 tb_id = l3mdev_fib_table(params->dev); |
5477 | const struct mlxsw_sp_rif_ops *ops; | 5483 | const struct mlxsw_sp_rif_ops *ops; |
@@ -5485,14 +5491,16 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, | |||
5485 | type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev); | 5491 | type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev); |
5486 | ops = mlxsw_sp->router->rif_ops_arr[type]; | 5492 | ops = mlxsw_sp->router->rif_ops_arr[type]; |
5487 | 5493 | ||
5488 | vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN); | 5494 | vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN, extack); |
5489 | if (IS_ERR(vr)) | 5495 | if (IS_ERR(vr)) |
5490 | return ERR_CAST(vr); | 5496 | return ERR_CAST(vr); |
5491 | vr->rif_count++; | 5497 | vr->rif_count++; |
5492 | 5498 | ||
5493 | err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index); | 5499 | err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index); |
5494 | if (err) | 5500 | if (err) { |
5501 | NL_SET_ERR_MSG(extack, "spectrum: Exceeded number of supported router interfaces"); | ||
5495 | goto err_rif_index_alloc; | 5502 | goto err_rif_index_alloc; |
5503 | } | ||
5496 | 5504 | ||
5497 | rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev); | 5505 | rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev); |
5498 | if (!rif) { | 5506 | if (!rif) { |
@@ -5579,7 +5587,8 @@ mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params *params, | |||
5579 | 5587 | ||
5580 | static int | 5588 | static int |
5581 | mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan, | 5589 | mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan, |
5582 | struct net_device *l3_dev) | 5590 | struct net_device *l3_dev, |
5591 | struct netlink_ext_ack *extack) | ||
5583 | { | 5592 | { |
5584 | struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port; | 5593 | struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port; |
5585 | struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; | 5594 | struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; |
@@ -5595,7 +5604,7 @@ mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan, | |||
5595 | }; | 5604 | }; |
5596 | 5605 | ||
5597 | mlxsw_sp_rif_subport_params_init(¶ms, mlxsw_sp_port_vlan); | 5606 | mlxsw_sp_rif_subport_params_init(¶ms, mlxsw_sp_port_vlan); |
5598 | rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms); | 5607 | rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms, extack); |
5599 | if (IS_ERR(rif)) | 5608 | if (IS_ERR(rif)) |
5600 | return PTR_ERR(rif); | 5609 | return PTR_ERR(rif); |
5601 | } | 5610 | } |
@@ -5650,7 +5659,8 @@ mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan) | |||
5650 | 5659 | ||
5651 | static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev, | 5660 | static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev, |
5652 | struct net_device *port_dev, | 5661 | struct net_device *port_dev, |
5653 | unsigned long event, u16 vid) | 5662 | unsigned long event, u16 vid, |
5663 | struct netlink_ext_ack *extack) | ||
5654 | { | 5664 | { |
5655 | struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(port_dev); | 5665 | struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(port_dev); |
5656 | struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; | 5666 | struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; |
@@ -5662,7 +5672,7 @@ static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev, | |||
5662 | switch (event) { | 5672 | switch (event) { |
5663 | case NETDEV_UP: | 5673 | case NETDEV_UP: |
5664 | return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, | 5674 | return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, |
5665 | l3_dev); | 5675 | l3_dev, extack); |
5666 | case NETDEV_DOWN: | 5676 | case NETDEV_DOWN: |
5667 | mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan); | 5677 | mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan); |
5668 | break; | 5678 | break; |
@@ -5672,19 +5682,22 @@ static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev, | |||
5672 | } | 5682 | } |
5673 | 5683 | ||
5674 | static int mlxsw_sp_inetaddr_port_event(struct net_device *port_dev, | 5684 | static int mlxsw_sp_inetaddr_port_event(struct net_device *port_dev, |
5675 | unsigned long event) | 5685 | unsigned long event, |
5686 | struct netlink_ext_ack *extack) | ||
5676 | { | 5687 | { |
5677 | if (netif_is_bridge_port(port_dev) || | 5688 | if (netif_is_bridge_port(port_dev) || |
5678 | netif_is_lag_port(port_dev) || | 5689 | netif_is_lag_port(port_dev) || |
5679 | netif_is_ovs_port(port_dev)) | 5690 | netif_is_ovs_port(port_dev)) |
5680 | return 0; | 5691 | return 0; |
5681 | 5692 | ||
5682 | return mlxsw_sp_inetaddr_port_vlan_event(port_dev, port_dev, event, 1); | 5693 | return mlxsw_sp_inetaddr_port_vlan_event(port_dev, port_dev, event, 1, |
5694 | extack); | ||
5683 | } | 5695 | } |
5684 | 5696 | ||
5685 | static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev, | 5697 | static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev, |
5686 | struct net_device *lag_dev, | 5698 | struct net_device *lag_dev, |
5687 | unsigned long event, u16 vid) | 5699 | unsigned long event, u16 vid, |
5700 | struct netlink_ext_ack *extack) | ||
5688 | { | 5701 | { |
5689 | struct net_device *port_dev; | 5702 | struct net_device *port_dev; |
5690 | struct list_head *iter; | 5703 | struct list_head *iter; |
@@ -5694,7 +5707,8 @@ static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev, | |||
5694 | if (mlxsw_sp_port_dev_check(port_dev)) { | 5707 | if (mlxsw_sp_port_dev_check(port_dev)) { |
5695 | err = mlxsw_sp_inetaddr_port_vlan_event(l3_dev, | 5708 | err = mlxsw_sp_inetaddr_port_vlan_event(l3_dev, |
5696 | port_dev, | 5709 | port_dev, |
5697 | event, vid); | 5710 | event, vid, |
5711 | extack); | ||
5698 | if (err) | 5712 | if (err) |
5699 | return err; | 5713 | return err; |
5700 | } | 5714 | } |
@@ -5704,16 +5718,19 @@ static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev, | |||
5704 | } | 5718 | } |
5705 | 5719 | ||
5706 | static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev, | 5720 | static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev, |
5707 | unsigned long event) | 5721 | unsigned long event, |
5722 | struct netlink_ext_ack *extack) | ||
5708 | { | 5723 | { |
5709 | if (netif_is_bridge_port(lag_dev)) | 5724 | if (netif_is_bridge_port(lag_dev)) |
5710 | return 0; | 5725 | return 0; |
5711 | 5726 | ||
5712 | return __mlxsw_sp_inetaddr_lag_event(lag_dev, lag_dev, event, 1); | 5727 | return __mlxsw_sp_inetaddr_lag_event(lag_dev, lag_dev, event, 1, |
5728 | extack); | ||
5713 | } | 5729 | } |
5714 | 5730 | ||
5715 | static int mlxsw_sp_inetaddr_bridge_event(struct net_device *l3_dev, | 5731 | static int mlxsw_sp_inetaddr_bridge_event(struct net_device *l3_dev, |
5716 | unsigned long event) | 5732 | unsigned long event, |
5733 | struct netlink_ext_ack *extack) | ||
5717 | { | 5734 | { |
5718 | struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev); | 5735 | struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev); |
5719 | struct mlxsw_sp_rif_params params = { | 5736 | struct mlxsw_sp_rif_params params = { |
@@ -5723,7 +5740,7 @@ static int mlxsw_sp_inetaddr_bridge_event(struct net_device *l3_dev, | |||
5723 | 5740 | ||
5724 | switch (event) { | 5741 | switch (event) { |
5725 | case NETDEV_UP: | 5742 | case NETDEV_UP: |
5726 | rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms); | 5743 | rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms, extack); |
5727 | if (IS_ERR(rif)) | 5744 | if (IS_ERR(rif)) |
5728 | return PTR_ERR(rif); | 5745 | return PTR_ERR(rif); |
5729 | break; | 5746 | break; |
@@ -5737,7 +5754,8 @@ static int mlxsw_sp_inetaddr_bridge_event(struct net_device *l3_dev, | |||
5737 | } | 5754 | } |
5738 | 5755 | ||
5739 | static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev, | 5756 | static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev, |
5740 | unsigned long event) | 5757 | unsigned long event, |
5758 | struct netlink_ext_ack *extack) | ||
5741 | { | 5759 | { |
5742 | struct net_device *real_dev = vlan_dev_real_dev(vlan_dev); | 5760 | struct net_device *real_dev = vlan_dev_real_dev(vlan_dev); |
5743 | u16 vid = vlan_dev_vlan_id(vlan_dev); | 5761 | u16 vid = vlan_dev_vlan_id(vlan_dev); |
@@ -5747,27 +5765,28 @@ static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev, | |||
5747 | 5765 | ||
5748 | if (mlxsw_sp_port_dev_check(real_dev)) | 5766 | if (mlxsw_sp_port_dev_check(real_dev)) |
5749 | return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev, real_dev, | 5767 | return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev, real_dev, |
5750 | event, vid); | 5768 | event, vid, extack); |
5751 | else if (netif_is_lag_master(real_dev)) | 5769 | else if (netif_is_lag_master(real_dev)) |
5752 | return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event, | 5770 | return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event, |
5753 | vid); | 5771 | vid, extack); |
5754 | else if (netif_is_bridge_master(real_dev) && br_vlan_enabled(real_dev)) | 5772 | else if (netif_is_bridge_master(real_dev) && br_vlan_enabled(real_dev)) |
5755 | return mlxsw_sp_inetaddr_bridge_event(vlan_dev, event); | 5773 | return mlxsw_sp_inetaddr_bridge_event(vlan_dev, event, extack); |
5756 | 5774 | ||
5757 | return 0; | 5775 | return 0; |
5758 | } | 5776 | } |
5759 | 5777 | ||
5760 | static int __mlxsw_sp_inetaddr_event(struct net_device *dev, | 5778 | static int __mlxsw_sp_inetaddr_event(struct net_device *dev, |
5761 | unsigned long event) | 5779 | unsigned long event, |
5780 | struct netlink_ext_ack *extack) | ||
5762 | { | 5781 | { |
5763 | if (mlxsw_sp_port_dev_check(dev)) | 5782 | if (mlxsw_sp_port_dev_check(dev)) |
5764 | return mlxsw_sp_inetaddr_port_event(dev, event); | 5783 | return mlxsw_sp_inetaddr_port_event(dev, event, extack); |
5765 | else if (netif_is_lag_master(dev)) | 5784 | else if (netif_is_lag_master(dev)) |
5766 | return mlxsw_sp_inetaddr_lag_event(dev, event); | 5785 | return mlxsw_sp_inetaddr_lag_event(dev, event, extack); |
5767 | else if (netif_is_bridge_master(dev)) | 5786 | else if (netif_is_bridge_master(dev)) |
5768 | return mlxsw_sp_inetaddr_bridge_event(dev, event); | 5787 | return mlxsw_sp_inetaddr_bridge_event(dev, event, extack); |
5769 | else if (is_vlan_dev(dev)) | 5788 | else if (is_vlan_dev(dev)) |
5770 | return mlxsw_sp_inetaddr_vlan_event(dev, event); | 5789 | return mlxsw_sp_inetaddr_vlan_event(dev, event, extack); |
5771 | else | 5790 | else |
5772 | return 0; | 5791 | return 0; |
5773 | } | 5792 | } |
@@ -5781,6 +5800,32 @@ int mlxsw_sp_inetaddr_event(struct notifier_block *unused, | |||
5781 | struct mlxsw_sp_rif *rif; | 5800 | struct mlxsw_sp_rif *rif; |
5782 | int err = 0; | 5801 | int err = 0; |
5783 | 5802 | ||
5803 | /* NETDEV_UP event is handled by mlxsw_sp_inetaddr_valid_event */ | ||
5804 | if (event == NETDEV_UP) | ||
5805 | goto out; | ||
5806 | |||
5807 | mlxsw_sp = mlxsw_sp_lower_get(dev); | ||
5808 | if (!mlxsw_sp) | ||
5809 | goto out; | ||
5810 | |||
5811 | rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev); | ||
5812 | if (!mlxsw_sp_rif_should_config(rif, dev, event)) | ||
5813 | goto out; | ||
5814 | |||
5815 | err = __mlxsw_sp_inetaddr_event(dev, event, NULL); | ||
5816 | out: | ||
5817 | return notifier_from_errno(err); | ||
5818 | } | ||
5819 | |||
5820 | int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused, | ||
5821 | unsigned long event, void *ptr) | ||
5822 | { | ||
5823 | struct in_validator_info *ivi = (struct in_validator_info *) ptr; | ||
5824 | struct net_device *dev = ivi->ivi_dev->dev; | ||
5825 | struct mlxsw_sp *mlxsw_sp; | ||
5826 | struct mlxsw_sp_rif *rif; | ||
5827 | int err = 0; | ||
5828 | |||
5784 | mlxsw_sp = mlxsw_sp_lower_get(dev); | 5829 | mlxsw_sp = mlxsw_sp_lower_get(dev); |
5785 | if (!mlxsw_sp) | 5830 | if (!mlxsw_sp) |
5786 | goto out; | 5831 | goto out; |
@@ -5789,7 +5834,7 @@ int mlxsw_sp_inetaddr_event(struct notifier_block *unused, | |||
5789 | if (!mlxsw_sp_rif_should_config(rif, dev, event)) | 5834 | if (!mlxsw_sp_rif_should_config(rif, dev, event)) |
5790 | goto out; | 5835 | goto out; |
5791 | 5836 | ||
5792 | err = __mlxsw_sp_inetaddr_event(dev, event); | 5837 | err = __mlxsw_sp_inetaddr_event(dev, event, ivi->extack); |
5793 | out: | 5838 | out: |
5794 | return notifier_from_errno(err); | 5839 | return notifier_from_errno(err); |
5795 | } | 5840 | } |
@@ -5818,7 +5863,7 @@ static void mlxsw_sp_inet6addr_event_work(struct work_struct *work) | |||
5818 | if (!mlxsw_sp_rif_should_config(rif, dev, event)) | 5863 | if (!mlxsw_sp_rif_should_config(rif, dev, event)) |
5819 | goto out; | 5864 | goto out; |
5820 | 5865 | ||
5821 | __mlxsw_sp_inetaddr_event(dev, event); | 5866 | __mlxsw_sp_inetaddr_event(dev, event, NULL); |
5822 | out: | 5867 | out: |
5823 | rtnl_unlock(); | 5868 | rtnl_unlock(); |
5824 | dev_put(dev); | 5869 | dev_put(dev); |
@@ -5833,6 +5878,10 @@ int mlxsw_sp_inet6addr_event(struct notifier_block *unused, | |||
5833 | struct mlxsw_sp_inet6addr_event_work *inet6addr_work; | 5878 | struct mlxsw_sp_inet6addr_event_work *inet6addr_work; |
5834 | struct net_device *dev = if6->idev->dev; | 5879 | struct net_device *dev = if6->idev->dev; |
5835 | 5880 | ||
5881 | /* NETDEV_UP event is handled by mlxsw_sp_inet6addr_valid_event */ | ||
5882 | if (event == NETDEV_UP) | ||
5883 | return NOTIFY_DONE; | ||
5884 | |||
5836 | if (!mlxsw_sp_port_dev_lower_find_rcu(dev)) | 5885 | if (!mlxsw_sp_port_dev_lower_find_rcu(dev)) |
5837 | return NOTIFY_DONE; | 5886 | return NOTIFY_DONE; |
5838 | 5887 | ||
@@ -5849,6 +5898,28 @@ int mlxsw_sp_inet6addr_event(struct notifier_block *unused, | |||
5849 | return NOTIFY_DONE; | 5898 | return NOTIFY_DONE; |
5850 | } | 5899 | } |
5851 | 5900 | ||
5901 | int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused, | ||
5902 | unsigned long event, void *ptr) | ||
5903 | { | ||
5904 | struct in6_validator_info *i6vi = (struct in6_validator_info *) ptr; | ||
5905 | struct net_device *dev = i6vi->i6vi_dev->dev; | ||
5906 | struct mlxsw_sp *mlxsw_sp; | ||
5907 | struct mlxsw_sp_rif *rif; | ||
5908 | int err = 0; | ||
5909 | |||
5910 | mlxsw_sp = mlxsw_sp_lower_get(dev); | ||
5911 | if (!mlxsw_sp) | ||
5912 | goto out; | ||
5913 | |||
5914 | rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev); | ||
5915 | if (!mlxsw_sp_rif_should_config(rif, dev, event)) | ||
5916 | goto out; | ||
5917 | |||
5918 | err = __mlxsw_sp_inetaddr_event(dev, event, i6vi->extack); | ||
5919 | out: | ||
5920 | return notifier_from_errno(err); | ||
5921 | } | ||
5922 | |||
5852 | static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index, | 5923 | static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index, |
5853 | const char *mac, int mtu) | 5924 | const char *mac, int mtu) |
5854 | { | 5925 | { |
@@ -5921,7 +5992,8 @@ err_rif_edit: | |||
5921 | } | 5992 | } |
5922 | 5993 | ||
5923 | static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp, | 5994 | static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp, |
5924 | struct net_device *l3_dev) | 5995 | struct net_device *l3_dev, |
5996 | struct netlink_ext_ack *extack) | ||
5925 | { | 5997 | { |
5926 | struct mlxsw_sp_rif *rif; | 5998 | struct mlxsw_sp_rif *rif; |
5927 | 5999 | ||
@@ -5930,9 +6002,9 @@ static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp, | |||
5930 | */ | 6002 | */ |
5931 | rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev); | 6003 | rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev); |
5932 | if (rif) | 6004 | if (rif) |
5933 | __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN); | 6005 | __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN, extack); |
5934 | 6006 | ||
5935 | return __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_UP); | 6007 | return __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_UP, extack); |
5936 | } | 6008 | } |
5937 | 6009 | ||
5938 | static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp, | 6010 | static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp, |
@@ -5943,7 +6015,7 @@ static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp, | |||
5943 | rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev); | 6015 | rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev); |
5944 | if (!rif) | 6016 | if (!rif) |
5945 | return; | 6017 | return; |
5946 | __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN); | 6018 | __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN, NULL); |
5947 | } | 6019 | } |
5948 | 6020 | ||
5949 | int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event, | 6021 | int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event, |
@@ -5959,10 +6031,14 @@ int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event, | |||
5959 | case NETDEV_PRECHANGEUPPER: | 6031 | case NETDEV_PRECHANGEUPPER: |
5960 | return 0; | 6032 | return 0; |
5961 | case NETDEV_CHANGEUPPER: | 6033 | case NETDEV_CHANGEUPPER: |
5962 | if (info->linking) | 6034 | if (info->linking) { |
5963 | err = mlxsw_sp_port_vrf_join(mlxsw_sp, l3_dev); | 6035 | struct netlink_ext_ack *extack; |
5964 | else | 6036 | |
6037 | extack = netdev_notifier_info_to_extack(&info->info); | ||
6038 | err = mlxsw_sp_port_vrf_join(mlxsw_sp, l3_dev, extack); | ||
6039 | } else { | ||
5965 | mlxsw_sp_port_vrf_leave(mlxsw_sp, l3_dev); | 6040 | mlxsw_sp_port_vrf_leave(mlxsw_sp, l3_dev); |
6041 | } | ||
5966 | break; | 6042 | break; |
5967 | } | 6043 | } |
5968 | 6044 | ||
@@ -6269,7 +6345,7 @@ mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif) | |||
6269 | struct mlxsw_sp_vr *ul_vr; | 6345 | struct mlxsw_sp_vr *ul_vr; |
6270 | int err; | 6346 | int err; |
6271 | 6347 | ||
6272 | ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id); | 6348 | ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id, NULL); |
6273 | if (IS_ERR(ul_vr)) | 6349 | if (IS_ERR(ul_vr)) |
6274 | return PTR_ERR(ul_vr); | 6350 | return PTR_ERR(ul_vr); |
6275 | 6351 | ||
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 3cf67db513e2..f0ab55df57f1 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c | |||
@@ -808,10 +808,6 @@ static int ipvlan_addr6_event(struct notifier_block *unused, | |||
808 | struct net_device *dev = (struct net_device *)if6->idev->dev; | 808 | struct net_device *dev = (struct net_device *)if6->idev->dev; |
809 | struct ipvl_dev *ipvlan = netdev_priv(dev); | 809 | struct ipvl_dev *ipvlan = netdev_priv(dev); |
810 | 810 | ||
811 | /* FIXME IPv6 autoconf calls us from bh without RTNL */ | ||
812 | if (in_softirq()) | ||
813 | return NOTIFY_DONE; | ||
814 | |||
815 | if (!netif_is_ipvlan(dev)) | 811 | if (!netif_is_ipvlan(dev)) |
816 | return NOTIFY_DONE; | 812 | return NOTIFY_DONE; |
817 | 813 | ||
@@ -851,8 +847,11 @@ static int ipvlan_addr6_validator_event(struct notifier_block *unused, | |||
851 | 847 | ||
852 | switch (event) { | 848 | switch (event) { |
853 | case NETDEV_UP: | 849 | case NETDEV_UP: |
854 | if (ipvlan_addr_busy(ipvlan->port, &i6vi->i6vi_addr, true)) | 850 | if (ipvlan_addr_busy(ipvlan->port, &i6vi->i6vi_addr, true)) { |
851 | NL_SET_ERR_MSG(i6vi->extack, | ||
852 | "Address already assigned to an ipvlan device"); | ||
855 | return notifier_from_errno(-EADDRINUSE); | 853 | return notifier_from_errno(-EADDRINUSE); |
854 | } | ||
856 | break; | 855 | break; |
857 | } | 856 | } |
858 | 857 | ||
@@ -921,8 +920,11 @@ static int ipvlan_addr4_validator_event(struct notifier_block *unused, | |||
921 | 920 | ||
922 | switch (event) { | 921 | switch (event) { |
923 | case NETDEV_UP: | 922 | case NETDEV_UP: |
924 | if (ipvlan_addr_busy(ipvlan->port, &ivi->ivi_addr, false)) | 923 | if (ipvlan_addr_busy(ipvlan->port, &ivi->ivi_addr, false)) { |
924 | NL_SET_ERR_MSG(ivi->extack, | ||
925 | "Address already assigned to an ipvlan device"); | ||
925 | return notifier_from_errno(-EADDRINUSE); | 926 | return notifier_from_errno(-EADDRINUSE); |
927 | } | ||
926 | break; | 928 | break; |
927 | } | 929 | } |
928 | 930 | ||
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 751d051f0bc7..681dff30940b 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h | |||
@@ -154,6 +154,7 @@ struct in_ifaddr { | |||
154 | struct in_validator_info { | 154 | struct in_validator_info { |
155 | __be32 ivi_addr; | 155 | __be32 ivi_addr; |
156 | struct in_device *ivi_dev; | 156 | struct in_device *ivi_dev; |
157 | struct netlink_ext_ack *extack; | ||
157 | }; | 158 | }; |
158 | 159 | ||
159 | int register_inetaddr_notifier(struct notifier_block *nb); | 160 | int register_inetaddr_notifier(struct notifier_block *nb); |
diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 87981cd63180..b8b16437c6d5 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h | |||
@@ -55,6 +55,7 @@ struct prefix_info { | |||
55 | struct in6_validator_info { | 55 | struct in6_validator_info { |
56 | struct in6_addr i6vi_addr; | 56 | struct in6_addr i6vi_addr; |
57 | struct inet6_dev *i6vi_dev; | 57 | struct inet6_dev *i6vi_dev; |
58 | struct netlink_ext_ack *extack; | ||
58 | }; | 59 | }; |
59 | 60 | ||
60 | #define IN6_ADDR_HSIZE_SHIFT 4 | 61 | #define IN6_ADDR_HSIZE_SHIFT 4 |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index e1e2ec0525e6..a4573bccd6da 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -444,7 +444,7 @@ static void check_lifetime(struct work_struct *work); | |||
444 | static DECLARE_DELAYED_WORK(check_lifetime_work, check_lifetime); | 444 | static DECLARE_DELAYED_WORK(check_lifetime_work, check_lifetime); |
445 | 445 | ||
446 | static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, | 446 | static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, |
447 | u32 portid) | 447 | u32 portid, struct netlink_ext_ack *extack) |
448 | { | 448 | { |
449 | struct in_device *in_dev = ifa->ifa_dev; | 449 | struct in_device *in_dev = ifa->ifa_dev; |
450 | struct in_ifaddr *ifa1, **ifap, **last_primary; | 450 | struct in_ifaddr *ifa1, **ifap, **last_primary; |
@@ -489,6 +489,7 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, | |||
489 | */ | 489 | */ |
490 | ivi.ivi_addr = ifa->ifa_address; | 490 | ivi.ivi_addr = ifa->ifa_address; |
491 | ivi.ivi_dev = ifa->ifa_dev; | 491 | ivi.ivi_dev = ifa->ifa_dev; |
492 | ivi.extack = extack; | ||
492 | ret = blocking_notifier_call_chain(&inetaddr_validator_chain, | 493 | ret = blocking_notifier_call_chain(&inetaddr_validator_chain, |
493 | NETDEV_UP, &ivi); | 494 | NETDEV_UP, &ivi); |
494 | ret = notifier_to_errno(ret); | 495 | ret = notifier_to_errno(ret); |
@@ -521,7 +522,7 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, | |||
521 | 522 | ||
522 | static int inet_insert_ifa(struct in_ifaddr *ifa) | 523 | static int inet_insert_ifa(struct in_ifaddr *ifa) |
523 | { | 524 | { |
524 | return __inet_insert_ifa(ifa, NULL, 0); | 525 | return __inet_insert_ifa(ifa, NULL, 0, NULL); |
525 | } | 526 | } |
526 | 527 | ||
527 | static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) | 528 | static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) |
@@ -902,7 +903,8 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
902 | return ret; | 903 | return ret; |
903 | } | 904 | } |
904 | } | 905 | } |
905 | return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid); | 906 | return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid, |
907 | extack); | ||
906 | } else { | 908 | } else { |
907 | inet_free_ifa(ifa); | 909 | inet_free_ifa(ifa); |
908 | 910 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4603aa488f4f..93f9c0a61911 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -957,18 +957,42 @@ static u32 inet6_addr_hash(const struct in6_addr *addr) | |||
957 | return hash_32(ipv6_addr_hash(addr), IN6_ADDR_HSIZE_SHIFT); | 957 | return hash_32(ipv6_addr_hash(addr), IN6_ADDR_HSIZE_SHIFT); |
958 | } | 958 | } |
959 | 959 | ||
960 | static int ipv6_add_addr_hash(struct net_device *dev, struct inet6_ifaddr *ifa) | ||
961 | { | ||
962 | unsigned int hash; | ||
963 | int err = 0; | ||
964 | |||
965 | spin_lock(&addrconf_hash_lock); | ||
966 | |||
967 | /* Ignore adding duplicate addresses on an interface */ | ||
968 | if (ipv6_chk_same_addr(dev_net(dev), &ifa->addr, dev)) { | ||
969 | ADBG("ipv6_add_addr: already assigned\n"); | ||
970 | err = -EEXIST; | ||
971 | goto out; | ||
972 | } | ||
973 | |||
974 | /* Add to big hash table */ | ||
975 | hash = inet6_addr_hash(&ifa->addr); | ||
976 | hlist_add_head_rcu(&ifa->addr_lst, &inet6_addr_lst[hash]); | ||
977 | |||
978 | out: | ||
979 | spin_unlock(&addrconf_hash_lock); | ||
980 | |||
981 | return err; | ||
982 | } | ||
983 | |||
960 | /* On success it returns ifp with increased reference count */ | 984 | /* On success it returns ifp with increased reference count */ |
961 | 985 | ||
962 | static struct inet6_ifaddr * | 986 | static struct inet6_ifaddr * |
963 | ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, | 987 | ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, |
964 | const struct in6_addr *peer_addr, int pfxlen, | 988 | const struct in6_addr *peer_addr, int pfxlen, |
965 | int scope, u32 flags, u32 valid_lft, u32 prefered_lft) | 989 | int scope, u32 flags, u32 valid_lft, u32 prefered_lft, |
990 | bool can_block, struct netlink_ext_ack *extack) | ||
966 | { | 991 | { |
992 | gfp_t gfp_flags = can_block ? GFP_KERNEL : GFP_ATOMIC; | ||
967 | struct net *net = dev_net(idev->dev); | 993 | struct net *net = dev_net(idev->dev); |
968 | struct inet6_ifaddr *ifa = NULL; | 994 | struct inet6_ifaddr *ifa = NULL; |
969 | struct rt6_info *rt; | 995 | struct rt6_info *rt = NULL; |
970 | struct in6_validator_info i6vi; | ||
971 | unsigned int hash; | ||
972 | int err = 0; | 996 | int err = 0; |
973 | int addr_type = ipv6_addr_type(addr); | 997 | int addr_type = ipv6_addr_type(addr); |
974 | 998 | ||
@@ -978,42 +1002,33 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, | |||
978 | addr_type & IPV6_ADDR_LOOPBACK)) | 1002 | addr_type & IPV6_ADDR_LOOPBACK)) |
979 | return ERR_PTR(-EADDRNOTAVAIL); | 1003 | return ERR_PTR(-EADDRNOTAVAIL); |
980 | 1004 | ||
981 | rcu_read_lock_bh(); | ||
982 | |||
983 | in6_dev_hold(idev); | ||
984 | |||
985 | if (idev->dead) { | 1005 | if (idev->dead) { |
986 | err = -ENODEV; /*XXX*/ | 1006 | err = -ENODEV; /*XXX*/ |
987 | goto out2; | 1007 | goto out; |
988 | } | 1008 | } |
989 | 1009 | ||
990 | if (idev->cnf.disable_ipv6) { | 1010 | if (idev->cnf.disable_ipv6) { |
991 | err = -EACCES; | 1011 | err = -EACCES; |
992 | goto out2; | ||
993 | } | ||
994 | |||
995 | i6vi.i6vi_addr = *addr; | ||
996 | i6vi.i6vi_dev = idev; | ||
997 | rcu_read_unlock_bh(); | ||
998 | |||
999 | err = inet6addr_validator_notifier_call_chain(NETDEV_UP, &i6vi); | ||
1000 | |||
1001 | rcu_read_lock_bh(); | ||
1002 | err = notifier_to_errno(err); | ||
1003 | if (err) | ||
1004 | goto out2; | ||
1005 | |||
1006 | spin_lock(&addrconf_hash_lock); | ||
1007 | |||
1008 | /* Ignore adding duplicate addresses on an interface */ | ||
1009 | if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) { | ||
1010 | ADBG("ipv6_add_addr: already assigned\n"); | ||
1011 | err = -EEXIST; | ||
1012 | goto out; | 1012 | goto out; |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | ifa = kzalloc(sizeof(struct inet6_ifaddr), GFP_ATOMIC); | 1015 | /* validator notifier needs to be blocking; |
1016 | * do not call in atomic context | ||
1017 | */ | ||
1018 | if (can_block) { | ||
1019 | struct in6_validator_info i6vi = { | ||
1020 | .i6vi_addr = *addr, | ||
1021 | .i6vi_dev = idev, | ||
1022 | .extack = extack, | ||
1023 | }; | ||
1024 | |||
1025 | err = inet6addr_validator_notifier_call_chain(NETDEV_UP, &i6vi); | ||
1026 | err = notifier_to_errno(err); | ||
1027 | if (err < 0) | ||
1028 | goto out; | ||
1029 | } | ||
1016 | 1030 | ||
1031 | ifa = kzalloc(sizeof(*ifa), gfp_flags); | ||
1017 | if (!ifa) { | 1032 | if (!ifa) { |
1018 | ADBG("ipv6_add_addr: malloc failed\n"); | 1033 | ADBG("ipv6_add_addr: malloc failed\n"); |
1019 | err = -ENOBUFS; | 1034 | err = -ENOBUFS; |
@@ -1023,6 +1038,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, | |||
1023 | rt = addrconf_dst_alloc(idev, addr, false); | 1038 | rt = addrconf_dst_alloc(idev, addr, false); |
1024 | if (IS_ERR(rt)) { | 1039 | if (IS_ERR(rt)) { |
1025 | err = PTR_ERR(rt); | 1040 | err = PTR_ERR(rt); |
1041 | rt = NULL; | ||
1026 | goto out; | 1042 | goto out; |
1027 | } | 1043 | } |
1028 | 1044 | ||
@@ -1053,16 +1069,21 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, | |||
1053 | ifa->rt = rt; | 1069 | ifa->rt = rt; |
1054 | 1070 | ||
1055 | ifa->idev = idev; | 1071 | ifa->idev = idev; |
1072 | in6_dev_hold(idev); | ||
1073 | |||
1056 | /* For caller */ | 1074 | /* For caller */ |
1057 | refcount_set(&ifa->refcnt, 1); | 1075 | refcount_set(&ifa->refcnt, 1); |
1058 | 1076 | ||
1059 | /* Add to big hash table */ | 1077 | rcu_read_lock_bh(); |
1060 | hash = inet6_addr_hash(addr); | ||
1061 | 1078 | ||
1062 | hlist_add_head_rcu(&ifa->addr_lst, &inet6_addr_lst[hash]); | 1079 | err = ipv6_add_addr_hash(idev->dev, ifa); |
1063 | spin_unlock(&addrconf_hash_lock); | 1080 | if (err < 0) { |
1081 | rcu_read_unlock_bh(); | ||
1082 | goto out; | ||
1083 | } | ||
1064 | 1084 | ||
1065 | write_lock(&idev->lock); | 1085 | write_lock(&idev->lock); |
1086 | |||
1066 | /* Add to inet6_dev unicast addr list. */ | 1087 | /* Add to inet6_dev unicast addr list. */ |
1067 | ipv6_link_dev_addr(idev, ifa); | 1088 | ipv6_link_dev_addr(idev, ifa); |
1068 | 1089 | ||
@@ -1073,21 +1094,23 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, | |||
1073 | 1094 | ||
1074 | in6_ifa_hold(ifa); | 1095 | in6_ifa_hold(ifa); |
1075 | write_unlock(&idev->lock); | 1096 | write_unlock(&idev->lock); |
1076 | out2: | 1097 | |
1077 | rcu_read_unlock_bh(); | 1098 | rcu_read_unlock_bh(); |
1078 | 1099 | ||
1079 | if (likely(err == 0)) | 1100 | inet6addr_notifier_call_chain(NETDEV_UP, ifa); |
1080 | inet6addr_notifier_call_chain(NETDEV_UP, ifa); | 1101 | out: |
1081 | else { | 1102 | if (unlikely(err < 0)) { |
1082 | kfree(ifa); | 1103 | if (rt) |
1083 | in6_dev_put(idev); | 1104 | ip6_rt_put(rt); |
1105 | if (ifa) { | ||
1106 | if (ifa->idev) | ||
1107 | in6_dev_put(ifa->idev); | ||
1108 | kfree(ifa); | ||
1109 | } | ||
1084 | ifa = ERR_PTR(err); | 1110 | ifa = ERR_PTR(err); |
1085 | } | 1111 | } |
1086 | 1112 | ||
1087 | return ifa; | 1113 | return ifa; |
1088 | out: | ||
1089 | spin_unlock(&addrconf_hash_lock); | ||
1090 | goto out2; | ||
1091 | } | 1114 | } |
1092 | 1115 | ||
1093 | enum cleanup_prefix_rt_t { | 1116 | enum cleanup_prefix_rt_t { |
@@ -1334,7 +1357,7 @@ retry: | |||
1334 | 1357 | ||
1335 | ift = ipv6_add_addr(idev, &addr, NULL, tmp_plen, | 1358 | ift = ipv6_add_addr(idev, &addr, NULL, tmp_plen, |
1336 | ipv6_addr_scope(&addr), addr_flags, | 1359 | ipv6_addr_scope(&addr), addr_flags, |
1337 | tmp_valid_lft, tmp_prefered_lft); | 1360 | tmp_valid_lft, tmp_prefered_lft, true, NULL); |
1338 | if (IS_ERR(ift)) { | 1361 | if (IS_ERR(ift)) { |
1339 | in6_ifa_put(ifp); | 1362 | in6_ifa_put(ifp); |
1340 | in6_dev_put(idev); | 1363 | in6_dev_put(idev); |
@@ -2018,7 +2041,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
2018 | 2041 | ||
2019 | ifp2 = ipv6_add_addr(idev, &new_addr, NULL, pfxlen, | 2042 | ifp2 = ipv6_add_addr(idev, &new_addr, NULL, pfxlen, |
2020 | scope, flags, valid_lft, | 2043 | scope, flags, valid_lft, |
2021 | preferred_lft); | 2044 | preferred_lft, false, NULL); |
2022 | if (IS_ERR(ifp2)) | 2045 | if (IS_ERR(ifp2)) |
2023 | goto lock_errdad; | 2046 | goto lock_errdad; |
2024 | 2047 | ||
@@ -2476,7 +2499,7 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev, | |||
2476 | pinfo->prefix_len, | 2499 | pinfo->prefix_len, |
2477 | addr_type&IPV6_ADDR_SCOPE_MASK, | 2500 | addr_type&IPV6_ADDR_SCOPE_MASK, |
2478 | addr_flags, valid_lft, | 2501 | addr_flags, valid_lft, |
2479 | prefered_lft); | 2502 | prefered_lft, false, NULL); |
2480 | 2503 | ||
2481 | if (IS_ERR_OR_NULL(ifp)) | 2504 | if (IS_ERR_OR_NULL(ifp)) |
2482 | return -1; | 2505 | return -1; |
@@ -2786,7 +2809,8 @@ static int inet6_addr_add(struct net *net, int ifindex, | |||
2786 | const struct in6_addr *pfx, | 2809 | const struct in6_addr *pfx, |
2787 | const struct in6_addr *peer_pfx, | 2810 | const struct in6_addr *peer_pfx, |
2788 | unsigned int plen, __u32 ifa_flags, | 2811 | unsigned int plen, __u32 ifa_flags, |
2789 | __u32 prefered_lft, __u32 valid_lft) | 2812 | __u32 prefered_lft, __u32 valid_lft, |
2813 | struct netlink_ext_ack *extack) | ||
2790 | { | 2814 | { |
2791 | struct inet6_ifaddr *ifp; | 2815 | struct inet6_ifaddr *ifp; |
2792 | struct inet6_dev *idev; | 2816 | struct inet6_dev *idev; |
@@ -2845,7 +2869,7 @@ static int inet6_addr_add(struct net *net, int ifindex, | |||
2845 | } | 2869 | } |
2846 | 2870 | ||
2847 | ifp = ipv6_add_addr(idev, pfx, peer_pfx, plen, scope, ifa_flags, | 2871 | ifp = ipv6_add_addr(idev, pfx, peer_pfx, plen, scope, ifa_flags, |
2848 | valid_lft, prefered_lft); | 2872 | valid_lft, prefered_lft, true, extack); |
2849 | 2873 | ||
2850 | if (!IS_ERR(ifp)) { | 2874 | if (!IS_ERR(ifp)) { |
2851 | if (!(ifa_flags & IFA_F_NOPREFIXROUTE)) { | 2875 | if (!(ifa_flags & IFA_F_NOPREFIXROUTE)) { |
@@ -2930,7 +2954,7 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg) | |||
2930 | rtnl_lock(); | 2954 | rtnl_lock(); |
2931 | err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, NULL, | 2955 | err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, NULL, |
2932 | ireq.ifr6_prefixlen, IFA_F_PERMANENT, | 2956 | ireq.ifr6_prefixlen, IFA_F_PERMANENT, |
2933 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); | 2957 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, NULL); |
2934 | rtnl_unlock(); | 2958 | rtnl_unlock(); |
2935 | return err; | 2959 | return err; |
2936 | } | 2960 | } |
@@ -2960,7 +2984,8 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr, | |||
2960 | 2984 | ||
2961 | ifp = ipv6_add_addr(idev, addr, NULL, plen, | 2985 | ifp = ipv6_add_addr(idev, addr, NULL, plen, |
2962 | scope, IFA_F_PERMANENT, | 2986 | scope, IFA_F_PERMANENT, |
2963 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); | 2987 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, |
2988 | true, NULL); | ||
2964 | if (!IS_ERR(ifp)) { | 2989 | if (!IS_ERR(ifp)) { |
2965 | spin_lock_bh(&ifp->lock); | 2990 | spin_lock_bh(&ifp->lock); |
2966 | ifp->flags &= ~IFA_F_TENTATIVE; | 2991 | ifp->flags &= ~IFA_F_TENTATIVE; |
@@ -3060,7 +3085,7 @@ void addrconf_add_linklocal(struct inet6_dev *idev, | |||
3060 | #endif | 3085 | #endif |
3061 | 3086 | ||
3062 | ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags, | 3087 | ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags, |
3063 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); | 3088 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, true, NULL); |
3064 | if (!IS_ERR(ifp)) { | 3089 | if (!IS_ERR(ifp)) { |
3065 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0); | 3090 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0); |
3066 | addrconf_dad_start(ifp); | 3091 | addrconf_dad_start(ifp); |
@@ -4563,7 +4588,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
4563 | */ | 4588 | */ |
4564 | return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx, | 4589 | return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx, |
4565 | ifm->ifa_prefixlen, ifa_flags, | 4590 | ifm->ifa_prefixlen, ifa_flags, |
4566 | preferred_lft, valid_lft); | 4591 | preferred_lft, valid_lft, extack); |
4567 | } | 4592 | } |
4568 | 4593 | ||
4569 | if (nlh->nlmsg_flags & NLM_F_EXCL || | 4594 | if (nlh->nlmsg_flags & NLM_F_EXCL || |
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index 9e3488d50b15..32b564dfd02a 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c | |||
@@ -88,7 +88,7 @@ int __ipv6_addr_type(const struct in6_addr *addr) | |||
88 | EXPORT_SYMBOL(__ipv6_addr_type); | 88 | EXPORT_SYMBOL(__ipv6_addr_type); |
89 | 89 | ||
90 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); | 90 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); |
91 | static ATOMIC_NOTIFIER_HEAD(inet6addr_validator_chain); | 91 | static BLOCKING_NOTIFIER_HEAD(inet6addr_validator_chain); |
92 | 92 | ||
93 | int register_inet6addr_notifier(struct notifier_block *nb) | 93 | int register_inet6addr_notifier(struct notifier_block *nb) |
94 | { | 94 | { |
@@ -110,19 +110,20 @@ EXPORT_SYMBOL(inet6addr_notifier_call_chain); | |||
110 | 110 | ||
111 | int register_inet6addr_validator_notifier(struct notifier_block *nb) | 111 | int register_inet6addr_validator_notifier(struct notifier_block *nb) |
112 | { | 112 | { |
113 | return atomic_notifier_chain_register(&inet6addr_validator_chain, nb); | 113 | return blocking_notifier_chain_register(&inet6addr_validator_chain, nb); |
114 | } | 114 | } |
115 | EXPORT_SYMBOL(register_inet6addr_validator_notifier); | 115 | EXPORT_SYMBOL(register_inet6addr_validator_notifier); |
116 | 116 | ||
117 | int unregister_inet6addr_validator_notifier(struct notifier_block *nb) | 117 | int unregister_inet6addr_validator_notifier(struct notifier_block *nb) |
118 | { | 118 | { |
119 | return atomic_notifier_chain_unregister(&inet6addr_validator_chain, nb); | 119 | return blocking_notifier_chain_unregister(&inet6addr_validator_chain, |
120 | nb); | ||
120 | } | 121 | } |
121 | EXPORT_SYMBOL(unregister_inet6addr_validator_notifier); | 122 | EXPORT_SYMBOL(unregister_inet6addr_validator_notifier); |
122 | 123 | ||
123 | int inet6addr_validator_notifier_call_chain(unsigned long val, void *v) | 124 | int inet6addr_validator_notifier_call_chain(unsigned long val, void *v) |
124 | { | 125 | { |
125 | return atomic_notifier_call_chain(&inet6addr_validator_chain, val, v); | 126 | return blocking_notifier_call_chain(&inet6addr_validator_chain, val, v); |
126 | } | 127 | } |
127 | EXPORT_SYMBOL(inet6addr_validator_notifier_call_chain); | 128 | EXPORT_SYMBOL(inet6addr_validator_notifier_call_chain); |
128 | 129 | ||