2017-11-27 15:23:17 +00:00
|
|
|
/*-
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
|
|
|
*
|
2008-12-15 06:53:09 +00:00
|
|
|
* Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
|
|
|
|
* Copyright (c) 2004-2008 Qing Li. All rights reserved.
|
|
|
|
* Copyright (c) 2008 Kip Macy. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
|
|
|
#ifndef _NET_IF_LLATBL_H_
|
|
|
|
#define _NET_IF_LLATBL_H_
|
|
|
|
|
Extract eventfilter declarations to sys/_eventfilter.h
This allows replacing "sys/eventfilter.h" includes with "sys/_eventfilter.h"
in other header files (e.g., sys/{bus,conf,cpu}.h) and reduces header
pollution substantially.
EVENTHANDLER_DECLARE and EVENTHANDLER_LIST_DECLAREs were moved out of .c
files into appropriate headers (e.g., sys/proc.h, powernv/opal.h).
As a side effect of reduced header pollution, many .c files and headers no
longer contain needed definitions. The remainder of the patch addresses
adding appropriate includes to fix those files.
LOCK_DEBUG and LOCK_FILE_LINE_ARG are moved to sys/_lock.h, as required by
sys/mutex.h since r326106 (but silently protected by header pollution prior
to this change).
No functional change (intended). Of course, any out of tree modules that
relied on header pollution for sys/eventhandler.h, sys/lock.h, or
sys/mutex.h inclusion need to be fixed. __FreeBSD_version has been bumped.
2019-05-20 00:38:23 +00:00
|
|
|
#include <sys/_eventhandler.h>
|
2008-12-15 06:53:09 +00:00
|
|
|
#include <sys/_rwlock.h>
|
|
|
|
#include <netinet/in.h>
|
2018-05-23 21:02:14 +00:00
|
|
|
#include <sys/epoch.h>
|
2018-05-24 23:21:23 +00:00
|
|
|
#include <sys/ck.h>
|
2008-12-15 06:53:09 +00:00
|
|
|
|
|
|
|
struct ifnet;
|
|
|
|
struct sysctl_req;
|
|
|
|
struct rt_msghdr;
|
|
|
|
struct rt_addrinfo;
|
|
|
|
struct llentry;
|
2018-05-24 23:21:23 +00:00
|
|
|
CK_LIST_HEAD(llentries, llentry);
|
2008-12-15 06:53:09 +00:00
|
|
|
|
2015-12-31 05:03:27 +00:00
|
|
|
#define LLE_MAX_LINKHDR 24 /* Full IB header */
|
2008-12-15 06:53:09 +00:00
|
|
|
/*
|
|
|
|
* Code referencing llentry must at least hold
|
|
|
|
* a shared lock
|
|
|
|
*/
|
|
|
|
struct llentry {
|
2018-05-24 23:21:23 +00:00
|
|
|
CK_LIST_ENTRY(llentry) lle_next;
|
2015-08-11 09:26:11 +00:00
|
|
|
union {
|
|
|
|
struct in_addr addr4;
|
|
|
|
struct in6_addr addr6;
|
|
|
|
} r_l3addr;
|
2015-12-31 05:03:27 +00:00
|
|
|
char r_linkdata[LLE_MAX_LINKHDR]; /* L2 data */
|
|
|
|
uint8_t r_hdrlen; /* length for LL header */
|
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
2021-08-21 14:13:32 +00:00
|
|
|
uint8_t r_family; /* Upper layer proto family */
|
|
|
|
uint8_t spare0[2];
|
2015-12-05 09:50:37 +00:00
|
|
|
uint16_t r_flags; /* LLE runtime flags */
|
|
|
|
uint16_t r_skip_req; /* feedback from fast path */
|
2015-08-11 09:26:11 +00:00
|
|
|
|
2008-12-15 06:53:09 +00:00
|
|
|
struct lltable *lle_tbl;
|
|
|
|
struct llentries *lle_head;
|
2015-08-10 12:03:59 +00:00
|
|
|
void (*lle_free)(struct llentry *);
|
2008-12-15 06:53:09 +00:00
|
|
|
struct mbuf *la_hold;
|
2012-07-31 11:31:12 +00:00
|
|
|
int la_numheld; /* # of packets currently held */
|
2008-12-15 06:53:09 +00:00
|
|
|
time_t la_expire;
|
2012-07-31 11:31:12 +00:00
|
|
|
uint16_t la_flags;
|
2008-12-15 06:53:09 +00:00
|
|
|
uint16_t la_asked;
|
|
|
|
uint16_t la_preempt;
|
|
|
|
int16_t ln_state; /* IPv6 has ND6_LLINFO_NOSTATE == -2 */
|
2012-07-31 11:31:12 +00:00
|
|
|
uint16_t ln_router;
|
2008-12-15 06:53:09 +00:00
|
|
|
time_t ln_ntick;
|
2015-12-13 07:39:49 +00:00
|
|
|
time_t lle_remtime; /* Real time remaining */
|
|
|
|
time_t lle_hittime; /* Time when r_skip_req was unset */
|
2008-12-15 06:53:09 +00:00
|
|
|
int lle_refcnt;
|
2015-12-31 05:03:27 +00:00
|
|
|
char *ll_addr; /* link-layer address */
|
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
2021-08-21 14:13:32 +00:00
|
|
|
CK_SLIST_HEAD(llentry_children_head,llentry) lle_children; /* child encaps */
|
|
|
|
CK_SLIST_ENTRY(llentry) lle_child_next; /* child encaps */
|
|
|
|
struct llentry *lle_parent; /* parent for a child */
|
2012-07-31 11:31:12 +00:00
|
|
|
|
2018-05-24 23:21:23 +00:00
|
|
|
CK_LIST_ENTRY(llentry) lle_chain; /* chain of deleted items */
|
2015-08-11 12:38:54 +00:00
|
|
|
struct callout lle_timer;
|
2015-08-11 09:26:11 +00:00
|
|
|
struct rwlock lle_lock;
|
2015-12-05 09:50:37 +00:00
|
|
|
struct mtx req_mtx;
|
2018-05-23 21:02:14 +00:00
|
|
|
struct epoch_context lle_epoch_ctx;
|
2008-12-15 06:53:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define LLE_WLOCK(lle) rw_wlock(&(lle)->lle_lock)
|
|
|
|
#define LLE_RLOCK(lle) rw_rlock(&(lle)->lle_lock)
|
|
|
|
#define LLE_WUNLOCK(lle) rw_wunlock(&(lle)->lle_lock)
|
|
|
|
#define LLE_RUNLOCK(lle) rw_runlock(&(lle)->lle_lock)
|
|
|
|
#define LLE_DOWNGRADE(lle) rw_downgrade(&(lle)->lle_lock)
|
|
|
|
#define LLE_TRY_UPGRADE(lle) rw_try_upgrade(&(lle)->lle_lock)
|
|
|
|
#define LLE_LOCK_INIT(lle) rw_init_flags(&(lle)->lle_lock, "lle", RW_DUPOK)
|
2008-12-16 00:20:15 +00:00
|
|
|
#define LLE_LOCK_DESTROY(lle) rw_destroy(&(lle)->lle_lock)
|
2008-12-15 06:53:09 +00:00
|
|
|
#define LLE_WLOCK_ASSERT(lle) rw_assert(&(lle)->lle_lock, RA_WLOCKED)
|
|
|
|
|
2015-12-05 09:50:37 +00:00
|
|
|
#define LLE_REQ_INIT(lle) mtx_init(&(lle)->req_mtx, "lle req", \
|
|
|
|
NULL, MTX_DEF)
|
|
|
|
#define LLE_REQ_DESTROY(lle) mtx_destroy(&(lle)->req_mtx)
|
|
|
|
#define LLE_REQ_LOCK(lle) mtx_lock(&(lle)->req_mtx)
|
|
|
|
#define LLE_REQ_UNLOCK(lle) mtx_unlock(&(lle)->req_mtx)
|
|
|
|
|
2008-12-15 06:53:09 +00:00
|
|
|
#define LLE_IS_VALID(lle) (((lle) != NULL) && ((lle) != (void *)-1))
|
|
|
|
|
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
2021-08-21 14:13:32 +00:00
|
|
|
#define LLE_SF(_fam, _flags) (((_flags) & 0xFFFF) | ((_fam) << 16))
|
|
|
|
|
2008-12-15 06:53:09 +00:00
|
|
|
#define LLE_ADDREF(lle) do { \
|
|
|
|
LLE_WLOCK_ASSERT(lle); \
|
|
|
|
KASSERT((lle)->lle_refcnt >= 0, \
|
2012-08-02 13:57:49 +00:00
|
|
|
("negative refcnt %d on lle %p", \
|
|
|
|
(lle)->lle_refcnt, (lle))); \
|
2008-12-15 06:53:09 +00:00
|
|
|
(lle)->lle_refcnt++; \
|
|
|
|
} while (0)
|
2012-07-31 11:31:12 +00:00
|
|
|
|
2008-12-15 06:53:09 +00:00
|
|
|
#define LLE_REMREF(lle) do { \
|
|
|
|
LLE_WLOCK_ASSERT(lle); \
|
2012-08-02 13:57:49 +00:00
|
|
|
KASSERT((lle)->lle_refcnt > 0, \
|
|
|
|
("bogus refcnt %d on lle %p", \
|
|
|
|
(lle)->lle_refcnt, (lle))); \
|
2008-12-15 06:53:09 +00:00
|
|
|
(lle)->lle_refcnt--; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define LLE_FREE_LOCKED(lle) do { \
|
2012-08-02 13:57:49 +00:00
|
|
|
if ((lle)->lle_refcnt == 1) \
|
2015-08-10 12:03:59 +00:00
|
|
|
(lle)->lle_free(lle); \
|
2008-12-15 06:53:09 +00:00
|
|
|
else { \
|
2012-08-02 13:57:49 +00:00
|
|
|
LLE_REMREF(lle); \
|
2008-12-15 06:53:09 +00:00
|
|
|
LLE_WUNLOCK(lle); \
|
|
|
|
} \
|
|
|
|
/* guard against invalid refs */ \
|
2012-08-02 13:57:49 +00:00
|
|
|
(lle) = NULL; \
|
2008-12-15 06:53:09 +00:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define LLE_FREE(lle) do { \
|
|
|
|
LLE_WLOCK(lle); \
|
2010-12-31 21:57:54 +00:00
|
|
|
LLE_FREE_LOCKED(lle); \
|
2008-12-15 06:53:09 +00:00
|
|
|
} while (0)
|
|
|
|
|
2014-11-15 18:54:07 +00:00
|
|
|
typedef struct llentry *(llt_lookup_t)(struct lltable *, u_int flags,
|
|
|
|
const struct sockaddr *l3addr);
|
2015-08-20 12:05:17 +00:00
|
|
|
typedef struct llentry *(llt_alloc_t)(struct lltable *, u_int flags,
|
2014-11-15 18:54:07 +00:00
|
|
|
const struct sockaddr *l3addr);
|
2015-09-14 16:48:19 +00:00
|
|
|
typedef void (llt_delete_t)(struct lltable *, struct llentry *);
|
2014-11-15 18:54:07 +00:00
|
|
|
typedef void (llt_prefix_free_t)(struct lltable *,
|
2015-09-14 16:48:19 +00:00
|
|
|
const struct sockaddr *addr, const struct sockaddr *mask, u_int flags);
|
2015-08-10 12:03:59 +00:00
|
|
|
typedef int (llt_dump_entry_t)(struct lltable *, struct llentry *,
|
|
|
|
struct sysctl_req *);
|
|
|
|
typedef uint32_t (llt_hash_t)(const struct llentry *, uint32_t);
|
|
|
|
typedef int (llt_match_prefix_t)(const struct sockaddr *,
|
|
|
|
const struct sockaddr *, u_int, struct llentry *);
|
|
|
|
typedef void (llt_free_entry_t)(struct lltable *, struct llentry *);
|
|
|
|
typedef void (llt_fill_sa_entry_t)(const struct llentry *, struct sockaddr *);
|
2015-08-11 05:51:00 +00:00
|
|
|
typedef void (llt_free_tbl_t)(struct lltable *);
|
2020-03-04 17:17:02 +00:00
|
|
|
typedef int (llt_link_entry_t)(struct lltable *, struct llentry *);
|
|
|
|
typedef int (llt_unlink_entry_t)(struct llentry *);
|
2018-03-17 17:05:48 +00:00
|
|
|
typedef void (llt_mark_used_t)(struct llentry *);
|
2022-05-30 07:38:54 +00:00
|
|
|
typedef void (llt_post_resolved_t)(struct lltable *, struct llentry *);
|
2015-08-10 12:03:59 +00:00
|
|
|
|
|
|
|
typedef int (llt_foreach_cb_t)(struct lltable *, struct llentry *, void *);
|
|
|
|
typedef int (llt_foreach_entry_t)(struct lltable *, llt_foreach_cb_t *, void *);
|
2022-05-30 07:51:15 +00:00
|
|
|
typedef bool (llt_match_cb_t)(struct lltable *, struct llentry *, void *);
|
2014-11-15 18:54:07 +00:00
|
|
|
|
2008-12-15 06:53:09 +00:00
|
|
|
struct lltable {
|
|
|
|
SLIST_ENTRY(lltable) llt_link;
|
2022-05-30 07:36:52 +00:00
|
|
|
sa_family_t llt_af;
|
2022-05-30 07:51:15 +00:00
|
|
|
uint8_t llt_flags;
|
|
|
|
uint8_t llt_spare[2];
|
2015-08-11 05:51:00 +00:00
|
|
|
int llt_hsize;
|
2020-03-04 17:17:02 +00:00
|
|
|
int llt_entries;
|
|
|
|
int llt_maxentries;
|
2015-08-11 05:51:00 +00:00
|
|
|
struct llentries *lle_head;
|
2008-12-15 06:53:09 +00:00
|
|
|
struct ifnet *llt_ifp;
|
|
|
|
|
2014-11-15 18:54:07 +00:00
|
|
|
llt_lookup_t *llt_lookup;
|
2015-08-20 12:05:17 +00:00
|
|
|
llt_alloc_t *llt_alloc_entry;
|
2015-09-14 16:48:19 +00:00
|
|
|
llt_delete_t *llt_delete_entry;
|
2014-11-15 18:54:07 +00:00
|
|
|
llt_prefix_free_t *llt_prefix_free;
|
2015-08-10 12:03:59 +00:00
|
|
|
llt_dump_entry_t *llt_dump_entry;
|
|
|
|
llt_hash_t *llt_hash;
|
|
|
|
llt_match_prefix_t *llt_match_prefix;
|
|
|
|
llt_free_entry_t *llt_free_entry;
|
|
|
|
llt_foreach_entry_t *llt_foreach_entry;
|
|
|
|
llt_link_entry_t *llt_link_entry;
|
|
|
|
llt_unlink_entry_t *llt_unlink_entry;
|
|
|
|
llt_fill_sa_entry_t *llt_fill_sa_entry;
|
2015-08-11 05:51:00 +00:00
|
|
|
llt_free_tbl_t *llt_free_tbl;
|
2018-03-17 17:05:48 +00:00
|
|
|
llt_mark_used_t *llt_mark_used;
|
2022-05-30 07:38:54 +00:00
|
|
|
llt_post_resolved_t *llt_post_resolved;
|
2008-12-15 06:53:09 +00:00
|
|
|
};
|
2014-11-15 18:54:07 +00:00
|
|
|
|
2008-12-15 06:53:09 +00:00
|
|
|
MALLOC_DECLARE(M_LLTABLE);
|
|
|
|
|
2022-05-30 07:51:15 +00:00
|
|
|
/*
|
|
|
|
* LLtable flags
|
|
|
|
*/
|
|
|
|
#define LLT_ADDEDPROXY 0x01 /* added a proxy llentry */
|
|
|
|
|
2008-12-15 06:53:09 +00:00
|
|
|
/*
|
2015-08-08 17:48:54 +00:00
|
|
|
* LLentry flags
|
2008-12-15 06:53:09 +00:00
|
|
|
*/
|
|
|
|
#define LLE_DELETED 0x0001 /* entry must be deleted */
|
|
|
|
#define LLE_STATIC 0x0002 /* entry is static */
|
|
|
|
#define LLE_IFADDR 0x0004 /* entry is interface addr */
|
|
|
|
#define LLE_VALID 0x0008 /* ll_addr is valid */
|
Fix the handling of IPv6 On-Link Redirects.
On receipt of a redirect message, install an interface route for the
redirected destination. On removal of the corresponding Neighbor Cache
entry, remove the interface route.
This requires changes in rtredirect_fib() to cope with an AF_LINK
address for the gateway and with the absence of RTF_GATEWAY.
This fixes the "Redirected On-Link" test cases in the Tahi IPv6 Ready Logo
Phase 2 test suite.
Unrelated to the above, fix a recursion on the radix node head lock
triggered by the Tahi Redirected to Alternate Router test cases.
When I first wrote this patch in October 2012, all Section 2
(Neighbor Discovery) test cases passed on 10-CURRENT, 9-STABLE,
and 8-STABLE. cem@ recently rebased the 10.x patch onto head and reported
that it passes Tahi. (Thanks!)
These other test cases also passed in 2012:
* the RTF_MODIFIED case, with IPv4 and IPv6 (using a
RTF_HOST|RTF_GATEWAY route for the destination)
* the redirected-to-self case, with IPv4 and IPv6
* a valid IPv4 redirect
All testing in 2012 was done with WITNESS and INVARIANTS.
Tested by: EMC / Isilon Storage Division via Conrad Meyer (cem) in 2015,
Mark Kelley <mark_kelley@dell.com> in 2012,
TC Telkamp <terence_telkamp@dell.com> in 2012
PR: 152791
Reviewed by: melifaro (current rev), bz (earlier rev)
Approved by: kib (mentor)
MFC after: 1 month
Relnotes: yes
Sponsored by: Dell Inc.
Differential Revision: https://reviews.freebsd.org/D3602
2015-09-14 19:17:25 +00:00
|
|
|
#define LLE_REDIRECT 0x0010 /* installed by redirect; has host rtentry */
|
2008-12-15 06:53:09 +00:00
|
|
|
#define LLE_PUB 0x0020 /* publish entry ??? */
|
2012-08-02 13:57:49 +00:00
|
|
|
#define LLE_LINKED 0x0040 /* linked to lookup structure */
|
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
2021-08-21 14:13:32 +00:00
|
|
|
#define LLE_CHILD 0x0080 /* Child LLE storing different AF encap */
|
2014-11-15 18:54:07 +00:00
|
|
|
/* LLE request flags */
|
2012-07-31 11:31:12 +00:00
|
|
|
#define LLE_EXCLUSIVE 0x2000 /* return lle xlocked */
|
2015-12-05 09:50:37 +00:00
|
|
|
#define LLE_UNLOCKED 0x4000 /* return lle unlocked */
|
2015-12-31 05:03:27 +00:00
|
|
|
#define LLE_ADDRONLY 0x4000 /* return lladdr instead of full header */
|
|
|
|
#define LLE_CREATE 0x8000 /* hint to avoid lle lookup */
|
2015-12-05 09:50:37 +00:00
|
|
|
|
|
|
|
/* LLE flags used by fastpath code */
|
|
|
|
#define RLLE_VALID 0x0001 /* entry is valid */
|
|
|
|
#define RLLE_IFADDR LLE_IFADDR /* entry is ifaddr */
|
2008-12-15 06:53:09 +00:00
|
|
|
|
|
|
|
#define LLATBL_HASH(key, mask) \
|
|
|
|
(((((((key >> 8) ^ key) >> 8) ^ key) >> 8) ^ key) & mask)
|
|
|
|
|
2015-08-11 05:51:00 +00:00
|
|
|
struct lltable *lltable_allocate_htbl(uint32_t hsize);
|
2008-12-15 06:53:09 +00:00
|
|
|
void lltable_free(struct lltable *);
|
2015-08-11 05:51:00 +00:00
|
|
|
void lltable_link(struct lltable *llt);
|
2012-07-31 11:31:12 +00:00
|
|
|
void lltable_prefix_free(int, struct sockaddr *,
|
|
|
|
struct sockaddr *, u_int);
|
2008-12-15 06:53:09 +00:00
|
|
|
int lltable_sysctl_dumparp(int, struct sysctl_req *);
|
2022-05-31 20:04:51 +00:00
|
|
|
size_t lltable_append_entry_queue(struct llentry *,
|
|
|
|
struct mbuf *, size_t);
|
2008-12-15 06:53:09 +00:00
|
|
|
|
2021-12-26 12:39:26 +00:00
|
|
|
struct lltable *in_lltable_get(struct ifnet *ifp);
|
|
|
|
struct lltable *in6_lltable_get(struct ifnet *ifp);
|
|
|
|
struct lltable *lltable_get(struct ifnet *ifp, int family);
|
|
|
|
|
2010-11-12 22:03:02 +00:00
|
|
|
size_t llentry_free(struct llentry *);
|
2008-12-15 06:53:09 +00:00
|
|
|
|
2015-08-10 12:03:59 +00:00
|
|
|
/* helper functions */
|
|
|
|
size_t lltable_drop_entry_queue(struct llentry *);
|
2015-11-07 11:12:00 +00:00
|
|
|
void lltable_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
|
2015-12-31 05:03:27 +00:00
|
|
|
const char *linkhdr, size_t linkhdrsize, int lladdr_off);
|
2015-12-13 07:39:49 +00:00
|
|
|
int lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
|
2015-12-31 05:03:27 +00:00
|
|
|
const char *linkhdr, size_t linkhdrsize, int lladdr_off);
|
2015-08-10 12:03:59 +00:00
|
|
|
|
2015-12-31 05:03:27 +00:00
|
|
|
int lltable_calc_llheader(struct ifnet *ifp, int family, char *lladdr,
|
|
|
|
char *buf, size_t *bufsize, int *lladdr_off);
|
|
|
|
void lltable_update_ifaddr(struct lltable *llt);
|
2015-08-20 12:05:17 +00:00
|
|
|
struct llentry *lltable_alloc_entry(struct lltable *llt, u_int flags,
|
|
|
|
const struct sockaddr *l4addr);
|
|
|
|
void lltable_free_entry(struct lltable *llt, struct llentry *lle);
|
2015-09-14 16:48:19 +00:00
|
|
|
int lltable_delete_addr(struct lltable *llt, u_int flags,
|
|
|
|
const struct sockaddr *l3addr);
|
2020-03-04 17:17:02 +00:00
|
|
|
int lltable_link_entry(struct lltable *llt, struct llentry *lle);
|
|
|
|
int lltable_unlink_entry(struct lltable *llt, struct llentry *lle);
|
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
2021-08-21 14:13:32 +00:00
|
|
|
void lltable_link_child_entry(struct llentry *parent_lle, struct llentry *child_lle);
|
|
|
|
void lltable_unlink_child_entry(struct llentry *child_lle);
|
2015-08-10 12:03:59 +00:00
|
|
|
void lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa);
|
|
|
|
struct ifnet *lltable_get_ifp(const struct lltable *llt);
|
|
|
|
int lltable_get_af(const struct lltable *llt);
|
|
|
|
|
2021-08-06 08:27:22 +00:00
|
|
|
bool lltable_acquire_wlock(struct ifnet *ifp, struct llentry *lle);
|
|
|
|
|
2015-08-10 12:03:59 +00:00
|
|
|
int lltable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f,
|
|
|
|
void *farg);
|
2022-05-30 07:51:15 +00:00
|
|
|
void lltable_delete_conditional(struct lltable *llt, llt_match_cb_t *func,
|
|
|
|
void *farg);
|
|
|
|
|
2008-12-15 06:53:09 +00:00
|
|
|
/*
|
|
|
|
* Generic link layer address lookup function.
|
|
|
|
*/
|
|
|
|
static __inline struct llentry *
|
|
|
|
lla_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
|
|
|
|
{
|
2014-11-15 18:54:07 +00:00
|
|
|
|
2015-08-08 17:48:54 +00:00
|
|
|
return (llt->llt_lookup(llt, flags, l3addr));
|
2008-12-15 06:53:09 +00:00
|
|
|
}
|
|
|
|
|
2021-08-02 22:39:00 +00:00
|
|
|
void llentry_request_feedback(struct llentry *lle);
|
|
|
|
void llentry_mark_used(struct llentry *lle);
|
|
|
|
time_t llentry_get_hittime(struct llentry *lle);
|
2021-12-26 18:42:12 +00:00
|
|
|
int llentry_get_upper_family(const struct llentry *lle, int default_family);
|
2021-08-02 22:39:00 +00:00
|
|
|
|
2018-03-17 17:05:48 +00:00
|
|
|
/*
|
|
|
|
* Notify the LLE code that the entry was used by datapath.
|
|
|
|
*/
|
|
|
|
static __inline void
|
2021-08-02 22:39:00 +00:00
|
|
|
llentry_provide_feedback(struct llentry *lle)
|
2018-03-17 17:05:48 +00:00
|
|
|
{
|
|
|
|
|
2021-08-02 22:39:00 +00:00
|
|
|
if (__predict_true(lle->r_skip_req == 0))
|
2018-03-17 17:05:48 +00:00
|
|
|
return;
|
2021-08-02 22:39:00 +00:00
|
|
|
llentry_mark_used(lle);
|
2018-03-17 17:05:48 +00:00
|
|
|
}
|
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
2021-08-21 14:13:32 +00:00
|
|
|
struct llentry *llentry_lookup_family(struct llentry *lle, int family);
|
2018-03-17 17:05:48 +00:00
|
|
|
|
2008-12-15 06:53:09 +00:00
|
|
|
int lla_rt_output(struct rt_msghdr *, struct rt_addrinfo *);
|
2013-01-25 23:58:21 +00:00
|
|
|
|
|
|
|
enum {
|
|
|
|
LLENTRY_RESOLVED,
|
|
|
|
LLENTRY_TIMEDOUT,
|
|
|
|
LLENTRY_DELETED,
|
|
|
|
LLENTRY_EXPIRED,
|
|
|
|
};
|
|
|
|
typedef void (*lle_event_fn)(void *, struct llentry *, int);
|
|
|
|
EVENTHANDLER_DECLARE(lle_event, lle_event_fn);
|
2008-12-15 06:53:09 +00:00
|
|
|
#endif /* _NET_IF_LLATBL_H_ */
|