diff options
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index f264ff162979..58c4e36f87d7 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -4241,6 +4241,39 @@ out: | |||
4241 | return 0; | 4241 | return 0; |
4242 | } | 4242 | } |
4243 | 4243 | ||
4244 | static void bond_activebackup_xmit_copy(struct sk_buff *skb, | ||
4245 | struct bonding *bond, | ||
4246 | struct slave *slave) | ||
4247 | { | ||
4248 | struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); | ||
4249 | struct ethhdr *eth_data; | ||
4250 | u8 *hwaddr; | ||
4251 | int res; | ||
4252 | |||
4253 | if (!skb2) { | ||
4254 | printk(KERN_ERR DRV_NAME ": Error: " | ||
4255 | "bond_activebackup_xmit_copy(): skb_copy() failed\n"); | ||
4256 | return; | ||
4257 | } | ||
4258 | |||
4259 | skb2->mac.raw = (unsigned char *)skb2->data; | ||
4260 | eth_data = eth_hdr(skb2); | ||
4261 | |||
4262 | /* Pick an appropriate source MAC address */ | ||
4263 | hwaddr = slave->perm_hwaddr; | ||
4264 | if (!memcmp(eth_data->h_source, hwaddr, ETH_ALEN)) | ||
4265 | hwaddr = bond->curr_active_slave->perm_hwaddr; | ||
4266 | |||
4267 | /* Set source MAC address appropriately */ | ||
4268 | memcpy(eth_data->h_source, hwaddr, ETH_ALEN); | ||
4269 | |||
4270 | res = bond_dev_queue_xmit(bond, skb2, slave->dev); | ||
4271 | if (res) | ||
4272 | dev_kfree_skb(skb2); | ||
4273 | |||
4274 | return; | ||
4275 | } | ||
4276 | |||
4244 | /* | 4277 | /* |
4245 | * in active-backup mode, we know that bond->curr_active_slave is always valid if | 4278 | * in active-backup mode, we know that bond->curr_active_slave is always valid if |
4246 | * the bond has a usable interface. | 4279 | * the bond has a usable interface. |
@@ -4257,10 +4290,26 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d | |||
4257 | goto out; | 4290 | goto out; |
4258 | } | 4291 | } |
4259 | 4292 | ||
4260 | if (bond->curr_active_slave) { /* one usable interface */ | 4293 | if (!bond->curr_active_slave) |
4261 | res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev); | 4294 | goto out; |
4295 | |||
4296 | /* Xmit IGMP frames on all slaves to ensure rapid fail-over | ||
4297 | for multicast traffic on snooping switches */ | ||
4298 | if (skb->protocol == __constant_htons(ETH_P_IP) && | ||
4299 | skb->nh.iph->protocol == IPPROTO_IGMP) { | ||
4300 | struct slave *slave, *active_slave; | ||
4301 | int i; | ||
4302 | |||
4303 | active_slave = bond->curr_active_slave; | ||
4304 | bond_for_each_slave_from_to(bond, slave, i, active_slave->next, | ||
4305 | active_slave->prev) | ||
4306 | if (IS_UP(slave->dev) && | ||
4307 | (slave->link == BOND_LINK_UP)) | ||
4308 | bond_activebackup_xmit_copy(skb, bond, slave); | ||
4262 | } | 4309 | } |
4263 | 4310 | ||
4311 | res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev); | ||
4312 | |||
4264 | out: | 4313 | out: |
4265 | if (res) { | 4314 | if (res) { |
4266 | /* no suitable interface, frame not sent */ | 4315 | /* no suitable interface, frame not sent */ |