-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Vadim Fedorenko
authored and
Martin KaFai Lau
committed
Apr 24, 2024
1 parent
91541ab
commit 8000e62
Showing
4 changed files
with
302 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ | ||
|
||
#include <argp.h> | ||
#include "bench.h" | ||
#include "crypto_bench.skel.h" | ||
|
||
#define MAX_CIPHER_LEN 32 | ||
static char *input; | ||
static struct crypto_ctx { | ||
struct crypto_bench *skel; | ||
int pfd; | ||
} ctx; | ||
|
||
static struct crypto_args { | ||
u32 crypto_len; | ||
char *crypto_cipher; | ||
} args = { | ||
.crypto_len = 16, | ||
.crypto_cipher = "ecb(aes)", | ||
}; | ||
|
||
enum { | ||
ARG_CRYPTO_LEN = 5000, | ||
ARG_CRYPTO_CIPHER = 5001, | ||
}; | ||
|
||
static const struct argp_option opts[] = { | ||
{ "crypto-len", ARG_CRYPTO_LEN, "CRYPTO_LEN", 0, | ||
"Set the length of crypto buffer" }, | ||
{ "crypto-cipher", ARG_CRYPTO_CIPHER, "CRYPTO_CIPHER", 0, | ||
"Set the cipher to use (default:ecb(aes))" }, | ||
{}, | ||
}; | ||
|
||
static error_t crypto_parse_arg(int key, char *arg, struct argp_state *state) | ||
{ | ||
switch (key) { | ||
case ARG_CRYPTO_LEN: | ||
args.crypto_len = strtoul(arg, NULL, 10); | ||
if (!args.crypto_len || | ||
args.crypto_len > sizeof(ctx.skel->bss->dst)) { | ||
fprintf(stderr, "Invalid crypto buffer len (limit %zu)\n", | ||
sizeof(ctx.skel->bss->dst)); | ||
argp_usage(state); | ||
} | ||
break; | ||
case ARG_CRYPTO_CIPHER: | ||
args.crypto_cipher = strdup(arg); | ||
if (!strlen(args.crypto_cipher) || | ||
strlen(args.crypto_cipher) > MAX_CIPHER_LEN) { | ||
fprintf(stderr, "Invalid crypto cipher len (limit %d)\n", | ||
MAX_CIPHER_LEN); | ||
argp_usage(state); | ||
} | ||
break; | ||
default: | ||
return ARGP_ERR_UNKNOWN; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
const struct argp bench_crypto_argp = { | ||
.options = opts, | ||
.parser = crypto_parse_arg, | ||
}; | ||
|
||
static void crypto_validate(void) | ||
{ | ||
if (env.consumer_cnt != 0) { | ||
fprintf(stderr, "bpf crypto benchmark doesn't support consumer!\n"); | ||
exit(1); | ||
} | ||
} | ||
|
||
static void crypto_setup(void) | ||
{ | ||
LIBBPF_OPTS(bpf_test_run_opts, opts); | ||
|
||
int err, pfd; | ||
size_t i, sz; | ||
|
||
sz = args.crypto_len; | ||
if (!sz || sz > sizeof(ctx.skel->bss->dst)) { | ||
fprintf(stderr, "invalid encrypt buffer size (source %zu, target %zu)\n", | ||
sz, sizeof(ctx.skel->bss->dst)); | ||
exit(1); | ||
} | ||
|
||
setup_libbpf(); | ||
|
||
ctx.skel = crypto_bench__open(); | ||
if (!ctx.skel) { | ||
fprintf(stderr, "failed to open skeleton\n"); | ||
exit(1); | ||
} | ||
|
||
snprintf(ctx.skel->bss->cipher, 128, "%s", args.crypto_cipher); | ||
memcpy(ctx.skel->bss->key, "12345678testtest", 16); | ||
ctx.skel->bss->key_len = 16; | ||
ctx.skel->bss->authsize = 0; | ||
|
||
srandom(time(NULL)); | ||
input = malloc(sz); | ||
for (i = 0; i < sz - 1; i++) | ||
input[i] = '1' + random() % 9; | ||
input[sz - 1] = '\0'; | ||
|
||
ctx.skel->rodata->len = args.crypto_len; | ||
|
||
err = crypto_bench__load(ctx.skel); | ||
if (err) { | ||
fprintf(stderr, "failed to load skeleton\n"); | ||
crypto_bench__destroy(ctx.skel); | ||
exit(1); | ||
} | ||
|
||
pfd = bpf_program__fd(ctx.skel->progs.crypto_setup); | ||
if (pfd < 0) { | ||
fprintf(stderr, "failed to get fd for setup prog\n"); | ||
crypto_bench__destroy(ctx.skel); | ||
exit(1); | ||
} | ||
|
||
err = bpf_prog_test_run_opts(pfd, &opts); | ||
if (err || ctx.skel->bss->status) { | ||
fprintf(stderr, "failed to run setup prog: err %d, status %d\n", | ||
err, ctx.skel->bss->status); | ||
crypto_bench__destroy(ctx.skel); | ||
exit(1); | ||
} | ||
} | ||
|
||
static void crypto_encrypt_setup(void) | ||
{ | ||
crypto_setup(); | ||
ctx.pfd = bpf_program__fd(ctx.skel->progs.crypto_encrypt); | ||
} | ||
|
||
static void crypto_decrypt_setup(void) | ||
{ | ||
crypto_setup(); | ||
ctx.pfd = bpf_program__fd(ctx.skel->progs.crypto_decrypt); | ||
} | ||
|
||
static void crypto_measure(struct bench_res *res) | ||
{ | ||
res->hits = atomic_swap(&ctx.skel->bss->hits, 0); | ||
} | ||
|
||
static void *crypto_producer(void *unused) | ||
{ | ||
LIBBPF_OPTS(bpf_test_run_opts, opts, | ||
.repeat = 64, | ||
.data_in = input, | ||
.data_size_in = args.crypto_len, | ||
); | ||
|
||
while (true) | ||
(void)bpf_prog_test_run_opts(ctx.pfd, &opts); | ||
return NULL; | ||
} | ||
|
||
const struct bench bench_crypto_encrypt = { | ||
.name = "crypto-encrypt", | ||
.argp = &bench_crypto_argp, | ||
.validate = crypto_validate, | ||
.setup = crypto_encrypt_setup, | ||
.producer_thread = crypto_producer, | ||
.measure = crypto_measure, | ||
.report_progress = hits_drops_report_progress, | ||
.report_final = hits_drops_report_final, | ||
}; | ||
|
||
const struct bench bench_crypto_decrypt = { | ||
.name = "crypto-decrypt", | ||
.argp = &bench_crypto_argp, | ||
.validate = crypto_validate, | ||
.setup = crypto_decrypt_setup, | ||
.producer_thread = crypto_producer, | ||
.measure = crypto_measure, | ||
.report_progress = hits_drops_report_progress, | ||
.report_final = hits_drops_report_final, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ | ||
|
||
#include "vmlinux.h" | ||
#include "bpf_tracing_net.h" | ||
#include <bpf/bpf_helpers.h> | ||
#include <bpf/bpf_endian.h> | ||
#include <bpf/bpf_tracing.h> | ||
#include "bpf_misc.h" | ||
#include "bpf_kfuncs.h" | ||
#include "crypto_common.h" | ||
|
||
const volatile unsigned int len = 16; | ||
char cipher[128] = {}; | ||
u32 key_len, authsize; | ||
char dst[256] = {}; | ||
u8 key[256] = {}; | ||
long hits = 0; | ||
int status; | ||
|
||
SEC("syscall") | ||
int crypto_setup(void *args) | ||
{ | ||
struct bpf_crypto_ctx *cctx; | ||
struct bpf_crypto_params params = { | ||
.type = "skcipher", | ||
.key_len = key_len, | ||
.authsize = authsize, | ||
}; | ||
int err = 0; | ||
|
||
status = 0; | ||
|
||
if (!cipher[0] || !key_len || key_len > 256) { | ||
status = -EINVAL; | ||
return 0; | ||
} | ||
|
||
__builtin_memcpy(¶ms.algo, cipher, sizeof(cipher)); | ||
__builtin_memcpy(¶ms.key, key, sizeof(key)); | ||
cctx = bpf_crypto_ctx_create(¶ms, sizeof(params), &err); | ||
|
||
if (!cctx) { | ||
status = err; | ||
return 0; | ||
} | ||
|
||
err = crypto_ctx_insert(cctx); | ||
if (err && err != -EEXIST) | ||
status = err; | ||
|
||
return 0; | ||
} | ||
|
||
SEC("tc") | ||
int crypto_encrypt(struct __sk_buff *skb) | ||
{ | ||
struct __crypto_ctx_value *v; | ||
struct bpf_crypto_ctx *ctx; | ||
struct bpf_dynptr psrc, pdst, iv; | ||
|
||
v = crypto_ctx_value_lookup(); | ||
if (!v) { | ||
status = -ENOENT; | ||
return 0; | ||
} | ||
|
||
ctx = v->ctx; | ||
if (!ctx) { | ||
status = -ENOENT; | ||
return 0; | ||
} | ||
|
||
bpf_dynptr_from_skb(skb, 0, &psrc); | ||
bpf_dynptr_from_mem(dst, len, 0, &pdst); | ||
bpf_dynptr_from_mem(dst, 0, 0, &iv); | ||
|
||
status = bpf_crypto_encrypt(ctx, &psrc, &pdst, &iv); | ||
__sync_add_and_fetch(&hits, 1); | ||
|
||
return 0; | ||
} | ||
|
||
SEC("tc") | ||
int crypto_decrypt(struct __sk_buff *skb) | ||
{ | ||
struct bpf_dynptr psrc, pdst, iv; | ||
struct __crypto_ctx_value *v; | ||
struct bpf_crypto_ctx *ctx; | ||
|
||
v = crypto_ctx_value_lookup(); | ||
if (!v) | ||
return -ENOENT; | ||
|
||
ctx = v->ctx; | ||
if (!ctx) | ||
return -ENOENT; | ||
|
||
bpf_dynptr_from_skb(skb, 0, &psrc); | ||
bpf_dynptr_from_mem(dst, len, 0, &pdst); | ||
bpf_dynptr_from_mem(dst, 0, 0, &iv); | ||
|
||
status = bpf_crypto_decrypt(ctx, &psrc, &pdst, &iv); | ||
__sync_add_and_fetch(&hits, 1); | ||
|
||
return 0; | ||
} | ||
|
||
char __license[] SEC("license") = "GPL"; |