[Acked] [PATCH Precise SRU] UBUNTU: SAUCE: net/ipv6: don't take interface down when enabling/disabling use_tempaddr

Andy Whitcroft apw at canonical.com
Fri Jun 20 14:45:06 UTC 2014


On Fri, Jun 20, 2014 at 07:32:27AM -0600, Tim Gardner wrote:
> From: Malcolm Scott <debianpkg at malc.org.uk>
> 
> BugLink: http://bugs.launchpad.net/bugs/994931
> 
> Altering use_tempaddr drops all IPv6 addresses.
> 
> Signed-off-by: Malcolm Scott <debianpkg at malc.org.uk>
> Signed-off-by: Tim Gardner <tim.gardner at canonical.com>
> ---
>  net/ipv6/addrconf.c | 57 ++++++++++++++++++++++++++++++++++++++++-------------
>  1 file changed, 43 insertions(+), 14 deletions(-)
> 
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index 246a170..6e576c6 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -125,7 +125,8 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev)
>  #ifdef CONFIG_IPV6_PRIVACY
>  static int __ipv6_regen_rndid(struct inet6_dev *idev);
>  static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
> -static void ipv6_regen_rndid(unsigned long data);
> +static void ipv6_regen_rndid(struct inet6_dev *idev);
> +static void ipv6_regen_rndid_tick(unsigned long data);
>  #endif
>  
>  static int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
> @@ -409,7 +410,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
>  
>  #ifdef CONFIG_IPV6_PRIVACY
>  	INIT_LIST_HEAD(&ndev->tempaddr_list);
> -	setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev);
> +	setup_timer(&ndev->regen_timer, ipv6_regen_rndid_tick, (unsigned long)ndev);
>  	if ((dev->flags&IFF_LOOPBACK) ||
>  	    dev->type == ARPHRD_TUNNEL ||
>  	    dev->type == ARPHRD_TUNNEL6 ||
> @@ -417,8 +418,9 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
>  	    dev->type == ARPHRD_NONE) {
>  		ndev->cnf.use_tempaddr = -1;
>  	} else {
> -		in6_dev_hold(ndev);
> -		ipv6_regen_rndid((unsigned long) ndev);
> +		rcu_read_lock_bh();
> +		ipv6_regen_rndid(ndev);
> +		rcu_read_unlock_bh();
>  	}
>  #endif
>  
> @@ -1649,12 +1651,21 @@ regen:
>  	return 0;
>  }
>  
> -static void ipv6_regen_rndid(unsigned long data)
> +static void ipv6_regen_rndid_tick(unsigned long data)
>  {
>  	struct inet6_dev *idev = (struct inet6_dev *) data;
> -	unsigned long expires;
>  
>  	rcu_read_lock_bh();
> +	ipv6_regen_rndid(idev);
> +	rcu_read_unlock_bh();
> +	in6_dev_put(idev);
> +}
> +
> +/* called with rcu_read_lock_bh() */
> +static void ipv6_regen_rndid(struct inet6_dev *idev)
> +{
> +	unsigned long expires;
> +
>  	write_lock_bh(&idev->lock);
>  
>  	if (idev->dead)
> @@ -1679,8 +1690,6 @@ static void ipv6_regen_rndid(unsigned long data)
>  
>  out:
>  	write_unlock_bh(&idev->lock);
> -	rcu_read_unlock_bh();
> -	in6_dev_put(idev);
>  }
>  
>  static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr) {
> @@ -4390,12 +4399,32 @@ static void dev_tempaddr_change(struct inet6_dev *idev)
>  	if (!idev || !idev->dev)
>  		return;
>  
> -	if (!idev->cnf.disable_ipv6) {
> -		/* If ipv6 is enabled, try to bring down and back up the
> -		 * interface to get new temporary addresses created
> -		 */
> -		addrconf_notify(NULL, NETDEV_DOWN, idev->dev);
> -		addrconf_notify(NULL, NETDEV_UP, idev->dev);
> +	/* Add/remove temporary addresses if necessary */
> +	if (!idev->cnf.disable_ipv6 && idev->cnf.autoconf) {
> +		if (idev->cnf.use_tempaddr > 0) {
> +			struct inet6_ifaddr *ifp, *ifn;
> +
> +			/*
> +			 * Create a temporary address for every non-temporary,
> +			 * non-permanent (i.e. autoconfigured) address
> +			 */
> +
> +			ipv6_regen_rndid(idev);
> +
> +			list_for_each_entry_safe(ifp, ifn, &idev->addr_list, if_list) {
> +				if (!(ifp->flags & (IFA_F_TEMPORARY | IFA_F_PERMANENT))) {
> +					ipv6_create_tempaddr(ifp, NULL);
> +				}
> +			}
> +		} else {
> +			struct inet6_ifaddr *ifa;
> +
> +			while (!list_empty(&idev->tempaddr_list)) {
> +				ifa = list_first_entry(&idev->tempaddr_list,
> +						       struct inet6_ifaddr, tmp_list);
> +				ipv6_del_addr(ifa);
> +			}
> +		}
>  	}
>  }

That does appear to do what is claimed.  The spagetti seems rather
different in 3.16 so I cannot trivally tell if the same issue appears
there?  I think they are just left to expire and are not recreated
rather than activly managed, but it would be good to have confirmation.

This ought to be easily testable, with such testing.

Acked-by: Andy Whitcroft <apw at canonical.com>

-apw




More information about the kernel-team mailing list