Skip to content

Commit d2fc695

Browse files
namhyungNobody
authored and
Nobody
committed
bpf/selftests: 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 <[email protected]>
1 parent a239f4d commit d2fc695

File tree

2 files changed

+154
-0
lines changed

2 files changed

+154
-0
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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 control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd;
11+
int err, stack_trace_len;
12+
__u32 key, val, duration = 0;
13+
14+
skel = stacktrace_map_skip__open_and_load();
15+
if (CHECK(!skel, "skel_open_and_load", "skeleton open failed\n"))
16+
return;
17+
18+
/* find map fds */
19+
control_map_fd = bpf_map__fd(skel->maps.control_map);
20+
if (CHECK_FAIL(control_map_fd < 0))
21+
goto out;
22+
23+
stackid_hmap_fd = bpf_map__fd(skel->maps.stackid_hmap);
24+
if (CHECK_FAIL(stackid_hmap_fd < 0))
25+
goto out;
26+
27+
stackmap_fd = bpf_map__fd(skel->maps.stackmap);
28+
if (CHECK_FAIL(stackmap_fd < 0))
29+
goto out;
30+
31+
stack_amap_fd = bpf_map__fd(skel->maps.stack_amap);
32+
if (CHECK_FAIL(stack_amap_fd < 0))
33+
goto out;
34+
35+
err = stacktrace_map_skip__attach(skel);
36+
if (CHECK(err, "skel_attach", "skeleton attach failed\n"))
37+
goto out;
38+
39+
/* give some time for bpf program run */
40+
sleep(1);
41+
42+
/* disable stack trace collection */
43+
key = 0;
44+
val = 1;
45+
bpf_map_update_elem(control_map_fd, &key, &val, 0);
46+
47+
/* for every element in stackid_hmap, we can find a corresponding one
48+
* in stackmap, and vise versa.
49+
*/
50+
err = compare_map_keys(stackid_hmap_fd, stackmap_fd);
51+
if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap",
52+
"err %d errno %d\n", err, errno))
53+
goto out;
54+
55+
err = compare_map_keys(stackmap_fd, stackid_hmap_fd);
56+
if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap",
57+
"err %d errno %d\n", err, errno))
58+
goto out;
59+
60+
stack_trace_len = TEST_STACK_DEPTH * sizeof(__u64);
61+
err = compare_stack_ips(stackmap_fd, stack_amap_fd, stack_trace_len);
62+
if (CHECK(err, "compare_stack_ips stackmap vs. stack_amap",
63+
"err %d errno %d\n", err, errno))
64+
goto out;
65+
66+
if (CHECK(skel->bss->failed, "check skip",
67+
"failed to skip some depth: %d", skel->bss->failed))
68+
goto out;
69+
70+
out:
71+
stacktrace_map_skip__destroy(skel);
72+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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+
7+
struct {
8+
__uint(type, BPF_MAP_TYPE_ARRAY);
9+
__uint(max_entries, 1);
10+
__type(key, __u32);
11+
__type(value, __u32);
12+
} control_map SEC(".maps");
13+
14+
struct {
15+
__uint(type, BPF_MAP_TYPE_HASH);
16+
__uint(max_entries, 16384);
17+
__type(key, __u32);
18+
__type(value, __u32);
19+
} stackid_hmap SEC(".maps");
20+
21+
typedef __u64 stack_trace_t[TEST_STACK_DEPTH];
22+
23+
struct {
24+
__uint(type, BPF_MAP_TYPE_STACK_TRACE);
25+
__uint(max_entries, 16384);
26+
__type(key, __u32);
27+
__type(value, stack_trace_t);
28+
} stackmap SEC(".maps");
29+
30+
struct {
31+
__uint(type, BPF_MAP_TYPE_ARRAY);
32+
__uint(max_entries, 16384);
33+
__type(key, __u32);
34+
__type(value, stack_trace_t);
35+
} stack_amap SEC(".maps");
36+
37+
/* taken from /sys/kernel/debug/tracing/events/sched/sched_switch/format */
38+
struct sched_switch_args {
39+
unsigned long long pad;
40+
char prev_comm[TASK_COMM_LEN];
41+
int prev_pid;
42+
int prev_prio;
43+
long long prev_state;
44+
char next_comm[TASK_COMM_LEN];
45+
int next_pid;
46+
int next_prio;
47+
};
48+
49+
int failed = 0;
50+
51+
SEC("tracepoint/sched/sched_switch")
52+
int oncpu(struct sched_switch_args *ctx)
53+
{
54+
__u32 max_len = TEST_STACK_DEPTH * sizeof(__u64);
55+
__u32 key = 0, val = 0, *value_p;
56+
__u64 *stack_p;
57+
58+
value_p = bpf_map_lookup_elem(&control_map, &key);
59+
if (value_p && *value_p)
60+
return 0; /* skip if non-zero *value_p */
61+
62+
/* it should allow skipping whole buffer size entries */
63+
key = bpf_get_stackid(ctx, &stackmap, TEST_STACK_DEPTH);
64+
if ((int)key >= 0) {
65+
/* The size of stackmap and stack_amap should be the same */
66+
bpf_map_update_elem(&stackid_hmap, &key, &val, 0);
67+
stack_p = bpf_map_lookup_elem(&stack_amap, &key);
68+
if (stack_p) {
69+
bpf_get_stack(ctx, stack_p, max_len, TEST_STACK_DEPTH);
70+
/* it wrongly skipped all the entries and filled zero */
71+
if (stack_p[0] == 0)
72+
failed = 1;
73+
}
74+
} else if ((int)key == -14/*EFAULT*/) {
75+
/* old kernel doesn't support skipping that many entries */
76+
failed = 2;
77+
}
78+
79+
return 0;
80+
}
81+
82+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)