Module Name:    src
Committed By:   ozaki-r
Date:           Tue Feb 14 03:05:06 UTC 2017

Modified Files:
        src/sys/dist/pf/net: pf.c
        src/sys/external/bsd/ipf/netinet: ip_fil_netbsd.c
        src/sys/net: if_arcsubr.c if_ethersubr.c if_fddisubr.c
            if_ieee1394subr.c if_srt.c
        src/sys/netinet6: in6_offload.c ip6_forward.c ip6_mroute.c ip6_output.c
            ip6_var.h nd6.c nd6.h

Log Message:
Do ND in L2_output in the same manner as arpresolve

The benefits of this change are:
- The flow is consistent with IPv4 (and FreeBSD and OpenBSD)
  - old: ip6_output => nd6_output (do ND if needed) => L2_output (lookup a 
stored cache)
  - new: ip6_output => L2_output (lookup a cache. Do ND if cache not found)
- We can remove some workarounds in nd6_output
- We can move L2 specific operations to their own place
- The performance slightly improves because one cache lookup is reduced


To generate a diff of this commit:
cvs rdiff -u -r1.75 -r1.76 src/sys/dist/pf/net/pf.c
cvs rdiff -u -r1.21 -r1.22 src/sys/external/bsd/ipf/netinet/ip_fil_netbsd.c
cvs rdiff -u -r1.76 -r1.77 src/sys/net/if_arcsubr.c
cvs rdiff -u -r1.237 -r1.238 src/sys/net/if_ethersubr.c
cvs rdiff -u -r1.104 -r1.105 src/sys/net/if_fddisubr.c
cvs rdiff -u -r1.58 -r1.59 src/sys/net/if_ieee1394subr.c
cvs rdiff -u -r1.25 -r1.26 src/sys/net/if_srt.c
cvs rdiff -u -r1.6 -r1.7 src/sys/netinet6/in6_offload.c
cvs rdiff -u -r1.85 -r1.86 src/sys/netinet6/ip6_forward.c
cvs rdiff -u -r1.116 -r1.117 src/sys/netinet6/ip6_mroute.c
cvs rdiff -u -r1.182 -r1.183 src/sys/netinet6/ip6_output.c
cvs rdiff -u -r1.71 -r1.72 src/sys/netinet6/ip6_var.h
cvs rdiff -u -r1.226 -r1.227 src/sys/netinet6/nd6.c
cvs rdiff -u -r1.81 -r1.82 src/sys/netinet6/nd6.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dist/pf/net/pf.c
diff -u src/sys/dist/pf/net/pf.c:1.75 src/sys/dist/pf/net/pf.c:1.76
--- src/sys/dist/pf/net/pf.c:1.75	Thu Dec  8 05:16:33 2016
+++ src/sys/dist/pf/net/pf.c	Tue Feb 14 03:05:06 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: pf.c,v 1.75 2016/12/08 05:16:33 ozaki-r Exp $	*/
+/*	$NetBSD: pf.c,v 1.76 2017/02/14 03:05:06 ozaki-r Exp $	*/
 /*	$OpenBSD: pf.c,v 1.552.2.1 2007/11/27 16:37:57 henning Exp $ */
 
 /*
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pf.c,v 1.75 2016/12/08 05:16:33 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pf.c,v 1.76 2017/02/14 03:05:06 ozaki-r Exp $");
 
 #include "pflog.h"
 
@@ -5553,7 +5553,7 @@ pf_route6(struct mbuf **m, struct pf_rul
 	if (IN6_IS_SCOPE_EMBEDDABLE(&dst.sin6_addr))
 		dst.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
 	if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
-		(void)nd6_output(ifp, ifp, m0, &dst, NULL);
+		(void)ip6_if_output(ifp, ifp, m0, &dst, NULL);
 	} else {
 		in6_ifstat_inc(ifp, ifs6_in_toobig);
 		if (r->rt != PF_DUPTO)

Index: src/sys/external/bsd/ipf/netinet/ip_fil_netbsd.c
diff -u src/sys/external/bsd/ipf/netinet/ip_fil_netbsd.c:1.21 src/sys/external/bsd/ipf/netinet/ip_fil_netbsd.c:1.22
--- src/sys/external/bsd/ipf/netinet/ip_fil_netbsd.c:1.21	Wed Dec 28 19:53:02 2016
+++ src/sys/external/bsd/ipf/netinet/ip_fil_netbsd.c	Tue Feb 14 03:05:06 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_fil_netbsd.c,v 1.21 2016/12/28 19:53:02 christos Exp $	*/
+/*	$NetBSD: ip_fil_netbsd.c,v 1.22 2017/02/14 03:05:06 ozaki-r Exp $	*/
 
 /*
  * Copyright (C) 2012 by Darren Reed.
@@ -8,7 +8,7 @@
 #if !defined(lint)
 #if defined(__NetBSD__)
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_fil_netbsd.c,v 1.21 2016/12/28 19:53:02 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_fil_netbsd.c,v 1.22 2017/02/14 03:05:06 ozaki-r Exp $");
 #else
 static const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-2000 Darren Reed";
 static const char rcsid[] = "@(#)Id: ip_fil_netbsd.c,v 1.1.1.2 2012/07/22 13:45:17 darrenr Exp";
@@ -1478,7 +1478,7 @@ ipf_fastroute6(struct mbuf *m0, struct m
 # endif
 		if ((error == 0) && (m0->m_pkthdr.len <= mtu)) {
 # if __NetBSD_Version__ >= 499001100
-			error = nd6_output(ifp, ifp, m0, satocsin6(dst), rt);
+			error = ip6_if_output(ifp, ifp, m0, satocsin6(dst), rt);
 # else
 			error = nd6_output(ifp, ifp, m0, dst6, rt);
 # endif

Index: src/sys/net/if_arcsubr.c
diff -u src/sys/net/if_arcsubr.c:1.76 src/sys/net/if_arcsubr.c:1.77
--- src/sys/net/if_arcsubr.c:1.76	Tue Jan 24 18:37:20 2017
+++ src/sys/net/if_arcsubr.c	Tue Feb 14 03:05:06 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_arcsubr.c,v 1.76 2017/01/24 18:37:20 maxv Exp $	*/
+/*	$NetBSD: if_arcsubr.c,v 1.77 2017/02/14 03:05:06 ozaki-r Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995 Ignatios Souvatzis
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_arcsubr.c,v 1.76 2017/01/24 18:37:20 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_arcsubr.c,v 1.77 2017/02/14 03:05:06 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -218,8 +218,14 @@ arc_output(struct ifnet *ifp, struct mbu
 #endif
 #ifdef INET6
 	case AF_INET6:
-		if (!nd6_storelladdr(ifp, rt, m, dst, &adst, sizeof(adst)))
-			return (0); /* it must be impossible, but... */
+		if (m->m_flags & M_MCAST) {
+			adst = 0;
+		} else {
+			error = nd6_resolve(ifp, rt, m, dst, &adst,
+			    sizeof(adst));
+			if (error != 0)
+				return error == EWOULDBLOCK ? 0 : error;
+		}
 		atype = htons(ARCTYPE_INET6);
 		newencoding = 1;
 		break;

