* [PATCH net 1/2] net: fix mac_len of skbs copied by generic XDP
2026-11-03 20:00 [PATCH net 0/2] net: fix mac_len of skbs copied by generic XDP Tianyi Gao
@ 2026-11-03 20:00 ` Tianyi Gao
2026-11-06 10:34 ` Toke Høiland-Jørgensen
2026-11-03 20:00 ` [PATCH net 2/2] selftests: drv-net: ping: test generic XDP redirect to cpumap Tianyi Gao
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Tianyi Gao @ 2026-11-03 20:00 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Andrew Lunn, Shuah Khan, Alexei Starovoitov,
Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Lorenzo Bianconi, Toke Hoiland-Jorgensen,
linux-kselftest, bpf, kernel-team, Tianyi Gao
skb_pp_cow_data() copies the header fields of the old skb with
skb_copy_header(). skb_copy_header() does not copy mac_len.
Generic XDP uses skb_pp_cow_data() for programs with frags support.
After such a program, the skb can have mac_len 0.
cpu_map_generic_redirect() and tc ingress then get the position of the
Ethernet header wrong.
Copy mac_len in skb_pp_cow_data(), as dev_map_generic_redirect() does
after skb_copy().
Fixes: e6d5dbdd20aa ("xdp: add multi-buff support for xdp running in generic mode")
Signed-off-by: Tianyi Gao <tianyi@cloudflare.com>
---
net/core/skbuff.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 48f676411724..aa0b11204708 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -967,6 +967,7 @@ int skb_pp_cow_data(struct page_pool *pool, struct sk_buff **pskb,
skb_reserve(nskb, headroom);
skb_copy_header(nskb, skb);
+ nskb->mac_len = skb->mac_len;
skb_mark_for_recycle(nskb);
err = skb_copy_bits(skb, 0, nskb->data, size);
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH net 1/2] net: fix mac_len of skbs copied by generic XDP
2026-11-03 20:00 ` [PATCH net 1/2] " Tianyi Gao
@ 2026-11-06 10:34 ` Toke Høiland-Jørgensen
0 siblings, 0 replies; 7+ messages in thread
From: Toke Høiland-Jørgensen @ 2026-11-06 10:34 UTC (permalink / raw)
To: Tianyi Gao, netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Andrew Lunn, Shuah Khan, Alexei Starovoitov,
Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Lorenzo Bianconi, linux-kselftest, bpf,
kernel-team
Tianyi Gao <tianyi@cloudflare.com> writes:
> skb_pp_cow_data() copies the header fields of the old skb with
> skb_copy_header(). skb_copy_header() does not copy mac_len.
>
> Generic XDP uses skb_pp_cow_data() for programs with frags support.
> After such a program, the skb can have mac_len 0.
> cpu_map_generic_redirect() and tc ingress then get the position of the
> Ethernet header wrong.
>
> Copy mac_len in skb_pp_cow_data(), as dev_map_generic_redirect() does
> after skb_copy().
>
> Fixes: e6d5dbdd20aa ("xdp: add multi-buff support for xdp running in generic mode")
> Signed-off-by: Tianyi Gao <tianyi@cloudflare.com>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net 2/2] selftests: drv-net: ping: test generic XDP redirect to cpumap
2026-11-03 20:00 [PATCH net 0/2] net: fix mac_len of skbs copied by generic XDP Tianyi Gao
2026-11-03 20:00 ` [PATCH net 1/2] " Tianyi Gao
@ 2026-11-03 20:00 ` Tianyi Gao
2026-11-03 20:04 ` [PATCH net 0/2] net: fix mac_len of skbs copied by generic XDP netdev-bot+sinfo
2026-11-10 14:30 ` patchwork-bot+netdevbpf
3 siblings, 0 replies; 7+ messages in thread
From: Tianyi Gao @ 2026-11-03 20:00 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Andrew Lunn, Shuah Khan, Alexei Starovoitov,
Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Lorenzo Bianconi, Toke Hoiland-Jorgensen,
linux-kselftest, bpf, kernel-team, Tianyi Gao
The generic XDP tests in ping.py only cover XDP_PASS. Add a test that
redirects all packets to a cpumap with an xdp.frags program. It runs
the same ping and TCP checks as the other tests.
xdp_cpumap.bpf.c is a new program. It redirects every packet to entry 0
of a cpumap. It is not added to xdp_dummy.bpf.c. test_xdp_offload loads
xdp_dummy.bpf.o in offload mode, which would fail on a cpumap.
The new test extends _set_xdp_generic_mb_on() with two optional
arguments. The first argument, prog, is the XDP program file name, with
default "xdp_dummy.bpf.o". The second argument, on_attach, is a
callback function, with default None. on_attach runs right after the
program is attached. The new test passes "xdp_cpumap.bpf.o" to prog and
a lambda that adds the cpumap entry to on_attach.
Without the previous patch, the new test fails on netdevsim because ping
gets no reply.
Signed-off-by: Tianyi Gao <tianyi@cloudflare.com>
---
tools/testing/selftests/drivers/net/ping.py | 27 ++++++++++++++++---
.../selftests/net/lib/xdp_cpumap.bpf.c | 19 +++++++++++++
2 files changed, 43 insertions(+), 3 deletions(-)
create mode 100644 tools/testing/selftests/net/lib/xdp_cpumap.bpf.c
diff --git a/tools/testing/selftests/drivers/net/ping.py b/tools/testing/selftests/drivers/net/ping.py
index da3623c5e8a9..a0de9a98d906 100755
--- a/tools/testing/selftests/drivers/net/ping.py
+++ b/tools/testing/selftests/drivers/net/ping.py
@@ -7,7 +7,7 @@ from lib.py import ksft_run, ksft_exit
from lib.py import ksft_eq, KsftSkipEx, KsftFailEx
from lib.py import EthtoolFamily, NetDrvEpEnv
from lib.py import bkg, cmd, wait_port_listen, rand_port
-from lib.py import defer, ethtool, ip
+from lib.py import bpf_map_set, defer, ethtool, ip
no_sleep=False
@@ -75,16 +75,23 @@ def _set_xdp_generic_sb_on(cfg) -> None:
if no_sleep != True:
time.sleep(10)
-def _set_xdp_generic_mb_on(cfg) -> None:
- prog = cfg.net_lib_dir / "xdp_dummy.bpf.o"
+def _set_xdp_generic_mb_on(cfg, prog="xdp_dummy.bpf.o", on_attach=None) -> None:
+ prog = cfg.net_lib_dir / prog
cmd(f"ip link set dev {cfg.remote_ifname} mtu 9000", shell=True, host=cfg.remote)
defer(ip, f"link set dev {cfg.remote_ifname} mtu 1500", host=cfg.remote)
ip("link set dev %s mtu 9000 xdpgeneric obj %s sec xdp.frags" % (cfg.ifname, prog))
defer(ip, f"link set dev {cfg.ifname} mtu 1500 xdpgeneric off")
+ if on_attach:
+ on_attach()
if no_sleep != True:
time.sleep(10)
+def _set_xdp_generic_cpumap_mb_on(cfg) -> None:
+ cfg.require_cmd("bpftool")
+ _set_xdp_generic_mb_on(cfg, "xdp_cpumap.bpf.o",
+ on_attach=lambda: bpf_map_set("map_cpumap", 0, 2048))
+
def _set_xdp_native_sb_on(cfg) -> None:
prog = cfg.net_lib_dir / "xdp_dummy.bpf.o"
cmd(f"ip link set dev {cfg.remote_ifname} mtu 1500", shell=True, host=cfg.remote)
@@ -192,6 +199,19 @@ def test_xdp_generic_mb(cfg, netnl) -> None:
_test_v6(cfg)
_test_tcp(cfg)
+def test_xdp_generic_cpumap_mb(cfg, netnl) -> None:
+ """Redirect all packets to a cpumap from a generic xdp.frags program."""
+ _schedule_checksum_reset(cfg, netnl)
+ _set_xdp_generic_cpumap_mb_on(cfg)
+ _set_offload_checksum(cfg, netnl, "off")
+ _test_v4(cfg)
+ _test_v6(cfg)
+ _test_tcp(cfg)
+ _set_offload_checksum(cfg, netnl, "on")
+ _test_v4(cfg)
+ _test_v6(cfg)
+ _test_tcp(cfg)
+
def test_xdp_native_sb(cfg, netnl) -> None:
_schedule_checksum_reset(cfg, netnl)
_set_xdp_native_sb_on(cfg)
@@ -230,6 +250,7 @@ def main() -> None:
test_default_v6,
test_xdp_generic_sb,
test_xdp_generic_mb,
+ test_xdp_generic_cpumap_mb,
test_xdp_native_sb,
test_xdp_native_mb,
test_xdp_offload],
diff --git a/tools/testing/selftests/net/lib/xdp_cpumap.bpf.c b/tools/testing/selftests/net/lib/xdp_cpumap.bpf.c
new file mode 100644
index 000000000000..150352343114
--- /dev/null
+++ b/tools/testing/selftests/net/lib/xdp_cpumap.bpf.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+struct {
+ __uint(type, BPF_MAP_TYPE_CPUMAP);
+ __uint(max_entries, 1);
+ __type(key, __u32);
+ __type(value, __u32);
+} map_cpumap SEC(".maps");
+
+SEC("xdp.frags")
+int xdp_cpumap_prog_frags(struct xdp_md *ctx)
+{
+ return bpf_redirect_map(&map_cpumap, 0, XDP_DROP);
+}
+
+char _license[] SEC("license") = "GPL";
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH net 0/2] net: fix mac_len of skbs copied by generic XDP
2026-11-03 20:00 [PATCH net 0/2] net: fix mac_len of skbs copied by generic XDP Tianyi Gao
2026-11-03 20:00 ` [PATCH net 1/2] " Tianyi Gao
2026-11-03 20:00 ` [PATCH net 2/2] selftests: drv-net: ping: test generic XDP redirect to cpumap Tianyi Gao
@ 2026-11-03 20:04 ` netdev-bot+sinfo
2026-11-03 20:53 ` Tianyi Gao
2026-11-10 14:30 ` patchwork-bot+netdevbpf
3 siblings, 1 reply; 7+ messages in thread
From: netdev-bot+sinfo @ 2026-11-03 20:04 UTC (permalink / raw)
To: Tianyi Gao
Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Andrew Lunn, Shuah Khan,
Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
John Fastabend, Stanislav Fomichev, Lorenzo Bianconi,
Toke Hoiland-Jorgensen, linux-kselftest, bpf, kernel-team
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- How the issue was discovered, e.g. hit in production, hit during
development, syzbot report, manual code inspection, LLM or static
analysis tool scan.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net 0/2] net: fix mac_len of skbs copied by generic XDP
2026-11-03 20:04 ` [PATCH net 0/2] net: fix mac_len of skbs copied by generic XDP netdev-bot+sinfo
@ 2026-11-03 20:53 ` Tianyi Gao
0 siblings, 0 replies; 7+ messages in thread
From: Tianyi Gao @ 2026-11-03 20:53 UTC (permalink / raw)
To: netdev-bot+sinfo
Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Andrew Lunn, Shuah Khan,
Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
John Fastabend, Stanislav Fomichev, Lorenzo Bianconi,
Toke Hoiland-Jorgensen, linux-kselftest, bpf, kernel-team
Hi,
I hit this while benchmarking generic XDP with an xdp.frags program
that redirects to a cpumap. TCP throughput dropped to almost zero.
Cheers,
Tianyi
On Tue, Nov 3, 2026 at 8:04 PM <netdev-bot+sinfo@kernel.org> wrote:
>
> Hi!
>
> This is an automated message. This series looks like a fix, but its
> commit messages seem to be missing some information:
>
> - How the issue was discovered, e.g. hit in production, hit during
> development, syzbot report, manual code inspection, LLM or static
> analysis tool scan.
>
> Please do not repost the series just to address the above. Instead,
> reply to this email with the missing information, so that reviewers
> can take it into account. If the series needs another revision for
> other reasons, please include the information in the commit messages
> then.
>
> The evaluation is done by an LLM so it may be wrong, if you think
> that is the case please reply and explain.
--
Cheers,
Tianyi
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net 0/2] net: fix mac_len of skbs copied by generic XDP
2026-11-03 20:00 [PATCH net 0/2] net: fix mac_len of skbs copied by generic XDP Tianyi Gao
` (2 preceding siblings ...)
2026-11-03 20:04 ` [PATCH net 0/2] net: fix mac_len of skbs copied by generic XDP netdev-bot+sinfo
@ 2026-11-10 14:30 ` patchwork-bot+netdevbpf
3 siblings, 0 replies; 7+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-11-10 14:30 UTC (permalink / raw)
To: Tianyi Gao
Cc: netdev, davem, edumazet, kuba, pabeni, horms, andrew+netdev,
shuah, ast, daniel, hawk, john.fastabend, sdf, lorenzo, toke,
linux-kselftest, bpf, kernel-team
Hello:
This series was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:
On Tue, 3 Nov 2026 20:00:35 +0000 you wrote:
> Generic XDP copies the skb before it runs a program with frags support.
> The copy happens when the skb is cloned, nonlinear, or has less than 256
> bytes of headroom. skb_pp_cow_data() makes the copy, but it does not
> copy mac_len. After XDP, the skb has mac_len 0.
>
> Two places after generic XDP move skb->data by mac_len:
> - On XDP_REDIRECT to a cpumap, cpu_map_generic_redirect() pulls mac_len
> bytes, the length of the Ethernet header. Then it queues the skb to
> the target CPU. With mac_len 0, the IP layer on that CPU sees the
> Ethernet header and drops the packet.
> - On XDP_PASS, the skb can go on to tc ingress with a BPF program
> attached (tcx, cls_bpf or act_bpf). Before it runs the program, tc
> pushes mac_len bytes, the length of the Ethernet header. With
> mac_len 0, skb->data stays at the IP header. Therefore, the program
> reads the IP header as the Ethernet header.
>
> [...]
Here is the summary with links:
- [net,1/2] net: fix mac_len of skbs copied by generic XDP
https://git.kernel.org/netdev/net/c/71578e43b8a6
- [net,2/2] selftests: drv-net: ping: test generic XDP redirect to cpumap
https://git.kernel.org/netdev/net/c/71b116cf334b
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 7+ messages in thread