Skip to content

Commit

Permalink
bonding: Add array of all slaves
Browse files Browse the repository at this point in the history
Keep all slaves in array so it could be used to get the xmit slave
assume all the slaves are active.
The logic to add slave to the array is like the usable slaves, except
that we also add slaves that currently can't transmit - not up or active.

Signed-off-by: Maor Gottlieb <maorg@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Reviewed-by: Jay Vosburgh <jay.vosburgh@canonical.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
  • Loading branch information
Maor Gottlieb authored and Saeed Mahameed committed May 1, 2020
1 parent 5a19f1c commit 6b447e7
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 20 deletions.
78 changes: 59 additions & 19 deletions drivers/net/bonding/bond_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4120,6 +4120,38 @@ static void bond_skip_slave(struct bond_up_slave *slaves,
}
}

static void bond_set_slave_arr(struct bonding *bond,
struct bond_up_slave *usable_slaves,
struct bond_up_slave *all_slaves)
{
struct bond_up_slave *usable, *all;

usable = rtnl_dereference(bond->usable_slaves);
rcu_assign_pointer(bond->usable_slaves, usable_slaves);
kfree_rcu(usable, rcu);

all = rtnl_dereference(bond->all_slaves);
rcu_assign_pointer(bond->all_slaves, all_slaves);
kfree_rcu(all, rcu);
}

static void bond_reset_slave_arr(struct bonding *bond)
{
struct bond_up_slave *usable, *all;

usable = rtnl_dereference(bond->usable_slaves);
if (usable) {
RCU_INIT_POINTER(bond->usable_slaves, NULL);
kfree_rcu(usable, rcu);
}

all = rtnl_dereference(bond->all_slaves);
if (all) {
RCU_INIT_POINTER(bond->all_slaves, NULL);
kfree_rcu(all, rcu);
}
}

/* Build the usable slaves array in control path for modes that use xmit-hash
* to determine the slave interface -
* (a) BOND_MODE_8023AD
Expand All @@ -4130,7 +4162,7 @@ static void bond_skip_slave(struct bond_up_slave *slaves,
*/
int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)
{
struct bond_up_slave *usable_slaves, *old_usable_slaves;
struct bond_up_slave *usable_slaves = NULL, *all_slaves = NULL;
struct slave *slave;
struct list_head *iter;
int agg_id = 0;
Expand All @@ -4142,7 +4174,9 @@ int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)

usable_slaves = kzalloc(struct_size(usable_slaves, arr,
bond->slave_cnt), GFP_KERNEL);
if (!usable_slaves) {
all_slaves = kzalloc(struct_size(all_slaves, arr,
bond->slave_cnt), GFP_KERNEL);
if (!usable_slaves || !all_slaves) {
ret = -ENOMEM;
goto out;
}
Expand All @@ -4151,20 +4185,19 @@ int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)

if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
pr_debug("bond_3ad_get_active_agg_info failed\n");
kfree_rcu(usable_slaves, rcu);
/* No active aggragator means it's not safe to use
* the previous array.
*/
old_usable_slaves = rtnl_dereference(bond->usable_slaves);
if (old_usable_slaves) {
RCU_INIT_POINTER(bond->usable_slaves, NULL);
kfree_rcu(old_usable_slaves, rcu);
}
bond_reset_slave_arr(bond);
goto out;
}
agg_id = ad_info.aggregator_id;
}
bond_for_each_slave(bond, slave, iter) {
if (skipslave == slave)
continue;

all_slaves->arr[all_slaves->count++] = slave;
if (BOND_MODE(bond) == BOND_MODE_8023AD) {
struct aggregator *agg;

Expand All @@ -4174,23 +4207,24 @@ int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)
}
if (!bond_slave_can_tx(slave))
continue;
if (skipslave == slave)
continue;

slave_dbg(bond->dev, slave->dev, "Adding slave to tx hash array[%d]\n",
usable_slaves->count);

usable_slaves->arr[usable_slaves->count++] = slave;
}

old_usable_slaves = rtnl_dereference(bond->usable_slaves);
rcu_assign_pointer(bond->usable_slaves, usable_slaves);
if (old_usable_slaves)
kfree_rcu(old_usable_slaves, rcu);
bond_set_slave_arr(bond, usable_slaves, all_slaves);
return ret;
out:
if (ret != 0 && skipslave)
if (ret != 0 && skipslave) {
bond_skip_slave(rtnl_dereference(bond->all_slaves),
skipslave);
bond_skip_slave(rtnl_dereference(bond->usable_slaves),
skipslave);
}
kfree_rcu(all_slaves, rcu);
kfree_rcu(usable_slaves, rcu);

return ret;
}
Expand Down Expand Up @@ -4501,9 +4535,9 @@ void bond_setup(struct net_device *bond_dev)
static void bond_uninit(struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
struct bond_up_slave *usable, *all;
struct list_head *iter;
struct slave *slave;
struct bond_up_slave *arr;

bond_netpoll_cleanup(bond_dev);

Expand All @@ -4512,10 +4546,16 @@ static void bond_uninit(struct net_device *bond_dev)
__bond_release_one(bond_dev, slave->dev, true, true);
netdev_info(bond_dev, "Released all slaves\n");

arr = rtnl_dereference(bond->usable_slaves);
if (arr) {
usable = rtnl_dereference(bond->usable_slaves);
if (usable) {
RCU_INIT_POINTER(bond->usable_slaves, NULL);
kfree_rcu(arr, rcu);
kfree_rcu(usable, rcu);
}

all = rtnl_dereference(bond->all_slaves);
if (all) {
RCU_INIT_POINTER(bond->all_slaves, NULL);
kfree_rcu(all, rcu);
}

list_del(&bond->bond_list);
Expand Down
3 changes: 2 additions & 1 deletion include/net/bonding.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,8 @@ struct bonding {
struct slave __rcu *curr_active_slave;
struct slave __rcu *current_arp_slave;
struct slave __rcu *primary_slave;
struct bond_up_slave __rcu *usable_slaves; /* Array of usable slaves */
struct bond_up_slave __rcu *usable_slaves;
struct bond_up_slave __rcu *all_slaves;
bool force_primary;
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
int (*recv_probe)(const struct sk_buff *, struct bonding *,
Expand Down

0 comments on commit 6b447e7

Please sign in to comment.