Index: src/sys/net/if_ethersubr.c
diff -u src/sys/net/if_ethersubr.c:1.237 src/sys/net/if_ethersubr.c:1.238
--- src/sys/net/if_ethersubr.c:1.237	Sun Feb 12 09:36:05 2017
+++ src/sys/net/if_ethersubr.c	Tue Feb 14 03:05:06 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_ethersubr.c,v 1.237 2017/02/12 09:36:05 skrll Exp $	*/
+/*	$NetBSD: if_ethersubr.c,v 1.238 2017/02/14 03:05:06 ozaki-r Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.237 2017/02/12 09:36:05 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.238 2017/02/14 03:05:06 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -303,9 +303,16 @@ ether_output(struct ifnet * const ifp0, 
 #endif
 #ifdef INET6
 	case AF_INET6:
-		if (!nd6_storelladdr(ifp, rt, m, dst, edst, sizeof(edst))){
-			/* something bad happened */
-			return (0);
+		if (m->m_flags & M_BCAST)
+			(void)memcpy(edst, etherbroadcastaddr, sizeof(edst));
+		else if (m->m_flags & M_MCAST) {
+			ETHER_MAP_IPV6_MULTICAST(&satocsin6(dst)->sin6_addr,
+			    edst);
+		} else {
+			error = nd6_resolve(ifp, rt, m, dst, edst,
+			    sizeof(edst));
+			if (error != 0)
+				return error == EWOULDBLOCK ? 0 : error;
 		}
 		etype = htons(ETHERTYPE_IPV6);
 		break;

