Commit b2751e50 authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji Committed by David S. Miller

net/ipv6/addrconf.c: Refine IPv6 Address Validation Timer.

parent ad15305d
......@@ -26,6 +26,8 @@
* packets.
* yoshfuji@USAGI : Fixed interval between DAD
* packets.
* YOSHIFUJI Hideaki @USAGI : improved accuracy of
* address validation timer.
*/
#include <linux/config.h>
......@@ -93,6 +95,7 @@ rwlock_t addrconf_lock = RW_LOCK_UNLOCKED;
static void addrconf_verify(unsigned long);
static struct timer_list addr_chk_timer = { function: addrconf_verify };
static spinlock_t addrconf_verify_lock = SPIN_LOCK_UNLOCKED;
static int addrconf_ifdown(struct net_device *dev, int how);
......@@ -1616,9 +1619,15 @@ static int iface_proc_info(char *buffer, char **start, off_t offset,
static void addrconf_verify(unsigned long foo)
{
struct inet6_ifaddr *ifp;
unsigned long now = jiffies;
unsigned long now, next;
int i;
spin_lock_bh(&addrconf_verify_lock);
now = jiffies;
next = now + ADDR_CHECK_FREQUENCY;
del_timer(&addr_chk_timer);
for (i=0; i < IN6_ADDR_HSIZE; i++) {
restart:
......@@ -1629,21 +1638,27 @@ static void addrconf_verify(unsigned long foo)
if (ifp->flags & IFA_F_PERMANENT)
continue;
spin_lock(&ifp->lock);
age = (now - ifp->tstamp) / HZ;
if (age > ifp->valid_lft) {
if (age >= ifp->valid_lft) {
spin_unlock(&ifp->lock);
in6_ifa_hold(ifp);
write_unlock(&addrconf_hash_lock);
ipv6_del_addr(ifp);
goto restart;
} else if (age > ifp->prefered_lft) {
} else if (age >= ifp->prefered_lft) {
/* jiffies - ifp->tsamp > age >= ifp->prefered_lft */
int deprecate = 0;
spin_lock(&ifp->lock);
if (!(ifp->flags&IFA_F_DEPRECATED)) {
deprecate = 1;
ifp->flags |= IFA_F_DEPRECATED;
}
if (time_before(ifp->tstamp + ifp->valid_lft * HZ, next))
next = ifp->tstamp + ifp->valid_lft * HZ;
spin_unlock(&ifp->lock);
if (deprecate) {
......@@ -1654,12 +1669,19 @@ static void addrconf_verify(unsigned long foo)
in6_ifa_put(ifp);
goto restart;
}
} else {
/* ifp->prefered_lft <= ifp->valid_lft */
if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next))
next = ifp->tstamp + ifp->prefered_lft * HZ;
spin_unlock(&ifp->lock);
}
}
write_unlock(&addrconf_hash_lock);
}
mod_timer(&addr_chk_timer, jiffies + ADDR_CHECK_FREQUENCY);
addr_chk_timer.expires = time_before(next, jiffies + HZ) ? jiffies + HZ : next;
add_timer(&addr_chk_timer);
spin_unlock_bh(&addrconf_verify_lock);
}
static int
......@@ -2033,8 +2055,7 @@ void __init addrconf_init(void)
proc_net_create("if_inet6", 0, iface_proc_info);
#endif
addr_chk_timer.expires = jiffies + ADDR_CHECK_FREQUENCY;
add_timer(&addr_chk_timer);
addrconf_verify(0);
rtnetlink_links[PF_INET6] = inet6_rtnetlink_table;
#ifdef CONFIG_SYSCTL
addrconf_sysctl.sysctl_header =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment