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

Commit 234bcf8a authored by Shlomo Pongratz's avatar Shlomo Pongratz Committed by David S. Miller
Browse files

net/bonding: correctly proxy slave neigh param setup ndo function



The current implemenation was buggy for slaves who use ndo_neigh_setup,
since the networking stack invokes the bonding device ndo entry (from
neigh_params_alloc) before any devices are enslaved, and the bonding
driver can't further delegate the call at that point in time. As a
result when bonding IPoIB devices, the neigh_cleanup hasn't been called.

Fix that by deferring the actual call into the slave ndo_neigh_setup
from the time the bonding neigh_setup is called.

Signed-off-by: default avatarShlomo Pongratz <shlomop@mellanox.com>
Signed-off-by: default avatarJay Vosburgh <fubar@us.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2af73d4b
Loading
Loading
Loading
Loading
+43 −8
Original line number Diff line number Diff line
@@ -3704,17 +3704,52 @@ static void bond_set_multicast_list(struct net_device *bond_dev)
	read_unlock(&bond->lock);
}

static int bond_neigh_setup(struct net_device *dev, struct neigh_parms *parms)
static int bond_neigh_init(struct neighbour *n)
{
	struct bonding *bond = netdev_priv(dev);
	struct bonding *bond = netdev_priv(n->dev);
	struct slave *slave = bond->first_slave;
	const struct net_device_ops *slave_ops;
	struct neigh_parms parms;
	int ret;

	if (slave) {
		const struct net_device_ops *slave_ops
			= slave->dev->netdev_ops;
		if (slave_ops->ndo_neigh_setup)
			return slave_ops->ndo_neigh_setup(slave->dev, parms);
	if (!slave)
		return 0;

	slave_ops = slave->dev->netdev_ops;

	if (!slave_ops->ndo_neigh_setup)
		return 0;

	parms.neigh_setup = NULL;
	parms.neigh_cleanup = NULL;
	ret = slave_ops->ndo_neigh_setup(slave->dev, &parms);
	if (ret)
		return ret;

	/*
	 * Assign slave's neigh_cleanup to neighbour in case cleanup is called
	 * after the last slave has been detached.  Assumes that all slaves
	 * utilize the same neigh_cleanup (true at this writing as only user
	 * is ipoib).
	 */
	n->parms->neigh_cleanup = parms.neigh_cleanup;

	if (!parms.neigh_setup)
		return 0;

	return parms.neigh_setup(n);
}

/*
 * The bonding ndo_neigh_setup is called at init time beofre any
 * slave exists. So we must declare proxy setup function which will
 * be used at run time to resolve the actual slave neigh param setup.
 */
static int bond_neigh_setup(struct net_device *dev,
			    struct neigh_parms *parms)
{
	parms->neigh_setup   = bond_neigh_init;

	return 0;
}