History

bpf: Add test ops for BPF_PROG_TYPE_TRACING

The current fexit and fentry tests rely on a different program to exercise the functions they attach to. Instead of doing this, implement the test operations for tracing which will also be used for BPF_MODIFY_RETURN in a subsequent patch. Also, clean up the fexit test to use the generated skeleton.

KP Singh committed 6 years ago

Commit da00d2f1 parent aca228c6 files · +67 −76Browse files

Unified · Split

6 files
  1. include/linux/bpf.h +10 −0
  2. kernel/trace/bpf_trace.c +1 −0
  3. net/bpf/test_run.c +28 −9
  4. tools/testing/selftests/bpf/prog_tests/fentry_fexit.c +3 −9
  5. tools/testing/selftests/bpf/prog_tests/fentry_test.c +4 −10
  6. tools/testing/selftests/bpf/prog_tests/fexit_test.c +21 −48
include/linux/bpf.h+10−0
@@ -1156,6 +1156,9 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr, · 1155 unmodified lines
1156 union bpf_attr __user *uattr);1156 union bpf_attr __user *uattr);
1157int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,1157int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
1158 union bpf_attr __user *uattr);1158 union bpf_attr __user *uattr);
1159int bpf_prog_test_run_tracing(struct bpf_prog *prog,
1160 const union bpf_attr *kattr,
1161 union bpf_attr __user *uattr);
1159int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,1162int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
1160 const union bpf_attr *kattr,1163 const union bpf_attr *kattr,
1161 union bpf_attr __user *uattr);1164 union bpf_attr __user *uattr);
@@ -1313,6 +1316,13 @@ static inline int bpf_prog_test_run_skb(struct bpf_prog *prog, · 151 unmodified lines
1313 return -ENOTSUPP;1316 return -ENOTSUPP;
1314}1317}
1315 1318
1319static inline int bpf_prog_test_run_tracing(struct bpf_prog *prog,
1320 const union bpf_attr *kattr,
1321 union bpf_attr __user *uattr)
1322{
1323 return -ENOTSUPP;
1324}
1325
1316static inline int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,1326static inline int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
1317 const union bpf_attr *kattr,1327 const union bpf_attr *kattr,
1318 union bpf_attr __user *uattr)1328 union bpf_attr __user *uattr)
kernel/trace/bpf_trace.c+1−0
@@ -1266,6 +1266,7 @@ const struct bpf_verifier_ops tracing_verifier_ops = { · 1265 unmodified lines
1266};1266};
1267 1267
1268const struct bpf_prog_ops tracing_prog_ops = {1268const struct bpf_prog_ops tracing_prog_ops = {
1269 .test_run = bpf_prog_test_run_tracing,
1269};1270};
1270 1271
1271static bool raw_tp_writable_prog_is_valid_access(int off, int size,1272static bool raw_tp_writable_prog_is_valid_access(int off, int size,
net/bpf/test_run.c+28−9
@@ -160,18 +160,37 @@ static void *bpf_test_init(const union bpf_attr *kattr, u32 size, · 159 unmodified lines
160 kfree(data);160 kfree(data);
161 return ERR_PTR(-EFAULT);161 return ERR_PTR(-EFAULT);
162 }162 }
163 if (bpf_fentry_test1(1) != 2 ||163
164 bpf_fentry_test2(2, 3) != 5 ||
165 bpf_fentry_test3(4, 5, 6) != 15 ||
166 bpf_fentry_test4((void *)7, 8, 9, 10) != 34 ||
167 bpf_fentry_test5(11, (void *)12, 13, 14, 15) != 65 ||
168 bpf_fentry_test6(16, (void *)17, 18, 19, (void *)20, 21) != 111) {
169 kfree(data);
170 return ERR_PTR(-EFAULT);
171 }
172 return data;164 return data;
173}165}
174 166
167int bpf_prog_test_run_tracing(struct bpf_prog *prog,
168 const union bpf_attr *kattr,
169 union bpf_attr __user *uattr)
170{
171 int err = -EFAULT;
172
173 switch (prog->expected_attach_type) {
174 case BPF_TRACE_FENTRY:
175 case BPF_TRACE_FEXIT:
176 if (bpf_fentry_test1(1) != 2 ||
177 bpf_fentry_test2(2, 3) != 5 ||
178 bpf_fentry_test3(4, 5, 6) != 15 ||
179 bpf_fentry_test4((void *)7, 8, 9, 10) != 34 ||
180 bpf_fentry_test5(11, (void *)12, 13, 14, 15) != 65 ||
181 bpf_fentry_test6(16, (void *)17, 18, 19, (void *)20, 21) != 111)
182 goto out;
183 break;
184 default:
185 goto out;
186 }
187
188 err = 0;
189out:
190 trace_bpf_test_finish(&err);
191 return err;
192}
193
175static void *bpf_ctx_init(const union bpf_attr *kattr, u32 max_size)194static void *bpf_ctx_init(const union bpf_attr *kattr, u32 max_size)
176{195{
177 void __user *data_in = u64_to_user_ptr(kattr->test.ctx_in);196 void __user *data_in = u64_to_user_ptr(kattr->test.ctx_in);
tools/testing/selftests/bpf/prog_tests/fentry_fexit.c+3−9
@@ -1,22 +1,17 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2019 Facebook */2/* Copyright (c) 2019 Facebook */
3#include <test_progs.h>3#include <test_progs.h>
4#include "test_pkt_access.skel.h"
5#include "fentry_test.skel.h"4#include "fentry_test.skel.h"
6#include "fexit_test.skel.h"5#include "fexit_test.skel.h"
7 6
8void test_fentry_fexit(void)7void test_fentry_fexit(void)
9{8{
10 struct test_pkt_access *pkt_skel = NULL;
11 struct fentry_test *fentry_skel = NULL;9 struct fentry_test *fentry_skel = NULL;
12 struct fexit_test *fexit_skel = NULL;10 struct fexit_test *fexit_skel = NULL;
13 __u64 *fentry_res, *fexit_res;11 __u64 *fentry_res, *fexit_res;
14 __u32 duration = 0, retval;12 __u32 duration = 0, retval;
15 int err, pkt_fd, i;13 int err, prog_fd, i;
16 14
17 pkt_skel = test_pkt_access__open_and_load();
18 if (CHECK(!pkt_skel, "pkt_skel_load", "pkt_access skeleton failed\n"))
19 return;
20 fentry_skel = fentry_test__open_and_load();15 fentry_skel = fentry_test__open_and_load();
21 if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n"))16 if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n"))
22 goto close_prog;17 goto close_prog;
@@ -31,8 +26,8 @@ void test_fentry_fexit(void) · 8 unmodified lines
31 if (CHECK(err, "fexit_attach", "fexit attach failed: %d\n", err))26 if (CHECK(err, "fexit_attach", "fexit attach failed: %d\n", err))
32 goto close_prog;27 goto close_prog;
33 28
34 pkt_fd = bpf_program__fd(pkt_skel->progs.test_pkt_access);29 prog_fd = bpf_program__fd(fexit_skel->progs.test1);
35 err = bpf_prog_test_run(pkt_fd, 1, &pkt_v6, sizeof(pkt_v6),30 err = bpf_prog_test_run(prog_fd, 1, NULL, 0,
36 NULL, NULL, &retval, &duration);31 NULL, NULL, &retval, &duration);
37 CHECK(err || retval, "ipv6",32 CHECK(err || retval, "ipv6",
38 "err %d errno %d retval %d duration %d\n",33 "err %d errno %d retval %d duration %d\n",
@@ -49,7 +44,6 @@ void test_fentry_fexit(void) · 10 unmodified lines
49 }44 }
50 45
51close_prog:46close_prog:
52 test_pkt_access__destroy(pkt_skel);
53 fentry_test__destroy(fentry_skel);47 fentry_test__destroy(fentry_skel);
54 fexit_test__destroy(fexit_skel);48 fexit_test__destroy(fexit_skel);
55}49}
tools/testing/selftests/bpf/prog_tests/fentry_test.c+4−10
@@ -1,20 +1,15 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2019 Facebook */2/* Copyright (c) 2019 Facebook */
3#include <test_progs.h>3#include <test_progs.h>
4#include "test_pkt_access.skel.h"
5#include "fentry_test.skel.h"4#include "fentry_test.skel.h"
6 5
7void test_fentry_test(void)6void test_fentry_test(void)
8{7{
9 struct test_pkt_access *pkt_skel = NULL;
10 struct fentry_test *fentry_skel = NULL;8 struct fentry_test *fentry_skel = NULL;
11 int err, pkt_fd, i;9 int err, prog_fd, i;
12 __u32 duration = 0, retval;10 __u32 duration = 0, retval;
13 __u64 *result;11 __u64 *result;
14 12
15 pkt_skel = test_pkt_access__open_and_load();
16 if (CHECK(!pkt_skel, "pkt_skel_load", "pkt_access skeleton failed\n"))
17 return;
18 fentry_skel = fentry_test__open_and_load();13 fentry_skel = fentry_test__open_and_load();
19 if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n"))14 if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n"))
20 goto cleanup;15 goto cleanup;
@@ -23,10 +18,10 @@ void test_fentry_test(void) · 2 unmodified lines
23 if (CHECK(err, "fentry_attach", "fentry attach failed: %d\n", err))18 if (CHECK(err, "fentry_attach", "fentry attach failed: %d\n", err))
24 goto cleanup;19 goto cleanup;
25 20
26 pkt_fd = bpf_program__fd(pkt_skel->progs.test_pkt_access);21 prog_fd = bpf_program__fd(fentry_skel->progs.test1);
27 err = bpf_prog_test_run(pkt_fd, 1, &pkt_v6, sizeof(pkt_v6),22 err = bpf_prog_test_run(prog_fd, 1, NULL, 0,
28 NULL, NULL, &retval, &duration);23 NULL, NULL, &retval, &duration);
29 CHECK(err || retval, "ipv6",24 CHECK(err || retval, "test_run",
30 "err %d errno %d retval %d duration %d\n",25 "err %d errno %d retval %d duration %d\n",
31 err, errno, retval, duration);26 err, errno, retval, duration);
32 27
@@ -39,5 +34,4 @@ void test_fentry_test(void) · 6 unmodified lines
39 34
40cleanup:35cleanup:
41 fentry_test__destroy(fentry_skel);36 fentry_test__destroy(fentry_skel);
42 test_pkt_access__destroy(pkt_skel);
43}37}
tools/testing/selftests/bpf/prog_tests/fexit_test.c+21−48
@@ -1,64 +1,37 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2019 Facebook */2/* Copyright (c) 2019 Facebook */
3#include <test_progs.h>3#include <test_progs.h>
4#include "fexit_test.skel.h"
4 5
5void test_fexit_test(void)6void test_fexit_test(void)
6{7{
7 struct bpf_prog_load_attr attr = {8 struct fexit_test *fexit_skel = NULL;
8 .file = "./fexit_test.o",9 int err, prog_fd, i;
9 };
10
11 char prog_name[] = "fexit/bpf_fentry_testX";
12 struct bpf_object *obj = NULL, *pkt_obj;
13 int err, pkt_fd, kfree_skb_fd, i;
14 struct bpf_link *link[6] = {};
15 struct bpf_program *prog[6];
16 __u32 duration = 0, retval;10 __u32 duration = 0, retval;
17 struct bpf_map *data_map;11 __u64 *result;
18 const int zero = 0;
19 u64 result[6];
20 12
21 err = bpf_prog_load("./test_pkt_access.o", BPF_PROG_TYPE_SCHED_CLS,13 fexit_skel = fexit_test__open_and_load();
22 &pkt_obj, &pkt_fd);14 if (CHECK(!fexit_skel, "fexit_skel_load", "fexit skeleton failed\n"))
23 if (CHECK(err, "prog_load sched cls", "err %d errno %d\n", err, errno))15 goto cleanup;
24 return;
25 err = bpf_prog_load_xattr(&attr, &obj, &kfree_skb_fd);
26 if (CHECK(err, "prog_load fail", "err %d errno %d\n", err, errno))
27 goto close_prog;
28 16
29 for (i = 0; i < 6; i++) {17 err = fexit_test__attach(fexit_skel);
30 prog_name[sizeof(prog_name) - 2] = '1' + i;18 if (CHECK(err, "fexit_attach", "fexit attach failed: %d\n", err))
31 prog[i] = bpf_object__find_program_by_title(obj, prog_name);19 goto cleanup;
32 if (CHECK(!prog[i], "find_prog", "prog %s not found\n", prog_name))
33 goto close_prog;
34 link[i] = bpf_program__attach_trace(prog[i]);
35 if (CHECK(IS_ERR(link[i]), "attach_trace", "failed to link\n"))
36 goto close_prog;
37 }
38 data_map = bpf_object__find_map_by_name(obj, "fexit_te.bss");
39 if (CHECK(!data_map, "find_data_map", "data map not found\n"))
40 goto close_prog;
41 20
42 err = bpf_prog_test_run(pkt_fd, 1, &pkt_v6, sizeof(pkt_v6),21 prog_fd = bpf_program__fd(fexit_skel->progs.test1);
22 err = bpf_prog_test_run(prog_fd, 1, NULL, 0,
43 NULL, NULL, &retval, &duration);23 NULL, NULL, &retval, &duration);
44 CHECK(err || retval, "ipv6",24 CHECK(err || retval, "test_run",
45 "err %d errno %d retval %d duration %d\n",25 "err %d errno %d retval %d duration %d\n",
46 err, errno, retval, duration);26 err, errno, retval, duration);
47 27
48 err = bpf_map_lookup_elem(bpf_map__fd(data_map), &zero, &result);28 result = (__u64 *)fexit_skel->bss;
49 if (CHECK(err, "get_result",29 for (i = 0; i < 6; i++) {
50 "failed to get output data: %d\n", err))30 if (CHECK(result[i] != 1, "result",
51 goto close_prog;31 "fexit_test%d failed err %lld\n", i + 1, result[i]))
52 32 goto cleanup;
53 for (i = 0; i < 6; i++)33 }
54 if (CHECK(result[i] != 1, "result", "bpf_fentry_test%d failed err %ld\n",
55 i + 1, result[i]))
56 goto close_prog;
57 34
58close_prog:35cleanup:
59 for (i = 0; i < 6; i++)36 fexit_test__destroy(fexit_skel);
60 if (!IS_ERR_OR_NULL(link[i]))
61 bpf_link__destroy(link[i]);
62 bpf_object__close(obj);
63 bpf_object__close(pkt_obj);
64}37}