From 61c0a3ddb84b8e43059c619299e12e9c098c7743 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Fri, 5 Apr 2019 19:42:21 +0200 Subject: [PATCH 1/1] crypto: add performace test to unittest plugin Change-Id: I49c710c5ace24a4c1f083120fd4c2972566a1695 Signed-off-by: Damjan Marion Signed-off-by: Filip Tehlar --- src/plugins/unittest/crypto/crypto.h | 9 ++ src/plugins/unittest/crypto_test.c | 189 ++++++++++++++++++++++++++++++++++- src/vnet/crypto/crypto.h | 1 + src/vnet/crypto/format.c | 21 ++++ 4 files changed, 219 insertions(+), 1 deletion(-) diff --git a/src/plugins/unittest/crypto/crypto.h b/src/plugins/unittest/crypto/crypto.h index 587d7b76a2f..ab9f706c081 100644 --- a/src/plugins/unittest/crypto/crypto.h +++ b/src/plugins/unittest/crypto/crypto.h @@ -38,6 +38,15 @@ typedef struct unittest_crypto_test_registration typedef struct { int verbose; + + /* perf */ + vnet_crypto_alg_t alg; + u32 warmup_rounds; + u32 rounds; + u32 buffer_size; + u32 n_buffers; + u8 one_key; + unittest_crypto_test_registration_t *test_registrations; } crypto_test_main_t; diff --git a/src/plugins/unittest/crypto_test.c b/src/plugins/unittest/crypto_test.c index eb73e91e186..fba1e0696aa 100644 --- a/src/plugins/unittest/crypto_test.c +++ b/src/plugins/unittest/crypto_test.c @@ -257,11 +257,182 @@ test_crypto (vlib_main_t * vm, crypto_test_main_t * tm) return 0; } +static clib_error_t * +test_crypto_perf (vlib_main_t * vm, crypto_test_main_t * tm) +{ + vnet_crypto_main_t *cm = &crypto_main; + clib_error_t *err = 0; + u32 n_buffers, n_alloc = 0, warmup_rounds, rounds; + u32 *buffer_indices = 0; + vnet_crypto_op_t *ops1 = 0, *ops2 = 0, *op1, *op2; + vnet_crypto_alg_data_t *ad = vec_elt_at_index (cm->algs, tm->alg); + int buffer_size = vlib_buffer_get_default_data_size (vm); + u64 seed = clib_cpu_time_now (); + u64 t0[5], t1[5], t2[5], n_bytes = 0; + int i, j; + u8 *key; + + if (tm->buffer_size > buffer_size) + return clib_error_return (0, "buffer size must be <= %u", buffer_size); + + rounds = tm->rounds ? tm->rounds : 100; + n_buffers = tm->n_buffers ? tm->n_buffers : 256; + buffer_size = tm->buffer_size ? tm->buffer_size : 2048; + warmup_rounds = tm->warmup_rounds ? tm->warmup_rounds : 100; + + if (buffer_size > vlib_buffer_get_default_data_size (vm)) + return clib_error_return (0, "buffer size too big"); + + vec_validate_aligned (buffer_indices, n_buffers - 1, CLIB_CACHE_LINE_BYTES); + vec_validate_aligned (ops1, n_buffers - 1, CLIB_CACHE_LINE_BYTES); + vec_validate_aligned (ops2, n_buffers - 1, CLIB_CACHE_LINE_BYTES); + + n_alloc = vlib_buffer_alloc (vm, buffer_indices, n_buffers); + if (n_alloc != n_buffers) + { + if (n_alloc) + vlib_buffer_free (vm, buffer_indices, n_alloc); + err = clib_error_return (0, "buffer alloc failure"); + goto done; + } + + vlib_cli_output (vm, "%U: n_buffers %u buffer-size %u rounds %u " + "warmup-rounds %u one-key %s", + format_vnet_crypto_alg, tm->alg, n_buffers, buffer_size, + rounds, warmup_rounds, tm->one_key ? "yes" : "no"); + vlib_cli_output (vm, " cpu-freq %.2f GHz", + (f64) vm->clib_time.clocks_per_second * 1e-9); + + vnet_crypto_op_type_t ot = 0; + + for (i = 0; i < VNET_CRYPTO_OP_N_TYPES; i++) + { + vnet_crypto_op_id_t id = ad->op_by_type[i]; + if (id == 0) + continue; + ot = i; + break; + } + + for (i = 0; i < n_buffers; i++) + { + vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]); + op1 = ops1 + i; + op2 = ops2 + i; + if (i == 0) + key = b->data - 32; + + switch (ot) + { + case VNET_CRYPTO_OP_TYPE_ENCRYPT: + case VNET_CRYPTO_OP_TYPE_DECRYPT: + vnet_crypto_op_init (op1, + ad->op_by_type[VNET_CRYPTO_OP_TYPE_ENCRYPT]); + vnet_crypto_op_init (op2, + ad->op_by_type[VNET_CRYPTO_OP_TYPE_DECRYPT]); + op1->flags = VNET_CRYPTO_OP_FLAG_INIT_IV; + op1->src = op2->src = op1->dst = op2->dst = b->data; + op1->key = op2->key = tm->one_key ? key : b->data - 32; + op1->iv = op2->iv = b->data - 64; + n_bytes += op1->len = op2->len = buffer_size; + break; + case VNET_CRYPTO_OP_TYPE_AEAD_ENCRYPT: + case VNET_CRYPTO_OP_TYPE_AEAD_DECRYPT: + vnet_crypto_op_init (op1, + ad->op_by_type + [VNET_CRYPTO_OP_TYPE_AEAD_ENCRYPT]); + vnet_crypto_op_init (op2, + ad->op_by_type + [VNET_CRYPTO_OP_TYPE_AEAD_DECRYPT]); + op1->flags = VNET_CRYPTO_OP_FLAG_INIT_IV; + op1->src = op2->src = op1->dst = op2->dst = b->data; + op1->key = op2->key = tm->one_key ? key : b->data - 32; + op1->iv = op2->iv = b->data - 64; + op1->aad = op2->aad = b->data - VLIB_BUFFER_PRE_DATA_SIZE; + op1->aad_len = op2->aad_len = 0; + n_bytes += op1->len = op2->len = buffer_size; + break; + case VNET_CRYPTO_OP_TYPE_HMAC: + vnet_crypto_op_init (op1, ad->op_by_type[VNET_CRYPTO_OP_TYPE_HMAC]); + op1->src = b->data; + op1->key = tm->one_key ? key : b->data - 32; + op1->iv = 0; + op1->digest = b->data - VLIB_BUFFER_PRE_DATA_SIZE; + op1->digest_len = 0; + n_bytes += op1->len = buffer_size; + break; + default: + return 0; + } + + for (j = -VLIB_BUFFER_PRE_DATA_SIZE; j < buffer_size; j += 8) + *(u64 *) (b->data + j) = 1 + random_u64 (&seed); + } + + for (i = 0; i < 5; i++) + { + for (j = 0; j < warmup_rounds; j++) + { + vnet_crypto_process_ops (vm, ops1, n_buffers); + if (ot != VNET_CRYPTO_OP_TYPE_HMAC) + vnet_crypto_process_ops (vm, ops2, n_buffers); + } + + t0[i] = clib_cpu_time_now (); + for (j = 0; j < rounds; j++) + vnet_crypto_process_ops (vm, ops1, n_buffers); + t1[i] = clib_cpu_time_now (); + + if (ot != VNET_CRYPTO_OP_TYPE_HMAC) + { + for (j = 0; j < rounds; j++) + vnet_crypto_process_ops (vm, ops2, n_buffers); + t2[i] = clib_cpu_time_now (); + } + } + + for (i = 0; i < 5; i++) + { + f64 tpb1 = (f64) (t1[i] - t0[i]) / (n_bytes * rounds); + f64 gbps1 = vm->clib_time.clocks_per_second * 1e-9 * 8 / tpb1; + f64 tpb2, gbps2; + + if (ot != VNET_CRYPTO_OP_TYPE_HMAC) + { + tpb2 = (f64) (t2[i] - t1[i]) / (n_bytes * rounds); + gbps2 = vm->clib_time.clocks_per_second * 1e-9 * 8 / tpb2; + vlib_cli_output (vm, "%-2u: encrypt %.03f ticks/byte, %.02f Gbps; " + "decrypt %.03f ticks/byte, %.02f Gbps", + i + 1, tpb1, gbps1, tpb2, gbps2); + } + else + { + vlib_cli_output (vm, "%-2u: hash %.03f ticks/byte, %.02f Gbps\n", + i + 1, tpb1, gbps1); + } + } + +done: + if (n_alloc) + vlib_buffer_free (vm, buffer_indices, n_alloc); + vec_free (buffer_indices); + vec_free (ops1); + vec_free (ops2); + return err; +} + static clib_error_t * test_crypto_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { crypto_test_main_t *tm = &crypto_test_main; + unittest_crypto_test_registration_t *tr; + int is_perf = 0; + + tr = tm->test_registrations; + memset (tm, 0, sizeof (crypto_test_main_t)); + tm->test_registrations = tr; + tm->alg = ~0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { @@ -269,12 +440,28 @@ test_crypto_command_fn (vlib_main_t * vm, tm->verbose = 1; else if (unformat (input, "detail")) tm->verbose = 2; + else + if (unformat (input, "perf %U", unformat_vnet_crypto_alg, &tm->alg)) + is_perf = 1; + else if (unformat (input, "buffers %u", &tm->n_buffers)) + ; + else if (unformat (input, "rounds %u", &tm->rounds)) + ; + else if (unformat (input, "warmup-rounds %u", &tm->warmup_rounds)) + ; + else if (unformat (input, "buffer-size %u", &tm->buffer_size)) + ; + else if (unformat (input, "one-key")) + tm->one_key = 1; else return clib_error_return (0, "unknown input '%U'", format_unformat_error, input); } - return test_crypto (vm, tm); + if (is_perf) + return test_crypto_perf (vm, tm); + else + return test_crypto (vm, tm); } /* *INDENT-OFF* */ diff --git a/src/vnet/crypto/crypto.h b/src/vnet/crypto/crypto.h index 5d03d52756e..92b65a4722a 100644 --- a/src/vnet/crypto/crypto.h +++ b/src/vnet/crypto/crypto.h @@ -185,6 +185,7 @@ format_function_t format_vnet_crypto_engine; format_function_t format_vnet_crypto_op; format_function_t format_vnet_crypto_op_type; format_function_t format_vnet_crypto_op_status; +unformat_function_t unformat_vnet_crypto_alg; static_always_inline void vnet_crypto_op_init (vnet_crypto_op_t * op, vnet_crypto_op_id_t type) diff --git a/src/vnet/crypto/format.c b/src/vnet/crypto/format.c index df811fe4f2f..715941e0ee7 100644 --- a/src/vnet/crypto/format.c +++ b/src/vnet/crypto/format.c @@ -26,6 +26,27 @@ format_vnet_crypto_alg (u8 * s, va_list * args) return format (s, "%s", d->name); } +uword +unformat_vnet_crypto_alg (unformat_input_t * input, va_list * args) +{ + vnet_crypto_main_t *cm = &crypto_main; + vnet_crypto_alg_t *alg = va_arg (*args, vnet_crypto_alg_t *); + uword *p; + u8 *name; + + if (!unformat (input, "%s", &name)) + return 0; + + p = hash_get_mem (cm->alg_index_by_name, name); + vec_free (name); + if (p == 0) + return 0; + + *alg = p[0]; + + return 1; +} + u8 * format_vnet_crypto_op (u8 * s, va_list * args) { -- 2.16.6