Module Name: src
Committed By: roy
Date: Fri Sep 11 15:03:33 UTC 2020
Modified Files:
src/sys/netinet6: icmp6.c nd6.c nd6.h nd6_nbr.c
Log Message:
inet6: Use generic Neighor Detection rather than IPv6 specific
No functional change intended.
To generate a diff of this commit:
cvs rdiff -u -r1.246 -r1.247 src/sys/netinet6/icmp6.c
cvs rdiff -u -r1.271 -r1.272 src/sys/netinet6/nd6.c
cvs rdiff -u -r1.90 -r1.91 src/sys/netinet6/nd6.h
cvs rdiff -u -r1.180 -r1.181 src/sys/netinet6/nd6_nbr.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/netinet6/icmp6.c
diff -u src/sys/netinet6/icmp6.c:1.246 src/sys/netinet6/icmp6.c:1.247
--- src/sys/netinet6/icmp6.c:1.246 Mon Jul 27 14:52:55 2020
+++ src/sys/netinet6/icmp6.c Fri Sep 11 15:03:33 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: icmp6.c,v 1.246 2020/07/27 14:52:55 roy Exp $ */
+/* $NetBSD: icmp6.c,v 1.247 2020/09/11 15:03:33 roy Exp $ */
/* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
/*
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.246 2020/07/27 14:52:55 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.247 2020/09/11 15:03:33 roy Exp $");
#ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h"
@@ -87,6 +87,7 @@ __KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.
#include <net/route.h>
#include <net/if_dl.h>
#include <net/if_types.h>
+#include <net/nd.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
@@ -98,9 +99,9 @@ __KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.
#include <netinet6/icmp6_private.h>
#include <netinet6/mld6_var.h>
#include <netinet6/in6_pcb.h>
-#include <netinet6/nd6.h>
#include <netinet6/in6_ifattach.h>
#include <netinet6/ip6protosw.h>
+#include <netinet6/nd6.h>
#include <netinet6/scope6_var.h>
#ifdef IPSEC
@@ -2953,7 +2954,6 @@ out:
static void
sysctl_net_inet6_icmp6_setup(struct sysctllog **clog)
{
- extern int nd6_maxqueuelen; /* defined in nd6.c */
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT,
@@ -3008,23 +3008,37 @@ sysctl_net_inet6_icmp6_setup(struct sysc
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
CTLTYPE_INT, "nd6_delay",
SYSCTL_DESCR("First probe delay time"),
- NULL, 0, &nd6_delay, 0,
+ NULL, 0, &nd6_nd_domain.nd_delay, 0,
CTL_NET, PF_INET6, IPPROTO_ICMPV6,
ICMPV6CTL_ND6_DELAY, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+ CTLTYPE_INT, "nd6_mmaxtries",
+ SYSCTL_DESCR("Number of multicast discovery attempts"),
+ NULL, 0, &nd6_nd_domain.nd_mmaxtries, 0,
+ CTL_NET, PF_INET6, IPPROTO_ICMPV6,
+ ICMPV6CTL_ND6_MMAXTRIES, CTL_EOL);
+ sysctl_createv(clog, 0, NULL, NULL,
+ CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
CTLTYPE_INT, "nd6_umaxtries",
SYSCTL_DESCR("Number of unicast discovery attempts"),
- NULL, 0, &nd6_umaxtries, 0,
+ NULL, 0, &nd6_nd_domain.nd_umaxtries, 0,
CTL_NET, PF_INET6, IPPROTO_ICMPV6,
ICMPV6CTL_ND6_UMAXTRIES, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
- CTLTYPE_INT, "nd6_mmaxtries",
- SYSCTL_DESCR("Number of multicast discovery attempts"),
- NULL, 0, &nd6_mmaxtries, 0,
+ CTLTYPE_INT, "nd6_maxnudhint",
+ SYSCTL_DESCR("Maximum neighbor unreachable hint count"),
+ NULL, 0, &nd6_nd_domain.nd_maxnudhint, 0,
CTL_NET, PF_INET6, IPPROTO_ICMPV6,
- ICMPV6CTL_ND6_MMAXTRIES, CTL_EOL);
+ ICMPV6CTL_ND6_MAXNUDHINT, CTL_EOL);
+ sysctl_createv(clog, 0, NULL, NULL,
+ CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+ CTLTYPE_INT, "maxqueuelen",
+ SYSCTL_DESCR("max packet queue len for a unresolved ND"),
+ NULL, 1, &nd6_nd_domain.nd_maxqueuelen, 0,
+ CTL_NET, PF_INET6, IPPROTO_ICMPV6,
+ ICMPV6CTL_ND6_MAXQLEN, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
CTLTYPE_INT, "nd6_useloopback",
@@ -3056,13 +3070,6 @@ sysctl_net_inet6_icmp6_setup(struct sysc
ICMPV6CTL_ERRPPSLIMIT, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
- CTLTYPE_INT, "nd6_maxnudhint",
- SYSCTL_DESCR("Maximum neighbor unreachable hint count"),
- NULL, 0, &nd6_maxnudhint, 0,
- CTL_NET, PF_INET6, IPPROTO_ICMPV6,
- ICMPV6CTL_ND6_MAXNUDHINT, CTL_EOL);
- sysctl_createv(clog, 0, NULL, NULL,
- CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
CTLTYPE_INT, "mtudisc_hiwat",
SYSCTL_DESCR("Low mark on MTU Discovery route timers"),
NULL, 0, &icmp6_mtudisc_hiwat, 0,
@@ -3098,13 +3105,6 @@ sysctl_net_inet6_icmp6_setup(struct sysc
CTL_NET, PF_INET6, IPPROTO_ICMPV6,
OICMPV6CTL_ND6_PRLIST, CTL_EOL);
#endif
- sysctl_createv(clog, 0, NULL, NULL,
- CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
- CTLTYPE_INT, "maxqueuelen",
- SYSCTL_DESCR("max packet queue len for a unresolved ND"),
- NULL, 1, &nd6_maxqueuelen, 0,
- CTL_NET, PF_INET6, IPPROTO_ICMPV6,
- ICMPV6CTL_ND6_MAXQLEN, CTL_EOL);
}
void
Index: src/sys/netinet6/nd6.c
diff -u src/sys/netinet6/nd6.c:1.271 src/sys/netinet6/nd6.c:1.272
--- src/sys/netinet6/nd6.c:1.271 Fri Jun 12 11:04:45 2020
+++ src/sys/netinet6/nd6.c Fri Sep 11 15:03:33 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: nd6.c,v 1.271 2020/06/12 11:04:45 roy Exp $ */
+/* $NetBSD: nd6.c,v 1.272 2020/09/11 15:03:33 roy 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.271 2020/06/12 11:04:45 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.272 2020/09/11 15:03:33 roy Exp $");
#ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h"
@@ -62,6 +62,7 @@ __KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.27
#include <net/if_dl.h>
#include <net/if_llatbl.h>
#include <net/if_types.h>
+#include <net/nd.h>
#include <net/route.h>
#include <net/if_ether.h>
#include <net/if_arc.h>
@@ -86,19 +87,11 @@ __KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.27
/* timer values */
int nd6_prune = 1; /* walk list every 1 seconds */
-int nd6_delay = 5; /* delay first probe time 5 second */
-int nd6_umaxtries = 3; /* maximum unicast query */
-int nd6_mmaxtries = 3; /* maximum multicast query */
int nd6_useloopback = 1; /* use loopback interface for local traffic */
-int nd6_gctimer = (60 * 60 * 24); /* 1 day: garbage collection timer */
/* preventing too many loops in ND option parsing */
int nd6_maxndopt = 10; /* max # of ND options allowed */
-int nd6_maxnudhint = 0; /* max # of subsequent upper layer hints */
-
-int nd6_maxqueuelen = 1; /* max # of packets cached in unresolved ND entries */
-
#ifdef ND6_DEBUG
int nd6_debug = 1;
#else
@@ -111,10 +104,16 @@ int nd6_recalc_reachtm_interval = ND6_RE
static void nd6_slowtimo(void *);
static void nd6_free(struct llentry *, int);
-static void nd6_llinfo_timer(void *);
+static bool nd6_nud_enabled(struct ifnet *);
+static unsigned int nd6_llinfo_reachable(struct ifnet *);
+static unsigned int nd6_llinfo_retrans(struct ifnet *);
+static union nd_addr *nd6_llinfo_holdsrc(struct llentry *, union nd_addr *);
+static void nd6_llinfo_output(struct ifnet *, const union nd_addr *,
+ const union nd_addr *, const uint8_t *, const union nd_addr *);
+static void nd6_llinfo_missed(struct ifnet *, const union nd_addr *,
+ struct mbuf *);
static void nd6_timer(void *);
static void nd6_timer_work(struct work *, void *);
-static void clear_llinfo_pqueue(struct llentry *);
static struct nd_opt_hdr *nd6_option(union nd_opts *);
static callout_t nd6_slowtimo_ch;
@@ -122,6 +121,22 @@ static callout_t nd6_timer_ch;
static struct workqueue *nd6_timer_wq;
static struct work nd6_timer_wk;
+struct nd_domain nd6_nd_domain = {
+ .nd_family = AF_INET6,
+ .nd_delay = 5, /* delay first probe time 5 second */
+ .nd_mmaxtries = 3, /* maximum unicast query */
+ .nd_umaxtries = 3, /* maximum multicast query */
+ .nd_maxnudhint = 0, /* max # of subsequent upper layer hints */
+ .nd_maxqueuelen = 1, /* max # of packets in unresolved ND entries */
+ .nd_nud_enabled = nd6_nud_enabled,
+ .nd_reachable = nd6_llinfo_reachable,
+ .nd_retrans = nd6_llinfo_retrans,
+ .nd_holdsrc = nd6_llinfo_holdsrc,
+ .nd_output = nd6_llinfo_output,
+ .nd_missed = nd6_llinfo_missed,
+ .nd_free = nd6_free,
+};
+
MALLOC_DEFINE(M_IP6NDP, "NDP", "IPv6 Neighbour Discovery");
void
@@ -129,6 +144,7 @@ nd6_init(void)
{
int error;
+ nd_attach_domain(&nd6_nd_domain);
nd6_nbr_init();
rw_init(&nd6_lock);
@@ -326,44 +342,6 @@ skip1:
}
/*
- * ND6 timer routine to handle ND6 entries
- */
-void
-nd6_llinfo_settimer(struct llentry *ln, time_t xtick)
-{
-
- CTASSERT(sizeof(time_t) > sizeof(int));
- LLE_WLOCK_ASSERT(ln);
-
- KASSERT(xtick >= 0);
-
- /*
- * We have to take care of a reference leak which occurs if
- * callout_reset overwrites a pending callout schedule. Unfortunately
- * we don't have a mean to know the overwrite, so we need to know it
- * using callout_stop. We need to call callout_pending first to exclude
- * the case that the callout has never been scheduled.
- */
- if (callout_pending(&ln->la_timer)) {
- bool expired = callout_stop(&ln->la_timer);
- if (!expired)
- LLE_REMREF(ln);
- }
-
- ln->ln_expire = time_uptime + xtick / hz;
- LLE_ADDREF(ln);
- if (xtick > INT_MAX) {
- ln->ln_ntick = xtick - 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, xtick,
- nd6_llinfo_timer, ln);
- }
-}
-
-/*
* Gets source address of the first packet in hold queue
* and stores it in @src.
* Returns pointer to @src (if hold queue is not empty) or NULL.
@@ -389,148 +367,67 @@ nd6_llinfo_get_holdsrc(struct llentry *l
return src;
}
-static void
-nd6_llinfo_timer(void *arg)
+static union nd_addr *
+nd6_llinfo_holdsrc(struct llentry *ln, union nd_addr *src)
{
- struct llentry *ln = arg;
- struct ifnet *ifp;
- struct nd_kifinfo *ndi;
- bool send_ns = false;
- const struct in6_addr *daddr6 = NULL;
- const struct in6_addr *taddr6 = &ln->r_l3addr.addr6;
- struct sockaddr_in6 dsin6, tsin6;
- struct mbuf *m = NULL;
- bool missed = false;
-
- SOFTNET_KERNEL_LOCK_UNLESS_NET_MPSAFE();
-
- LLE_WLOCK(ln);
- if ((ln->la_flags & LLE_LINKED) == 0)
- goto out;
- if (ln->ln_ntick > 0) {
- nd6_llinfo_settimer(ln, ln->ln_ntick);
- goto out;
- }
-
- ifp = ln->lle_tbl->llt_ifp;
- KASSERT(ifp != NULL);
-
- ndi = ND_IFINFO(ifp);
- switch (ln->ln_state) {
- case ND6_LLINFO_WAITDELETE:
- LLE_REMREF(ln);
- nd6_free(ln, 0);
- ln = NULL;
- break;
-
- case ND6_LLINFO_INCOMPLETE:
- if (ln->ln_asked++ < nd6_mmaxtries) {
- send_ns = true;
- break;
- }
+ if (nd6_llinfo_get_holdsrc(ln, &src->nd_addr6) == NULL)
+ return NULL;
+ return src;
+}
- missed = true;
- sockaddr_in6_init(&tsin6, taddr6, 0, 0, 0);
+static void
+nd6_llinfo_output(struct ifnet *ifp, const union nd_addr *daddr,
+ const union nd_addr *taddr, __unused const uint8_t *tlladdr,
+ const union nd_addr *hsrc)
+{
- if (ln->ln_hold) {
- struct mbuf *m0;
+ nd6_ns_output(ifp, &daddr->nd_addr6, &taddr->nd_addr6,
+ &hsrc->nd_addr6, NULL);
+}
- m = ln->ln_hold;
+static bool
+nd6_nud_enabled(struct ifnet *ifp)
+{
+ struct nd_kifinfo *ndi = ND_IFINFO(ifp);
- /*
- * assuming every packet in ln_hold has
- * the same IP header
- */
- m0 = m->m_nextpkt;
- m->m_nextpkt = NULL;
- ln->ln_hold = m0;
- clear_llinfo_pqueue(ln);
- }
+ return ndi->flags & ND6_IFF_PERFORMNUD;
+}
- /*
- * Move to the ND6_LLINFO_WAITDELETE state for another
- * interval at which point the llentry will be freed
- * unless it's attempted to be used again and we'll
- * resend NS again, rinse and repeat.
- */
- ln->ln_state = ND6_LLINFO_WAITDELETE;
- if (ln->ln_asked == nd6_mmaxtries)
- nd6_llinfo_settimer(ln, ndi->retrans * hz / 1000);
- else
- send_ns = true;
- break;
+static unsigned int
+nd6_llinfo_reachable(struct ifnet *ifp)
+{
+ struct nd_kifinfo *ndi = ND_IFINFO(ifp);
- case ND6_LLINFO_REACHABLE:
- if (!ND6_LLINFO_PERMANENT(ln)) {
- ln->ln_state = ND6_LLINFO_STALE;
- nd6_llinfo_settimer(ln, nd6_gctimer * hz);
- }
- break;
+ return ndi->reachable;
+}
- case ND6_LLINFO_PURGE:
- case ND6_LLINFO_STALE:
- /* Garbage Collection(RFC 2461 5.3) */
- if (!ND6_LLINFO_PERMANENT(ln)) {
- LLE_REMREF(ln);
- nd6_free(ln, 1);
- ln = NULL;
- }
- break;
+static unsigned int
+nd6_llinfo_retrans(struct ifnet *ifp)
+{
+ struct nd_kifinfo *ndi = ND_IFINFO(ifp);
- case ND6_LLINFO_DELAY:
- if (ndi->flags & ND6_IFF_PERFORMNUD) {
- /* We need NUD */
- ln->ln_asked = 1;
- ln->ln_state = ND6_LLINFO_PROBE;
- daddr6 = &ln->r_l3addr.addr6;
- send_ns = true;
- } else {
- ln->ln_state = ND6_LLINFO_STALE; /* XXX */
- nd6_llinfo_settimer(ln, nd6_gctimer * hz);
- }
- break;
- case ND6_LLINFO_PROBE:
- if (ln->ln_asked < nd6_umaxtries) {
- ln->ln_asked++;
- daddr6 = &ln->r_l3addr.addr6;
- send_ns = true;
- } else {
- LLE_REMREF(ln);
- nd6_free(ln, 0);
- ln = NULL;
- }
- break;
- }
+ return ndi->retrans;
+}
- if (send_ns) {
- struct in6_addr src, *psrc;
+static void
+nd6_llinfo_missed(struct ifnet *ifp, const union nd_addr *taddr, struct mbuf *m)
+{
+ struct in6_addr mdaddr6 = zeroin6_addr;
+ struct sockaddr_in6 dsin6, tsin6;
+ struct sockaddr *sa;
- nd6_llinfo_settimer(ln, ndi->retrans * hz / 1000);
- psrc = nd6_llinfo_get_holdsrc(ln, &src);
- LLE_FREE_LOCKED(ln);
- ln = NULL;
- nd6_ns_output(ifp, daddr6, taddr6, psrc, NULL);
- }
+ if (m != NULL)
+ icmp6_error2(m, ICMP6_DST_UNREACH,
+ ICMP6_DST_UNREACH_ADDR, 0, ifp, &mdaddr6);
+ if (!IN6_IS_ADDR_UNSPECIFIED(&mdaddr6)) {
+ sockaddr_in6_init(&dsin6, &mdaddr6, 0, 0, 0);
+ sa = sin6tosa(&dsin6);
+ } else
+ sa = NULL;
-out:
- if (ln != NULL)
- LLE_FREE_LOCKED(ln);
- SOFTNET_KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
- if (missed) {
- struct in6_addr mdaddr6 = zeroin6_addr;
- struct sockaddr *sa;
-
- if (m != NULL)
- icmp6_error2(m, ICMP6_DST_UNREACH,
- ICMP6_DST_UNREACH_ADDR, 0, ifp, &mdaddr6);
- if (!IN6_IS_ADDR_UNSPECIFIED(&mdaddr6)) {
- sockaddr_in6_init(&dsin6, &mdaddr6, 0, 0, 0);
- sa = sin6tosa(&dsin6);
- } else
- sa = NULL;
- rt_clonedmsg(RTM_MISS, sa, sin6tosa(&tsin6), NULL, ifp);
- }
+ sockaddr_in6_init(&tsin6, &taddr->nd_addr6, 0, 0, 0);
+ rt_clonedmsg(RTM_MISS, sa, sin6tosa(&tsin6), NULL, ifp);
}
/*
@@ -675,7 +572,7 @@ nd6_create(const struct in6_addr *addr6,
if (rt != NULL)
rt_unref(rt);
if (ln != NULL)
- ln->ln_state = ND6_LLINFO_NOSTATE;
+ ln->ln_state = ND_LLINFO_NOSTATE;
return ln;
}
@@ -822,13 +719,9 @@ nd6_free(struct llentry *ln, int gc)
* but we intentionally keep it just in case.
*/
if (!ip6_forwarding && ln->ln_router &&
- ln->ln_state == ND6_LLINFO_STALE && gc)
+ ln->ln_state == ND_LLINFO_STALE && gc)
{
- if (ln->ln_expire > time_uptime)
- nd6_llinfo_settimer(ln,
- (ln->ln_expire - time_uptime) * hz);
- else
- nd6_llinfo_settimer(ln, nd6_gctimer * hz);
+ nd_set_timer(ln, ND_TIMER_EXPIRE);
LLE_WUNLOCK(ln);
return;
}
@@ -874,28 +767,7 @@ nd6_nud_hint(struct rtentry *rt)
ifp = rt->rt_ifp;
ln = nd6_lookup(&(satocsin6(rt_getkey(rt)))->sin6_addr, ifp, true);
- if (ln == NULL)
- return;
-
- if (ln->ln_state < ND6_LLINFO_REACHABLE)
- goto done;
-
- /*
- * if we get upper-layer reachability confirmation many times,
- * it is possible we have false information.
- */
- ln->ln_byhint++;
- if (ln->ln_byhint > nd6_maxnudhint)
- goto done;
-
- ln->ln_state = ND6_LLINFO_REACHABLE;
- if (!ND6_LLINFO_PERMANENT(ln))
- nd6_llinfo_settimer(ln, ND_IFINFO(rt->rt_ifp)->reachable * hz);
-
-done:
- LLE_WUNLOCK(ln);
-
- return;
+ nd_nud_hint(ln);
}
struct gc_args {
@@ -913,18 +785,18 @@ nd6_purge_entry(struct lltable *llt, str
if (*n <= 0)
return 0;
- if (ND6_LLINFO_PERMANENT(ln))
+ if (ND_IS_LLINFO_PERMANENT(ln))
return 0;
if (IN6_ARE_ADDR_EQUAL(&ln->r_l3addr.addr6, skip_in6))
return 0;
LLE_WLOCK(ln);
- if (ln->ln_state > ND6_LLINFO_INCOMPLETE)
- ln->ln_state = ND6_LLINFO_STALE;
+ if (ln->ln_state > ND_LLINFO_INCOMPLETE)
+ ln->ln_state = ND_LLINFO_STALE;
else
- ln->ln_state = ND6_LLINFO_PURGE;
- nd6_llinfo_settimer(ln, 0);
+ ln->ln_state = ND_LLINFO_PURGE;
+ nd_set_timer(ln, ND_TIMER_IMMEDIATE);
LLE_WUNLOCK(ln);
(*n)--;
@@ -1524,15 +1396,15 @@ nd6_cache_lladdr(
if ((!olladdr && lladdr) || /* (3) */
(olladdr && lladdr && llchange)) { /* (5) */
do_update = 1;
- newstate = ND6_LLINFO_STALE;
+ newstate = ND_LLINFO_STALE;
} else /* (1-2,4) */
do_update = 0;
} else {
do_update = 1;
if (lladdr == NULL) /* (6) */
- newstate = ND6_LLINFO_NOSTATE;
+ newstate = ND_LLINFO_NOSTATE;
else /* (7) */
- newstate = ND6_LLINFO_STALE;
+ newstate = ND_LLINFO_STALE;
}
if (do_update) {
@@ -1541,19 +1413,19 @@ nd6_cache_lladdr(
*/
ln->ln_state = newstate;
- if (ln->ln_state == ND6_LLINFO_STALE) {
+ if (ln->ln_state == ND_LLINFO_STALE) {
/*
* XXX: since nd6_output() below will cause
* state tansition to DELAY and reset the timer,
* we must set the timer now, although it is actually
* meaningless.
*/
- nd6_llinfo_settimer(ln, nd6_gctimer * hz);
+ nd_set_timer(ln, ND_TIMER_GC);
nd6_llinfo_release_pkts(ln, ifp);
- } else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
+ } else if (ln->ln_state == ND_LLINFO_INCOMPLETE) {
/* probe right away */
- nd6_llinfo_settimer((void *)ln, 0);
+ nd_set_timer(ln, ND_TIMER_IMMEDIATE);
}
}
@@ -1704,7 +1576,7 @@ nd6_resolve(struct ifnet *ifp, const str
ln = nd6_lookup(&dst->sin6_addr, ifp, false);
if (ln != NULL && (ln->la_flags & LLE_VALID) != 0 &&
- ln->ln_state == ND6_LLINFO_REACHABLE) {
+ ln->ln_state == ND_LLINFO_REACHABLE) {
/* Fast path */
memcpy(lldst, &ln->ll_addr, MIN(dstsize, ifp->if_addrlen));
LLE_RUNLOCK(ln);
@@ -1739,92 +1611,7 @@ nd6_resolve(struct ifnet *ifp, const str
return ENETDOWN; /* better error? */
}
- LLE_WLOCK_ASSERT(ln);
-
- /* We don't have to do link-layer address resolution on a p2p link. */
- if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
- ln->ln_state < ND6_LLINFO_REACHABLE) {
- ln->ln_state = ND6_LLINFO_STALE;
- nd6_llinfo_settimer(ln, nd6_gctimer * hz);
- }
-
- /*
- * The first time we send a packet to a neighbor whose entry is
- * STALE, we have to change the state to DELAY and a sets a timer to
- * expire in DELAY_FIRST_PROBE_TIME seconds to ensure do
- * neighbor unreachability detection on expiration.
- * (RFC 2461 7.3.3)
- */
- if (ln->ln_state == ND6_LLINFO_STALE) {
- ln->ln_asked = 0;
- ln->ln_state = ND6_LLINFO_DELAY;
- nd6_llinfo_settimer(ln, nd6_delay * hz);
- }
-
- /*
- * If the neighbor cache entry has a state other than INCOMPLETE
- * (i.e. its link-layer address is already resolved), just
- * send the packet.
- */
- if (ln->ln_state > ND6_LLINFO_INCOMPLETE) {
- KASSERT((ln->la_flags & LLE_VALID) != 0);
- memcpy(lldst, &ln->ll_addr, MIN(dstsize, ifp->if_addrlen));
- LLE_WUNLOCK(ln);
- return 0;
- }
-
- /*
- * There is a neighbor cache entry, but no ethernet address
- * response yet. Append this latest packet to the end of the
- * packet queue in the mbuf, unless the number of the packet
- * does not exceed nd6_maxqueuelen. When it exceeds nd6_maxqueuelen,
- * the oldest packet in the queue will be removed.
- */
- if (ln->ln_state == ND6_LLINFO_NOSTATE ||
- ln->ln_state == ND6_LLINFO_WAITDELETE)
- ln->ln_state = ND6_LLINFO_INCOMPLETE;
- if (ln->ln_hold) {
- struct mbuf *m_hold;
- int i;
-
- i = 0;
- for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold->m_nextpkt) {
- i++;
- if (m_hold->m_nextpkt == NULL) {
- m_hold->m_nextpkt = m;
- break;
- }
- }
- while (i >= nd6_maxqueuelen) {
- m_hold = ln->ln_hold;
- ln->ln_hold = ln->ln_hold->m_nextpkt;
- m_freem(m_hold);
- i--;
- }
- } else {
- ln->ln_hold = m;
- }
-
- if (ln->ln_asked >= nd6_mmaxtries)
- error = (rt != NULL && rt->rt_flags & RTF_GATEWAY) ?
- EHOSTUNREACH : EHOSTDOWN;
- else
- error = EWOULDBLOCK;
-
- /*
- * If there has been no NS for the neighbor after entering the
- * INCOMPLETE state, send the first solicitation.
- */
- if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) {
- struct in6_addr src, *psrc;
-
- ln->ln_asked++;
- nd6_llinfo_settimer(ln, ndi->retrans * hz / 1000);
- psrc = nd6_llinfo_get_holdsrc(ln, &src);
- LLE_WUNLOCK(ln);
- nd6_ns_output(ifp, NULL, &dst->sin6_addr, psrc, NULL);
- } else
- LLE_WUNLOCK(ln);
+ error = nd_resolve(ln, rt, m, lldst, dstsize);
if (created)
nd6_gc_neighbors(LLTABLE6(ifp), &dst->sin6_addr);
@@ -1856,21 +1643,6 @@ nd6_need_cache(struct ifnet *ifp)
}
}
-static void
-clear_llinfo_pqueue(struct llentry *ln)
-{
- struct mbuf *m_hold, *m_hold_next;
-
- for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold_next) {
- m_hold_next = m_hold->m_nextpkt;
- m_hold->m_nextpkt = NULL;
- m_freem(m_hold);
- }
-
- ln->ln_hold = NULL;
- return;
-}
-
int
nd6_sysctl(
int name,
Index: src/sys/netinet6/nd6.h
diff -u src/sys/netinet6/nd6.h:1.90 src/sys/netinet6/nd6.h:1.91
--- src/sys/netinet6/nd6.h:1.90 Thu Aug 20 11:01:02 2020
+++ src/sys/netinet6/nd6.h Fri Sep 11 15:03:33 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: nd6.h,v 1.90 2020/08/20 11:01:02 roy Exp $ */
+/* $NetBSD: nd6.h,v 1.91 2020/09/11 15:03:33 roy Exp $ */
/* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */
/*
@@ -36,17 +36,18 @@
#include <sys/queue.h>
#include <sys/callout.h>
-#define ND6_LLINFO_PURGE -3
-#define ND6_LLINFO_NOSTATE -2
-#define ND6_LLINFO_WAITDELETE -1
-#define ND6_LLINFO_INCOMPLETE 0
-#define ND6_LLINFO_REACHABLE 1
-#define ND6_LLINFO_STALE 2
-#define ND6_LLINFO_DELAY 3
-#define ND6_LLINFO_PROBE 4
-
-#define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE)
-#define ND6_LLINFO_PERMANENT(n) (((n)->ln_expire == 0) && ((n)->ln_state > ND6_LLINFO_INCOMPLETE))
+#ifndef _KERNEL
+/* Backwards compat */
+#include <net/nd.h>
+#define ND6_LLINFO_PURGE ND_LLINFO_PURGE
+#define ND6_LLINFO_NOSTATE ND_LLINFO_NOSTATE
+#define ND6_LLINFO_WAITDELETE ND_LLINFO_WAITDELETE
+#define ND6_LLINFO_INCOMPLETE ND_LLINFO_INCOMPLETE
+#define ND6_LLINFO_REACHABLE ND_LLINFO_REACHABLE
+#define ND6_LLINFO_STALE ND_LLINFO_STALE
+#define ND6_LLINFO_DELAY ND_LLINFO_DELAY
+#define ND6_LLINFO_PROBE ND_LLINFO_PROBE
+#endif
struct nd_ifinfo {
uint8_t chlim; /* CurHopLimit */
@@ -98,29 +99,16 @@ struct in6_ndireq {
#define ND6_INFINITE_LIFETIME ((u_int32_t)~0)
#ifdef _KERNEL
-/* node constants */
-#define MAX_REACHABLE_TIME 3600000 /* msec */
-#define REACHABLE_TIME 30000 /* msec */
-#define RETRANS_TIMER 1000 /* msec */
-#define MIN_RANDOM_FACTOR 512 /* 1024 * 0.5 */
-#define MAX_RANDOM_FACTOR 1536 /* 1024 * 1.5 */
-#define ND_COMPUTE_RTIME(x) \
- (((MIN_RANDOM_FACTOR * (x >> 10)) + (cprng_fast32() & \
- ((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000)
-
#include <sys/mallocvar.h>
MALLOC_DECLARE(M_IP6NDP);
/* nd6.c */
extern int nd6_prune;
-extern int nd6_delay;
-extern int nd6_umaxtries;
-extern int nd6_mmaxtries;
extern int nd6_useloopback;
-extern int nd6_maxnudhint;
-extern int nd6_gctimer;
extern int nd6_debug;
+extern struct nd_domain nd6_nd_domain;
+
#define nd6log(level, fmt, args...) \
do { if (nd6_debug) log(level, "%s: " fmt, __func__, ##args);} while (0)
@@ -181,7 +169,6 @@ void nd6_option_init(void *, int, union
int nd6_options(union nd_opts *);
struct llentry *nd6_lookup(const struct in6_addr *, const struct ifnet *, bool);
struct llentry *nd6_create(const struct in6_addr *, const struct ifnet *);
-void nd6_llinfo_settimer(struct llentry *, time_t);
void nd6_purge(struct ifnet *, struct in6_ifextra *);
void nd6_nud_hint(struct rtentry *);
int nd6_resolve(struct ifnet *, const struct rtentry *, struct mbuf *,
Index: src/sys/netinet6/nd6_nbr.c
diff -u src/sys/netinet6/nd6_nbr.c:1.180 src/sys/netinet6/nd6_nbr.c:1.181
--- src/sys/netinet6/nd6_nbr.c:1.180 Thu Aug 20 11:01:02 2020
+++ src/sys/netinet6/nd6_nbr.c Fri Sep 11 15:03:33 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: nd6_nbr.c,v 1.180 2020/08/20 11:01:02 roy Exp $ */
+/* $NetBSD: nd6_nbr.c,v 1.181 2020/09/11 15:03:33 roy 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.180 2020/08/20 11:01:02 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.181 2020/09/11 15:03:33 roy Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -57,6 +57,8 @@ __KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v
#include <net/if.h>
#include <net/if_types.h>
#include <net/if_dl.h>
+#include <net/if_llatbl.h>
+#include <net/nd.h>
#include <net/route.h>
#include <netinet/in.h>
@@ -735,7 +737,7 @@ nd6_na_input(struct mbuf *m, int off, in
goto freeit;
rt_cmd = 0;
- if (ln->ln_state <= ND6_LLINFO_INCOMPLETE) {
+ if (ln->ln_state <= ND_LLINFO_INCOMPLETE) {
/*
* If the link-layer has address, and no lladdr option came,
* discard the packet.
@@ -750,15 +752,13 @@ nd6_na_input(struct mbuf *m, int off, in
ln->la_flags |= LLE_VALID;
rt_cmd = RTM_ADD;
if (is_solicited) {
- ln->ln_state = ND6_LLINFO_REACHABLE;
+ ln->ln_state = ND_LLINFO_REACHABLE;
ln->ln_byhint = 0;
- if (!ND6_LLINFO_PERMANENT(ln)) {
- nd6_llinfo_settimer(ln,
- ND_IFINFO(ln->lle_tbl->llt_ifp)->reachable * hz);
- }
+ if (!ND_IS_LLINFO_PERMANENT(ln))
+ nd_set_timer(ln, ND_TIMER_REACHABLE);
} else {
- ln->ln_state = ND6_LLINFO_STALE;
- nd6_llinfo_settimer(ln, nd6_gctimer * hz);
+ ln->ln_state = ND_LLINFO_STALE;
+ nd_set_timer(ln, ND_TIMER_GC);
}
} else {
bool llchange;
@@ -804,9 +804,9 @@ nd6_na_input(struct mbuf *m, int off, in
* 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(ln, nd6_gctimer * hz);
+ if (ln->ln_state == ND_LLINFO_REACHABLE) {
+ ln->ln_state = ND_LLINFO_STALE;
+ nd_set_timer(ln, ND_TIMER_GC);
}
goto freeit;
} else if (is_override /* (2a) */
@@ -826,17 +826,14 @@ nd6_na_input(struct mbuf *m, int off, in
* changed, make it STALE.
*/
if (is_solicited) {
- ln->ln_state = ND6_LLINFO_REACHABLE;
+ ln->ln_state = ND_LLINFO_REACHABLE;
ln->ln_byhint = 0;
- if (!ND6_LLINFO_PERMANENT(ln)) {
- nd6_llinfo_settimer(ln,
- ND_IFINFO(ifp)->reachable * hz);
- }
+ if (!ND_IS_LLINFO_PERMANENT(ln))
+ nd_set_timer(ln, ND_TIMER_REACHABLE);
} else {
if (lladdr && llchange) {
- ln->ln_state = ND6_LLINFO_STALE;
- nd6_llinfo_settimer(ln,
- nd6_gctimer * hz);
+ ln->ln_state = ND_LLINFO_STALE;
+ nd_set_timer(ln, ND_TIMER_GC);
}
}
}