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