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