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 @@ ...@@ -26,6 +26,8 @@
* packets. * packets.
* yoshfuji@USAGI : Fixed interval between DAD * yoshfuji@USAGI : Fixed interval between DAD
* packets. * packets.
* YOSHIFUJI Hideaki @USAGI : improved accuracy of
* address validation timer.
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -93,6 +95,7 @@ rwlock_t addrconf_lock = RW_LOCK_UNLOCKED; ...@@ -93,6 +95,7 @@ rwlock_t addrconf_lock = RW_LOCK_UNLOCKED;
static void addrconf_verify(unsigned long); static void addrconf_verify(unsigned long);
static struct timer_list addr_chk_timer = { function: addrconf_verify }; 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); 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, ...@@ -1616,9 +1619,15 @@ static int iface_proc_info(char *buffer, char **start, off_t offset,
static void addrconf_verify(unsigned long foo) static void addrconf_verify(unsigned long foo)
{ {
struct inet6_ifaddr *ifp; struct inet6_ifaddr *ifp;
unsigned long now = jiffies; unsigned long now, next;
int i; 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++) { for (i=0; i < IN6_ADDR_HSIZE; i++) {
restart: restart:
...@@ -1629,21 +1638,27 @@ static void addrconf_verify(unsigned long foo) ...@@ -1629,21 +1638,27 @@ static void addrconf_verify(unsigned long foo)
if (ifp->flags & IFA_F_PERMANENT) if (ifp->flags & IFA_F_PERMANENT)
continue; continue;
spin_lock(&ifp->lock);
age = (now - ifp->tstamp) / HZ; age = (now - ifp->tstamp) / HZ;
if (age > ifp->valid_lft) { if (age >= ifp->valid_lft) {
spin_unlock(&ifp->lock);
in6_ifa_hold(ifp); in6_ifa_hold(ifp);
write_unlock(&addrconf_hash_lock); write_unlock(&addrconf_hash_lock);
ipv6_del_addr(ifp); ipv6_del_addr(ifp);
goto restart; goto restart;
} else if (age > ifp->prefered_lft) { } else if (age >= ifp->prefered_lft) {
/* jiffies - ifp->tsamp > age >= ifp->prefered_lft */
int deprecate = 0; int deprecate = 0;
spin_lock(&ifp->lock);
if (!(ifp->flags&IFA_F_DEPRECATED)) { if (!(ifp->flags&IFA_F_DEPRECATED)) {
deprecate = 1; deprecate = 1;
ifp->flags |= IFA_F_DEPRECATED; 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); spin_unlock(&ifp->lock);
if (deprecate) { if (deprecate) {
...@@ -1654,12 +1669,19 @@ static void addrconf_verify(unsigned long foo) ...@@ -1654,12 +1669,19 @@ static void addrconf_verify(unsigned long foo)
in6_ifa_put(ifp); in6_ifa_put(ifp);
goto restart; 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); 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 static int
...@@ -2033,8 +2055,7 @@ void __init addrconf_init(void) ...@@ -2033,8 +2055,7 @@ void __init addrconf_init(void)
proc_net_create("if_inet6", 0, iface_proc_info); proc_net_create("if_inet6", 0, iface_proc_info);
#endif #endif
addr_chk_timer.expires = jiffies + ADDR_CHECK_FREQUENCY; addrconf_verify(0);
add_timer(&addr_chk_timer);
rtnetlink_links[PF_INET6] = inet6_rtnetlink_table; rtnetlink_links[PF_INET6] = inet6_rtnetlink_table;
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
addrconf_sysctl.sysctl_header = 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