bonding: Add helper function to get the xmit slave in rr mode

Add helper function to get the xmit slave when bond is in round
robin mode. Change bond_xmit_slave_id to bond_get_slave_by_id, then
the logic for find the next slave for transmit could be used
both by the xmit flow and the .ndo to get the xmit slave.

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>
This commit is contained in:
Maor Gottlieb 2020-04-30 22:21:36 +03:00 committed by Saeed Mahameed
parent c071d91d2a
commit 29d5bbccb3
1 changed files with 30 additions and 26 deletions

View File

@ -3923,16 +3923,15 @@ unwind:
} }
/** /**
* bond_xmit_slave_id - transmit skb through slave with slave_id * bond_get_slave_by_id - get xmit slave with slave_id
* @bond: bonding device that is transmitting * @bond: bonding device that is transmitting
* @skb: buffer to transmit
* @slave_id: slave id up to slave_cnt-1 through which to transmit * @slave_id: slave id up to slave_cnt-1 through which to transmit
* *
* This function tries to transmit through slave with slave_id but in case * This function tries to get slave with slave_id but in case
* it fails, it tries to find the first available slave for transmission. * it fails, it tries to find the first available slave for transmission.
* The skb is consumed in all cases, thus the function is void.
*/ */
static void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int slave_id) static struct slave *bond_get_slave_by_id(struct bonding *bond,
int slave_id)
{ {
struct list_head *iter; struct list_head *iter;
struct slave *slave; struct slave *slave;
@ -3941,10 +3940,8 @@ static void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int sl
/* Here we start from the slave with slave_id */ /* Here we start from the slave with slave_id */
bond_for_each_slave_rcu(bond, slave, iter) { bond_for_each_slave_rcu(bond, slave, iter) {
if (--i < 0) { if (--i < 0) {
if (bond_slave_can_tx(slave)) { if (bond_slave_can_tx(slave))
bond_dev_queue_xmit(bond, skb, slave->dev); return slave;
return;
}
} }
} }
@ -3953,13 +3950,11 @@ static void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int sl
bond_for_each_slave_rcu(bond, slave, iter) { bond_for_each_slave_rcu(bond, slave, iter) {
if (--i < 0) if (--i < 0)
break; break;
if (bond_slave_can_tx(slave)) { if (bond_slave_can_tx(slave))
bond_dev_queue_xmit(bond, skb, slave->dev); return slave;
return;
}
} }
/* no slave that can tx has been found */
bond_tx_drop(bond->dev, skb); return NULL;
} }
/** /**
@ -3995,10 +3990,9 @@ static u32 bond_rr_gen_slave_id(struct bonding *bond)
return slave_id; return slave_id;
} }
static netdev_tx_t bond_xmit_roundrobin(struct sk_buff *skb, static struct slave *bond_xmit_roundrobin_slave_get(struct bonding *bond,
struct net_device *bond_dev) struct sk_buff *skb)
{ {
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave; struct slave *slave;
int slave_cnt; int slave_cnt;
u32 slave_id; u32 slave_id;
@ -4020,21 +4014,31 @@ static netdev_tx_t bond_xmit_roundrobin(struct sk_buff *skb,
if (iph->protocol == IPPROTO_IGMP) { if (iph->protocol == IPPROTO_IGMP) {
slave = rcu_dereference(bond->curr_active_slave); slave = rcu_dereference(bond->curr_active_slave);
if (slave) if (slave)
bond_dev_queue_xmit(bond, skb, slave->dev); return slave;
else return bond_get_slave_by_id(bond, 0);
bond_xmit_slave_id(bond, skb, 0);
return NETDEV_TX_OK;
} }
} }
non_igmp: non_igmp:
slave_cnt = READ_ONCE(bond->slave_cnt); slave_cnt = READ_ONCE(bond->slave_cnt);
if (likely(slave_cnt)) { if (likely(slave_cnt)) {
slave_id = bond_rr_gen_slave_id(bond); slave_id = bond_rr_gen_slave_id(bond) % slave_cnt;
bond_xmit_slave_id(bond, skb, slave_id % slave_cnt); return bond_get_slave_by_id(bond, slave_id);
} else {
bond_tx_drop(bond_dev, skb);
} }
return NULL;
}
static netdev_tx_t bond_xmit_roundrobin(struct sk_buff *skb,
struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave;
slave = bond_xmit_roundrobin_slave_get(bond, skb);
if (slave)
bond_dev_queue_xmit(bond, skb, slave->dev);
else
bond_tx_drop(bond_dev, skb);
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }