===================================================================
@@ -147,6 +147,7 @@ static void addrconf_leave_anycast(struc
static void addrconf_type_change(struct net_device *dev,
unsigned long event);
static int addrconf_ifdown(struct net_device *dev, int how);
+static void dev_disable_change(struct inet6_dev *idev);
static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags);
static void addrconf_dad_timer(unsigned long data);
@@ -2221,7 +2222,7 @@ static int inet6_addr_del(struct net *ne
disable IPv6 on this interface.
*/
if (list_empty(&idev->addr_list))
- addrconf_ifdown(idev->dev, 1);
+ dev_disable_change(idev);
return 0;
}
}
@@ -2499,7 +2500,7 @@ static int addrconf_notify(struct notifi
switch (event) {
case NETDEV_REGISTER:
- if (!idev && dev->mtu >= IPV6_MIN_MTU) {
+ if (!idev) {
idev = ipv6_add_dev(dev);
if (!idev)
return notifier_from_errno(-ENOMEM);
@@ -2520,26 +2521,18 @@ static int addrconf_notify(struct notifi
dev->name);
break;
}
-
- if (!idev && dev->mtu >= IPV6_MIN_MTU)
- idev = ipv6_add_dev(dev);
-
- if (idev) {
- idev->if_flags |= IF_READY;
- run_pending = 1;
- }
+ idev->if_flags |= IF_READY;
+ run_pending = 1;
} else {
if (!addrconf_qdisc_ok(dev)) {
/* device is still not ready. */
break;
}
- if (idev) {
- if (idev->if_flags & IF_READY)
- /* device is already configured. */
- break;
- idev->if_flags |= IF_READY;
- }
+ if (idev->if_flags & IF_READY)
+ /* device is already configured. */
+ break;
+ idev->if_flags |= IF_READY;
printk(KERN_INFO
"ADDRCONF(NETDEV_CHANGE): %s: "
@@ -2567,45 +2560,37 @@ static int addrconf_notify(struct notifi
break;
}
- if (idev) {
- if (run_pending)
- addrconf_dad_run(idev);
-
- /*
- * If the MTU changed during the interface down,
- * when the interface up, the changed MTU must be
- * reflected in the idev as well as routers.
- */
- if (idev->cnf.mtu6 != dev->mtu &&
- dev->mtu >= IPV6_MIN_MTU) {
- rt6_mtu_change(dev, dev->mtu);
- idev->cnf.mtu6 = dev->mtu;
- }
- idev->tstamp = jiffies;
- inet6_ifinfo_notify(RTM_NEWLINK, idev);
+ if (run_pending)
+ addrconf_dad_run(idev);
- /*
- * If the changed mtu during down is lower than
- * IPV6_MIN_MTU stop IPv6 on this interface.
- */
- if (dev->mtu < IPV6_MIN_MTU)
- addrconf_ifdown(dev, 1);
+ /*
+ * If the MTU changed during the interface down,
+ * when the interface up, the changed MTU must be
+ * reflected in the idev as well as routers.
+ */
+ if (idev->cnf.mtu6 != dev->mtu &&
+ dev->mtu >= IPV6_MIN_MTU) {
+ rt6_mtu_change(dev, dev->mtu);
+ idev->cnf.mtu6 = dev->mtu;
}
+ idev->tstamp = jiffies;
+ inet6_ifinfo_notify(RTM_NEWLINK, idev);
+
+ /*
+ * If the changed mtu during down is lower than
+ * IPV6_MIN_MTU stop IPv6 on this interface.
+ */
+ if (dev->mtu < IPV6_MIN_MTU)
+ dev_disable_change(idev);
break;
case NETDEV_CHANGEMTU:
- if (idev && dev->mtu >= IPV6_MIN_MTU) {
+ if (dev->mtu >= IPV6_MIN_MTU) {
rt6_mtu_change(dev, dev->mtu);
idev->cnf.mtu6 = dev->mtu;
break;
}
- if (!idev && dev->mtu >= IPV6_MIN_MTU) {
- idev = ipv6_add_dev(dev);
- if (idev)
- break;
- }
-
/*
* MTU falled under IPV6_MIN_MTU.
* Stop IPv6 on this interface.
@@ -2616,7 +2601,7 @@ static int addrconf_notify(struct notifi
/*
* Remove all addresses from this interface.
*/
- addrconf_ifdown(dev, event != NETDEV_DOWN);
+ addrconf_ifdown(dev, event == NETDEV_UNREGISTER);
break;
case NETDEV_CHANGENAME:
@@ -4137,6 +4122,18 @@ static void ipv6_ifa_notify(int event, s
rcu_read_unlock_bh();
}
+static void dev_disable_change(struct inet6_dev *idev)
+{
+ if (!idev || !idev->dev)
+ return;
+
+ if (idev->cnf.disable_ipv6 || (list_empty(&idev->addr_list)) ||
+ (idev->dev->mtu < IPV6_MIN_MTU))
+ addrconf_notify(NULL, NETDEV_DOWN, idev->dev);
+ else
+ addrconf_notify(NULL, NETDEV_UP, idev->dev);
+}
+
#ifdef CONFIG_SYSCTL
static
@@ -4157,17 +4154,6 @@ int addrconf_sysctl_forward(ctl_table *c
return ret;
}
-static void dev_disable_change(struct inet6_dev *idev)
-{
- if (!idev || !idev->dev)
- return;
-
- if (idev->cnf.disable_ipv6)
- addrconf_notify(NULL, NETDEV_DOWN, idev->dev);
- else
- addrconf_notify(NULL, NETDEV_UP, idev->dev);
-}
-
static void addrconf_disable_change(struct net *net, __s32 newf)
{
struct net_device *dev;