aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/addrconf.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d012f6ac7040..f6ead6a843e3 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -137,6 +137,7 @@ static int addrconf_ifdown(struct net_device *dev, int how);
137static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); 137static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags);
138static void addrconf_dad_timer(unsigned long data); 138static void addrconf_dad_timer(unsigned long data);
139static void addrconf_dad_completed(struct inet6_ifaddr *ifp); 139static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
140static void addrconf_dad_run(struct inet6_dev *idev);
140static void addrconf_rs_timer(unsigned long data); 141static void addrconf_rs_timer(unsigned long data);
141static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); 142static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
142static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); 143static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
@@ -418,6 +419,7 @@ static struct inet6_dev * ipv6_find_idev(struct net_device *dev)
418 if ((idev = ipv6_add_dev(dev)) == NULL) 419 if ((idev = ipv6_add_dev(dev)) == NULL)
419 return NULL; 420 return NULL;
420 } 421 }
422
421 if (dev->flags&IFF_UP) 423 if (dev->flags&IFF_UP)
422 ipv6_mc_up(idev); 424 ipv6_mc_up(idev);
423 return idev; 425 return idev;
@@ -2140,6 +2142,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
2140{ 2142{
2141 struct net_device *dev = (struct net_device *) data; 2143 struct net_device *dev = (struct net_device *) data;
2142 struct inet6_dev *idev = __in6_dev_get(dev); 2144 struct inet6_dev *idev = __in6_dev_get(dev);
2145 int run_pending = 0;
2143 2146
2144 switch(event) { 2147 switch(event) {
2145 case NETDEV_UP: 2148 case NETDEV_UP:
@@ -2172,6 +2175,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
2172 "link becomes ready\n", 2175 "link becomes ready\n",
2173 dev->name); 2176 dev->name);
2174 2177
2178 run_pending = 1;
2175 } 2179 }
2176 2180
2177 switch(dev->type) { 2181 switch(dev->type) {
@@ -2190,6 +2194,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
2190 break; 2194 break;
2191 }; 2195 };
2192 if (idev) { 2196 if (idev) {
2197 if (run_pending)
2198 addrconf_dad_run(idev);
2199
2193 /* If the MTU changed during the interface down, when the 2200 /* If the MTU changed during the interface down, when the
2194 interface up, the changed MTU must be reflected in the 2201 interface up, the changed MTU must be reflected in the
2195 idev as well as routers. 2202 idev as well as routers.
@@ -2546,6 +2553,22 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
2546 } 2553 }
2547} 2554}
2548 2555
2556static void addrconf_dad_run(struct inet6_dev *idev) {
2557 struct inet6_ifaddr *ifp;
2558
2559 read_lock_bh(&idev->lock);
2560 for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) {
2561 spin_lock_bh(&ifp->lock);
2562 if (!(ifp->flags & IFA_F_TENTATIVE)) {
2563 spin_unlock_bh(&ifp->lock);
2564 continue;
2565 }
2566 spin_unlock_bh(&ifp->lock);
2567 addrconf_dad_kick(ifp);
2568 }
2569 read_unlock_bh(&idev->lock);
2570}
2571
2549#ifdef CONFIG_PROC_FS 2572#ifdef CONFIG_PROC_FS
2550struct if6_iter_state { 2573struct if6_iter_state {
2551 int bucket; 2574 int bucket;