xref: /linux/tools/testing/selftests/bpf/benchs/bench_bpf_for.c (revision 5a8cd539ac19f7a68e68e1d25ef9ca2ff55b8500)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
3 
4 #include <argp.h>
5 #include "bench.h"
6 #include "bpf_for_bench.skel.h"
7 
8 /* BPF triggering benchmarks */
9 static struct ctx {
10 	struct bpf_for_bench *skel;
11 } ctx;
12 
13 static struct {
14 	__u32 nr_loops;
15 } args = {
16 	/*
17 	 * Default to a large loop count so the per-iteration bpf_iter_num_next() cost dominates
18 	 * the one-time bpf_iter_num_new()/destroy() setup and teardown.
19 	 */
20 	.nr_loops = 1000,
21 };
22 
23 enum {
24 	ARG_NR_LOOPS = 4000,
25 };
26 
27 static const struct argp_option opts[] = {
28 	{ "nr_loops", ARG_NR_LOOPS, "nr_loops", 0,
29 		"Set number of iterations for the bpf_for() loop"},
30 	{},
31 };
32 
parse_arg(int key,char * arg,struct argp_state * state)33 static error_t parse_arg(int key, char *arg, struct argp_state *state)
34 {
35 	switch (key) {
36 	case ARG_NR_LOOPS:
37 		args.nr_loops = strtol(arg, NULL, 10);
38 		break;
39 	default:
40 		return ARGP_ERR_UNKNOWN;
41 	}
42 
43 	return 0;
44 }
45 
46 /* exported into benchmark runner */
47 const struct argp bench_bpf_for_argp = {
48 	.options = opts,
49 	.parser = parse_arg,
50 };
51 
validate(void)52 static void validate(void)
53 {
54 	if (env.consumer_cnt != 0) {
55 		fprintf(stderr, "benchmark doesn't support consumer!\n");
56 		exit(1);
57 	}
58 }
59 
producer(void * input)60 static void *producer(void *input)
61 {
62 	while (true)
63 		/* trigger the bpf program */
64 		syscall(__NR_getpgid);
65 
66 	return NULL;
67 }
68 
measure(struct bench_res * res)69 static void measure(struct bench_res *res)
70 {
71 	res->hits = atomic_swap(&ctx.skel->bss->hits, 0);
72 }
73 
setup(void)74 static void setup(void)
75 {
76 	struct bpf_link *link;
77 
78 	setup_libbpf();
79 
80 	ctx.skel = bpf_for_bench__open_and_load();
81 	if (!ctx.skel) {
82 		fprintf(stderr, "failed to open skeleton\n");
83 		exit(1);
84 	}
85 
86 	link = bpf_program__attach(ctx.skel->progs.benchmark);
87 	if (!link) {
88 		fprintf(stderr, "failed to attach program!\n");
89 		exit(1);
90 	}
91 
92 	ctx.skel->bss->nr_loops = args.nr_loops;
93 }
94 
95 const struct bench bench_bpf_for = {
96 	.name = "bpf-for",
97 	.argp = &bench_bpf_for_argp,
98 	.validate = validate,
99 	.setup = setup,
100 	.producer_thread = producer,
101 	.measure = measure,
102 	.report_progress = ops_report_progress,
103 	.report_final = ops_report_final,
104 };
105