Commit 55d7c914 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mlxsw-cleanups'



Petr Machata says:

====================
mlxsw: Cleanups in router code

This patchset moves some router-related code from spectrum.c to
spectrum_router.c where it should be. It also simplifies handlers of
netevent notifications.

- Patch #1 caches router pointer in a dedicated variable. This obviates the
  need to access the same as mlxsw_sp->router, making lines shorter, and
  permitting a future patch to add code that fits within 80 character
  limit.

- Patch #2 moves IP / IPv6 validation notifier blocks from spectrum.c
  to spectrum_router, where the handlers are anyway.

- In patch #3, pass router pointer to scheduler of deferred work directly,
  instead of having it deduce it on its own.

- This makes the router pointer available in the handler function
  mlxsw_sp_router_netevent_event(), so in patch #4, use it directly,
  instead of finding it through mlxsw_sp_port.

- In patch #5, extend mlxsw_sp_router_schedule_work() so that the
  NETEVENT_NEIGH_UPDATE handler can use it directly instead of inlining
  equivalent code.

- In patches #6 and #7, add helpers for two common operations involving
  a backing netdev of a RIF. This makes it unnecessary for the function
  mlxsw_sp_rif_dev() to be visible outside of the router module, so in
  patch #8, hide it.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e069ba07 df95ae66
Loading
Loading
Loading
Loading
+1 −17
Original line number Diff line number Diff line
@@ -5139,14 +5139,6 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb,
	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_inet6addr_valid_nb __read_mostly = {
	.notifier_call = mlxsw_sp_inet6addr_valid_event,
};

static const struct pci_device_id mlxsw_sp1_pci_id_table[] = {
	{PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0},
	{0, },
@@ -5191,12 +5183,9 @@ static int __init mlxsw_sp_module_init(void)
{
	int err;

	register_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
	register_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);

	err = mlxsw_core_driver_register(&mlxsw_sp1_driver);
	if (err)
		goto err_sp1_core_driver_register;
		return err;

	err = mlxsw_core_driver_register(&mlxsw_sp2_driver);
	if (err)
@@ -5242,9 +5231,6 @@ static int __init mlxsw_sp_module_init(void)
	mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
err_sp2_core_driver_register:
	mlxsw_core_driver_unregister(&mlxsw_sp1_driver);
err_sp1_core_driver_register:
	unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
	unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
	return err;
}

@@ -5258,8 +5244,6 @@ static void __exit mlxsw_sp_module_exit(void)
	mlxsw_core_driver_unregister(&mlxsw_sp3_driver);
	mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
	mlxsw_core_driver_unregister(&mlxsw_sp1_driver);
	unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
	unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
}

module_init(mlxsw_sp_module_init);
+0 −4
Original line number Diff line number Diff line
@@ -755,10 +755,6 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
			      const struct net_device *macvlan_dev);
int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
				  unsigned long event, void *ptr);
int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
				   unsigned long event, void *ptr);
int
mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
			       struct net_device *l3_dev,
