Add an overflow check to ensure that data_offset + data_len + 8 does not
wrap, which would enable an OOB read of the USB data buffer.
Cc: Andrew Lunn <andrew+netdev@lunn.ch>
Cc: Shaoxu Liu <shaoxul@foxmail.com>
Signed-off-by: Griffin Kroah-Hartman <griffin@kroah.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/2026070900-denim-brook-52d4@gregkh
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
The tcp_syn_ack_timeout() function gets inlined by Clang,
preventing tracing. Since the call is not in the fast
path, prevent it from being inlined.
Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260708180837.9507-1-emil@etsalapatis.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
During a tree-wide gpio include cleanup, the linux/gpio.h include was
replaced with linux/gpio/consumer.h.
mdio-device.c was already including that header, resulting in a
duplicated inclusion. Let's drop it.
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20260715201213.206180-1-maxime.chevallier@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This reverts commit 0be5c3f0fb.
Commit 0be5c3f0fb ("gtp: annotate PDP lookups under RTNL") added a
lockdep_rtnl_is_held condition to hlist_for_each_rcu() loops to help
insure that RTNL is held.
Unfortunately, as pointed out by Pablo Neira Ayuso, the PDP context list
is actually protected by the genetlink mutex. And so the condition
is incorrect.
Compile tested only.
Link: https://lore.kernel.org/ak4NgOrro-4OZjz3@chamomile
Signed-off-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260708-gtp-rtnl-v1-1-218091f171bc@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Tariq Toukan says:
====================
net/mlx5e: PSP cleanups and improvements
This series by Cosmin refactors mlx5 PSP support in preparation for
HW-GRO support.
There are almost no functionality changes in all but the last two
patches, which address a long-standing TODO in mlx5e_psp_set_config().
====================
Link: https://patch.msgid.link/20260707130858.969928-1-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
mlx5e_psp_register() was forced to eat PSP dev registration errors as
the caller was not propagating them. Change this so PSP dev registration
failures get reported back to the caller instead.
After the recent changes in the series, PSP dev registration failures
will just leave some data structs in priv->psp (mostly counters), with
no steering rules and no means to configure them. There's no point
actively cleaning those up on failure, as they'll get removed during
profile->cleanup.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260707130858.969928-16-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
profile->enable is called before enabling an mlx5 netdevice and
currently doesn't return errors. Code called from it has to either:
1. eat errors and keep going, leaving a netdevice initialized with
missing functionality
or
2. manually clean up things that other parts of the init flow might have
set up.
Option 1 might be useful in some cases for optional functionality but
option 2 doesn't make for good design.
Add a 3rd option for code which wants to propagate errors from
profile->enable and fail netdev init. This change is a noop for now, the
first 'user' of this option 3 will be in the next patch.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260707130858.969928-15-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Only create PSP steering tables when PSP configuration is enabled on a
PSP device.
Previously, mlx5e_psp_set_config (== .set_config on the PSP device) did
nothing. Steering was created and hooked up to incoming traffic at
device initialization time, via mlx5e_init_nic_rx -> mlx5e_accel_init_rx
-> mlx5_accel_psp_fs_init_rx_tables. Similarly, TX tables were created
and hooked to egress traffic at mlx5e_init_nic_tx -> mlx5e_accel_init_tx
-> mlx5_accel_psp_fs_init_tx_tables
Doing this means both ingress and egress UDP packets go through the
PSP steering tables, causing extra latency and overhead.
A better solution is to let the incoming encrypted PSP packets get
dropped by SW and not impose an overhead on all UDP packets which have
to traverse the PSP steering rules when PSP isn't used.
Additionally, upcoming changes to support HW-GRO need to reconfigure PSP
steering dynamically and this patch is a necessary step in that
direction.
Two new functions are defined:
- accel_psp_fs_create: Creates steering tables and connects RX UDP v4/v6
traffic to PSP RX tables.
- accel_psp_fs_destroy: Disconnects incoming RX traffic from PSP
steering and destroys steering tables.
PSP steering cleanup, which happens independently from PSP device
configuration, is unchanged. When the device is going away, steering
tables are destroyed as well.
The netdev lock is now used for proper synchronization between the new
set_config flow and device steering init/cleanup. This will be important
in future patches, when PSP will be able to reconfigure itself
dynamically upon netdev feature changes.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260707130858.969928-14-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
PSP steering code has two dynamically allocated structures to store RX
and TX steering structs. Remove those and flatten out everything into
the parent mlx5e_psp_fs.
The tx_counter was moved out of the TX table as well, because the table
doesn't own it, it outlives TX table destruction.
All table creation/destruction now happens in
accel_psp_fs_{rx,tx}_{create,destroy}. This will be used in subsequent
patches to make PSP configuration dynamic.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260707130858.969928-13-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
PSP uses a check steering table per IP version, but the PSP rules are
IP-version agnostic, so there's no point duplicating these in HW.
This commit makes the rx check steering table independent of the IP
version, with the final table added in the previous patch responsible
for directing packets to the corresponding UDP TIRs (or the TTC table
itself for non-UDP traffic).
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260707130858.969928-12-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Successfully decrypted PSP traffic is currently forwarded to the UDP
v4/v6 TTC default destination from its respective PSP rx_check table.
In preparation for flattening out RX steering and for decapsulation
support (which needs to handle non-UDP traffic as well), add an RX table
which directs traffic to either the UDP v4/v6 default TTC destinations,
or back to the TTC table itself for further processing. There can be no
loops as non-UDP traffic will not go through PSP processing again.
This is now used as a destination for successfully decrypted PSP
packets. The rx_counter is also incremented there, freeing the rx_check
rule for PSP_OK for atomic destination update in a future patch.
Use this opportunity to separate RX flow table levels from IPsec, as
reusing random IPsec ft levels as PSP isn't clear and now is a good
opportunity to separate them.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260707130858.969928-11-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
The rx_check ft was requesting max_fte == 2, but it created 4 entries.
While this accidentally works, it's not accurate, so change that and use
the correct number of entries. Also use an explicit drop_group for the
last match(*) drop rule.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260707130858.969928-10-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
There are multiple naming inconsistencies and the code is fragmented and
hard to follow.
For example, the PSP TX steering structure is named 'mlx5e_psp_tx', but
its RX counterpart is 'mlx5e_accel_fs_psp' and its protocol
instantiation 'mlx5e_accel_fs_psp_prot', neither of which make it clear
they relate to RX.
This commit renames things to be more consistent, realigns declarations
to abide by the xmas tree rule, and merges some functions to reduce
fragmentation. Renamed:
mlx5e_accel_fs_psp -> mlx5e_psp_rx
mlx5e_accel_fs_psp_prot -> mlx5e_psp_rx_decrypt_table
fs_prot -> decrypt
accel_psp -> rx_fs
mlx5e_psp_rx_err -> mlx5e_psp_rx_check_table
mlx5e_psp_tx -> mlx5e_psp_tx_table
def_rule -> rule
Also renamed many functions with names of the form
accel_psp_fs_A_B_C_..._verb, with A->B->C->... following a
general->specific hierarchy. Full list:
accel_psp_fs_rx_err_destroy_ft -> accel_psp_fs_rx_check_ft_destroy
accel_psp_fs_rx_err_create_ft -> accel_psp_fs_rx_check_ft_create
accel_psp_fs_rx_fs_destroy -> accel_psp_fs_rx_decrypt_ft_destroy
accel_psp_fs_rx_create_ft -> accel_psp_fs_rx_decrypt_ft_create
accel_psp_fs_tx_create_ft_table -> accel_psp_fs_tx_ft_create
accel_psp_fs_tx_destroy -> accel_psp_fs_tx_ft_destroy
accel_psp_fs_{init,cleanup}_{rx,tx} ->
accel_psp_fs_{rx,tx}_{init,cleanup}
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260707130858.969928-9-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
The PSP error flow table copies the HW syndrome to metadata register B,
but this value is never used in the RX path. Bad packets (auth fail,
bad trailer) are dropped by HW via explicit drop rules before reaching
software.
Remove the syndrome copy action, the syndrome macro, and the dead
syndrome check in the RX handler.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260707130858.969928-8-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
There are 3 rules added with the same structure. Factor out common code
into a helper function to reduce duplication.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260707130858.969928-7-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Add helper functions for creating and destroying PSP steering objects to
reduce code duplication.
This will become more relevant in future patches which add more steering
tables/groups/flows.
One nice side-effect of this is that the cleanup functions become
idempotent and can be used instead of long goto chains. This further
simplifies the code.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260707130858.969928-6-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
The rx_err table is different than the others, having separate functions
to create the flow rules in addition to the flow table.
Merge the add/delete rules functions with the ft create/delete functions
for consistency.
Noop change.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260707130858.969928-5-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
PSP steering uses reference counting for TX and RX steering tables, but
there's only a single reference for each acquired and thus the reference
counting is unnecessary.
Remove it and consolidate functions to simplify the code.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Link: https://patch.msgid.link/20260707130858.969928-4-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
PSP steering uses three mutexes to serialize steering rule init/cleanup.
But init/cleanup are already serialized with the higher level devlink
lock (for both device init and esw mode changes), so there's no need for
multiple additional mutexes.
Remove them to make room for the new changes.
Later in the series, the netdev lock will be used to serialize PSP
steering changes from multiple sources, so don't bother adding
assertions now only for them to be overwritten later.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Link: https://patch.msgid.link/20260707130858.969928-3-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This is the canonical name used in the core, so try to be consistent.
No-op change.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Link: https://patch.msgid.link/20260707130858.969928-2-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Ido Schimmel says:
====================
mlxsw: Make the driver ops-locked
Make the driver ops-locked in order to allow ethtool operations to be
invoked without RTNL being held.
An ops-locked driver has most of its NDOs, all of its ethtool operations
and some net device notifications run with the netdev instance lock
held.
In the specific case of mlxsw, the driver is not using any functions
that acquire this lock nor functions that expect the lock to be held for
an ops-locked driver. Therefore, converting its NDOs to run with the
lock being held is trivial except for a small quirk which is handled in
patch #1.
The driver does not generate any net device notifications, so there is
no risk of nested notifications of the ops-locked types. For the
notifications that run under the instance lock, RTNL is also held, and
the driver does not acquire the instance lock itself, so no changes are
required in its notifier handling.
Ethtool operations can be invoked without RTNL except for two operations
that are annotated in patch #2.
Lastly, patch #3 converts the driver to be ops-locked.
A probe on rtnl_lock() shows it is no longer taken when dumping
statistics:
# perf probe --add rtnl_lock
Before:
# perf stat -e probe:rtnl_lock -- ethtool -S swp1 --all-groups
[...]
1 probe:rtnl_lock
After:
# perf stat -e probe:rtnl_lock -- ethtool -S swp1 --all-groups
[...]
0 probe:rtnl_lock
No issues were reported after running a full regression with a debug
config that has lockdep enabled.
====================
Link: https://patch.msgid.link/20260708123933.1303291-1-idosch@nvidia.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
After the previous changes the driver is now ready to have its net
device and ethtool operations invoked with the netdev instance lock
held.
Tell the core about it by setting request_ops_lock to true.
Reviewed-by: Danielle Ratson <danieller@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260708123933.1303291-4-idosch@nvidia.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
A subsequent patch is going to make the driver ops-locked and allow
ethtool operations to run without RTNL. In preparation for this change,
tell the core about a couple of ethtool operations that should remain
under RTNL:
1. Set pause parameters: Configures the port's headroom buffer which is
also configured by RTNL-only paths such as DCB and qdisc. These paths
can probably be converted to acquire the netdev instance lock, but this
operation in not frequently called (unlike stats query), so avoid the
added complexity for now.
2. Get link state: Calls ethtool_op_get_link() which requires RTNL. See
commit 1105ef941c ("net: ethtool: keep rtnl_lock for ops using
ethtool_op_get_link()").
All the other operations do not access shared resources, do not invoke
helpers that require RTNL or already have the appropriate locking in
place.
Reviewed-by: Danielle Ratson <danieller@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260708123933.1303291-3-idosch@nvidia.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Commit c5b9b518ad ("mlxsw: spectrum: Add set_rx_mode ndo stub") added
a stub for ndo_set_rx_mode to prevent dev_ifsioc() from returning an
error for the SIOCADDMULTI and SIOCDELMULTI cases.
Since then dev_ifsioc() was taught to also accept ndo_set_rx_mode_async
and commit 3cbd229388 ("net: warn ops-locked drivers still using
ndo_set_rx_mode") modified register_netdevice() to warn when registering
an ops-locked net device that still uses ndo_set_rx_mode instead of
ndo_set_rx_mode_async.
In preparation for converting the driver to be ops-locked, convert the
ndo_set_rx_mode stub to a ndo_set_rx_mode_async stub.
Reviewed-by: Danielle Ratson <danieller@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260708123933.1303291-2-idosch@nvidia.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
After the previous patch, __br_multicast_send_query() no longer relies
on br_multicast_alloc_query() to determine the IGMP type of the query.
Remove the argument.
Reviewed-by: Petr Machata <petrm@nvidia.com>
Acked-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260708122820.1298718-3-idosch@nvidia.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Connecting two bridges on the same system [1] can result in a lockdep
splat [2].
The report is a false positive. Multicast queries are built and
transmitted under the bridge multicast lock. When the outgoing port of
one bridge is configured on top of another bridge, the transmit path
re-enters bridge code and acquires the other bridge's multicast lock in
order to snoop the query. Both lock instances share a single lockdep
class, so lockdep flags the nested acquisition as an AA deadlock.
Giving each bridge its own lock class will not solve the problem: the
reverse topology would produce an ABBA splat with the same pair of
classes. It also consumes a lockdep key per bridge.
Instead, fix the problem by deferring the transmission of the queries to
a workqueue. Build the skb and update querier state under the lock as
before, then enqueue the skb on a per multicast context queue and
schedule the work.
Purge the queue when the multicast context is de-initialized. At this
stage the work cannot be requeued. There is no need to take a reference
on skb->dev since the work cannot outlive the bridge or the bridge port.
Use the high priority workqueue to reduce the delay between the enqueue
time and the transmission time. With default settings (i.e., querier
interval - 255 seconds, query interval - 125 seconds) the extra delay
should not be a problem.
Avoid the unlikely case of the queue growing endlessly by limiting it to
1,000 skbs. Use this number for the simple reason that this is the
default Tx queue length.
Use local_bh_{disable,enable}() to disable/enable softIRQs and migration
in order to avoid corrupting the multicast statistics (per-CPU
u64_stats).
[1]
ip link add name br1 up type bridge mcast_snooping 1 mcast_querier 1
ip link add name br0 up type bridge mcast_snooping 1 mcast_querier 1
ip link add link br0 name br0.10 up master br1 type vlan id 10
[2]
WARNING: possible recursive locking detected
7.0.0-virtme-gb50c64a58a90 #1 Not tainted
[...]
ip/339 is trying to acquire lock:
ffff888104f0b480 (&br->multicast_lock){+.-.}-{3:3}, at: br_ip6_multicast_query (net/bridge/br_multicast.c:3584)
but task is already holding lock:
ffff888104f03480 (&br->multicast_lock){+.-.}-{3:3}, at: br_multicast_port_query_expired (net/bridge/br_multicast.c:1904)
[...]
Call Trace:
[...]
br_ip6_multicast_query (net/bridge/br_multicast.c:3584)
br_multicast_ipv6_rcv (net/bridge/br_multicast.c:3988)
br_dev_xmit (net/bridge/br_device.c:98 (discriminator 1))
dev_hard_start_xmit (net/core/dev.c:3904)
__dev_queue_xmit (net/core/dev.c:4871)
vlan_dev_hard_start_xmit (net/8021q/vlan_dev.c:131 (discriminator 1))
dev_hard_start_xmit (net/core/dev.c:3904)
__dev_queue_xmit (net/core/dev.c:4871)
br_dev_queue_push_xmit (net/bridge/br_forward.c:60)
__br_multicast_send_query (net/bridge/br_multicast.c:1811 (discriminator 1))
br_multicast_send_query (net/bridge/br_multicast.c:1889)
br_multicast_port_query_expired (net/bridge/br_multicast.c:1914)
call_timer_fn (kernel/time/timer.c:1749)
[...]
Reported-by: syzbot+d7b7f1412c02134efa6d@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/000000000000c4c9d405f2643e01@google.com/
Reviewed-by: Petr Machata <petrm@nvidia.com>
Acked-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260708122820.1298718-2-idosch@nvidia.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Pass source address, DSCP and output interface from the tunnel
configuration to ip_route_output() in ipip_fill_forward_path(), aligning
the route lookup with the slow path in ipip_tunnel_xmit().
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20260708-ipip-route-lookup-fill_forward_path-v1-1-b77df74822ed@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
rt_flush_dev() can replace rt->dst.dev with blackhole_netdev while RCU
readers are running. ip_rt_send_redirect() and ip_rt_get_source() both
read rt->dst.dev more than once and use the results in one operation.
If rt->dst.dev changes between those reads, the operation can use values
from two devices. For example, ip_rt_send_redirect() can use in_dev from
the old device and the L3 master ifindex from blackhole_netdev.
Read rt->dst.dev once in these two functions and use the snapshot for the
later device accesses.
Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260708060537.17188-3-xuanqiang.luo@linux.dev
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
rt_flush_dev() replaces rt->dst.dev with blackhole_netdev on uncached
routes. The field is also exposed as dst.dev_rcu, and existing readers
use dst_dev_rcu().
Use rcu_assign_pointer() for the replacement, as dst_dev_put() already
does for the same field.
Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260708060537.17188-2-xuanqiang.luo@linux.dev
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Commit 98d0912e9f ("net: skbuff: fix missing zerocopy reference in
pskb_carve helpers") introduced two calls of net_zcopy_get(skb_zcopy(skb)).
In fact, skb_zcopy() has already been executed once before. When calling
net_zcopy_get(), skb_zcopy() always returns skb_uarg(skb), which results
in adding some unnecessary instructions in skb_zcopy. So, change these
two calls to directly use skb_uarg(skb) instead of skb_zcopy.
In addition, also use net_zcopy_get() instead of refcount_inc() in
pskb_expand_head() for code consistency.
No functional change intended.
Signed-off-by: Yun Lu <luyun@kylinos.cn>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20260708055454.9167-1-luyun_611@163.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Anton Danilov says:
====================
udp: fix FOU/GUE over multicast
UDP encapsulation (FOU, GUE) has never worked correctly with multicast
destination addresses. When a FOU-encapsulated packet arrives at a
multicast address, it enters __udp4_lib_mcast_deliver() /
__udp6_lib_mcast_deliver() which call consume_skb() on packets that
need resubmission to the inner protocol handler, silently dropping
them instead.
The unicast delivery paths handle this correctly by propagating the
return value up to ip[6]_protocol_deliver_rcu() for resubmission, but
the multicast paths were never updated to support UDP encapsulation
resubmit.
This causes silent packet loss for FOU/GRETAP tunnels configured with
multicast remote addresses (both IPv4 and IPv6).
Reproducing the issue (IPv4):
ip netns add ns_a && ip netns add ns_b
ip link add veth0 netns ns_a type veth peer name veth1 netns ns_b
ip -n ns_a addr add 10.0.0.1/24 dev veth0 && ip -n ns_a link set veth0 up
ip -n ns_b addr add 10.0.0.2/24 dev veth1 && ip -n ns_b link set veth1 up
ip -n ns_a route add 239.0.0.0/8 dev veth0
ip -n ns_b route add 239.0.0.0/8 dev veth1
# Disable early demux to expose the issue (otherwise it's partially masked)
ip netns exec ns_b sysctl -w net.ipv4.ip_early_demux=0
# Join multicast group on receiver
ip -n ns_b addr add 239.0.0.1/32 dev veth1 autojoin
# Sender: GRETAP with FOU encap
ip -n ns_a link add eoudp0 type gretap \
remote 239.0.0.1 local 10.0.0.1 \
encap fou encap-sport 4797 encap-dport 4797 key 239.0.0.1
ip -n ns_a link set eoudp0 up
ip -n ns_a addr add 192.168.99.1/24 dev eoudp0
# Receiver: FOU listener + GRETAP
ip netns exec ns_b ip fou add port 4797 ipproto 47
ip -n ns_b link add eoudp0 type gretap \
remote 239.0.0.1 local 10.0.0.2 \
encap fou encap-sport 4797 encap-dport 4797 key 239.0.0.1
ip -n ns_b link set eoudp0 up
ip -n ns_b addr add 192.168.99.2/24 dev eoudp0
# Static neigh: ARP replies can't traverse unidirectional mcast tunnel
recv_mac=$(ip -n ns_b link show eoudp0 | awk '/ether/{print $2}')
ip -n ns_a neigh add 192.168.99.2 lladdr $recv_mac dev eoudp0
# Test: ping through the FOU/GRETAP tunnel
ip netns exec ns_a ping -c 100 192.168.99.2
# -> without this patch: 0 packets received on eoudp0
# -> with this patch: all packets received on eoudp0
IPv6 (using fou6 + ip6gretap) exhibits the same silent drop with a
different fix (see 1/2 for the sign-of-ret difference between
ip_protocol_deliver_rcu() and ip6_protocol_deliver_rcu()).
AI assistance (Claude, claude-opus-4-6) was used during root cause
analysis of the kernel source code (tracing the call chain from
udp[6]_queue_rcv_skb through encap_rcv to ip[6]_protocol_deliver_rcu,
comparing unicast/GSO/multicast paths) and during patch and selftest
authoring.
v5: https://lore.kernel.org/netdev/cover.1783218197.git.littlesmilingcloud@gmail.com/
v4: https://lore.kernel.org/netdev/cover.1782945956.git.littlesmilingcloud@gmail.com/
v3: https://lore.kernel.org/netdev/cover.1777934869.git.littlesmilingcloud@gmail.com/
v2: https://lore.kernel.org/netdev/ad_dal164gVmImWl@dau-home-pc/
v1 (RFC): https://lore.kernel.org/netdev/ad7MsSJOuUU6EGwS@dau-home-pc/
====================
Link: https://patch.msgid.link/cover.1783372173.git.littlesmilingcloud@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Add a selftest to verify that FOU-encapsulated packets addressed to a
multicast destination are correctly resubmitted to the inner protocol
handler (GRE) via the UDP multicast delivery path. Both IPv4 and IPv6
paths are tested.
The test creates two network namespaces connected by a veth pair with
a FOU/GRETAP (IPv4) and FOU/ip6gretap (IPv6) tunnel using multicast
remote addresses (239.0.0.1 and ff0e::1). Ping is sent through each
tunnel and received packets are counted on the receiver's tunnel
interface.
The veth pair is created directly inside the namespaces to avoid
possible name collisions with devices in the root namespace.
Static neighbor entries are configured on the sender because ARP/ND
replies from the receiver cannot traverse the unidirectional multicast
tunnel back to the sender.
The early demux optimization (net.ipv4.ip_early_demux, which controls
both IPv4 and IPv6) is disabled on the receiver to force packets
through __udp4_lib_mcast_deliver() / __udp6_lib_mcast_deliver(), which
is the code path being tested.
Signed-off-by: Anton Danilov <littlesmilingcloud@gmail.com>
Assisted-by: Claude:claude-opus-4-6
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/a5b65f092d22a12b52fc536c0565b948cd8ecae3.1783372173.git.littlesmilingcloud@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
When a UDP encapsulation socket (e.g., FOU) receives a multicast
packet, __udp4_lib_mcast_deliver() and __udp6_lib_mcast_deliver()
call consume_skb() when udp_queue_rcv_skb() returns a positive value.
A positive return value from udp_queue_rcv_skb() indicates that the
encap_rcv handler (e.g., fou_udp_recv) has consumed the UDP header
and wants the packet to be resubmitted to the IP protocol handler
for further processing (e.g., as a GRE packet).
The unicast paths handle this correctly by propagating the return
value up to ip_protocol_deliver_rcu() / ip6_protocol_deliver_rcu()
for resubmission. However, the multicast paths destroy the packet
via consume_skb() instead of resubmitting it, causing silent packet
loss.
This affects any UDP encapsulation (FOU, GUE) combined with multicast
destination addresses.
Fix this by returning the value from udp_queue_rcv_skb() when it is
positive, matching the behavior of the corresponding unicast paths.
Note the sign difference between IPv4 and IPv6:
- IPv4: udp_unicast_rcv_skb() returns -ret, and
ip_protocol_deliver_rcu() resubmits when ret < 0
(using -ret as the protocol number).
- IPv6: udp6_unicast_rcv_skb() returns ret, and
ip6_protocol_deliver_rcu() resubmits when ret > 0
(using ret as the nexthdr).
Both mcast paths now follow the same convention as their respective
unicast paths.
Suggested-by: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: Anton Danilov <littlesmilingcloud@gmail.com>
Assisted-by: Claude:claude-opus-4-6
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/5372ccac062193147e02b991d5328a5c3fa3a85a.1783372173.git.littlesmilingcloud@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Ciprian Regus says:
====================
net: Add ADIN1140 support
This series introduces support for the ADIN1140 (also called AD3306)
10BASE-T1S single port MACPHY. The device integrates the MAC and PHY in
the same package. The communication with the host CPU is done through an
SPI interface, using the Open Alliance TC6 protocol for control and data
transactions. As a result, the oa_tc6 framework is used to implement
the communication with the device (register accesses and Ethernet frame
RX/TX).
The MAC and PHY are connected internally using an MII and MDIO bus.
The PHY is a half duplex 10Mbps device, which implements both the PLCA
RS (IEEE 802.3 clause 148) and CSMA/CD methods of accessing the Ethernet
medium. The 10BASE-T1S standard allows multiple PHY devices to be
connected (in parallel) on the same single twisted pair network segment,
so PLCA can be configured in order to provide a fair access scheme to
all the nodes and reduce the jitter introduced by the unordered CSMA/CD
transmits. The PHY's internal register map can be accessed using the
direct MDIO mode of the OA TC6. The control, status, phy id 1 & 2 C22
registers are mapped to the 0xFF00 - 0xFF03 range. As for C45
addressable devices, the PHY has PCS, PMA and PLCA blocks.
The oa_tc6 framework patches are changes that would make the library
usable by the subsequent ADIN1140 MAC driver.
The protected mode patch is required because the ADIN1140 only allows
protected mode OA TC6 control transactions, which the oa_tc6 framework
doesn't currently implement.
The OA_TC6_BROKEN_PHY quirk patch is required in order to allow the MAC
driver to have a custom implementation for the mii_bus access methods as a
workaround for hardware issues:
1. The OA TC6 standard defines the direct and indirect access modes for
MDIO transactions. The ADIN1140 incorrectly advertises indirect mode
only (supported capabilities register - 0x2, bit 9), while actually
implementing just the direct mode. We cannot rely on the CAP register
to choose an access method (which oa_tc6 does by default, even though
it only implements the direct mode), so the driver has to use its
own.
2. The ADIN1140 cannot access the C22 register space of the internal
PHY, while the PHY is busy receiving frames. If that happens, the
CONFIG0 and CONFIG2 registers of the MAC will get corrupted and the
data transfer will stop. Those two registers configure settings for
the transfer protocol between the MAC and host, so the value for some
of their subfields shouldn't be changed while the netdev is up.
Since we know the PHY is internal, the MAC driver can implement a
custom mii_bus, which can intercept C22 accesses. Most of the
registers mapped in the 0x0 - 0x3 range (the only ones the PHY offers)
are read only, and their value can be read from somewhere else (e.g
the PHYID 1 & 2 have the same value as 0x1 in the MAC memory map).
C45 accesses do not cause this issue, so we can properly implement
them.
Even though they have different driver, the MAC one cannot function
without the PHY driver, since the PHY is not compatible with the generic
c22 driver. As such CONFIG_ADIN1140 selects CONFIG_ADIN1140_PHY.
Signed-off-by: Ciprian Regus <ciprian.regus@analog.com>
====================
Link: https://patch.msgid.link/20260708-adin1140-driver-v5-0-4aca7b51a58b@analog.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Add a driver for ADIN1140. The device is a 10BASE-T1S MAC-PHY
(integrated in the same package) that connects to a CPU over an SPI bus,
and implements the Open Alliance TC6 protocol for control and frame
transfers. As such, this driver relies on oa_tc6 for the communication
with the device. The device has an alternative name (AD3306), so the
driver can be probed using one of the two compatible strings.
For control transactions, ADIN1140 only implements the protected mode.
The driver has a custom implementation for the mii_bus access methods as a
workaround for hardware issues:
1. The OA TC6 standard defines the direct and indirect access modes for
MDIO transactions. The ADIN1140 incorrectly advertises indirect mode
only (supported capabilities register - 0x2, bit 9), while actually
implementing just the direct mode. We cannot rely on the CAP register
to choose an access method (which oa_tc6 does by default, even though
it only implements the direct mode), so the driver has to use its
own.
2. The ADIN1140 cannot access the C22 register space of the internal
PHY, while the PHY is busy receiving frames. If that happens, the
CONFIG0 and CONFIG2 registers of the MAC will get corrupted and the
data transfer will stop. Those two registers configure settings for
the transfer protocol between the MAC and host, so the value for some
of their subfields shouldn't be changed while the netdev is up.
Since we know the PHY is internal, the MAC driver can implement a
custom mii_bus, which can intercept C22 accesses. Most of the
registers mapped in the 0x0 - 0x3 range (the only ones the PHY offers)
are read only, and their value can be read from somewhere else (e.g
the PHYID 1 & 2 have the same value as 0x1 in the MAC memory map).
For the fields that are R/W (loopback and AN/reset) in the control
register, the PHY driver already implements the set_loopback() and
config_aneg() functions. The C22 write function of the driver is a
no-op and is used to protect against the ioctl MDIO access path.
C45 accesses do not cause this issue, so we can properly implement
them.
Signed-off-by: Ciprian Regus <ciprian.regus@analog.com>
Link: https://patch.msgid.link/20260708-adin1140-driver-v5-13-4aca7b51a58b@analog.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Add a driver for the ADIN1140's internal 10BASE-T1S PHY. The device
doesn't implement autonegotiation, so the link is always reported as
being up.
The device implements both C22 and C45 MDIO access methods, but can only
be discovered over C22, since the C45 MMD devices lack the MDIO_DEVID1 and
MDIO_DEVID2 registers. The indirect C45 over C22 feature is not
supported.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Ciprian Regus <ciprian.regus@analog.com>
Link: https://patch.msgid.link/20260708-adin1140-driver-v5-12-4aca7b51a58b@analog.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Replace the driver specific lan865x_phy_read_mmd() and
lan865x_phy_write_mmd() with the shared genphy_read_mmd_c45() and
genphy_write_mmd_c45() helpers.
No functional change.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Ciprian Regus <ciprian.regus@analog.com>
Link: https://patch.msgid.link/20260708-adin1140-driver-v5-11-4aca7b51a58b@analog.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Some PHYs support direct C45 register access but not C22 indirect MMD
access (registers 0xD and 0xE). When discovered via C22, phylib routes
MMD access through the indirect path, which won't work on these
devices.
Add genphy_read_mmd_c45() and genphy_write_mmd_c45() as read_mmd/
write_mmd callbacks that bypass the C22 indirect path and use the bus
C45 accessors directly.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Ciprian Regus <ciprian.regus@analog.com>
Link: https://patch.msgid.link/20260708-adin1140-driver-v5-10-4aca7b51a58b@analog.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Accessing PHY MMD devices requires control transactions to registers in
a memory map other than 0. Replace the current formatting of the
register addresses with the oa_tc6_{read,write}_register_mms()
functions. While we're here, introduce the mms variable to store the
memory map returned by oa_tc6_get_phy_c45_mms() instead of ret, in order
to improve the code readability.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Ciprian Regus <ciprian.regus@analog.com>
Link: https://patch.msgid.link/20260708-adin1140-driver-v5-8-4aca7b51a58b@analog.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
The Open Alliance TC6 standard defines multiple memory maps for the
MAC-PHY's register space. These are used to separate standard, vendor
and PHY MMD specific registers. Define register access functions that
allow the caller to specify the MMS.
Signed-off-by: Ciprian Regus <ciprian.regus@analog.com>
Link: https://patch.msgid.link/20260708-adin1140-driver-v5-7-4aca7b51a58b@analog.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
The OA TC6 standard registers are currently exported in a header file.
Add the OA_TC6_ prefix to the register address and subfield mask macros
to avoid future naming conflicts.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Ciprian Regus <ciprian.regus@analog.com>
Link: https://patch.msgid.link/20260708-adin1140-driver-v5-6-4aca7b51a58b@analog.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Move defines for standard Open Alliance TC6 register addresses and
subfields in the oa_tc6's header. As such, other ethernet drivers
that rely on oa_tc6 can use them directly.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Ciprian Regus <ciprian.regus@analog.com>
Link: https://patch.msgid.link/20260708-adin1140-driver-v5-5-4aca7b51a58b@analog.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
The C45 access functions can still be used by some Ethernet drivers
which set the OA_TC6_BROKEN_PHY flag. Export them.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Ciprian Regus <ciprian.regus@analog.com>
Link: https://patch.msgid.link/20260708-adin1140-driver-v5-4-4aca7b51a58b@analog.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Some MAC-PHY devices need custom MDIO bus access functions to work
around hardware issues. Add the OA_TC6_BROKEN_PHY quirk flag so drivers
can opt in to skip oa_tc6's internal PHY init and manage the PHY
themselves. When the flag is set, oa_tc6 skips MDIO bus registration,
PHY discovery and PHY connection, leaving these to the driver.
Drivers that do not set the flag retain the existing behavior. Update
lan865x and the framework documentation accordingly.
Signed-off-by: Ciprian Regus <ciprian.regus@analog.com>
Link: https://patch.msgid.link/20260708-adin1140-driver-v5-3-4aca7b51a58b@analog.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Implement the OA TC6 standard defined protected mode for control (register
access) transactions. In addition to the current register access formats
the oa_tc6 driver handles, 1's complement values of the data field
are included (by both the host and the MACPHY) in the SPI transfer frames.
This feature acts as an integrity check.
Control write transactions look like this:
|<- 32 bits ->|<--- data_size --->|<- 32 bits ->|
MOSI: | ctrl header | reg write data | ignored |
MISO: | (discard) | echoed ctrl hdr | echoed data |
data_size (LEN = number of registers to read in a sequence):
Unprotected: 32 x (LEN + 1) bits
Protected: 2 x 32 x (LEN + 1) bits
Control read transaction:
|<- 32 bits ->|<--- 32 bits --> |<- data_size ->|
MOSI: | ctrl header | ignored ... |
MISO: | (discard) | echoed ctrl hdr | reg read data |
data_size (LEN = number of registers to read in a sequence):
Unprotected: 32 x (LEN + 1) bits
Protected: 2 x 32 x (LEN + 1) bits
Register data format ("reg write data" and "reg read data"):
Unprotected:
| W1 (normal) | W2 (normal) | ... | Wx (normal) |
Protected:
| W1 (normal) | W1 (complement) | ... | Wx (normal) | Wx (complement)|
The protected mode state can be read from the bit 5 of CONFIG0 (0x4)
register, and this setting is usually only configured during the
MACPHY's reset (depending on the device it can be done by setting the
state of a pin). We can read the protected mode configuration before any
other register access and since the SPI transfer is initially sized for an
unprotected read, the MACPHY's complement words are never clocked out
and no checking is required. The data transactions (Ethernet frames)
remain unchanged.
Signed-off-by: Ciprian Regus <ciprian.regus@analog.com>
Link: https://patch.msgid.link/20260708-adin1140-driver-v5-2-4aca7b51a58b@analog.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
The ADIN1140 is a single port 10BASE-T1S Ethernet controller that
includes both the MAC and a PHY in the same package.
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Ciprian Regus <ciprian.regus@analog.com>
Link: https://patch.msgid.link/20260708-adin1140-driver-v5-1-4aca7b51a58b@analog.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>