|
@@ -4057,8 +4057,7 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
|
|
|
{
|
|
|
struct bonding *bond = bond_dev->priv;
|
|
|
struct slave *slave, *start_at;
|
|
|
- int i;
|
|
|
- int res = 1;
|
|
|
+ int i, slave_no, res = 1;
|
|
|
|
|
|
read_lock(&bond->lock);
|
|
|
|
|
@@ -4066,29 +4065,29 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- read_lock(&bond->curr_slave_lock);
|
|
|
- slave = start_at = bond->curr_active_slave;
|
|
|
- read_unlock(&bond->curr_slave_lock);
|
|
|
+ /*
|
|
|
+ * Concurrent TX may collide on rr_tx_counter; we accept that
|
|
|
+ * as being rare enough not to justify using an atomic op here
|
|
|
+ */
|
|
|
+ slave_no = bond->rr_tx_counter++ % bond->slave_cnt;
|
|
|
|
|
|
- if (!slave) {
|
|
|
- goto out;
|
|
|
+ bond_for_each_slave(bond, slave, i) {
|
|
|
+ slave_no--;
|
|
|
+ if (slave_no < 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ start_at = slave;
|
|
|
bond_for_each_slave_from(bond, slave, i, start_at) {
|
|
|
if (IS_UP(slave->dev) &&
|
|
|
(slave->link == BOND_LINK_UP) &&
|
|
|
(slave->state == BOND_STATE_ACTIVE)) {
|
|
|
res = bond_dev_queue_xmit(bond, skb, slave->dev);
|
|
|
-
|
|
|
- write_lock(&bond->curr_slave_lock);
|
|
|
- bond->curr_active_slave = slave->next;
|
|
|
- write_unlock(&bond->curr_slave_lock);
|
|
|
-
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
out:
|
|
|
if (res) {
|
|
|
/* no suitable interface, frame not sent */
|