+1 −1
Original line number Diff line number Diff line
@@ -221,7 +221,7 @@ mlxsw_sp_dpipe_table_erif_entries_dump(void *priv, bool counters_enabled,
	for (; i < rif_count; i++) {
		struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);

		if (!rif || !mlxsw_sp_rif_dev(rif))
		if (!rif || !mlxsw_sp_rif_has_dev(rif))
			continue;
		err = mlxsw_sp_erif_entry_get(mlxsw_sp, &entry, rif,
					      counters_enabled);
+8 −11
Original line number Diff line number Diff line
@@ -704,12 +704,12 @@ void mlxsw_sp_mr_vif_del(struct mlxsw_sp_mr_table *mr_table, vifi_t vif_index)

static struct mlxsw_sp_mr_vif *
mlxsw_sp_mr_dev_vif_lookup(struct mlxsw_sp_mr_table *mr_table,
			   const struct net_device *dev)
			   const struct mlxsw_sp_rif *rif)
{
	vifi_t vif_index;

	for (vif_index = 0; vif_index < MAXVIFS; vif_index++)
		if (mr_table->vifs[vif_index].dev == dev)
		if (mlxsw_sp_rif_dev_is(rif, mr_table->vifs[vif_index].dev))
			return &mr_table->vifs[vif_index];
	return NULL;
}
@@ -717,13 +717,12 @@ mlxsw_sp_mr_dev_vif_lookup(struct mlxsw_sp_mr_table *mr_table,
int mlxsw_sp_mr_rif_add(struct mlxsw_sp_mr_table *mr_table,
			const struct mlxsw_sp_rif *rif)
{
	const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif);
	struct mlxsw_sp_mr_vif *mr_vif;

	if (!rif_dev)
	if (!mlxsw_sp_rif_has_dev(rif))
		return 0;

	mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev);
	mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif);
	if (!mr_vif)
		return 0;
	return mlxsw_sp_mr_vif_resolve(mr_table, mr_vif->dev, mr_vif,
@@ -733,13 +732,12 @@ int mlxsw_sp_mr_rif_add(struct mlxsw_sp_mr_table *mr_table,
void mlxsw_sp_mr_rif_del(struct mlxsw_sp_mr_table *mr_table,
			 const struct mlxsw_sp_rif *rif)
{
	const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif);
	struct mlxsw_sp_mr_vif *mr_vif;

	if (!rif_dev)
	if (!mlxsw_sp_rif_has_dev(rif))
		return;

	mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev);
	mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif);
	if (!mr_vif)
		return;
	mlxsw_sp_mr_vif_unresolve(mr_table, mr_vif->dev, mr_vif);
@@ -748,17 +746,16 @@ void mlxsw_sp_mr_rif_del(struct mlxsw_sp_mr_table *mr_table,
void mlxsw_sp_mr_rif_mtu_update(struct mlxsw_sp_mr_table *mr_table,
				const struct mlxsw_sp_rif *rif, int mtu)
{
	const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif);
	struct mlxsw_sp *mlxsw_sp = mr_table->mlxsw_sp;
	struct mlxsw_sp_mr_route_vif_entry *rve;
	struct mlxsw_sp_mr *mr = mlxsw_sp->mr;
	struct mlxsw_sp_mr_vif *mr_vif;

	if (!rif_dev)
	if (!mlxsw_sp_rif_has_dev(rif))
		return;

	/* Search for a VIF that use that RIF */
	mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev);
	mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif);
	if (!mr_vif)
		return;

+74 −47
Original line number Diff line number Diff line
@@ -2748,13 +2748,12 @@ static void mlxsw_sp_router_update_priority_work(struct work_struct *work)
}

