Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests: bpf: crypto: add benchmark for crypto functions

Some simple benchmarks are added to understand the baseline of
performance.

Signed-off-by: Vadim Fedorenko <vadfed@meta.com>
Link: https://lore.kernel.org/r/20240422225024.2847039-5-vadfed@meta.com
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>

authored by

Vadim Fedorenko and committed by
Martin KaFai Lau
8000e627 91541ab1

+302
+2
tools/testing/selftests/bpf/Makefile
··· 730 730 $(OUTPUT)/bench_local_storage_create.o: $(OUTPUT)/bench_local_storage_create.skel.h 731 731 $(OUTPUT)/bench_bpf_hashmap_lookup.o: $(OUTPUT)/bpf_hashmap_lookup.skel.h 732 732 $(OUTPUT)/bench_htab_mem.o: $(OUTPUT)/htab_mem_bench.skel.h 733 + $(OUTPUT)/bench_bpf_crypto.o: $(OUTPUT)/crypto_bench.skel.h 733 734 $(OUTPUT)/bench.o: bench.h testing_helpers.h $(BPFOBJ) 734 735 $(OUTPUT)/bench: LDLIBS += -lm 735 736 $(OUTPUT)/bench: $(OUTPUT)/bench.o \ ··· 750 749 $(OUTPUT)/bench_bpf_hashmap_lookup.o \ 751 750 $(OUTPUT)/bench_local_storage_create.o \ 752 751 $(OUTPUT)/bench_htab_mem.o \ 752 + $(OUTPUT)/bench_bpf_crypto.o \ 753 753 # 754 754 $(call msg,BINARY,,$@) 755 755 $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@
+6
tools/testing/selftests/bpf/bench.c
··· 281 281 extern struct argp bench_local_storage_create_argp; 282 282 extern struct argp bench_htab_mem_argp; 283 283 extern struct argp bench_trigger_batch_argp; 284 + extern struct argp bench_crypto_argp; 284 285 285 286 static const struct argp_child bench_parsers[] = { 286 287 { &bench_ringbufs_argp, 0, "Ring buffers benchmark", 0 }, ··· 295 294 { &bench_local_storage_create_argp, 0, "local-storage-create benchmark", 0 }, 296 295 { &bench_htab_mem_argp, 0, "hash map memory benchmark", 0 }, 297 296 { &bench_trigger_batch_argp, 0, "BPF triggering benchmark", 0 }, 297 + { &bench_crypto_argp, 0, "bpf crypto benchmark", 0 }, 298 298 {}, 299 299 }; 300 300 ··· 540 538 extern const struct bench bench_bpf_hashmap_lookup; 541 539 extern const struct bench bench_local_storage_create; 542 540 extern const struct bench bench_htab_mem; 541 + extern const struct bench bench_crypto_encrypt; 542 + extern const struct bench bench_crypto_decrypt; 543 543 544 544 static const struct bench *benchs[] = { 545 545 &bench_count_global, ··· 594 590 &bench_bpf_hashmap_lookup, 595 591 &bench_local_storage_create, 596 592 &bench_htab_mem, 593 + &bench_crypto_encrypt, 594 + &bench_crypto_decrypt, 597 595 }; 598 596 599 597 static void find_benchmark(void)
+185
tools/testing/selftests/bpf/benchs/bench_bpf_crypto.c
··· 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 + 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 + 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 + 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 + 135 + static void crypto_encrypt_setup(void) 136 + { 137 + crypto_setup(); 138 + ctx.pfd = bpf_program__fd(ctx.skel->progs.crypto_encrypt); 139 + } 140 + 141 + static void crypto_decrypt_setup(void) 142 + { 143 + crypto_setup(); 144 + ctx.pfd = bpf_program__fd(ctx.skel->progs.crypto_decrypt); 145 + } 146 + 147 + static void crypto_measure(struct bench_res *res) 148 + { 149 + res->hits = atomic_swap(&ctx.skel->bss->hits, 0); 150 + } 151 + 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 + };
+109
tools/testing/selftests/bpf/progs/crypto_bench.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ 3 + 4 + #include "vmlinux.h" 5 + #include "bpf_tracing_net.h" 6 + #include <bpf/bpf_helpers.h> 7 + #include <bpf/bpf_endian.h> 8 + #include <bpf/bpf_tracing.h> 9 + #include "bpf_misc.h" 10 + #include "bpf_kfuncs.h" 11 + #include "crypto_common.h" 12 + 13 + const volatile unsigned int len = 16; 14 + char cipher[128] = {}; 15 + u32 key_len, authsize; 16 + char dst[256] = {}; 17 + u8 key[256] = {}; 18 + long hits = 0; 19 + int status; 20 + 21 + SEC("syscall") 22 + int crypto_setup(void *args) 23 + { 24 + struct bpf_crypto_ctx *cctx; 25 + struct bpf_crypto_params params = { 26 + .type = "skcipher", 27 + .key_len = key_len, 28 + .authsize = authsize, 29 + }; 30 + int err = 0; 31 + 32 + status = 0; 33 + 34 + if (!cipher[0] || !key_len || key_len > 256) { 35 + status = -EINVAL; 36 + return 0; 37 + } 38 + 39 + __builtin_memcpy(&params.algo, cipher, sizeof(cipher)); 40 + __builtin_memcpy(&params.key, key, sizeof(key)); 41 + cctx = bpf_crypto_ctx_create(&params, sizeof(params), &err); 42 + 43 + if (!cctx) { 44 + status = err; 45 + return 0; 46 + } 47 + 48 + err = crypto_ctx_insert(cctx); 49 + if (err && err != -EEXIST) 50 + status = err; 51 + 52 + return 0; 53 + } 54 + 55 + SEC("tc") 56 + int crypto_encrypt(struct __sk_buff *skb) 57 + { 58 + struct __crypto_ctx_value *v; 59 + struct bpf_crypto_ctx *ctx; 60 + struct bpf_dynptr psrc, pdst, iv; 61 + 62 + v = crypto_ctx_value_lookup(); 63 + if (!v) { 64 + status = -ENOENT; 65 + return 0; 66 + } 67 + 68 + ctx = v->ctx; 69 + if (!ctx) { 70 + status = -ENOENT; 71 + return 0; 72 + } 73 + 74 + bpf_dynptr_from_skb(skb, 0, &psrc); 75 + bpf_dynptr_from_mem(dst, len, 0, &pdst); 76 + bpf_dynptr_from_mem(dst, 0, 0, &iv); 77 + 78 + status = bpf_crypto_encrypt(ctx, &psrc, &pdst, &iv); 79 + __sync_add_and_fetch(&hits, 1); 80 + 81 + return 0; 82 + } 83 + 84 + SEC("tc") 85 + int crypto_decrypt(struct __sk_buff *skb) 86 + { 87 + struct bpf_dynptr psrc, pdst, iv; 88 + struct __crypto_ctx_value *v; 89 + struct bpf_crypto_ctx *ctx; 90 + 91 + v = crypto_ctx_value_lookup(); 92 + if (!v) 93 + return -ENOENT; 94 + 95 + ctx = v->ctx; 96 + if (!ctx) 97 + return -ENOENT; 98 + 99 + bpf_dynptr_from_skb(skb, 0, &psrc); 100 + bpf_dynptr_from_mem(dst, len, 0, &pdst); 101 + bpf_dynptr_from_mem(dst, 0, 0, &iv); 102 + 103 + status = bpf_crypto_decrypt(ctx, &psrc, &pdst, &iv); 104 + __sync_add_and_fetch(&hits, 1); 105 + 106 + return 0; 107 + } 108 + 109 + char __license[] SEC("license") = "GPL";