xref: /linux/tools/testing/selftests/bpf/benchs/bench_bpf_crypto.c (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
3 
4 #include <argp.h>
5 #include "bench.h"
6 #include "crypto_bench.skel.h"
7 
8 #define MAX_CIPHER_LEN 32
9 static char *input;
10 static struct crypto_ctx {
11 	struct crypto_bench *skel;
12 	int pfd;
13 } ctx;
14 
15 static struct crypto_args {
16 	u32 crypto_len;
17 	char *crypto_cipher;
18 } args = {
19 	.crypto_len = 16,
20 	.crypto_cipher = "ecb(aes)",
21 };
22 
23 enum {
24 	ARG_CRYPTO_LEN = 5000,
25 	ARG_CRYPTO_CIPHER = 5001,
26 };
27 
28 static const struct argp_option opts[] = {
29 	{ "crypto-len", ARG_CRYPTO_LEN, "CRYPTO_LEN", 0,
30 	  "Set the length of crypto buffer" },
31 	{ "crypto-cipher", ARG_CRYPTO_CIPHER, "CRYPTO_CIPHER", 0,
32 	  "Set the cipher to use (default:ecb(aes))" },
33 	{},
34 };
35 
crypto_parse_arg(int key,char * arg,struct argp_state * state)36 static error_t crypto_parse_arg(int key, char *arg, struct argp_state *state)
37 {
38 	switch (key) {
39 	case ARG_CRYPTO_LEN:
40 		args.crypto_len = strtoul(arg, NULL, 10);
41 		if (!args.crypto_len ||
42 		    args.crypto_len > sizeof(ctx.skel->bss->dst)) {
43 			fprintf(stderr, "Invalid crypto buffer len (limit %zu)\n",
44 				sizeof(ctx.skel->bss->dst));
45 			argp_usage(state);
46 		}
47 		break;
48 	case ARG_CRYPTO_CIPHER:
49 		args.crypto_cipher = strdup(arg);
50 		if (!strlen(args.crypto_cipher) ||
51 		    strlen(args.crypto_cipher) > MAX_CIPHER_LEN) {
52 			fprintf(stderr, "Invalid crypto cipher len (limit %d)\n",
53 				MAX_CIPHER_LEN);
54 			argp_usage(state);
55 		}
56 		break;
57 	default:
58 		return ARGP_ERR_UNKNOWN;
59 	}
60 
61 	return 0;
62 }
63 
64 const struct argp bench_crypto_argp = {
65 	.options = opts,
66 	.parser = crypto_parse_arg,
67 };
68 
crypto_validate(void)69 static void crypto_validate(void)
70 {
71 	if (env.consumer_cnt != 0) {
72 		fprintf(stderr, "bpf crypto benchmark doesn't support consumer!\n");
73 		exit(1);
74 	}
75 }
76 
crypto_setup(void)77 static void crypto_setup(void)
78 {
79 	LIBBPF_OPTS(bpf_test_run_opts, opts);
80 
81 	int err, pfd;
82 	size_t i, sz;
83 
84 	sz = args.crypto_len;
85 	if (!sz || sz > sizeof(ctx.skel->bss->dst)) {
86 		fprintf(stderr, "invalid encrypt buffer size (source %zu, target %zu)\n",
87 			sz, sizeof(ctx.skel->bss->dst));
88 		exit(1);
89 	}
90 
91 	setup_libbpf();
92 
93 	ctx.skel = crypto_bench__open();
94 	if (!ctx.skel) {
95 		fprintf(stderr, "failed to open skeleton\n");
96 		exit(1);
97 	}
98 
99 	snprintf(ctx.skel->bss->cipher, 128, "%s", args.crypto_cipher);
100 	memcpy(ctx.skel->bss->key, "12345678testtest", 16);
101 	ctx.skel->bss->key_len = 16;
102 	ctx.skel->bss->authsize = 0;
103 
104 	srandom(time(NULL));
105 	input = malloc(sz);
106 	for (i = 0; i < sz - 1; i++)
107 		input[i] = '1' + random() % 9;
108 	input[sz - 1] = '\0';
109 
110 	ctx.skel->rodata->len = args.crypto_len;
111 
112 	err = crypto_bench__load(ctx.skel);
113 	if (err) {
114 		fprintf(stderr, "failed to load skeleton\n");
115 		crypto_bench__destroy(ctx.skel);
116 		exit(1);
117 	}
118 
119 	pfd = bpf_program__fd(ctx.skel->progs.crypto_setup);
120 	if (pfd < 0) {
121 		fprintf(stderr, "failed to get fd for setup prog\n");
122 		crypto_bench__destroy(ctx.skel);
123 		exit(1);
124 	}
125 
126 	err = bpf_prog_test_run_opts(pfd, &opts);
127 	if (err || ctx.skel->bss->status) {
128 		fprintf(stderr, "failed to run setup prog: err %d, status %d\n",
129 			err, ctx.skel->bss->status);
130 		crypto_bench__destroy(ctx.skel);
131 		exit(1);
132 	}
133 }
134 
crypto_encrypt_setup(void)135 static void crypto_encrypt_setup(void)
136 {
137 	crypto_setup();
138 	ctx.pfd = bpf_program__fd(ctx.skel->progs.crypto_encrypt);
139 }
140 
crypto_decrypt_setup(void)141 static void crypto_decrypt_setup(void)
142 {
143 	crypto_setup();
144 	ctx.pfd = bpf_program__fd(ctx.skel->progs.crypto_decrypt);
145 }
146 
crypto_measure(struct bench_res * res)147 static void crypto_measure(struct bench_res *res)
148 {
149 	res->hits = atomic_swap(&ctx.skel->bss->hits, 0);
150 }
151 
crypto_producer(void * unused)152 static void *crypto_producer(void *unused)
153 {
154 	LIBBPF_OPTS(bpf_test_run_opts, opts,
155 		.repeat = 64,
156 		.data_in = input,
157 		.data_size_in = args.crypto_len,
158 	);
159 
160 	while (true)
161 		(void)bpf_prog_test_run_opts(ctx.pfd, &opts);
162 	return NULL;
163 }
164 
165 const struct bench bench_crypto_encrypt = {
166 	.name = "crypto-encrypt",
167 	.argp = &bench_crypto_argp,
168 	.validate = crypto_validate,
169 	.setup = crypto_encrypt_setup,
170 	.producer_thread = crypto_producer,
171 	.measure = crypto_measure,
172 	.report_progress = hits_drops_report_progress,
173 	.report_final = hits_drops_report_final,
174 };
175 
176 const struct bench bench_crypto_decrypt = {
177 	.name = "crypto-decrypt",
178 	.argp = &bench_crypto_argp,
179 	.validate = crypto_validate,
180 	.setup = crypto_decrypt_setup,
181 	.producer_thread = crypto_producer,
182 	.measure = crypto_measure,
183 	.report_progress = hits_drops_report_progress,
184 	.report_final = hits_drops_report_final,
185 };
186