IPv6: Drop the temporary address regen_timer
authorJiri Bohac <jbohac@suse.cz>
Thu, 13 Oct 2016 16:50:02 +0000 (18:50 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 14 Oct 2016 14:59:15 +0000 (10:59 -0400)
The randomized interface identifier (rndid) was periodically updated from
the regen_timer timer. Simplify the code by updating the rndid only when
needed by ipv6_try_regen_rndid().

This makes the follow-up DESYNC_FACTOR fix much simpler.  Also it fixes a
reference counting error in this error path, where an in6_dev_put was
missing:
err = addrconf_sysctl_register(ndev);
if (err) {
ipv6_mc_destroy_dev(ndev);
-               del_timer(&ndev->regen_timer);
snmp6_unregister_dev(ndev);
goto err_release;

Signed-off-by: Jiri Bohac <jbohac@suse.cz>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/if_inet6.h
net/ipv6/addrconf.c

index 515352c..ae70735 100644 (file)
@@ -191,7 +191,6 @@ struct inet6_dev {
        int                     dead;
 
        u8                      rndid[8];
-       struct timer_list       regen_timer;
        struct list_head        tempaddr_list;
 
        struct in6_addr         token;
index 9faafe5..58c3d73 100644 (file)
@@ -147,9 +147,8 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev)
 }
 #endif
 
-static void __ipv6_regen_rndid(struct inet6_dev *idev);
-static void __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_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
 
 static int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
 static int ipv6_count_addresses(struct inet6_dev *idev);
@@ -409,9 +408,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
                goto err_release;
        }
 
-       /* One reference from device.  We must do this before
-        * we invoke __ipv6_regen_rndid().
-        */
+       /* One reference from device. */
        in6_dev_hold(ndev);
 
        if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
@@ -425,17 +422,14 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
 #endif
 
        INIT_LIST_HEAD(&ndev->tempaddr_list);
-       setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev);
        if ((dev->flags&IFF_LOOPBACK) ||
            dev->type == ARPHRD_TUNNEL ||
            dev->type == ARPHRD_TUNNEL6 ||
            dev->type == ARPHRD_SIT ||
            dev->type == ARPHRD_NONE) {
                ndev->cnf.use_tempaddr = -1;
-       } else {
-               in6_dev_hold(ndev);
-               ipv6_regen_rndid((unsigned long) ndev);
-       }
+       } else
+               ipv6_regen_rndid(ndev);
 
        ndev->token = in6addr_any;
 
@@ -447,7 +441,6 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
        err = addrconf_sysctl_register(ndev);
        if (err) {
                ipv6_mc_destroy_dev(ndev);
-               del_timer(&ndev->regen_timer);
                snmp6_unregister_dev(ndev);
                goto err_release;
        }
@@ -1222,7 +1215,7 @@ retry:
        }
        in6_ifa_hold(ifp);
        memcpy(addr.s6_addr, ifp->addr.s6_addr, 8);
-       __ipv6_try_regen_rndid(idev, tmpaddr);
+       ipv6_try_regen_rndid(idev, tmpaddr);
        memcpy(&addr.s6_addr[8], idev->rndid, 8);
        age = (now - ifp->tstamp) / HZ;
        tmp_valid_lft = min_t(__u32,
@@ -2150,7 +2143,7 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
 }
 
 /* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */
-static void __ipv6_regen_rndid(struct inet6_dev *idev)
+static void ipv6_regen_rndid(struct inet6_dev *idev)
 {
 regen:
        get_random_bytes(idev->rndid, sizeof(idev->rndid));
@@ -2179,43 +2172,10 @@ regen:
        }
 }
 
-static void ipv6_regen_rndid(unsigned long data)
-{
-       struct inet6_dev *idev = (struct inet6_dev *) data;
-       unsigned long expires;
-
-       rcu_read_lock_bh();
-       write_lock_bh(&idev->lock);
-
-       if (idev->dead)
-               goto out;
-
-       __ipv6_regen_rndid(idev);
-
-       expires = jiffies +
-               idev->cnf.temp_prefered_lft * HZ -
-               idev->cnf.regen_max_retry * idev->cnf.dad_transmits *
-               NEIGH_VAR(idev->nd_parms, RETRANS_TIME) -
-               idev->cnf.max_desync_factor * HZ;
-       if (time_before(expires, jiffies)) {
-               pr_warn("%s: too short regeneration interval; timer disabled for %s\n",
-                       __func__, idev->dev->name);
-               goto out;
-       }
-
-       if (!mod_timer(&idev->regen_timer, expires))
-               in6_dev_hold(idev);
-
-out:
-       write_unlock_bh(&idev->lock);
-       rcu_read_unlock_bh();
-       in6_dev_put(idev);
-}
-
-static void  __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr)
+static void  ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr)
 {
        if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0)
-               __ipv6_regen_rndid(idev);
+               ipv6_regen_rndid(idev);
 }
 
 /*
@@ -3594,9 +3554,6 @@ restart:
        if (!how)
                idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY);
 
-       if (how && del_timer(&idev->regen_timer))
-               in6_dev_put(idev);
-
        /* Step 3: clear tempaddr list */
        while (!list_empty(&idev->tempaddr_list)) {
                ifa = list_first_entry(&idev->tempaddr_list,