[RFC PATCH bpf-next 13/13] selftests/bpf: Add selftest for bpf namespace

From: Yafang Shao
Date: Sun Mar 26 2023 - 05:23:14 EST


A simple test case is added for the newly introduced bpf namespcae.

Signed-off-by: Yafang Shao <laoar.shao@xxxxxxxxx>
---
tools/testing/selftests/bpf/Makefile | 3 +-
tools/testing/selftests/bpf/test_bpfns.c | 76 ++++++++++++++++++++++++++++++++
2 files changed, 78 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/bpf/test_bpfns.c

diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 4a8ef11..55f0aeb 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -40,7 +40,7 @@ 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_bpfns

# Also test bpf-gcc, if present
ifneq ($(BPF_GCC),)
@@ -255,6 +255,7 @@ $(OUTPUT)/flow_dissector_load: $(TESTING_HELPERS)
$(OUTPUT)/test_maps: $(TESTING_HELPERS)
$(OUTPUT)/test_verifier: $(TESTING_HELPERS) $(CAP_HELPERS) $(UNPRIV_HELPERS)
$(OUTPUT)/xsk.o: $(BPFOBJ)
+$(OUTPUT)/test_bpfns: $(TESTING_HELPERS)

BPFTOOL ?= $(DEFAULT_BPFTOOL)
$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \
diff --git a/tools/testing/selftests/bpf/test_bpfns.c b/tools/testing/selftests/bpf/test_bpfns.c
new file mode 100644
index 0000000..7baebe2
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_bpfns.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+#include <unistd.h>
+#include <errno.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/syscall.h>
+#include <sys/wait.h>
+#include <linux/sched.h>
+
+#include <bpf/bpf.h>
+#include <bpf/libbpf.h>
+
+static int create_bpf_map(const char *name)
+{
+ static struct bpf_map_create_opts map_opts = {
+ .sz = sizeof(map_opts),
+ };
+ unsigned int value;
+ unsigned int key;
+ int map_fd;
+
+ map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, name, sizeof(key),
+ sizeof(value), 1, &map_opts);
+ if (map_fd < 0)
+ fprintf(stderr, "%s - Failed to create map\n", strerror(errno));
+ return map_fd;
+}
+
+
+int main(int argc, char *argv[])
+{
+ struct bpf_map_info info = {};
+ __u32 info_len = sizeof(info);
+ struct clone_args args = {
+ .flags = 0x400000000ULL, /* CLONE_NEWBPF */
+ .exit_signal = SIGCHLD,
+ };
+ int map_fd, child_map_fd;
+ pid_t pid;
+
+ /* Create a map in init bpf namespace. */
+ map_fd = create_bpf_map("map_in_init");
+ if (map_fd < 0)
+ exit(EXIT_FAILURE);
+ pid = syscall(__NR_clone3, &args, sizeof(struct clone_args));
+ if (pid < 0) {
+ fprintf(stderr, "%s - Failed to create new process\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if (pid == 0) {
+ struct bpf_map_info info = {};
+
+ /* In a new bpf namespace, it is the first map. */
+ child_map_fd = create_bpf_map("map_in_bpfns");
+ if (child_map_fd < 0)
+ exit(EXIT_FAILURE);
+ bpf_obj_get_info_by_fd(child_map_fd, &info, &info_len);
+ assert(info.id == 1);
+ exit(EXIT_SUCCESS);
+ }
+
+ if (waitpid(pid, NULL, 0) != pid) {
+ fprintf(stderr, "Failed to wait on child process\n");
+ exit(EXIT_FAILURE);
+ }
+
+ return 0;
+}
--
1.8.3.1