Index: src/sys/net/if_fddisubr.c
diff -u src/sys/net/if_fddisubr.c:1.104 src/sys/net/if_fddisubr.c:1.105
--- src/sys/net/if_fddisubr.c:1.104	Tue Jan 24 18:37:20 2017
+++ src/sys/net/if_fddisubr.c	Tue Feb 14 03:05:06 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_fddisubr.c,v 1.104 2017/01/24 18:37:20 maxv Exp $	*/
+/*	$NetBSD: if_fddisubr.c,v 1.105 2017/02/14 03:05:06 ozaki-r Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -96,7 +96,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_fddisubr.c,v 1.104 2017/01/24 18:37:20 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_fddisubr.c,v 1.105 2017/02/14 03:05:06 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_gateway.h"
@@ -250,9 +250,18 @@ fddi_output(struct ifnet *ifp0, struct m
 #endif
 #ifdef INET6
 	case AF_INET6:
-		if (!nd6_storelladdr(ifp, rt, m, dst, edst, sizeof(edst))){
-			/* something bad happened */
-			return (0);
+		if (m->m_flags & M_BCAST)
+			(void)memcpy(edst, fddibroadcastaddr, sizeof(edst));
+		else if (m->m_flags & M_MCAST) {
+			ETHER_MAP_IPV6_MULTICAST(&satocsin6(dst)->sin6_addr,
+			    edst);
+		} else {
+			error = nd6_resolve(ifp, rt, m, dst, edst,
+			    sizeof(edst));
+			if (error != 0) {
+				error = error == EWOULDBLOCK ? 0 : error;
+				return error;
+			}
 		}
 		etype = htons(ETHERTYPE_IPV6);
 		break;

Index: src/sys/net/if_ieee1394subr.c
diff -u src/sys/net/if_ieee1394subr.c:1.58 src/sys/net/if_ieee1394subr.c:1.59
--- src/sys/net/if_ieee1394subr.c:1.58	Mon Oct  3 11:06:06 2016
+++ src/sys/net/if_ieee1394subr.c	Tue Feb 14 03:05:06 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_ieee1394subr.c,v 1.58 2016/10/03 11:06:06 ozaki-r Exp $	*/
+/*	$NetBSD: if_ieee1394subr.c,v 1.59 2017/02/14 03:05:06 ozaki-r Exp $	*/
 
 /*
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ieee1394subr.c,v 1.58 2016/10/03 11:06:06 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ieee1394subr.c,v 1.59 2017/02/14 03:05:06 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -154,10 +154,21 @@ ieee1394_output(struct ifnet *ifp, struc
 #endif /* INET */
 #ifdef INET6
 	case AF_INET6:
