Skip to content

Commit

Permalink
bonding: simplify broadcast_xmit function
Browse files Browse the repository at this point in the history
We don't need to start from the curr_active_slave as the frame will be
sent to all eligible slaves anyway, so we remove the unnecessary local
variables, checks and comments, and make it use the standard list API.
This has the nice side-effect that later when it's converted to RCU
a race condition will be avoided which could lead to double packet tx.

Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Nikolay Aleksandrov authored and David S. Miller committed Aug 1, 2013
1 parent 71bc3b2 commit 78a646c
Showing 1 changed file with 16 additions and 36 deletions.
52 changes: 16 additions & 36 deletions drivers/net/bonding/bond_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3910,52 +3910,32 @@ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev)
return NETDEV_TX_OK;
}

/*
* in broadcast mode, we send everything to all usable interfaces.
*/
/* in broadcast mode, we send everything to all usable interfaces. */
static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave, *start_at;
struct net_device *tx_dev = NULL;
int i;
int res = 1;

start_at = bond->curr_active_slave;
if (!start_at)
goto out;
struct slave *slave = NULL;

bond_for_each_slave_from(bond, slave, i, start_at) {
if (IS_UP(slave->dev) &&
(slave->link == BOND_LINK_UP) &&
bond_is_active_slave(slave)) {
if (tx_dev) {
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
if (!skb2) {
pr_err("%s: Error: bond_xmit_broadcast(): skb_clone() failed\n",
bond_dev->name);
continue;
}
bond_for_each_slave(bond, slave) {
if (bond_is_last_slave(bond, slave))
break;
if (IS_UP(slave->dev) && slave->link == BOND_LINK_UP) {
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);

res = bond_dev_queue_xmit(bond, skb2, tx_dev);
if (res) {
kfree_skb(skb2);
continue;
}
if (!skb2) {
pr_err("%s: Error: bond_xmit_broadcast(): skb_clone() failed\n",
bond_dev->name);
continue;
}
tx_dev = slave->dev;
/* bond_dev_queue_xmit always returns 0 */
bond_dev_queue_xmit(bond, skb2, slave->dev);
}
}

if (tx_dev)
res = bond_dev_queue_xmit(bond, skb, tx_dev);

out:
if (res)
/* no suitable interface, frame not sent */
if (slave && IS_UP(slave->dev) && slave->link == BOND_LINK_UP)
bond_dev_queue_xmit(bond, skb, slave->dev);
else
kfree_skb(skb);

/* frame sent to all suitable interfaces */
return NETDEV_TX_OK;
}

Expand Down

0 comments on commit 78a646c

Please sign in to comment.