static int mlxsw_sp_router_schedule_work(struct net *net,
					 struct notifier_block *nb,
					 struct mlxsw_sp_router *router,
					 struct neighbour *n,
					 void (*cb)(struct work_struct *))
{
	struct mlxsw_sp_netevent_work *net_work;
	struct mlxsw_sp_router *router;

	router = container_of(nb, struct mlxsw_sp_router, netevent_nb);
	if (!net_eq(net, mlxsw_sp_net(router->mlxsw_sp)))
		return NOTIFY_DONE;

@@ -2764,19 +2763,31 @@ static int mlxsw_sp_router_schedule_work(struct net *net,

	INIT_WORK(&net_work->work, cb);
	net_work->mlxsw_sp = router->mlxsw_sp;
	net_work->n = n;
	mlxsw_core_schedule_work(&net_work->work);
	return NOTIFY_DONE;
}

static bool mlxsw_sp_dev_lower_is_port(struct net_device *dev)
{
	struct mlxsw_sp_port *mlxsw_sp_port;

	rcu_read_lock();
	mlxsw_sp_port = mlxsw_sp_port_dev_lower_find_rcu(dev);
	rcu_read_unlock();
	return !!mlxsw_sp_port;
}

static int mlxsw_sp_router_netevent_event(struct notifier_block *nb,
					  unsigned long event, void *ptr)
{
	struct mlxsw_sp_netevent_work *net_work;
	struct mlxsw_sp_port *mlxsw_sp_port;
	struct mlxsw_sp *mlxsw_sp;
	struct mlxsw_sp_router *router;
	unsigned long interval;
	struct neigh_parms *p;
	struct neighbour *n;
	struct net *net;

	router = container_of(nb, struct mlxsw_sp_router, netevent_nb);

	switch (event) {
	case NETEVENT_DELAY_PROBE_TIME_UPDATE:
@@ -2790,51 +2801,37 @@ static int mlxsw_sp_router_netevent_event(struct notifier_block *nb,
		/* We are in atomic context and can't take RTNL mutex,
		 * so use RCU variant to walk the device chain.
		 */
		mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(p->dev);
		if (!mlxsw_sp_port)
		if (!mlxsw_sp_dev_lower_is_port(p->dev))
			return NOTIFY_DONE;

		mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
		interval = jiffies_to_msecs(NEIGH_VAR(p, DELAY_PROBE_TIME));
		mlxsw_sp->router->neighs_update.interval = interval;

		mlxsw_sp_port_dev_put(mlxsw_sp_port);
		router->neighs_update.interval = interval;
		break;
	case NETEVENT_NEIGH_UPDATE:
		n = ptr;
		net = neigh_parms_net(n->parms);

		if (n->tbl->family != AF_INET && n->tbl->family != AF_INET6)
			return NOTIFY_DONE;

		mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(n->dev);
		if (!mlxsw_sp_port)
		if (!mlxsw_sp_dev_lower_is_port(n->dev))
			return NOTIFY_DONE;

		net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
		if (!net_work) {
			mlxsw_sp_port_dev_put(mlxsw_sp_port);
			return NOTIFY_BAD;
		}

		INIT_WORK(&net_work->work, mlxsw_sp_router_neigh_event_work);
		net_work->mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
		net_work->n = n;

		/* Take a reference to ensure the neighbour won't be
		 * destructed until we drop the reference in delayed
		 * work.
		 */
		neigh_clone(n);
		mlxsw_core_schedule_work(&net_work->work);
		mlxsw_sp_port_dev_put(mlxsw_sp_port);
		break;
		return mlxsw_sp_router_schedule_work(net, router, n,
				mlxsw_sp_router_neigh_event_work);

	case NETEVENT_IPV4_MPATH_HASH_UPDATE:
	case NETEVENT_IPV6_MPATH_HASH_UPDATE:
		return mlxsw_sp_router_schedule_work(ptr, nb,
		return mlxsw_sp_router_schedule_work(ptr, router, NULL,
				mlxsw_sp_router_mp_hash_event_work);

	case NETEVENT_IPV4_FWD_UPDATE_PRIORITY_UPDATE:
		return mlxsw_sp_router_schedule_work(ptr, nb,
		return mlxsw_sp_router_schedule_work(ptr, router, NULL,
				mlxsw_sp_router_update_priority_work);
	}

@@ -7708,7 +7705,7 @@ mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,

	for (i = 0; i < max_rifs; i++)
		if (mlxsw_sp->router->rifs[i] &&
		    mlxsw_sp->router->rifs[i]->dev == dev)
		    mlxsw_sp_rif_dev_is(mlxsw_sp->router->rifs[i], dev))
			return mlxsw_sp->router->rifs[i];

	return NULL;
@@ -8078,11 +8075,22 @@ int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif)
	return rif->dev->ifindex;
}

const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif)
static const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif)
{
	return rif->dev;
}

bool mlxsw_sp_rif_has_dev(const struct mlxsw_sp_rif *rif)
{
	return !!mlxsw_sp_rif_dev(rif);
}

bool mlxsw_sp_rif_dev_is(const struct mlxsw_sp_rif *rif,
			 const struct net_device *dev)
{
	return mlxsw_sp_rif_dev(rif) == dev;
}

