Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Test skipping stacktrace

Add a test case for stacktrace with skip > 0 using a small sized
buffer. It didn't support skipping entries greater than or equal to
the size of buffer and filled the skipped part with 0.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Yonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/bpf/20220314182042.71025-2-namhyung@kernel.org

authored by

Namhyung Kim and committed by
Alexei Starovoitov
e1cc1f39 ee2a0988

+131
+63
tools/testing/selftests/bpf/prog_tests/stacktrace_map_skip.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <test_progs.h> 3 + #include "stacktrace_map_skip.skel.h" 4 + 5 + #define TEST_STACK_DEPTH 2 6 + 7 + void test_stacktrace_map_skip(void) 8 + { 9 + struct stacktrace_map_skip *skel; 10 + int stackid_hmap_fd, stackmap_fd, stack_amap_fd; 11 + int err, stack_trace_len; 12 + 13 + skel = stacktrace_map_skip__open_and_load(); 14 + if (!ASSERT_OK_PTR(skel, "skel_open_and_load")) 15 + return; 16 + 17 + /* find map fds */ 18 + stackid_hmap_fd = bpf_map__fd(skel->maps.stackid_hmap); 19 + if (!ASSERT_GE(stackid_hmap_fd, 0, "stackid_hmap fd")) 20 + goto out; 21 + 22 + stackmap_fd = bpf_map__fd(skel->maps.stackmap); 23 + if (!ASSERT_GE(stackmap_fd, 0, "stackmap fd")) 24 + goto out; 25 + 26 + stack_amap_fd = bpf_map__fd(skel->maps.stack_amap); 27 + if (!ASSERT_GE(stack_amap_fd, 0, "stack_amap fd")) 28 + goto out; 29 + 30 + skel->bss->pid = getpid(); 31 + 32 + err = stacktrace_map_skip__attach(skel); 33 + if (!ASSERT_OK(err, "skel_attach")) 34 + goto out; 35 + 36 + /* give some time for bpf program run */ 37 + sleep(1); 38 + 39 + /* disable stack trace collection */ 40 + skel->bss->control = 1; 41 + 42 + /* for every element in stackid_hmap, we can find a corresponding one 43 + * in stackmap, and vise versa. 44 + */ 45 + err = compare_map_keys(stackid_hmap_fd, stackmap_fd); 46 + if (!ASSERT_OK(err, "compare_map_keys stackid_hmap vs. stackmap")) 47 + goto out; 48 + 49 + err = compare_map_keys(stackmap_fd, stackid_hmap_fd); 50 + if (!ASSERT_OK(err, "compare_map_keys stackmap vs. stackid_hmap")) 51 + goto out; 52 + 53 + stack_trace_len = TEST_STACK_DEPTH * sizeof(__u64); 54 + err = compare_stack_ips(stackmap_fd, stack_amap_fd, stack_trace_len); 55 + if (!ASSERT_OK(err, "compare_stack_ips stackmap vs. stack_amap")) 56 + goto out; 57 + 58 + if (!ASSERT_EQ(skel->bss->failed, 0, "skip_failed")) 59 + goto out; 60 + 61 + out: 62 + stacktrace_map_skip__destroy(skel); 63 + }
+68
tools/testing/selftests/bpf/progs/stacktrace_map_skip.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <vmlinux.h> 3 + #include <bpf/bpf_helpers.h> 4 + 5 + #define TEST_STACK_DEPTH 2 6 + #define TEST_MAX_ENTRIES 16384 7 + 8 + typedef __u64 stack_trace_t[TEST_STACK_DEPTH]; 9 + 10 + struct { 11 + __uint(type, BPF_MAP_TYPE_STACK_TRACE); 12 + __uint(max_entries, TEST_MAX_ENTRIES); 13 + __type(key, __u32); 14 + __type(value, stack_trace_t); 15 + } stackmap SEC(".maps"); 16 + 17 + struct { 18 + __uint(type, BPF_MAP_TYPE_HASH); 19 + __uint(max_entries, TEST_MAX_ENTRIES); 20 + __type(key, __u32); 21 + __type(value, __u32); 22 + } stackid_hmap SEC(".maps"); 23 + 24 + struct { 25 + __uint(type, BPF_MAP_TYPE_ARRAY); 26 + __uint(max_entries, TEST_MAX_ENTRIES); 27 + __type(key, __u32); 28 + __type(value, stack_trace_t); 29 + } stack_amap SEC(".maps"); 30 + 31 + int pid = 0; 32 + int control = 0; 33 + int failed = 0; 34 + 35 + SEC("tracepoint/sched/sched_switch") 36 + int oncpu(struct trace_event_raw_sched_switch *ctx) 37 + { 38 + __u32 max_len = TEST_STACK_DEPTH * sizeof(__u64); 39 + __u32 key = 0, val = 0; 40 + __u64 *stack_p; 41 + 42 + if (pid != (bpf_get_current_pid_tgid() >> 32)) 43 + return 0; 44 + 45 + if (control) 46 + return 0; 47 + 48 + /* it should allow skipping whole buffer size entries */ 49 + key = bpf_get_stackid(ctx, &stackmap, TEST_STACK_DEPTH); 50 + if ((int)key >= 0) { 51 + /* The size of stackmap and stack_amap should be the same */ 52 + bpf_map_update_elem(&stackid_hmap, &key, &val, 0); 53 + stack_p = bpf_map_lookup_elem(&stack_amap, &key); 54 + if (stack_p) { 55 + bpf_get_stack(ctx, stack_p, max_len, TEST_STACK_DEPTH); 56 + /* it wrongly skipped all the entries and filled zero */ 57 + if (stack_p[0] == 0) 58 + failed = 1; 59 + } 60 + } else { 61 + /* old kernel doesn't support skipping that many entries */ 62 + failed = 2; 63 + } 64 + 65 + return 0; 66 + } 67 + 68 + char _license[] SEC("license") = "GPL";