Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 89d5dd2e authored by David Ahern's avatar David Ahern Committed by David S. Miller
Browse files

mlxsw: spectrum: router: Add support for address validator notifier



Add support for inetaddr_validator and inet6addr_validator. The
notifiers provide a means for validating ipv4 and ipv6 addresses
before the addresses are installed and on failure the error
is propagated back to the user.

Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Reviewed-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent de95e047
Loading
Loading
Loading
Loading
+14 −1
Original line number Original line Diff line number Diff line
@@ -4521,9 +4521,16 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb,
	return notifier_from_errno(err);
	return notifier_from_errno(err);
}
}


static struct notifier_block mlxsw_sp_inetaddr_valid_nb __read_mostly = {
	.notifier_call = mlxsw_sp_inetaddr_valid_event,
};

static struct notifier_block mlxsw_sp_inetaddr_nb __read_mostly = {
static struct notifier_block mlxsw_sp_inetaddr_nb __read_mostly = {
	.notifier_call = mlxsw_sp_inetaddr_event,
	.notifier_call = mlxsw_sp_inetaddr_event,
	.priority = 10,	/* Must be called before FIB notifier block */
};

static struct notifier_block mlxsw_sp_inet6addr_valid_nb __read_mostly = {
	.notifier_call = mlxsw_sp_inet6addr_valid_event,
};
};


static struct notifier_block mlxsw_sp_inet6addr_nb __read_mostly = {
static struct notifier_block mlxsw_sp_inet6addr_nb __read_mostly = {
@@ -4548,7 +4555,9 @@ static int __init mlxsw_sp_module_init(void)
{
{
	int err;
	int err;


	register_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
	register_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
	register_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
	register_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
	register_inet6addr_notifier(&mlxsw_sp_inet6addr_nb);
	register_inet6addr_notifier(&mlxsw_sp_inet6addr_nb);
	register_netevent_notifier(&mlxsw_sp_router_netevent_nb);
	register_netevent_notifier(&mlxsw_sp_router_netevent_nb);


@@ -4567,7 +4576,9 @@ static int __init mlxsw_sp_module_init(void)
err_core_driver_register:
err_core_driver_register:
	unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
	unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
	unregister_inet6addr_notifier(&mlxsw_sp_inet6addr_nb);
	unregister_inet6addr_notifier(&mlxsw_sp_inet6addr_nb);
	unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
	unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
	unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
	unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
	return err;
	return err;
}
}


@@ -4577,7 +4588,9 @@ static void __exit mlxsw_sp_module_exit(void)
	mlxsw_core_driver_unregister(&mlxsw_sp_driver);
	mlxsw_core_driver_unregister(&mlxsw_sp_driver);
	unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
	unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
	unregister_inet6addr_notifier(&mlxsw_sp_inet6addr_nb);
	unregister_inet6addr_notifier(&mlxsw_sp_inet6addr_nb);
	unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
	unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
	unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
	unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
}
}


module_init(mlxsw_sp_module_init);
module_init(mlxsw_sp_module_init);
+4 −0
Original line number Original line Diff line number Diff line
@@ -391,8 +391,12 @@ int mlxsw_sp_router_netevent_event(struct notifier_block *unused,
int mlxsw_sp_netdevice_router_port_event(struct net_device *dev);
int mlxsw_sp_netdevice_router_port_event(struct net_device *dev);
int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
			    unsigned long event, void *ptr);
			    unsigned long event, void *ptr);
int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
				  unsigned long event, void *ptr);
int mlxsw_sp_inet6addr_event(struct notifier_block *unused,
int mlxsw_sp_inet6addr_event(struct notifier_block *unused,
			     unsigned long event, void *ptr);
			     unsigned long event, void *ptr);
int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
				   unsigned long event, void *ptr);
int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
				 struct netdev_notifier_changeupper_info *info);
				 struct netdev_notifier_changeupper_info *info);
bool mlxsw_sp_netdev_is_ipip(const struct mlxsw_sp *mlxsw_sp,
bool mlxsw_sp_netdev_is_ipip(const struct mlxsw_sp *mlxsw_sp,
+52 −0
Original line number Original line Diff line number Diff line
@@ -5781,6 +5781,32 @@ int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
	struct mlxsw_sp_rif *rif;
	struct mlxsw_sp_rif *rif;
	int err = 0;
	int err = 0;


	/* NETDEV_UP event is handled by mlxsw_sp_inetaddr_valid_event */
	if (event == NETDEV_UP)
		goto out;

	mlxsw_sp = mlxsw_sp_lower_get(dev);
	if (!mlxsw_sp)
		goto out;

	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
	if (!mlxsw_sp_rif_should_config(rif, dev, event))
		goto out;

	err = __mlxsw_sp_inetaddr_event(dev, event);
out:
	return notifier_from_errno(err);
}

int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
				  unsigned long event, void *ptr)
{
	struct in_validator_info *ivi = (struct in_validator_info *) ptr;
	struct net_device *dev = ivi->ivi_dev->dev;
	struct mlxsw_sp *mlxsw_sp;
	struct mlxsw_sp_rif *rif;
	int err = 0;

	mlxsw_sp = mlxsw_sp_lower_get(dev);
	mlxsw_sp = mlxsw_sp_lower_get(dev);
	if (!mlxsw_sp)
	if (!mlxsw_sp)
		goto out;
		goto out;
@@ -5833,6 +5859,10 @@ int mlxsw_sp_inet6addr_event(struct notifier_block *unused,
	struct mlxsw_sp_inet6addr_event_work *inet6addr_work;
	struct mlxsw_sp_inet6addr_event_work *inet6addr_work;
	struct net_device *dev = if6->idev->dev;
	struct net_device *dev = if6->idev->dev;


	/* NETDEV_UP event is handled by mlxsw_sp_inet6addr_valid_event */
	if (event == NETDEV_UP)
		return NOTIFY_DONE;

	if (!mlxsw_sp_port_dev_lower_find_rcu(dev))
	if (!mlxsw_sp_port_dev_lower_find_rcu(dev))
		return NOTIFY_DONE;
		return NOTIFY_DONE;


@@ -5849,6 +5879,28 @@ int mlxsw_sp_inet6addr_event(struct notifier_block *unused,
	return NOTIFY_DONE;
	return NOTIFY_DONE;
}
}


int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
				   unsigned long event, void *ptr)
{
	struct in6_validator_info *i6vi = (struct in6_validator_info *) ptr;
	struct net_device *dev = i6vi->i6vi_dev->dev;
	struct mlxsw_sp *mlxsw_sp;
	struct mlxsw_sp_rif *rif;
	int err = 0;

	mlxsw_sp = mlxsw_sp_lower_get(dev);
	if (!mlxsw_sp)
		goto out;

	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
	if (!mlxsw_sp_rif_should_config(rif, dev, event))
		goto out;

	err = __mlxsw_sp_inetaddr_event(dev, event);
out:
	return notifier_from_errno(err);
}

static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
			     const char *mac, int mtu)
			     const char *mac, int mtu)
{
{