Unify nd6 state switching by using newly-created nd6_llinfo_setstate()
function. The change is mostly mechanical with the following exception: Last piece of nd6_resolve_slow() was refactored: ND6_LLINFO_PERMANENT condition was removed as always-true, explicit ND6_LLINFO_NOSTATE -> ND6_LLINFO_INCOMPLETE state transition was removed as duplicate. Reviewed by: ae Sponsored by: Yandex LLC
This commit is contained in:
parent
e968ae531f
commit
536c20752f
@ -468,7 +468,6 @@ toe_nd6_resolve(struct ifnet *ifp, struct sockaddr *sa, uint8_t *lladdr)
|
||||
lle = nd6_alloc(&sin6->sin6_addr, 0, ifp);
|
||||
if (lle == NULL)
|
||||
return (ENOMEM); /* Couldn't create entry in cache. */
|
||||
lle->ln_state = ND6_LLINFO_INCOMPLETE;
|
||||
IF_AFDATA_WLOCK(ifp);
|
||||
LLE_WLOCK(lle);
|
||||
lle_tmp = nd6_lookup(&sin6->sin6_addr, ND6_EXCLUSIVE, ifp);
|
||||
@ -478,8 +477,7 @@ toe_nd6_resolve(struct ifnet *ifp, struct sockaddr *sa, uint8_t *lladdr)
|
||||
IF_AFDATA_WUNLOCK(ifp);
|
||||
if (lle_tmp == NULL) {
|
||||
/* Arm timer for newly-created entry and send NS */
|
||||
nd6_llinfo_settimer_locked(lle,
|
||||
(long)ND_IFINFO(ifp)->retrans * hz / 1000);
|
||||
nd6_llinfo_setstate(lle, ND6_LLINFO_INCOMPLETE);
|
||||
LLE_WUNLOCK(lle);
|
||||
|
||||
nd6_ns_output(ifp, NULL, NULL, &sin6->sin6_addr, 0);
|
||||
@ -503,8 +501,7 @@ toe_nd6_resolve(struct ifnet *ifp, struct sockaddr *sa, uint8_t *lladdr)
|
||||
LLE_WLOCK_ASSERT(lle);
|
||||
|
||||
lle->la_asked = 0;
|
||||
lle->ln_state = ND6_LLINFO_DELAY;
|
||||
nd6_llinfo_settimer_locked(lle, (long)V_nd6_delay * hz);
|
||||
nd6_llinfo_setstate(lle, ND6_LLINFO_DELAY);
|
||||
}
|
||||
|
||||
if (lle->la_flags & LLE_VALID) {
|
||||
|
@ -539,6 +539,44 @@ nd6_llinfo_get_holdsrc(struct llentry *ln, struct in6_addr *src)
|
||||
return (src);
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch @lle state to new state optionally arming timers.
|
||||
*/
|
||||
void
|
||||
nd6_llinfo_setstate(struct llentry *lle, int newstate)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
long delay;
|
||||
|
||||
delay = 0;
|
||||
|
||||
switch (newstate) {
|
||||
case ND6_LLINFO_INCOMPLETE:
|
||||
ifp = lle->lle_tbl->llt_ifp;
|
||||
delay = (long)ND_IFINFO(ifp)->retrans * hz / 1000;
|
||||
break;
|
||||
case ND6_LLINFO_REACHABLE:
|
||||
if (!ND6_LLINFO_PERMANENT(lle)) {
|
||||
ifp = lle->lle_tbl->llt_ifp;
|
||||
delay = (long)ND_IFINFO(ifp)->reachable * hz;
|
||||
}
|
||||
break;
|
||||
case ND6_LLINFO_STALE:
|
||||
delay = (long)V_nd6_gctimer * hz;
|
||||
break;
|
||||
case ND6_LLINFO_DELAY:
|
||||
lle->la_asked = 0;
|
||||
delay = (long)V_nd6_delay * hz;
|
||||
break;
|
||||
}
|
||||
|
||||
if (delay > 0)
|
||||
nd6_llinfo_settimer_locked(lle, delay);
|
||||
|
||||
lle->ln_state = newstate;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nd6_llinfo_settimer(struct llentry *ln, long tick)
|
||||
{
|
||||
@ -638,10 +676,8 @@ nd6_llinfo_timer(void *arg)
|
||||
}
|
||||
break;
|
||||
case ND6_LLINFO_REACHABLE:
|
||||
if (!ND6_LLINFO_PERMANENT(ln)) {
|
||||
ln->ln_state = ND6_LLINFO_STALE;
|
||||
nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
|
||||
}
|
||||
if (!ND6_LLINFO_PERMANENT(ln))
|
||||
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
|
||||
break;
|
||||
|
||||
case ND6_LLINFO_STALE:
|
||||
@ -657,12 +693,10 @@ nd6_llinfo_timer(void *arg)
|
||||
if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) {
|
||||
/* We need NUD */
|
||||
ln->la_asked = 1;
|
||||
ln->ln_state = ND6_LLINFO_PROBE;
|
||||
nd6_llinfo_setstate(ln, ND6_LLINFO_PROBE);
|
||||
send_ns = 1;
|
||||
} else {
|
||||
ln->ln_state = ND6_LLINFO_STALE; /* XXX */
|
||||
nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
|
||||
}
|
||||
} else
|
||||
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); /* XXX */
|
||||
break;
|
||||
case ND6_LLINFO_PROBE:
|
||||
if (ln->la_asked < V_nd6_umaxtries) {
|
||||
@ -1316,11 +1350,7 @@ nd6_nud_hint(struct rtentry *rt, struct in6_addr *dst6, int force)
|
||||
}
|
||||
}
|
||||
|
||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||
if (!ND6_LLINFO_PERMANENT(ln)) {
|
||||
nd6_llinfo_settimer_locked(ln,
|
||||
(long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
|
||||
}
|
||||
nd6_llinfo_setstate(ln, ND6_LLINFO_REACHABLE);
|
||||
done:
|
||||
LLE_WUNLOCK(ln);
|
||||
}
|
||||
@ -1740,8 +1770,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
||||
if (ln_tmp == NULL) {
|
||||
/* No existing lle, mark as new entry */
|
||||
is_newentry = 1;
|
||||
ln->ln_state = ND6_LLINFO_STALE;
|
||||
nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
|
||||
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
|
||||
} else {
|
||||
lltable_free_entry(LLTABLE6(ifp), ln);
|
||||
ln = ln_tmp;
|
||||
@ -1788,8 +1817,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
||||
*/
|
||||
bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
|
||||
ln->la_flags |= LLE_VALID;
|
||||
ln->ln_state = ND6_LLINFO_STALE;
|
||||
nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
|
||||
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
|
||||
|
||||
EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
|
||||
|
||||
@ -1892,9 +1920,7 @@ nd6_grab_holdchain(struct llentry *ln, struct mbuf **chain,
|
||||
* detection on expiration.
|
||||
* (RFC 2461 7.3.3)
|
||||
*/
|
||||
ln->la_asked = 0;
|
||||
ln->ln_state = ND6_LLINFO_DELAY;
|
||||
nd6_llinfo_settimer_locked(ln, (long)V_nd6_delay * hz);
|
||||
nd6_llinfo_setstate(ln, ND6_LLINFO_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2034,6 +2060,8 @@ nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m,
|
||||
const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags)
|
||||
{
|
||||
struct llentry *lle = NULL, *lle_tmp;
|
||||
struct in6_addr *psrc, src;
|
||||
int send_ns;
|
||||
|
||||
/*
|
||||
* Address resolution or Neighbor Unreachability Detection
|
||||
@ -2061,7 +2089,6 @@ nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m,
|
||||
m_freem(m);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
lle->ln_state = ND6_LLINFO_NOSTATE;
|
||||
|
||||
IF_AFDATA_WLOCK(ifp);
|
||||
LLE_WLOCK(lle);
|
||||
@ -2097,11 +2124,8 @@ nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m,
|
||||
* neighbor unreachability detection on expiration.
|
||||
* (RFC 2461 7.3.3)
|
||||
*/
|
||||
if (lle->ln_state == ND6_LLINFO_STALE) {
|
||||
lle->la_asked = 0;
|
||||
lle->ln_state = ND6_LLINFO_DELAY;
|
||||
nd6_llinfo_settimer_locked(lle, (long)V_nd6_delay * hz);
|
||||
}
|
||||
if (lle->ln_state == ND6_LLINFO_STALE)
|
||||
nd6_llinfo_setstate(lle, ND6_LLINFO_DELAY);
|
||||
|
||||
/*
|
||||
* If the neighbor cache entry has a state other than INCOMPLETE
|
||||
@ -2123,8 +2147,6 @@ nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m,
|
||||
* does not exceed nd6_maxqueuelen. When it exceeds nd6_maxqueuelen,
|
||||
* the oldest packet in the queue will be removed.
|
||||
*/
|
||||
if (lle->ln_state == ND6_LLINFO_NOSTATE)
|
||||
lle->ln_state = ND6_LLINFO_INCOMPLETE;
|
||||
|
||||
if (lle->la_hold != NULL) {
|
||||
struct mbuf *m_hold;
|
||||
@ -2151,20 +2173,22 @@ nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m,
|
||||
/*
|
||||
* If there has been no NS for the neighbor after entering the
|
||||
* INCOMPLETE state, send the first solicitation.
|
||||
* Note that for newly-created lle la_asked will be 0,
|
||||
* so we will transition from ND6_LLINFO_NOSTATE to
|
||||
* ND6_LLINFO_INCOMPLETE state here.
|
||||
*/
|
||||
if (!ND6_LLINFO_PERMANENT(lle) && lle->la_asked == 0) {
|
||||
struct in6_addr src, *psrc;
|
||||
psrc = NULL;
|
||||
send_ns = 0;
|
||||
if (lle->la_asked == 0) {
|
||||
lle->la_asked++;
|
||||
|
||||
nd6_llinfo_settimer_locked(lle,
|
||||
(long)ND_IFINFO(ifp)->retrans * hz / 1000);
|
||||
send_ns = 1;
|
||||
psrc = nd6_llinfo_get_holdsrc(lle, &src);
|
||||
LLE_WUNLOCK(lle);
|
||||
nd6_ns_output(ifp, psrc, NULL, &dst->sin6_addr, NULL);
|
||||
} else {
|
||||
/* We did the lookup so we need to do the unlock here. */
|
||||
LLE_WUNLOCK(lle);
|
||||
|
||||
nd6_llinfo_setstate(lle, ND6_LLINFO_INCOMPLETE);
|
||||
}
|
||||
LLE_WUNLOCK(lle);
|
||||
if (send_ns != 0)
|
||||
nd6_ns_output(ifp, psrc, NULL, &dst->sin6_addr, NULL);
|
||||
|
||||
return (EWOULDBLOCK);
|
||||
}
|
||||
|
@ -409,6 +409,7 @@ int nd6_options(union nd_opts *);
|
||||
struct llentry *nd6_lookup(const struct in6_addr *, int, struct ifnet *);
|
||||
struct llentry *nd6_alloc(const struct in6_addr *, int, struct ifnet *);
|
||||
void nd6_setmtu(struct ifnet *);
|
||||
void nd6_llinfo_setstate(struct llentry *lle, int newstate);
|
||||
void nd6_llinfo_settimer(struct llentry *, long);
|
||||
void nd6_llinfo_settimer_locked(struct llentry *, long);
|
||||
void nd6_timer(void *);
|
||||
|
@ -769,16 +769,10 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
|
||||
ln->la_flags |= LLE_VALID;
|
||||
EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
|
||||
if (is_solicited) {
|
||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||
nd6_llinfo_setstate(ln, ND6_LLINFO_REACHABLE);
|
||||
ln->ln_byhint = 0;
|
||||
if (!ND6_LLINFO_PERMANENT(ln)) {
|
||||
nd6_llinfo_settimer_locked(ln,
|
||||
(long)ND_IFINFO(ln->lle_tbl->llt_ifp)->reachable * hz);
|
||||
}
|
||||
} else {
|
||||
ln->ln_state = ND6_LLINFO_STALE;
|
||||
nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
|
||||
}
|
||||
} else
|
||||
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
|
||||
if ((ln->ln_router = is_router) != 0) {
|
||||
/*
|
||||
* This means a router's state has changed from
|
||||
@ -829,10 +823,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
|
||||
* If state is REACHABLE, make it STALE.
|
||||
* no other updates should be done.
|
||||
*/
|
||||
if (ln->ln_state == ND6_LLINFO_REACHABLE) {
|
||||
ln->ln_state = ND6_LLINFO_STALE;
|
||||
nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
|
||||
}
|
||||
if (ln->ln_state == ND6_LLINFO_REACHABLE)
|
||||
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
|
||||
goto freeit;
|
||||
} else if (is_override /* (2a) */
|
||||
|| (!is_override && (lladdr != NULL && !llchange)) /* (2b) */
|
||||
@ -853,18 +845,11 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
|
||||
* changed, make it STALE.
|
||||
*/
|
||||
if (is_solicited) {
|
||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||
ln->ln_byhint = 0;
|
||||
if (!ND6_LLINFO_PERMANENT(ln)) {
|
||||
nd6_llinfo_settimer_locked(ln,
|
||||
(long)ND_IFINFO(ifp)->reachable * hz);
|
||||
}
|
||||
nd6_llinfo_setstate(ln, ND6_LLINFO_REACHABLE);
|
||||
} else {
|
||||
if (lladdr != NULL && llchange) {
|
||||
ln->ln_state = ND6_LLINFO_STALE;
|
||||
nd6_llinfo_settimer_locked(ln,
|
||||
(long)V_nd6_gctimer * hz);
|
||||
}
|
||||
if (lladdr != NULL && llchange)
|
||||
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user