1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2021. Huawei Technologies Co., Ltd */
3 #include <argp.h>
4 #include "bench.h"
5 #include "strncmp_bench.skel.h"
6
7 static struct strncmp_ctx {
8 struct strncmp_bench *skel;
9 } ctx;
10
11 static struct strncmp_args {
12 u32 cmp_str_len;
13 } args = {
14 .cmp_str_len = 32,
15 };
16
17 enum {
18 ARG_CMP_STR_LEN = 5000,
19 };
20
21 static const struct argp_option opts[] = {
22 { "cmp-str-len", ARG_CMP_STR_LEN, "CMP_STR_LEN", 0,
23 "Set the length of compared string" },
24 {},
25 };
26
strncmp_parse_arg(int key,char * arg,struct argp_state * state)27 static error_t strncmp_parse_arg(int key, char *arg, struct argp_state *state)
28 {
29 switch (key) {
30 case ARG_CMP_STR_LEN:
31 args.cmp_str_len = strtoul(arg, NULL, 10);
32 if (!args.cmp_str_len ||
33 args.cmp_str_len >= sizeof(ctx.skel->bss->str)) {
34 fprintf(stderr, "Invalid cmp str len (limit %zu)\n",
35 sizeof(ctx.skel->bss->str));
36 argp_usage(state);
37 }
38 break;
39 default:
40 return ARGP_ERR_UNKNOWN;
41 }
42
43 return 0;
44 }
45
46 const struct argp bench_strncmp_argp = {
47 .options = opts,
48 .parser = strncmp_parse_arg,
49 };
50
strncmp_validate(void)51 static void strncmp_validate(void)
52 {
53 if (env.consumer_cnt != 0) {
54 fprintf(stderr, "strncmp benchmark doesn't support consumer!\n");
55 exit(1);
56 }
57 }
58
strncmp_setup(void)59 static void strncmp_setup(void)
60 {
61 int err;
62 char *target;
63 size_t i, sz;
64
65 sz = sizeof(ctx.skel->rodata->target);
66 if (!sz || sz < sizeof(ctx.skel->bss->str)) {
67 fprintf(stderr, "invalid string size (target %zu, src %zu)\n",
68 sz, sizeof(ctx.skel->bss->str));
69 exit(1);
70 }
71
72 setup_libbpf();
73
74 ctx.skel = strncmp_bench__open();
75 if (!ctx.skel) {
76 fprintf(stderr, "failed to open skeleton\n");
77 exit(1);
78 }
79
80 srandom(time(NULL));
81 target = ctx.skel->rodata->target;
82 for (i = 0; i < sz - 1; i++)
83 target[i] = '1' + random() % 9;
84 target[sz - 1] = '\0';
85
86 ctx.skel->rodata->cmp_str_len = args.cmp_str_len;
87
88 memcpy(ctx.skel->bss->str, target, args.cmp_str_len);
89 ctx.skel->bss->str[args.cmp_str_len] = '\0';
90 /* Make bss->str < rodata->target */
91 ctx.skel->bss->str[args.cmp_str_len - 1] -= 1;
92
93 err = strncmp_bench__load(ctx.skel);
94 if (err) {
95 fprintf(stderr, "failed to load skeleton\n");
96 strncmp_bench__destroy(ctx.skel);
97 exit(1);
98 }
99 }
100
strncmp_attach_prog(struct bpf_program * prog)101 static void strncmp_attach_prog(struct bpf_program *prog)
102 {
103 struct bpf_link *link;
104
105 link = bpf_program__attach(prog);
106 if (!link) {
107 fprintf(stderr, "failed to attach program!\n");
108 exit(1);
109 }
110 }
111
strncmp_no_helper_setup(void)112 static void strncmp_no_helper_setup(void)
113 {
114 strncmp_setup();
115 strncmp_attach_prog(ctx.skel->progs.strncmp_no_helper);
116 }
117
strncmp_helper_setup(void)118 static void strncmp_helper_setup(void)
119 {
120 strncmp_setup();
121 strncmp_attach_prog(ctx.skel->progs.strncmp_helper);
122 }
123
strncmp_producer(void * ctx)124 static void *strncmp_producer(void *ctx)
125 {
126 while (true)
127 (void)syscall(__NR_getpgid);
128 return NULL;
129 }
130
strncmp_measure(struct bench_res * res)131 static void strncmp_measure(struct bench_res *res)
132 {
133 res->hits = atomic_swap(&ctx.skel->bss->hits, 0);
134 }
135
136 const struct bench bench_strncmp_no_helper = {
137 .name = "strncmp-no-helper",
138 .argp = &bench_strncmp_argp,
139 .validate = strncmp_validate,
140 .setup = strncmp_no_helper_setup,
141 .producer_thread = strncmp_producer,
142 .measure = strncmp_measure,
143 .report_progress = hits_drops_report_progress,
144 .report_final = hits_drops_report_final,
145 };
146
147 const struct bench bench_strncmp_helper = {
148 .name = "strncmp-helper",
149 .argp = &bench_strncmp_argp,
150 .validate = strncmp_validate,
151 .setup = strncmp_helper_setup,
152 .producer_thread = strncmp_producer,
153 .measure = strncmp_measure,
154 .report_progress = hits_drops_report_progress,
155 .report_final = hits_drops_report_final,
156 };
157