On 19/07/2025 11:30, Mohsin Bashir wrote:
Test XDP_PASS/DROP in single buffer and multi buffer mode when XDP native support is available.
./drivers/net/xdp.py TAP version 13 1..4 ok 1 xdp.test_xdp_native_pass_sb ok 2 xdp.test_xdp_native_pass_mb ok 3 xdp.test_xdp_native_drop_sb ok 4 xdp.test_xdp_native_drop_mb # Totals: pass:4 fail:0 xfail:0 xpass:0 skip:0 error:0
Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Mohsin Bashir mohsin.bashr@gmail.com
tools/testing/selftests/drivers/net/Makefile | 1 + tools/testing/selftests/drivers/net/xdp.py | 303 ++++++++++++++++++ .../selftests/net/lib/xdp_native.bpf.c | 158 +++++++++ 3 files changed, 462 insertions(+) create mode 100755 tools/testing/selftests/drivers/net/xdp.py create mode 100644 tools/testing/selftests/net/lib/xdp_native.bpf.c
...
+static struct udphdr *filter_udphdr(struct xdp_md *ctx, __u16 port) +{
- void *data_end = (void *)(long)ctx->data_end;
- void *data = (void *)(long)ctx->data;
- struct udphdr *udph = NULL;
- struct ethhdr *eth = data;
- if (data + sizeof(*eth) > data_end)
return NULL;
This check assumes that the packet headers reside in the linear part of the xdp_buff. However, this assumption does not hold across all drivers. For example, in mlx5, the linear part is empty when using multi-buffer mode with striding rq configuration. This causes all multi-buffer test cases to fail over mlx5.
To ensure correctness across all drivers, all direct accesses to packet data should use these safer helper functions instead: bpf_xdp_load_bytes() and bpf_xdp_store_bytes().
Related discussion and context can be found here: https://github.com/xdp-project/xdp-tools/pull/409
- if (eth->h_proto == bpf_htons(ETH_P_IP)) {
struct iphdr *iph = data + sizeof(*eth);
if (iph + 1 > (struct iphdr *)data_end ||
iph->protocol != IPPROTO_UDP)
return NULL;
udph = (void *)eth + sizeof(*iph) + sizeof(*eth);
- } else if (eth->h_proto == bpf_htons(ETH_P_IPV6)) {
struct ipv6hdr *ipv6h = data + sizeof(*eth);
if (ipv6h + 1 > (struct ipv6hdr *)data_end ||
ipv6h->nexthdr != IPPROTO_UDP)
return NULL;
udph = (void *)eth + sizeof(*ipv6h) + sizeof(*eth);
- } else {
return NULL;
- }
- if (udph + 1 > (struct udphdr *)data_end)
return NULL;
- if (udph->dest != bpf_htons(port))
return NULL;
- record_stats(ctx, STATS_RX);
- return udph;
+}