Skip to content

Commit ac6c62b

Browse files
alan-maguirekernel-patches-bot
authored andcommitted
selftests/bpf: add test for bpf_seq_printf_btf helper
Add a test verifying iterating over tasks and displaying BTF representation of task_struct succeeds. Suggested-by: Alexei Starovoitov <[email protected]> Signed-off-by: Alan Maguire <[email protected]>
1 parent 7d9dbca commit ac6c62b

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed

tools/testing/selftests/bpf/prog_tests/bpf_iter.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "bpf_iter_task.skel.h"
88
#include "bpf_iter_task_stack.skel.h"
99
#include "bpf_iter_task_file.skel.h"
10+
#include "bpf_iter_task_btf.skel.h"
1011
#include "bpf_iter_tcp4.skel.h"
1112
#include "bpf_iter_tcp6.skel.h"
1213
#include "bpf_iter_udp4.skel.h"
@@ -167,6 +168,77 @@ static void test_task_file(void)
167168
bpf_iter_task_file__destroy(skel);
168169
}
169170

171+
#define TASKBUFSZ 32768
172+
173+
static char taskbuf[TASKBUFSZ];
174+
175+
static void do_btf_read(struct bpf_iter_task_btf *skel)
176+
{
177+
struct bpf_program *prog = skel->progs.dump_task_struct;
178+
struct bpf_iter_task_btf__bss *bss = skel->bss;
179+
int iter_fd = -1, len = 0, bufleft = TASKBUFSZ;
180+
struct bpf_link *link;
181+
char *buf = taskbuf;
182+
183+
link = bpf_program__attach_iter(prog, NULL);
184+
if (CHECK(IS_ERR(link), "attach_iter", "attach_iter failed\n"))
185+
return;
186+
187+
iter_fd = bpf_iter_create(bpf_link__fd(link));
188+
if (CHECK(iter_fd < 0, "create_iter", "create_iter failed\n"))
189+
goto free_link;
190+
191+
do {
192+
len = read(iter_fd, buf, bufleft);
193+
if (len > 0) {
194+
buf += len;
195+
bufleft -= len;
196+
}
197+
} while (len > 0);
198+
199+
if (bss->skip) {
200+
printf("%s:SKIP:no __builtin_btf_type_id\n", __func__);
201+
test__skip();
202+
goto free_link;
203+
}
204+
205+
if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno)))
206+
goto free_link;
207+
208+
CHECK(strstr(taskbuf, "(struct task_struct)") == NULL,
209+
"check for btf representation of task_struct in iter data",
210+
"struct task_struct not found");
211+
free_link:
212+
if (iter_fd > 0)
213+
close(iter_fd);
214+
bpf_link__destroy(link);
215+
}
216+
217+
static void test_task_btf(void)
218+
{
219+
struct bpf_iter_task_btf__bss *bss;
220+
struct bpf_iter_task_btf *skel;
221+
222+
skel = bpf_iter_task_btf__open_and_load();
223+
if (CHECK(!skel, "bpf_iter_task_btf__open_and_load",
224+
"skeleton open_and_load failed\n"))
225+
return;
226+
227+
bss = skel->bss;
228+
229+
do_btf_read(skel);
230+
231+
if (CHECK(bss->tasks == 0, "check if iterated over tasks",
232+
"no task iteration, did BPF program run?\n"))
233+
goto cleanup;
234+
235+
CHECK(bss->seq_err != 0, "check for unexpected err",
236+
"bpf_seq_printf_btf returned %ld", bss->seq_err);
237+
238+
cleanup:
239+
bpf_iter_task_btf__destroy(skel);
240+
}
241+
170242
static void test_tcp4(void)
171243
{
172244
struct bpf_iter_tcp4 *skel;
@@ -957,6 +1029,8 @@ void test_bpf_iter(void)
9571029
test_task_stack();
9581030
if (test__start_subtest("task_file"))
9591031
test_task_file();
1032+
if (test__start_subtest("task_btf"))
1033+
test_task_btf();
9601034
if (test__start_subtest("tcp4"))
9611035
test_tcp4();
9621036
if (test__start_subtest("tcp6"))
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2020, Oracle and/or its affiliates. */
3+
#include "bpf_iter.h"
4+
#include <bpf/bpf_helpers.h>
5+
#include <bpf/bpf_tracing.h>
6+
#include <bpf/bpf_core_read.h>
7+
8+
#include <errno.h>
9+
10+
char _license[] SEC("license") = "GPL";
11+
12+
long tasks = 0;
13+
long seq_err = 0;
14+
bool skip = false;
15+
16+
SEC("iter/task")
17+
int dump_task_struct(struct bpf_iter__task *ctx)
18+
{
19+
struct seq_file *seq = ctx->meta->seq;
20+
struct task_struct *task = ctx->task;
21+
static struct btf_ptr ptr = { };
22+
long ret;
23+
24+
#if __has_builtin(__builtin_btf_type_id)
25+
ptr.type_id = bpf_core_type_id_kernel(struct task_struct);
26+
ptr.ptr = task;
27+
28+
if (ctx->meta->seq_num == 0)
29+
BPF_SEQ_PRINTF(seq, "Raw BTF task\n");
30+
31+
ret = bpf_seq_printf_btf(seq, &ptr, sizeof(ptr), 0);
32+
switch (ret) {
33+
case 0:
34+
tasks++;
35+
break;
36+
case -ERANGE:
37+
/* NULL task or task->fs, don't count it as an error. */
38+
break;
39+
case -E2BIG:
40+
return 1;
41+
default:
42+
seq_err = ret;
43+
break;
44+
}
45+
#else
46+
skip = true;
47+
#endif
48+
49+
return 0;
50+
}

0 commit comments

Comments
 (0)