-		if (unicast && (!nd6_storelladdr(ifp, rt, m0, dst,
-		    hwdst->iha_uid, IEEE1394_ADDR_LEN))) {
-			/* something bad happened */
-			return 0;
+#if 0
+		/*
+		 * XXX This code was in nd6_storelladdr, which was replaced with
+		 * nd6_resolve, but it never be used because nd6_storelladdr was
+		 * called only if unicast. Should it be enabled?
+		 */
+		if (m0->m_flags & M_BCAST)
+			memcpy(hwdst->iha_uid, ifp->if_broadcastaddr,
+			    MIN(IEEE1394_ADDR_LEN, ifp->if_addrlen));
+#endif
+		if (unicast) {
+			error = nd6_resolve(ifp, rt, m0, dst, hwdst->iha_uid,
+			    IEEE1394_ADDR_LEN);
+			if (error != 0)
+				return error == EWOULDBLOCK ? 0 : error;
 		}
 		etype = htons(ETHERTYPE_IPV6);
 		break;

Index: src/sys/net/if_srt.c
diff -u src/sys/net/if_srt.c:1.25 src/sys/net/if_srt.c:1.26
--- src/sys/net/if_srt.c:1.25	Thu Feb  9 11:43:32 2017
+++ src/sys/net/if_srt.c	Tue Feb 14 03:05:06 2017
@@ -1,8 +1,8 @@
-/* $NetBSD: if_srt.c,v 1.25 2017/02/09 11:43:32 kre Exp $ */
+/* $NetBSD: if_srt.c,v 1.26 2017/02/14 03:05:06 ozaki-r Exp $ */
 /* This file is in the public domain. */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_srt.c,v 1.25 2017/02/09 11:43:32 kre Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_srt.c,v 1.26 2017/02/14 03:05:06 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -36,6 +36,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_srt.c,v 1
 #include <netinet/ip.h>
 #include <netinet/ip6.h>
 #include <netinet6/in6_var.h>
+#include <netinet6/ip6_var.h>
 #include <netinet6/nd6.h>
 #include <netinet6/scope6_var.h>
 #include <net/if_types.h>
@@ -240,7 +241,7 @@ srt_if_output(
 	}
 	/* XXX is 0 the right last arg here? */
 	if (to->sa_family == AF_INET6)
-		return nd6_output(r->u.dstifp, r->u.dstifp, m, &r->dst.sin6, 0);
+		return ip6_if_output(r->u.dstifp, r->u.dstifp, m, &r->dst.sin6, 0);
 	return if_output_lock(r->u.dstifp, r->u.dstifp, m, &r->dst.sa, 0);
 }
 

