]> Git Repo - J-linux.git/blob - tools/testing/selftests/bpf/prog_tests/bpf_loop.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / tools / testing / selftests / bpf / prog_tests / bpf_loop.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2021 Facebook */
3
4 #include <test_progs.h>
5 #include <network_helpers.h>
6 #include "bpf_loop.skel.h"
7
8 static void check_nr_loops(struct bpf_loop *skel)
9 {
10         struct bpf_link *link;
11
12         link = bpf_program__attach(skel->progs.test_prog);
13         if (!ASSERT_OK_PTR(link, "link"))
14                 return;
15
16         /* test 0 loops */
17         skel->bss->nr_loops = 0;
18
19         usleep(1);
20
21         ASSERT_EQ(skel->bss->nr_loops_returned, skel->bss->nr_loops,
22                   "0 loops");
23
24         /* test 500 loops */
25         skel->bss->nr_loops = 500;
26
27         usleep(1);
28
29         ASSERT_EQ(skel->bss->nr_loops_returned, skel->bss->nr_loops,
30                   "500 loops");
31         ASSERT_EQ(skel->bss->g_output, (500 * 499) / 2, "g_output");
32
33         /* test exceeding the max limit */
34         skel->bss->nr_loops = -1;
35
36         usleep(1);
37
38         ASSERT_EQ(skel->bss->err, -E2BIG, "over max limit");
39
40         bpf_link__destroy(link);
41 }
42
43 static void check_callback_fn_stop(struct bpf_loop *skel)
44 {
45         struct bpf_link *link;
46
47         link = bpf_program__attach(skel->progs.test_prog);
48         if (!ASSERT_OK_PTR(link, "link"))
49                 return;
50
51         /* testing that loop is stopped when callback_fn returns 1 */
52         skel->bss->nr_loops = 400;
53         skel->data->stop_index = 50;
54
55         usleep(1);
56
57         ASSERT_EQ(skel->bss->nr_loops_returned, skel->data->stop_index + 1,
58                   "nr_loops_returned");
59         ASSERT_EQ(skel->bss->g_output, (50 * 49) / 2,
60                   "g_output");
61
62         bpf_link__destroy(link);
63 }
64
65 static void check_null_callback_ctx(struct bpf_loop *skel)
66 {
67         struct bpf_link *link;
68
69         /* check that user is able to pass in a null callback_ctx */
70         link = bpf_program__attach(skel->progs.prog_null_ctx);
71         if (!ASSERT_OK_PTR(link, "link"))
72                 return;
73
74         skel->bss->nr_loops = 10;
75
76         usleep(1);
77
78         ASSERT_EQ(skel->bss->nr_loops_returned, skel->bss->nr_loops,
79                   "nr_loops_returned");
80
81         bpf_link__destroy(link);
82 }
83
84 static void check_invalid_flags(struct bpf_loop *skel)
85 {
86         struct bpf_link *link;
87
88         /* check that passing in non-zero flags returns -EINVAL */
89         link = bpf_program__attach(skel->progs.prog_invalid_flags);
90         if (!ASSERT_OK_PTR(link, "link"))
91                 return;
92
93         usleep(1);
94
95         ASSERT_EQ(skel->bss->err, -EINVAL, "err");
96
97         bpf_link__destroy(link);
98 }
99
100 static void check_nested_calls(struct bpf_loop *skel)
101 {
102         __u32 nr_loops = 100, nested_callback_nr_loops = 4;
103         struct bpf_link *link;
104
105         /* check that nested calls are supported */
106         link = bpf_program__attach(skel->progs.prog_nested_calls);
107         if (!ASSERT_OK_PTR(link, "link"))
108                 return;
109
110         skel->bss->nr_loops = nr_loops;
111         skel->bss->nested_callback_nr_loops = nested_callback_nr_loops;
112
113         usleep(1);
114
115         ASSERT_EQ(skel->bss->nr_loops_returned, nr_loops * nested_callback_nr_loops
116                   * nested_callback_nr_loops, "nr_loops_returned");
117         ASSERT_EQ(skel->bss->g_output, (4 * 3) / 2 * nested_callback_nr_loops
118                 * nr_loops, "g_output");
119
120         bpf_link__destroy(link);
121 }
122
123 static void check_non_constant_callback(struct bpf_loop *skel)
124 {
125         struct bpf_link *link =
126                 bpf_program__attach(skel->progs.prog_non_constant_callback);
127
128         if (!ASSERT_OK_PTR(link, "link"))
129                 return;
130
131         skel->bss->callback_selector = 0x0F;
132         usleep(1);
133         ASSERT_EQ(skel->bss->g_output, 0x0F, "g_output #1");
134
135         skel->bss->callback_selector = 0xF0;
136         usleep(1);
137         ASSERT_EQ(skel->bss->g_output, 0xF0, "g_output #2");
138
139         bpf_link__destroy(link);
140 }
141
142 static void check_stack(struct bpf_loop *skel)
143 {
144         struct bpf_link *link = bpf_program__attach(skel->progs.stack_check);
145         const int max_key = 12;
146         int key;
147         int map_fd;
148
149         if (!ASSERT_OK_PTR(link, "link"))
150                 return;
151
152         map_fd = bpf_map__fd(skel->maps.map1);
153
154         if (!ASSERT_GE(map_fd, 0, "bpf_map__fd"))
155                 goto out;
156
157         for (key = 1; key <= max_key; ++key) {
158                 int val = key;
159                 int err = bpf_map_update_elem(map_fd, &key, &val, BPF_NOEXIST);
160
161                 if (!ASSERT_OK(err, "bpf_map_update_elem"))
162                         goto out;
163         }
164
165         usleep(1);
166
167         for (key = 1; key <= max_key; ++key) {
168                 int val;
169                 int err = bpf_map_lookup_elem(map_fd, &key, &val);
170
171                 if (!ASSERT_OK(err, "bpf_map_lookup_elem"))
172                         goto out;
173                 if (!ASSERT_EQ(val, key + 1, "bad value in the map"))
174                         goto out;
175         }
176
177 out:
178         bpf_link__destroy(link);
179 }
180
181 void test_bpf_loop(void)
182 {
183         struct bpf_loop *skel;
184
185         skel = bpf_loop__open_and_load();
186         if (!ASSERT_OK_PTR(skel, "bpf_loop__open_and_load"))
187                 return;
188
189         skel->bss->pid = getpid();
190
191         if (test__start_subtest("check_nr_loops"))
192                 check_nr_loops(skel);
193         if (test__start_subtest("check_callback_fn_stop"))
194                 check_callback_fn_stop(skel);
195         if (test__start_subtest("check_null_callback_ctx"))
196                 check_null_callback_ctx(skel);
197         if (test__start_subtest("check_invalid_flags"))
198                 check_invalid_flags(skel);
199         if (test__start_subtest("check_nested_calls"))
200                 check_nested_calls(skel);
201         if (test__start_subtest("check_non_constant_callback"))
202                 check_non_constant_callback(skel);
203         if (test__start_subtest("check_stack"))
204                 check_stack(skel);
205
206         bpf_loop__destroy(skel);
207 }
This page took 0.038533 seconds and 4 git commands to generate.