Skip to content

Commit

Permalink
Merge branch 'bonding_neighbours'
Browse files Browse the repository at this point in the history
bonding: use neighbours instead of own lists

Veaceslav Falico says:

====================
This patchset introduces all the needed infrastructure, on top of current
adjacent lists, to be able to remove bond's slave_list/slave->list. The
overhead in memory/CPU is minimal, and after the patchset bonding can rely
on its slave-related functions, given the proper locking. I've done some
netperf benchmarks on a vm, and the delta was about 0.1gbps for 35gbps as a
whole, so no speed fluctuations.

It also automatically creates lower/upper and master symlinks in dev's
sysfs directory.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 26, 2013
2 parents 4ed377e + 5831d66 commit aae8c28
Show file tree
Hide file tree
Showing 11 changed files with 638 additions and 444 deletions.
54 changes: 27 additions & 27 deletions drivers/net/bonding/bond_3ad.c
Original file line number Diff line number Diff line change
Expand Up @@ -2117,7 +2117,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
read_lock(&bond->lock);

//check if there are any slaves
if (list_empty(&bond->slave_list))
if (!bond_has_slaves(bond))
goto re_arm;

// check if agg_select_timer timer after initialize is timed out
Expand Down Expand Up @@ -2417,14 +2417,15 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)

