2005-01-07 02:30:35 +00:00
|
|
|
/*-
|
2017-11-20 19:43:44 +00:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
*
|
1999-11-22 02:45:11 +00:00
|
|
|
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
|
|
|
* 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.
|
|
|
|
* 3. Neither the name of the project nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 THE PROJECT 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.
|
2007-12-10 16:03:40 +00:00
|
|
|
*
|
|
|
|
* $KAME: nd6.c,v 1.144 2001/05/24 07:44:00 itojun Exp $
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
|
|
|
|
2007-12-10 16:03:40 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
#include "opt_inet.h"
|
|
|
|
#include "opt_inet6.h"
|
2020-10-03 10:47:17 +00:00
|
|
|
#include "opt_route.h"
|
2000-07-04 16:35:15 +00:00
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.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>
|
2001-06-11 12:39:29 +00:00
|
|
|
#include <sys/callout.h>
|
2016-10-07 21:10:53 +00:00
|
|
|
#include <sys/lock.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/mbuf.h>
|
2016-10-07 21:10:53 +00:00
|
|
|
#include <sys/mutex.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/sockio.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/kernel.h>
|
2000-07-04 16:35:15 +00:00
|
|
|
#include <sys/protosw.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <sys/errno.h>
|
|
|
|
#include <sys/syslog.h>
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
#include <sys/rwlock.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <sys/queue.h>
|
2013-08-25 21:54:41 +00:00
|
|
|
#include <sys/sdt.h>
|
2001-06-11 12:39:29 +00:00
|
|
|
#include <sys/sysctl.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
#include <net/if.h>
|
2013-10-26 17:58:36 +00:00
|
|
|
#include <net/if_var.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <net/if_dl.h>
|
|
|
|
#include <net/if_types.h>
|
|
|
|
#include <net/route.h>
|
2020-07-12 11:24:23 +00:00
|
|
|
#include <net/route/route_ctl.h>
|
2020-04-16 17:20:18 +00:00
|
|
|
#include <net/route/nhop.h>
|
2008-12-02 21:37:28 +00:00
|
|
|
#include <net/vnet.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
#include <netinet/in.h>
|
2013-08-25 21:54:41 +00:00
|
|
|
#include <netinet/in_kdtrace.h>
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
#include <net/if_llatbl.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <netinet/if_ether.h>
|
2022-08-10 11:51:58 +00:00
|
|
|
#include <netinet6/in6_fib.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <netinet6/in6_var.h>
|
2000-07-04 16:35:15 +00:00
|
|
|
#include <netinet/ip6.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <netinet6/ip6_var.h>
|
2005-07-25 12:31:43 +00:00
|
|
|
#include <netinet6/scope6_var.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
#include <netinet6/nd6.h>
|
2009-09-12 22:08:20 +00:00
|
|
|
#include <netinet6/in6_ifattach.h>
|
2000-07-04 16:35:15 +00:00
|
|
|
#include <netinet/icmp6.h>
|
2010-08-19 11:31:03 +00:00
|
|
|
#include <netinet6/send.h>
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2005-10-21 16:23:01 +00:00
|
|
|
#include <sys/limits.h>
|
|
|
|
|
2006-10-22 11:52:19 +00:00
|
|
|
#include <security/mac/mac_framework.h>
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
#define ND6_SLOWTIMER_INTERVAL (60 * 60) /* 1 hour */
|
|
|
|
#define ND6_RECALC_REACHTM_INTERVAL (60 * 120) /* 2 hours */
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2013-04-26 12:50:32 +00:00
|
|
|
#define SIN6(s) ((const struct sockaddr_in6 *)(s))
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2016-05-20 04:45:08 +00:00
|
|
|
MALLOC_DEFINE(M_IP6NDP, "ip6ndp", "IPv6 Neighbor Discovery");
|
|
|
|
|
2010-04-29 11:52:42 +00:00
|
|
|
/* timer values */
|
|
|
|
VNET_DEFINE(int, nd6_prune) = 1; /* walk list every 1 seconds */
|
|
|
|
VNET_DEFINE(int, nd6_delay) = 5; /* delay first probe time 5 second */
|
|
|
|
VNET_DEFINE(int, nd6_umaxtries) = 3; /* maximum unicast query */
|
|
|
|
VNET_DEFINE(int, nd6_mmaxtries) = 3; /* maximum multicast query */
|
|
|
|
VNET_DEFINE(int, nd6_useloopback) = 1; /* use loopback interface for
|
|
|
|
* local traffic */
|
|
|
|
VNET_DEFINE(int, nd6_gctimer) = (60 * 60 * 24); /* 1 day: garbage
|
|
|
|
* collection timer */
|
2000-07-04 16:35:15 +00:00
|
|
|
|
|
|
|
/* preventing too many loops in ND option parsing */
|
2018-07-24 16:35:52 +00:00
|
|
|
VNET_DEFINE_STATIC(int, nd6_maxndopt) = 10; /* max # of ND options allowed */
|
2010-04-29 11:52:42 +00:00
|
|
|
|
|
|
|
VNET_DEFINE(int, nd6_maxnudhint) = 0; /* max # of subsequent upper
|
|
|
|
* layer hints */
|
Bump amount of queued packets in for unresolved ARP/NDP entries to 16.
Currently default behaviour is to keep only 1 packet per unresolved entry.
Ability to queue more than one packet was added 10 years ago, in r215207,
though the default value was kep intact.
Things have changed since that time. Systems tend to initiate multiple
connections at once for a variety of reasons.
For example, recent kern/252278 bug report describe happy-eyeball DNS
behaviour sending multiple requests to the DNS server.
The primary driver for upper value for the queue length determination is
memory consumption. Remote actors should not be able to easily exhaust
local memory by sending packets to unresolved arp/ND entries.
For now, bump value to 16 packets, to match Darwin implementation.
The proper approach would be to switch the limit to calculate memory
consumption instead of packet count and limit based on memory.
We should MFC this with a variation of D22447.
Reviewers: #manpages, #network, bz, emaste
Reviewed By: emaste, gbe(doc), jilles(doc)
MFC after: 1 month
Differential Revision: https://reviews.freebsd.org/D28068
2021-01-11 19:50:21 +00:00
|
|
|
VNET_DEFINE_STATIC(int, nd6_maxqueuelen) = 16; /* max pkts cached in unresolved
|
2010-04-29 11:52:42 +00:00
|
|
|
* ND entries */
|
2009-07-16 21:13:04 +00:00
|
|
|
#define V_nd6_maxndopt VNET(nd6_maxndopt)
|
|
|
|
#define V_nd6_maxqueuelen VNET(nd6_maxqueuelen)
|
2000-07-04 16:35:15 +00:00
|
|
|
|
2010-04-29 11:52:42 +00:00
|
|
|
#ifdef ND6_DEBUG
|
|
|
|
VNET_DEFINE(int, nd6_debug) = 1;
|
|
|
|
#else
|
|
|
|
VNET_DEFINE(int, nd6_debug) = 0;
|
|
|
|
#endif
|
2001-06-11 12:39:29 +00:00
|
|
|
|
2019-03-07 23:03:39 +00:00
|
|
|
static eventhandler_tag lle_event_eh, iflladdr_event_eh, ifnet_link_event_eh;
|
2015-07-20 06:58:32 +00:00
|
|
|
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
VNET_DEFINE(struct nd_prhead, nd_prefix);
|
2016-02-25 20:12:05 +00:00
|
|
|
VNET_DEFINE(struct rwlock, nd6_lock);
|
2016-10-07 21:10:53 +00:00
|
|
|
VNET_DEFINE(uint64_t, nd6_list_genid);
|
|
|
|
VNET_DEFINE(struct mtx, nd6_onlink_mtx);
|
2008-11-19 09:39:34 +00:00
|
|
|
|
2010-04-29 11:52:42 +00:00
|
|
|
VNET_DEFINE(int, nd6_recalc_reachtm_interval) = ND6_RECALC_REACHTM_INTERVAL;
|
2009-07-16 21:13:04 +00:00
|
|
|
#define V_nd6_recalc_reachtm_interval VNET(nd6_recalc_reachtm_interval)
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2010-08-19 11:31:03 +00:00
|
|
|
int (*send_sendso_input_hook)(struct mbuf *, struct ifnet *, int, int);
|
|
|
|
|
2022-08-10 11:51:58 +00:00
|
|
|
static bool nd6_is_new_addr_neighbor(const struct sockaddr_in6 *,
|
2012-10-22 21:49:56 +00:00
|
|
|
struct ifnet *);
|
2008-01-08 19:08:58 +00:00
|
|
|
static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *);
|
|
|
|
static void nd6_slowtimo(void *);
|
|
|
|
static int regen_tmpaddr(struct in6_ifaddr *);
|
2016-03-29 19:23:00 +00:00
|
|
|
static void nd6_free(struct llentry **, int);
|
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
|
|
|
static void nd6_free_redirect(const struct llentry *);
|
2008-01-08 19:08:58 +00:00
|
|
|
static void nd6_llinfo_timer(void *);
|
2015-10-04 08:33:16 +00:00
|
|
|
static void nd6_llinfo_settimer_locked(struct llentry *, long);
|
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
|
|
|
static int nd6_resolve_slow(struct ifnet *, int, int, struct mbuf *,
|
2016-06-02 17:51:29 +00:00
|
|
|
const struct sockaddr_in6 *, u_char *, uint32_t *, struct llentry **);
|
2015-09-16 14:26:28 +00:00
|
|
|
static int nd6_need_cache(struct ifnet *);
|
2001-06-11 12:39:29 +00:00
|
|
|
|
2018-07-24 16:35:52 +00:00
|
|
|
VNET_DEFINE_STATIC(struct callout, nd6_slowtimo_ch);
|
2009-07-16 21:13:04 +00:00
|
|
|
#define V_nd6_slowtimo_ch VNET(nd6_slowtimo_ch)
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
|
2019-11-19 20:54:17 +00:00
|
|
|
VNET_DEFINE_STATIC(struct callout, nd6_timer_ch);
|
2016-03-22 15:43:47 +00:00
|
|
|
#define V_nd6_timer_ch VNET(nd6_timer_ch)
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
|
2019-11-19 21:08:18 +00:00
|
|
|
SYSCTL_DECL(_net_inet6_icmp6);
|
|
|
|
|
2015-07-20 06:58:32 +00:00
|
|
|
static void
|
|
|
|
nd6_lle_event(void *arg __unused, struct llentry *lle, int evt)
|
|
|
|
{
|
|
|
|
struct rt_addrinfo rtinfo;
|
2015-08-11 09:26:11 +00:00
|
|
|
struct sockaddr_in6 dst;
|
2015-07-20 06:58:32 +00:00
|
|
|
struct sockaddr_dl gw;
|
|
|
|
struct ifnet *ifp;
|
|
|
|
int type;
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
int fibnum;
|
2015-07-20 06:58:32 +00:00
|
|
|
|
|
|
|
LLE_WLOCK_ASSERT(lle);
|
|
|
|
|
2015-08-11 09:26:11 +00:00
|
|
|
if (lltable_get_af(lle->lle_tbl) != AF_INET6)
|
|
|
|
return;
|
|
|
|
|
2015-07-20 06:58:32 +00:00
|
|
|
switch (evt) {
|
|
|
|
case LLENTRY_RESOLVED:
|
|
|
|
type = RTM_ADD;
|
|
|
|
KASSERT(lle->la_flags & LLE_VALID,
|
|
|
|
("%s: %p resolved but not valid?", __func__, lle));
|
|
|
|
break;
|
|
|
|
case LLENTRY_EXPIRED:
|
|
|
|
type = RTM_DELETE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-11 09:26:11 +00:00
|
|
|
ifp = lltable_get_ifp(lle->lle_tbl);
|
2015-07-20 06:58:32 +00:00
|
|
|
|
|
|
|
bzero(&dst, sizeof(dst));
|
|
|
|
bzero(&gw, sizeof(gw));
|
|
|
|
bzero(&rtinfo, sizeof(rtinfo));
|
2015-08-11 09:26:11 +00:00
|
|
|
lltable_fill_sa_entry(lle, (struct sockaddr *)&dst);
|
2015-07-20 06:58:32 +00:00
|
|
|
dst.sin6_scope_id = in6_getscopezone(ifp,
|
2015-08-11 09:26:11 +00:00
|
|
|
in6_addrscope(&dst.sin6_addr));
|
2015-07-20 06:58:32 +00:00
|
|
|
gw.sdl_len = sizeof(struct sockaddr_dl);
|
|
|
|
gw.sdl_family = AF_LINK;
|
|
|
|
gw.sdl_alen = ifp->if_addrlen;
|
|
|
|
gw.sdl_index = ifp->if_index;
|
|
|
|
gw.sdl_type = ifp->if_type;
|
|
|
|
if (evt == LLENTRY_RESOLVED)
|
2015-12-31 05:03:27 +00:00
|
|
|
bcopy(lle->ll_addr, gw.sdl_data, ifp->if_addrlen);
|
2015-07-20 06:58:32 +00:00
|
|
|
rtinfo.rti_info[RTAX_DST] = (struct sockaddr *)&dst;
|
|
|
|
rtinfo.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw;
|
|
|
|
rtinfo.rti_addrs = RTA_DST | RTA_GATEWAY;
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
fibnum = V_rt_add_addr_allfibs ? RT_ALL_FIBS : ifp->if_fib;
|
2015-07-20 06:58:32 +00:00
|
|
|
rt_missmsg_fib(type, &rtinfo, RTF_HOST | RTF_LLDATA | (
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
type == RTM_ADD ? RTF_UP: 0), 0, fibnum);
|
2015-07-20 06:58:32 +00:00
|
|
|
}
|
|
|
|
|
2015-12-31 05:03:27 +00:00
|
|
|
/*
|
|
|
|
* A handler for interface link layer address change event.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
nd6_iflladdr(void *arg __unused, struct ifnet *ifp)
|
|
|
|
{
|
2021-02-22 07:19:43 +00:00
|
|
|
if (ifp->if_afdata[AF_INET6] == NULL)
|
|
|
|
return;
|
2015-12-31 05:03:27 +00:00
|
|
|
|
|
|
|
lltable_update_ifaddr(LLTABLE6(ifp));
|
|
|
|
}
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
void
|
2007-07-05 16:23:49 +00:00
|
|
|
nd6_init(void)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
|
|
|
|
2016-10-07 21:10:53 +00:00
|
|
|
mtx_init(&V_nd6_onlink_mtx, "nd6 onlink", NULL, MTX_DEF);
|
|
|
|
rw_init(&V_nd6_lock, "nd6 list");
|
2016-02-25 20:12:05 +00:00
|
|
|
|
2008-11-19 09:39:34 +00:00
|
|
|
LIST_INIT(&V_nd_prefix);
|
2019-11-13 12:05:48 +00:00
|
|
|
nd6_defrouter_init();
|
2010-04-29 11:52:42 +00:00
|
|
|
|
2016-03-22 15:43:47 +00:00
|
|
|
/* Start timers. */
|
2021-08-09 17:21:43 +00:00
|
|
|
callout_init(&V_nd6_slowtimo_ch, 1);
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
|
Permit buiding kernels with options VIMAGE, restricted to only a single
active network stack instance. Turning on options VIMAGE at compile
time yields the following changes relative to default kernel build:
1) V_ accessor macros for virtualized variables resolve to structure
fields via base pointers, instead of being resolved as fields in global
structs or plain global variables. As an example, V_ifnet becomes:
options VIMAGE: ((struct vnet_net *) vnet_net)->_ifnet
default build: vnet_net_0._ifnet
options VIMAGE_GLOBALS: ifnet
2) INIT_VNET_* macros will declare and set up base pointers to be used
by V_ accessor macros, instead of resolving to whitespace:
INIT_VNET_NET(ifp->if_vnet); becomes
struct vnet_net *vnet_net = (ifp->if_vnet)->mod_data[VNET_MOD_NET];
3) Memory for vnet modules registered via vnet_mod_register() is now
allocated at run time in sys/kern/kern_vimage.c, instead of per vnet
module structs being declared as globals. If required, vnet modules
can now request the framework to provide them with allocated bzeroed
memory by filling in the vmi_size field in their vmi_modinfo structures.
4) structs socket, ifnet, inpcbinfo, tcpcb and syncache_head are
extended to hold a pointer to the parent vnet. options VIMAGE builds
will fill in those fields as required.
5) curvnet is introduced as a new global variable in options VIMAGE
builds, always pointing to the default and only struct vnet.
6) struct sysctl_oid has been extended with additional two fields to
store major and minor virtualization module identifiers, oid_v_subs and
oid_v_mod. SYSCTL_V_* family of macros will fill in those fields
accordingly, and store the offset in the appropriate vnet container
struct in oid_arg1.
In sysctl handlers dealing with virtualized sysctls, the
SYSCTL_RESOLVE_V_ARG1() macro will compute the address of the target
variable and make it available in arg1 variable for further processing.
Unused fields in structs vnet_inet, vnet_inet6 and vnet_ipfw have
been deleted.
Reviewed by: bz, rwatson
Approved by: julian (mentor)
2009-04-30 13:36:26 +00:00
|
|
|
nd6_slowtimo, curvnet);
|
2014-12-08 04:44:40 +00:00
|
|
|
|
2021-08-09 17:21:43 +00:00
|
|
|
callout_init(&V_nd6_timer_ch, 1);
|
2016-03-22 15:43:47 +00:00
|
|
|
callout_reset(&V_nd6_timer_ch, hz, nd6_timer, curvnet);
|
|
|
|
|
2014-12-08 04:44:40 +00:00
|
|
|
nd6_dad_init();
|
2015-12-31 05:03:27 +00:00
|
|
|
if (IS_DEFAULT_VNET(curvnet)) {
|
2015-07-20 06:58:32 +00:00
|
|
|
lle_event_eh = EVENTHANDLER_REGISTER(lle_event, nd6_lle_event,
|
|
|
|
NULL, EVENTHANDLER_PRI_ANY);
|
2015-12-31 05:03:27 +00:00
|
|
|
iflladdr_event_eh = EVENTHANDLER_REGISTER(iflladdr_event,
|
|
|
|
nd6_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
|
2019-03-07 23:03:39 +00:00
|
|
|
ifnet_link_event_eh = EVENTHANDLER_REGISTER(ifnet_link_event,
|
|
|
|
nd6_ifnet_link_event, NULL, EVENTHANDLER_PRI_ANY);
|
2015-12-31 05:03:27 +00:00
|
|
|
}
|
Introduce an infrastructure for dismantling vnet instances.
Vnet modules and protocol domains may now register destructor
functions to clean up and release per-module state. The destructor
mechanisms can be triggered by invoking "vimage -d", or a future
equivalent command which will be provided via the new jail framework.
While this patch introduces numerous placeholder destructor functions,
many of those are currently incomplete, thus leaking memory or (even
worse) failing to stop all running timers. Many of such issues are
already known and will be incrementaly fixed over the next weeks in
smaller incremental commits.
Apart from introducing new fields in structs ifnet, domain, protosw
and vnet_net, which requires the kernel and modules to be rebuilt, this
change should have no impact on nooptions VIMAGE builds, since vnet
destructors can only be called in VIMAGE kernels. Moreover,
destructor functions should be in general compiled in only in
options VIMAGE builds, except for kernel modules which can be safely
kldunloaded at run time.
Bump __FreeBSD_version to 800097.
Reviewed by: bz, julian
Approved by: rwatson, kib (re), julian (mentor)
2009-06-08 17:15:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef VIMAGE
|
|
|
|
void
|
2022-07-26 19:10:58 +00:00
|
|
|
nd6_destroy(void)
|
Introduce an infrastructure for dismantling vnet instances.
Vnet modules and protocol domains may now register destructor
functions to clean up and release per-module state. The destructor
mechanisms can be triggered by invoking "vimage -d", or a future
equivalent command which will be provided via the new jail framework.
While this patch introduces numerous placeholder destructor functions,
many of those are currently incomplete, thus leaking memory or (even
worse) failing to stop all running timers. Many of such issues are
already known and will be incrementaly fixed over the next weeks in
smaller incremental commits.
Apart from introducing new fields in structs ifnet, domain, protosw
and vnet_net, which requires the kernel and modules to be rebuilt, this
change should have no impact on nooptions VIMAGE builds, since vnet
destructors can only be called in VIMAGE kernels. Moreover,
destructor functions should be in general compiled in only in
options VIMAGE builds, except for kernel modules which can be safely
kldunloaded at run time.
Bump __FreeBSD_version to 800097.
Reviewed by: bz, julian
Approved by: rwatson, kib (re), julian (mentor)
2009-06-08 17:15:40 +00:00
|
|
|
{
|
2008-08-20 01:05:56 +00:00
|
|
|
|
Introduce an infrastructure for dismantling vnet instances.
Vnet modules and protocol domains may now register destructor
functions to clean up and release per-module state. The destructor
mechanisms can be triggered by invoking "vimage -d", or a future
equivalent command which will be provided via the new jail framework.
While this patch introduces numerous placeholder destructor functions,
many of those are currently incomplete, thus leaking memory or (even
worse) failing to stop all running timers. Many of such issues are
already known and will be incrementaly fixed over the next weeks in
smaller incremental commits.
Apart from introducing new fields in structs ifnet, domain, protosw
and vnet_net, which requires the kernel and modules to be rebuilt, this
change should have no impact on nooptions VIMAGE builds, since vnet
destructors can only be called in VIMAGE kernels. Moreover,
destructor functions should be in general compiled in only in
options VIMAGE builds, except for kernel modules which can be safely
kldunloaded at run time.
Bump __FreeBSD_version to 800097.
Reviewed by: bz, julian
Approved by: rwatson, kib (re), julian (mentor)
2009-06-08 17:15:40 +00:00
|
|
|
callout_drain(&V_nd6_slowtimo_ch);
|
|
|
|
callout_drain(&V_nd6_timer_ch);
|
2015-12-31 05:03:27 +00:00
|
|
|
if (IS_DEFAULT_VNET(curvnet)) {
|
2019-03-07 23:03:39 +00:00
|
|
|
EVENTHANDLER_DEREGISTER(ifnet_link_event, ifnet_link_event_eh);
|
2015-07-20 06:58:32 +00:00
|
|
|
EVENTHANDLER_DEREGISTER(lle_event, lle_event_eh);
|
2015-12-31 05:03:27 +00:00
|
|
|
EVENTHANDLER_DEREGISTER(iflladdr_event, iflladdr_event_eh);
|
|
|
|
}
|
2016-02-25 20:12:05 +00:00
|
|
|
rw_destroy(&V_nd6_lock);
|
2016-10-07 21:10:53 +00:00
|
|
|
mtx_destroy(&V_nd6_onlink_mtx);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
Introduce an infrastructure for dismantling vnet instances.
Vnet modules and protocol domains may now register destructor
functions to clean up and release per-module state. The destructor
mechanisms can be triggered by invoking "vimage -d", or a future
equivalent command which will be provided via the new jail framework.
While this patch introduces numerous placeholder destructor functions,
many of those are currently incomplete, thus leaking memory or (even
worse) failing to stop all running timers. Many of such issues are
already known and will be incrementaly fixed over the next weeks in
smaller incremental commits.
Apart from introducing new fields in structs ifnet, domain, protosw
and vnet_net, which requires the kernel and modules to be rebuilt, this
change should have no impact on nooptions VIMAGE builds, since vnet
destructors can only be called in VIMAGE kernels. Moreover,
destructor functions should be in general compiled in only in
options VIMAGE builds, except for kernel modules which can be safely
kldunloaded at run time.
Bump __FreeBSD_version to 800097.
Reviewed by: bz, julian
Approved by: rwatson, kib (re), julian (mentor)
2009-06-08 17:15:40 +00:00
|
|
|
#endif
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2003-10-17 15:46:31 +00:00
|
|
|
struct nd_ifinfo *
|
2007-07-05 16:23:49 +00:00
|
|
|
nd6_ifattach(struct ifnet *ifp)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2003-10-17 15:46:31 +00:00
|
|
|
struct nd_ifinfo *nd;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2016-02-12 20:52:53 +00:00
|
|
|
nd = malloc(sizeof(*nd), M_IP6NDP, M_WAITOK | M_ZERO);
|
2003-10-17 15:46:31 +00:00
|
|
|
nd->initialized = 1;
|
2000-07-04 16:35:15 +00:00
|
|
|
|
2003-10-17 15:46:31 +00:00
|
|
|
nd->chlim = IPV6_DEFHLIM;
|
|
|
|
nd->basereachable = REACHABLE_TIME;
|
|
|
|
nd->reachable = ND_COMPUTE_RTIME(nd->basereachable);
|
|
|
|
nd->retrans = RETRANS_TIMER;
|
2009-09-12 22:08:20 +00:00
|
|
|
|
|
|
|
nd->flags = ND6_IFF_PERFORMNUD;
|
|
|
|
|
2020-11-25 20:58:01 +00:00
|
|
|
/* Set IPv6 disabled on all interfaces but loopback by default. */
|
|
|
|
if ((ifp->if_flags & IFF_LOOPBACK) == 0)
|
|
|
|
nd->flags |= ND6_IFF_IFDISABLED;
|
|
|
|
|
2013-07-02 16:58:15 +00:00
|
|
|
/* A loopback interface always has ND6_IFF_AUTO_LINKLOCAL.
|
|
|
|
* XXXHRS: Clear ND6_IFF_AUTO_LINKLOCAL on an IFT_BRIDGE interface by
|
|
|
|
* default regardless of the V_ip6_auto_linklocal configuration to
|
|
|
|
* give a reasonable default behavior.
|
|
|
|
*/
|
2021-03-16 02:38:23 +00:00
|
|
|
if ((V_ip6_auto_linklocal && ifp->if_type != IFT_BRIDGE) ||
|
|
|
|
(ifp->if_flags & IFF_LOOPBACK))
|
2009-09-12 22:08:20 +00:00
|
|
|
nd->flags |= ND6_IFF_AUTO_LINKLOCAL;
|
2013-07-02 16:58:15 +00:00
|
|
|
/*
|
|
|
|
* A loopback interface does not need to accept RTADV.
|
|
|
|
* XXXHRS: Clear ND6_IFF_ACCEPT_RTADV on an IFT_BRIDGE interface by
|
|
|
|
* default regardless of the V_ip6_accept_rtadv configuration to
|
|
|
|
* prevent the interface from accepting RA messages arrived
|
|
|
|
* on one of the member interfaces with ND6_IFF_ACCEPT_RTADV.
|
|
|
|
*/
|
|
|
|
if (V_ip6_accept_rtadv &&
|
|
|
|
!(ifp->if_flags & IFF_LOOPBACK) &&
|
2020-11-25 20:58:01 +00:00
|
|
|
(ifp->if_type != IFT_BRIDGE)) {
|
2013-07-02 16:58:15 +00:00
|
|
|
nd->flags |= ND6_IFF_ACCEPT_RTADV;
|
2020-11-25 20:58:01 +00:00
|
|
|
/* If we globally accept rtadv, assume IPv6 on. */
|
|
|
|
nd->flags &= ~ND6_IFF_IFDISABLED;
|
|
|
|
}
|
- Accept Router Advertisement messages even when net.inet6.ip6.forwarding=1.
- A new per-interface knob IFF_ND6_NO_RADR and sysctl IPV6CTL_NO_RADR.
This controls if accepting a route in an RA message as the default route.
The default value for each interface can be set by net.inet6.ip6.no_radr.
The system wide default value is 0.
- A new sysctl: net.inet6.ip6.norbit_raif. This controls if setting R-bit in
NA on RA accepting interfaces. The default is 0 (R-bit is set based on
net.inet6.ip6.forwarding).
Background:
IPv6 host/router model suggests a router sends an RA and a host accepts it for
router discovery. Because of that, KAME implementation does not allow
accepting RAs when net.inet6.ip6.forwarding=1. Accepting RAs on a router can
make the routing table confused since it can change the default router
unintentionally.
However, in practice there are cases where we cannot distinguish a host from
a router clearly. For example, a customer edge router often works as a host
against the ISP, and as a router against the LAN at the same time. Another
example is a complex network configurations like an L2TP tunnel for IPv6
connection to Internet over an Ethernet link with another native IPv6 subnet.
In this case, the physical interface for the native IPv6 subnet works as a
host, and the pseudo-interface for L2TP works as the default IP forwarding
route.
Problem:
Disabling processing RA messages when net.inet6.ip6.forwarding=1 and
accepting them when net.inet6.ip6.forward=0 cause the following practical
issues:
- A router cannot perform SLAAC. It becomes a problem if a box has
multiple interfaces and you want to use SLAAC on some of them, for
example. A customer edge router for IPv6 Internet access service
using an IPv6-over-IPv6 tunnel sometimes needs SLAAC on the
physical interface for administration purpose; updating firmware
and so on (link-local addresses can be used there, but GUAs by
SLAAC are often used for scalability).
- When a host has multiple IPv6 interfaces and it receives multiple RAs on
them, controlling the default route is difficult. Router preferences
defined in RFC 4191 works only when the routers on the links are
under your control.
Details of Implementation Changes:
Router Advertisement messages will be accepted even when
net.inet6.ip6.forwarding=1. More precisely, the conditions are as
follow:
(ACCEPT_RTADV && !NO_RADR && !ip6.forwarding)
=> Normal RA processing on that interface. (as IPv6 host)
(ACCEPT_RTADV && (NO_RADR || ip6.forwarding))
=> Accept RA but add the router to the defroute list with
rtlifetime=0 unconditionally. This effectively prevents
from setting the received router address as the box's
default route.
(!ACCEPT_RTADV)
=> No RA processing on that interface.
ACCEPT_RTADV and NO_RADR are per-interface knob. In short, all interface
are classified as "RA-accepting" or not. An RA-accepting interface always
processes RA messages regardless of ip6.forwarding. The difference caused by
NO_RADR or ip6.forwarding is whether the RA source address is considered as
the default router or not.
R-bit in NA on the RA accepting interfaces is set based on
net.inet6.ip6.forwarding. While RFC 6204 W-1 rule (for CPE case) suggests
a router should disable the R-bit completely even when the box has
net.inet6.ip6.forwarding=1, I believe there is no technical reason with
doing so. This behavior can be set by a new sysctl net.inet6.ip6.norbit_raif
(the default is 0).
Usage:
# ifconfig fxp0 inet6 accept_rtadv
=> accept RA on fxp0
# ifconfig fxp0 inet6 accept_rtadv no_radr
=> accept RA on fxp0 but ignore default route information in it.
# sysctl net.inet6.ip6.norbit_no_radr=1
=> R-bit in NAs on RA accepting interfaces will always be set to 0.
2011-06-06 02:14:23 +00:00
|
|
|
if (V_ip6_no_radr && !(ifp->if_flags & IFF_LOOPBACK))
|
|
|
|
nd->flags |= ND6_IFF_NO_RADR;
|
2003-10-17 15:46:31 +00:00
|
|
|
|
|
|
|
/* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */
|
|
|
|
nd6_setmtu0(ifp, nd);
|
|
|
|
|
|
|
|
return nd;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
Get closer to a VIMAGE network stack teardown from top to bottom rather
than removing the network interfaces first. This change is rather larger
and convoluted as the ordering requirements cannot be separated.
Move the pfil(9) framework to SI_SUB_PROTO_PFIL, move Firewalls and
related modules to their own SI_SUB_PROTO_FIREWALL.
Move initialization of "physical" interfaces to SI_SUB_DRIVERS,
move virtual (cloned) interfaces to SI_SUB_PSEUDO.
Move Multicast to SI_SUB_PROTO_MC.
Re-work parts of multicast initialisation and teardown, not taking the
huge amount of memory into account if used as a module yet.
For interface teardown we try to do as many of them as we can on
SI_SUB_INIT_IF, but for some this makes no sense, e.g., when tunnelling
over a higher layer protocol such as IP. In that case the interface
has to go along (or before) the higher layer protocol is shutdown.
Kernel hhooks need to go last on teardown as they may be used at various
higher layers and we cannot remove them before we cleaned up the higher
layers.
For interface teardown there are multiple paths:
(a) a cloned interface is destroyed (inside a VIMAGE or in the base system),
(b) any interface is moved from a virtual network stack to a different
network stack ("vmove"), or (c) a virtual network stack is being shut down.
All code paths go through if_detach_internal() where we, depending on the
vmove flag or the vnet state, make a decision on how much to shut down;
in case we are destroying a VNET the individual protocol layers will
cleanup their own parts thus we cannot do so again for each interface as
we end up with, e.g., double-frees, destroying locks twice or acquiring
already destroyed locks.
When calling into protocol cleanups we equally have to tell them
whether they need to detach upper layer protocols ("ulp") or not
(e.g., in6_ifdetach()).
Provide or enahnce helper functions to do proper cleanup at a protocol
rather than at an interface level.
Approved by: re (hrs)
Obtained from: projects/vnet
Reviewed by: gnn, jhb
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D6747
2016-06-21 13:48:49 +00:00
|
|
|
nd6_ifdetach(struct ifnet *ifp, struct nd_ifinfo *nd)
|
2003-10-17 15:46:31 +00:00
|
|
|
{
|
2019-01-09 01:11:19 +00:00
|
|
|
struct epoch_tracker et;
|
Get closer to a VIMAGE network stack teardown from top to bottom rather
than removing the network interfaces first. This change is rather larger
and convoluted as the ordering requirements cannot be separated.
Move the pfil(9) framework to SI_SUB_PROTO_PFIL, move Firewalls and
related modules to their own SI_SUB_PROTO_FIREWALL.
Move initialization of "physical" interfaces to SI_SUB_DRIVERS,
move virtual (cloned) interfaces to SI_SUB_PSEUDO.
Move Multicast to SI_SUB_PROTO_MC.
Re-work parts of multicast initialisation and teardown, not taking the
huge amount of memory into account if used as a module yet.
For interface teardown we try to do as many of them as we can on
SI_SUB_INIT_IF, but for some this makes no sense, e.g., when tunnelling
over a higher layer protocol such as IP. In that case the interface
has to go along (or before) the higher layer protocol is shutdown.
Kernel hhooks need to go last on teardown as they may be used at various
higher layers and we cannot remove them before we cleaned up the higher
layers.
For interface teardown there are multiple paths:
(a) a cloned interface is destroyed (inside a VIMAGE or in the base system),
(b) any interface is moved from a virtual network stack to a different
network stack ("vmove"), or (c) a virtual network stack is being shut down.
All code paths go through if_detach_internal() where we, depending on the
vmove flag or the vnet state, make a decision on how much to shut down;
in case we are destroying a VNET the individual protocol layers will
cleanup their own parts thus we cannot do so again for each interface as
we end up with, e.g., double-frees, destroying locks twice or acquiring
already destroyed locks.
When calling into protocol cleanups we equally have to tell them
whether they need to detach upper layer protocols ("ulp") or not
(e.g., in6_ifdetach()).
Provide or enahnce helper functions to do proper cleanup at a protocol
rather than at an interface level.
Approved by: re (hrs)
Obtained from: projects/vnet
Reviewed by: gnn, jhb
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D6747
2016-06-21 13:48:49 +00:00
|
|
|
struct ifaddr *ifa, *next;
|
|
|
|
|
2019-01-09 01:11:19 +00:00
|
|
|
NET_EPOCH_ENTER(et);
|
2018-05-18 20:13:34 +00:00
|
|
|
CK_STAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
|
Get closer to a VIMAGE network stack teardown from top to bottom rather
than removing the network interfaces first. This change is rather larger
and convoluted as the ordering requirements cannot be separated.
Move the pfil(9) framework to SI_SUB_PROTO_PFIL, move Firewalls and
related modules to their own SI_SUB_PROTO_FIREWALL.
Move initialization of "physical" interfaces to SI_SUB_DRIVERS,
move virtual (cloned) interfaces to SI_SUB_PSEUDO.
Move Multicast to SI_SUB_PROTO_MC.
Re-work parts of multicast initialisation and teardown, not taking the
huge amount of memory into account if used as a module yet.
For interface teardown we try to do as many of them as we can on
SI_SUB_INIT_IF, but for some this makes no sense, e.g., when tunnelling
over a higher layer protocol such as IP. In that case the interface
has to go along (or before) the higher layer protocol is shutdown.
Kernel hhooks need to go last on teardown as they may be used at various
higher layers and we cannot remove them before we cleaned up the higher
layers.
For interface teardown there are multiple paths:
(a) a cloned interface is destroyed (inside a VIMAGE or in the base system),
(b) any interface is moved from a virtual network stack to a different
network stack ("vmove"), or (c) a virtual network stack is being shut down.
All code paths go through if_detach_internal() where we, depending on the
vmove flag or the vnet state, make a decision on how much to shut down;
in case we are destroying a VNET the individual protocol layers will
cleanup their own parts thus we cannot do so again for each interface as
we end up with, e.g., double-frees, destroying locks twice or acquiring
already destroyed locks.
When calling into protocol cleanups we equally have to tell them
whether they need to detach upper layer protocols ("ulp") or not
(e.g., in6_ifdetach()).
Provide or enahnce helper functions to do proper cleanup at a protocol
rather than at an interface level.
Approved by: re (hrs)
Obtained from: projects/vnet
Reviewed by: gnn, jhb
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D6747
2016-06-21 13:48:49 +00:00
|
|
|
if (ifa->ifa_addr->sa_family != AF_INET6)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* stop DAD processing */
|
|
|
|
nd6_dad_stop(ifa);
|
|
|
|
}
|
2019-01-09 01:11:19 +00:00
|
|
|
NET_EPOCH_EXIT(et);
|
2003-10-17 15:46:31 +00:00
|
|
|
|
|
|
|
free(nd, M_IP6NDP);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reset ND level link MTU. This function is called when the physical MTU
|
|
|
|
* changes, which means we might have to adjust the ND level MTU.
|
|
|
|
*/
|
|
|
|
void
|
2007-07-05 16:23:49 +00:00
|
|
|
nd6_setmtu(struct ifnet *ifp)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2015-12-14 19:44:49 +00:00
|
|
|
if (ifp->if_afdata[AF_INET6] == NULL)
|
|
|
|
return;
|
2003-10-17 15:46:31 +00:00
|
|
|
|
|
|
|
nd6_setmtu0(ifp, ND_IFINFO(ifp));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX todo: do not maintain copy of ifp->if_mtu in ndi->maxmtu */
|
|
|
|
void
|
2007-07-05 16:23:49 +00:00
|
|
|
nd6_setmtu0(struct ifnet *ifp, struct nd_ifinfo *ndi)
|
2003-10-17 15:46:31 +00:00
|
|
|
{
|
2003-10-20 15:27:48 +00:00
|
|
|
u_int32_t omaxmtu;
|
2003-10-17 15:46:31 +00:00
|
|
|
|
2003-10-20 15:27:48 +00:00
|
|
|
omaxmtu = ndi->maxmtu;
|
2018-04-13 21:18:04 +00:00
|
|
|
ndi->maxmtu = ifp->if_mtu;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2003-10-20 15:27:48 +00:00
|
|
|
/*
|
|
|
|
* Decreasing the interface MTU under IPV6 minimum MTU may cause
|
|
|
|
* undesirable situation. We thus notify the operator of the change
|
|
|
|
* explicitly. The check for omaxmtu is necessary to restrict the
|
|
|
|
* log to the case of changing the MTU, not initializing it.
|
|
|
|
*/
|
|
|
|
if (omaxmtu >= IPV6_MMTU && ndi->maxmtu < IPV6_MMTU) {
|
|
|
|
log(LOG_NOTICE, "nd6_setmtu0: "
|
|
|
|
"new link MTU on %s (%lu) is too small for IPv6\n",
|
|
|
|
if_name(ifp), (unsigned long)ndi->maxmtu);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2003-10-20 15:27:48 +00:00
|
|
|
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (ndi->maxmtu > V_in6_maxmtu)
|
2003-10-20 15:27:48 +00:00
|
|
|
in6_setmaxmtu(); /* check all interfaces just in case */
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-07-05 16:23:49 +00:00
|
|
|
nd6_option_init(void *opt, int icmp6len, union nd_opts *ndopts)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2003-10-09 16:13:47 +00:00
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
bzero(ndopts, sizeof(*ndopts));
|
|
|
|
ndopts->nd_opts_search = (struct nd_opt_hdr *)opt;
|
|
|
|
ndopts->nd_opts_last
|
|
|
|
= (struct nd_opt_hdr *)(((u_char *)opt) + icmp6len);
|
|
|
|
|
|
|
|
if (icmp6len == 0) {
|
|
|
|
ndopts->nd_opts_done = 1;
|
|
|
|
ndopts->nd_opts_search = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Take one ND option.
|
|
|
|
*/
|
|
|
|
struct nd_opt_hdr *
|
2007-07-05 16:23:49 +00:00
|
|
|
nd6_option(union nd_opts *ndopts)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
|
|
|
struct nd_opt_hdr *nd_opt;
|
|
|
|
int olen;
|
|
|
|
|
2012-05-25 09:27:16 +00:00
|
|
|
KASSERT(ndopts != NULL, ("%s: ndopts == NULL", __func__));
|
|
|
|
KASSERT(ndopts->nd_opts_last != NULL, ("%s: uninitialized ndopts",
|
|
|
|
__func__));
|
2005-10-19 10:09:19 +00:00
|
|
|
if (ndopts->nd_opts_search == NULL)
|
1999-11-22 02:45:11 +00:00
|
|
|
return NULL;
|
|
|
|
if (ndopts->nd_opts_done)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
nd_opt = ndopts->nd_opts_search;
|
|
|
|
|
2001-02-26 03:41:13 +00:00
|
|
|
/* make sure nd_opt_len is inside the buffer */
|
|
|
|
if ((caddr_t)&nd_opt->nd_opt_len >= (caddr_t)ndopts->nd_opts_last) {
|
|
|
|
bzero(ndopts, sizeof(*ndopts));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
olen = nd_opt->nd_opt_len << 3;
|
|
|
|
if (olen == 0) {
|
|
|
|
/*
|
|
|
|
* Message validation requires that all included
|
|
|
|
* options have a length that is greater than zero.
|
|
|
|
*/
|
|
|
|
bzero(ndopts, sizeof(*ndopts));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ndopts->nd_opts_search = (struct nd_opt_hdr *)((caddr_t)nd_opt + olen);
|
2001-02-26 03:41:13 +00:00
|
|
|
if (ndopts->nd_opts_search > ndopts->nd_opts_last) {
|
|
|
|
/* option overruns the end of buffer, invalid */
|
|
|
|
bzero(ndopts, sizeof(*ndopts));
|
|
|
|
return NULL;
|
|
|
|
} else if (ndopts->nd_opts_search == ndopts->nd_opts_last) {
|
|
|
|
/* reached the end of options chain */
|
1999-11-22 02:45:11 +00:00
|
|
|
ndopts->nd_opts_done = 1;
|
|
|
|
ndopts->nd_opts_search = NULL;
|
|
|
|
}
|
|
|
|
return nd_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse multiple ND options.
|
|
|
|
* This function is much easier to use, for ND routines that do not need
|
|
|
|
* multiple options of the same type.
|
|
|
|
*/
|
|
|
|
int
|
2007-07-05 16:23:49 +00:00
|
|
|
nd6_options(union nd_opts *ndopts)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
|
|
|
struct nd_opt_hdr *nd_opt;
|
|
|
|
int i = 0;
|
|
|
|
|
2012-05-25 09:27:16 +00:00
|
|
|
KASSERT(ndopts != NULL, ("%s: ndopts == NULL", __func__));
|
|
|
|
KASSERT(ndopts->nd_opts_last != NULL, ("%s: uninitialized ndopts",
|
|
|
|
__func__));
|
2005-10-19 10:09:19 +00:00
|
|
|
if (ndopts->nd_opts_search == NULL)
|
1999-11-22 02:45:11 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
nd_opt = nd6_option(ndopts);
|
2005-10-19 10:09:19 +00:00
|
|
|
if (nd_opt == NULL && ndopts->nd_opts_last == NULL) {
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* Message validation requires that all included
|
|
|
|
* options have a length that is greater than zero.
|
|
|
|
*/
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_nd_badopt);
|
1999-11-22 02:45:11 +00:00
|
|
|
bzero(ndopts, sizeof(*ndopts));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2005-10-19 10:09:19 +00:00
|
|
|
if (nd_opt == NULL)
|
1999-11-22 02:45:11 +00:00
|
|
|
goto skip1;
|
|
|
|
|
|
|
|
switch (nd_opt->nd_opt_type) {
|
|
|
|
case ND_OPT_SOURCE_LINKADDR:
|
|
|
|
case ND_OPT_TARGET_LINKADDR:
|
|
|
|
case ND_OPT_MTU:
|
|
|
|
case ND_OPT_REDIRECTED_HEADER:
|
2015-03-02 17:30:26 +00:00
|
|
|
case ND_OPT_NONCE:
|
1999-11-22 02:45:11 +00:00
|
|
|
if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_INFO,
|
|
|
|
"duplicated ND6 option found (type=%d)\n",
|
|
|
|
nd_opt->nd_opt_type));
|
1999-11-22 02:45:11 +00:00
|
|
|
/* XXX bark? */
|
|
|
|
} else {
|
|
|
|
ndopts->nd_opt_array[nd_opt->nd_opt_type]
|
|
|
|
= nd_opt;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ND_OPT_PREFIX_INFORMATION:
|
|
|
|
if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0) {
|
|
|
|
ndopts->nd_opt_array[nd_opt->nd_opt_type]
|
|
|
|
= nd_opt;
|
|
|
|
}
|
|
|
|
ndopts->nd_opts_pi_end =
|
|
|
|
(struct nd_opt_prefix_info *)nd_opt;
|
|
|
|
break;
|
2012-03-04 18:51:45 +00:00
|
|
|
/* What about ND_OPT_ROUTE_INFO? RFC 4191 */
|
|
|
|
case ND_OPT_RDNSS: /* RFC 6106 */
|
|
|
|
case ND_OPT_DNSSL: /* RFC 6106 */
|
|
|
|
/*
|
|
|
|
* Silently ignore options we know and do not care about
|
|
|
|
* in the kernel.
|
|
|
|
*/
|
|
|
|
break;
|
1999-11-22 02:45:11 +00:00
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* Unknown options must be silently ignored,
|
2016-05-03 18:05:43 +00:00
|
|
|
* to accommodate future extension to the protocol.
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_DEBUG,
|
1999-11-22 02:45:11 +00:00
|
|
|
"nd6_options: unsupported option %d - "
|
2001-06-11 12:39:29 +00:00
|
|
|
"option ignored\n", nd_opt->nd_opt_type));
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
skip1:
|
|
|
|
i++;
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (i > V_nd6_maxndopt) {
|
2009-04-12 13:22:33 +00:00
|
|
|
ICMP6STAT_INC(icp6s_nd_toomanyopt);
|
2001-06-11 12:39:29 +00:00
|
|
|
nd6log((LOG_INFO, "too many loop in nd opt\n"));
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ndopts->nd_opts_done)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2005-10-21 16:23:01 +00:00
|
|
|
* ND6 timer routine to handle ND6 entries
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2015-10-04 08:33:16 +00:00
|
|
|
static void
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
nd6_llinfo_settimer_locked(struct llentry *ln, long tick)
|
2005-10-21 16:23:01 +00:00
|
|
|
{
|
2009-11-12 14:48:36 +00:00
|
|
|
int canceled;
|
|
|
|
|
2010-11-29 00:04:08 +00:00
|
|
|
LLE_WLOCK_ASSERT(ln);
|
|
|
|
|
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
|
|
|
/* Do not schedule timers for child LLEs. */
|
|
|
|
if (ln->la_flags & LLE_CHILD)
|
|
|
|
return;
|
|
|
|
|
2005-10-21 16:23:01 +00:00
|
|
|
if (tick < 0) {
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
ln->la_expire = 0;
|
2005-10-21 16:23:01 +00:00
|
|
|
ln->ln_ntick = 0;
|
2015-08-11 12:38:54 +00:00
|
|
|
canceled = callout_stop(&ln->lle_timer);
|
2005-10-21 16:23:01 +00:00
|
|
|
} else {
|
2013-08-05 20:13:02 +00:00
|
|
|
ln->la_expire = time_uptime + tick / hz;
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
LLE_ADDREF(ln);
|
2005-10-21 16:23:01 +00:00
|
|
|
if (tick > INT_MAX) {
|
|
|
|
ln->ln_ntick = tick - INT_MAX;
|
2015-08-11 12:38:54 +00:00
|
|
|
canceled = callout_reset(&ln->lle_timer, INT_MAX,
|
2005-10-21 16:23:01 +00:00
|
|
|
nd6_llinfo_timer, ln);
|
|
|
|
} else {
|
|
|
|
ln->ln_ntick = 0;
|
2015-08-11 12:38:54 +00:00
|
|
|
canceled = callout_reset(&ln->lle_timer, tick,
|
2005-10-21 16:23:01 +00:00
|
|
|
nd6_llinfo_timer, ln);
|
|
|
|
}
|
|
|
|
}
|
2015-11-13 22:51:35 +00:00
|
|
|
if (canceled > 0)
|
2009-11-12 14:48:36 +00:00
|
|
|
LLE_REMREF(ln);
|
2005-10-21 16:23:01 +00:00
|
|
|
}
|
|
|
|
|
2015-09-05 14:14:03 +00:00
|
|
|
/*
|
2015-10-04 08:21:15 +00:00
|
|
|
* Gets source address of the first packet in hold queue
|
|
|
|
* and stores it in @src.
|
|
|
|
* Returns pointer to @src (if hold queue is not empty) or NULL.
|
|
|
|
*
|
|
|
|
* Set noinline to be dtrace-friendly
|
|
|
|
*/
|
|
|
|
static __noinline struct in6_addr *
|
2015-09-05 14:14:03 +00:00
|
|
|
nd6_llinfo_get_holdsrc(struct llentry *ln, struct in6_addr *src)
|
|
|
|
{
|
|
|
|
struct ip6_hdr hdr;
|
|
|
|
struct mbuf *m;
|
|
|
|
|
|
|
|
if (ln->la_hold == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* assume every packet in la_hold has the same IP header
|
|
|
|
*/
|
|
|
|
m = ln->la_hold;
|
2015-10-04 07:02:17 +00:00
|
|
|
if (sizeof(hdr) > m->m_len)
|
2015-09-05 14:14:03 +00:00
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr);
|
|
|
|
*src = hdr.ip6_src;
|
|
|
|
|
|
|
|
return (src);
|
|
|
|
}
|
|
|
|
|
2015-12-13 07:39:49 +00:00
|
|
|
/*
|
|
|
|
* Checks if we need to switch from STALE state.
|
|
|
|
*
|
|
|
|
* RFC 4861 requires switching from STALE to DELAY state
|
|
|
|
* on first packet matching entry, waiting V_nd6_delay and
|
|
|
|
* transition to PROBE state (if upper layer confirmation was
|
|
|
|
* not received).
|
|
|
|
*
|
|
|
|
* This code performs a bit differently:
|
|
|
|
* On packet hit we don't change state (but desired state
|
|
|
|
* can be guessed by control plane). However, after V_nd6_delay
|
|
|
|
* seconds code will transition to PROBE state (so DELAY state
|
|
|
|
* is kinda skipped in most situations).
|
|
|
|
*
|
|
|
|
* Typically, V_nd6_gctimer is bigger than V_nd6_delay, so
|
|
|
|
* we perform the following upon entering STALE state:
|
|
|
|
*
|
|
|
|
* 1) Arm timer to run each V_nd6_delay seconds to make sure that
|
|
|
|
* if packet was transmitted at the start of given interval, we
|
|
|
|
* would be able to switch to PROBE state in V_nd6_delay seconds
|
|
|
|
* as user expects.
|
|
|
|
*
|
|
|
|
* 2) Reschedule timer until original V_nd6_gctimer expires keeping
|
|
|
|
* lle in STALE state (remaining timer value stored in lle_remtime).
|
|
|
|
*
|
|
|
|
* 3) Reschedule timer if packet was transmitted less that V_nd6_delay
|
|
|
|
* seconds ago.
|
|
|
|
*
|
|
|
|
* Returns non-zero value if the entry is still STALE (storing
|
|
|
|
* the next timer interval in @pdelay).
|
|
|
|
*
|
|
|
|
* Returns zero value if original timer expired or we need to switch to
|
|
|
|
* PROBE (store that in @do_switch variable).
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
nd6_is_stale(struct llentry *lle, long *pdelay, int *do_switch)
|
|
|
|
{
|
2021-08-02 22:39:00 +00:00
|
|
|
int nd_delay, nd_gctimer;
|
2015-12-13 07:39:49 +00:00
|
|
|
time_t lle_hittime;
|
|
|
|
long delay;
|
|
|
|
|
|
|
|
*do_switch = 0;
|
|
|
|
nd_gctimer = V_nd6_gctimer;
|
|
|
|
nd_delay = V_nd6_delay;
|
|
|
|
|
2021-08-02 22:39:00 +00:00
|
|
|
lle_hittime = llentry_get_hittime(lle);
|
2015-12-13 07:39:49 +00:00
|
|
|
|
2021-08-02 22:39:00 +00:00
|
|
|
if (lle_hittime == 0) {
|
2015-12-13 07:39:49 +00:00
|
|
|
/*
|
2021-08-02 22:39:00 +00:00
|
|
|
* Datapath feedback has been requested upon entering
|
|
|
|
* STALE state. No packets has been passed using this lle.
|
|
|
|
* Ask for the timer reschedule and keep STALE state.
|
2015-12-13 07:39:49 +00:00
|
|
|
*/
|
|
|
|
delay = (long)(MIN(nd_gctimer, nd_delay));
|
|
|
|
delay *= hz;
|
|
|
|
if (lle->lle_remtime > delay)
|
|
|
|
lle->lle_remtime -= delay;
|
|
|
|
else {
|
|
|
|
delay = lle->lle_remtime;
|
|
|
|
lle->lle_remtime = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (delay == 0) {
|
|
|
|
/*
|
|
|
|
* The original ng6_gctime timeout ended,
|
|
|
|
* no more rescheduling.
|
|
|
|
*/
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
*pdelay = delay;
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Packet received. Verify timestamp
|
|
|
|
*/
|
|
|
|
delay = (long)(time_uptime - lle_hittime);
|
|
|
|
if (delay < nd_delay) {
|
|
|
|
/*
|
|
|
|
* V_nd6_delay still not passed since the first
|
|
|
|
* hit in STALE state.
|
2021-08-28 16:53:59 +00:00
|
|
|
* Reschedule timer and return.
|
2015-12-13 07:39:49 +00:00
|
|
|
*/
|
|
|
|
*pdelay = (long)(nd_delay - delay) * hz;
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Request switching to probe */
|
|
|
|
*do_switch = 1;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2015-09-21 11:19:53 +00:00
|
|
|
/*
|
|
|
|
* Switch @lle state to new state optionally arming timers.
|
2015-10-04 08:21:15 +00:00
|
|
|
*
|
|
|
|
* Set noinline to be dtrace-friendly
|
2015-09-21 11:19:53 +00:00
|
|
|
*/
|
2015-10-04 08:21:15 +00:00
|
|
|
__noinline void
|
2015-09-21 11:19:53 +00:00
|
|
|
nd6_llinfo_setstate(struct llentry *lle, int newstate)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp;
|
2015-12-13 07:39:49 +00:00
|
|
|
int nd_gctimer, nd_delay;
|
|
|
|
long delay, remtime;
|
2015-09-21 11:19:53 +00:00
|
|
|
|
|
|
|
delay = 0;
|
2015-12-13 07:39:49 +00:00
|
|
|
remtime = 0;
|
2015-09-21 11:19:53 +00:00
|
|
|
|
|
|
|
switch (newstate) {
|
|
|
|
case ND6_LLINFO_INCOMPLETE:
|
|
|
|
ifp = lle->lle_tbl->llt_ifp;
|
|
|
|
delay = (long)ND_IFINFO(ifp)->retrans * hz / 1000;
|
|
|
|
break;
|
|
|
|
case ND6_LLINFO_REACHABLE:
|
|
|
|
if (!ND6_LLINFO_PERMANENT(lle)) {
|
|
|
|
ifp = lle->lle_tbl->llt_ifp;
|
|
|
|
delay = (long)ND_IFINFO(ifp)->reachable * hz;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ND6_LLINFO_STALE:
|
2015-12-13 07:39:49 +00:00
|
|
|
|
2021-08-02 22:39:00 +00:00
|
|
|
llentry_request_feedback(lle);
|
2015-12-13 07:39:49 +00:00
|
|
|
nd_delay = V_nd6_delay;
|
|
|
|
nd_gctimer = V_nd6_gctimer;
|
|
|
|
|
|
|
|
delay = (long)(MIN(nd_gctimer, nd_delay)) * hz;
|
|
|
|
remtime = (long)nd_gctimer * hz - delay;
|
2015-09-21 11:19:53 +00:00
|
|
|
break;
|
|
|
|
case ND6_LLINFO_DELAY:
|
|
|
|
lle->la_asked = 0;
|
|
|
|
delay = (long)V_nd6_delay * hz;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (delay > 0)
|
|
|
|
nd6_llinfo_settimer_locked(lle, delay);
|
|
|
|
|
2015-12-13 07:39:49 +00:00
|
|
|
lle->lle_remtime = remtime;
|
2015-09-21 11:19:53 +00:00
|
|
|
lle->ln_state = newstate;
|
|
|
|
}
|
|
|
|
|
2015-10-04 08:21:15 +00:00
|
|
|
/*
|
|
|
|
* Timer-dependent part of nd state machine.
|
|
|
|
*
|
|
|
|
* Set noinline to be dtrace-friendly
|
|
|
|
*/
|
|
|
|
static __noinline void
|
2007-07-05 16:23:49 +00:00
|
|
|
nd6_llinfo_timer(void *arg)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
Widen NET_EPOCH coverage.
When epoch(9) was introduced to network stack, it was basically
dropped in place of existing locking, which was mutexes and
rwlocks. For the sake of performance mutex covered areas were
as small as possible, so became epoch covered areas.
However, epoch doesn't introduce any contention, it just delays
memory reclaim. So, there is no point to minimise epoch covered
areas in sense of performance. Meanwhile entering/exiting epoch
also has non-zero CPU usage, so doing this less often is a win.
Not the least is also code maintainability. In the new paradigm
we can assume that at any stage of processing a packet, we are
inside network epoch. This makes coding both input and output
path way easier.
On output path we already enter epoch quite early - in the
ip_output(), in the ip6_output().
This patch does the same for the input path. All ISR processing,
network related callouts, other ways of packet injection to the
network stack shall be performed in net_epoch. Any leaf function
that walks network configuration now asserts epoch.
Tricky part is configuration code paths - ioctls, sysctls. They
also call into leaf functions, so some need to be changed.
This patch would introduce more epoch recursions (see EPOCH_TRACE)
than we had before. They will be cleaned up separately, as several
of them aren't trivial. Note, that unlike a lock recursion the
epoch recursion is safe and just wastes a bit of resources.
Reviewed by: gallatin, hselasky, cy, adrian, kristof
Differential Revision: https://reviews.freebsd.org/D19111
2019-10-07 22:40:05 +00:00
|
|
|
struct epoch_tracker et;
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
struct llentry *ln;
|
2015-09-05 14:14:03 +00:00
|
|
|
struct in6_addr *dst, *pdst, *psrc, src;
|
2001-06-11 12:39:29 +00:00
|
|
|
struct ifnet *ifp;
|
2016-03-29 19:23:00 +00:00
|
|
|
struct nd_ifinfo *ndi;
|
2015-12-13 07:39:49 +00:00
|
|
|
int do_switch, send_ns;
|
|
|
|
long delay;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2010-07-31 21:33:18 +00:00
|
|
|
KASSERT(arg != NULL, ("%s: arg NULL", __func__));
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
ln = (struct llentry *)arg;
|
2016-03-29 19:23:00 +00:00
|
|
|
ifp = lltable_get_ifp(ln->lle_tbl);
|
|
|
|
CURVNET_SET(ifp->if_vnet);
|
|
|
|
|
|
|
|
ND6_RLOCK();
|
2015-02-09 19:28:11 +00:00
|
|
|
LLE_WLOCK(ln);
|
2015-08-11 12:38:54 +00:00
|
|
|
if (callout_pending(&ln->lle_timer)) {
|
2015-02-09 19:28:11 +00:00
|
|
|
/*
|
|
|
|
* Here we are a bit odd here in the treatment of
|
|
|
|
* active/pending. If the pending bit is set, it got
|
|
|
|
* rescheduled before I ran. The active
|
|
|
|
* bit we ignore, since if it was stopped
|
|
|
|
* in ll_tablefree() and was currently running
|
|
|
|
* it would have return 0 so the code would
|
|
|
|
* not have deleted it since the callout could
|
|
|
|
* not be stopped so we want to go through
|
|
|
|
* with the delete here now. If the callout
|
|
|
|
* was restarted, the pending bit will be back on and
|
|
|
|
* we just want to bail since the callout_reset would
|
|
|
|
* return 1 and our reference would have been removed
|
|
|
|
* by nd6_llinfo_settimer_locked above since canceled
|
|
|
|
* would have been 1.
|
|
|
|
*/
|
|
|
|
LLE_WUNLOCK(ln);
|
2016-03-29 19:23:00 +00:00
|
|
|
ND6_RUNLOCK();
|
|
|
|
CURVNET_RESTORE();
|
2015-02-09 19:28:11 +00:00
|
|
|
return;
|
|
|
|
}
|
Widen NET_EPOCH coverage.
When epoch(9) was introduced to network stack, it was basically
dropped in place of existing locking, which was mutexes and
rwlocks. For the sake of performance mutex covered areas were
as small as possible, so became epoch covered areas.
However, epoch doesn't introduce any contention, it just delays
memory reclaim. So, there is no point to minimise epoch covered
areas in sense of performance. Meanwhile entering/exiting epoch
also has non-zero CPU usage, so doing this less often is a win.
Not the least is also code maintainability. In the new paradigm
we can assume that at any stage of processing a packet, we are
inside network epoch. This makes coding both input and output
path way easier.
On output path we already enter epoch quite early - in the
ip_output(), in the ip6_output().
This patch does the same for the input path. All ISR processing,
network related callouts, other ways of packet injection to the
network stack shall be performed in net_epoch. Any leaf function
that walks network configuration now asserts epoch.
Tricky part is configuration code paths - ioctls, sysctls. They
also call into leaf functions, so some need to be changed.
This patch would introduce more epoch recursions (see EPOCH_TRACE)
than we had before. They will be cleaned up separately, as several
of them aren't trivial. Note, that unlike a lock recursion the
epoch recursion is safe and just wastes a bit of resources.
Reviewed by: gallatin, hselasky, cy, adrian, kristof
Differential Revision: https://reviews.freebsd.org/D19111
2019-10-07 22:40:05 +00:00
|
|
|
NET_EPOCH_ENTER(et);
|
2015-09-05 14:14:03 +00:00
|
|
|
ndi = ND_IFINFO(ifp);
|
|
|
|
send_ns = 0;
|
|
|
|
dst = &ln->r_l3addr.addr6;
|
|
|
|
pdst = dst;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2005-10-21 16:23:01 +00:00
|
|
|
if (ln->ln_ntick > 0) {
|
|
|
|
if (ln->ln_ntick > INT_MAX) {
|
|
|
|
ln->ln_ntick -= INT_MAX;
|
2010-11-29 00:04:08 +00:00
|
|
|
nd6_llinfo_settimer_locked(ln, INT_MAX);
|
2005-10-21 16:23:01 +00:00
|
|
|
} else {
|
|
|
|
ln->ln_ntick = 0;
|
2010-11-29 00:04:08 +00:00
|
|
|
nd6_llinfo_settimer_locked(ln, ln->ln_ntick);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
goto done;
|
2005-10-21 16:23:01 +00:00
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2009-11-06 17:34:26 +00:00
|
|
|
if (ln->la_flags & LLE_STATIC) {
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2002-04-19 04:46:24 +00:00
|
|
|
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
if (ln->la_flags & LLE_DELETED) {
|
2016-03-29 19:23:00 +00:00
|
|
|
nd6_free(&ln, 0);
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2001-06-11 12:39:29 +00:00
|
|
|
|
2005-10-21 16:23:01 +00:00
|
|
|
switch (ln->ln_state) {
|
|
|
|
case ND6_LLINFO_INCOMPLETE:
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
if (ln->la_asked < V_nd6_mmaxtries) {
|
|
|
|
ln->la_asked++;
|
2015-09-05 14:14:03 +00:00
|
|
|
send_ns = 1;
|
|
|
|
/* Send NS to multicast address */
|
|
|
|
pdst = NULL;
|
2005-10-21 16:23:01 +00:00
|
|
|
} else {
|
2022-05-31 20:04:51 +00:00
|
|
|
struct mbuf *m;
|
2006-03-24 16:20:12 +00:00
|
|
|
|
2022-05-31 20:04:51 +00:00
|
|
|
ICMP6STAT_ADD(icp6s_dropped, ln->la_numheld);
|
|
|
|
|
|
|
|
m = ln->la_hold;
|
|
|
|
if (m != NULL) {
|
2005-10-21 16:23:01 +00:00
|
|
|
/*
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
* assuming every packet in la_hold has the
|
2010-11-29 00:04:08 +00:00
|
|
|
* same IP header. Send error after unlock.
|
2005-10-21 16:23:01 +00:00
|
|
|
*/
|
2022-05-31 20:04:51 +00:00
|
|
|
ln->la_hold = m->m_nextpkt;
|
2006-03-24 16:20:12 +00:00
|
|
|
m->m_nextpkt = NULL;
|
2022-05-31 20:04:51 +00:00
|
|
|
ln->la_numheld--;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2016-03-29 19:23:00 +00:00
|
|
|
nd6_free(&ln, 0);
|
2020-05-12 17:18:44 +00:00
|
|
|
if (m != NULL) {
|
|
|
|
struct mbuf *n = m;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if there are any ummapped mbufs, we
|
|
|
|
* must free them, rather than using
|
|
|
|
* them for an ICMP, as they cannot be
|
|
|
|
* checksummed.
|
|
|
|
*/
|
|
|
|
while ((n = n->m_next) != NULL) {
|
|
|
|
if (n->m_flags & M_EXTPG)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (n != NULL) {
|
|
|
|
m_freem(m);
|
|
|
|
m = NULL;
|
|
|
|
} else {
|
|
|
|
icmp6_error2(m, ICMP6_DST_UNREACH,
|
|
|
|
ICMP6_DST_UNREACH_ADDR, 0, ifp);
|
|
|
|
}
|
|
|
|
}
|
2005-10-21 16:23:01 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ND6_LLINFO_REACHABLE:
|
2015-09-21 11:19:53 +00:00
|
|
|
if (!ND6_LLINFO_PERMANENT(ln))
|
|
|
|
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
|
2005-10-21 16:23:01 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ND6_LLINFO_STALE:
|
2015-12-13 07:39:49 +00:00
|
|
|
if (nd6_is_stale(ln, &delay, &do_switch) != 0) {
|
|
|
|
/*
|
|
|
|
* No packet has used this entry and GC timeout
|
2021-08-28 16:53:59 +00:00
|
|
|
* has not been passed. Reschedule timer and
|
2015-12-13 07:39:49 +00:00
|
|
|
* return.
|
|
|
|
*/
|
|
|
|
nd6_llinfo_settimer_locked(ln, delay);
|
|
|
|
break;
|
2005-10-21 16:23:01 +00:00
|
|
|
}
|
2015-12-13 07:39:49 +00:00
|
|
|
|
|
|
|
if (do_switch == 0) {
|
|
|
|
/*
|
|
|
|
* GC timer has ended and entry hasn't been used.
|
|
|
|
* Run Garbage collector (RFC 4861, 5.3)
|
|
|
|
*/
|
2016-03-29 19:23:00 +00:00
|
|
|
if (!ND6_LLINFO_PERMANENT(ln))
|
|
|
|
nd6_free(&ln, 1);
|
2015-12-13 07:39:49 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Entry has been used AND delay timer has ended. */
|
|
|
|
|
|
|
|
/* FALLTHROUGH */
|
2005-10-21 16:23:01 +00:00
|
|
|
|
|
|
|
case ND6_LLINFO_DELAY:
|
|
|
|
if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) {
|
|
|
|
/* We need NUD */
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
ln->la_asked = 1;
|
2015-09-21 11:19:53 +00:00
|
|
|
nd6_llinfo_setstate(ln, ND6_LLINFO_PROBE);
|
2015-09-05 14:14:03 +00:00
|
|
|
send_ns = 1;
|
2015-09-21 11:19:53 +00:00
|
|
|
} else
|
|
|
|
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); /* XXX */
|
2005-10-21 16:23:01 +00:00
|
|
|
break;
|
|
|
|
case ND6_LLINFO_PROBE:
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
if (ln->la_asked < V_nd6_umaxtries) {
|
|
|
|
ln->la_asked++;
|
2015-09-05 14:14:03 +00:00
|
|
|
send_ns = 1;
|
2005-10-21 16:23:01 +00:00
|
|
|
} else {
|
2016-03-29 19:23:00 +00:00
|
|
|
nd6_free(&ln, 0);
|
2005-10-21 16:23:01 +00:00
|
|
|
}
|
|
|
|
break;
|
2010-11-29 00:04:08 +00:00
|
|
|
default:
|
|
|
|
panic("%s: paths in a dark night can be confusing: %d",
|
|
|
|
__func__, ln->ln_state);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
done:
|
2016-03-29 19:23:00 +00:00
|
|
|
if (ln != NULL)
|
|
|
|
ND6_RUNLOCK();
|
2015-09-05 14:14:03 +00:00
|
|
|
if (send_ns != 0) {
|
|
|
|
nd6_llinfo_settimer_locked(ln, (long)ndi->retrans * hz / 1000);
|
|
|
|
psrc = nd6_llinfo_get_holdsrc(ln, &src);
|
|
|
|
LLE_FREE_LOCKED(ln);
|
|
|
|
ln = NULL;
|
|
|
|
nd6_ns_output(ifp, psrc, pdst, dst, NULL);
|
|
|
|
}
|
|
|
|
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
if (ln != NULL)
|
2010-11-29 00:04:08 +00:00
|
|
|
LLE_FREE_LOCKED(ln);
|
Widen NET_EPOCH coverage.
When epoch(9) was introduced to network stack, it was basically
dropped in place of existing locking, which was mutexes and
rwlocks. For the sake of performance mutex covered areas were
as small as possible, so became epoch covered areas.
However, epoch doesn't introduce any contention, it just delays
memory reclaim. So, there is no point to minimise epoch covered
areas in sense of performance. Meanwhile entering/exiting epoch
also has non-zero CPU usage, so doing this less often is a win.
Not the least is also code maintainability. In the new paradigm
we can assume that at any stage of processing a packet, we are
inside network epoch. This makes coding both input and output
path way easier.
On output path we already enter epoch quite early - in the
ip_output(), in the ip6_output().
This patch does the same for the input path. All ISR processing,
network related callouts, other ways of packet injection to the
network stack shall be performed in net_epoch. Any leaf function
that walks network configuration now asserts epoch.
Tricky part is configuration code paths - ioctls, sysctls. They
also call into leaf functions, so some need to be changed.
This patch would introduce more epoch recursions (see EPOCH_TRACE)
than we had before. They will be cleaned up separately, as several
of them aren't trivial. Note, that unlike a lock recursion the
epoch recursion is safe and just wastes a bit of resources.
Reviewed by: gallatin, hselasky, cy, adrian, kristof
Differential Revision: https://reviews.freebsd.org/D19111
2019-10-07 22:40:05 +00:00
|
|
|
NET_EPOCH_EXIT(et);
|
2009-11-11 08:28:18 +00:00
|
|
|
CURVNET_RESTORE();
|
2005-10-21 16:23:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ND6 timer routine to expire default route list and prefix list
|
|
|
|
*/
|
|
|
|
void
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
nd6_timer(void *arg)
|
2005-10-21 16:23:01 +00:00
|
|
|
{
|
Change the curvnet variable from a global const struct vnet *,
previously always pointing to the default vnet context, to a
dynamically changing thread-local one. The currvnet context
should be set on entry to networking code via CURVNET_SET() macros,
and reverted to previous state via CURVNET_RESTORE(). Recursions
on curvnet are permitted, though strongly discuouraged.
This change should have no functional impact on nooptions VIMAGE
kernel builds, where CURVNET_* macros expand to whitespace.
The curthread->td_vnet (aka curvnet) variable's purpose is to be an
indicator of the vnet context in which the current network-related
operation takes place, in case we cannot deduce the current vnet
context from any other source, such as by looking at mbuf's
m->m_pkthdr.rcvif->if_vnet, sockets's so->so_vnet etc. Moreover, so
far curvnet has turned out to be an invaluable consistency checking
aid: it helps to catch cases when sockets, ifnets or any other
vnet-aware structures may have leaked from one vnet to another.
The exact placement of the CURVNET_SET() / CURVNET_RESTORE() macros
was a result of an empirical iterative process, whith an aim to
reduce recursions on CURVNET_SET() to a minimum, while still reducing
the scope of CURVNET_SET() to networking only operations - the
alternative would be calling CURVNET_SET() on each system call entry.
In general, curvnet has to be set in three typicall cases: when
processing socket-related requests from userspace or from within the
kernel; when processing inbound traffic flowing from device drivers
to upper layers of the networking stack, and when executing
timer-driven networking functions.
This change also introduces a DDB subcommand to show the list of all
vnet instances.
Approved by: julian (mentor)
2009-05-05 10:56:12 +00:00
|
|
|
CURVNET_SET((struct vnet *) arg);
|
Widen NET_EPOCH coverage.
When epoch(9) was introduced to network stack, it was basically
dropped in place of existing locking, which was mutexes and
rwlocks. For the sake of performance mutex covered areas were
as small as possible, so became epoch covered areas.
However, epoch doesn't introduce any contention, it just delays
memory reclaim. So, there is no point to minimise epoch covered
areas in sense of performance. Meanwhile entering/exiting epoch
also has non-zero CPU usage, so doing this less often is a win.
Not the least is also code maintainability. In the new paradigm
we can assume that at any stage of processing a packet, we are
inside network epoch. This makes coding both input and output
path way easier.
On output path we already enter epoch quite early - in the
ip_output(), in the ip6_output().
This patch does the same for the input path. All ISR processing,
network related callouts, other ways of packet injection to the
network stack shall be performed in net_epoch. Any leaf function
that walks network configuration now asserts epoch.
Tricky part is configuration code paths - ioctls, sysctls. They
also call into leaf functions, so some need to be changed.
This patch would introduce more epoch recursions (see EPOCH_TRACE)
than we had before. They will be cleaned up separately, as several
of them aren't trivial. Note, that unlike a lock recursion the
epoch recursion is safe and just wastes a bit of resources.
Reviewed by: gallatin, hselasky, cy, adrian, kristof
Differential Revision: https://reviews.freebsd.org/D19111
2019-10-07 22:40:05 +00:00
|
|
|
struct epoch_tracker et;
|
2016-10-07 21:10:53 +00:00
|
|
|
struct nd_prhead prl;
|
2011-12-29 18:25:18 +00:00
|
|
|
struct nd_prefix *pr, *npr;
|
2019-03-30 18:00:44 +00:00
|
|
|
struct ifnet *ifp;
|
2005-10-21 16:23:01 +00:00
|
|
|
struct in6_ifaddr *ia6, *nia6;
|
2017-01-08 18:46:00 +00:00
|
|
|
uint64_t genid;
|
2005-10-21 16:23:01 +00:00
|
|
|
|
2016-10-07 21:10:53 +00:00
|
|
|
LIST_INIT(&prl);
|
2016-02-25 20:12:05 +00:00
|
|
|
|
2019-11-04 17:35:37 +00:00
|
|
|
NET_EPOCH_ENTER(et);
|
2019-11-13 12:05:48 +00:00
|
|
|
nd6_defrouter_timer();
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
/*
|
|
|
|
* expire interface addresses.
|
|
|
|
* in the past the loop was inside prefix expiry processing.
|
|
|
|
* However, from a stricter speci-confrmance standpoint, we should
|
|
|
|
* rather separate address lifetimes and prefix lifetimes.
|
2009-06-25 16:35:28 +00:00
|
|
|
*
|
|
|
|
* XXXRW: in6_ifaddrhead locking.
|
2001-06-11 12:39:29 +00:00
|
|
|
*/
|
|
|
|
addrloop:
|
2018-05-18 20:13:34 +00:00
|
|
|
CK_STAILQ_FOREACH_SAFE(ia6, &V_in6_ifaddrhead, ia_link, nia6) {
|
2001-06-11 12:39:29 +00:00
|
|
|
/* check address lifetime */
|
|
|
|
if (IFA6_IS_INVALID(ia6)) {
|
|
|
|
int regen = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the expiring address is temporary, try
|
|
|
|
* regenerating a new one. This would be useful when
|
2002-04-19 04:46:24 +00:00
|
|
|
* we suspended a laptop PC, then turned it on after a
|
2001-06-11 12:39:29 +00:00
|
|
|
* period that could invalidate all temporary
|
|
|
|
* addresses. Although we may have to restart the
|
|
|
|
* loop (see below), it must be after purging the
|
|
|
|
* address. Otherwise, we'd see an infinite loop of
|
2003-10-09 16:13:47 +00:00
|
|
|
* regeneration.
|
2001-06-11 12:39:29 +00:00
|
|
|
*/
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (V_ip6_use_tempaddr &&
|
2001-06-11 12:39:29 +00:00
|
|
|
(ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
|
|
|
|
if (regen_tmpaddr(ia6) == 0)
|
|
|
|
regen = 1;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2001-06-11 12:39:29 +00:00
|
|
|
|
|
|
|
in6_purgeaddr(&ia6->ia_ifa);
|
|
|
|
|
|
|
|
if (regen)
|
|
|
|
goto addrloop; /* XXX: see below */
|
2006-02-12 15:37:08 +00:00
|
|
|
} else if (IFA6_IS_DEPRECATED(ia6)) {
|
2001-06-11 12:39:29 +00:00
|
|
|
int oldflags = ia6->ia6_flags;
|
|
|
|
|
|
|
|
ia6->ia6_flags |= IN6_IFF_DEPRECATED;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If a temporary address has just become deprecated,
|
|
|
|
* regenerate a new one if possible.
|
|
|
|
*/
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (V_ip6_use_tempaddr &&
|
2001-06-11 12:39:29 +00:00
|
|
|
(ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
|
|
|
|
(oldflags & IN6_IFF_DEPRECATED) == 0) {
|
|
|
|
if (regen_tmpaddr(ia6) == 0) {
|
|
|
|
/*
|
|
|
|
* A new temporary address is
|
|
|
|
* generated.
|
|
|
|
* XXX: this means the address chain
|
|
|
|
* has changed while we are still in
|
|
|
|
* the loop. Although the change
|
|
|
|
* would not cause disaster (because
|
2002-04-19 04:46:24 +00:00
|
|
|
* it's not a deletion, but an
|
|
|
|
* addition,) we'd rather restart the
|
2003-10-09 16:13:47 +00:00
|
|
|
* loop just for safety. Or does this
|
2001-06-11 12:39:29 +00:00
|
|
|
* significantly reduce performance??
|
|
|
|
*/
|
|
|
|
goto addrloop;
|
|
|
|
}
|
|
|
|
}
|
2015-10-03 12:09:12 +00:00
|
|
|
} else if ((ia6->ia6_flags & IN6_IFF_TENTATIVE) != 0) {
|
|
|
|
/*
|
|
|
|
* Schedule DAD for a tentative address. This happens
|
|
|
|
* if the interface was down or not running
|
|
|
|
* when the address was configured.
|
|
|
|
*/
|
|
|
|
int delay;
|
|
|
|
|
|
|
|
delay = arc4random() %
|
|
|
|
(MAX_RTR_SOLICITATION_DELAY * hz);
|
|
|
|
nd6_dad_start((struct ifaddr *)ia6, delay);
|
2002-04-24 19:09:48 +00:00
|
|
|
} else {
|
2015-10-03 12:09:12 +00:00
|
|
|
/*
|
|
|
|
* Check status of the interface. If it is down,
|
|
|
|
* mark the address as tentative for future DAD.
|
|
|
|
*/
|
2019-03-30 18:00:44 +00:00
|
|
|
ifp = ia6->ia_ifp;
|
|
|
|
if ((ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD) == 0 &&
|
|
|
|
((ifp->if_flags & IFF_UP) == 0 ||
|
|
|
|
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
|
|
|
|
(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) != 0)){
|
2015-10-03 12:09:12 +00:00
|
|
|
ia6->ia6_flags &= ~IN6_IFF_DUPLICATED;
|
|
|
|
ia6->ia6_flags |= IN6_IFF_TENTATIVE;
|
|
|
|
}
|
2019-03-30 18:00:44 +00:00
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
/*
|
|
|
|
* A new RA might have made a deprecated address
|
|
|
|
* preferred.
|
|
|
|
*/
|
|
|
|
ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
Widen NET_EPOCH coverage.
When epoch(9) was introduced to network stack, it was basically
dropped in place of existing locking, which was mutexes and
rwlocks. For the sake of performance mutex covered areas were
as small as possible, so became epoch covered areas.
However, epoch doesn't introduce any contention, it just delays
memory reclaim. So, there is no point to minimise epoch covered
areas in sense of performance. Meanwhile entering/exiting epoch
also has non-zero CPU usage, so doing this less often is a win.
Not the least is also code maintainability. In the new paradigm
we can assume that at any stage of processing a packet, we are
inside network epoch. This makes coding both input and output
path way easier.
On output path we already enter epoch quite early - in the
ip_output(), in the ip6_output().
This patch does the same for the input path. All ISR processing,
network related callouts, other ways of packet injection to the
network stack shall be performed in net_epoch. Any leaf function
that walks network configuration now asserts epoch.
Tricky part is configuration code paths - ioctls, sysctls. They
also call into leaf functions, so some need to be changed.
This patch would introduce more epoch recursions (see EPOCH_TRACE)
than we had before. They will be cleaned up separately, as several
of them aren't trivial. Note, that unlike a lock recursion the
epoch recursion is safe and just wastes a bit of resources.
Reviewed by: gallatin, hselasky, cy, adrian, kristof
Differential Revision: https://reviews.freebsd.org/D19111
2019-10-07 22:40:05 +00:00
|
|
|
NET_EPOCH_EXIT(et);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2016-10-07 21:10:53 +00:00
|
|
|
ND6_WLOCK();
|
|
|
|
restart:
|
2011-12-29 18:25:18 +00:00
|
|
|
LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, npr) {
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
2016-10-07 21:10:53 +00:00
|
|
|
* Expire prefixes. Since the pltime is only used for
|
|
|
|
* autoconfigured addresses, pltime processing for prefixes is
|
|
|
|
* not necessary.
|
|
|
|
*
|
|
|
|
* Only unlink after all derived addresses have expired. This
|
|
|
|
* may not occur until two hours after the prefix has expired
|
|
|
|
* per RFC 4862. If the prefix expires before its derived
|
|
|
|
* addresses, mark it off-link. This will be done automatically
|
|
|
|
* after unlinking if no address references remain.
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2016-10-07 21:10:53 +00:00
|
|
|
if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME ||
|
|
|
|
time_uptime - pr->ndpr_lastupdate <= pr->ndpr_vltime)
|
|
|
|
continue;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2016-10-07 21:10:53 +00:00
|
|
|
if (pr->ndpr_addrcnt == 0) {
|
|
|
|
nd6_prefix_unlink(pr, &prl);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
|
2017-01-08 18:46:00 +00:00
|
|
|
genid = V_nd6_list_genid;
|
|
|
|
nd6_prefix_ref(pr);
|
|
|
|
ND6_WUNLOCK();
|
|
|
|
ND6_ONLINK_LOCK();
|
2016-10-07 21:10:53 +00:00
|
|
|
(void)nd6_prefix_offlink(pr);
|
2017-01-08 18:46:00 +00:00
|
|
|
ND6_ONLINK_UNLOCK();
|
|
|
|
ND6_WLOCK();
|
|
|
|
nd6_prefix_rele(pr);
|
|
|
|
if (genid != V_nd6_list_genid)
|
|
|
|
goto restart;
|
2011-12-29 18:25:18 +00:00
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2016-10-07 21:10:53 +00:00
|
|
|
ND6_WUNLOCK();
|
|
|
|
|
|
|
|
while ((pr = LIST_FIRST(&prl)) != NULL) {
|
|
|
|
LIST_REMOVE(pr, ndpr_entry);
|
|
|
|
nd6_prefix_del(pr);
|
|
|
|
}
|
2016-06-06 14:01:09 +00:00
|
|
|
|
|
|
|
callout_reset(&V_nd6_timer_ch, V_nd6_prune * hz,
|
|
|
|
nd6_timer, curvnet);
|
|
|
|
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
CURVNET_RESTORE();
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2007-07-05 16:23:49 +00:00
|
|
|
/*
|
|
|
|
* ia6 - deprecated/invalidated temporary address
|
|
|
|
*/
|
2001-06-11 12:39:29 +00:00
|
|
|
static int
|
2007-07-05 16:23:49 +00:00
|
|
|
regen_tmpaddr(struct in6_ifaddr *ia6)
|
2001-06-11 12:39:29 +00:00
|
|
|
{
|
|
|
|
struct ifaddr *ifa;
|
|
|
|
struct ifnet *ifp;
|
|
|
|
struct in6_ifaddr *public_ifa6 = NULL;
|
|
|
|
|
Widen NET_EPOCH coverage.
When epoch(9) was introduced to network stack, it was basically
dropped in place of existing locking, which was mutexes and
rwlocks. For the sake of performance mutex covered areas were
as small as possible, so became epoch covered areas.
However, epoch doesn't introduce any contention, it just delays
memory reclaim. So, there is no point to minimise epoch covered
areas in sense of performance. Meanwhile entering/exiting epoch
also has non-zero CPU usage, so doing this less often is a win.
Not the least is also code maintainability. In the new paradigm
we can assume that at any stage of processing a packet, we are
inside network epoch. This makes coding both input and output
path way easier.
On output path we already enter epoch quite early - in the
ip_output(), in the ip6_output().
This patch does the same for the input path. All ISR processing,
network related callouts, other ways of packet injection to the
network stack shall be performed in net_epoch. Any leaf function
that walks network configuration now asserts epoch.
Tricky part is configuration code paths - ioctls, sysctls. They
also call into leaf functions, so some need to be changed.
This patch would introduce more epoch recursions (see EPOCH_TRACE)
than we had before. They will be cleaned up separately, as several
of them aren't trivial. Note, that unlike a lock recursion the
epoch recursion is safe and just wastes a bit of resources.
Reviewed by: gallatin, hselasky, cy, adrian, kristof
Differential Revision: https://reviews.freebsd.org/D19111
2019-10-07 22:40:05 +00:00
|
|
|
NET_EPOCH_ASSERT();
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
ifp = ia6->ia_ifa.ifa_ifp;
|
2018-05-18 20:13:34 +00:00
|
|
|
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
|
2001-06-11 12:39:29 +00:00
|
|
|
struct in6_ifaddr *it6;
|
|
|
|
|
|
|
|
if (ifa->ifa_addr->sa_family != AF_INET6)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
it6 = (struct in6_ifaddr *)ifa;
|
|
|
|
|
|
|
|
/* ignore no autoconf addresses. */
|
|
|
|
if ((it6->ia6_flags & IN6_IFF_AUTOCONF) == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* ignore autoconf addresses with different prefixes. */
|
|
|
|
if (it6->ia6_ndpr == NULL || it6->ia6_ndpr != ia6->ia6_ndpr)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now we are looking at an autoconf address with the same
|
|
|
|
* prefix as ours. If the address is temporary and is still
|
|
|
|
* preferred, do not create another one. It would be rare, but
|
|
|
|
* could happen, for example, when we resume a laptop PC after
|
|
|
|
* a long period.
|
|
|
|
*/
|
|
|
|
if ((it6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
|
|
|
|
!IFA6_IS_DEPRECATED(it6)) {
|
|
|
|
public_ifa6 = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is a public autoconf address that has the same prefix
|
|
|
|
* as ours. If it is preferred, keep it. We can't break the
|
|
|
|
* loop here, because there may be a still-preferred temporary
|
|
|
|
* address with the prefix.
|
|
|
|
*/
|
|
|
|
if (!IFA6_IS_DEPRECATED(it6))
|
2015-04-13 01:55:42 +00:00
|
|
|
public_ifa6 = it6;
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
2015-04-13 01:55:42 +00:00
|
|
|
if (public_ifa6 != NULL)
|
|
|
|
ifa_ref(&public_ifa6->ia_ifa);
|
2001-06-11 12:39:29 +00:00
|
|
|
|
|
|
|
if (public_ifa6 != NULL) {
|
|
|
|
int e;
|
|
|
|
|
2005-10-21 16:23:01 +00:00
|
|
|
if ((e = in6_tmpifadd(public_ifa6, 0, 0)) != 0) {
|
2010-02-27 07:12:25 +00:00
|
|
|
ifa_free(&public_ifa6->ia_ifa);
|
2001-06-11 12:39:29 +00:00
|
|
|
log(LOG_NOTICE, "regen_tmpaddr: failed to create a new"
|
|
|
|
" tmp addr,errno=%d\n", e);
|
2003-10-06 14:02:09 +00:00
|
|
|
return (-1);
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
2010-02-27 07:12:25 +00:00
|
|
|
ifa_free(&public_ifa6->ia_ifa);
|
2003-10-06 14:02:09 +00:00
|
|
|
return (0);
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
|
|
|
|
2003-10-06 14:02:09 +00:00
|
|
|
return (-1);
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
/*
|
2016-05-09 23:43:12 +00:00
|
|
|
* Remove prefix and default router list entries corresponding to ifp. Neighbor
|
|
|
|
* cache entries are freed in in6_domifdetach().
|
2000-07-04 16:35:15 +00:00
|
|
|
*/
|
|
|
|
void
|
2007-07-05 16:23:49 +00:00
|
|
|
nd6_purge(struct ifnet *ifp)
|
2000-07-04 16:35:15 +00:00
|
|
|
{
|
2016-10-07 21:10:53 +00:00
|
|
|
struct nd_prhead prl;
|
2000-07-04 16:35:15 +00:00
|
|
|
struct nd_prefix *pr, *npr;
|
|
|
|
|
2016-10-07 21:10:53 +00:00
|
|
|
LIST_INIT(&prl);
|
2016-02-25 20:12:05 +00:00
|
|
|
|
2019-11-13 12:05:48 +00:00
|
|
|
/* Purge default router list entries toward ifp. */
|
|
|
|
nd6_defrouter_purge(ifp);
|
2016-10-07 21:10:53 +00:00
|
|
|
|
2019-11-13 12:05:48 +00:00
|
|
|
ND6_WLOCK();
|
2016-10-07 21:10:53 +00:00
|
|
|
/*
|
|
|
|
* Remove prefixes on ifp. We should have already removed addresses on
|
|
|
|
* this interface, so no addresses should be referencing these prefixes.
|
|
|
|
*/
|
|
|
|
LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, npr) {
|
|
|
|
if (pr->ndpr_ifp == ifp)
|
|
|
|
nd6_prefix_unlink(pr, &prl);
|
|
|
|
}
|
2016-02-25 20:12:05 +00:00
|
|
|
ND6_WUNLOCK();
|
|
|
|
|
2019-11-13 12:05:48 +00:00
|
|
|
/* Delete the unlinked prefix objects. */
|
2016-10-07 21:10:53 +00:00
|
|
|
while ((pr = LIST_FIRST(&prl)) != NULL) {
|
|
|
|
LIST_REMOVE(pr, ndpr_entry);
|
|
|
|
nd6_prefix_del(pr);
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* cancel default outgoing interface setting */
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (V_nd6_defifindex == ifp->if_index)
|
2000-07-04 16:35:15 +00:00
|
|
|
nd6_setdefaultiface(0);
|
|
|
|
|
- Accept Router Advertisement messages even when net.inet6.ip6.forwarding=1.
- A new per-interface knob IFF_ND6_NO_RADR and sysctl IPV6CTL_NO_RADR.
This controls if accepting a route in an RA message as the default route.
The default value for each interface can be set by net.inet6.ip6.no_radr.
The system wide default value is 0.
- A new sysctl: net.inet6.ip6.norbit_raif. This controls if setting R-bit in
NA on RA accepting interfaces. The default is 0 (R-bit is set based on
net.inet6.ip6.forwarding).
Background:
IPv6 host/router model suggests a router sends an RA and a host accepts it for
router discovery. Because of that, KAME implementation does not allow
accepting RAs when net.inet6.ip6.forwarding=1. Accepting RAs on a router can
make the routing table confused since it can change the default router
unintentionally.
However, in practice there are cases where we cannot distinguish a host from
a router clearly. For example, a customer edge router often works as a host
against the ISP, and as a router against the LAN at the same time. Another
example is a complex network configurations like an L2TP tunnel for IPv6
connection to Internet over an Ethernet link with another native IPv6 subnet.
In this case, the physical interface for the native IPv6 subnet works as a
host, and the pseudo-interface for L2TP works as the default IP forwarding
route.
Problem:
Disabling processing RA messages when net.inet6.ip6.forwarding=1 and
accepting them when net.inet6.ip6.forward=0 cause the following practical
issues:
- A router cannot perform SLAAC. It becomes a problem if a box has
multiple interfaces and you want to use SLAAC on some of them, for
example. A customer edge router for IPv6 Internet access service
using an IPv6-over-IPv6 tunnel sometimes needs SLAAC on the
physical interface for administration purpose; updating firmware
and so on (link-local addresses can be used there, but GUAs by
SLAAC are often used for scalability).
- When a host has multiple IPv6 interfaces and it receives multiple RAs on
them, controlling the default route is difficult. Router preferences
defined in RFC 4191 works only when the routers on the links are
under your control.
Details of Implementation Changes:
Router Advertisement messages will be accepted even when
net.inet6.ip6.forwarding=1. More precisely, the conditions are as
follow:
(ACCEPT_RTADV && !NO_RADR && !ip6.forwarding)
=> Normal RA processing on that interface. (as IPv6 host)
(ACCEPT_RTADV && (NO_RADR || ip6.forwarding))
=> Accept RA but add the router to the defroute list with
rtlifetime=0 unconditionally. This effectively prevents
from setting the received router address as the box's
default route.
(!ACCEPT_RTADV)
=> No RA processing on that interface.
ACCEPT_RTADV and NO_RADR are per-interface knob. In short, all interface
are classified as "RA-accepting" or not. An RA-accepting interface always
processes RA messages regardless of ip6.forwarding. The difference caused by
NO_RADR or ip6.forwarding is whether the RA source address is considered as
the default router or not.
R-bit in NA on the RA accepting interfaces is set based on
net.inet6.ip6.forwarding. While RFC 6204 W-1 rule (for CPE case) suggests
a router should disable the R-bit completely even when the box has
net.inet6.ip6.forwarding=1, I believe there is no technical reason with
doing so. This behavior can be set by a new sysctl net.inet6.ip6.norbit_raif
(the default is 0).
Usage:
# ifconfig fxp0 inet6 accept_rtadv
=> accept RA on fxp0
# ifconfig fxp0 inet6 accept_rtadv no_radr
=> accept RA on fxp0 but ignore default route information in it.
# sysctl net.inet6.ip6.norbit_no_radr=1
=> R-bit in NAs on RA accepting interfaces will always be set to 0.
2011-06-06 02:14:23 +00:00
|
|
|
if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
|
2009-09-12 22:08:20 +00:00
|
|
|
/* Refresh default router list. */
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
defrouter_select_fib(ifp->if_fib);
|
2001-06-27 17:56:17 +00:00
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
}
|
|
|
|
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
/*
|
|
|
|
* the caller acquires and releases the lock on the lltbls
|
|
|
|
* Returns the llentry locked
|
|
|
|
*/
|
|
|
|
struct llentry *
|
2015-09-16 11:06:07 +00:00
|
|
|
nd6_lookup(const struct in6_addr *addr6, int flags, struct ifnet *ifp)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
|
|
|
struct sockaddr_in6 sin6;
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
struct llentry *ln;
|
2020-09-01 21:19:14 +00:00
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
bzero(&sin6, sizeof(sin6));
|
|
|
|
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
|
|
|
sin6.sin6_family = AF_INET6;
|
|
|
|
sin6.sin6_addr = *addr6;
|
2000-07-04 16:35:15 +00:00
|
|
|
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
IF_AFDATA_LOCK_ASSERT(ifp);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2015-09-22 20:45:04 +00:00
|
|
|
ln = lla_lookup(LLTABLE6(ifp), flags, (struct sockaddr *)&sin6);
|
2015-08-08 17:48:54 +00:00
|
|
|
|
2014-11-15 18:54:07 +00:00
|
|
|
return (ln);
|
|
|
|
}
|
|
|
|
|
2019-11-13 13:53:17 +00:00
|
|
|
static struct llentry *
|
2015-09-16 11:06:07 +00:00
|
|
|
nd6_alloc(const struct in6_addr *addr6, int flags, struct ifnet *ifp)
|
2014-11-15 18:54:07 +00:00
|
|
|
{
|
|
|
|
struct sockaddr_in6 sin6;
|
|
|
|
struct llentry *ln;
|
2015-08-08 17:48:54 +00:00
|
|
|
|
2014-11-15 18:54:07 +00:00
|
|
|
bzero(&sin6, sizeof(sin6));
|
|
|
|
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
|
|
|
sin6.sin6_family = AF_INET6;
|
|
|
|
sin6.sin6_addr = *addr6;
|
|
|
|
|
2015-08-20 12:05:17 +00:00
|
|
|
ln = lltable_alloc_entry(LLTABLE6(ifp), 0, (struct sockaddr *)&sin6);
|
2014-11-15 18:54:07 +00:00
|
|
|
if (ln != NULL)
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
ln->ln_state = ND6_LLINFO_NOSTATE;
|
2015-08-08 17:48:54 +00:00
|
|
|
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
return (ln);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2022-08-10 11:51:58 +00:00
|
|
|
* Test whether a given IPv6 address can be a neighbor.
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2022-08-10 11:51:58 +00:00
|
|
|
static bool
|
2015-09-16 11:06:07 +00:00
|
|
|
nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
/*
|
|
|
|
* A link-local address is always a neighbor.
|
2003-12-08 11:59:21 +00:00
|
|
|
* XXX: a link does not necessarily specify a single interface.
|
2000-07-04 16:35:15 +00:00
|
|
|
*/
|
2005-07-25 12:31:43 +00:00
|
|
|
if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
|
|
|
|
struct sockaddr_in6 sin6_copy;
|
|
|
|
u_int32_t zone;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We need sin6_copy since sa6_recoverscope() may modify the
|
|
|
|
* content (XXX).
|
|
|
|
*/
|
|
|
|
sin6_copy = *addr;
|
|
|
|
if (sa6_recoverscope(&sin6_copy))
|
|
|
|
return (0); /* XXX: should be impossible */
|
|
|
|
if (in6_setscope(&sin6_copy.sin6_addr, ifp, &zone))
|
|
|
|
return (0);
|
|
|
|
if (sin6_copy.sin6_scope_id == zone)
|
|
|
|
return (1);
|
|
|
|
else
|
|
|
|
return (0);
|
|
|
|
}
|
2022-08-10 11:51:58 +00:00
|
|
|
/* Checking global unicast */
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2022-08-10 11:51:58 +00:00
|
|
|
/* If an address is directly reachable, it is a neigbor */
|
|
|
|
struct nhop_object *nh;
|
|
|
|
nh = fib6_lookup(ifp->if_fib, &addr->sin6_addr, 0, NHR_NONE, 0);
|
|
|
|
if (nh != NULL && nh->nh_aifp == ifp && (nh->nh_flags & NHF_GATEWAY) == 0)
|
|
|
|
return (true);
|
2016-01-04 15:03:20 +00:00
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
2022-08-10 11:51:58 +00:00
|
|
|
* Check prefixes with desired on-link state, as some may be not
|
|
|
|
* installed in the routing table.
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2022-08-10 11:51:58 +00:00
|
|
|
bool matched = false;
|
|
|
|
struct nd_prefix *pr;
|
2016-10-07 21:10:53 +00:00
|
|
|
ND6_RLOCK();
|
2011-12-29 18:25:18 +00:00
|
|
|
LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
|
2003-12-08 11:59:21 +00:00
|
|
|
if (pr->ndpr_ifp != ifp)
|
|
|
|
continue;
|
2022-08-10 11:51:58 +00:00
|
|
|
if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0)
|
|
|
|
continue;
|
2003-12-08 11:59:21 +00:00
|
|
|
if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr,
|
2016-10-07 21:10:53 +00:00
|
|
|
&addr->sin6_addr, &pr->ndpr_mask)) {
|
2022-08-10 11:51:58 +00:00
|
|
|
matched = true;
|
|
|
|
break;
|
2016-10-07 21:10:53 +00:00
|
|
|
}
|
2003-12-08 11:59:21 +00:00
|
|
|
}
|
2016-10-07 21:10:53 +00:00
|
|
|
ND6_RUNLOCK();
|
2022-08-10 11:51:58 +00:00
|
|
|
if (matched)
|
|
|
|
return (true);
|
2003-12-08 11:59:21 +00:00
|
|
|
|
2005-10-21 16:23:01 +00:00
|
|
|
/*
|
|
|
|
* If the address is assigned on the node of the other side of
|
|
|
|
* a p2p interface, the address should be a neighbor.
|
|
|
|
*/
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
if (ifp->if_flags & IFF_POINTOPOINT) {
|
2022-08-10 11:51:58 +00:00
|
|
|
struct ifaddr *ifa;
|
2019-01-09 01:11:19 +00:00
|
|
|
|
2018-05-18 20:13:34 +00:00
|
|
|
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
if (ifa->ifa_addr->sa_family != addr->sin6_family)
|
|
|
|
continue;
|
|
|
|
if (ifa->ifa_dstaddr != NULL &&
|
|
|
|
sa_equal(addr, ifa->ifa_dstaddr)) {
|
2022-08-10 11:51:58 +00:00
|
|
|
return (true);
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
}
|
2009-06-23 20:19:09 +00:00
|
|
|
}
|
|
|
|
}
|
2005-10-21 16:23:01 +00:00
|
|
|
|
2003-12-08 11:59:21 +00:00
|
|
|
/*
|
|
|
|
* If the default router list is empty, all addresses are regarded
|
|
|
|
* as on-link, and thus, as a neighbor.
|
|
|
|
*/
|
- Accept Router Advertisement messages even when net.inet6.ip6.forwarding=1.
- A new per-interface knob IFF_ND6_NO_RADR and sysctl IPV6CTL_NO_RADR.
This controls if accepting a route in an RA message as the default route.
The default value for each interface can be set by net.inet6.ip6.no_radr.
The system wide default value is 0.
- A new sysctl: net.inet6.ip6.norbit_raif. This controls if setting R-bit in
NA on RA accepting interfaces. The default is 0 (R-bit is set based on
net.inet6.ip6.forwarding).
Background:
IPv6 host/router model suggests a router sends an RA and a host accepts it for
router discovery. Because of that, KAME implementation does not allow
accepting RAs when net.inet6.ip6.forwarding=1. Accepting RAs on a router can
make the routing table confused since it can change the default router
unintentionally.
However, in practice there are cases where we cannot distinguish a host from
a router clearly. For example, a customer edge router often works as a host
against the ISP, and as a router against the LAN at the same time. Another
example is a complex network configurations like an L2TP tunnel for IPv6
connection to Internet over an Ethernet link with another native IPv6 subnet.
In this case, the physical interface for the native IPv6 subnet works as a
host, and the pseudo-interface for L2TP works as the default IP forwarding
route.
Problem:
Disabling processing RA messages when net.inet6.ip6.forwarding=1 and
accepting them when net.inet6.ip6.forward=0 cause the following practical
issues:
- A router cannot perform SLAAC. It becomes a problem if a box has
multiple interfaces and you want to use SLAAC on some of them, for
example. A customer edge router for IPv6 Internet access service
using an IPv6-over-IPv6 tunnel sometimes needs SLAAC on the
physical interface for administration purpose; updating firmware
and so on (link-local addresses can be used there, but GUAs by
SLAAC are often used for scalability).
- When a host has multiple IPv6 interfaces and it receives multiple RAs on
them, controlling the default route is difficult. Router preferences
defined in RFC 4191 works only when the routers on the links are
under your control.
Details of Implementation Changes:
Router Advertisement messages will be accepted even when
net.inet6.ip6.forwarding=1. More precisely, the conditions are as
follow:
(ACCEPT_RTADV && !NO_RADR && !ip6.forwarding)
=> Normal RA processing on that interface. (as IPv6 host)
(ACCEPT_RTADV && (NO_RADR || ip6.forwarding))
=> Accept RA but add the router to the defroute list with
rtlifetime=0 unconditionally. This effectively prevents
from setting the received router address as the box's
default route.
(!ACCEPT_RTADV)
=> No RA processing on that interface.
ACCEPT_RTADV and NO_RADR are per-interface knob. In short, all interface
are classified as "RA-accepting" or not. An RA-accepting interface always
processes RA messages regardless of ip6.forwarding. The difference caused by
NO_RADR or ip6.forwarding is whether the RA source address is considered as
the default router or not.
R-bit in NA on the RA accepting interfaces is set based on
net.inet6.ip6.forwarding. While RFC 6204 W-1 rule (for CPE case) suggests
a router should disable the R-bit completely even when the box has
net.inet6.ip6.forwarding=1, I believe there is no technical reason with
doing so. This behavior can be set by a new sysctl net.inet6.ip6.norbit_raif
(the default is 0).
Usage:
# ifconfig fxp0 inet6 accept_rtadv
=> accept RA on fxp0
# ifconfig fxp0 inet6 accept_rtadv no_radr
=> accept RA on fxp0 but ignore default route information in it.
# sysctl net.inet6.ip6.norbit_no_radr=1
=> R-bit in NAs on RA accepting interfaces will always be set to 0.
2011-06-06 02:14:23 +00:00
|
|
|
if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV &&
|
2019-11-13 12:05:48 +00:00
|
|
|
nd6_defrouter_list_empty() &&
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
V_nd6_defifindex == ifp->if_index) {
|
2003-10-06 14:02:09 +00:00
|
|
|
return (1);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2004-10-03 00:49:33 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Detect if a given IPv6 address identifies a neighbor on a given link.
|
|
|
|
* XXX: should take care of the destination of a p2p link?
|
|
|
|
*/
|
|
|
|
int
|
2015-09-16 11:06:07 +00:00
|
|
|
nd6_is_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
|
2004-10-03 00:49:33 +00:00
|
|
|
{
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
struct llentry *lle;
|
|
|
|
int rc = 0;
|
2004-10-03 00:49:33 +00:00
|
|
|
|
Widen NET_EPOCH coverage.
When epoch(9) was introduced to network stack, it was basically
dropped in place of existing locking, which was mutexes and
rwlocks. For the sake of performance mutex covered areas were
as small as possible, so became epoch covered areas.
However, epoch doesn't introduce any contention, it just delays
memory reclaim. So, there is no point to minimise epoch covered
areas in sense of performance. Meanwhile entering/exiting epoch
also has non-zero CPU usage, so doing this less often is a win.
Not the least is also code maintainability. In the new paradigm
we can assume that at any stage of processing a packet, we are
inside network epoch. This makes coding both input and output
path way easier.
On output path we already enter epoch quite early - in the
ip_output(), in the ip6_output().
This patch does the same for the input path. All ISR processing,
network related callouts, other ways of packet injection to the
network stack shall be performed in net_epoch. Any leaf function
that walks network configuration now asserts epoch.
Tricky part is configuration code paths - ioctls, sysctls. They
also call into leaf functions, so some need to be changed.
This patch would introduce more epoch recursions (see EPOCH_TRACE)
than we had before. They will be cleaned up separately, as several
of them aren't trivial. Note, that unlike a lock recursion the
epoch recursion is safe and just wastes a bit of resources.
Reviewed by: gallatin, hselasky, cy, adrian, kristof
Differential Revision: https://reviews.freebsd.org/D19111
2019-10-07 22:40:05 +00:00
|
|
|
NET_EPOCH_ASSERT();
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
IF_AFDATA_UNLOCK_ASSERT(ifp);
|
2004-10-03 00:49:33 +00:00
|
|
|
if (nd6_is_new_addr_neighbor(addr, ifp))
|
|
|
|
return (1);
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* Even if the address matches none of our addresses, it might be
|
|
|
|
* in the neighbor cache.
|
|
|
|
*/
|
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
|
|
|
if ((lle = nd6_lookup(&addr->sin6_addr, LLE_SF(AF_INET6, 0), ifp)) != NULL) {
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
LLE_RUNLOCK(lle);
|
|
|
|
rc = 1;
|
|
|
|
}
|
|
|
|
return (rc);
|
1999-11-22 02:45:11 +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
|
|
|
static __noinline void
|
|
|
|
nd6_free_children(struct llentry *lle)
|
|
|
|
{
|
|
|
|
struct llentry *child_lle;
|
|
|
|
|
|
|
|
NET_EPOCH_ASSERT();
|
|
|
|
LLE_WLOCK_ASSERT(lle);
|
|
|
|
|
|
|
|
while ((child_lle = CK_SLIST_FIRST(&lle->lle_children)) != NULL) {
|
|
|
|
LLE_WLOCK(child_lle);
|
|
|
|
lltable_unlink_child_entry(child_lle);
|
|
|
|
llentry_free(child_lle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-06 08:27:22 +00:00
|
|
|
/*
|
|
|
|
* Tries to update @lle address/prepend data with new @lladdr.
|
|
|
|
*
|
|
|
|
* Returns true on success.
|
|
|
|
* In any case, @lle is returned wlocked.
|
|
|
|
*/
|
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
|
|
|
static __noinline bool
|
|
|
|
nd6_try_set_entry_addr_locked(struct ifnet *ifp, struct llentry *lle, char *lladdr)
|
2021-08-06 08:27:22 +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
|
|
|
u_char buf[LLE_MAX_LINKHDR];
|
|
|
|
int fam, off;
|
|
|
|
size_t sz;
|
2021-08-06 08:27:22 +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
|
|
|
sz = sizeof(buf);
|
|
|
|
if (lltable_calc_llheader(ifp, AF_INET6, lladdr, buf, &sz, &off) != 0)
|
2021-08-06 08:27:22 +00:00
|
|
|
return (false);
|
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
|
|
|
|
|
|
|
/* Update data */
|
|
|
|
lltable_set_entry_addr(ifp, lle, buf, sz, off);
|
|
|
|
|
|
|
|
struct llentry *child_lle;
|
|
|
|
CK_SLIST_FOREACH(child_lle, &lle->lle_children, lle_child_next) {
|
|
|
|
LLE_WLOCK(child_lle);
|
|
|
|
fam = child_lle->r_family;
|
|
|
|
sz = sizeof(buf);
|
|
|
|
if (lltable_calc_llheader(ifp, fam, lladdr, buf, &sz, &off) == 0) {
|
|
|
|
/* success */
|
|
|
|
lltable_set_entry_addr(ifp, child_lle, buf, sz, off);
|
|
|
|
child_lle->ln_state = ND6_LLINFO_REACHABLE;
|
|
|
|
}
|
|
|
|
LLE_WUNLOCK(child_lle);
|
2021-08-06 08:27:22 +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
|
|
|
return (true);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nd6_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle, char *lladdr)
|
|
|
|
{
|
|
|
|
NET_EPOCH_ASSERT();
|
|
|
|
LLE_WLOCK_ASSERT(lle);
|
|
|
|
|
2021-08-06 08:27:22 +00:00
|
|
|
if (!lltable_acquire_wlock(ifp, lle))
|
|
|
|
return (false);
|
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
|
|
|
bool ret = nd6_try_set_entry_addr_locked(ifp, lle, lladdr);
|
2021-08-06 08:27:22 +00:00
|
|
|
IF_AFDATA_WUNLOCK(ifp);
|
|
|
|
|
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
|
|
|
return (ret);
|
2021-08-06 08:27:22 +00:00
|
|
|
}
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* Free an nd6 llinfo entry.
|
2005-10-21 16:23:01 +00:00
|
|
|
* Since the function would cause significant changes in the kernel, DO NOT
|
|
|
|
* make it global, unless you have a strong reason for the change, and are sure
|
|
|
|
* that the change is safe.
|
2015-10-04 08:21:15 +00:00
|
|
|
*
|
|
|
|
* Set noinline to be dtrace-friendly
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2015-10-04 08:21:15 +00:00
|
|
|
static __noinline void
|
2016-03-29 19:23:00 +00:00
|
|
|
nd6_free(struct llentry **lnp, int gc)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2010-11-29 00:04:08 +00:00
|
|
|
struct ifnet *ifp;
|
2016-03-29 19:23:00 +00:00
|
|
|
struct llentry *ln;
|
|
|
|
struct nd_defrouter *dr;
|
|
|
|
|
|
|
|
ln = *lnp;
|
|
|
|
*lnp = NULL;
|
2010-11-29 00:04:08 +00:00
|
|
|
|
|
|
|
LLE_WLOCK_ASSERT(ln);
|
2016-03-29 19:23:00 +00:00
|
|
|
ND6_RLOCK_ASSERT();
|
|
|
|
|
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
|
|
|
KASSERT((ln->la_flags & LLE_CHILD) == 0, ("child lle"));
|
|
|
|
|
2016-03-29 19:23:00 +00:00
|
|
|
ifp = lltable_get_ifp(ln->lle_tbl);
|
|
|
|
if ((ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) != 0)
|
|
|
|
dr = defrouter_lookup_locked(&ln->r_l3addr.addr6, ifp);
|
|
|
|
else
|
|
|
|
dr = NULL;
|
|
|
|
ND6_RUNLOCK();
|
|
|
|
|
|
|
|
if ((ln->la_flags & LLE_DELETED) == 0)
|
|
|
|
EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
/*
|
2003-10-09 16:13:47 +00:00
|
|
|
* we used to have pfctlinput(PRC_HOSTDEAD) here.
|
2001-06-11 12:39:29 +00:00
|
|
|
* even though it is not harmful, it was not really necessary.
|
2000-07-04 16:35:15 +00:00
|
|
|
*/
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2005-10-21 16:23:01 +00:00
|
|
|
/* cancel timer */
|
2010-11-29 00:04:08 +00:00
|
|
|
nd6_llinfo_settimer_locked(ln, -1);
|
|
|
|
|
- Accept Router Advertisement messages even when net.inet6.ip6.forwarding=1.
- A new per-interface knob IFF_ND6_NO_RADR and sysctl IPV6CTL_NO_RADR.
This controls if accepting a route in an RA message as the default route.
The default value for each interface can be set by net.inet6.ip6.no_radr.
The system wide default value is 0.
- A new sysctl: net.inet6.ip6.norbit_raif. This controls if setting R-bit in
NA on RA accepting interfaces. The default is 0 (R-bit is set based on
net.inet6.ip6.forwarding).
Background:
IPv6 host/router model suggests a router sends an RA and a host accepts it for
router discovery. Because of that, KAME implementation does not allow
accepting RAs when net.inet6.ip6.forwarding=1. Accepting RAs on a router can
make the routing table confused since it can change the default router
unintentionally.
However, in practice there are cases where we cannot distinguish a host from
a router clearly. For example, a customer edge router often works as a host
against the ISP, and as a router against the LAN at the same time. Another
example is a complex network configurations like an L2TP tunnel for IPv6
connection to Internet over an Ethernet link with another native IPv6 subnet.
In this case, the physical interface for the native IPv6 subnet works as a
host, and the pseudo-interface for L2TP works as the default IP forwarding
route.
Problem:
Disabling processing RA messages when net.inet6.ip6.forwarding=1 and
accepting them when net.inet6.ip6.forward=0 cause the following practical
issues:
- A router cannot perform SLAAC. It becomes a problem if a box has
multiple interfaces and you want to use SLAAC on some of them, for
example. A customer edge router for IPv6 Internet access service
using an IPv6-over-IPv6 tunnel sometimes needs SLAAC on the
physical interface for administration purpose; updating firmware
and so on (link-local addresses can be used there, but GUAs by
SLAAC are often used for scalability).
- When a host has multiple IPv6 interfaces and it receives multiple RAs on
them, controlling the default route is difficult. Router preferences
defined in RFC 4191 works only when the routers on the links are
under your control.
Details of Implementation Changes:
Router Advertisement messages will be accepted even when
net.inet6.ip6.forwarding=1. More precisely, the conditions are as
follow:
(ACCEPT_RTADV && !NO_RADR && !ip6.forwarding)
=> Normal RA processing on that interface. (as IPv6 host)
(ACCEPT_RTADV && (NO_RADR || ip6.forwarding))
=> Accept RA but add the router to the defroute list with
rtlifetime=0 unconditionally. This effectively prevents
from setting the received router address as the box's
default route.
(!ACCEPT_RTADV)
=> No RA processing on that interface.
ACCEPT_RTADV and NO_RADR are per-interface knob. In short, all interface
are classified as "RA-accepting" or not. An RA-accepting interface always
processes RA messages regardless of ip6.forwarding. The difference caused by
NO_RADR or ip6.forwarding is whether the RA source address is considered as
the default router or not.
R-bit in NA on the RA accepting interfaces is set based on
net.inet6.ip6.forwarding. While RFC 6204 W-1 rule (for CPE case) suggests
a router should disable the R-bit completely even when the box has
net.inet6.ip6.forwarding=1, I believe there is no technical reason with
doing so. This behavior can be set by a new sysctl net.inet6.ip6.norbit_raif
(the default is 0).
Usage:
# ifconfig fxp0 inet6 accept_rtadv
=> accept RA on fxp0
# ifconfig fxp0 inet6 accept_rtadv no_radr
=> accept RA on fxp0 but ignore default route information in it.
# sysctl net.inet6.ip6.norbit_no_radr=1
=> R-bit in NAs on RA accepting interfaces will always be set to 0.
2011-06-06 02:14:23 +00:00
|
|
|
if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
|
2005-10-21 16:23:01 +00:00
|
|
|
if (dr != NULL && dr->expire &&
|
|
|
|
ln->ln_state == ND6_LLINFO_STALE && gc) {
|
|
|
|
/*
|
|
|
|
* If the reason for the deletion is just garbage
|
|
|
|
* collection, and the neighbor is an active default
|
|
|
|
* router, do not delete it. Instead, reset the GC
|
|
|
|
* timer using the router's lifetime.
|
|
|
|
* Simply deleting the entry would affect default
|
|
|
|
* router selection, which is not necessarily a good
|
|
|
|
* thing, especially when we're using router preference
|
|
|
|
* values.
|
|
|
|
* XXX: the check for ln_state would be redundant,
|
|
|
|
* but we intentionally keep it just in case.
|
|
|
|
*/
|
2013-08-05 20:13:02 +00:00
|
|
|
if (dr->expire > time_uptime)
|
2010-11-29 00:04:08 +00:00
|
|
|
nd6_llinfo_settimer_locked(ln,
|
2013-08-05 20:13:02 +00:00
|
|
|
(dr->expire - time_uptime) * hz);
|
2005-10-21 16:23:01 +00:00
|
|
|
else
|
2010-11-29 00:04:08 +00:00
|
|
|
nd6_llinfo_settimer_locked(ln,
|
|
|
|
(long)V_nd6_gctimer * hz);
|
|
|
|
|
2009-11-12 14:48:36 +00:00
|
|
|
LLE_REMREF(ln);
|
|
|
|
LLE_WUNLOCK(ln);
|
2016-02-25 20:12:05 +00:00
|
|
|
defrouter_rele(dr);
|
2015-09-15 06:48:19 +00:00
|
|
|
return;
|
2005-10-21 16:23:01 +00:00
|
|
|
}
|
|
|
|
|
2000-07-04 16:35:15 +00:00
|
|
|
if (dr) {
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
2022-08-07 12:20:52 +00:00
|
|
|
* Unreachability of a router might affect the default
|
2000-07-04 16:35:15 +00:00
|
|
|
* router selection and on-link detection of advertised
|
|
|
|
* prefixes.
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2000-07-04 16:35:15 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Temporarily fake the state to choose a new default
|
|
|
|
* router and to perform on-link determination of
|
2002-04-19 04:46:24 +00:00
|
|
|
* prefixes correctly.
|
2000-07-04 16:35:15 +00:00
|
|
|
* Below the state will be set correctly,
|
|
|
|
* or the entry itself will be deleted.
|
|
|
|
*/
|
|
|
|
ln->ln_state = ND6_LLINFO_INCOMPLETE;
|
2010-12-07 22:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ln->ln_router || dr) {
|
|
|
|
/*
|
|
|
|
* We need to unlock to avoid a LOR with rt6_flush() with the
|
|
|
|
* rnh and for the calls to pfxlist_onlink_check() and
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
* defrouter_select_fib() in the block further down for calls
|
2010-12-07 22:43:29 +00:00
|
|
|
* into nd6_lookup(). We still hold a ref.
|
|
|
|
*/
|
|
|
|
LLE_WUNLOCK(ln);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* rt6_flush must be called whether or not the neighbor
|
|
|
|
* is in the Default Router List.
|
|
|
|
* See a corresponding comment in nd6_na_input().
|
|
|
|
*/
|
2015-08-11 09:26:11 +00:00
|
|
|
rt6_flush(&ln->r_l3addr.addr6, ifp);
|
2010-12-07 22:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dr) {
|
2001-06-11 12:39:29 +00:00
|
|
|
/*
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
* Since defrouter_select_fib() does not affect the
|
2001-06-11 12:39:29 +00:00
|
|
|
* on-link determination and MIP6 needs the check
|
|
|
|
* before the default router selection, we perform
|
|
|
|
* the check now.
|
|
|
|
*/
|
|
|
|
pfxlist_onlink_check();
|
|
|
|
|
2005-10-21 16:23:01 +00:00
|
|
|
/*
|
2010-12-07 22:43:29 +00:00
|
|
|
* Refresh default router list.
|
2005-10-21 16:23:01 +00:00
|
|
|
*/
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
defrouter_select_fib(dr->ifp->if_fib);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2010-12-07 22:43:29 +00:00
|
|
|
|
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
|
|
|
/*
|
|
|
|
* If this entry was added by an on-link redirect, remove the
|
|
|
|
* corresponding host route.
|
|
|
|
*/
|
|
|
|
if (ln->la_flags & LLE_REDIRECT)
|
|
|
|
nd6_free_redirect(ln);
|
|
|
|
|
2010-12-07 22:43:29 +00:00
|
|
|
if (ln->ln_router || dr)
|
|
|
|
LLE_WLOCK(ln);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
|
2010-11-29 00:04:08 +00:00
|
|
|
/*
|
|
|
|
* Save to unlock. We still hold an extra reference and will not
|
|
|
|
* free(9) in llentry_free() if someone else holds one as well.
|
|
|
|
*/
|
|
|
|
LLE_WUNLOCK(ln);
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
IF_AFDATA_LOCK(ifp);
|
|
|
|
LLE_WLOCK(ln);
|
2012-12-13 11:11:15 +00:00
|
|
|
/* Guard against race with other llentry_free(). */
|
|
|
|
if (ln->la_flags & LLE_LINKED) {
|
2015-09-15 06:48:19 +00:00
|
|
|
/* Remove callout reference */
|
2012-12-13 11:11:15 +00:00
|
|
|
LLE_REMREF(ln);
|
2015-09-15 06:48:19 +00:00
|
|
|
lltable_unlink_entry(ln->lle_tbl, ln);
|
|
|
|
}
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
IF_AFDATA_UNLOCK(ifp);
|
2001-06-11 12:39:29 +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
|
|
|
nd6_free_children(ln);
|
|
|
|
|
2015-09-15 06:48:19 +00:00
|
|
|
llentry_free(ln);
|
2016-02-25 20:12:05 +00:00
|
|
|
if (dr != NULL)
|
|
|
|
defrouter_rele(dr);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2015-11-30 05:51:14 +00:00
|
|
|
static int
|
2020-04-16 17:20:18 +00:00
|
|
|
nd6_isdynrte(const struct rtentry *rt, const struct nhop_object *nh, void *xap)
|
2015-11-30 05:51:14 +00:00
|
|
|
{
|
|
|
|
|
2020-04-16 17:20:18 +00:00
|
|
|
if (nh->nh_flags & NHF_REDIRECT)
|
2015-11-30 05:51:14 +00:00
|
|
|
return (1);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
2020-04-16 17:20:18 +00:00
|
|
|
|
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
|
|
|
/*
|
|
|
|
* Remove the rtentry for the given llentry,
|
|
|
|
* both of which were installed by a redirect.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
nd6_free_redirect(const struct llentry *ln)
|
|
|
|
{
|
|
|
|
int fibnum;
|
|
|
|
struct sockaddr_in6 sin6;
|
2020-07-21 19:56:13 +00:00
|
|
|
struct rib_cmd_info rc;
|
2020-05-23 10:21:02 +00:00
|
|
|
struct epoch_tracker et;
|
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
|
|
|
|
|
|
|
lltable_fill_sa_entry(ln, (struct sockaddr *)&sin6);
|
|
|
|
|
2020-05-23 10:21:02 +00:00
|
|
|
NET_EPOCH_ENTER(et);
|
2015-11-30 05:51:14 +00:00
|
|
|
for (fibnum = 0; fibnum < rt_numfibs; fibnum++)
|
2022-08-09 11:45:59 +00:00
|
|
|
rib_del_route_px(fibnum, (struct sockaddr *)&sin6, 128,
|
|
|
|
nd6_isdynrte, NULL, 0, &rc);
|
2020-05-23 10:21:02 +00:00
|
|
|
NET_EPOCH_EXIT(et);
|
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
|
|
|
}
|
|
|
|
|
2011-11-11 23:22:38 +00:00
|
|
|
/*
|
2020-07-12 11:24:23 +00:00
|
|
|
* Updates status of the default router route.
|
2011-11-11 23:22:38 +00:00
|
|
|
*/
|
2020-09-21 20:02:26 +00:00
|
|
|
static void
|
2022-08-29 18:10:21 +00:00
|
|
|
check_release_defrouter(const struct rib_cmd_info *rc, void *_cbdata)
|
2011-11-11 23:22:38 +00:00
|
|
|
{
|
|
|
|
struct nd_defrouter *dr;
|
2020-07-12 11:24:23 +00:00
|
|
|
struct nhop_object *nh;
|
2011-11-11 23:22:38 +00:00
|
|
|
|
2020-09-21 20:02:26 +00:00
|
|
|
nh = rc->rc_nh_old;
|
2011-11-11 23:22:38 +00:00
|
|
|
|
2020-09-21 20:02:26 +00:00
|
|
|
if ((nh != NULL) && (nh->nh_flags & NHF_DEFAULT)) {
|
|
|
|
dr = defrouter_lookup(&nh->gw6_sa.sin6_addr, nh->nh_ifp);
|
|
|
|
if (dr != NULL) {
|
|
|
|
dr->installed = 0;
|
|
|
|
defrouter_rele(dr);
|
2011-11-11 23:22:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-21 20:02:26 +00:00
|
|
|
void
|
|
|
|
nd6_subscription_cb(struct rib_head *rnh, struct rib_cmd_info *rc, void *arg)
|
|
|
|
{
|
|
|
|
|
2020-10-03 10:47:17 +00:00
|
|
|
#ifdef ROUTE_MPATH
|
|
|
|
rib_decompose_notification(rc, check_release_defrouter, NULL);
|
|
|
|
#else
|
2020-09-21 20:02:26 +00:00
|
|
|
check_release_defrouter(rc, NULL);
|
2020-10-03 10:47:17 +00:00
|
|
|
#endif
|
2020-09-21 20:02:26 +00:00
|
|
|
}
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
int
|
2007-07-05 16:23:49 +00:00
|
|
|
nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
|
|
|
struct in6_ndireq *ndi = (struct in6_ndireq *)data;
|
|
|
|
struct in6_nbrinfo *nbi = (struct in6_nbrinfo *)data;
|
2000-07-04 16:35:15 +00:00
|
|
|
struct in6_ndifreq *ndif = (struct in6_ndifreq *)data;
|
2019-01-09 01:11:19 +00:00
|
|
|
struct epoch_tracker et;
|
2015-09-10 06:29:18 +00:00
|
|
|
int error = 0;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2013-07-31 16:24:49 +00:00
|
|
|
if (ifp->if_afdata[AF_INET6] == NULL)
|
|
|
|
return (EPFNOSUPPORT);
|
1999-11-22 02:45:11 +00:00
|
|
|
switch (cmd) {
|
2001-06-11 12:39:29 +00:00
|
|
|
case OSIOCGIFINFO_IN6:
|
2005-10-19 10:09:19 +00:00
|
|
|
#define ND ndi->ndi
|
2003-10-17 15:46:31 +00:00
|
|
|
/* XXX: old ndp(8) assumes a positive value for linkmtu. */
|
2005-10-19 10:09:19 +00:00
|
|
|
bzero(&ND, sizeof(ND));
|
|
|
|
ND.linkmtu = IN6_LINKMTU(ifp);
|
|
|
|
ND.maxmtu = ND_IFINFO(ifp)->maxmtu;
|
|
|
|
ND.basereachable = ND_IFINFO(ifp)->basereachable;
|
|
|
|
ND.reachable = ND_IFINFO(ifp)->reachable;
|
|
|
|
ND.retrans = ND_IFINFO(ifp)->retrans;
|
|
|
|
ND.flags = ND_IFINFO(ifp)->flags;
|
|
|
|
ND.recalctm = ND_IFINFO(ifp)->recalctm;
|
|
|
|
ND.chlim = ND_IFINFO(ifp)->chlim;
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
|
|
|
case SIOCGIFINFO_IN6:
|
2005-10-19 10:09:19 +00:00
|
|
|
ND = *ND_IFINFO(ifp);
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
2005-10-19 15:05:42 +00:00
|
|
|
case SIOCSIFINFO_IN6:
|
|
|
|
/*
|
|
|
|
* used to change host variables from userland.
|
2016-05-03 18:05:43 +00:00
|
|
|
* intended for a use on router to reflect RA configurations.
|
2005-10-19 15:05:42 +00:00
|
|
|
*/
|
|
|
|
/* 0 means 'unspecified' */
|
|
|
|
if (ND.linkmtu != 0) {
|
|
|
|
if (ND.linkmtu < IPV6_MMTU ||
|
|
|
|
ND.linkmtu > IN6_LINKMTU(ifp)) {
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ND_IFINFO(ifp)->linkmtu = ND.linkmtu;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ND.basereachable != 0) {
|
|
|
|
int obasereachable = ND_IFINFO(ifp)->basereachable;
|
|
|
|
|
|
|
|
ND_IFINFO(ifp)->basereachable = ND.basereachable;
|
|
|
|
if (ND.basereachable != obasereachable)
|
|
|
|
ND_IFINFO(ifp)->reachable =
|
|
|
|
ND_COMPUTE_RTIME(ND.basereachable);
|
|
|
|
}
|
|
|
|
if (ND.retrans != 0)
|
|
|
|
ND_IFINFO(ifp)->retrans = ND.retrans;
|
|
|
|
if (ND.chlim != 0)
|
|
|
|
ND_IFINFO(ifp)->chlim = ND.chlim;
|
|
|
|
/* FALLTHROUGH */
|
2000-07-04 16:35:15 +00:00
|
|
|
case SIOCSIFINFO_FLAGS:
|
2009-09-12 22:08:20 +00:00
|
|
|
{
|
|
|
|
struct ifaddr *ifa;
|
|
|
|
struct in6_ifaddr *ia;
|
|
|
|
|
|
|
|
if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) &&
|
|
|
|
!(ND.flags & ND6_IFF_IFDISABLED)) {
|
|
|
|
/* ifdisabled 1->0 transision */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the interface is marked as ND6_IFF_IFDISABLED and
|
|
|
|
* has an link-local address with IN6_IFF_DUPLICATED,
|
|
|
|
* do not clear ND6_IFF_IFDISABLED.
|
|
|
|
* See RFC 4862, Section 5.4.5.
|
|
|
|
*/
|
2019-10-13 04:25:16 +00:00
|
|
|
NET_EPOCH_ENTER(et);
|
2018-05-18 20:13:34 +00:00
|
|
|
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
|
2009-09-12 22:08:20 +00:00
|
|
|
if (ifa->ifa_addr->sa_family != AF_INET6)
|
|
|
|
continue;
|
|
|
|
ia = (struct in6_ifaddr *)ifa;
|
|
|
|
if ((ia->ia6_flags & IN6_IFF_DUPLICATED) &&
|
2015-09-10 06:29:18 +00:00
|
|
|
IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia)))
|
2009-09-12 22:08:20 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-10-13 04:25:16 +00:00
|
|
|
NET_EPOCH_EXIT(et);
|
2009-09-12 22:08:20 +00:00
|
|
|
|
2015-09-10 06:29:18 +00:00
|
|
|
if (ifa != NULL) {
|
|
|
|
/* LLA is duplicated. */
|
2009-09-12 22:08:20 +00:00
|
|
|
ND.flags |= ND6_IFF_IFDISABLED;
|
|
|
|
log(LOG_ERR, "Cannot enable an interface"
|
|
|
|
" with a link-local address marked"
|
|
|
|
" duplicate.\n");
|
|
|
|
} else {
|
|
|
|
ND_IFINFO(ifp)->flags &= ~ND6_IFF_IFDISABLED;
|
2011-10-16 19:46:52 +00:00
|
|
|
if (ifp->if_flags & IFF_UP)
|
|
|
|
in6_if_up(ifp);
|
2009-09-12 22:08:20 +00:00
|
|
|
}
|
|
|
|
} else if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) &&
|
|
|
|
(ND.flags & ND6_IFF_IFDISABLED)) {
|
|
|
|
/* ifdisabled 0->1 transision */
|
|
|
|
/* Mark all IPv6 address as tentative. */
|
|
|
|
|
|
|
|
ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
|
2015-10-03 12:09:12 +00:00
|
|
|
if (V_ip6_dad_count > 0 &&
|
|
|
|
(ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD) == 0) {
|
2019-10-13 04:25:16 +00:00
|
|
|
NET_EPOCH_ENTER(et);
|
2018-05-18 20:13:34 +00:00
|
|
|
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead,
|
2015-09-10 06:29:18 +00:00
|
|
|
ifa_link) {
|
|
|
|
if (ifa->ifa_addr->sa_family !=
|
|
|
|
AF_INET6)
|
|
|
|
continue;
|
|
|
|
ia = (struct in6_ifaddr *)ifa;
|
|
|
|
ia->ia6_flags |= IN6_IFF_TENTATIVE;
|
|
|
|
}
|
2019-10-13 04:25:16 +00:00
|
|
|
NET_EPOCH_EXIT(et);
|
2009-09-12 22:08:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-16 19:46:52 +00:00
|
|
|
if (ND.flags & ND6_IFF_AUTO_LINKLOCAL) {
|
|
|
|
if (!(ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL)) {
|
|
|
|
/* auto_linklocal 0->1 transision */
|
2009-09-12 22:08:20 +00:00
|
|
|
|
2011-10-16 19:46:52 +00:00
|
|
|
/* If no link-local address on ifp, configure */
|
|
|
|
ND_IFINFO(ifp)->flags |= ND6_IFF_AUTO_LINKLOCAL;
|
|
|
|
in6_ifattach(ifp, NULL);
|
|
|
|
} else if (!(ND.flags & ND6_IFF_IFDISABLED) &&
|
|
|
|
ifp->if_flags & IFF_UP) {
|
|
|
|
/*
|
|
|
|
* When the IF already has
|
|
|
|
* ND6_IFF_AUTO_LINKLOCAL, no link-local
|
|
|
|
* address is assigned, and IFF_UP, try to
|
|
|
|
* assign one.
|
|
|
|
*/
|
2019-10-13 04:25:16 +00:00
|
|
|
NET_EPOCH_ENTER(et);
|
2018-05-18 20:13:34 +00:00
|
|
|
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead,
|
2015-09-10 06:29:18 +00:00
|
|
|
ifa_link) {
|
|
|
|
if (ifa->ifa_addr->sa_family !=
|
|
|
|
AF_INET6)
|
2011-10-16 19:46:52 +00:00
|
|
|
continue;
|
|
|
|
ia = (struct in6_ifaddr *)ifa;
|
2015-09-10 06:29:18 +00:00
|
|
|
if (IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia)))
|
2011-10-16 19:46:52 +00:00
|
|
|
break;
|
2011-06-06 02:37:38 +00:00
|
|
|
}
|
2019-10-13 04:25:16 +00:00
|
|
|
NET_EPOCH_EXIT(et);
|
2015-09-10 06:29:18 +00:00
|
|
|
if (ifa != NULL)
|
|
|
|
/* No LLA is configured. */
|
2011-10-16 19:46:52 +00:00
|
|
|
in6_ifattach(ifp, NULL);
|
2011-06-06 02:37:38 +00:00
|
|
|
}
|
2009-09-12 22:08:20 +00:00
|
|
|
}
|
2005-10-19 10:09:19 +00:00
|
|
|
ND_IFINFO(ifp)->flags = ND.flags;
|
2000-07-04 16:35:15 +00:00
|
|
|
break;
|
Widen NET_EPOCH coverage.
When epoch(9) was introduced to network stack, it was basically
dropped in place of existing locking, which was mutexes and
rwlocks. For the sake of performance mutex covered areas were
as small as possible, so became epoch covered areas.
However, epoch doesn't introduce any contention, it just delays
memory reclaim. So, there is no point to minimise epoch covered
areas in sense of performance. Meanwhile entering/exiting epoch
also has non-zero CPU usage, so doing this less often is a win.
Not the least is also code maintainability. In the new paradigm
we can assume that at any stage of processing a packet, we are
inside network epoch. This makes coding both input and output
path way easier.
On output path we already enter epoch quite early - in the
ip_output(), in the ip6_output().
This patch does the same for the input path. All ISR processing,
network related callouts, other ways of packet injection to the
network stack shall be performed in net_epoch. Any leaf function
that walks network configuration now asserts epoch.
Tricky part is configuration code paths - ioctls, sysctls. They
also call into leaf functions, so some need to be changed.
This patch would introduce more epoch recursions (see EPOCH_TRACE)
than we had before. They will be cleaned up separately, as several
of them aren't trivial. Note, that unlike a lock recursion the
epoch recursion is safe and just wastes a bit of resources.
Reviewed by: gallatin, hselasky, cy, adrian, kristof
Differential Revision: https://reviews.freebsd.org/D19111
2019-10-07 22:40:05 +00:00
|
|
|
}
|
2005-10-19 10:09:19 +00:00
|
|
|
#undef ND
|
2000-07-04 16:35:15 +00:00
|
|
|
case SIOCSNDFLUSH_IN6: /* XXX: the ioctl name is confusing... */
|
2005-10-21 16:23:01 +00:00
|
|
|
/* sync kernel routing table with the default router list */
|
|
|
|
defrouter_reset();
|
2019-11-16 00:17:35 +00:00
|
|
|
defrouter_select_fib(RT_ALL_FIBS);
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
|
|
|
case SIOCSPFXFLUSH_IN6:
|
2003-10-09 16:13:47 +00:00
|
|
|
{
|
1999-11-22 02:45:11 +00:00
|
|
|
/* flush all the prefix advertised by routers */
|
2016-10-07 21:10:53 +00:00
|
|
|
struct in6_ifaddr *ia, *ia_next;
|
1999-11-22 02:45:11 +00:00
|
|
|
struct nd_prefix *pr, *next;
|
2016-10-07 21:10:53 +00:00
|
|
|
struct nd_prhead prl;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2016-10-07 21:10:53 +00:00
|
|
|
LIST_INIT(&prl);
|
2001-06-11 12:39:29 +00:00
|
|
|
|
2016-10-07 21:10:53 +00:00
|
|
|
ND6_WLOCK();
|
|
|
|
LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, next) {
|
2022-08-23 16:19:50 +00:00
|
|
|
if (pr->ndpr_raf_ra_derived)
|
|
|
|
nd6_prefix_unlink(pr, &prl);
|
2016-10-07 21:10:53 +00:00
|
|
|
}
|
|
|
|
ND6_WUNLOCK();
|
2001-06-11 12:39:29 +00:00
|
|
|
|
2016-10-07 21:10:53 +00:00
|
|
|
while ((pr = LIST_FIRST(&prl)) != NULL) {
|
|
|
|
LIST_REMOVE(pr, ndpr_entry);
|
2009-06-25 16:35:28 +00:00
|
|
|
/* XXXRW: in6_ifaddrhead locking. */
|
2018-05-18 20:13:34 +00:00
|
|
|
CK_STAILQ_FOREACH_SAFE(ia, &V_in6_ifaddrhead, ia_link,
|
2009-06-24 21:00:25 +00:00
|
|
|
ia_next) {
|
2001-06-11 12:39:29 +00:00
|
|
|
if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (ia->ia6_ndpr == pr)
|
|
|
|
in6_purgeaddr(&ia->ia_ifa);
|
|
|
|
}
|
2016-10-07 21:10:53 +00:00
|
|
|
nd6_prefix_del(pr);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
break;
|
2003-10-09 16:13:47 +00:00
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
case SIOCSRTRFLUSH_IN6:
|
2003-10-09 16:13:47 +00:00
|
|
|
{
|
1999-11-22 02:45:11 +00:00
|
|
|
/* flush all the default routers */
|
|
|
|
|
2005-10-21 16:23:01 +00:00
|
|
|
defrouter_reset();
|
2019-11-13 12:05:48 +00:00
|
|
|
nd6_defrouter_flush_all();
|
2019-11-16 00:17:35 +00:00
|
|
|
defrouter_select_fib(RT_ALL_FIBS);
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
2003-10-09 16:13:47 +00:00
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
case SIOCGNBRINFO_IN6:
|
2003-10-09 16:13:47 +00:00
|
|
|
{
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
struct llentry *ln;
|
1999-11-22 02:45:11 +00:00
|
|
|
struct in6_addr nb_addr = nbi->addr; /* make local for safety */
|
|
|
|
|
2005-07-25 12:31:43 +00:00
|
|
|
if ((error = in6_setscope(&nb_addr, ifp, NULL)) != 0)
|
|
|
|
return (error);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2019-01-09 01:11:19 +00:00
|
|
|
NET_EPOCH_ENTER(et);
|
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
|
|
|
ln = nd6_lookup(&nb_addr, LLE_SF(AF_INET6, 0), ifp);
|
2019-01-09 01:11:19 +00:00
|
|
|
NET_EPOCH_EXIT(et);
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
|
|
|
|
if (ln == NULL) {
|
1999-11-22 02:45:11 +00:00
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
nbi->state = ln->ln_state;
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
nbi->asked = ln->la_asked;
|
1999-11-22 02:45:11 +00:00
|
|
|
nbi->isrouter = ln->ln_router;
|
2013-08-17 07:14:45 +00:00
|
|
|
if (ln->la_expire == 0)
|
|
|
|
nbi->expire = 0;
|
|
|
|
else
|
2015-12-16 10:14:16 +00:00
|
|
|
nbi->expire = ln->la_expire + ln->lle_remtime / hz +
|
2013-08-17 07:14:45 +00:00
|
|
|
(time_second - time_uptime);
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
LLE_RUNLOCK(ln);
|
1999-11-22 02:45:11 +00:00
|
|
|
break;
|
2003-10-09 16:13:47 +00:00
|
|
|
}
|
2000-07-04 16:35:15 +00:00
|
|
|
case SIOCGDEFIFACE_IN6: /* XXX: should be implemented as a sysctl? */
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
ndif->ifindex = V_nd6_defifindex;
|
2000-07-04 16:35:15 +00:00
|
|
|
break;
|
|
|
|
case SIOCSDEFIFACE_IN6: /* XXX: should be implemented as a sysctl? */
|
2003-10-06 14:02:09 +00:00
|
|
|
return (nd6_setdefaultiface(ndif->ifindex));
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2003-10-06 14:02:09 +00:00
|
|
|
return (error);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-15 17:16:31 +00:00
|
|
|
/*
|
|
|
|
* Calculates new isRouter value based on provided parameters and
|
|
|
|
* returns it.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
nd6_is_router(int type, int code, int is_new, int old_addr, int new_addr,
|
|
|
|
int ln_router)
|
|
|
|
{
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ICMP6 type dependent behavior.
|
|
|
|
*
|
|
|
|
* NS: clear IsRouter if new entry
|
|
|
|
* RS: clear IsRouter
|
|
|
|
* RA: set IsRouter if there's lladdr
|
|
|
|
* redir: clear IsRouter if new entry
|
|
|
|
*
|
|
|
|
* RA case, (1):
|
|
|
|
* The spec says that we must set IsRouter in the following cases:
|
|
|
|
* - If lladdr exist, set IsRouter. This means (1-5).
|
|
|
|
* - If it is old entry (!newentry), set IsRouter. This means (7).
|
|
|
|
* So, based on the spec, in (1-5) and (7) cases we must set IsRouter.
|
|
|
|
* A quetion arises for (1) case. (1) case has no lladdr in the
|
|
|
|
* neighbor cache, this is similar to (6).
|
|
|
|
* This case is rare but we figured that we MUST NOT set IsRouter.
|
|
|
|
*
|
2015-09-18 07:18:10 +00:00
|
|
|
* is_new old_addr new_addr NS RS RA redir
|
2015-09-15 17:16:31 +00:00
|
|
|
* D R
|
2015-09-18 07:18:10 +00:00
|
|
|
* 0 n n (1) c ? s
|
|
|
|
* 0 y n (2) c s s
|
|
|
|
* 0 n y (3) c s s
|
|
|
|
* 0 y y (4) c s s
|
|
|
|
* 0 y y (5) c s s
|
|
|
|
* 1 -- n (6) c c c s
|
|
|
|
* 1 -- y (7) c c s c s
|
2015-09-15 17:16:31 +00:00
|
|
|
*
|
|
|
|
* (c=clear s=set)
|
|
|
|
*/
|
|
|
|
switch (type & 0xff) {
|
|
|
|
case ND_NEIGHBOR_SOLICIT:
|
|
|
|
/*
|
|
|
|
* New entry must have is_router flag cleared.
|
|
|
|
*/
|
|
|
|
if (is_new) /* (6-7) */
|
|
|
|
ln_router = 0;
|
|
|
|
break;
|
|
|
|
case ND_REDIRECT:
|
|
|
|
/*
|
|
|
|
* If the icmp is a redirect to a better router, always set the
|
|
|
|
* is_router flag. Otherwise, if the entry is newly created,
|
|
|
|
* clear the flag. [RFC 2461, sec 8.3]
|
|
|
|
*/
|
|
|
|
if (code == ND_REDIRECT_ROUTER)
|
|
|
|
ln_router = 1;
|
|
|
|
else {
|
|
|
|
if (is_new) /* (6-7) */
|
|
|
|
ln_router = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ND_ROUTER_SOLICIT:
|
|
|
|
/*
|
|
|
|
* is_router flag must always be cleared.
|
|
|
|
*/
|
|
|
|
ln_router = 0;
|
|
|
|
break;
|
|
|
|
case ND_ROUTER_ADVERT:
|
|
|
|
/*
|
|
|
|
* Mark an entry with lladdr as a router.
|
|
|
|
*/
|
|
|
|
if ((!is_new && (old_addr || new_addr)) || /* (2-5) */
|
|
|
|
(is_new && new_addr)) { /* (7) */
|
|
|
|
ln_router = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ln_router);
|
|
|
|
}
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* Create neighbor cache entry and cache link-layer address,
|
2003-10-09 16:13:47 +00:00
|
|
|
* on reception of inbound ND6 packets. (RS/RA/NS/redirect)
|
2007-07-05 16:23:49 +00:00
|
|
|
*
|
|
|
|
* type - ICMP6 type
|
|
|
|
* code - type dependent information
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
*
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2015-09-15 17:16:31 +00:00
|
|
|
void
|
2007-07-05 16:23:49 +00:00
|
|
|
nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
|
|
|
int lladdrlen, int type, int code)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2015-08-20 12:05:17 +00:00
|
|
|
struct llentry *ln = NULL, *ln_tmp;
|
1999-11-22 02:45:11 +00:00
|
|
|
int is_newentry;
|
|
|
|
int do_update;
|
|
|
|
int olladdr;
|
|
|
|
int llchange;
|
2010-11-17 10:43:20 +00:00
|
|
|
int flags;
|
2008-12-16 01:21:19 +00:00
|
|
|
uint16_t router = 0;
|
2008-12-16 23:06:36 +00:00
|
|
|
struct mbuf *chain = NULL;
|
2015-12-31 05:03:27 +00:00
|
|
|
u_char linkhdr[LLE_MAX_LINKHDR];
|
|
|
|
size_t linkhdrsize;
|
|
|
|
int lladdr_off;
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
|
Widen NET_EPOCH coverage.
When epoch(9) was introduced to network stack, it was basically
dropped in place of existing locking, which was mutexes and
rwlocks. For the sake of performance mutex covered areas were
as small as possible, so became epoch covered areas.
However, epoch doesn't introduce any contention, it just delays
memory reclaim. So, there is no point to minimise epoch covered
areas in sense of performance. Meanwhile entering/exiting epoch
also has non-zero CPU usage, so doing this less often is a win.
Not the least is also code maintainability. In the new paradigm
we can assume that at any stage of processing a packet, we are
inside network epoch. This makes coding both input and output
path way easier.
On output path we already enter epoch quite early - in the
ip_output(), in the ip6_output().
This patch does the same for the input path. All ISR processing,
network related callouts, other ways of packet injection to the
network stack shall be performed in net_epoch. Any leaf function
that walks network configuration now asserts epoch.
Tricky part is configuration code paths - ioctls, sysctls. They
also call into leaf functions, so some need to be changed.
This patch would introduce more epoch recursions (see EPOCH_TRACE)
than we had before. They will be cleaned up separately, as several
of them aren't trivial. Note, that unlike a lock recursion the
epoch recursion is safe and just wastes a bit of resources.
Reviewed by: gallatin, hselasky, cy, adrian, kristof
Differential Revision: https://reviews.freebsd.org/D19111
2019-10-07 22:40:05 +00:00
|
|
|
NET_EPOCH_ASSERT();
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
IF_AFDATA_UNLOCK_ASSERT(ifp);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2012-05-25 09:27:16 +00:00
|
|
|
KASSERT(ifp != NULL, ("%s: ifp == NULL", __func__));
|
|
|
|
KASSERT(from != NULL, ("%s: from == NULL", __func__));
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
/* nothing must be updated for unspecified address */
|
|
|
|
if (IN6_IS_ADDR_UNSPECIFIED(from))
|
2015-09-15 17:16:31 +00:00
|
|
|
return;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Validation about ifp->if_addrlen and lladdrlen must be done in
|
|
|
|
* the caller.
|
|
|
|
*
|
|
|
|
* XXX If the link does not have link-layer adderss, what should
|
|
|
|
* we do? (ifp->if_addrlen == 0)
|
|
|
|
* Spec says nothing in sections for RA, RS and NA. There's small
|
|
|
|
* description on it in NS section (RFC 2461 7.2.3).
|
|
|
|
*/
|
2015-09-22 20:45:04 +00:00
|
|
|
flags = lladdr ? LLE_EXCLUSIVE : 0;
|
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
|
|
|
ln = nd6_lookup(from, LLE_SF(AF_INET6, flags), ifp);
|
2015-08-20 12:05:17 +00:00
|
|
|
is_newentry = 0;
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
if (ln == NULL) {
|
2015-09-22 20:45:04 +00:00
|
|
|
flags |= LLE_EXCLUSIVE;
|
2015-08-20 12:05:17 +00:00
|
|
|
ln = nd6_alloc(from, 0, ifp);
|
|
|
|
if (ln == NULL)
|
2015-09-15 17:16:31 +00:00
|
|
|
return;
|
2015-09-19 11:50:02 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Since we already know all the data for the new entry,
|
|
|
|
* fill it before insertion.
|
|
|
|
*/
|
2015-12-31 05:03:27 +00:00
|
|
|
if (lladdr != NULL) {
|
|
|
|
linkhdrsize = sizeof(linkhdr);
|
|
|
|
if (lltable_calc_llheader(ifp, AF_INET6, lladdr,
|
2022-04-08 15:47:25 +00:00
|
|
|
linkhdr, &linkhdrsize, &lladdr_off) != 0) {
|
|
|
|
lltable_free_entry(LLTABLE6(ifp), ln);
|
2015-12-31 05:03:27 +00:00
|
|
|
return;
|
2022-04-08 15:47:25 +00:00
|
|
|
}
|
2015-12-31 05:03:27 +00:00
|
|
|
lltable_set_entry_addr(ifp, ln, linkhdr, linkhdrsize,
|
|
|
|
lladdr_off);
|
|
|
|
}
|
|
|
|
|
2015-08-20 12:05:17 +00:00
|
|
|
IF_AFDATA_WLOCK(ifp);
|
|
|
|
LLE_WLOCK(ln);
|
|
|
|
/* Prefer any existing lle over newly-created one */
|
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
|
|
|
ln_tmp = nd6_lookup(from, LLE_SF(AF_INET6, LLE_EXCLUSIVE), ifp);
|
2015-08-20 12:05:17 +00:00
|
|
|
if (ln_tmp == NULL)
|
|
|
|
lltable_link_entry(LLTABLE6(ifp), ln);
|
|
|
|
IF_AFDATA_WUNLOCK(ifp);
|
2015-09-21 10:24:34 +00:00
|
|
|
if (ln_tmp == NULL) {
|
2015-10-04 19:10:27 +00:00
|
|
|
/* No existing lle, mark as new entry (6,7) */
|
2015-08-20 12:05:17 +00:00
|
|
|
is_newentry = 1;
|
2018-01-29 16:12:26 +00:00
|
|
|
if (lladdr != NULL) { /* (7) */
|
|
|
|
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
|
2015-10-04 19:10:27 +00:00
|
|
|
EVENTHANDLER_INVOKE(lle_event, ln,
|
|
|
|
LLENTRY_RESOLVED);
|
2018-01-29 16:12:26 +00:00
|
|
|
}
|
2015-09-21 10:24:34 +00:00
|
|
|
} else {
|
2015-08-20 12:05:17 +00:00
|
|
|
lltable_free_entry(LLTABLE6(ifp), ln);
|
|
|
|
ln = ln_tmp;
|
|
|
|
ln_tmp = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* do nothing if static ndp is set */
|
|
|
|
if ((ln->la_flags & LLE_STATIC)) {
|
2015-09-22 20:45:04 +00:00
|
|
|
if (flags & LLE_EXCLUSIVE)
|
2015-09-15 17:16:31 +00:00
|
|
|
LLE_WUNLOCK(ln);
|
|
|
|
else
|
|
|
|
LLE_RUNLOCK(ln);
|
|
|
|
return;
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
|
|
|
|
olladdr = (ln->la_flags & LLE_VALID) ? 1 : 0;
|
1999-11-22 02:45:11 +00:00
|
|
|
if (olladdr && lladdr) {
|
2015-12-31 05:03:27 +00:00
|
|
|
llchange = bcmp(lladdr, ln->ll_addr,
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
ifp->if_addrlen);
|
2015-09-18 07:18:10 +00:00
|
|
|
} else if (!olladdr && lladdr)
|
|
|
|
llchange = 1;
|
|
|
|
else
|
1999-11-22 02:45:11 +00:00
|
|
|
llchange = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* newentry olladdr lladdr llchange (*=record)
|
|
|
|
* 0 n n -- (1)
|
|
|
|
* 0 y n -- (2)
|
2015-09-18 07:18:10 +00:00
|
|
|
* 0 n y y (3) * STALE
|
1999-11-22 02:45:11 +00:00
|
|
|
* 0 y y n (4) *
|
|
|
|
* 0 y y y (5) * STALE
|
|
|
|
* 1 -- n -- (6) NOSTATE(= PASSIVE)
|
|
|
|
* 1 -- y -- (7) * STALE
|
|
|
|
*/
|
|
|
|
|
2015-09-19 11:50:02 +00:00
|
|
|
do_update = 0;
|
2015-10-04 12:42:07 +00:00
|
|
|
if (is_newentry == 0 && llchange != 0) {
|
2015-09-19 11:50:02 +00:00
|
|
|
do_update = 1; /* (3,5) */
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* Record source link-layer address
|
|
|
|
* XXX is it dependent to ifp->if_type?
|
|
|
|
*/
|
2021-08-06 08:27:22 +00:00
|
|
|
if (!nd6_try_set_entry_addr(ifp, ln, lladdr)) {
|
2015-12-13 07:39:49 +00:00
|
|
|
/* Entry was deleted */
|
2021-08-06 08:27:22 +00:00
|
|
|
LLE_WUNLOCK(ln);
|
2015-12-13 07:39:49 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-04 12:42:07 +00:00
|
|
|
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2015-09-19 11:50:02 +00:00
|
|
|
EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2015-10-04 12:42:07 +00:00
|
|
|
if (ln->la_hold != NULL)
|
2021-08-02 23:16:48 +00:00
|
|
|
chain = nd6_grab_holdchain(ln);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2015-09-15 17:16:31 +00:00
|
|
|
/* Calculates new router status */
|
|
|
|
router = nd6_is_router(type, code, is_newentry, olladdr,
|
|
|
|
lladdr != NULL ? 1 : 0, ln->ln_router);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2015-09-15 17:16:31 +00:00
|
|
|
ln->ln_router = router;
|
|
|
|
/* Mark non-router redirects with special flag */
|
|
|
|
if ((type & 0xFF) == ND_REDIRECT && code != ND_REDIRECT_ROUTER)
|
|
|
|
ln->la_flags |= LLE_REDIRECT;
|
|
|
|
|
2015-09-22 20:45:04 +00:00
|
|
|
if (flags & LLE_EXCLUSIVE)
|
2015-09-15 17:16:31 +00:00
|
|
|
LLE_WUNLOCK(ln);
|
|
|
|
else
|
|
|
|
LLE_RUNLOCK(ln);
|
2008-12-16 00:16:51 +00:00
|
|
|
|
2015-01-08 18:02:05 +00:00
|
|
|
if (chain != NULL)
|
2021-08-02 23:16:48 +00:00
|
|
|
nd6_flush_holdchain(ifp, ln, chain);
|
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
|
|
|
if (do_update)
|
|
|
|
nd6_flush_children_holdchain(ifp, ln);
|
2020-09-01 21:19:14 +00:00
|
|
|
|
2001-07-04 11:27:24 +00:00
|
|
|
/*
|
|
|
|
* When the link-layer address of a router changes, select the
|
|
|
|
* best router again. In particular, when the neighbor entry is newly
|
|
|
|
* created, it might affect the selection policy.
|
|
|
|
* Question: can we restrict the first condition to the "is_newentry"
|
|
|
|
* case?
|
|
|
|
* XXX: when we hear an RA from a new router with the link-layer
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
* address option, defrouter_select_fib() is called twice, since
|
2001-07-04 11:27:24 +00:00
|
|
|
* defrtrlist_update called the function as well. However, I believe
|
|
|
|
* we can compromise the overhead, since it only happens the first
|
|
|
|
* time.
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
* XXX: although defrouter_select_fib() should not have a bad effect
|
2001-07-04 11:27:24 +00:00
|
|
|
* for those are not autoconfigured hosts, we explicitly avoid such
|
|
|
|
* cases for safety.
|
|
|
|
*/
|
2015-09-19 11:50:02 +00:00
|
|
|
if ((do_update || is_newentry) && router &&
|
2009-09-12 22:08:20 +00:00
|
|
|
ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
/*
|
|
|
|
* guaranteed recursion
|
|
|
|
*/
|
Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0
sys/netinet6/icmp6.c
Use the interface's FIB for source address selection in ICMPv6 error
responses.
sys/netinet6/in6.c
In in6_newaddrmsg, announce arrival of local addresses on the
interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6
cache instead of a single cache.
sys/netinet6/in6_src.c
In in6_selectsrc, use the caller's fib instead of the default fib.
In in6_selectsrc_socket, remove a superfluous check.
sys/netinet6/nd6.c
In nd6_lle_event, use the interface's fib for routing socket
messages. In nd6_is_new_addr_neighbor, check all FIBs when trying
to determine whether an address is a neighbor. Also, simplify the
code for point to point interfaces.
sys/netinet6/nd6.h
sys/netinet6/nd6.c
sys/netinet6/nd6_rtr.c
Make defrouter_select fib-aware, and make all of its callers pass in
the interface fib.
sys/netinet6/nd6_nbr.c
When inputting a Neighbor Solicitation packet, consider the
interface fib instead of the default fib for DAD. Output NS and
Neighbor Advertisement packets on the correct fib.
sys/netinet6/nd6_rtr.c
Allow installing the same host route on different interfaces in
different FIBs. If rt_add_addr_allfibs=0, only install or delete
the prefix route on the interface fib.
tests/sys/netinet/fibs_test.sh
Clear some expected failures, but add a skip for the newly revealed
BUG217871.
PR: 196361
Submitted by: Erick Turnquist <jhujhiti@adjectivism.org>
Reported by: Jason Healy <jhealy@logn.net>
Reviewed by: asomers
MFC after: 3 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D9451
2017-03-17 16:50:37 +00:00
|
|
|
defrouter_select_fib(ifp->if_fib);
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
nd6_slowtimo(void *arg)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2019-01-09 01:11:19 +00:00
|
|
|
struct epoch_tracker et;
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
CURVNET_SET((struct vnet *) arg);
|
2001-06-11 12:39:29 +00:00
|
|
|
struct nd_ifinfo *nd6if;
|
2003-10-17 15:46:31 +00:00
|
|
|
struct ifnet *ifp;
|
1999-11-22 02:45:11 +00:00
|
|
|
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
|
Permit buiding kernels with options VIMAGE, restricted to only a single
active network stack instance. Turning on options VIMAGE at compile
time yields the following changes relative to default kernel build:
1) V_ accessor macros for virtualized variables resolve to structure
fields via base pointers, instead of being resolved as fields in global
structs or plain global variables. As an example, V_ifnet becomes:
options VIMAGE: ((struct vnet_net *) vnet_net)->_ifnet
default build: vnet_net_0._ifnet
options VIMAGE_GLOBALS: ifnet
2) INIT_VNET_* macros will declare and set up base pointers to be used
by V_ accessor macros, instead of resolving to whitespace:
INIT_VNET_NET(ifp->if_vnet); becomes
struct vnet_net *vnet_net = (ifp->if_vnet)->mod_data[VNET_MOD_NET];
3) Memory for vnet modules registered via vnet_mod_register() is now
allocated at run time in sys/kern/kern_vimage.c, instead of per vnet
module structs being declared as globals. If required, vnet modules
can now request the framework to provide them with allocated bzeroed
memory by filling in the vmi_size field in their vmi_modinfo structures.
4) structs socket, ifnet, inpcbinfo, tcpcb and syncache_head are
extended to hold a pointer to the parent vnet. options VIMAGE builds
will fill in those fields as required.
5) curvnet is introduced as a new global variable in options VIMAGE
builds, always pointing to the default and only struct vnet.
6) struct sysctl_oid has been extended with additional two fields to
store major and minor virtualization module identifiers, oid_v_subs and
oid_v_mod. SYSCTL_V_* family of macros will fill in those fields
accordingly, and store the offset in the appropriate vnet container
struct in oid_arg1.
In sysctl handlers dealing with virtualized sysctls, the
SYSCTL_RESOLVE_V_ARG1() macro will compute the address of the target
variable and make it available in arg1 variable for further processing.
Unused fields in structs vnet_inet, vnet_inet6 and vnet_ipfw have
been deleted.
Reviewed by: bz, rwatson
Approved by: julian (mentor)
2009-04-30 13:36:26 +00:00
|
|
|
nd6_slowtimo, curvnet);
|
2019-01-09 01:11:19 +00:00
|
|
|
NET_EPOCH_ENTER(et);
|
2018-05-23 21:02:14 +00:00
|
|
|
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
|
2013-07-31 16:24:49 +00:00
|
|
|
if (ifp->if_afdata[AF_INET6] == NULL)
|
|
|
|
continue;
|
2003-10-17 15:46:31 +00:00
|
|
|
nd6if = ND_IFINFO(ifp);
|
1999-11-22 02:45:11 +00:00
|
|
|
if (nd6if->basereachable && /* already initialized */
|
|
|
|
(nd6if->recalctm -= ND6_SLOWTIMER_INTERVAL) <= 0) {
|
|
|
|
/*
|
|
|
|
* Since reachable time rarely changes by router
|
|
|
|
* advertisements, we SHOULD insure that a new random
|
|
|
|
* value gets recomputed at least once every few hours.
|
|
|
|
* (RFC 2461, 6.3.4)
|
|
|
|
*/
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
nd6if->recalctm = V_nd6_recalc_reachtm_interval;
|
1999-11-22 02:45:11 +00:00
|
|
|
nd6if->reachable = ND_COMPUTE_RTIME(nd6if->basereachable);
|
|
|
|
}
|
|
|
|
}
|
2019-01-09 01:11:19 +00:00
|
|
|
NET_EPOCH_EXIT(et);
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
CURVNET_RESTORE();
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2021-08-02 23:16:48 +00:00
|
|
|
struct mbuf *
|
|
|
|
nd6_grab_holdchain(struct llentry *ln)
|
2015-01-08 18:02:05 +00:00
|
|
|
{
|
2021-08-02 23:16:48 +00:00
|
|
|
struct mbuf *chain;
|
2015-01-08 18:02:05 +00:00
|
|
|
|
|
|
|
LLE_WLOCK_ASSERT(ln);
|
|
|
|
|
2021-08-02 23:16:48 +00:00
|
|
|
chain = ln->la_hold;
|
2015-01-08 18:02:05 +00:00
|
|
|
ln->la_hold = NULL;
|
2022-05-31 20:04:51 +00:00
|
|
|
ln->la_numheld = 0;
|
2015-01-08 18:02:05 +00:00
|
|
|
|
|
|
|
if (ln->ln_state == ND6_LLINFO_STALE) {
|
|
|
|
/*
|
|
|
|
* The first time we send a packet to a
|
|
|
|
* neighbor whose entry is STALE, we have
|
|
|
|
* to change the state to DELAY and a sets
|
|
|
|
* a timer to expire in DELAY_FIRST_PROBE_TIME
|
|
|
|
* seconds to ensure do neighbor unreachability
|
|
|
|
* detection on expiration.
|
|
|
|
* (RFC 2461 7.3.3)
|
|
|
|
*/
|
2015-09-21 11:19:53 +00:00
|
|
|
nd6_llinfo_setstate(ln, ND6_LLINFO_DELAY);
|
2015-01-08 18:02:05 +00:00
|
|
|
}
|
2021-08-02 23:16:48 +00:00
|
|
|
|
|
|
|
return (chain);
|
2015-01-08 18:02:05 +00:00
|
|
|
}
|
|
|
|
|
2015-09-16 14:26:28 +00:00
|
|
|
int
|
2015-01-08 18:02:05 +00:00
|
|
|
nd6_output_ifp(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
|
2015-11-15 16:02:22 +00:00
|
|
|
struct sockaddr_in6 *dst, struct route *ro)
|
2015-01-08 18:02:05 +00:00
|
|
|
{
|
|
|
|
int error;
|
|
|
|
int ip6len;
|
|
|
|
struct ip6_hdr *ip6;
|
|
|
|
struct m_tag *mtag;
|
|
|
|
|
|
|
|
#ifdef MAC
|
|
|
|
mac_netinet6_nd6_send(ifp, m);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If called from nd6_ns_output() (NS), nd6_na_output() (NA),
|
|
|
|
* icmp6_redirect_output() (REDIRECT) or from rip6_output() (RS, RA
|
|
|
|
* as handled by rtsol and rtadvd), mbufs will be tagged for SeND
|
|
|
|
* to be diverted to user space. When re-injected into the kernel,
|
|
|
|
* send_output() will directly dispatch them to the outgoing interface.
|
|
|
|
*/
|
|
|
|
if (send_sendso_input_hook != NULL) {
|
|
|
|
mtag = m_tag_find(m, PACKET_TAG_ND_OUTGOING, NULL);
|
|
|
|
if (mtag != NULL) {
|
|
|
|
ip6 = mtod(m, struct ip6_hdr *);
|
|
|
|
ip6len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
|
|
|
|
/* Use the SEND socket */
|
|
|
|
error = send_sendso_input_hook(m, ifp, SND_OUT,
|
|
|
|
ip6len);
|
|
|
|
/* -1 == no app on SEND socket */
|
|
|
|
if (error == 0 || error != -1)
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_clrprotoflags(m); /* Avoid confusing lower layers. */
|
|
|
|
IP_PROBE(send, NULL, NULL, mtod(m, struct ip6_hdr *), ifp, NULL,
|
|
|
|
mtod(m, struct ip6_hdr *));
|
|
|
|
|
|
|
|
if ((ifp->if_flags & IFF_LOOPBACK) == 0)
|
|
|
|
origifp = ifp;
|
|
|
|
|
2015-11-15 16:02:22 +00:00
|
|
|
error = (*ifp->if_output)(origifp, m, (struct sockaddr *)dst, ro);
|
2015-01-08 18:02:05 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2014-02-13 19:09:04 +00:00
|
|
|
/*
|
2015-12-31 05:03:27 +00:00
|
|
|
* Lookup link headerfor @sa_dst address. Stores found
|
|
|
|
* data in @desten buffer. Copy of lle ln_flags can be also
|
2015-09-16 14:26:28 +00:00
|
|
|
* saved in @pflags if @pflags is non-NULL.
|
|
|
|
*
|
|
|
|
* If destination LLE does not exists or lle state modification
|
|
|
|
* is required, call "slow" version.
|
|
|
|
*
|
|
|
|
* Return values:
|
|
|
|
* - 0 on success (address copied to buffer).
|
|
|
|
* - EWOULDBLOCK (no local error, but address is still unresolved)
|
|
|
|
* - other errors (alloc failure, etc)
|
2014-02-13 19:09:04 +00:00
|
|
|
*/
|
1999-11-22 02:45:11 +00:00
|
|
|
int
|
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
|
|
|
nd6_resolve(struct ifnet *ifp, int gw_flags, struct mbuf *m,
|
2016-06-02 17:51:29 +00:00
|
|
|
const struct sockaddr *sa_dst, u_char *desten, uint32_t *pflags,
|
|
|
|
struct llentry **plle)
|
1999-11-22 02:45:11 +00:00
|
|
|
{
|
2014-02-13 19:09:04 +00:00
|
|
|
struct llentry *ln = NULL;
|
2015-09-16 14:26:28 +00:00
|
|
|
const struct sockaddr_in6 *dst6;
|
|
|
|
|
Widen NET_EPOCH coverage.
When epoch(9) was introduced to network stack, it was basically
dropped in place of existing locking, which was mutexes and
rwlocks. For the sake of performance mutex covered areas were
as small as possible, so became epoch covered areas.
However, epoch doesn't introduce any contention, it just delays
memory reclaim. So, there is no point to minimise epoch covered
areas in sense of performance. Meanwhile entering/exiting epoch
also has non-zero CPU usage, so doing this less often is a win.
Not the least is also code maintainability. In the new paradigm
we can assume that at any stage of processing a packet, we are
inside network epoch. This makes coding both input and output
path way easier.
On output path we already enter epoch quite early - in the
ip_output(), in the ip6_output().
This patch does the same for the input path. All ISR processing,
network related callouts, other ways of packet injection to the
network stack shall be performed in net_epoch. Any leaf function
that walks network configuration now asserts epoch.
Tricky part is configuration code paths - ioctls, sysctls. They
also call into leaf functions, so some need to be changed.
This patch would introduce more epoch recursions (see EPOCH_TRACE)
than we had before. They will be cleaned up separately, as several
of them aren't trivial. Note, that unlike a lock recursion the
epoch recursion is safe and just wastes a bit of resources.
Reviewed by: gallatin, hselasky, cy, adrian, kristof
Differential Revision: https://reviews.freebsd.org/D19111
2019-10-07 22:40:05 +00:00
|
|
|
NET_EPOCH_ASSERT();
|
|
|
|
|
2015-09-16 14:26:28 +00:00
|
|
|
if (pflags != NULL)
|
|
|
|
*pflags = 0;
|
|
|
|
|
|
|
|
dst6 = (const struct sockaddr_in6 *)sa_dst;
|
2014-02-13 19:09:04 +00:00
|
|
|
|
|
|
|
/* 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? */
|
|
|
|
}
|
|
|
|
|
2015-09-16 14:26:28 +00:00
|
|
|
if (m != NULL && m->m_flags & M_MCAST) {
|
|
|
|
switch (ifp->if_type) {
|
|
|
|
case IFT_ETHER:
|
|
|
|
case IFT_L2VLAN:
|
|
|
|
case IFT_BRIDGE:
|
|
|
|
ETHER_MAP_IPV6_MULTICAST(&dst6->sin6_addr,
|
|
|
|
desten);
|
|
|
|
return (0);
|
|
|
|
default:
|
|
|
|
m_freem(m);
|
|
|
|
return (EAFNOSUPPORT);
|
|
|
|
}
|
|
|
|
}
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +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
|
|
|
int family = gw_flags >> 16;
|
|
|
|
int lookup_flags = plle ? LLE_EXCLUSIVE : LLE_UNLOCKED;
|
|
|
|
ln = nd6_lookup(&dst6->sin6_addr, LLE_SF(family, lookup_flags), ifp);
|
2015-12-13 07:39:49 +00:00
|
|
|
if (ln != NULL && (ln->r_flags & RLLE_VALID) != 0) {
|
|
|
|
/* Entry found, let's copy lle info */
|
2015-12-31 05:03:27 +00:00
|
|
|
bcopy(ln->r_linkdata, desten, ln->r_hdrlen);
|
2015-12-13 07:39:49 +00:00
|
|
|
if (pflags != NULL)
|
|
|
|
*pflags = LLE_VALID | (ln->r_flags & RLLE_IFADDR);
|
2021-08-02 22:39:00 +00:00
|
|
|
llentry_provide_feedback(ln);
|
2016-07-22 02:11:49 +00:00
|
|
|
if (plle) {
|
|
|
|
LLE_ADDREF(ln);
|
|
|
|
*plle = ln;
|
|
|
|
LLE_WUNLOCK(ln);
|
|
|
|
}
|
2015-12-13 07:39:49 +00:00
|
|
|
return (0);
|
2016-07-22 02:11:49 +00:00
|
|
|
} else if (plle && ln)
|
|
|
|
LLE_WUNLOCK(ln);
|
2014-02-13 19:09:04 +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
|
|
|
return (nd6_resolve_slow(ifp, family, 0, m, dst6, desten, pflags, plle));
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
}
|
|
|
|
|
2021-08-06 08:27:22 +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
|
|
|
* Finds or creates a new llentry for @addr and @family.
|
2021-08-06 08:27:22 +00:00
|
|
|
* Returns wlocked llentry or NULL.
|
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
|
|
|
*
|
|
|
|
*
|
|
|
|
* Child LLEs.
|
|
|
|
*
|
|
|
|
* Do not have their own state machine (gets marked as static)
|
|
|
|
* settimer bails out for child LLEs just in case.
|
|
|
|
*
|
|
|
|
* Locking order: parent lle gets locked first, chen goes the child.
|
2021-08-06 08:27:22 +00:00
|
|
|
*/
|
|
|
|
static __noinline struct llentry *
|
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
|
|
|
nd6_get_llentry(struct ifnet *ifp, const struct in6_addr *addr, int family)
|
2021-08-06 08:27:22 +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 *child_lle = NULL;
|
2021-08-06 08:27:22 +00:00
|
|
|
struct llentry *lle, *lle_tmp;
|
|
|
|
|
|
|
|
lle = nd6_alloc(addr, 0, ifp);
|
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
|
|
|
if (lle != NULL && family != AF_INET6) {
|
|
|
|
child_lle = nd6_alloc(addr, 0, ifp);
|
|
|
|
if (child_lle == NULL) {
|
|
|
|
lltable_free_entry(LLTABLE6(ifp), lle);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
child_lle->r_family = family;
|
|
|
|
child_lle->la_flags |= LLE_CHILD | LLE_STATIC;
|
|
|
|
child_lle->ln_state = ND6_LLINFO_INCOMPLETE;
|
|
|
|
}
|
|
|
|
|
2021-08-06 08:27:22 +00:00
|
|
|
if (lle == NULL) {
|
|
|
|
char ip6buf[INET6_ADDRSTRLEN];
|
|
|
|
log(LOG_DEBUG,
|
|
|
|
"nd6_get_llentry: can't allocate llinfo for %s "
|
|
|
|
"(ln=%p)\n",
|
|
|
|
ip6_sprintf(ip6buf, addr), lle);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
IF_AFDATA_WLOCK(ifp);
|
|
|
|
LLE_WLOCK(lle);
|
|
|
|
/* Prefer any existing entry over newly-created one */
|
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
|
|
|
lle_tmp = nd6_lookup(addr, LLE_SF(AF_INET6, LLE_EXCLUSIVE), ifp);
|
2021-08-06 08:27:22 +00:00
|
|
|
if (lle_tmp == NULL)
|
|
|
|
lltable_link_entry(LLTABLE6(ifp), 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
|
|
|
else {
|
2021-08-06 08:27:22 +00:00
|
|
|
lltable_free_entry(LLTABLE6(ifp), 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
|
|
|
lle = lle_tmp;
|
|
|
|
}
|
|
|
|
if (child_lle != NULL) {
|
|
|
|
/* Check if child lle for the same family exists */
|
|
|
|
lle_tmp = llentry_lookup_family(lle, child_lle->r_family);
|
|
|
|
LLE_WLOCK(child_lle);
|
|
|
|
if (lle_tmp == NULL) {
|
|
|
|
/* Attach */
|
|
|
|
lltable_link_child_entry(lle, child_lle);
|
|
|
|
} else {
|
|
|
|
/* child lle already exists, free newly-created one */
|
|
|
|
lltable_free_entry(LLTABLE6(ifp), child_lle);
|
|
|
|
child_lle = lle_tmp;
|
|
|
|
}
|
|
|
|
LLE_WUNLOCK(lle);
|
|
|
|
lle = child_lle;
|
|
|
|
}
|
|
|
|
IF_AFDATA_WUNLOCK(ifp);
|
|
|
|
return (lle);
|
2021-08-06 08:27:22 +00:00
|
|
|
}
|
|
|
|
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
/*
|
2015-09-16 14:26:28 +00:00
|
|
|
* Do L2 address resolution for @sa_dst address. Stores found
|
|
|
|
* address in @desten buffer. Copy of lle ln_flags can be also
|
|
|
|
* saved in @pflags if @pflags is non-NULL.
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
*
|
2015-09-16 14:26:28 +00:00
|
|
|
* Heavy version.
|
|
|
|
* Function assume that destination LLE does not exist,
|
2015-09-22 20:45:04 +00:00
|
|
|
* is invalid or stale, so LLE_EXCLUSIVE lock needs to be acquired.
|
2015-10-04 08:21:15 +00:00
|
|
|
*
|
|
|
|
* Set noinline to be dtrace-friendly
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
*/
|
2015-10-04 08:21:15 +00:00
|
|
|
static __noinline int
|
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
|
|
|
nd6_resolve_slow(struct ifnet *ifp, int family, int flags, struct mbuf *m,
|
2016-06-02 17:51:29 +00:00
|
|
|
const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags,
|
|
|
|
struct llentry **plle)
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
{
|
2021-08-06 08:27:22 +00:00
|
|
|
struct llentry *lle = NULL;
|
2015-09-21 11:19:53 +00:00
|
|
|
struct in6_addr *psrc, src;
|
2015-12-31 05:03:27 +00:00
|
|
|
int send_ns, ll_len;
|
|
|
|
char *lladdr;
|
2022-05-31 20:04:51 +00:00
|
|
|
size_t dropped;
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
|
Widen NET_EPOCH coverage.
When epoch(9) was introduced to network stack, it was basically
dropped in place of existing locking, which was mutexes and
rwlocks. For the sake of performance mutex covered areas were
as small as possible, so became epoch covered areas.
However, epoch doesn't introduce any contention, it just delays
memory reclaim. So, there is no point to minimise epoch covered
areas in sense of performance. Meanwhile entering/exiting epoch
also has non-zero CPU usage, so doing this less often is a win.
Not the least is also code maintainability. In the new paradigm
we can assume that at any stage of processing a packet, we are
inside network epoch. This makes coding both input and output
path way easier.
On output path we already enter epoch quite early - in the
ip_output(), in the ip6_output().
This patch does the same for the input path. All ISR processing,
network related callouts, other ways of packet injection to the
network stack shall be performed in net_epoch. Any leaf function
that walks network configuration now asserts epoch.
Tricky part is configuration code paths - ioctls, sysctls. They
also call into leaf functions, so some need to be changed.
This patch would introduce more epoch recursions (see EPOCH_TRACE)
than we had before. They will be cleaned up separately, as several
of them aren't trivial. Note, that unlike a lock recursion the
epoch recursion is safe and just wastes a bit of resources.
Reviewed by: gallatin, hselasky, cy, adrian, kristof
Differential Revision: https://reviews.freebsd.org/D19111
2019-10-07 22:40:05 +00:00
|
|
|
NET_EPOCH_ASSERT();
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* Address resolution or Neighbor Unreachability Detection
|
|
|
|
* for the next hop.
|
|
|
|
* At this point, the destination of the packet must be a unicast
|
|
|
|
* or an anycast address(i.e. not a multicast).
|
|
|
|
*/
|
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
|
|
|
lle = nd6_lookup(&dst->sin6_addr, LLE_SF(family, LLE_EXCLUSIVE), ifp);
|
2021-08-06 08:27:22 +00:00
|
|
|
if ((lle == 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.
|
|
|
|
*/
|
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
|
|
|
lle = nd6_get_llentry(ifp, &dst->sin6_addr, family);
|
2021-08-06 08:27:22 +00:00
|
|
|
}
|
2015-08-20 12:05:17 +00:00
|
|
|
|
2014-02-13 19:09:04 +00:00
|
|
|
if (lle == NULL) {
|
2019-11-15 13:45:38 +00:00
|
|
|
m_freem(m);
|
2015-09-16 14:26:28 +00:00
|
|
|
return (ENOBUFS);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
|
|
|
|
2014-02-13 19:09:04 +00:00
|
|
|
LLE_WLOCK_ASSERT(lle);
|
|
|
|
|
1999-11-22 02:45:11 +00:00
|
|
|
/*
|
|
|
|
* The first time we send a packet to a neighbor whose entry is
|
|
|
|
* STALE, we have to change the state to DELAY and a sets a timer to
|
|
|
|
* expire in DELAY_FIRST_PROBE_TIME seconds to ensure do
|
|
|
|
* neighbor unreachability detection on expiration.
|
|
|
|
* (RFC 2461 7.3.3)
|
|
|
|
*/
|
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
|
|
|
if ((!(lle->la_flags & LLE_CHILD)) && (lle->ln_state == ND6_LLINFO_STALE))
|
2015-09-21 11:19:53 +00:00
|
|
|
nd6_llinfo_setstate(lle, ND6_LLINFO_DELAY);
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the neighbor cache entry has a state other than INCOMPLETE
|
2002-04-19 04:46:24 +00:00
|
|
|
* (i.e. its link-layer address is already resolved), just
|
1999-11-22 02:45:11 +00:00
|
|
|
* send the packet.
|
|
|
|
*/
|
2015-09-16 14:26:28 +00:00
|
|
|
if (lle->ln_state > ND6_LLINFO_INCOMPLETE) {
|
2015-12-31 05:03:27 +00:00
|
|
|
if (flags & LLE_ADDRONLY) {
|
|
|
|
lladdr = lle->ll_addr;
|
|
|
|
ll_len = ifp->if_addrlen;
|
|
|
|
} else {
|
|
|
|
lladdr = lle->r_linkdata;
|
|
|
|
ll_len = lle->r_hdrlen;
|
|
|
|
}
|
|
|
|
bcopy(lladdr, desten, ll_len);
|
2015-09-16 14:26:28 +00:00
|
|
|
if (pflags != NULL)
|
|
|
|
*pflags = lle->la_flags;
|
2016-06-02 17:51:29 +00:00
|
|
|
if (plle) {
|
|
|
|
LLE_ADDREF(lle);
|
|
|
|
*plle = lle;
|
|
|
|
}
|
2015-09-16 14:26:28 +00:00
|
|
|
LLE_WUNLOCK(lle);
|
|
|
|
return (0);
|
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* There is a neighbor cache entry, but no ethernet address
|
2005-10-21 16:23:01 +00:00
|
|
|
* response yet. Append this latest packet to the end of the
|
2016-04-25 23:12:39 +00:00
|
|
|
* packet queue in the mbuf. When it exceeds nd6_maxqueuelen,
|
2005-10-21 16:23:01 +00:00
|
|
|
* the oldest packet in the queue will be removed.
|
1999-11-22 02:45:11 +00:00
|
|
|
*/
|
2022-05-31 20:04:51 +00:00
|
|
|
dropped = lltable_append_entry_queue(lle, m, V_nd6_maxqueuelen);
|
|
|
|
ICMP6STAT_ADD(icp6s_dropped, dropped);
|
2010-11-29 00:04:08 +00:00
|
|
|
|
2005-10-21 16:23:01 +00:00
|
|
|
/*
|
|
|
|
* If there has been no NS for the neighbor after entering the
|
|
|
|
* INCOMPLETE state, send the first solicitation.
|
2015-09-21 11:19:53 +00:00
|
|
|
* Note that for newly-created lle la_asked will be 0,
|
|
|
|
* so we will transition from ND6_LLINFO_NOSTATE to
|
|
|
|
* ND6_LLINFO_INCOMPLETE state here.
|
2005-10-21 16:23:01 +00:00
|
|
|
*/
|
2015-09-21 11:19:53 +00:00
|
|
|
psrc = NULL;
|
|
|
|
send_ns = 0;
|
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
|
|
|
|
|
|
|
/* If we have child lle, switch to the parent to send NS */
|
|
|
|
if (lle->la_flags & LLE_CHILD) {
|
|
|
|
struct llentry *lle_parent = lle->lle_parent;
|
|
|
|
LLE_WUNLOCK(lle);
|
|
|
|
lle = lle_parent;
|
|
|
|
LLE_WLOCK(lle);
|
|
|
|
}
|
2015-09-21 11:19:53 +00:00
|
|
|
if (lle->la_asked == 0) {
|
2014-02-13 19:09:04 +00:00
|
|
|
lle->la_asked++;
|
2015-09-21 11:19:53 +00:00
|
|
|
send_ns = 1;
|
2015-09-05 14:14:03 +00:00
|
|
|
psrc = nd6_llinfo_get_holdsrc(lle, &src);
|
2015-09-21 11:19:53 +00:00
|
|
|
|
|
|
|
nd6_llinfo_setstate(lle, ND6_LLINFO_INCOMPLETE);
|
1999-11-22 02:45:11 +00:00
|
|
|
}
|
2015-09-21 11:19:53 +00:00
|
|
|
LLE_WUNLOCK(lle);
|
|
|
|
if (send_ns != 0)
|
|
|
|
nd6_ns_output(ifp, psrc, NULL, &dst->sin6_addr, NULL);
|
2010-11-29 00:04:08 +00:00
|
|
|
|
2015-09-16 14:26:28 +00:00
|
|
|
return (EWOULDBLOCK);
|
2003-10-09 16:13:47 +00:00
|
|
|
}
|
1999-11-22 02:45:11 +00:00
|
|
|
|
2015-12-31 05:03:27 +00:00
|
|
|
/*
|
|
|
|
* Do L2 address resolution for @sa_dst address. Stores found
|
|
|
|
* address in @desten buffer. Copy of lle ln_flags can be also
|
|
|
|
* saved in @pflags if @pflags is non-NULL.
|
|
|
|
*
|
|
|
|
* Return values:
|
|
|
|
* - 0 on success (address copied to buffer).
|
|
|
|
* - EWOULDBLOCK (no local error, but address is still unresolved)
|
|
|
|
* - other errors (alloc failure, etc)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
nd6_resolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst,
|
|
|
|
char *desten, uint32_t *pflags)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
|
|
|
flags |= LLE_ADDRONLY;
|
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
|
|
|
error = nd6_resolve_slow(ifp, AF_INET6, flags, NULL,
|
2016-06-02 17:51:29 +00:00
|
|
|
(const struct sockaddr_in6 *)dst, desten, pflags, NULL);
|
2015-12-31 05:03:27 +00:00
|
|
|
return (error);
|
|
|
|
}
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
|
|
|
|
int
|
2021-08-02 23:16:48 +00:00
|
|
|
nd6_flush_holdchain(struct ifnet *ifp, struct llentry *lle, struct mbuf *chain)
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
{
|
|
|
|
struct mbuf *m, *m_head;
|
2021-08-02 23:16:48 +00:00
|
|
|
struct sockaddr_in6 dst6;
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
int error = 0;
|
|
|
|
|
2021-08-02 23:16:48 +00:00
|
|
|
NET_EPOCH_ASSERT();
|
|
|
|
|
|
|
|
struct route_in6 ro = {
|
|
|
|
.ro_prepend = lle->r_linkdata,
|
|
|
|
.ro_plen = lle->r_hdrlen,
|
|
|
|
};
|
|
|
|
|
|
|
|
lltable_fill_sa_entry(lle, (struct sockaddr *)&dst6);
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
m_head = chain;
|
2017-12-25 04:48:39 +00:00
|
|
|
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
while (m_head) {
|
|
|
|
m = m_head;
|
|
|
|
m_head = m_head->m_nextpkt;
|
2021-01-27 18:32:52 +00:00
|
|
|
m->m_nextpkt = NULL;
|
2021-08-02 23:16:48 +00:00
|
|
|
error = nd6_output_ifp(ifp, ifp, m, &dst6, (struct route *)&ro);
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX
|
2015-09-16 14:26:28 +00:00
|
|
|
* note that intermediate errors are blindly ignored
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +00:00
|
|
|
*/
|
|
|
|
return (error);
|
2017-12-25 04:48:39 +00:00
|
|
|
}
|
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables
2. removing as much locking dependencies among these layers as
possible to allow for some parallelism in the search operations
3. simplify the logic in the routing code,
The most notable end result is the obsolescent of the route
cloning (RTF_CLONING) concept, which translated into code reduction
in both IPv4 ARP and IPv6 NDP related modules, and size reduction in
struct rtentry{}. The change in design obsoletes the semantics of
RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland
applications such as "arp" and "ndp" have been modified to reflect
those changes. The output from "netstat -r" shows only the routing
entries.
Quite a few developers have contributed to this project in the
past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and
Andre Oppermann. And most recently:
- Kip Macy revised the locking code completely, thus completing
the last piece of the puzzle, Kip has also been conducting
active functional testing
- Sam Leffler has helped me improving/refactoring the code, and
provided valuable reviews
- Julian Elischer setup the perforce tree for me and has helped
me maintaining that branch before the svn conversion
2008-12-15 06:10:57 +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
|
|
|
__noinline void
|
|
|
|
nd6_flush_children_holdchain(struct ifnet *ifp, struct llentry *lle)
|
|
|
|
{
|
|
|
|
struct llentry *child_lle;
|
|
|
|
struct mbuf *chain;
|
|
|
|
|
|
|
|
NET_EPOCH_ASSERT();
|
|
|
|
|
|
|
|
CK_SLIST_FOREACH(child_lle, &lle->lle_children, lle_child_next) {
|
|
|
|
LLE_WLOCK(child_lle);
|
|
|
|
chain = nd6_grab_holdchain(child_lle);
|
|
|
|
LLE_WUNLOCK(child_lle);
|
|
|
|
nd6_flush_holdchain(ifp, child_lle, chain);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-16 14:26:28 +00:00
|
|
|
static int
|
2007-07-05 16:23:49 +00:00
|
|
|
nd6_need_cache(struct ifnet *ifp)
|
2001-06-11 12:39:29 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* XXX: we currently do not make neighbor cache on any interface
|
2018-04-13 21:18:04 +00:00
|
|
|
* other than Ethernet and GIF.
|
2001-06-11 12:39:29 +00:00
|
|
|
*
|
|
|
|
* RFC2893 says:
|
|
|
|
* - unidirectional tunnels needs no ND
|
|
|
|
*/
|
|
|
|
switch (ifp->if_type) {
|
|
|
|
case IFT_ETHER:
|
|
|
|
case IFT_IEEE1394:
|
2001-06-19 14:48:02 +00:00
|
|
|
case IFT_L2VLAN:
|
2011-03-21 09:40:01 +00:00
|
|
|
case IFT_INFINIBAND:
|
2005-09-06 21:11:59 +00:00
|
|
|
case IFT_BRIDGE:
|
2007-02-03 09:34:36 +00:00
|
|
|
case IFT_PROPVIRTUAL:
|
2003-10-06 14:02:09 +00:00
|
|
|
return (1);
|
2001-06-11 12:39:29 +00:00
|
|
|
default:
|
2003-10-06 14:02:09 +00:00
|
|
|
return (0);
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-19 16:07:27 +00:00
|
|
|
/*
|
|
|
|
* Add pernament ND6 link-layer record for given
|
|
|
|
* interface address.
|
|
|
|
*
|
|
|
|
* Very similar to IPv4 arp_ifinit(), but:
|
|
|
|
* 1) IPv6 DAD is performed in different place
|
|
|
|
* 2) It is called by IPv6 protocol stack in contrast to
|
|
|
|
* arp_ifinit() which is typically called in SIOCSIFADDR
|
|
|
|
* driver ioctl handler.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
nd6_add_ifa_lle(struct in6_ifaddr *ia)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp;
|
2015-08-20 12:05:17 +00:00
|
|
|
struct llentry *ln, *ln_tmp;
|
|
|
|
struct sockaddr *dst;
|
2014-01-19 16:07:27 +00:00
|
|
|
|
|
|
|
ifp = ia->ia_ifa.ifa_ifp;
|
2014-11-24 21:51:43 +00:00
|
|
|
if (nd6_need_cache(ifp) == 0)
|
|
|
|
return (0);
|
2015-08-20 12:05:17 +00:00
|
|
|
|
|
|
|
dst = (struct sockaddr *)&ia->ia_addr;
|
|
|
|
ln = lltable_alloc_entry(LLTABLE6(ifp), LLE_IFADDR, dst);
|
|
|
|
if (ln == NULL)
|
|
|
|
return (ENOBUFS);
|
2014-01-19 16:07:27 +00:00
|
|
|
|
2015-08-20 12:05:17 +00:00
|
|
|
IF_AFDATA_WLOCK(ifp);
|
|
|
|
LLE_WLOCK(ln);
|
|
|
|
/* Unlink any entry if exists */
|
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
|
|
|
ln_tmp = lla_lookup(LLTABLE6(ifp), LLE_SF(AF_INET6, LLE_EXCLUSIVE), dst);
|
2015-08-20 12:05:17 +00:00
|
|
|
if (ln_tmp != NULL)
|
|
|
|
lltable_unlink_entry(LLTABLE6(ifp), ln_tmp);
|
|
|
|
lltable_link_entry(LLTABLE6(ifp), ln);
|
|
|
|
IF_AFDATA_WUNLOCK(ifp);
|
|
|
|
|
|
|
|
if (ln_tmp != NULL)
|
|
|
|
EVENTHANDLER_INVOKE(lle_event, ln_tmp, LLENTRY_EXPIRED);
|
|
|
|
EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
|
|
|
|
|
|
|
|
LLE_WUNLOCK(ln);
|
|
|
|
if (ln_tmp != NULL)
|
|
|
|
llentry_free(ln_tmp);
|
|
|
|
|
|
|
|
return (0);
|
2014-01-19 16:07:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2015-09-14 16:48:19 +00:00
|
|
|
* Removes either all lle entries for given @ia, or lle
|
|
|
|
* corresponding to @ia address.
|
2014-01-19 16:07:27 +00:00
|
|
|
*/
|
|
|
|
void
|
2015-09-14 16:48:19 +00:00
|
|
|
nd6_rem_ifa_lle(struct in6_ifaddr *ia, int all)
|
2014-01-19 16:07:27 +00:00
|
|
|
{
|
|
|
|
struct sockaddr_in6 mask, addr;
|
2015-09-14 16:48:19 +00:00
|
|
|
struct sockaddr *saddr, *smask;
|
2014-01-19 16:07:27 +00:00
|
|
|
struct ifnet *ifp;
|
|
|
|
|
|
|
|
ifp = ia->ia_ifa.ifa_ifp;
|
|
|
|
memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
|
|
|
|
memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
|
2015-09-14 16:48:19 +00:00
|
|
|
saddr = (struct sockaddr *)&addr;
|
|
|
|
smask = (struct sockaddr *)&mask;
|
|
|
|
|
|
|
|
if (all != 0)
|
|
|
|
lltable_prefix_free(AF_INET6, saddr, smask, LLE_STATIC);
|
|
|
|
else
|
|
|
|
lltable_delete_addr(LLTABLE6(ifp), LLE_IFADDR, saddr);
|
2014-01-19 16:07:27 +00:00
|
|
|
}
|
|
|
|
|
2001-06-11 12:39:29 +00:00
|
|
|
static int
|
|
|
|
nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS)
|
|
|
|
{
|
2012-05-20 05:12:31 +00:00
|
|
|
struct in6_prefix p;
|
|
|
|
struct sockaddr_in6 s6;
|
2001-06-11 12:39:29 +00:00
|
|
|
struct nd_prefix *pr;
|
2012-05-20 05:12:31 +00:00
|
|
|
struct nd_pfxrouter *pfr;
|
|
|
|
time_t maxexpire;
|
|
|
|
int error;
|
2006-12-12 12:17:58 +00:00
|
|
|
char ip6buf[INET6_ADDRSTRLEN];
|
2001-06-11 12:39:29 +00:00
|
|
|
|
|
|
|
if (req->newptr)
|
2012-05-20 05:12:31 +00:00
|
|
|
return (EPERM);
|
2001-06-11 12:39:29 +00:00
|
|
|
|
2016-05-23 20:15:08 +00:00
|
|
|
error = sysctl_wire_old_buffer(req, 0);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
|
2012-05-20 05:12:31 +00:00
|
|
|
bzero(&p, sizeof(p));
|
|
|
|
p.origin = PR_ORIG_RA;
|
|
|
|
bzero(&s6, sizeof(s6));
|
|
|
|
s6.sin6_family = AF_INET6;
|
|
|
|
s6.sin6_len = sizeof(s6);
|
2001-06-11 12:39:29 +00:00
|
|
|
|
2016-05-23 20:15:08 +00:00
|
|
|
ND6_RLOCK();
|
2012-05-20 05:12:31 +00:00
|
|
|
LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
|
2022-08-23 16:19:50 +00:00
|
|
|
if (!pr->ndpr_raf_ra_derived)
|
|
|
|
continue;
|
2012-05-20 05:12:31 +00:00
|
|
|
p.prefix = pr->ndpr_prefix;
|
|
|
|
if (sa6_recoverscope(&p.prefix)) {
|
|
|
|
log(LOG_ERR, "scope error in prefix list (%s)\n",
|
|
|
|
ip6_sprintf(ip6buf, &p.prefix.sin6_addr));
|
|
|
|
/* XXX: press on... */
|
|
|
|
}
|
|
|
|
p.raflags = pr->ndpr_raf;
|
|
|
|
p.prefixlen = pr->ndpr_plen;
|
|
|
|
p.vltime = pr->ndpr_vltime;
|
|
|
|
p.pltime = pr->ndpr_pltime;
|
|
|
|
p.if_index = pr->ndpr_ifp->if_index;
|
|
|
|
if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME)
|
|
|
|
p.expire = 0;
|
|
|
|
else {
|
|
|
|
/* XXX: we assume time_t is signed. */
|
|
|
|
maxexpire = (-1) &
|
|
|
|
~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
|
|
|
|
if (pr->ndpr_vltime < maxexpire - pr->ndpr_lastupdate)
|
|
|
|
p.expire = pr->ndpr_lastupdate +
|
2013-08-06 17:10:52 +00:00
|
|
|
pr->ndpr_vltime +
|
|
|
|
(time_second - time_uptime);
|
2012-05-20 05:12:31 +00:00
|
|
|
else
|
|
|
|
p.expire = maxexpire;
|
|
|
|
}
|
2016-09-24 01:14:25 +00:00
|
|
|
p.refcnt = pr->ndpr_addrcnt;
|
2012-05-20 05:12:31 +00:00
|
|
|
p.flags = pr->ndpr_stateflags;
|
|
|
|
p.advrtrs = 0;
|
|
|
|
LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry)
|
|
|
|
p.advrtrs++;
|
|
|
|
error = SYSCTL_OUT(req, &p, sizeof(p));
|
|
|
|
if (error != 0)
|
2016-05-23 20:15:08 +00:00
|
|
|
break;
|
2012-05-20 05:12:31 +00:00
|
|
|
LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) {
|
|
|
|
s6.sin6_addr = pfr->router->rtaddr;
|
|
|
|
if (sa6_recoverscope(&s6))
|
2001-06-11 12:39:29 +00:00
|
|
|
log(LOG_ERR,
|
|
|
|
"scope error in prefix list (%s)\n",
|
2012-05-20 05:12:31 +00:00
|
|
|
ip6_sprintf(ip6buf, &pfr->router->rtaddr));
|
|
|
|
error = SYSCTL_OUT(req, &s6, sizeof(s6));
|
|
|
|
if (error != 0)
|
2016-10-07 21:10:53 +00:00
|
|
|
goto out;
|
2012-05-20 05:12:31 +00:00
|
|
|
}
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
2016-10-07 21:10:53 +00:00
|
|
|
out:
|
2016-05-23 20:15:08 +00:00
|
|
|
ND6_RUNLOCK();
|
|
|
|
return (error);
|
2001-06-11 12:39:29 +00:00
|
|
|
}
|
2019-11-19 21:08:18 +00:00
|
|
|
SYSCTL_PROC(_net_inet6_icmp6, ICMPV6CTL_ND6_PRLIST, nd6_prlist,
|
|
|
|
CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
|
|
|
NULL, 0, nd6_sysctl_prlist, "S,in6_prefix",
|
|
|
|
"NDP prefix list");
|
|
|
|
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXQLEN, nd6_maxqueuelen,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_maxqueuelen), 1, "");
|
|
|
|
SYSCTL_INT(_net_inet6_icmp6, OID_AUTO, nd6_gctimer,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_gctimer), (60 * 60 * 24), "");
|