aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
authorMoni Shoua <monis@voltaire.com>2009-09-15 05:37:40 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-15 05:37:40 -0400
commit75c78500ddad74b229cd0691496b8549490496a2 (patch)
tree5249219d68627421e4717c4e8f03f8b4bbad2e92 /net/ipv6/addrconf.c
parent481a8199142c050b72bff8a1956a49fd0a75bbe0 (diff)
bonding: remap muticast addresses without using dev_close() and dev_open()
This patch fixes commit e36b9d16c6a6d0f59803b3ef04ff3c22c3844c10. The approach there is to call dev_close()/dev_open() whenever the device type is changed in order to remap the device IP multicast addresses to HW multicast addresses. This approach suffers from 2 drawbacks: *. It assumes tha the device is UP when calling dev_close(), or otherwise dev_close() has no affect. It is worth to mention that initscripts (Redhat) and sysconfig (Suse) doesn't act the same in this matter. *. dev_close() has other side affects, like deleting entries from the routing table, which might be unnecessary. The fix here is to directly remap the IP multicast addresses to HW multicast addresses for a bonding device that changes its type, and nothing else. Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Moni Shoua <monis@voltaire.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index c9b369034a40..f216a41ceb22 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -137,6 +137,8 @@ static DEFINE_SPINLOCK(addrconf_verify_lock);
137static void addrconf_join_anycast(struct inet6_ifaddr *ifp); 137static void addrconf_join_anycast(struct inet6_ifaddr *ifp);
138static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); 138static void addrconf_leave_anycast(struct inet6_ifaddr *ifp);
139 139
140static void addrconf_bonding_change(struct net_device *dev,
141 unsigned long event);
140static int addrconf_ifdown(struct net_device *dev, int how); 142static int addrconf_ifdown(struct net_device *dev, int how);
141 143
142static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); 144static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags);
@@ -2582,6 +2584,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
2582 return notifier_from_errno(err); 2584 return notifier_from_errno(err);
2583 } 2585 }
2584 break; 2586 break;
2587 case NETDEV_BONDING_OLDTYPE:
2588 case NETDEV_BONDING_NEWTYPE:
2589 addrconf_bonding_change(dev, event);
2590 break;
2585 } 2591 }
2586 2592
2587 return NOTIFY_OK; 2593 return NOTIFY_OK;
@@ -2595,6 +2601,19 @@ static struct notifier_block ipv6_dev_notf = {
2595 .priority = 0 2601 .priority = 0
2596}; 2602};
2597 2603
2604static void addrconf_bonding_change(struct net_device *dev, unsigned long event)
2605{
2606 struct inet6_dev *idev;
2607 ASSERT_RTNL();
2608
2609 idev = __in6_dev_get(dev);
2610
2611 if (event == NETDEV_BONDING_NEWTYPE)
2612 ipv6_mc_remap(idev);
2613 else if (event == NETDEV_BONDING_OLDTYPE)
2614 ipv6_mc_unmap(idev);
2615}
2616
2598static int addrconf_ifdown(struct net_device *dev, int how) 2617static int addrconf_ifdown(struct net_device *dev, int how)
2599{ 2618{
2600 struct inet6_dev *idev; 2619 struct inet6_dev *idev;