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
This commit is contained in:
parent
6d2f4d7edc
commit
3f909d1769
6
sys/dist/pf/net/pf.c
vendored
6
sys/dist/pf/net/pf.c
vendored
@ -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_rule *r, int dir, struct ifnet *oifp,
|
||||
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)
|
||||
|
6
sys/external/bsd/ipf/netinet/ip_fil_netbsd.c
vendored
6
sys/external/bsd/ipf/netinet/ip_fil_netbsd.c
vendored
@ -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 mbuf **mpp, fr_info_t *fin,
|
||||
# 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
|
||||
|
@ -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 mbuf *m0, const struct sockaddr *dst,
|
||||
#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;
|
||||
|
@ -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, struct mbuf * const m0,
|
||||
#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;
|
||||
|
@ -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 mbuf *m0, const struct sockaddr *dst,
|
||||
#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;
|
||||
|
@ -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, struct mbuf *m0, const struct sockaddr *dst,
|
||||
#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;
|
||||
|
@ -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.25 2017/02/09 11:43:32 kre Exp $");
|
||||
#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);
|
||||
}
|
||||
|
||||
|
@ -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.c,v 1.6 2011/04/25 22:07:57 yamt Exp $")
|
||||
#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 mbuf *m)
|
||||
{
|
||||
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
|
||||
|
@ -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);
|
||||
|
@ -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 mif6 *mifp, struct mbuf *m)
|
||||
*/
|
||||
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",
|
||||
|
@ -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"
|
||||
@ -179,6 +179,31 @@ ip6_handle_rthdr(struct ip6_rthdr *rh, struct ip6_hdr *ip6)
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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).
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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_pktopts *,
|
||||
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 *);
|
||||
|
@ -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 *ln, struct ifnet *ifp)
|
||||
* 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) {
|
||||
/* discard the packet if IPv6 operation is disabled on the interface */
|
||||
if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
|
||||
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);
|
||||
return ENETDOWN; /* better error? */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2328,29 +2292,37 @@ nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
|
||||
*/
|
||||
|
||||
/* 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)) {
|
||||
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);
|
||||
@ -2375,14 +2347,6 @@ nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
|
||||
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)
|
||||
goto sendpkt;
|
||||
|
||||
/*
|
||||
* There is a neighbor cache entry, but no ethernet address
|
||||
* response yet. Append this latest packet to the end of the
|
||||
@ -2432,34 +2396,10 @@ nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
|
||||
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)
|
||||
{
|
||||
|
@ -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 *, time_t);
|
||||
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 *);
|
||||
|
Loading…
Reference in New Issue
Block a user