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:
ozaki-r 2017-02-14 03:05:06 +00:00
parent 6d2f4d7edc
commit 3f909d1769
14 changed files with 145 additions and 213 deletions

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

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

View File

@ -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

View File

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

View File

@ -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",

View File

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

View File

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

View File

@ -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) {
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 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)) {
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);
@ -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)
{

View File

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