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 $ */
|
/* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -31,7 +31,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#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/param.h>
|
||||||
#include <sys/systm.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_setmtu0 __P((struct ifnet *, struct nd_ifinfo *));
|
||||||
static void nd6_slowtimo __P((void *));
|
static void nd6_slowtimo __P((void *));
|
||||||
static struct llinfo_nd6 *nd6_free __P((struct rtentry *, int));
|
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_slowtimo_ch = CALLOUT_INITIALIZER;
|
||||||
struct callout nd6_timer_ch = CALLOUT_INITIALIZER;
|
struct callout nd6_timer_ch = CALLOUT_INITIALIZER;
|
||||||
@ -372,6 +373,149 @@ skip1:
|
|||||||
return 0;
|
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
|
* ND6 timer routine to expire default route list and prefix list
|
||||||
*/
|
*/
|
||||||
@ -380,10 +524,8 @@ nd6_timer(ignored_arg)
|
|||||||
void *ignored_arg;
|
void *ignored_arg;
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
struct llinfo_nd6 *ln;
|
|
||||||
struct nd_defrouter *dr;
|
struct nd_defrouter *dr;
|
||||||
struct nd_prefix *pr;
|
struct nd_prefix *pr;
|
||||||
struct ifnet *ifp;
|
|
||||||
struct in6_ifaddr *ia6, *nia6;
|
struct in6_ifaddr *ia6, *nia6;
|
||||||
struct in6_addrlifetime *lt6;
|
struct in6_addrlifetime *lt6;
|
||||||
|
|
||||||
@ -391,108 +533,6 @@ nd6_timer(ignored_arg)
|
|||||||
callout_reset(&nd6_timer_ch, nd6_prune * hz,
|
callout_reset(&nd6_timer_ch, nd6_prune * hz,
|
||||||
nd6_timer, NULL);
|
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 */
|
/* expire default router list */
|
||||||
dr = TAILQ_FIRST(&nd_defrouter);
|
dr = TAILQ_FIRST(&nd_defrouter);
|
||||||
while (dr) {
|
while (dr) {
|
||||||
@ -815,6 +855,9 @@ nd6_free(rt, gc)
|
|||||||
* even though it is not harmful, it was not really necessary.
|
* even though it is not harmful, it was not really necessary.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* cancel timer */
|
||||||
|
nd6_llinfo_settimer(ln, -1);
|
||||||
|
|
||||||
if (!ip6_forwarding) {
|
if (!ip6_forwarding) {
|
||||||
int s;
|
int s;
|
||||||
s = splsoftnet();
|
s = splsoftnet();
|
||||||
@ -835,7 +878,11 @@ nd6_free(rt, gc)
|
|||||||
* XXX: the check for ln_state would be redundant,
|
* XXX: the check for ln_state would be redundant,
|
||||||
* but we intentionally keep it just in case.
|
* 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);
|
splx(s);
|
||||||
return (ln->ln_next);
|
return (ln->ln_next);
|
||||||
}
|
}
|
||||||
@ -947,8 +994,10 @@ nd6_nud_hint(rt, dst6, force)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||||
if (ln->ln_expire)
|
if (!ND6_LLINFO_PERMANENT(ln)) {
|
||||||
ln->ln_expire = time.tv_sec + ND_IFINFO(rt->rt_ifp)->reachable;
|
nd6_llinfo_settimer(ln,
|
||||||
|
(long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1022,17 +1071,7 @@ nd6_rtrequest(req, rt, info)
|
|||||||
SDL(gate)->sdl_type = ifp->if_type;
|
SDL(gate)->sdl_type = ifp->if_type;
|
||||||
SDL(gate)->sdl_index = ifp->if_index;
|
SDL(gate)->sdl_index = ifp->if_index;
|
||||||
if (ln)
|
if (ln)
|
||||||
ln->ln_expire = time.tv_sec;
|
nd6_llinfo_settimer(ln, 0);
|
||||||
#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
|
|
||||||
if ((rt->rt_flags & RTF_CLONING) != 0)
|
if ((rt->rt_flags & RTF_CLONING) != 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1096,6 +1135,7 @@ nd6_rtrequest(req, rt, info)
|
|||||||
nd6_allocated++;
|
nd6_allocated++;
|
||||||
Bzero(ln, sizeof(*ln));
|
Bzero(ln, sizeof(*ln));
|
||||||
ln->ln_rt = rt;
|
ln->ln_rt = rt;
|
||||||
|
callout_init(&ln->ln_timer_ch);
|
||||||
/* this is required for "ndp" command. - shin */
|
/* this is required for "ndp" command. - shin */
|
||||||
if (req == RTM_ADD) {
|
if (req == RTM_ADD) {
|
||||||
/*
|
/*
|
||||||
@ -1111,7 +1151,7 @@ nd6_rtrequest(req, rt, info)
|
|||||||
* initialized in rtrequest(), so rt_expire is 0.
|
* initialized in rtrequest(), so rt_expire is 0.
|
||||||
*/
|
*/
|
||||||
ln->ln_state = ND6_LLINFO_NOSTATE;
|
ln->ln_state = ND6_LLINFO_NOSTATE;
|
||||||
ln->ln_expire = time.tv_sec;
|
nd6_llinfo_settimer(ln, 0);
|
||||||
}
|
}
|
||||||
rt->rt_flags |= RTF_LLINFO;
|
rt->rt_flags |= RTF_LLINFO;
|
||||||
ln->ln_next = llinfo_nd6.ln_next;
|
ln->ln_next = llinfo_nd6.ln_next;
|
||||||
@ -1127,7 +1167,7 @@ nd6_rtrequest(req, rt, info)
|
|||||||
&SIN6(rt_key(rt))->sin6_addr);
|
&SIN6(rt_key(rt))->sin6_addr);
|
||||||
if (ifa) {
|
if (ifa) {
|
||||||
caddr_t macp = nd6_ifptomac(ifp);
|
caddr_t macp = nd6_ifptomac(ifp);
|
||||||
ln->ln_expire = 0;
|
nd6_llinfo_settimer(ln, -1);
|
||||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||||
ln->ln_byhint = 0;
|
ln->ln_byhint = 0;
|
||||||
mine = 1;
|
mine = 1;
|
||||||
@ -1152,7 +1192,7 @@ nd6_rtrequest(req, rt, info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (rt->rt_flags & RTF_ANNOUNCE) {
|
} else if (rt->rt_flags & RTF_ANNOUNCE) {
|
||||||
ln->ln_expire = 0;
|
nd6_llinfo_settimer(ln, -1);
|
||||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||||
ln->ln_byhint = 0;
|
ln->ln_byhint = 0;
|
||||||
|
|
||||||
@ -1201,6 +1241,7 @@ nd6_rtrequest(req, rt, info)
|
|||||||
ln->ln_next->ln_prev = ln->ln_prev;
|
ln->ln_next->ln_prev = ln->ln_prev;
|
||||||
ln->ln_prev->ln_next = ln->ln_next;
|
ln->ln_prev->ln_next = ln->ln_next;
|
||||||
ln->ln_prev = NULL;
|
ln->ln_prev = NULL;
|
||||||
|
nd6_llinfo_settimer(ln, -1);
|
||||||
rt->rt_llinfo = 0;
|
rt->rt_llinfo = 0;
|
||||||
rt->rt_flags &= ~RTF_LLINFO;
|
rt->rt_flags &= ~RTF_LLINFO;
|
||||||
if (ln->ln_hold)
|
if (ln->ln_hold)
|
||||||
@ -1551,7 +1592,7 @@ fail:
|
|||||||
* we must set the timer now, although it is actually
|
* we must set the timer now, although it is actually
|
||||||
* meaningless.
|
* meaningless.
|
||||||
*/
|
*/
|
||||||
ln->ln_expire = time.tv_sec + nd6_gctimer;
|
nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
|
||||||
|
|
||||||
if (ln->ln_hold) {
|
if (ln->ln_hold) {
|
||||||
/*
|
/*
|
||||||
@ -1564,7 +1605,7 @@ fail:
|
|||||||
}
|
}
|
||||||
} else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
|
} else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
|
||||||
/* probe right away */
|
/* 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 &&
|
if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
|
||||||
ln->ln_state < ND6_LLINFO_REACHABLE) {
|
ln->ln_state < ND6_LLINFO_REACHABLE) {
|
||||||
ln->ln_state = ND6_LLINFO_STALE;
|
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) {
|
if (ln->ln_state == ND6_LLINFO_STALE) {
|
||||||
ln->ln_asked = 0;
|
ln->ln_asked = 0;
|
||||||
ln->ln_state = ND6_LLINFO_DELAY;
|
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
|
* If there has been no NS for the neighbor after entering the
|
||||||
* INCOMPLETE state, send the first solicitation.
|
* 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_asked++;
|
||||||
ln->ln_expire = time.tv_sec +
|
nd6_llinfo_settimer(ln,
|
||||||
ND6_RETRANS_SEC(ND_IFINFO(ifp)->retrans);
|
(long)ND_IFINFO(ifp)->retrans * hz / 1000);
|
||||||
nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
|
nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
|
||||||
}
|
}
|
||||||
return (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 $ */
|
/* $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_state; /* reachability state */
|
||||||
short ln_router; /* 2^0: ND6 router bit */
|
short ln_router; /* 2^0: ND6 router bit */
|
||||||
int ln_byhint; /* # of times we made it reachable by UL hint */
|
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
|
#define ND6_LLINFO_NOSTATE -2
|
||||||
@ -69,12 +72,7 @@ struct llinfo_nd6 {
|
|||||||
#define ND6_LLINFO_PROBE 4
|
#define ND6_LLINFO_PROBE 4
|
||||||
|
|
||||||
#define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE)
|
#define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE)
|
||||||
|
#define ND6_LLINFO_PERMANENT(n) ((n)->ln_expire == 0)
|
||||||
/*
|
|
||||||
* 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)
|
|
||||||
|
|
||||||
struct nd_ifinfo {
|
struct nd_ifinfo {
|
||||||
u_int32_t linkmtu; /* LinkMTU */
|
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 *));
|
int nd6_options __P((union nd_opts *));
|
||||||
struct rtentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *));
|
struct rtentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *));
|
||||||
void nd6_setmtu __P((struct ifnet *));
|
void nd6_setmtu __P((struct ifnet *));
|
||||||
|
void nd6_llinfo_settimer __P((struct llinfo_nd6 *, long));
|
||||||
void nd6_timer __P((void *));
|
void nd6_timer __P((void *));
|
||||||
void nd6_purge __P((struct ifnet *));
|
void nd6_purge __P((struct ifnet *));
|
||||||
void nd6_nud_hint __P((struct rtentry *, struct in6_addr *, int));
|
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 $ */
|
/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -31,7 +31,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#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_inet.h"
|
||||||
#include "opt_ipsec.h"
|
#include "opt_ipsec.h"
|
||||||
@ -666,12 +666,13 @@ nd6_na_input(m, off, icmp6len)
|
|||||||
if (is_solicited) {
|
if (is_solicited) {
|
||||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||||
ln->ln_byhint = 0;
|
ln->ln_byhint = 0;
|
||||||
if (ln->ln_expire)
|
if (!ND6_LLINFO_PERMANENT(ln)) {
|
||||||
ln->ln_expire = time.tv_sec +
|
nd6_llinfo_settimer(ln,
|
||||||
ND_IFINFO(rt->rt_ifp)->reachable;
|
(long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ln->ln_state = ND6_LLINFO_STALE;
|
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) {
|
if ((ln->ln_router = is_router) != 0) {
|
||||||
/*
|
/*
|
||||||
@ -725,7 +726,7 @@ nd6_na_input(m, off, icmp6len)
|
|||||||
*/
|
*/
|
||||||
if (ln->ln_state == ND6_LLINFO_REACHABLE) {
|
if (ln->ln_state == ND6_LLINFO_REACHABLE) {
|
||||||
ln->ln_state = ND6_LLINFO_STALE;
|
ln->ln_state = ND6_LLINFO_STALE;
|
||||||
ln->ln_expire = time.tv_sec + nd6_gctimer;
|
nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
|
||||||
}
|
}
|
||||||
goto freeit;
|
goto freeit;
|
||||||
} else if (is_override /* (2a) */
|
} else if (is_override /* (2a) */
|
||||||
@ -747,14 +748,15 @@ nd6_na_input(m, off, icmp6len)
|
|||||||
if (is_solicited) {
|
if (is_solicited) {
|
||||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||||
ln->ln_byhint = 0;
|
ln->ln_byhint = 0;
|
||||||
if (ln->ln_expire) {
|
if (!ND6_LLINFO_PERMANENT(ln)) {
|
||||||
ln->ln_expire = time.tv_sec +
|
nd6_llinfo_settimer(ln,
|
||||||
ND_IFINFO(ifp)->reachable;
|
(long)ND_IFINFO(ifp)->reachable * hz);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (lladdr && llchange) {
|
if (lladdr && llchange) {
|
||||||
ln->ln_state = ND6_LLINFO_STALE;
|
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) {
|
if (tick == NULL) {
|
||||||
nd6_dad_ns_output(dp, ifa);
|
nd6_dad_ns_output(dp, ifa);
|
||||||
nd6_dad_starttimer(dp,
|
nd6_dad_starttimer(dp,
|
||||||
ND6_RETRANS_SEC(ND_IFINFO(ifa->ifa_ifp)->retrans) * hz);
|
(long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
|
||||||
} else {
|
} else {
|
||||||
int ntick;
|
int ntick;
|
||||||
|
|
||||||
@ -1224,7 +1226,7 @@ nd6_dad_timer(ifa)
|
|||||||
*/
|
*/
|
||||||
nd6_dad_ns_output(dp, ifa);
|
nd6_dad_ns_output(dp, ifa);
|
||||||
nd6_dad_starttimer(dp,
|
nd6_dad_starttimer(dp,
|
||||||
ND6_RETRANS_SEC(ND_IFINFO(ifa->ifa_ifp)->retrans) * hz);
|
(long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* We have transmitted sufficient number of DAD packets.
|
* We have transmitted sufficient number of DAD packets.
|
||||||
|
Loading…
Reference in New Issue
Block a user