Index: src/sys/netinet6/in6_offload.c
diff -u src/sys/netinet6/in6_offload.c:1.6 src/sys/netinet6/in6_offload.c:1.7
--- src/sys/netinet6/in6_offload.c:1.6	Mon Apr 25 22:07:57 2011
+++ src/sys/netinet6/in6_offload.c	Tue Feb 14 03:05:06 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_offload.c,v 1.6 2011/04/25 22:07:57 yamt Exp $	*/
+/*	$NetBSD: in6_offload.c,v 1.7 2017/02/14 03:05:06 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c)2006 YAMAMOTO Takashi,
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_offload.c,v 1.6 2011/04/25 22:07:57 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_offload.c,v 1.7 2017/02/14 03:05:06 ozaki-r Exp $");
 
 #include <sys/param.h>
 #include <sys/mbuf.h>
@@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: in6_offload.
 #include <netinet/ip6.h>
 #include <netinet/tcp.h>
 #include <netinet6/in6_var.h>
+#include <netinet6/ip6_var.h>
 #include <netinet6/nd6.h>
 #include <netinet6/in6_offload.h>
 
@@ -56,7 +57,7 @@ ip6_tso_output_callback(void *vp, struct
 {
 	struct ip6_tso_output_args *args = vp;
 
-	return nd6_output(args->ifp, args->origifp, m, args->dst, args->rt);
+	return ip6_if_output(args->ifp, args->origifp, m, args->dst, args->rt);
 }
 
 int

Index: src/sys/netinet6/ip6_forward.c
diff -u src/sys/netinet6/ip6_forward.c:1.85 src/sys/netinet6/ip6_forward.c:1.86
--- src/sys/netinet6/ip6_forward.c:1.85	Mon Jan 16 15:44:47 2017
+++ src/sys/netinet6/ip6_forward.c	Tue Feb 14 03:05:06 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_forward.c,v 1.85 2017/01/16 15:44:47 christos Exp $	*/
+/*	$NetBSD: ip6_forward.c,v 1.86 2017/02/14 03:05:06 ozaki-r Exp $	*/
 /*	$KAME: ip6_forward.c,v 1.109 2002/09/11 08:10:17 sakane Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_forward.c,v 1.85 2017/01/16 15:44:47 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_forward.c,v 1.86 2017/02/14 03:05:06 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_gateway.h"
@@ -401,7 +401,7 @@ ip6_forward(struct mbuf *m, int srcrt)
 		goto freecopy;
 	ip6 = mtod(m, struct ip6_hdr *);
 
-	error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
+	error = ip6_if_output(rt->rt_ifp, origifp, m, dst, rt);
 	if (error) {
 		in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard);
 		IP6_STATINC(IP6_STAT_CANTFORWARD);

Index: src/sys/netinet6/ip6_mroute.c
diff -u src/sys/netinet6/ip6_mroute.c:1.116 src/sys/netinet6/ip6_mroute.c:1.117
--- src/sys/netinet6/ip6_mroute.c:1.116	Tue Jan 24 07:09:25 2017
+++ src/sys/netinet6/ip6_mroute.c	Tue Feb 14 03:05:06 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_mroute.c,v 1.116 2017/01/24 07:09:25 ozaki-r Exp $	*/
+/*	$NetBSD: ip6_mroute.c,v 1.117 2017/02/14 03:05:06 ozaki-r Exp $	*/
 /*	$KAME: ip6_mroute.c,v 1.49 2001/07/25 09:21:18 jinmei Exp $	*/
 
 /*
@@ -117,7 +117,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_mroute.c,v 1.116 2017/01/24 07:09:25 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_mroute.c,v 1.117 2017/02/14 03:05:06 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -1620,12 +1620,7 @@ phyint_send(struct ip6_hdr *ip6, struct 
 	 */
 	linkmtu = IN6_LINKMTU(ifp);
 	if (mb_copy->m_pkthdr.len <= linkmtu || linkmtu < IPV6_MMTU) {
-		/*
-		 * We could call if_output directly here, but we use
-		 * nd6_output on purpose to see if IPv6 operation is allowed
-		 * on the interface.
-		 */
-		error = nd6_output(ifp, ifp, mb_copy, &dst6, NULL);
+		error = ip6_if_output(ifp, ifp, mb_copy, &dst6, NULL);
 #ifdef MRT6DEBUG
 		if (mrt6debug & DEBUG_XMIT)
 			log(LOG_DEBUG, "phyint_send on mif %td err %d\n",

Index: src/sys/netinet6/ip6_output.c
diff -u src/sys/netinet6/ip6_output.c:1.182 src/sys/netinet6/ip6_output.c:1.183
--- src/sys/netinet6/ip6_output.c:1.182	Mon Jan 16 15:44:47 2017
+++ src/sys/netinet6/ip6_output.c	Tue Feb 14 03:05:06 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_output.c,v 1.182 2017/01/16 15:44:47 christos Exp $	*/
+/*	$NetBSD: ip6_output.c,v 1.183 2017/02/14 03:05:06 ozaki-r Exp $	*/
 /*	$KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.182 2017/01/16 15:44:47 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.183 2017/02/14 03:05:06 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -180,6 +180,31 @@ ip6_handle_rthdr(struct ip6_rthdr *rh, s
 }
 
 /*
+ * Send an IP packet to a host.
+ */
+int
+ip6_if_output(struct ifnet * const ifp, struct ifnet * const origifp,
+    struct mbuf * const m,
+    const struct sockaddr_in6 * const dst, const struct rtentry *rt)
+{
+	int error = 0;
+
+	if (rt != NULL) {
+		error = rt_check_reject_route(rt, ifp);
+		if (error != 0) {
+			m_freem(m);
+			return error;
+		}
+	}
+
+	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
+		error = if_output_lock(ifp, origifp, m, sin6tocsa(dst), rt);
+	else
+		error = if_output_lock(ifp, ifp, m, sin6tocsa(dst), rt);
+	return error;
+}
+
+/*
  * IP6 output. The packet in mbuf chain m contains a skeletal IP6
  * header (with pri, len, nxt, hlim, src, dst).
  * This function may modify ver and hlim only.
@@ -844,7 +869,7 @@ ip6_output(
 		KASSERT(dst != NULL);
 		if (__predict_true(!tso ||
 		    (ifp->if_capenable & IFCAP_TSOv6) != 0)) {
-			error = nd6_output(ifp, origifp, m, dst, rt);
+			error = ip6_if_output(ifp, origifp, m, dst, rt);
 		} else {
 			error = ip6_tso_output(ifp, origifp, m, dst, rt);
 		}
@@ -1030,7 +1055,7 @@ sendorfree:
 			}
 			pserialize_read_exit(s);
 			KASSERT(dst != NULL);
-			error = nd6_output(ifp, origifp, m, dst, rt);
+			error = ip6_if_output(ifp, origifp, m, dst, rt);
 		} else
 			m_freem(m);
 	}

Index: src/sys/netinet6/ip6_var.h
diff -u src/sys/netinet6/ip6_var.h:1.71 src/sys/netinet6/ip6_var.h:1.72
--- src/sys/netinet6/ip6_var.h:1.71	Thu Dec  8 05:16:34 2016
+++ src/sys/netinet6/ip6_var.h	Tue Feb 14 03:05:06 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_var.h,v 1.71 2016/12/08 05:16:34 ozaki-r Exp $	*/
+/*	$NetBSD: ip6_var.h,v 1.72 2017/02/14 03:05:06 ozaki-r Exp $	*/
 /*	$KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $	*/
 
 /*
@@ -353,6 +353,9 @@ int	ip6_output(struct mbuf *, struct ip6
 			struct route *, int,
 			struct ip6_moptions *, struct socket *,
 			struct ifnet **);
+int	ip6_if_output(struct ifnet * const, struct ifnet * const,
+	    struct mbuf * const,
+	    const struct sockaddr_in6 * const, const struct rtentry *);
 int	ip6_ctloutput(int, struct socket *, struct sockopt *);
 int	ip6_raw_ctloutput(int, struct socket *, struct sockopt *);
 void	ip6_initpktopts(struct ip6_pktopts *);

Index: src/sys/netinet6/nd6.c
diff -u src/sys/netinet6/nd6.c:1.226 src/sys/netinet6/nd6.c:1.227
--- src/sys/netinet6/nd6.c:1.226	Mon Jan 16 15:44:47 2017
+++ src/sys/netinet6/nd6.c	Tue Feb 14 03:05:06 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: nd6.c,v 1.226 2017/01/16 15:44:47 christos Exp $	*/
+/*	$NetBSD: nd6.c,v 1.227 2017/02/14 03:05:06 ozaki-r 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.226 2017/01/16 15:44:47 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.227 2017/02/14 03:05:06 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -1992,7 +1992,7 @@ nd6_llinfo_release_pkts(struct llentry *
 		 * just set the 2nd argument as the 
 		 * 1st one.
 		 */
-		nd6_output(ifp, ifp, m_hold, &sin6, NULL);
+		ip6_if_output(ifp, ifp, m_hold, &sin6, NULL);
 	}
 	LLE_WLOCK(ln);
 }
