aboutsummaryrefslogtreecommitdiff
path: root/sys/net/if_iso88025subr.c
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2015-09-16 14:26:28 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2015-09-16 14:26:28 +0000
commit1fe201c322f93424e29581c5622da7cde44db51f (patch)
treee04e3fcd4841d6aa1ce593fcc38aa9bb51b4cd33 /sys/net/if_iso88025subr.c
parent5c5fb901eb05f91db8e914500357953bf475b8a0 (diff)
downloadsrc-1fe201c322f93424e29581c5622da7cde44db51f.tar.gz
src-1fe201c322f93424e29581c5622da7cde44db51f.zip
Simplify the way of attaching IPv6 link-layer header.
Problem description: How do we currently perform layer 2 resolution and header imposition: For IPv4 we have the following chain: ip_output() -> (ether|atm|whatever)_output() -> arpresolve() Lookup is done in proper place (link-layer output routine) and it is possible to provide cached lle data. For IPv6 situation is more complex: ip6_output() -> nd6_output() -> nd6_output_ifp() -> (whatever)_output() -> nd6_storelladdr() We have ip6_ouput() which calls nd6_output() instead of link output routine. nd6_output() does the following: * checks if lle exists, creates it if needed (similar to arpresolve()) * performes lle state transitions (similar to arpresolve()) * calls nd6_output_ifp() which pushes packets to link output routine along with running SeND/MAC hooks regardless of lle state (e.g. works as run-hooks placeholder). After that, iface output routine like ether_output() calls nd6_storelladdr() which performs lle lookup once again. As a result, we perform lookup twice for each outgoing packet for most types of interfaces. We also need to maintain runtime-checked table of 'nd6-free' interfaces (see nd6_need_cache()). Fix this behavior by eliminating first ND lookup. To be more specific: * make all nd6_output() consumers use nd6_output_ifp() instead * rename nd6_output[_slow]() to nd6_resolve_[slow]() * convert nd6_resolve() and nd6_resolve_slow() to arpresolve() semantics, e.g. copy L2 address to buffer instead of pushing packet towards lower layers * Make all nd6_storelladdr() users use nd6_resolve() * eliminate nd6_storelladdr() The resulting callchain is the following: ip6_output() -> nd6_output_ifp() -> (whatever)_output() -> nd6_resolve() Error handling: Currently sending packet to non-existing la results in ip6_<output|forward> -> nd6_output() -> nd6_output _lle() which returns 0. In new scenario packet is propagated to <ether|whatever>_output() -> nd6_resolve() which will return EWOULDBLOCK, and that result will be converted to 0. (And EWOULDBLOCK is actually used by IB/TOE code). Sponsored by: Yandex LLC Differential Revision: https://reviews.freebsd.org/D1469
Notes
Notes: svn path=/head/; revision=287861
Diffstat (limited to 'sys/net/if_iso88025subr.c')
-rw-r--r--sys/net/if_iso88025subr.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c
index 727df37f70db..976e41033157 100644
--- a/sys/net/if_iso88025subr.c
+++ b/sys/net/if_iso88025subr.c
@@ -293,9 +293,9 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
#endif /* INET */
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, NULL);
+ error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL);
if (error)
- return (error);
+ return (error == EWOULDBLOCK ? 0 : error);
snap_type = ETHERTYPE_IPV6;
break;
#endif /* INET6 */