aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/bonding/bond_main.c9
-rw-r--r--include/linux/igmp.h2
-rw-r--r--include/linux/netdevice.h3
-rw-r--r--include/linux/notifier.h2
-rw-r--r--include/net/addrconf.h2
-rw-r--r--net/core/dev.c4
-rw-r--r--net/ipv4/devinet.c6
-rw-r--r--net/ipv4/igmp.c22
-rw-r--r--net/ipv6/addrconf.c19
-rw-r--r--net/ipv6/mcast.c19
10 files changed, 82 insertions, 6 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a7e731f8a0da..6419cf9a4fa6 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1211,7 +1211,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
1211 write_unlock_bh(&bond->curr_slave_lock); 1211 write_unlock_bh(&bond->curr_slave_lock);
1212 read_unlock(&bond->lock); 1212 read_unlock(&bond->lock);
1213 1213
1214 netdev_bonding_change(bond->dev); 1214 netdev_bonding_change(bond->dev, NETDEV_BONDING_FAILOVER);
1215 1215
1216 read_lock(&bond->lock); 1216 read_lock(&bond->lock);
1217 write_lock_bh(&bond->curr_slave_lock); 1217 write_lock_bh(&bond->curr_slave_lock);
@@ -1469,14 +1469,17 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
1469 */ 1469 */
1470 if (bond->slave_cnt == 0) { 1470 if (bond->slave_cnt == 0) {
1471 if (bond_dev->type != slave_dev->type) { 1471 if (bond_dev->type != slave_dev->type) {
1472 dev_close(bond_dev);
1473 pr_debug("%s: change device type from %d to %d\n", 1472 pr_debug("%s: change device type from %d to %d\n",
1474 bond_dev->name, bond_dev->type, slave_dev->type); 1473 bond_dev->name, bond_dev->type, slave_dev->type);
1474
1475 netdev_bonding_change(bond_dev, NETDEV_BONDING_OLDTYPE);
1476
1475 if (slave_dev->type != ARPHRD_ETHER) 1477 if (slave_dev->type != ARPHRD_ETHER)
1476 bond_setup_by_slave(bond_dev, slave_dev); 1478 bond_setup_by_slave(bond_dev, slave_dev);
1477 else 1479 else
1478 ether_setup(bond_dev); 1480 ether_setup(bond_dev);
1479 dev_open(bond_dev); 1481
1482 netdev_bonding_change(bond_dev, NETDEV_BONDING_NEWTYPE);
1480 } 1483 }
1481 } else if (bond_dev->type != slave_dev->type) { 1484 } else if (bond_dev->type != slave_dev->type) {
1482 pr_err(DRV_NAME ": %s ether type (%d) is different " 1485 pr_err(DRV_NAME ": %s ether type (%d) is different "
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 92fbd8cbd68f..fe158e0e20e6 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -233,6 +233,8 @@ extern void ip_mc_init_dev(struct in_device *);
233extern void ip_mc_destroy_dev(struct in_device *); 233extern void ip_mc_destroy_dev(struct in_device *);
234extern void ip_mc_up(struct in_device *); 234extern void ip_mc_up(struct in_device *);
235extern void ip_mc_down(struct in_device *); 235extern void ip_mc_down(struct in_device *);
236extern void ip_mc_unmap(struct in_device *);
237extern void ip_mc_remap(struct in_device *);
236extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr); 238extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr);
237extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr); 239extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr);
238extern void ip_mc_rejoin_group(struct ip_mc_list *im); 240extern void ip_mc_rejoin_group(struct ip_mc_list *im);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 65ee1929b2b1..f46db6c7a734 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1873,7 +1873,8 @@ extern void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, struct
1873extern int dev_set_promiscuity(struct net_device *dev, int inc); 1873extern int dev_set_promiscuity(struct net_device *dev, int inc);
1874extern int dev_set_allmulti(struct net_device *dev, int inc); 1874extern int dev_set_allmulti(struct net_device *dev, int inc);
1875extern void netdev_state_change(struct net_device *dev); 1875extern void netdev_state_change(struct net_device *dev);
1876extern void netdev_bonding_change(struct net_device *dev); 1876extern void netdev_bonding_change(struct net_device *dev,
1877 unsigned long event);
1877extern void netdev_features_change(struct net_device *dev); 1878extern void netdev_features_change(struct net_device *dev);
1878/* Load a device via the kmod */ 1879/* Load a device via the kmod */
1879extern void dev_load(struct net *net, const char *name); 1880extern void dev_load(struct net *net, const char *name);
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 81bc252dc8ac..44428d247dbe 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -199,6 +199,8 @@ static inline int notifier_to_errno(int ret)
199#define NETDEV_FEAT_CHANGE 0x000B 199#define NETDEV_FEAT_CHANGE 0x000B
200#define NETDEV_BONDING_FAILOVER 0x000C 200#define NETDEV_BONDING_FAILOVER 0x000C
201#define NETDEV_PRE_UP 0x000D 201#define NETDEV_PRE_UP 0x000D
202#define NETDEV_BONDING_OLDTYPE 0x000E
203#define NETDEV_BONDING_NEWTYPE 0x000F
202 204
203#define SYS_DOWN 0x0001 /* Notify of system down */ 205#define SYS_DOWN 0x0001 /* Notify of system down */
204#define SYS_RESTART SYS_DOWN 206#define SYS_RESTART SYS_DOWN
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 7b55ab215a64..0f7c37825fc1 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -143,6 +143,8 @@ extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr
143extern int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr); 143extern int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr);
144extern void ipv6_mc_up(struct inet6_dev *idev); 144extern void ipv6_mc_up(struct inet6_dev *idev);
145extern void ipv6_mc_down(struct inet6_dev *idev); 145extern void ipv6_mc_down(struct inet6_dev *idev);
146extern void ipv6_mc_unmap(struct inet6_dev *idev);
147extern void ipv6_mc_remap(struct inet6_dev *idev);
146extern void ipv6_mc_init_dev(struct inet6_dev *idev); 148extern void ipv6_mc_init_dev(struct inet6_dev *idev);
147extern void ipv6_mc_destroy_dev(struct inet6_dev *idev); 149extern void ipv6_mc_destroy_dev(struct inet6_dev *idev);
148extern void addrconf_dad_failure(struct inet6_ifaddr *ifp); 150extern void addrconf_dad_failure(struct inet6_ifaddr *ifp);
diff --git a/net/core/dev.c b/net/core/dev.c
index 84945470ab38..560c8c9c03ab 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1017,9 +1017,9 @@ void netdev_state_change(struct net_device *dev)
1017} 1017}
1018EXPORT_SYMBOL(netdev_state_change); 1018EXPORT_SYMBOL(netdev_state_change);
1019 1019
1020void netdev_bonding_change(struct net_device *dev) 1020void netdev_bonding_change(struct net_device *dev, unsigned long event)
1021{ 1021{
1022 call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, dev); 1022 call_netdevice_notifiers(event, dev);
1023} 1023}
1024EXPORT_SYMBOL(netdev_bonding_change); 1024EXPORT_SYMBOL(netdev_bonding_change);
1025 1025
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 3863c3a4223f..07336c6201f0 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1087,6 +1087,12 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
1087 case NETDEV_DOWN: 1087 case NETDEV_DOWN:
1088 ip_mc_down(in_dev); 1088 ip_mc_down(in_dev);
1089 break; 1089 break;
1090 case NETDEV_BONDING_OLDTYPE:
1091 ip_mc_unmap(in_dev);
1092 break;
1093 case NETDEV_BONDING_NEWTYPE:
1094 ip_mc_remap(in_dev);
1095 break;
1090 case NETDEV_CHANGEMTU: 1096 case NETDEV_CHANGEMTU:
1091 if (inetdev_valid_mtu(dev->mtu)) 1097 if (inetdev_valid_mtu(dev->mtu))
1092 break; 1098 break;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 01b4284ed694..d41e5de79a82 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1298,6 +1298,28 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
1298 } 1298 }
1299} 1299}
1300 1300
1301/* Device changing type */
1302
1303void ip_mc_unmap(struct in_device *in_dev)
1304{
1305 struct ip_mc_list *i;
1306
1307 ASSERT_RTNL();
1308
1309 for (i = in_dev->mc_list; i; i = i->next)
1310 igmp_group_dropped(i);
1311}
1312
1313void ip_mc_remap(struct in_device *in_dev)
1314{
1315 struct ip_mc_list *i;
1316
1317 ASSERT_RTNL();
1318
1319 for (i = in_dev->mc_list; i; i = i->next)
1320 igmp_group_added(i);
1321}
1322
1301/* Device going down */ 1323/* Device going down */
1302 1324
1303void ip_mc_down(struct in_device *in_dev) 1325void ip_mc_down(struct in_device *in_dev)
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;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 71c3dacec1ed..f9fcf690bd5d 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2249,6 +2249,25 @@ static void igmp6_timer_handler(unsigned long data)
2249 ma_put(ma); 2249 ma_put(ma);
2250} 2250}
2251 2251
2252/* Device changing type */
2253
2254void ipv6_mc_unmap(struct inet6_dev *idev)
2255{
2256 struct ifmcaddr6 *i;
2257
2258 /* Install multicast list, except for all-nodes (already installed) */
2259
2260 read_lock_bh(&idev->lock);
2261 for (i = idev->mc_list; i; i = i->next)
2262 igmp6_group_dropped(i);
2263 read_unlock_bh(&idev->lock);
2264}
2265
2266void ipv6_mc_remap(struct inet6_dev *idev)
2267{
2268 ipv6_mc_up(idev);
2269}
2270
2252/* Device going down */ 2271/* Device going down */
2253 2272
2254void ipv6_mc_down(struct inet6_dev *idev) 2273void ipv6_mc_down(struct inet6_dev *idev)