On Tue, Jun 23, 2020 at 2:40 PM Lorenzo Bianconi <lorenzo@xxxxxxxxxx> wrote: > > Similar to what have been done for DEVMAP, introduce tests to verify > ability to add a XDP program to an entry in a CPUMAP. > Verify CPUMAP programs can not be attached to devices as a normal > XDP program, and only programs with BPF_XDP_CPUMAP attach type can > be loaded in a CPUMAP. > > Signed-off-by: Lorenzo Bianconi <lorenzo@xxxxxxxxxx> > --- > .../bpf/prog_tests/xdp_cpumap_attach.c | 70 +++++++++++++++++++ > .../bpf/progs/test_xdp_with_cpumap_helpers.c | 40 +++++++++++ > 2 files changed, 110 insertions(+) > create mode 100644 tools/testing/selftests/bpf/prog_tests/xdp_cpumap_attach.c > create mode 100644 tools/testing/selftests/bpf/progs/test_xdp_with_cpumap_helpers.c > > diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_cpumap_attach.c b/tools/testing/selftests/bpf/prog_tests/xdp_cpumap_attach.c > new file mode 100644 > index 000000000000..0176573fe4e7 > --- /dev/null > +++ b/tools/testing/selftests/bpf/prog_tests/xdp_cpumap_attach.c > @@ -0,0 +1,70 @@ > +// SPDX-License-Identifier: GPL-2.0 > +#include <uapi/linux/bpf.h> > +#include <linux/if_link.h> > +#include <test_progs.h> > + > +#include "test_xdp_with_cpumap_helpers.skel.h" > + > +#define IFINDEX_LO 1 > + > +void test_xdp_with_cpumap_helpers(void) > +{ > + struct test_xdp_with_cpumap_helpers *skel; > + struct bpf_prog_info info = {}; > + struct bpf_cpumap_val val = { > + .qsize = 192, > + }; > + __u32 duration = 0, idx = 0; > + __u32 len = sizeof(info); > + int err, prog_fd, map_fd; > + > + skel = test_xdp_with_cpumap_helpers__open_and_load(); > + if (CHECK_FAIL(!skel)) { > + perror("test_xdp_with_cpumap_helpers__open_and_load"); > + return; > + } > + > + /* can not attach program with cpumaps that allow programs > + * as xdp generic > + */ > + prog_fd = bpf_program__fd(skel->progs.xdp_redir_prog); > + err = bpf_set_link_xdp_fd(IFINDEX_LO, prog_fd, XDP_FLAGS_SKB_MODE); > + CHECK(err == 0, "Generic attach of program with 8-byte CPUMAP", > + "should have failed\n"); > + > + prog_fd = bpf_program__fd(skel->progs.xdp_dummy_cm); > + map_fd = bpf_map__fd(skel->maps.cpu_map); > + err = bpf_obj_get_info_by_fd(prog_fd, &info, &len); > + if (CHECK_FAIL(err)) > + goto out_close; > + > + val.bpf_prog.fd = prog_fd; > + err = bpf_map_update_elem(map_fd, &idx, &val, 0); > + CHECK(err, "Add program to cpumap entry", "err %d errno %d\n", > + err, errno); > + > + err = bpf_map_lookup_elem(map_fd, &idx, &val); > + CHECK(err, "Read cpumap entry", "err %d errno %d\n", err, errno); > + CHECK(info.id != val.bpf_prog.id, "Expected program id in cpumap entry", > + "expected %u read %u\n", info.id, val.bpf_prog.id); > + > + /* can not attach BPF_XDP_CPUMAP program to a device */ > + err = bpf_set_link_xdp_fd(IFINDEX_LO, prog_fd, XDP_FLAGS_SKB_MODE); > + CHECK(err == 0, "Attach of BPF_XDP_CPUMAP program", > + "should have failed\n"); > + > + val.qsize = 192; > + val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_dummy_prog); > + err = bpf_map_update_elem(map_fd, &idx, &val, 0); > + CHECK(err == 0, "Add non-BPF_XDP_CPUMAP program to cpumap entry", > + "should have failed\n"); > + > +out_close: > + test_xdp_with_cpumap_helpers__destroy(skel); > +} > + > +void test_xdp_cpumap_attach(void) > +{ > + if (test__start_subtest("cpumap_with_progs")) > + test_xdp_with_cpumap_helpers(); > +} > diff --git a/tools/testing/selftests/bpf/progs/test_xdp_with_cpumap_helpers.c b/tools/testing/selftests/bpf/progs/test_xdp_with_cpumap_helpers.c > new file mode 100644 > index 000000000000..861848d0c353 > --- /dev/null > +++ b/tools/testing/selftests/bpf/progs/test_xdp_with_cpumap_helpers.c > @@ -0,0 +1,40 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#include <linux/bpf.h> > +#include <bpf/bpf_helpers.h> > + > +static __u32 ingress_ifindex; > + > +struct { > + __uint(type, BPF_MAP_TYPE_CPUMAP); > + __uint(key_size, sizeof(__u32)); > + __uint(value_size, sizeof(struct bpf_cpumap_val)); > + __uint(max_entries, 4); > +} cpu_map SEC(".maps"); > + > +SEC("xdp_redir") > +int xdp_redir_prog(struct xdp_md *ctx) > +{ > + return bpf_redirect_map(&cpu_map, 1, 0); > +} > + > +SEC("xdp_dummy") > +int xdp_dummy_prog(struct xdp_md *ctx) > +{ > + return XDP_PASS; > +} > + > +SEC("xdp_cpumap/dummy_cm") > +int xdp_dummy_cm(struct xdp_md *ctx) > +{ > + char fmt[] = "devmap redirect: dev %u len %u\n"; > + void *data_end = (void *)(long)ctx->data_end; > + void *data = (void *)(long)ctx->data; > + unsigned int len = data_end - data; > + > + ingress_ifindex = ctx->ingress_ifindex; Have you checked the generated BPF assembly to verify ctx->ingress_ifindex is actually read? ingress_ifindex variable is declared static, so I'm guessing Clang just optimized it away. If you want to be sure this actually gets executed, make ingress_ifindex global var. > + > + return XDP_PASS; > +} > + > +char _license[] SEC("license") = "GPL"; > -- > 2.26.2 >