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