@@ -2265,59 +2265,23 @@ nd6_slowtimo(void *ignored_arg)
 #endif
 }
 
+/*
+ * Return 0 if a neighbor cache is found. Return EWOULDBLOCK if a cache is not
+ * found and trying to resolve a neighbor; in this case the mbuf is queued in
+ * the list. Otherwise return errno after freeing the mbuf.
+ */
 int
-nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
-    const struct sockaddr_in6 *dst, struct rtentry *rt)
+nd6_resolve(struct ifnet *ifp, const struct rtentry *rt, struct mbuf *m,
+    const struct sockaddr *_dst, uint8_t *lldst, size_t dstsize)
 {
-#define senderr(e) { error = (e); goto bad;}
 	struct llentry *ln = NULL;
-	int error = 0;
 	bool created = false;
+	const struct sockaddr_in6 *dst = satocsin6(_dst);
 
-	if (rt != NULL) {
-		error = rt_check_reject_route(rt, ifp);
-		if (error != 0) {
-			m_freem(m);
-			return error;
-		}
-	}
-
-	if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
-		goto sendpkt;
-
-	if (nd6_need_cache(ifp) == 0)
-		goto sendpkt;
-
-	if (rt != NULL && (rt->rt_flags & RTF_GATEWAY) != 0) {
-		struct sockaddr_in6 *gw6 = satosin6(rt->rt_gateway);
-		int s;
-
-		/* XXX remain the check to keep the original behavior. */
-		/*
-		 * We skip link-layer address resolution and NUD
-		 * if the gateway is not a neighbor from ND point
-		 * of view, regardless of the value of nd_ifinfo.flags.
-		 * The second condition is a bit tricky; we skip
-		 * if the gateway is our own address, which is
-		 * sometimes used to install a route to a p2p link.
-		 */
-		s = pserialize_read_enter();
-		if (!nd6_is_addr_neighbor(gw6, ifp) ||
-		    in6ifa_ifpwithaddr(ifp, &gw6->sin6_addr)) {
-			/*
-			 * We allow this kind of tricky route only
-			 * when the outgoing interface is p2p.
-			 * XXX: we may need a more generic rule here.
-			 */
-			if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
-				pserialize_read_exit(s);
-				senderr(EHOSTUNREACH);
-			}
-
-			pserialize_read_exit(s);
-			goto sendpkt;
-		}
-		pserialize_read_exit(s);
+	/* discard the packet if IPv6 operation is disabled on the interface */
+	if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
+		m_freem(m);
+		return ENETDOWN; /* better error? */
 	}
 
 	/*
@@ -2328,29 +2292,37 @@ nd6_output(struct ifnet *ifp, struct ifn
 	 */
 
 	/* Look up the neighbor cache for the nexthop */