static void mlxsw_sp_rif_push_l3_stats(struct mlxsw_sp_rif *rif)
{
	struct rtnl_hw_stats64 stats = {};
@@ -8879,7 +8887,7 @@ static int mlxsw_sp_inetaddr_event(struct notifier_block *nb,
	return notifier_from_errno(err);
}

int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
static 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;
@@ -8962,7 +8970,7 @@ static int mlxsw_sp_inet6addr_event(struct notifier_block *nb,
	return NOTIFY_DONE;
}

int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
static 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;
@@ -10510,6 +10518,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
			 struct netlink_ext_ack *extack)
{
	struct mlxsw_sp_router *router;
	struct notifier_block *nb;
	int err;

	router = kzalloc(sizeof(*mlxsw_sp->router), GFP_KERNEL);
@@ -10588,6 +10597,17 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
	if (err)
		goto err_register_inet6addr_notifier;

	router->inetaddr_valid_nb.notifier_call = mlxsw_sp_inetaddr_valid_event;
	err = register_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
	if (err)
		goto err_register_inetaddr_valid_notifier;

	nb = &router->inet6addr_valid_nb;
	nb->notifier_call = mlxsw_sp_inet6addr_valid_event;
	err = register_inet6addr_validator_notifier(nb);
	if (err)
		goto err_register_inet6addr_valid_notifier;

	mlxsw_sp->router->netevent_nb.notifier_call =
		mlxsw_sp_router_netevent_event;
	err = register_netevent_notifier(&mlxsw_sp->router->netevent_nb);
@@ -10627,6 +10647,10 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
err_register_nexthop_notifier:
	unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb);
err_register_netevent_notifier:
	unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb);
err_register_inet6addr_valid_notifier:
	unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
err_register_inetaddr_valid_notifier:
	unregister_inet6addr_notifier(&router->inet6addr_nb);
err_register_inet6addr_notifier:
	unregister_inetaddr_notifier(&router->inetaddr_nb);
@@ -10664,15 +10688,18 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,

void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
{
	struct mlxsw_sp_router *router = mlxsw_sp->router;

	unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
					  &mlxsw_sp->router->netdevice_nb);
	unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp),
				&mlxsw_sp->router->fib_nb);
					  &router->netdevice_nb);
	unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp), &router->fib_nb);
	unregister_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
				    &mlxsw_sp->router->nexthop_nb);
	unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb);
	unregister_inet6addr_notifier(&mlxsw_sp->router->inet6addr_nb);
	unregister_inetaddr_notifier(&mlxsw_sp->router->inetaddr_nb);
				    &router->nexthop_nb);
	unregister_netevent_notifier(&router->netevent_nb);
	unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb);
	unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
	unregister_inet6addr_notifier(&router->inet6addr_nb);
	unregister_inetaddr_notifier(&router->inetaddr_nb);
	mlxsw_core_flush_owq();
	mlxsw_sp_mp_hash_fini(mlxsw_sp);
	mlxsw_sp_neigh_fini(mlxsw_sp);
@@ -10680,12 +10707,12 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
	mlxsw_sp_vrs_fini(mlxsw_sp);
	mlxsw_sp_mr_fini(mlxsw_sp);
	mlxsw_sp_lpm_fini(mlxsw_sp);
	rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht);
	rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
	rhashtable_destroy(&router->nexthop_group_ht);
	rhashtable_destroy(&router->nexthop_ht);
	mlxsw_sp_ipips_fini(mlxsw_sp);
	mlxsw_sp_rifs_fini(mlxsw_sp);
	__mlxsw_sp_router_fini(mlxsw_sp);
	cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw);
	mutex_destroy(&mlxsw_sp->router->lock);
	kfree(mlxsw_sp->router);
	cancel_delayed_work_sync(&router->nh_grp_activity_dw);
	mutex_destroy(&router->lock);
	kfree(router);
}
Loading