Some context on the current IPv6 interface setup & address management:
There are two data path for IPv6 initialisation in context of assigning
LL addresses:
1) Userland explicitly requests IFF_UP for the interface w/o any addresses.
if_up() then calls in6_if_up(), which calls in6_ifattach().
The latter sets up some initial ND/IN6 state and disables IPv6 for the
interface if it’s not loopback. If the interface is loopback, then it
adds ::1/128 and LL addresses via in6_ifattach_loopback().
Then, devd notification is generated (if the VNET is the default one),
which triggers rc.network ifconfig_up(), causing ifdisabled to be removed
via SIOCSIFINFO_IN6 from ifconfig. The kernel SIOCSIFINFO_IN6 handler
calls in6_if_up() once again and it assigns the interface link-local address.
2) Userland adds IPv4 or IPv6 address to the interface. SIOCAIFADDR[_IN6]
kernel handler calls IPv4/IPv6 protocol handler to add the address.
Both then call if_ioctl() with SIOCSIFADDR. Ethernet/loopback ioctl handlers
silently sets IFF_UP for the interface. Finally, if.c:ifioctl() wrapper code
compares old and new interface flags and, if IFF_UP is added, it explicitly
calls in6_if_up(), which adds link-local address if either the original
address is IPv6 or the interface is loopback.
In the latter case, “formal” interface-up notifications are missing.
The kernel does not trigger event handler event, does not call carp hook
and does not provide any userland notification.
This diff unifies the event handling in both scenarios, providing the
necessary notifications to the kernel and userland.
Reviewed By: kp
Differential Revision: https://reviews.freebsd.org/D40332
MFC after: 2 weeks
b0e38a1373 improved if_bridge's ability to cope with different VLANs,
but it failed to update bridge_transmit() to cope with the new rule that
untagged packets are treated as having VLAN ID 0 (rather than 1, as used
to be the case).
Fix that oversight.
PR: 270559
Reviewed by: kp
tap(4) devices advertise themselves as just 'ethernet autoselect',
without duplex or speed capabilities.
This advertisement makes them unable to be aggregated into lacp-based
lagg(4):
- lacp code requires underlying interfaces to be full-duplex, else
interface will not participate in lacp at all
- lacp code requires underlying interface to have non-zero speed, else
this interface can not be selected as active aggregator
PR: 217374
Reported-by: Alexandre Snarskii <snar@snar.spb.ru>
Co-authored-by: Mina Galić <freebsd@igalic.co>
Reviewed-by: imp,karles
Pull-request: https://github.com/freebsd/freebsd-src/pull/745
Make struct pfsync_state contents configurable by sending out new
versions of the structure in separate subheader actions. Both old and
new version of struct pfsync_state can be understood, so replication of
states from a system running an older kernel is possible. The version
being sent out is configured using ifconfig pfsync0 … version XXXX. The
version is an user-friendly string - 1301 stands for FreeBSD 13.1 (I
have checked synchronization against a host running 13.1), 1400 stands
for 14.0.
A host running an older kernel will just ignore the messages and count
them as "packets discarded for bad action".
Reviewed by: kp
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D39392
- Fixes netgdb's double ack
- Moving ack responsibility to debugnet, decision to ack made by netdump/netgdb.
- Finish responsibility moved to debugnet, new finish handler.
- netgdb now prints the address to connect to in case the user doesn't have
access to the proxy machine.
Sponsored by: Dell EMC
Reviewed By: markj, bdrewery (earlier version)
Differential Revision: https://reviews.freebsd.org/D40064
The intent is to set the value to UINT32_MAX, not to |= UINT32_MAX.
Happily the intent (ensure that we do not send further packets) is
achieved either way.
Reported by: markj
Sponsored by: Rubicon Communications, LLC ("Netgate")
if_ovpn already notified userpsace when there was a risk of sequence
number re-use, but it trusted userspace to actually rotate the key.
Convert the internal sequence number counter to 64 bits so we can detect
overflows and then refuse to send packets.
Event: BSDCan 2023
Reviewed by: Leon Dang <ldang@netgate.com>
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D40187
When a new bridge_rtnode is added it is added with a NULL brt_dst. The
brt_dst is set after the entry is added. This means there's a small
window where another core could also attempt to add this node, leading
to the code attempting to log that the MAC addresses moved to a new
interface.
Aside from that being a spurious log entry it also panics, because
obif is NULL (and we attempt to dereference it).
Avoid this by settings brt_dst before we insert the bridge_rtnode.
Assert that obif is non-NULL, as an extra precaution.
Reported by: olivier@
Reviewed by: zlei@
Differential Revision: https://reviews.freebsd.org/D40147
Prepare for rtableid being included in struct pfsync_state where it will
be int32_t. Make variables which will be set to and from it the same
width.
Reviewed by: kp
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D40013
Nexthop groups can be referenced by the external code. The reference
can be released after the VNET destruction. Furthermore, nexthop
groups use a single per-rib lock, which is destroyed during the
VNET desctruction. To eliminate use-after-free problem, each nhg
is marked as "unlinked" during the VNET destruction stage, leaving
nhg_idx intact. Normally there should not be such nexthops, but if
there are any, the kernel will panic on 'gr_idx != 0' when the
last nhg reference is released.
Address this by using the assert checks only when the nexthop group
is destroyed during "valid" VNET lifetime.
MFC after: 3 days
State deletions are sent over pfsync using struct pfsync_del_c.
Remove the code for receiving state deletions using struct pfsync_state
as such deletions are never sent. Rename functions and constants so that
only the "compressed" versions remain.
Reviewed by: kp
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D40004
The SPDX folks have obsoleted the BSD-2-Clause-NetBSD identifier. Catch
up to that fact and revert to their recommended match of BSD-2-Clause.
Discussed with: pfg
MFC After: 3 days
Sponsored by: Netflix
The SPDX folks have obsoleted the BSD-2-Clause-FreeBSD identifier. Catch
up to that fact and revert to their recommended match of BSD-2-Clause.
Discussed with: pfg
MFC After: 3 days
Sponsored by: Netflix
Setting vlan flags needlessly takes the exclusive VLAN_XLOCK().
If we have stacked vlan devices (i.e. QinQ) and we set vlan flags (e.g.
IFF_PROMISC) we call rtnl_handle_ifevent() to send a notification about
the interface.
This ends up calling SIOCGIFMEDIA, which requires the VLAN_SLOCK().
Trying to take that one with the VLAN_XLOCK() held deadlocks us.
There's no need for the exclusive lock though, as we're only accessing
parent/trunk information, not modifying it, so a shared lock is
sufficient.
While here also add a test case for this issue.
Backtrace:
shared lock of (sx) vlan_sx @ /usr/src/sys/net/if_vlan.c:2192
while exclusively locked from /usr/src/sys/net/if_vlan.c:2307
panic: excl->share
cpuid = 29
time = 1683873033
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe015d4ad4b0
vpanic() at vpanic+0x152/frame 0xfffffe015d4ad500
panic() at panic+0x43/frame 0xfffffe015d4ad560
witness_checkorder() at witness_checkorder+0xcb5/frame 0xfffffe015d4ad720
_sx_slock_int() at _sx_slock_int+0x67/frame 0xfffffe015d4ad760
vlan_ioctl() at vlan_ioctl+0xf8/frame 0xfffffe015d4ad7c0
dump_iface() at dump_iface+0x12f/frame 0xfffffe015d4ad840
rtnl_handle_ifevent() at rtnl_handle_ifevent+0xab/frame 0xfffffe015d4ad8c0
if_setflag() at if_setflag+0xf6/frame 0xfffffe015d4ad930
ifpromisc() at ifpromisc+0x2a/frame 0xfffffe015d4ad960
vlan_setflags() at vlan_setflags+0x60/frame 0xfffffe015d4ad990
vlan_ioctl() at vlan_ioctl+0x216/frame 0xfffffe015d4ad9f0
if_setflag() at if_setflag+0xe4/frame 0xfffffe015d4ada60
ifpromisc() at ifpromisc+0x2a/frame 0xfffffe015d4ada90
bridge_ioctl_add() at bridge_ioctl_add+0x499/frame 0xfffffe015d4adb10
bridge_ioctl() at bridge_ioctl+0x328/frame 0xfffffe015d4adbc0
ifioctl() at ifioctl+0x972/frame 0xfffffe015d4adcc0
kern_ioctl() at kern_ioctl+0x1fe/frame 0xfffffe015d4add30
sys_ioctl() at sys_ioctl+0x154/frame 0xfffffe015d4ade00
amd64_syscall() at amd64_syscall+0x140/frame 0xfffffe015d4adf30
fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe015d4adf30
--- syscall (54, FreeBSD ELF64, ioctl), rip = 0x22b0f0ef8d8a, rsp = 0x22b0ec63f2c8, rbp = 0x22b0ec63f380 ---
KDB: enter: panic
[ thread pid 5715 tid 101132 ]
Sponsored by: Rubicon Communications, LLC ("Netgate")
OpenVPN uses the sequence number (as well as a userspace supplied nonce)
to build the IV. This means we should avoid re-using sequence numbers.
However, userspace doesn't know how many packets we've sent (and thus
what sequence number we're up to).
Notify userspace when we've used half of the available sequence numbers
to tell it that it's time for a key renegotiaton.
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D39570
Functions manipulating source nodes can fail due to various reasons like
memory allocation errors, hitting configured limits or lack of
redirection targets. Ensure those errors are properly caught and
propagated in the code. Increase the error counters not only when
parsing the main ruleset but the NAT ruleset too.
Cherry-picked from development of D39880
Reviewed by: kp
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D39940
if_llmaddr_count() only counts link-level multicast addresses.
hv_netvsc(4) needs to know if there are any multicast addresses. Since
hv_netvsc(4) is the only instance where this would be used, make it a
simple boolean. If others need a if_maddr_count(), that can be added in
the future.
Reviewed by: melifaro
Sponsored by: Juniper Networks, Inc.
Differential Revision: https://reviews.freebsd.org/D39493
Reduce number of hashing operations when handling source nodes by always
having a pointer to the hash row mutex in the source node. Provide
macros for handling and asserting the mutex. Calculate the hash only
once in pf_find_src_node() and then use this hash in subsequent
operations.
Cherry-picked from development of D39880
Reviewed by: kp, mjg
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D39888
* Move LLT_ADDEDPROXY handling into lltable_link_entry() to
reduct duplication
* Use standard lltable_delete_addr() for entry deletion
* Add (forgotten) call to llt_post_resolved handler after
adding the entry via netlink.
MFC after: 2 weeks
Make Ethernet rules more similar to the usual layer 3 rules by also
allowing ridentifier and labels to be set on them.
Reviewed by: kp
Sponsored by: Rubicon Communications, LLC ("Netgate")
This change adds netlink create/modify/dump interfaces to the `if_clone.c`.
The previous attempt with storing the logic inside `netlink/route/iface_drivers.c`
did not quite work, as, for example, dumping interface-specific state
(like vlan id or vlan parent) required some peeking into the private interfaces.
The new interfaces are added in a compatible way - callers don't have to do anything
unless they are extended with Netlink.
Reviewed by: kp
Differential Revision: https://reviews.freebsd.org/D39032
MFC after: 1 month
Nothing should be directly touching the ifnet members, which are hidden
in <net/if_private.h>, so hide them in the same header to avoid errors
from users.
Sponsored by: Juniper Networks, Inc.
As the flag M_WAITOK is passed to ip_encap_attach(), then the function
will never return NULL, and the following code within NULL check branch
will be unreachable.
No functional change intended.
Reviewed by: kp
Fixes: 6d8fdfa9d5 Rework IP encapsulation handling code
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D39746
This change is required to support interface renaming via Netlink.
No functional changes intended.
Reviewed by: zlei
Differential Revision: https://reviews.freebsd.org/D39692
MFC after: 2 weeks
Both pf_rules_lock and pf_ioctl_lock only ever affect one vnet, so
there's no point in having these locks affect other vnets.
(In fact, the only lock in pf that can affect multiple vnets is
pf_end_lock.)
That's especially important for the rules lock, because taking the write
lock suspends all network traffic until it's released. This will reduce
the impact a vnet running pf can have on other vnets, and improve
concurrency on machines running multiple pf-enabled vnets.
Reviewed by: zlei
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D39658
PF_TABLE_STATS_ASSERT() should be checking pf_table_stats_lock not
pf_rules_lock.
Fortunately the define is not yet used anywhere so this was harmless.
Fix it anyway, in case it does get used.
Sponsored by: Rubicon Communications, LLC ("Netgate")
Expect that drivers call into the network stack with the net epoch
entered. This has already been the fact since early 2020. The net
interrupts, that are marked with INTR_TYPE_NET, were entering epoch
since 511d1afb6b. For the taskqueues there is NET_TASK_INIT() and
all drivers that were known back in 2020 we marked with it in
6c3e93cb5a. However in e87c494015 we took conservative approach
and preferred to opt-in rather than opt-out for the epoch.
This change not only reverts e87c494015 but adds a safety belt to
avoid panicing with INVARIANTS if there is a missed driver. With
INVARIANTS we will run in_epoch() check, print a warning and enter
the net epoch. A driver that prints can be quickly fixed with the
IFF_NEEDSEPOCH flag, but better be augmented to properly enter the
epoch itself.
Note on TCP LRO: it is a backdoor to enter the TCP stack bypassing
some layers of net stack, ignoring either old IFF_KNOWSEPOCH or the
new IFF_NEEDSEPOCH. But the tcp_lro_flush_all() asserts the presence
of network epoch. Indeed, all NIC drivers that support LRO already
provide the epoch, either with help of INTR_TYPE_NET or just running
NET_EPOCH_ENTER() in their code.
Reviewed by: zlei, gallatin, erj
Differential Revision: https://reviews.freebsd.org/D39510
939a050ad9 virtualized lagg(4), but the corresponding sysctl of some
virtualized global variables are not marked with CTLFLAG_VNET. A try to
operate on those variables via sysctl will effectively go to the 'master'
copies and the virtualized ones are not read or set accordingly. As a
side effect, on updating the 'master' copy, the virtualized global
variables of newly created vnets will have correct values.
PR: 270705
Reviewed by: kp
Fixes: 939a050ad9 Virtualize lagg(4) cloner
MFC after: 3 days
Differential Revision: https://reviews.freebsd.org/D39467
The bridge treated no vlan tag as being equivalent to vlan ID 1, which
causes confusion if the bridge sees both untagged and vlan 1 tagged
traffic.
Use DOT1Q_VID_NULL when there's no tag, and fix up the lookup code by
using 'DOT1Q_VID_RSVD_IMPL' to mean 'any vlan', rather than vlan 0. Note
that we have to account for userspace expecting to use 0 as meaning 'any
vlan'.
PR: 270559
Suggested by: Zhenlei Huang <zlei@FreeBSD.org>
Reviewed by: philip, zlei
Differential Revision: https://reviews.freebsd.org/D39478
It is shorter and more readable.
No functional change intended.
Reviewed by: kp
Fixes: 2d3614fb13 bridge: Log MAC address port flapping
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D39542
Introduce the OpenBSD syntax of "scrub" option for "match" and "pass"
rules and the "set reassemble" flag. The patch is backward-compatible,
pf.conf can be still written in FreeBSD-style.
Obtained from: OpenBSD
MFC after: never
Sponsored by: InnoGames GmbH
Differential Revision: https://reviews.freebsd.org/D38025
if_bridge receives packets via a special interface, if_bridge_input,
rather than by if_input. Thus, netmap's usual hooking of ifnet routines
does not work as expected. Instead, modify bridge_input() to pass
packets directly to netmap when it is enabled. This applies to both
locally delivered packets and forwarded packets.
When a netmap application transmits a packet by writing it to the host
TX ring, the mbuf chain is passed to if_input, which ordinarily points
to ether_input(). However, when transmitting via if_bridge,
bridge_input() needs to see the packet again in order to decide whether
to deliver or forward. Thus, introduce a new protocol flag,
M_BRIDGE_INJECT, which 1) causes the packet to be passed to
bridge_input() again after Ethernet processing, and 2) avoids passing
the packet back to netmap. The source MAC address of the packet is used
to determine the original "receiving" interface.
Reviewed by: vmaffione
MFC after: 2 months
Sponsored by: Zenarmor
Sponsored by: OPNsense
Sponsored by: Klara, Inc.
Differential Revision: https://reviews.freebsd.org/D38066
We already remove mbuf tags from packets transitting an if_epair, but we
didn't remove vlan metadata.
In certain configurations this could lead to unexpected vlan tags
turning up on the rx side.
PR: 270736
Reviewed by: markj
MFC after: 1 week
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D39482
MAC flapping occurs when a bridge receives packets with the same source MAC
address on different member interfaces. The common reasons are:
- user roams from one bridge port to another
- user has wrong network setup, bridge loops e.g.
- someone set duplicated ethernet address on his/her nic
- some bad guy / virus / trojan send spoofed packets
if_bridge currently updates the bridge routing entry silently hence it is hard
to diagnose.
Emit logs when MAC address port flapping occurs to make it easier to diagnose.
Reviewed by: kp
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D39375
This is counterpart to e87c494015, which did the same for ethernet.
Suggested by: hselasky
Reviewed by: hselasky, kib
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D39405
- Let the compiler use constant folding to eliminate conditionals.
- Fix some inconsistent whitespace.
No functional change intended.
Reviewed by: zlei
MFC after: 2 weeks
Sponsored by: Klara, Inc.
Differential Revision: https://reviews.freebsd.org/D38410
Different lagg protocols have different means and policies to process incoming
traffic. For example, for failover protocol, by default received traffic is only
accepted when they are received through the active port. For lacp protocol, LACP
control messages are tapped off, also traffic will be dropped if they are
received through the port which is not in collecting state or is not joined to
the active aggregator. It confuses if user dump and see inbound traffic on
lagg(4) interfaces but they are actually silently dropped and not passed into
the net stack.
Tap traffic after protocol processing so that user will have consistent view of
the inbound traffic, meanwhile mbuf is set with correct receiving interface and
bpf(4) will diagnose the right direction of inbound packets.
PR: 270417
Reviewed by: melifaro (previous version)
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D39225
From static code analysis, some device drivers (cxgbe, mlx4, mthca, and qlnx)
do not enter net epoch before lagg_input_infiniband(). If IPoIB interface is a
member of lagg(4) interface, and after returning from lagg_input_infiniband()
the receiving interface of mbuf is set to lagg(4) interface, then when
concurrently destroying the lagg(4) interface, there is a small window that the
interface gets destroyed and becomes invalid before infiniband_input() re-enter
net epoch, thus leading use-after-free.
Widen NET_EPOCH coverage to prevent use-after-free.
Thanks hselasky@ for testing with mlx5 devices.
Reviewed by: hselasky
Tested by: hselasky
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D39275
Use already-existing RTM_F_PREFIX rtm_flag to indicate that the
request assumes exact-prefix lookup instead of the
longest-prefix-match.
MFC after: 2 weeks