split ND6 cache timer management to per-entry. increased accuracy,
no O(N) loop. sync w/ kame
This commit is contained in:
parent
1d910e61f7
commit
2cadb8ca7a
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: nd6.c,v 1.85 2003/06/24 07:54:48 itojun Exp $ */
|
||||
/* $NetBSD: nd6.c,v 1.86 2003/06/27 08:41:08 itojun Exp $ */
|
||||
/* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.85 2003/06/24 07:54:48 itojun Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.86 2003/06/27 08:41:08 itojun Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -106,6 +106,7 @@ static struct sockaddr_in6 all1_sa;
|
||||
static void nd6_setmtu0 __P((struct ifnet *, struct nd_ifinfo *));
|
||||
static void nd6_slowtimo __P((void *));
|
||||
static struct llinfo_nd6 *nd6_free __P((struct rtentry *, int));
|
||||
static void nd6_llinfo_timer __P((void *));
|
||||
|
||||
struct callout nd6_slowtimo_ch = CALLOUT_INITIALIZER;
|
||||
struct callout nd6_timer_ch = CALLOUT_INITIALIZER;
|
||||
@ -372,6 +373,149 @@ skip1:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ND6 timer routine to handle ND6 entries
|
||||
*/
|
||||
void
|
||||
nd6_llinfo_settimer(ln, tick)
|
||||
struct llinfo_nd6 *ln;
|
||||
long tick;
|
||||
{
|
||||
int s;
|
||||
|
||||
s = splsoftnet();
|
||||
|
||||
if (tick < 0) {
|
||||
ln->ln_expire = 0;
|
||||
ln->ln_ntick = 0;
|
||||
callout_stop(&ln->ln_timer_ch);
|
||||
} else {
|
||||
ln->ln_expire = time.tv_sec + tick / hz;
|
||||
if (tick > INT_MAX) {
|
||||
ln->ln_ntick = tick - INT_MAX;
|
||||
callout_reset(&ln->ln_timer_ch, INT_MAX,
|
||||
nd6_llinfo_timer, ln);
|
||||
} else {
|
||||
ln->ln_ntick = 0;
|
||||
callout_reset(&ln->ln_timer_ch, tick,
|
||||
nd6_llinfo_timer, ln);
|
||||
}
|
||||
}
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static void
|
||||
nd6_llinfo_timer(arg)
|
||||
void *arg;
|
||||
{
|
||||
int s;
|
||||
struct llinfo_nd6 *ln;
|
||||
struct rtentry *rt;
|
||||
const struct sockaddr_in6 *dst;
|
||||
struct ifnet *ifp;
|
||||
struct nd_ifinfo *ndi = NULL;
|
||||
|
||||
s = splsoftnet();
|
||||
|
||||
ln = (struct llinfo_nd6 *)arg;
|
||||
|
||||
if (ln->ln_ntick > 0) {
|
||||
if (ln->ln_ntick > INT_MAX) {
|
||||
ln->ln_ntick -= INT_MAX;
|
||||
nd6_llinfo_settimer(ln, INT_MAX);
|
||||
} else {
|
||||
ln->ln_ntick = 0;
|
||||
nd6_llinfo_settimer(ln, ln->ln_ntick);
|
||||
}
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((rt = ln->ln_rt) == NULL)
|
||||
panic("ln->ln_rt == NULL");
|
||||
if ((ifp = rt->rt_ifp) == NULL)
|
||||
panic("ln->ln_rt->rt_ifp == NULL");
|
||||
ndi = ND_IFINFO(ifp);
|
||||
dst = (struct sockaddr_in6 *)rt_key(rt);
|
||||
|
||||
/* sanity check */
|
||||
if (rt->rt_llinfo && (struct llinfo_nd6 *)rt->rt_llinfo != ln)
|
||||
panic("rt_llinfo(%p) is not equal to ln(%p)",
|
||||
rt->rt_llinfo, ln);
|
||||
if (!dst)
|
||||
panic("dst=0 in nd6_timer(ln=%p)", ln);
|
||||
|
||||
switch (ln->ln_state) {
|
||||
case ND6_LLINFO_INCOMPLETE:
|
||||
if (ln->ln_asked < nd6_mmaxtries) {
|
||||
ln->ln_asked++;
|
||||
nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
|
||||
nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
|
||||
} else {
|
||||
struct mbuf *m = ln->ln_hold;
|
||||
if (m) {
|
||||
ln->ln_hold = NULL;
|
||||
/*
|
||||
* Fake rcvif to make the ICMP error
|
||||
* more helpful in diagnosing for the
|
||||
* receiver.
|
||||
* XXX: should we consider
|
||||
* older rcvif?
|
||||
*/
|
||||
m->m_pkthdr.rcvif = rt->rt_ifp;
|
||||
|
||||
icmp6_error(m, ICMP6_DST_UNREACH,
|
||||
ICMP6_DST_UNREACH_ADDR, 0);
|
||||
}
|
||||
(void)nd6_free(rt, 0);
|
||||
ln = NULL;
|
||||
}
|
||||
break;
|
||||
case ND6_LLINFO_REACHABLE:
|
||||
if (!ND6_LLINFO_PERMANENT(ln)) {
|
||||
ln->ln_state = ND6_LLINFO_STALE;
|
||||
nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
|
||||
}
|
||||
break;
|
||||
|
||||
case ND6_LLINFO_STALE:
|
||||
/* Garbage Collection(RFC 2461 5.3) */
|
||||
if (!ND6_LLINFO_PERMANENT(ln)) {
|
||||
(void)nd6_free(rt, 1);
|
||||
ln = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case ND6_LLINFO_DELAY:
|
||||
if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) {
|
||||
/* We need NUD */
|
||||
ln->ln_asked = 1;
|
||||
ln->ln_state = ND6_LLINFO_PROBE;
|
||||
nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
|
||||
nd6_ns_output(ifp, &dst->sin6_addr,
|
||||
&dst->sin6_addr, ln, 0);
|
||||
} else {
|
||||
ln->ln_state = ND6_LLINFO_STALE; /* XXX */
|
||||
nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
|
||||
}
|
||||
break;
|
||||
case ND6_LLINFO_PROBE:
|
||||
if (ln->ln_asked < nd6_umaxtries) {
|
||||
ln->ln_asked++;
|
||||
nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
|
||||
nd6_ns_output(ifp, &dst->sin6_addr,
|
||||
&dst->sin6_addr, ln, 0);
|
||||
} else {
|
||||
(void)nd6_free(rt, 0);
|
||||
ln = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* ND6 timer routine to expire default route list and prefix list
|
||||
*/
|
||||
@ -380,10 +524,8 @@ nd6_timer(ignored_arg)
|
||||
void *ignored_arg;
|
||||
{
|
||||
int s;
|
||||
struct llinfo_nd6 *ln;
|
||||
struct nd_defrouter *dr;
|
||||
struct nd_prefix *pr;
|
||||
struct ifnet *ifp;
|
||||
struct in6_ifaddr *ia6, *nia6;
|
||||
struct in6_addrlifetime *lt6;
|
||||
|
||||
@ -391,108 +533,6 @@ nd6_timer(ignored_arg)
|
||||
callout_reset(&nd6_timer_ch, nd6_prune * hz,
|
||||
nd6_timer, NULL);
|
||||
|
||||
ln = llinfo_nd6.ln_next;
|
||||
while (ln && ln != &llinfo_nd6) {
|
||||
struct rtentry *rt;
|
||||
struct sockaddr_in6 *dst;
|
||||
struct llinfo_nd6 *next = ln->ln_next;
|
||||
/* XXX: used for the DELAY case only: */
|
||||
struct nd_ifinfo *ndi = NULL;
|
||||
|
||||
if ((rt = ln->ln_rt) == NULL) {
|
||||
ln = next;
|
||||
continue;
|
||||
}
|
||||
if ((ifp = rt->rt_ifp) == NULL) {
|
||||
ln = next;
|
||||
continue;
|
||||
}
|
||||
ndi = ND_IFINFO(ifp);
|
||||
dst = (struct sockaddr_in6 *)rt_key(rt);
|
||||
|
||||
if (ln->ln_expire > time.tv_sec) {
|
||||
ln = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
if (!rt)
|
||||
panic("rt=0 in nd6_timer(ln=%p)", ln);
|
||||
if (rt->rt_llinfo && (struct llinfo_nd6 *)rt->rt_llinfo != ln)
|
||||
panic("rt_llinfo(%p) is not equal to ln(%p)",
|
||||
rt->rt_llinfo, ln);
|
||||
if (!dst)
|
||||
panic("dst=0 in nd6_timer(ln=%p)", ln);
|
||||
|
||||
switch (ln->ln_state) {
|
||||
case ND6_LLINFO_INCOMPLETE:
|
||||
if (ln->ln_asked < nd6_mmaxtries) {
|
||||
ln->ln_asked++;
|
||||
ln->ln_expire = time.tv_sec +
|
||||
ND6_RETRANS_SEC(ND_IFINFO(ifp)->retrans);
|
||||
nd6_ns_output(ifp, NULL, &dst->sin6_addr,
|
||||
ln, 0);
|
||||
} else {
|
||||
struct mbuf *m = ln->ln_hold;
|
||||
if (m) {
|
||||
ln->ln_hold = NULL;
|
||||
/*
|
||||
* Fake rcvif to make the ICMP error
|
||||
* more helpful in diagnosing for the
|
||||
* receiver.
|
||||
* XXX: should we consider
|
||||
* older rcvif?
|
||||
*/
|
||||
m->m_pkthdr.rcvif = rt->rt_ifp;
|
||||
|
||||
icmp6_error(m, ICMP6_DST_UNREACH,
|
||||
ICMP6_DST_UNREACH_ADDR, 0);
|
||||
}
|
||||
next = nd6_free(rt, 0);
|
||||
}
|
||||
break;
|
||||
case ND6_LLINFO_REACHABLE:
|
||||
if (ln->ln_expire) {
|
||||
ln->ln_state = ND6_LLINFO_STALE;
|
||||
ln->ln_expire = time.tv_sec + nd6_gctimer;
|
||||
}
|
||||
break;
|
||||
|
||||
case ND6_LLINFO_STALE:
|
||||
/* Garbage Collection(RFC 2461 5.3) */
|
||||
if (ln->ln_expire)
|
||||
next = nd6_free(rt, 1);
|
||||
break;
|
||||
|
||||
case ND6_LLINFO_DELAY:
|
||||
if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) {
|
||||
/* We need NUD */
|
||||
ln->ln_asked = 1;
|
||||
ln->ln_state = ND6_LLINFO_PROBE;
|
||||
ln->ln_expire = time.tv_sec +
|
||||
ND6_RETRANS_SEC(ndi->retrans);
|
||||
nd6_ns_output(ifp, &dst->sin6_addr,
|
||||
&dst->sin6_addr, ln, 0);
|
||||
} else {
|
||||
ln->ln_state = ND6_LLINFO_STALE; /* XXX */
|
||||
ln->ln_expire = time.tv_sec + nd6_gctimer;
|
||||
}
|
||||
break;
|
||||
case ND6_LLINFO_PROBE:
|
||||
if (ln->ln_asked < nd6_umaxtries) {
|
||||
ln->ln_asked++;
|
||||
ln->ln_expire = time.tv_sec +
|
||||
ND6_RETRANS_SEC(ND_IFINFO(ifp)->retrans);
|
||||
nd6_ns_output(ifp, &dst->sin6_addr,
|
||||
&dst->sin6_addr, ln, 0);
|
||||
} else {
|
||||
next = nd6_free(rt, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
ln = next;
|
||||
}
|
||||
|
||||
/* expire default router list */
|
||||
dr = TAILQ_FIRST(&nd_defrouter);
|
||||
while (dr) {
|
||||
@ -815,6 +855,9 @@ nd6_free(rt, gc)
|
||||
* even though it is not harmful, it was not really necessary.
|
||||
*/
|
||||
|
||||
/* cancel timer */
|
||||
nd6_llinfo_settimer(ln, -1);
|
||||
|
||||
if (!ip6_forwarding) {
|
||||
int s;
|
||||
s = splsoftnet();
|
||||
@ -835,7 +878,11 @@ nd6_free(rt, gc)
|
||||
* XXX: the check for ln_state would be redundant,
|
||||
* but we intentionally keep it just in case.
|
||||
*/
|
||||
ln->ln_expire = dr->expire;
|
||||
if (dr->expire > time.tv_sec * hz)
|
||||
nd6_llinfo_settimer(ln,
|
||||
dr->expire - time.tv_sec * hz);
|
||||
else
|
||||
nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
|
||||
splx(s);
|
||||
return (ln->ln_next);
|
||||
}
|
||||
@ -947,8 +994,10 @@ nd6_nud_hint(rt, dst6, force)
|
||||
}
|
||||
|
||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||
if (ln->ln_expire)
|
||||
ln->ln_expire = time.tv_sec + ND_IFINFO(rt->rt_ifp)->reachable;
|
||||
if (!ND6_LLINFO_PERMANENT(ln)) {
|
||||
nd6_llinfo_settimer(ln,
|
||||
(long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1022,17 +1071,7 @@ nd6_rtrequest(req, rt, info)
|
||||
SDL(gate)->sdl_type = ifp->if_type;
|
||||
SDL(gate)->sdl_index = ifp->if_index;
|
||||
if (ln)
|
||||
ln->ln_expire = time.tv_sec;
|
||||
#if 1
|
||||
if (ln && ln->ln_expire == 0) {
|
||||
/* kludge for desktops */
|
||||
#if 0
|
||||
printf("nd6_rtrequest: time.tv_sec is zero; "
|
||||
"treat it as 1\n");
|
||||
#endif
|
||||
ln->ln_expire = 1;
|
||||
}
|
||||
#endif
|
||||
nd6_llinfo_settimer(ln, 0);
|
||||
if ((rt->rt_flags & RTF_CLONING) != 0)
|
||||
break;
|
||||
}
|
||||
@ -1096,6 +1135,7 @@ nd6_rtrequest(req, rt, info)
|
||||
nd6_allocated++;
|
||||
Bzero(ln, sizeof(*ln));
|
||||
ln->ln_rt = rt;
|
||||
callout_init(&ln->ln_timer_ch);
|
||||
/* this is required for "ndp" command. - shin */
|
||||
if (req == RTM_ADD) {
|
||||
/*
|
||||
@ -1111,7 +1151,7 @@ nd6_rtrequest(req, rt, info)
|
||||
* initialized in rtrequest(), so rt_expire is 0.
|
||||
*/
|
||||
ln->ln_state = ND6_LLINFO_NOSTATE;
|
||||
ln->ln_expire = time.tv_sec;
|
||||
nd6_llinfo_settimer(ln, 0);
|
||||
}
|
||||
rt->rt_flags |= RTF_LLINFO;
|
||||
ln->ln_next = llinfo_nd6.ln_next;
|
||||
@ -1127,7 +1167,7 @@ nd6_rtrequest(req, rt, info)
|
||||
&SIN6(rt_key(rt))->sin6_addr);
|
||||
if (ifa) {
|
||||
caddr_t macp = nd6_ifptomac(ifp);
|
||||
ln->ln_expire = 0;
|
||||
nd6_llinfo_settimer(ln, -1);
|
||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||
ln->ln_byhint = 0;
|
||||
mine = 1;
|
||||
@ -1152,7 +1192,7 @@ nd6_rtrequest(req, rt, info)
|
||||
}
|
||||
}
|
||||
} else if (rt->rt_flags & RTF_ANNOUNCE) {
|
||||
ln->ln_expire = 0;
|
||||
nd6_llinfo_settimer(ln, -1);
|
||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||
ln->ln_byhint = 0;
|
||||
|
||||
@ -1201,6 +1241,7 @@ nd6_rtrequest(req, rt, info)
|
||||
ln->ln_next->ln_prev = ln->ln_prev;
|
||||
ln->ln_prev->ln_next = ln->ln_next;
|
||||
ln->ln_prev = NULL;
|
||||
nd6_llinfo_settimer(ln, -1);
|
||||
rt->rt_llinfo = 0;
|
||||
rt->rt_flags &= ~RTF_LLINFO;
|
||||
if (ln->ln_hold)
|
||||
@ -1551,7 +1592,7 @@ fail:
|
||||
* we must set the timer now, although it is actually
|
||||
* meaningless.
|
||||
*/
|
||||
ln->ln_expire = time.tv_sec + nd6_gctimer;
|
||||
nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
|
||||
|
||||
if (ln->ln_hold) {
|
||||
/*
|
||||
@ -1564,7 +1605,7 @@ fail:
|
||||
}
|
||||
} else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
|
||||
/* probe right away */
|
||||
ln->ln_expire = time.tv_sec;
|
||||
nd6_llinfo_settimer((void *)ln, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1801,7 +1842,7 @@ nd6_output(ifp, origifp, m0, dst, rt0)
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
|
||||
ln->ln_state < ND6_LLINFO_REACHABLE) {
|
||||
ln->ln_state = ND6_LLINFO_STALE;
|
||||
ln->ln_expire = time.tv_sec + nd6_gctimer;
|
||||
nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1814,7 +1855,7 @@ nd6_output(ifp, origifp, m0, dst, rt0)
|
||||
if (ln->ln_state == ND6_LLINFO_STALE) {
|
||||
ln->ln_asked = 0;
|
||||
ln->ln_state = ND6_LLINFO_DELAY;
|
||||
ln->ln_expire = time.tv_sec + nd6_delay;
|
||||
nd6_llinfo_settimer(ln, nd6_delay * hz);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1838,17 +1879,11 @@ nd6_output(ifp, origifp, m0, dst, rt0)
|
||||
/*
|
||||
* If there has been no NS for the neighbor after entering the
|
||||
* INCOMPLETE state, send the first solicitation.
|
||||
* Technically this can be against the rate-limiting rule described in
|
||||
* Section 7.2.2 of RFC 2461 because the interval to the next scheduled
|
||||
* solicitation issued in nd6_timer() may be less than the specified
|
||||
* retransmission time. This should not be a problem from a practical
|
||||
* point of view, because we'll typically see an immediate response
|
||||
* from the neighbor, which suppresses the succeeding solicitations.
|
||||
*/
|
||||
if (ln->ln_expire && ln->ln_asked == 0) {
|
||||
if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) {
|
||||
ln->ln_asked++;
|
||||
ln->ln_expire = time.tv_sec +
|
||||
ND6_RETRANS_SEC(ND_IFINFO(ifp)->retrans);
|
||||
nd6_llinfo_settimer(ln,
|
||||
(long)ND_IFINFO(ifp)->retrans * hz / 1000);
|
||||
nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
|
||||
}
|
||||
return (0);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: nd6.h,v 1.34 2003/02/01 06:23:47 thorpej Exp $ */
|
||||
/* $NetBSD: nd6.h,v 1.35 2003/06/27 08:41:08 itojun Exp $ */
|
||||
/* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -51,6 +51,9 @@ struct llinfo_nd6 {
|
||||
short ln_state; /* reachability state */
|
||||
short ln_router; /* 2^0: ND6 router bit */
|
||||
int ln_byhint; /* # of times we made it reachable by UL hint */
|
||||
|
||||
long ln_ntick;
|
||||
struct callout ln_timer_ch;
|
||||
};
|
||||
|
||||
#define ND6_LLINFO_NOSTATE -2
|
||||
@ -69,12 +72,7 @@ struct llinfo_nd6 {
|
||||
#define ND6_LLINFO_PROBE 4
|
||||
|
||||
#define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE)
|
||||
|
||||
/*
|
||||
* Since the granularity of our retransmission timer is seconds, we should
|
||||
* ensure that a positive timer value will be mapped to at least one second.
|
||||
*/
|
||||
#define ND6_RETRANS_SEC(r) (((r) + 999) / 1000)
|
||||
#define ND6_LLINFO_PERMANENT(n) ((n)->ln_expire == 0)
|
||||
|
||||
struct nd_ifinfo {
|
||||
u_int32_t linkmtu; /* LinkMTU */
|
||||
@ -366,6 +364,7 @@ struct nd_opt_hdr *nd6_option __P((union nd_opts *));
|
||||
int nd6_options __P((union nd_opts *));
|
||||
struct rtentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *));
|
||||
void nd6_setmtu __P((struct ifnet *));
|
||||
void nd6_llinfo_settimer __P((struct llinfo_nd6 *, long));
|
||||
void nd6_timer __P((void *));
|
||||
void nd6_purge __P((struct ifnet *));
|
||||
void nd6_nud_hint __P((struct rtentry *, struct in6_addr *, int));
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: nd6_nbr.c,v 1.46 2003/06/24 07:54:48 itojun Exp $ */
|
||||
/* $NetBSD: nd6_nbr.c,v 1.47 2003/06/27 08:41:09 itojun Exp $ */
|
||||
/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.46 2003/06/24 07:54:48 itojun Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.47 2003/06/27 08:41:09 itojun Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
@ -666,12 +666,13 @@ nd6_na_input(m, off, icmp6len)
|
||||
if (is_solicited) {
|
||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||
ln->ln_byhint = 0;
|
||||
if (ln->ln_expire)
|
||||
ln->ln_expire = time.tv_sec +
|
||||
ND_IFINFO(rt->rt_ifp)->reachable;
|
||||
if (!ND6_LLINFO_PERMANENT(ln)) {
|
||||
nd6_llinfo_settimer(ln,
|
||||
(long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
|
||||
}
|
||||
} else {
|
||||
ln->ln_state = ND6_LLINFO_STALE;
|
||||
ln->ln_expire = time.tv_sec + nd6_gctimer;
|
||||
nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
|
||||
}
|
||||
if ((ln->ln_router = is_router) != 0) {
|
||||
/*
|
||||
@ -725,7 +726,7 @@ nd6_na_input(m, off, icmp6len)
|
||||
*/
|
||||
if (ln->ln_state == ND6_LLINFO_REACHABLE) {
|
||||
ln->ln_state = ND6_LLINFO_STALE;
|
||||
ln->ln_expire = time.tv_sec + nd6_gctimer;
|
||||
nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
|
||||
}
|
||||
goto freeit;
|
||||
} else if (is_override /* (2a) */
|
||||
@ -747,14 +748,15 @@ nd6_na_input(m, off, icmp6len)
|
||||
if (is_solicited) {
|
||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||
ln->ln_byhint = 0;
|
||||
if (ln->ln_expire) {
|
||||
ln->ln_expire = time.tv_sec +
|
||||
ND_IFINFO(ifp)->reachable;
|
||||
if (!ND6_LLINFO_PERMANENT(ln)) {
|
||||
nd6_llinfo_settimer(ln,
|
||||
(long)ND_IFINFO(ifp)->reachable * hz);
|
||||
}
|
||||
} else {
|
||||
if (lladdr && llchange) {
|
||||
ln->ln_state = ND6_LLINFO_STALE;
|
||||
ln->ln_expire = time.tv_sec + nd6_gctimer;
|
||||
nd6_llinfo_settimer(ln,
|
||||
(long)nd6_gctimer * hz);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1132,7 +1134,7 @@ nd6_dad_start(ifa, tick)
|
||||
if (tick == NULL) {
|
||||
nd6_dad_ns_output(dp, ifa);
|
||||
nd6_dad_starttimer(dp,
|
||||
ND6_RETRANS_SEC(ND_IFINFO(ifa->ifa_ifp)->retrans) * hz);
|
||||
(long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
|
||||
} else {
|
||||
int ntick;
|
||||
|
||||
@ -1224,7 +1226,7 @@ nd6_dad_timer(ifa)
|
||||
*/
|
||||
nd6_dad_ns_output(dp, ifa);
|
||||
nd6_dad_starttimer(dp,
|
||||
ND6_RETRANS_SEC(ND_IFINFO(ifa->ifa_ifp)->retrans) * hz);
|
||||
(long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
|
||||
} else {
|
||||
/*
|
||||
* We have transmitted sufficient number of DAD packets.
|
||||
|
Loading…
Reference in New Issue
Block a user