+	ln = nd6_lookup(&dst->sin6_addr, ifp, false);
+
+	if (ln != NULL && (ln->la_flags & LLE_VALID) != 0) {
+		KASSERT(ln->ln_state > ND6_LLINFO_INCOMPLETE);
+		/* Fast path */
+		memcpy(lldst, &ln->ll_addr, MIN(dstsize, ifp->if_addrlen));
+		LLE_RUNLOCK(ln);
+		return 0;
+	}
+	if (ln != NULL)
+		LLE_RUNLOCK(ln);
+
+	/* Slow path */
 	ln = nd6_lookup(&dst->sin6_addr, ifp, true);
-	if ((ln == NULL) && nd6_is_addr_neighbor(dst, ifp))  {
+	if (ln == NULL && nd6_is_addr_neighbor(dst, ifp))  {
 		/*
 		 * Since nd6_is_addr_neighbor() internally calls nd6_lookup(),
 		 * the condition below is not very efficient.  But we believe
 		 * it is tolerable, because this should be a rare case.
 		 */
 		ln = nd6_create(&dst->sin6_addr, ifp);
-		if (ln != NULL)
-			created = true;
-	}
-
-	if (ln == NULL) {
-		if ((ifp->if_flags & IFF_POINTOPOINT) == 0 &&
-		    !(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) {
+		if (ln == NULL) {
 			char ip6buf[INET6_ADDRSTRLEN];
 			log(LOG_DEBUG,
-			    "nd6_output: can't allocate llinfo for %s "
-			    "(ln=%p, rt=%p)\n",
+			    "%s: can't allocate llinfo for %s "
+			    "(ln=%p, rt=%p)\n", __func__,
 			    IN6_PRINT(ip6buf, &dst->sin6_addr), ln, rt);
-			senderr(EIO);	/* XXX: good error? */
+			m_freem(m);
+			return ENOBUFS;
 		}
-		goto sendpkt;	/* send anyway */
+		created = true;
 	}
 
 	LLE_WLOCK_ASSERT(ln);
@@ -2376,14 +2348,6 @@ nd6_output(struct ifnet *ifp, struct ifn
 	}
 
 	/*
-	 * 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)
-		goto sendpkt;
-
-	/*
 	 * 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
@@ -2432,34 +2396,10 @@ nd6_output(struct ifnet *ifp, struct ifn
 		LLE_WUNLOCK(ln);
 	}
 
-	error = 0;
-	goto exit;
-
-  sendpkt:
-	/* discard the packet if IPv6 operation is disabled on the interface */
-	if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
-		error = ENETDOWN; /* better error? */
-		goto bad;
-	}
-
-	if (ln != NULL)
-		LLE_WUNLOCK(ln);
-
-	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
-		error = if_output_lock(ifp, origifp, m, sin6tocsa(dst), rt);
-	else
-		error = if_output_lock(ifp, ifp, m, sin6tocsa(dst), rt);
-	goto exit;
-
-  bad:
-	if (m != NULL)
-		m_freem(m);
-  exit:
 	if (created)
 		nd6_gc_neighbors(LLTABLE6(ifp), &dst->sin6_addr);
 
-	return error;
-#undef senderr
+	return EWOULDBLOCK;
 }
 
 int
@@ -2542,68 +2482,6 @@ nd6_rem_ifa_lle(struct in6_ifaddr *ia)
 	    LLE_STATIC);
 }
 
