mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-18 22:14:16 +00:00 
			
		
		
		
	ipv6: Use POSTDAD state
This patch makes use of the new POSTDAD state. This prevents a race between DAD completion and failure. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									4c5ff6a6fe
								
							
						
					
					
						commit
						f2344a131b
					
				
					 1 changed files with 24 additions and 5 deletions
				
			
		|  | @ -1406,10 +1406,27 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
| 		ipv6_del_addr(ifp); | ||||
| } | ||||
| 
 | ||||
| static int addrconf_dad_end(struct inet6_ifaddr *ifp) | ||||
| { | ||||
| 	int err = -ENOENT; | ||||
| 
 | ||||
| 	spin_lock(&ifp->state_lock); | ||||
| 	if (ifp->state == INET6_IFADDR_STATE_DAD) { | ||||
| 		ifp->state = INET6_IFADDR_STATE_POSTDAD; | ||||
| 		err = 0; | ||||
| 	} | ||||
| 	spin_unlock(&ifp->state_lock); | ||||
| 
 | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| void addrconf_dad_failure(struct inet6_ifaddr *ifp) | ||||
| { | ||||
| 	struct inet6_dev *idev = ifp->idev; | ||||
| 
 | ||||
| 	if (addrconf_dad_end(ifp)) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (net_ratelimit()) | ||||
| 		printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", | ||||
| 			ifp->idev->dev->name, &ifp->addr); | ||||
|  | @ -2712,6 +2729,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 
 | ||||
| 			/* Flag it for later restoration when link comes up */ | ||||
| 			ifa->flags |= IFA_F_TENTATIVE; | ||||
| 			ifa->state = INET6_IFADDR_STATE_DAD; | ||||
| 
 | ||||
| 			write_unlock_bh(&idev->lock); | ||||
| 
 | ||||
|  | @ -2883,6 +2901,9 @@ static void addrconf_dad_timer(unsigned long data) | |||
| 	struct inet6_dev *idev = ifp->idev; | ||||
| 	struct in6_addr mcaddr; | ||||
| 
 | ||||
| 	if (!ifp->probes && addrconf_dad_end(ifp)) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	read_lock(&idev->lock); | ||||
| 	if (idev->dead || !(idev->if_flags & IF_READY)) { | ||||
| 		read_unlock(&idev->lock); | ||||
|  | @ -2956,12 +2977,10 @@ static void addrconf_dad_run(struct inet6_dev *idev) | |||
| 	read_lock_bh(&idev->lock); | ||||
| 	list_for_each_entry(ifp, &idev->addr_list, if_list) { | ||||
| 		spin_lock(&ifp->lock); | ||||
| 		if (!(ifp->flags & IFA_F_TENTATIVE)) { | ||||
| 			spin_unlock(&ifp->lock); | ||||
| 			continue; | ||||
| 		} | ||||
| 		spin_unlock(&ifp->lock); | ||||
| 		if (ifp->flags & IFA_F_TENTATIVE && | ||||
| 		    ifp->state == INET6_IFADDR_STATE_DAD) | ||||
| 			addrconf_dad_kick(ifp); | ||||
| 		spin_unlock(&ifp->lock); | ||||
| 	} | ||||
| 	read_unlock_bh(&idev->lock); | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Herbert Xu
						Herbert Xu