On 02/07/2025 16.59, Jesper Dangaard Brouer wrote: > From: Lorenzo Bianconi <lorenzo@xxxxxxxxxx> > > Introduce bpf selftests for the XDP rx_meta store kfuncs. > > Signed-off-by: Lorenzo Bianconi <lorenzo@xxxxxxxxxx> > --- > .../testing/selftests/bpf/prog_tests/xdp_rxmeta.c | 166 > ++++++++++++++++++++ > .../selftests/bpf/progs/xdp_rxmeta_receiver.c | 44 +++++ > .../selftests/bpf/progs/xdp_rxmeta_redirect.c | 43 +++++ > 3 files changed, 253 insertions(+) > create mode 100644 tools/testing/selftests/bpf/prog_tests/xdp_rxmeta.c > create mode 100644 tools/testing/selftests/bpf/progs/xdp_rxmeta_receiver.c > create mode 100644 tools/testing/selftests/bpf/progs/xdp_rxmeta_redirect.c > > diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_rxmeta.c > b/tools/testing/selftests/bpf/prog_tests/xdp_rxmeta.c > new file mode 100644 > index 000000000000..d5c181684ff8 > --- /dev/null > +++ b/tools/testing/selftests/bpf/prog_tests/xdp_rxmeta.c > @@ -0,0 +1,166 @@ > +// SPDX-License-Identifier: GPL-2.0 > +#include <test_progs.h> > +#include <network_helpers.h> > +#include <bpf/btf.h> > +#include <linux/if_link.h> > + > +#include "xdp_rxmeta_redirect.skel.h" > +#include "xdp_rxmeta_receiver.skel.h" > + > +#define LOCAL_NETNS_NAME "local" > +#define FWD_NETNS_NAME "forward" > +#define DST_NETNS_NAME "dest" > + > +#define LOCAL_NAME "local" > +#define FWD0_NAME "fwd0" > +#define FWD1_NAME "fwd1" > +#define DST_NAME "dest" > + > +#define LOCAL_MAC "00:00:00:00:00:01" > +#define FWD0_MAC "00:00:00:00:00:02" > +#define FWD1_MAC "00:00:00:00:01:01" > +#define DST_MAC "00:00:00:00:01:02" > + > +#define LOCAL_ADDR "10.0.0.1" > +#define FWD0_ADDR "10.0.0.2" > +#define FWD1_ADDR "20.0.0.1" > +#define DST_ADDR "20.0.0.2" > + > +#define PREFIX_LEN "8" > +#define NUM_PACKETS 10 > + > +static int run_ping(const char *dst, int num_ping) > +{ > + SYS(fail, "ping -c%d -W1 -i0.5 %s >/dev/null", num_ping, dst); > + return 0; > +fail: > + return -1; > +} > + > +void test_xdp_rxmeta(void) > +{ > + struct xdp_rxmeta_redirect *skel_redirect = NULL; > + struct xdp_rxmeta_receiver *skel_receiver = NULL; > + struct bpf_devmap_val val = {}; > + struct nstoken *tok = NULL; > + struct bpf_program *prog; > + __u32 key = 0, stats; > + int ret, index; > + > + SYS(out, "ip netns add " LOCAL_NETNS_NAME); > + SYS(out, "ip netns add " FWD_NETNS_NAME); > + SYS(out, "ip netns add " DST_NETNS_NAME); > + > + tok = open_netns(LOCAL_NETNS_NAME); > + if (!ASSERT_OK_PTR(tok, "setns")) > + goto out; > + > + SYS(out, "ip link add " LOCAL_NAME " type veth peer " FWD0_NAME); > + SYS(out, "ip link set " FWD0_NAME " netns " FWD_NETNS_NAME); > + SYS(out, "ip link set dev " LOCAL_NAME " address " LOCAL_MAC); > + SYS(out, "ip addr add " LOCAL_ADDR "/" PREFIX_LEN " dev " > LOCAL_NAME); > + SYS(out, "ip link set dev " LOCAL_NAME " up"); > + SYS(out, "ip route add default via " FWD0_ADDR); > + close_netns(tok); > + > + tok = open_netns(DST_NETNS_NAME); > + if (!ASSERT_OK_PTR(tok, "setns")) > + goto out; > + > + SYS(out, "ip link add " DST_NAME " type veth peer " FWD1_NAME); > + SYS(out, "ip link set " FWD1_NAME " netns " FWD_NETNS_NAME); > + SYS(out, "ip link set dev " DST_NAME " address " DST_MAC); > + SYS(out, "ip addr add " DST_ADDR "/" PREFIX_LEN " dev " DST_NAME); > + SYS(out, "ip link set dev " DST_NAME " up"); > + SYS(out, "ip route add default via " FWD1_ADDR); > + > + skel_receiver = xdp_rxmeta_receiver__open(); > + if (!ASSERT_OK_PTR(skel_receiver, "open skel_receiver")) > + goto out; > + > + prog = bpf_object__find_program_by_name(skel_receiver->obj, > + "xdp_rxmeta_receiver"); > + index = if_nametoindex(DST_NAME); > + bpf_program__set_ifindex(prog, index); > + bpf_program__set_flags(prog, BPF_F_XDP_DEV_BOUND_ONLY); > + > + if (!ASSERT_OK(xdp_rxmeta_receiver__load(skel_receiver), > + "load skel_receiver")) > + goto out; > + > + ret = bpf_xdp_attach(index, > + bpf_program__fd(skel_receiver- > >progs.xdp_rxmeta_receiver), > + XDP_FLAGS_DRV_MODE, NULL); > + if (!ASSERT_GE(ret, 0, "bpf_xdp_attach rx_meta_redirect")) > + goto out; > + > + close_netns(tok); > + tok = open_netns(FWD_NETNS_NAME); > + if (!ASSERT_OK_PTR(tok, "setns")) > + goto out; > + > + SYS(out, "ip link set dev " FWD0_NAME " address " FWD0_MAC); > + SYS(out, "ip addr add " FWD0_ADDR "/" PREFIX_LEN " dev " > FWD0_NAME); > + SYS(out, "ip link set dev " FWD0_NAME " up"); > + > + SYS(out, "ip link set dev " FWD1_NAME " address " FWD1_MAC); > + SYS(out, "ip addr add " FWD1_ADDR "/" PREFIX_LEN " dev " > FWD1_NAME); > + SYS(out, "ip link set dev " FWD1_NAME " up"); > + > + SYS(out, "sysctl -qw net.ipv4.conf.all.forwarding=1"); > + > + skel_redirect = xdp_rxmeta_redirect__open(); > + if (!ASSERT_OK_PTR(skel_redirect, "open skel_redirect")) > + goto out; > + > + prog = bpf_object__find_program_by_name(skel_redirect->obj, > + "xdp_rxmeta_redirect"); > + index = if_nametoindex(FWD0_NAME); > + bpf_program__set_ifindex(prog, index); > + bpf_program__set_flags(prog, BPF_F_XDP_DEV_BOUND_ONLY); > + > + if (!ASSERT_OK(xdp_rxmeta_redirect__load(skel_redirect), > + "load skel_redirect")) > + goto out; > + > + val.ifindex = if_nametoindex(FWD1_NAME); > + ret = bpf_map_update_elem(bpf_map__fd(skel_redirect->maps.dev_map), > + &key, &val, 0); > + if (!ASSERT_GE(ret, 0, "bpf_map_update_elem")) > + goto out; > + > + ret = bpf_xdp_attach(index, > + bpf_program__fd(skel_redirect- > >progs.xdp_rxmeta_redirect), > + XDP_FLAGS_DRV_MODE, NULL); > + if (!ASSERT_GE(ret, 0, "bpf_xdp_attach rxmeta_redirect")) > + goto out; > + > + close_netns(tok); > + tok = open_netns(LOCAL_NETNS_NAME); > + if (!ASSERT_OK_PTR(tok, "setns")) > + goto out; > + > + if (!ASSERT_OK(run_ping(DST_ADDR, NUM_PACKETS), "ping")) > + goto out; > + > + close_netns(tok); > + tok = open_netns(DST_NETNS_NAME); > + if (!ASSERT_OK_PTR(tok, "setns")) > + goto out; > + > + ret = bpf_map__lookup_elem(skel_receiver->maps.stats, > + &key, sizeof(key), > + &stats, sizeof(stats), 0); > + if (!ASSERT_GE(ret, 0, "bpf_map_update_elem")) This should have "bpf_map__lookup_elem" instead of "bpf_map_update_elem". > + goto out; > + > + ASSERT_EQ(stats, NUM_PACKETS, "rx_meta stats"); > +out: > + xdp_rxmeta_redirect__destroy(skel_redirect); > + xdp_rxmeta_receiver__destroy(skel_receiver); > + if (tok) > + close_netns(tok); > + SYS_NOFAIL("ip netns del " LOCAL_NETNS_NAME); > + SYS_NOFAIL("ip netns del " FWD_NETNS_NAME); > + SYS_NOFAIL("ip netns del " DST_NETNS_NAME); > +} > diff --git a/tools/testing/selftests/bpf/progs/xdp_rxmeta_receiver.c > b/tools/testing/selftests/bpf/progs/xdp_rxmeta_receiver.c > new file mode 100644 > index 000000000000..1033fa558970 > --- /dev/null > +++ b/tools/testing/selftests/bpf/progs/xdp_rxmeta_receiver.c > @@ -0,0 +1,44 @@ > +// SPDX-License-Identifier: GPL-2.0 > +#define BPF_NO_KFUNC_PROTOTYPES > +#include <vmlinux.h> > +#include <bpf/bpf_helpers.h> > +#include <bpf/bpf_endian.h> > + > +extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, __u32 *hash, > + enum xdp_rss_hash_type *rss_type) __ksym; > +extern int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, > + __u64 *timestamp) __ksym; > + > +#define RX_TIMESTAMP 0x12345678 > +#define RX_HASH 0x1234 > + > +struct { > + __uint(type, BPF_MAP_TYPE_ARRAY); > + __type(key, __u32); > + __type(value, __u32); > + __uint(max_entries, 1); > +} stats SEC(".maps"); > + > +SEC("xdp") > +int xdp_rxmeta_receiver(struct xdp_md *ctx) > +{ > + enum xdp_rss_hash_type rss_type; > + __u64 timestamp; > + __u32 hash; > + > + if (!bpf_xdp_metadata_rx_hash(ctx, &hash, &rss_type) && > + !bpf_xdp_metadata_rx_timestamp(ctx, ×tamp)) { > + if (hash == RX_HASH && rss_type == XDP_RSS_L4_TCP && > + timestamp == RX_TIMESTAMP) { > + __u32 *val, key = 0; > + > + val = bpf_map_lookup_elem(&stats, &key); > + if (val) > + __sync_add_and_fetch(val, 1); > + } > + } > + > + return XDP_PASS; > +} > + > +char _license[] SEC("license") = "GPL"; > diff --git a/tools/testing/selftests/bpf/progs/xdp_rxmeta_redirect.c > b/tools/testing/selftests/bpf/progs/xdp_rxmeta_redirect.c > new file mode 100644 > index 000000000000..635cbae64f53 > --- /dev/null > +++ b/tools/testing/selftests/bpf/progs/xdp_rxmeta_redirect.c > @@ -0,0 +1,43 @@ > +// SPDX-License-Identifier: GPL-2.0 > +#include <vmlinux.h> > +#include <bpf/bpf_helpers.h> > +#include <bpf/bpf_endian.h> > + > +#define RX_TIMESTAMP 0x12345678 > +#define RX_HASH 0x1234 > + > +#define ETH_ALEN 6 > +#define ETH_P_IP 0x0800 > + > +struct { > + __uint(type, BPF_MAP_TYPE_DEVMAP); > + __uint(key_size, sizeof(__u32)); > + __uint(value_size, sizeof(struct bpf_devmap_val)); > + __uint(max_entries, 1); > +} dev_map SEC(".maps"); > + > +SEC("xdp") > +int xdp_rxmeta_redirect(struct xdp_md *ctx) > +{ > + __u8 src_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x01 }; > + __u8 dst_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x02 }; > + void *data_end = (void *)(long)ctx->data_end; > + void *data = (void *)(long)ctx->data; > + struct ethhdr *eh = data; > + > + if (eh + 1 > (struct ethhdr *)data_end) > + return XDP_DROP; > + > + if (eh->h_proto != bpf_htons(ETH_P_IP)) > + return XDP_PASS; > + > + __builtin_memcpy(eh->h_source, src_mac, ETH_ALEN); > + __builtin_memcpy(eh->h_dest, dst_mac, ETH_ALEN); > + > + bpf_xdp_store_rx_hash(ctx, RX_HASH, XDP_RSS_L4_TCP); > + bpf_xdp_store_rx_ts(ctx, RX_TIMESTAMP); > + > + return bpf_redirect_map(&dev_map, ctx->rx_queue_index, XDP_PASS); > +} > + > +char _license[] SEC("license") = "GPL"; > > Best regards, Zdenek Bouska -- Siemens, s.r.o Foundational Technologies