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