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);
 				}
 			}
 		}

Reply via email to