When a bond has tc rules offloaded to its slaves, prevent new slaves being added. To remove a slave from a bond, the offloaded rules must first be deleted. For the case where a slave port on a bond is unregistered from the kernel, flush all offloaded rules and destroy the bond.
Signed-off-by: John Hurley <john.hur...@netronome.com> --- drivers/net/bonding/bond_main.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index d9e41cf..4c146b1 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1607,6 +1607,15 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, return -EPERM; } + /* check for TC offloaded */ + if (bond_get_offload_cnt(bond)) { + NL_SET_ERR_MSG(extack, + "Cannot enslave - bond has offloaded rules."); + netdev_err(bond_dev, + "cannot enslave - bond has offloaded rules.\n"); + return -EPERM; + } + /* vlan challenged mutual exclusion */ /* no need to lock since we're protected by rtnl_lock */ if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { @@ -2237,6 +2246,13 @@ static int __bond_release_one(struct net_device *bond_dev, /* A wrapper used because of ndo_del_link */ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) { + if (bond_get_offload_cnt(netdev_priv(bond_dev))) { + netdev_err(bond_dev, + "cannot release %s - has offloaded rules.\n", + slave_dev->name); + return -EPERM; + } + return __bond_release_one(bond_dev, slave_dev, false, false); } @@ -3325,6 +3341,8 @@ static int bond_slave_netdev_event(unsigned long event, case NETDEV_UNREGISTER: if (bond_dev->type != ARPHRD_ETHER) bond_release_and_destroy(bond_dev, slave_dev); + else if (bond_get_offload_cnt(bond)) + unregister_netdevice_queue(bond_dev, NULL); else __bond_release_one(bond_dev, slave_dev, false, true); break; -- 2.7.4