Skip to content

Commit b061017

Browse files
Alexei Starovoitovborkmann
authored andcommitted
selftests/bpf: add realistic loop tests
Add a bunch of loop tests. Most of them are created by replacing '#pragma unroll' with '#pragma clang loop unroll(disable)' Several tests are artificially large: /* partial unroll. llvm will unroll loop ~150 times. * C loop count -> 600. * Asm loop count -> 4. * 16k insns in loop body. * Total of 5 such loops. Total program size ~82k insns. */ "./pyperf600.o", /* no unroll at all. * C loop count -> 600. * ASM loop count -> 600. * ~110 insns in loop body. * Total of 5 such loops. Total program size ~1500 insns. */ "./pyperf600_nounroll.o", /* partial unroll. 19k insn in a loop. * Total program size 20.8k insn. * ~350k processed_insns */ "./strobemeta.o", Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]>
1 parent 0d3679e commit b061017

15 files changed

+1347
-12
lines changed

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

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ static int libbpf_debug_print(enum libbpf_print_level level,
55
const char *format, va_list args)
66
{
77
if (level != LIBBPF_DEBUG)
8-
return 0;
8+
return vfprintf(stderr, format, args);
99

1010
if (!strstr(format, "verifier log"))
1111
return 0;
@@ -32,24 +32,69 @@ static int check_load(const char *file, enum bpf_prog_type type)
3232

3333
void test_bpf_verif_scale(void)
3434
{
35-
const char *scale[] = {
36-
"./test_verif_scale1.o", "./test_verif_scale2.o", "./test_verif_scale3.o"
35+
const char *sched_cls[] = {
36+
"./test_verif_scale1.o", "./test_verif_scale2.o", "./test_verif_scale3.o",
3737
};
38-
const char *pyperf[] = {
39-
"./pyperf50.o", "./pyperf100.o", "./pyperf180.o"
38+
const char *raw_tp[] = {
39+
/* full unroll by llvm */
40+
"./pyperf50.o", "./pyperf100.o", "./pyperf180.o",
41+
42+
/* partial unroll. llvm will unroll loop ~150 times.
43+
* C loop count -> 600.
44+
* Asm loop count -> 4.
45+
* 16k insns in loop body.
46+
* Total of 5 such loops. Total program size ~82k insns.
47+
*/
48+
"./pyperf600.o",
49+
50+
/* no unroll at all.
51+
* C loop count -> 600.
52+
* ASM loop count -> 600.
53+
* ~110 insns in loop body.
54+
* Total of 5 such loops. Total program size ~1500 insns.
55+
*/
56+
"./pyperf600_nounroll.o",
57+
58+
"./loop1.o", "./loop2.o",
59+
60+
/* partial unroll. 19k insn in a loop.
61+
* Total program size 20.8k insn.
62+
* ~350k processed_insns
63+
*/
64+
"./strobemeta.o",
65+
66+
/* no unroll, tiny loops */
67+
"./strobemeta_nounroll1.o",
68+
"./strobemeta_nounroll2.o",
69+
};
70+
const char *cg_sysctl[] = {
71+
"./test_sysctl_loop1.o", "./test_sysctl_loop2.o",
4072
};
4173
int err, i;
4274

4375
if (verifier_stats)
4476
libbpf_set_print(libbpf_debug_print);
4577

46-
for (i = 0; i < ARRAY_SIZE(scale); i++) {
47-
err = check_load(scale[i], BPF_PROG_TYPE_SCHED_CLS);
48-
printf("test_scale:%s:%s\n", scale[i], err ? "FAIL" : "OK");
78+
err = check_load("./loop3.o", BPF_PROG_TYPE_RAW_TRACEPOINT);
79+
printf("test_scale:loop3:%s\n", err ? (error_cnt--, "OK") : "FAIL");
80+
81+
for (i = 0; i < ARRAY_SIZE(sched_cls); i++) {
82+
err = check_load(sched_cls[i], BPF_PROG_TYPE_SCHED_CLS);
83+
printf("test_scale:%s:%s\n", sched_cls[i], err ? "FAIL" : "OK");
4984
}
5085

51-
for (i = 0; i < ARRAY_SIZE(pyperf); i++) {
52-
err = check_load(pyperf[i], BPF_PROG_TYPE_RAW_TRACEPOINT);
53-
printf("test_scale:%s:%s\n", pyperf[i], err ? "FAIL" : "OK");
86+
for (i = 0; i < ARRAY_SIZE(raw_tp); i++) {
87+
err = check_load(raw_tp[i], BPF_PROG_TYPE_RAW_TRACEPOINT);
88+
printf("test_scale:%s:%s\n", raw_tp[i], err ? "FAIL" : "OK");
5489
}
90+
91+
for (i = 0; i < ARRAY_SIZE(cg_sysctl); i++) {
92+
err = check_load(cg_sysctl[i], BPF_PROG_TYPE_CGROUP_SYSCTL);
93+
printf("test_scale:%s:%s\n", cg_sysctl[i], err ? "FAIL" : "OK");
94+
}
95+
err = check_load("./test_xdp_loop.o", BPF_PROG_TYPE_XDP);
96+
printf("test_scale:test_xdp_loop:%s\n", err ? "FAIL" : "OK");
97+
98+
err = check_load("./test_seg6_loop.o", BPF_PROG_TYPE_LWT_SEG6LOCAL);
99+
printf("test_scale:test_seg6_loop:%s\n", err ? "FAIL" : "OK");
55100
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (c) 2019 Facebook
3+
#include <linux/sched.h>
4+
#include <linux/ptrace.h>
5+
#include <stdint.h>
6+
#include <stddef.h>
7+
#include <stdbool.h>
8+
#include <linux/bpf.h>
9+
#include "bpf_helpers.h"
10+
11+
char _license[] SEC("license") = "GPL";
12+
13+
SEC("raw_tracepoint/kfree_skb")
14+
int nested_loops(volatile struct pt_regs* ctx)
15+
{
16+
int i, j, sum = 0, m;
17+
18+
for (j = 0; j < 300; j++)
19+
for (i = 0; i < j; i++) {
20+
if (j & 1)
21+
m = ctx->rax;
22+
else
23+
m = j;
24+
sum += i * m;
25+
}
26+
27+
return sum;
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (c) 2019 Facebook
3+
#include <linux/sched.h>
4+
#include <linux/ptrace.h>
5+
#include <stdint.h>
6+
#include <stddef.h>
7+
#include <stdbool.h>
8+
#include <linux/bpf.h>
9+
#include "bpf_helpers.h"
10+
11+
char _license[] SEC("license") = "GPL";
12+
13+
SEC("raw_tracepoint/consume_skb")
14+
int while_true(volatile struct pt_regs* ctx)
15+
{
16+
int i = 0;
17+
18+
while (true) {
19+
if (ctx->rax & 1)
20+
i += 3;
21+
else
22+
i += 7;
23+
if (i > 40)
24+
break;
25+
}
26+
27+
return i;
28+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (c) 2019 Facebook
3+
#include <linux/sched.h>
4+
#include <linux/ptrace.h>
5+
#include <stdint.h>
6+
#include <stddef.h>
7+
#include <stdbool.h>
8+
#include <linux/bpf.h>
9+
#include "bpf_helpers.h"
10+
11+
char _license[] SEC("license") = "GPL";
12+
13+
SEC("raw_tracepoint/consume_skb")
14+
int while_true(volatile struct pt_regs* ctx)
15+
{
16+
__u64 i = 0, sum = 0;
17+
do {
18+
i++;
19+
sum += ctx->rax;
20+
} while (i < 0x100000000ULL);
21+
return sum;
22+
}

tools/testing/selftests/bpf/progs/pyperf.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,11 @@ static inline __attribute__((__always_inline__)) int __on_event(struct pt_regs *
220220
int32_t* symbol_counter = bpf_map_lookup_elem(&symbolmap, &sym);
221221
if (symbol_counter == NULL)
222222
return 0;
223-
#pragma unroll
223+
#ifdef NO_UNROLL
224+
#pragma clang loop unroll(disable)
225+
#else
226+
#pragma clang loop unroll(full)
227+
#endif
224228
/* Unwind python stack */
225229
for (int i = 0; i < STACK_MAX_LEN; ++i) {
226230
if (frame_ptr && get_frame_data(frame_ptr, pidData, &frame, &sym)) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (c) 2019 Facebook
3+
#define STACK_MAX_LEN 600
4+
/* clang will not unroll the loop 600 times.
5+
* Instead it will unroll it to the amount it deemed
6+
* appropriate, but the loop will still execute 600 times.
7+
* Total program size is around 90k insns
8+
*/
9+
#include "pyperf.h"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (c) 2019 Facebook
3+
#define STACK_MAX_LEN 600
4+
#define NO_UNROLL
5+
/* clang will not unroll at all.
6+
* Total program size is around 2k insns
7+
*/
8+
#include "pyperf.h"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2+
// Copyright (c) 2019 Facebook
3+
4+
#define STROBE_MAX_INTS 2
5+
#define STROBE_MAX_STRS 25
6+
#define STROBE_MAX_MAPS 100
7+
#define STROBE_MAX_MAP_ENTRIES 20
8+
/* full unroll by llvm #undef NO_UNROLL */
9+
#include "strobemeta.h"
10+

0 commit comments

Comments
 (0)