From: "Mauricio Vásquez" <mauricio@kinvolk.io>
To: netdev@vger.kernel.org, bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Quentin Monnet <quentin@isovalent.com>,
Rafael David Tinoco <rafaeldtinoco@gmail.com>,
Lorenzo Fontana <lorenzo.fontana@elastic.co>,
Leonardo Di Donato <leonardo.didonato@elastic.co>
Subject: [PATCH bpf-next v5 9/9] selftest/bpf: Implement tests for bpftool gen min_core_btf
Date: Fri, 28 Jan 2022 17:33:12 -0500 [thread overview]
Message-ID: <20220128223312.1253169-10-mauricio@kinvolk.io> (raw)
In-Reply-To: <20220128223312.1253169-1-mauricio@kinvolk.io>
This commit implements some integration tests for "BTFGen". The goal
of such tests is to verify that the generated BTF file contains the
expected types.
Signed-off-by: Mauricio Vásquez <mauricio@kinvolk.io>
Signed-off-by: Rafael David Tinoco <rafael.tinoco@aquasec.com>
Signed-off-by: Lorenzo Fontana <lorenzo.fontana@elastic.co>
Signed-off-by: Leonardo Di Donato <leonardo.didonato@elastic.co>
---
tools/testing/selftests/bpf/.gitignore | 1 +
tools/testing/selftests/bpf/Makefile | 4 +-
.../selftests/bpf/progs/btfgen_btf_source.c | 12 +
.../bpf/progs/btfgen_primitives_array.c | 39 +++
.../bpf/progs/btfgen_primitives_struct.c | 40 +++
.../bpf/progs/btfgen_primitives_struct2.c | 44 ++++
.../bpf/progs/btfgen_primitives_union.c | 32 +++
tools/testing/selftests/bpf/test_bpftool.c | 228 ++++++++++++++++++
8 files changed, 399 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/bpf/progs/btfgen_btf_source.c
create mode 100644 tools/testing/selftests/bpf/progs/btfgen_primitives_array.c
create mode 100644 tools/testing/selftests/bpf/progs/btfgen_primitives_struct.c
create mode 100644 tools/testing/selftests/bpf/progs/btfgen_primitives_struct2.c
create mode 100644 tools/testing/selftests/bpf/progs/btfgen_primitives_union.c
create mode 100644 tools/testing/selftests/bpf/test_bpftool.c
diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore
index 1dad8d617da8..308cd5b9cfc4 100644
--- a/tools/testing/selftests/bpf/.gitignore
+++ b/tools/testing/selftests/bpf/.gitignore
@@ -41,3 +41,4 @@ test_cpp
*.tmp
xdpxceiver
xdp_redirect_multi
+test_bpftool
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 945f92d71db3..afc9bff6545d 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -38,7 +38,8 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test
test_sock test_sockmap get_cgroup_id_user \
test_cgroup_storage \
test_tcpnotify_user test_sysctl \
- test_progs-no_alu32
+ test_progs-no_alu32 \
+ test_bpftool
# Also test bpf-gcc, if present
ifneq ($(BPF_GCC),)
@@ -212,6 +213,7 @@ $(OUTPUT)/xdping: $(TESTING_HELPERS)
$(OUTPUT)/flow_dissector_load: $(TESTING_HELPERS)
$(OUTPUT)/test_maps: $(TESTING_HELPERS)
$(OUTPUT)/test_verifier: $(TESTING_HELPERS)
+$(OUTPUT)/test_bpftool:
BPFTOOL ?= $(DEFAULT_BPFTOOL)
$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \
diff --git a/tools/testing/selftests/bpf/progs/btfgen_btf_source.c b/tools/testing/selftests/bpf/progs/btfgen_btf_source.c
new file mode 100644
index 000000000000..772d5d1e2788
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/btfgen_btf_source.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "core_reloc_types.h"
+
+// structure made of primitive types
+void f0(struct core_reloc_primitives x) {}
+
+// union made of primite types
+void f1(union a_union x) {}
+
+// arrays
+void f2(struct core_reloc_arrays x) {}
diff --git a/tools/testing/selftests/bpf/progs/btfgen_primitives_array.c b/tools/testing/selftests/bpf/progs/btfgen_primitives_array.c
new file mode 100644
index 000000000000..aa514d1bcd96
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/btfgen_primitives_array.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <stdint.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_core_read.h>
+
+char _license[] SEC("license") = "GPL";
+
+struct {
+ char in[256];
+ char out[256];
+} data = {};
+
+struct core_reloc_arrays_substruct {
+ int c;
+ int d;
+};
+
+struct core_reloc_arrays {
+ int a[5];
+ char b[2][3][4];
+ struct core_reloc_arrays_substruct c[3];
+ struct core_reloc_arrays_substruct d[1][2];
+ struct core_reloc_arrays_substruct f[][2];
+};
+#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*(dst)), src)
+
+SEC("raw_tracepoint/sys_enter")
+int test_btfgen_primitives(void *ctx)
+{
+ struct core_reloc_arrays *in = (void *)&data.in;
+ struct core_reloc_arrays *out = (void *)&data.out;
+
+ if (CORE_READ(&out->a[0], &in->a[0]))
+ return 1;
+
+ return 0;
+}
diff --git a/tools/testing/selftests/bpf/progs/btfgen_primitives_struct.c b/tools/testing/selftests/bpf/progs/btfgen_primitives_struct.c
new file mode 100644
index 000000000000..b761d020fa4d
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/btfgen_primitives_struct.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <stdint.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_core_read.h>
+
+char _license[] SEC("license") = "GPL";
+
+struct {
+ char in[256];
+ char out[256];
+} data = {};
+
+enum core_reloc_primitives_enum {
+ A = 0,
+ B = 1,
+};
+
+struct core_reloc_primitives {
+ char a;
+ int b;
+ enum core_reloc_primitives_enum c;
+ void *d;
+ int (*f)(const char *);
+};
+
+#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*(dst)), src)
+
+SEC("raw_tracepoint/sys_enter")
+int test_btfgen_primitives(void *ctx)
+{
+ struct core_reloc_primitives *in = (void *)&data.in;
+ struct core_reloc_primitives *out = (void *)&data.out;
+
+ if (CORE_READ(&out->a, &in->a))
+ return 1;
+
+ return 0;
+}
diff --git a/tools/testing/selftests/bpf/progs/btfgen_primitives_struct2.c b/tools/testing/selftests/bpf/progs/btfgen_primitives_struct2.c
new file mode 100644
index 000000000000..fe67c9a24a7f
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/btfgen_primitives_struct2.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* This is almost the same as btfgen_primitives_struct.c but in this one
+ * a different field is accessed
+ */
+
+#include <linux/bpf.h>
+#include <stdint.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_core_read.h>
+
+char _license[] SEC("license") = "GPL";
+
+struct {
+ char in[256];
+ char out[256];
+} data = {};
+
+enum core_reloc_primitives_enum {
+ A = 0,
+ B = 1,
+};
+
+struct core_reloc_primitives {
+ char a;
+ int b;
+ enum core_reloc_primitives_enum c;
+ void *d;
+ int (*f)(const char *);
+};
+
+#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*(dst)), src)
+
+SEC("raw_tracepoint/sys_enter")
+int test_btfgen_primitives(void *ctx)
+{
+ struct core_reloc_primitives *in = (void *)&data.in;
+ struct core_reloc_primitives *out = (void *)&data.out;
+
+ if (CORE_READ(&out->b, &in->b))
+ return 1;
+
+ return 0;
+}
diff --git a/tools/testing/selftests/bpf/progs/btfgen_primitives_union.c b/tools/testing/selftests/bpf/progs/btfgen_primitives_union.c
new file mode 100644
index 000000000000..d4690c9e963c
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/btfgen_primitives_union.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <stdint.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_core_read.h>
+
+char _license[] SEC("license") = "GPL";
+
+struct {
+ char in[256];
+ char out[256];
+} data = {};
+
+union a_union {
+ int y;
+ int z;
+};
+
+#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*(dst)), src)
+
+SEC("raw_tracepoint/sys_enter")
+int test_btfgen_primitives(void *ctx)
+{
+ union a_union *in = (void *)&data.in;
+ union a_union *out = (void *)&data.out;
+
+ if (CORE_READ(&out->y, &in->y))
+ return 1;
+
+ return 0;
+}
diff --git a/tools/testing/selftests/bpf/test_bpftool.c b/tools/testing/selftests/bpf/test_bpftool.c
new file mode 100644
index 000000000000..ca7facc582d5
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_bpftool.c
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <linux/limits.h>
+
+#include <bpf/libbpf.h>
+#include <bpf/btf.h>
+
+#include "bpf_util.h"
+
+static int run_btfgen(const char *src_btf, const char *dst_btf, const char *objspaths[])
+{
+ char command[4096];
+ int ret, i, n;
+
+ n = snprintf(command, sizeof(command),
+ "./tools/build/bpftool/bpftool gen min_core_btf %s %s", src_btf, dst_btf);
+ assert(n >= 0 && n < sizeof(command));
+
+ for (i = 0; objspaths[i] != NULL; i++) {
+ assert(sizeof(command) - strlen(command) > strlen(objspaths[i]) + 1);
+ strcat(command, " ");
+ strcat(command, objspaths[i]);
+ }
+
+ printf("Executing bpftool: %s\n", command);
+ printf("---\n");
+ ret = system(command);
+ printf("---\n");
+ return ret;
+}
+
+struct btfgen_test {
+ const char *descr;
+ const char *src_btf;
+ const char *bpfobj[16];
+ void (*run_test)(struct btf *btf);
+};
+
+static void check_btfgen_primitive_struct(struct btf *btf)
+{
+ struct btf_member *members;
+ const struct btf_type *t;
+ int id;
+
+ assert(btf__type_cnt(btf) == 3);
+
+ id = btf__find_by_name_kind(btf, "core_reloc_primitives", BTF_KIND_STRUCT);
+ assert(id > 0);
+
+ t = btf__type_by_id(btf, id);
+ assert(btf_vlen(t) == 1);
+
+ members = btf_members(t);
+
+ id = btf__find_by_name_kind(btf, "char", BTF_KIND_INT);
+ assert(id > 0);
+
+ /* the type of the struct member must be the char */
+ assert(members[0].type == id);
+}
+
+static void check_btfgen_primitive_union(struct btf *btf)
+{
+ struct btf_member *members;
+ const struct btf_type *t;
+ int id;
+
+ /* void, a_union and int*/
+ assert(btf__type_cnt(btf) == 3);
+
+ id = btf__find_by_name_kind(btf, "a_union", BTF_KIND_UNION);
+ assert(id > 0);
+
+ t = btf__type_by_id(btf, id);
+ assert(btf_vlen(t) == 1);
+
+ members = btf_members(t);
+
+ id = btf__find_by_name_kind(btf, "int", BTF_KIND_INT);
+ assert(id > 0);
+
+ /* the type of the union member must be the integer */
+ assert(members[0].type == id);
+}
+
+static void check_btfgen_primitive_array(struct btf *btf)
+{
+ int array_id, array_type_id, array_index_type_id;
+ struct btf_array *array;
+
+ /* void, struct, array, int (array index type) and int (array type) */
+ assert(btf__type_cnt(btf) == 5);
+
+ array_id = btf__find_by_name_kind(btf, "", BTF_KIND_ARRAY);
+ assert(array_id > 0);
+
+ array = btf_array(btf__type_by_id(btf, array_id));
+
+ array_type_id = btf__find_by_name_kind(btf, "int", BTF_KIND_INT);
+ assert(array_type_id > 0);
+
+ array_index_type_id = btf__find_by_name_kind(btf, "__ARRAY_SIZE_TYPE__", BTF_KIND_INT);
+ assert(array_index_type_id > 0);
+
+ /* check that array types are the correct ones */
+ assert(array->type == array_type_id);
+ assert(array->index_type == array_index_type_id);
+}
+
+/* If there are relocations in two different BPF objects involving
+ * different members of the same struct, then the generated BTF should
+ * contain a single instance of such struct with both fields.
+ */
+static void check_btfgen_primitive_structs_different_objects(struct btf *btf)
+{
+ struct btf_member *members;
+ const struct btf_type *t;
+ int struct_id, char_id, int_id;
+
+ /* void, struct, int and char */
+ assert(btf__type_cnt(btf) == 4);
+
+ struct_id = btf__find_by_name_kind(btf, "core_reloc_primitives", BTF_KIND_STRUCT);
+ assert(struct_id > 0);
+
+ t = btf__type_by_id(btf, struct_id);
+ assert(btf_vlen(t) == 2);
+
+ members = btf_members(t);
+
+ char_id = btf__find_by_name_kind(btf, "char", BTF_KIND_INT);
+ assert(char_id > 0);
+
+ int_id = btf__find_by_name_kind(btf, "int", BTF_KIND_INT);
+ assert(int_id > 0);
+
+ for (int i = 0; i < btf_vlen(t); i++) {
+ const char *name = btf__str_by_offset(btf, members[i].name_off);
+
+ if (!strcmp("a", name))
+ assert(members[i].type == char_id);
+ else if (!strcmp("b", name))
+ assert(members[i].type == int_id);
+ }
+}
+
+static struct btfgen_test btfgen_tests[] = {
+ {
+ "primitive struct",
+ "btfgen_btf_source.o",
+ {
+ "btfgen_primitives_struct.o",
+ },
+ check_btfgen_primitive_struct,
+ },
+ {
+ "primitive union",
+ "btfgen_btf_source.o",
+ {
+ "btfgen_primitives_union.o",
+ },
+ check_btfgen_primitive_union,
+ },
+ {
+ "primitive array",
+ "btfgen_btf_source.o",
+ {
+ "btfgen_primitives_array.o",
+ },
+ check_btfgen_primitive_array,
+ },
+ {
+ "primitive structs in different objects",
+ "btfgen_btf_source.o",
+ {
+ "btfgen_primitives_struct.o",
+ "btfgen_primitives_struct2.o",
+ },
+ check_btfgen_primitive_structs_different_objects,
+ },
+};
+
+void test_gen_min_core_btf(void)
+{
+ char target_path[PATH_MAX];
+ struct btfgen_test *test;
+ struct btf *dst_btf;
+ int ret;
+
+ for (int i = 0; i < ARRAY_SIZE(btfgen_tests); i++) {
+ char dir_path[] = "/tmp/btfgen-XXXXXX";
+
+ test = &btfgen_tests[i];
+
+ printf("Running %s\n", test->descr);
+
+ mkdtemp(dir_path);
+
+ snprintf(target_path, sizeof(target_path), "%s/foo.btf", dir_path);
+
+ ret = run_btfgen(test->src_btf, target_path, test->bpfobj);
+ assert(ret == 0);
+
+ dst_btf = btf__parse(target_path, NULL);
+ assert(dst_btf != NULL);
+
+ test->run_test(dst_btf);
+
+ printf("Test %s: PASS\n", test->descr);
+ }
+
+ printf("%s: PASS\n", __func__);
+}
+
+int main(void)
+{
+ libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
+
+ test_gen_min_core_btf();
+
+ printf("test_bpftool: OK\n");
+
+ return 0;
+}
--
2.25.1
next prev parent reply other threads:[~2022-01-28 22:33 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-01-28 22:33 [PATCH bpf-next v5 0/9] libbpf: Implement BTFGen Mauricio Vásquez
2022-01-28 22:33 ` [PATCH bpf-next v5 1/9] libbpf: Implement changes needed for BTFGen in bpftool Mauricio Vásquez
2022-02-01 20:57 ` Quentin Monnet
2022-02-03 16:08 ` Mauricio Vásquez Bernal
2022-02-02 18:54 ` Andrii Nakryiko
2022-02-02 19:02 ` Andrii Nakryiko
2022-02-03 16:09 ` Mauricio Vásquez Bernal
2022-01-28 22:33 ` [PATCH bpf-next v5 2/9] bpftool: Add gen min_core_btf command Mauricio Vásquez
2022-02-02 17:58 ` Andrii Nakryiko
2022-02-03 16:07 ` Mauricio Vásquez Bernal
2022-02-03 17:21 ` Andrii Nakryiko
2022-01-28 22:33 ` [PATCH bpf-next v5 3/9] bpftool: Implement btf_save_raw() Mauricio Vásquez
2022-02-02 18:48 ` Andrii Nakryiko
2022-02-03 16:07 ` Mauricio Vásquez Bernal
2022-02-03 17:23 ` Andrii Nakryiko
2022-01-28 22:33 ` [PATCH bpf-next v5 4/9] bpftool: Add struct definitions and helpers for BTFGen Mauricio Vásquez
2022-02-02 18:54 ` Andrii Nakryiko
2022-02-03 16:08 ` Mauricio Vásquez Bernal
2022-02-03 17:24 ` Andrii Nakryiko
2022-01-28 22:33 ` [PATCH bpf-next v5 5/9] bpftool: Implement btfgen() Mauricio Vásquez
2022-02-01 20:57 ` Quentin Monnet
2022-02-03 19:10 ` Mauricio Vásquez Bernal
2022-02-02 19:14 ` Andrii Nakryiko
2022-02-03 16:09 ` Mauricio Vásquez Bernal
2022-01-28 22:33 ` [PATCH bpf-next v5 6/9] bpftool: Implement relocations recording for BTFGen Mauricio Vásquez
2022-02-02 19:31 ` Andrii Nakryiko
2022-02-03 16:40 ` Mauricio Vásquez Bernal
2022-02-03 17:30 ` Andrii Nakryiko
2022-02-04 6:20 ` Rafael David Tinoco
2022-02-04 18:41 ` Andrii Nakryiko
2022-02-02 22:55 ` Andrii Nakryiko
2022-02-04 19:44 ` Mauricio Vásquez Bernal
2022-01-28 22:33 ` [PATCH bpf-next v5 7/9] bpftool: Implement btfgen_get_btf() Mauricio Vásquez
2022-02-02 19:36 ` Andrii Nakryiko
2022-02-03 16:10 ` Mauricio Vásquez Bernal
2022-02-03 17:31 ` Andrii Nakryiko
2022-01-28 22:33 ` [PATCH bpf-next v5 8/9] bpftool: gen min_core_btf explanation and examples Mauricio Vásquez
2022-02-01 20:57 ` Quentin Monnet
2022-01-28 22:33 ` Mauricio Vásquez [this message]
2022-01-28 23:23 ` [PATCH bpf-next v5 9/9] selftest/bpf: Implement tests for bpftool gen min_core_btf Mauricio Vásquez Bernal
2022-02-01 20:58 ` Quentin Monnet
2022-02-02 19:50 ` Andrii Nakryiko
2022-02-03 21:17 ` Mauricio Vásquez Bernal
2022-02-04 20:05 ` Andrii Nakryiko
2022-02-01 20:57 ` Quentin Monnet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220128223312.1253169-10-mauricio@kinvolk.io \
--to=mauricio@kinvolk.io \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=leonardo.didonato@elastic.co \
--cc=lorenzo.fontana@elastic.co \
--cc=netdev@vger.kernel.org \
--cc=quentin@isovalent.com \
--cc=rafaeldtinoco@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).