Commit 075897ce authored by John W. Linville's avatar John W. Linville Committed by Jeff Garzik

[PATCH] bonding: replicate IGMP traffic in activebackup mode

Replicate IGMP frames across all slaves in activebackup mode. This
ensures fail-over is rapid for multicast traffic as well. Otherwise,
multicast traffic will be lost until the next IGMP membership report
poll timeout.

This is conceptually similar to the treatment of IGMP traffic in
bond_alb_xmit. In that case, IGMP traffic transmitted on any slave
is re-routed to the active slave in order to ensure that multicast
traffic continues to be directed to the active receiver.
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 6c1792f4
...@@ -4240,6 +4240,39 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev ...@@ -4240,6 +4240,39 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
return 0; return 0;
} }
static void bond_activebackup_xmit_copy(struct sk_buff *skb,
struct bonding *bond,
struct slave *slave)
{
struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
struct ethhdr *eth_data;
u8 *hwaddr;
int res;
if (!skb2) {
printk(KERN_ERR DRV_NAME ": Error: "
"bond_activebackup_xmit_copy(): skb_copy() failed\n");
return;
}
skb2->mac.raw = (unsigned char *)skb2->data;
eth_data = eth_hdr(skb2);
/* Pick an appropriate source MAC address */
hwaddr = slave->perm_hwaddr;
if (!memcmp(eth_data->h_source, hwaddr, ETH_ALEN))
hwaddr = bond->curr_active_slave->perm_hwaddr;
/* Set source MAC address appropriately */
memcpy(eth_data->h_source, hwaddr, ETH_ALEN);
res = bond_dev_queue_xmit(bond, skb2, slave->dev);
if (res)
dev_kfree_skb(skb2);
return;
}
/* /*
* in active-backup mode, we know that bond->curr_active_slave is always valid if * in active-backup mode, we know that bond->curr_active_slave is always valid if
* the bond has a usable interface. * the bond has a usable interface.
...@@ -4256,10 +4289,26 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d ...@@ -4256,10 +4289,26 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
goto out; goto out;
} }
if (bond->curr_active_slave) { /* one usable interface */ if (!bond->curr_active_slave)
res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev); goto out;
/* Xmit IGMP frames on all slaves to ensure rapid fail-over
for multicast traffic on snooping switches */
if (skb->protocol == __constant_htons(ETH_P_IP) &&
skb->nh.iph->protocol == IPPROTO_IGMP) {
struct slave *slave, *active_slave;
int i;
active_slave = bond->curr_active_slave;
bond_for_each_slave_from_to(bond, slave, i, active_slave->next,
active_slave->prev)
if (IS_UP(slave->dev) &&
(slave->link == BOND_LINK_UP))
bond_activebackup_xmit_copy(skb, bond, slave);
} }
res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
out: out:
if (res) { if (res) {
/* no suitable interface, frame not sent */ /* no suitable interface, frame not sent */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment