aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
authorNikolay Aleksandrov <razor@BlackWall.org>2013-08-01 10:54:49 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-01 19:42:02 -0400
commit78a646ced88450754613573f7d1fa7cb0de14bb3 (patch)
treeff4d339878127fd2eeefbd81842b65b8c23828b5 /drivers/net/bonding
parent71bc3b2dc5d02566afe1b23a7b72bfc8acdd04e1 (diff)
bonding: simplify broadcast_xmit function
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>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/bond_main.c52
1 files changed, 16 insertions, 36 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index ac60b697ab7e..aa9da006fa68 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3910,52 +3910,32 @@ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev)
3910 return NETDEV_TX_OK; 3910 return NETDEV_TX_OK;
3911} 3911}
3912 3912
3913/* 3913/* in broadcast mode, we send everything to all usable interfaces. */
3914 * in broadcast mode, we send everything to all usable interfaces.
3915 */
3916static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) 3914static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
3917{ 3915{
3918 struct bonding *bond = netdev_priv(bond_dev); 3916 struct bonding *bond = netdev_priv(bond_dev);
3919 struct slave *slave, *start_at; 3917 struct slave *slave = NULL;
3920 struct net_device *tx_dev = NULL;
3921 int i;
3922 int res = 1;
3923
3924 start_at = bond->curr_active_slave;
3925 if (!start_at)
3926 goto out;
3927 3918
3928 bond_for_each_slave_from(bond, slave, i, start_at) { 3919 bond_for_each_slave(bond, slave) {
3929 if (IS_UP(slave->dev) && 3920 if (bond_is_last_slave(bond, slave))
3930 (slave->link == BOND_LINK_UP) && 3921 break;
3931 bond_is_active_slave(slave)) { 3922 if (IS_UP(slave->dev) && slave->link == BOND_LINK_UP) {
3932 if (tx_dev) { 3923 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
3933 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
3934 if (!skb2) {
3935 pr_err("%s: Error: bond_xmit_broadcast(): skb_clone() failed\n",
3936 bond_dev->name);
3937 continue;
3938 }
3939 3924
3940 res = bond_dev_queue_xmit(bond, skb2, tx_dev); 3925 if (!skb2) {
3941 if (res) { 3926 pr_err("%s: Error: bond_xmit_broadcast(): skb_clone() failed\n",
3942 kfree_skb(skb2); 3927 bond_dev->name);
3943 continue; 3928 continue;
3944 }
3945 } 3929 }
3946 tx_dev = slave->dev; 3930 /* bond_dev_queue_xmit always returns 0 */
3931 bond_dev_queue_xmit(bond, skb2, slave->dev);
3947 } 3932 }
3948 } 3933 }
3949 3934 if (slave && IS_UP(slave->dev) && slave->link == BOND_LINK_UP)
3950 if (tx_dev) 3935 bond_dev_queue_xmit(bond, skb, slave->dev);
3951 res = bond_dev_queue_xmit(bond, skb, tx_dev); 3936 else
3952
3953out:
3954 if (res)
3955 /* no suitable interface, frame not sent */
3956 kfree_skb(skb); 3937 kfree_skb(skb);
3957 3938
3958 /* frame sent to all suitable interfaces */
3959 return NETDEV_TX_OK; 3939 return NETDEV_TX_OK;
3960} 3940}
3961 3941