aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet6/nd6_nbr.c
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2021-08-21 14:13:32 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2021-08-21 17:34:35 +0000
commitc541bd368f863bbf5c08dd5c1ecce0166ad47389 (patch)
tree51ec2623511529ecb647750775f5cc964f65e98f /sys/netinet6/nd6_nbr.c
parente5a50b03297fa09652b3cf319bc6e863392554e0 (diff)
downloadsrc-c541bd368f863bbf5c08dd5c1ecce0166ad47389.tar.gz
src-c541bd368f863bbf5c08dd5c1ecce0166ad47389.zip
lltable: Add support for "child" LLEs holding encap for IPv4oIPv6 entries.
Currently we use pre-calculated headers inside LLE entries as prepend data for `if_output` functions. Using these headers allows saving some CPU cycles/memory accesses on the fast path. However, this approach makes adding L2 header for IPv4 traffic with IPv6 nexthops more complex, as it is not possible to store multiple pre-calculated headers inside lle. Additionally, the solution space is limited by the fact that PCB caching saves LLEs in addition to the nexthop. Thus, add support for creating special "child" LLEs for the purpose of holding custom family encaps and store mbufs pending resolution. To simplify handling of those LLEs, store them in a linked-list inside a "parent" (e.g. normal) LLE. Such LLEs are not visible when iterating LLE table. Their lifecycle is bound to the "parent" LLE - it is not possible to delete "child" when parent is alive. Furthermore, "child" LLEs are static (RTF_STATIC), avoding complex state machine used by the standard LLEs. nd6_lookup() and nd6_resolve() now accepts an additional argument, family, allowing to return such child LLEs. This change uses `LLE_SF()` macro which packs family and flags in a single int field. This is done to simplify merging back to stable/. Once this code lands, most of the cases will be converted to use a dedicated `family` parameter. Differential Revision: https://reviews.freebsd.org/D31379 MFC after: 2 weeks
Diffstat (limited to 'sys/netinet6/nd6_nbr.c')
-rw-r--r--sys/netinet6/nd6_nbr.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index 974c454e93a5..30d73f9d71a9 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -630,6 +630,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
size_t linkhdrsize;
int flags, is_override, is_router, is_solicited;
int lladdr_off, lladdrlen, checklink;
+ bool flush_holdchain = false;
NET_EPOCH_ASSERT();
@@ -747,7 +748,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
* If no neighbor cache entry is found, NA SHOULD silently be
* discarded.
*/
- ln = nd6_lookup(&taddr6, LLE_EXCLUSIVE, ifp);
+ ln = nd6_lookup(&taddr6, LLE_SF(AF_INET6, LLE_EXCLUSIVE), ifp);
if (ln == NULL) {
goto freeit;
}
@@ -773,6 +774,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
if (!nd6_try_set_entry_addr(ifp, ln, lladdr))
goto freeit;
+ flush_holdchain = true;
EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
if (is_solicited)
nd6_llinfo_setstate(ln, ND6_LLINFO_REACHABLE);
@@ -899,6 +901,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
if (chain != NULL)
nd6_flush_holdchain(ifp, ln, chain);
+ if (flush_holdchain)
+ nd6_flush_children_holdchain(ifp, ln);
if (checklink)
pfxlist_onlink_check();