-int
-nd6_storelladdr(const struct ifnet *ifp, const struct rtentry *rt,
-    struct mbuf *m, const struct sockaddr *dst, uint8_t *lldst,
-    size_t dstsize)
-{
-	struct llentry *ln;
-
-	if (m->m_flags & M_MCAST) {
-		switch (ifp->if_type) {
-		case IFT_ETHER:
-		case IFT_FDDI:
-			ETHER_MAP_IPV6_MULTICAST(&satocsin6(dst)->sin6_addr,
-			    lldst);
-			return 1;
-		case IFT_IEEE1394:
-			memcpy(lldst, ifp->if_broadcastaddr,
-			    MIN(dstsize, ifp->if_addrlen));
-			return 1;
-		case IFT_ARCNET:
-			*lldst = 0;
-			return 1;
-		default:
-			m_freem(m);
-			return 0;
-		}
-	}
-
-	/*
-	 * the entry should have been created in nd6_store_lladdr
-	 */
-	ln = nd6_lookup(&satocsin6(dst)->sin6_addr, ifp, false);
-	if ((ln == NULL) || !(ln->la_flags & LLE_VALID)) {
-		if (ln != NULL)
-			LLE_RUNLOCK(ln);
-		/* this could happen, if we could not allocate memory */
-		m_freem(m);
-		return 0;
-	}
-
-	/* XXX llentry should have addrlen? */
-#if 0
-	sdl = satocsdl(rt->rt_gateway);
-	if (sdl->sdl_alen == 0 || sdl->sdl_alen > dstsize) {
-		char sbuf[INET6_ADDRSTRLEN];
-		char dbuf[LINK_ADDRSTRLEN];
-		/* this should be impossible, but we bark here for debugging */
-		printf("%s: sdl_alen == %" PRIu8 ", if=%s, dst=%s, sdl=%s\n",
-		    __func__, sdl->sdl_alen, if_name(ifp),
-		    IN6_PRINT(sbuf, &satocsin6(dst)->sin6_addr),
-		    DL_PRINT(dbuf, &sdl->sdl_addr));
-		m_freem(m);
-		return 0;
-	}
-#endif
-
-	memcpy(lldst, &ln->ll_addr, MIN(dstsize, ifp->if_addrlen));
-
-	LLE_RUNLOCK(ln);
-
-	return 1;
-}
-
 static void 
 clear_llinfo_pqueue(struct llentry *ln)
 {

Index: src/sys/netinet6/nd6.h
diff -u src/sys/netinet6/nd6.h:1.81 src/sys/netinet6/nd6.h:1.82
--- src/sys/netinet6/nd6.h:1.81	Mon Dec 19 07:51:34 2016
+++ src/sys/netinet6/nd6.h	Tue Feb 14 03:05:06 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: nd6.h,v 1.81 2016/12/19 07:51:34 ozaki-r Exp $	*/
+/*	$NetBSD: nd6.h,v 1.82 2017/02/14 03:05:06 ozaki-r Exp $	*/
 /*	$KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $	*/
 
 /*
@@ -438,16 +438,12 @@ void nd6_llinfo_settimer(struct llentry 
 void nd6_purge(struct ifnet *, struct in6_ifextra *);
 void nd6_assert_purged(struct ifnet *);
 void nd6_nud_hint(struct rtentry *);
-int nd6_resolve(struct ifnet *, struct rtentry *,
-	struct mbuf *, struct sockaddr *, u_char *);
+int nd6_resolve(struct ifnet *, const struct rtentry *, struct mbuf *,
+	const struct sockaddr *, uint8_t *, size_t);
 void nd6_rtrequest(int, struct rtentry *, const struct rt_addrinfo *);
 int nd6_ioctl(u_long, void *, struct ifnet *);
 void nd6_cache_lladdr(struct ifnet *, struct in6_addr *,
 	char *, int, int, int);
-int nd6_output(struct ifnet *, struct ifnet *, struct mbuf *,
-	const struct sockaddr_in6 *, struct rtentry *);
-int nd6_storelladdr(const struct ifnet *, const struct rtentry *, struct mbuf *,
-	const struct sockaddr *, uint8_t *, size_t);
 int nd6_sysctl(int, void *, size_t *, void *, size_t);
 int nd6_need_cache(struct ifnet *);
 void nd6_llinfo_release_pkts(struct llentry *, struct ifnet *);

Reply via email to