diff options
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index f264ff162979..8032126fd589 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -4241,6 +4241,43 @@ 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 | * -- use slave's perm MAC addr, unless used by bond | ||
4264 | * -- otherwise, borrow active slave's perm MAC addr | ||
4265 | * since that will not be used | ||
4266 | */ | ||
4267 | hwaddr = slave->perm_hwaddr; | ||
4268 | if (!memcmp(eth_data->h_source, hwaddr, ETH_ALEN)) | ||
4269 | hwaddr = bond->curr_active_slave->perm_hwaddr; | ||
4270 | |||
4271 | /* Set source MAC address appropriately */ | ||
4272 | memcpy(eth_data->h_source, hwaddr, ETH_ALEN); | ||
4273 | |||
4274 | res = bond_dev_queue_xmit(bond, skb2, slave->dev); | ||
4275 | if (res) | ||
4276 | dev_kfree_skb(skb2); | ||
4277 | |||
4278 | return; | ||
4279 | } | ||
4280 | |||
4244 | /* | 4281 | /* |
4245 | * in active-backup mode, we know that bond->curr_active_slave is always valid if | 4282 | * in active-backup mode, we know that bond->curr_active_slave is always valid if |
4246 | * the bond has a usable interface. | 4283 | * the bond has a usable interface. |
@@ -4257,10 +4294,26 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d | |||
4257 | goto out; | 4294 | goto out; |
4258 | } | 4295 | } |
4259 | 4296 | ||
4260 | if (bond->curr_active_slave) { /* one usable interface */ | 4297 | if (!bond->curr_active_slave) |
4261 | res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev); | 4298 | goto out; |
4299 | |||
4300 | /* Xmit IGMP frames on all slaves to ensure rapid fail-over | ||
4301 | for multicast traffic on snooping switches */ | ||
4302 | if (skb->protocol == __constant_htons(ETH_P_IP) && | ||
4303 | skb->nh.iph->protocol == IPPROTO_IGMP) { | ||
4304 | struct slave *slave, *active_slave; | ||
4305 | int i; | ||
4306 | |||
4307 | active_slave = bond->curr_active_slave; | ||
4308 | bond_for_each_slave_from_to(bond, slave, i, active_slave->next, | ||
4309 | active_slave->prev) | ||
4310 | if (IS_UP(slave->dev) && | ||
4311 | (slave->link == BOND_LINK_UP)) | ||
4312 | bond_activebackup_xmit_copy(skb, bond, slave); | ||
4262 | } | 4313 | } |
4263 | 4314 | ||
4315 | res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev); | ||
4316 | |||
4264 | out: | 4317 | out: |
4265 | if (res) { | 4318 | if (res) { |
4266 | /* no suitable interface, frame not sent */ | 4319 | /* no suitable interface, frame not sent */ |