From: Toke Høiland-Jørgensen <toke@xxxxxxxxxx> This adds a simple selftest that combines two XDP programs through a third dispatcher, exercising the libbpf function externals handling. Signed-off-by: Toke Høiland-Jørgensen <toke@xxxxxxxxxx> --- .../selftests/bpf/prog_tests/xdp_multiprog.c | 52 ++++++++++++++++++++ tools/testing/selftests/bpf/progs/xdp_drop.c | 13 +++++ tools/testing/selftests/bpf/progs/xdp_multiprog.c | 26 ++++++++++ 3 files changed, 91 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/xdp_multiprog.c create mode 100644 tools/testing/selftests/bpf/progs/xdp_drop.c create mode 100644 tools/testing/selftests/bpf/progs/xdp_multiprog.c diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_multiprog.c b/tools/testing/selftests/bpf/prog_tests/xdp_multiprog.c new file mode 100644 index 000000000000..40a743437222 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/xdp_multiprog.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <test_progs.h> + +void test_xdp_multiprog(void) +{ + const char *file_dispatcher = "./xdp_multiprog.o"; + const char *file_drop = "./xdp_drop.o"; + const char *file_pass = "./xdp_dummy.o"; + struct bpf_object *obj, *obj_drop, *obj_pass; + int err; + + + obj = bpf_object__open_file(file_dispatcher, NULL); + err = libbpf_get_error(obj); + if (CHECK_FAIL(err)) + return; + + obj_drop = bpf_object__open_file(file_drop, NULL); + err = libbpf_get_error(obj_drop); + if (CHECK_FAIL(err)) + goto out_obj; + + obj_pass = bpf_object__open_file(file_pass, NULL); + err = libbpf_get_error(obj_pass); + if (CHECK_FAIL(err)) + goto out_drop; + + err = bpf_object__load(obj_drop); + err = err ?: bpf_object__load(obj_pass); + + if (CHECK_FAIL(err)) + goto out; + + struct bpf_extern_call_tgt tgts[] = + { + {.name = "prog1", .tgt_prog_name = "xdp_dummy_prog", .tgt_obj = obj_pass}, + {.name = "prog2", .tgt_prog_name = "xdp_drop_prog", .tgt_obj = obj_drop}, + }; + struct bpf_extern_calls calls = {.num_tgts = 2, .tgts = tgts }; + + DECLARE_LIBBPF_OPTS(bpf_object_load_opts, load_opts, + .ext_calls = &calls); + + err = bpf_object__load2(obj, &load_opts); + CHECK_FAIL(err); +out: + bpf_object__close(obj_pass); +out_drop: + bpf_object__close(obj_drop); +out_obj: + bpf_object__close(obj); +} diff --git a/tools/testing/selftests/bpf/progs/xdp_drop.c b/tools/testing/selftests/bpf/progs/xdp_drop.c new file mode 100644 index 000000000000..10e415e49564 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/xdp_drop.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define KBUILD_MODNAME "xdp_drop" +#include <linux/bpf.h> +#include "bpf_helpers.h" + +SEC("xdp_drop") +int xdp_drop_prog(struct xdp_md *ctx) +{ + return XDP_DROP; +} + +char _license[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/bpf/progs/xdp_multiprog.c b/tools/testing/selftests/bpf/progs/xdp_multiprog.c new file mode 100644 index 000000000000..ef5ba8172038 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/xdp_multiprog.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define KBUILD_MODNAME "xdp_multiprog" +#include <linux/bpf.h> +#include "bpf_helpers.h" + +extern int prog1(struct xdp_md *ctx); +extern int prog2(struct xdp_md *ctx); + +SEC("xdp_test") +int xdp_main(struct xdp_md *ctx) +{ + int ret; + + ret = prog1(ctx); + if (ret != XDP_PASS) + goto out; + + ret = prog2(ctx); + if (ret != XDP_DROP) + goto out; +out: + return ret; +} + +char _license[] SEC("license") = "GPL";