int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
{
struct slave *slave, *start_at;
struct bonding *bond = netdev_priv(dev);
int slave_agg_no;
int slaves_in_agg;
int agg_id;
int i;
struct slave *slave, *first_ok_slave;
struct aggregator *agg;
struct ad_info ad_info;
struct list_head *iter;
int slaves_in_agg;
int slave_agg_no;
int res = 1;
int agg_id;

read_lock(&bond->lock);
if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
Expand All @@ -2437,20 +2438,28 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
agg_id = ad_info.aggregator_id;

if (slaves_in_agg == 0) {
/*the aggregator is empty*/
pr_debug("%s: Error: active aggregator is empty\n", dev->name);
goto out;
}

slave_agg_no = bond->xmit_hash_policy(skb, slaves_in_agg);
first_ok_slave = NULL;

bond_for_each_slave(bond, slave) {
struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
bond_for_each_slave(bond, slave, iter) {
agg = SLAVE_AD_INFO(slave).port.aggregator;
if (!agg || agg->aggregator_identifier != agg_id)
continue;

if (agg && (agg->aggregator_identifier == agg_id)) {
if (slave_agg_no >= 0) {
if (!first_ok_slave && SLAVE_IS_OK(slave))
first_ok_slave = slave;
slave_agg_no--;
if (slave_agg_no < 0)
break;
continue;
}

if (SLAVE_IS_OK(slave)) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}

Expand All @@ -2460,20 +2469,10 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
goto out;
}

start_at = slave;

bond_for_each_slave_from(bond, slave, i, start_at) {
int slave_agg_id = 0;
struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;

if (agg)
slave_agg_id = agg->aggregator_identifier;

if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
break;
}
}
/* we couldn't find any suitable slave after the agg_no, so use the
* first suitable found, if found. */
if (first_ok_slave)
res = bond_dev_queue_xmit(bond, skb, first_ok_slave->dev);

out:
read_unlock(&bond->lock);
Expand Down Expand Up @@ -2515,11 +2514,12 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
void bond_3ad_update_lacp_rate(struct bonding *bond)
{
struct port *port = NULL;
struct list_head *iter;
struct slave *slave;
int lacp_fast;

lacp_fast = bond->params.lacp_fast;
bond_for_each_slave(bond, slave) {
bond_for_each_slave(bond, slave, iter) {
port = &(SLAVE_AD_INFO(slave).port);
__get_state_machine_lock(port);
if (lacp_fast)
Expand Down
81 changes: 44 additions & 37 deletions drivers/net/bonding/bond_alb.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,14 @@ static long long compute_gap(struct slave *slave)
static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
{
struct slave *slave, *least_loaded;
struct list_head *iter;
long long max_gap;

least_loaded = NULL;
max_gap = LLONG_MIN;

/* Find the slave with the largest gap */
bond_for_each_slave(bond, slave) {
bond_for_each_slave(bond, slave, iter) {
if (SLAVE_IS_OK(slave)) {
long long gap = compute_gap(slave);

Expand Down Expand Up @@ -382,30 +383,31 @@ static int rlb_arp_recv(const struct sk_buff *skb, struct bonding *bond,
static struct slave *rlb_next_rx_slave(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct slave *rx_slave, *slave, *start_at;
int i = 0;

if (bond_info->next_rx_slave)
start_at = bond_info->next_rx_slave;
else
start_at = bond_first_slave(bond);

rx_slave = NULL;
struct slave *before = NULL, *rx_slave = NULL, *slave;
struct list_head *iter;
bool found = false;

bond_for_each_slave_from(bond, slave, i, start_at) {
if (SLAVE_IS_OK(slave)) {
if (!rx_slave) {
rx_slave = slave;
} else if (slave->speed > rx_slave->speed) {
bond_for_each_slave(bond, slave, iter) {
if (!SLAVE_IS_OK(slave))
continue;
if (!found) {
if (!before || before->speed < slave->speed)
before = slave;
} else {
if (!rx_slave || rx_slave->speed < slave->speed)
rx_slave = slave;
}
}
if (slave == bond_info->rx_slave)
found = true;
}
/* we didn't find anything after the current or we have something
* better before and up to the current slave
*/
if (!rx_slave || (before && rx_slave->speed < before->speed))
rx_slave = before;

if (rx_slave) {
slave = bond_next_slave(bond, rx_slave);
bond_info->next_rx_slave = slave;
}
if (rx_slave)
bond_info->rx_slave = rx_slave;

return rx_slave;
}
Expand Down Expand Up @@ -1019,7 +1021,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])

/* loop through vlans and send one packet for each */
rcu_read_lock();
netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) {
netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
if (upper->priv_flags & IFF_802_1Q_VLAN)
alb_send_lp_vid(slave, mac_addr,
vlan_dev_vlan_id(upper));
Expand Down Expand Up @@ -1172,10 +1174,11 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla
*/
static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
{
struct slave *tmp_slave1, *free_mac_slave = NULL;
struct slave *has_bond_addr = bond->curr_active_slave;
struct slave *tmp_slave1, *free_mac_slave = NULL;
struct list_head *iter;

if (list_empty(&bond->slave_list)) {
if (!bond_has_slaves(bond)) {
/* this is the first slave */
return 0;
}
Expand All @@ -1196,7 +1199,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
/* The slave's address is equal to the address of the bond.
* Search for a spare address in the bond for this slave.
*/
bond_for_each_slave(bond, tmp_slave1) {
bond_for_each_slave(bond, tmp_slave1, iter) {
if (!bond_slave_has_mac(bond, tmp_slave1->perm_hwaddr)) {
/* no slave has tmp_slave1's perm addr
* as its curr addr
Expand Down Expand Up @@ -1246,15 +1249,16 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
*/
static int alb_set_mac_address(struct bonding *bond, void *addr)
{
char tmp_addr[ETH_ALEN];
struct slave *slave;
struct slave *slave, *rollback_slave;
struct list_head *iter;
struct sockaddr sa;
char tmp_addr[ETH_ALEN];
int res;

if (bond->alb_info.rlb_enabled)
return 0;

bond_for_each_slave(bond, slave) {
bond_for_each_slave(bond, slave, iter) {
/* save net_device's current hw address */
memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);

Expand All @@ -1274,10 +1278,12 @@ static int alb_set_mac_address(struct bonding *bond, void *addr)
sa.sa_family = bond->dev->type;

/* unwind from head to the slave that failed */
bond_for_each_slave_continue_reverse(bond, slave) {
memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
dev_set_mac_address(slave->dev, &sa);
memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
bond_for_each_slave(bond, rollback_slave, iter) {
if (rollback_slave == slave)
break;
memcpy(tmp_addr, rollback_slave->dev->dev_addr, ETH_ALEN);
dev_set_mac_address(rollback_slave->dev, &sa);
memcpy(rollback_slave->dev->dev_addr, tmp_addr, ETH_ALEN);
}

return res;
Expand Down Expand Up @@ -1458,11 +1464,12 @@ void bond_alb_monitor(struct work_struct *work)
struct bonding *bond = container_of(work, struct bonding,
alb_work.work);
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct list_head *iter;
struct slave *slave;

read_lock(&bond->lock);

if (list_empty(&bond->slave_list)) {
if (!bond_has_slaves(bond)) {
bond_info->tx_rebalance_counter = 0;
bond_info->lp_counter = 0;
goto re_arm;
Expand All @@ -1480,7 +1487,7 @@ void bond_alb_monitor(struct work_struct *work)
*/
read_lock(&bond->curr_slave_lock);

bond_for_each_slave(bond, slave)
bond_for_each_slave(bond, slave, iter)
alb_send_learning_packets(slave, slave->dev->dev_addr);

read_unlock(&bond->curr_slave_lock);
Expand All @@ -1493,7 +1500,7 @@ void bond_alb_monitor(struct work_struct *work)

read_lock(&bond->curr_slave_lock);

bond_for_each_slave(bond, slave) {
bond_for_each_slave(bond, slave, iter) {
tlb_clear_slave(bond, slave, 1);
if (slave == bond->curr_active_slave) {
SLAVE_TLB_INFO(slave).load =
Expand Down Expand Up @@ -1599,13 +1606,13 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
*/
void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
{
if (!list_empty(&bond->slave_list))
if (bond_has_slaves(bond))
alb_change_hw_addr_on_detach(bond, slave);

tlb_clear_slave(bond, slave, 0);

if (bond->alb_info.rlb_enabled) {
bond->alb_info.next_rx_slave = NULL;
bond->alb_info.rx_slave = NULL;
rlb_clear_slave(bond, slave);
}
}
Expand Down Expand Up @@ -1669,7 +1676,7 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
swap_slave = bond->curr_active_slave;
rcu_assign_pointer(bond->curr_active_slave, new_slave);

if (!new_slave || list_empty(&bond->slave_list))
if (!new_slave || !bond_has_slaves(bond))
return;

/* set the new curr_active_slave to the bonds mac address
Expand Down
4 changes: 1 addition & 3 deletions drivers/net/bonding/bond_alb.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,7 @@ struct alb_bond_info {
u8 rx_ntt; /* flag - need to transmit
* to all rx clients
*/
struct slave *next_rx_slave;/* next slave to be assigned
* to a new rx client for
*/
struct slave *rx_slave;/* last slave to xmit from */
u8 primary_is_promisc; /* boolean */
u32 rlb_promisc_timeout_counter;/* counts primary
* promiscuity time
Expand Down
Loading

0 comments on commit aae8c28

Please sign in to comment.