From 28dde5da503ed09f10cdfb295e390b114df7330a Mon Sep 17 00:00:00 2001 From: Akhil Goyal Date: Tue, 12 Oct 2021 15:37:19 +0530 Subject: [PATCH] app/crypto-perf: support lookaside IPsec Added support for lookaside IPsec protocol offload. Supported cases: -AEAD -Cipher+auth Command used for testing: ./dpdk-test-crypto-perf -c 0xf -- --devtype crypto_octeontx2 --ptest throughput --optype ipsec --cipher-algo aes-cbc --pool-sz 16384 --cipher-op encrypt --cipher-key-sz 16 --cipher-iv-sz 16 --auth-algo sha1-hmac --auth-op generate --digest-sz 16 --total-ops 10000000 --burst-sz 32 --buffer-sz 64,128,256,512,1024,1280,2048 ./dpdk-test-crypto-perf -c 0xf -- --devtype crypto_octeontx2 --ptest throughput --optype ipsec --aead-algo aes-gcm --pool-sz 16384 --aead-op encrypt --aead-key-sz 32 --aead-iv-sz 12 --aead-aad-sz 16 --digest-sz 16 --total-ops 10000000 --burst-sz 32 --buffer-sz 64,128,256,512,1024,1280,2048 Signed-off-by: Akhil Goyal Signed-off-by: Archana Muniganti --- app/test-crypto-perf/cperf_ops.c | 234 +++++++++++++++--- app/test-crypto-perf/cperf_ops.h | 3 +- app/test-crypto-perf/cperf_options.h | 1 + app/test-crypto-perf/cperf_options_parsing.c | 4 + app/test-crypto-perf/cperf_test_latency.c | 2 +- .../cperf_test_pmd_cyclecount.c | 4 +- app/test-crypto-perf/cperf_test_throughput.c | 5 +- app/test-crypto-perf/cperf_test_vectors.c | 21 +- app/test-crypto-perf/cperf_test_verify.c | 2 +- app/test-crypto-perf/main.c | 3 +- doc/guides/rel_notes/release_21_11.rst | 1 + 11 files changed, 233 insertions(+), 47 deletions(-) diff --git a/app/test-crypto-perf/cperf_ops.c b/app/test-crypto-perf/cperf_ops.c index 4b7d66edb2..263841c339 100644 --- a/app/test-crypto-perf/cperf_ops.c +++ b/app/test-crypto-perf/cperf_ops.c @@ -4,6 +4,7 @@ #include #include +#include #include "cperf_ops.h" #include "cperf_test_vectors.h" @@ -16,7 +17,8 @@ cperf_set_ops_asym(struct rte_crypto_op **ops, const struct cperf_options *options __rte_unused, const struct cperf_test_vector *test_vector __rte_unused, uint16_t iv_offset __rte_unused, - uint32_t *imix_idx __rte_unused) + uint32_t *imix_idx __rte_unused, + uint64_t *tsc_start __rte_unused) { uint16_t i; uint8_t result[sizeof(perf_mod_p)] = { 0 }; @@ -36,15 +38,31 @@ cperf_set_ops_asym(struct rte_crypto_op **ops, } #ifdef RTE_LIB_SECURITY +static void +test_ipsec_vec_populate(struct rte_mbuf *m, const struct cperf_options *options, + const struct cperf_test_vector *test_vector) +{ + struct rte_ipv4_hdr *ip = rte_pktmbuf_mtod(m, struct rte_ipv4_hdr *); + + if ((options->aead_op == RTE_CRYPTO_AEAD_OP_ENCRYPT) || + (options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT)) { + memcpy(ip, test_vector->plaintext.data, m->data_len); + + ip->total_length = rte_cpu_to_be_16(m->data_len); + } +} + static int cperf_set_ops_security(struct rte_crypto_op **ops, uint32_t src_buf_offset __rte_unused, uint32_t dst_buf_offset __rte_unused, uint16_t nb_ops, struct rte_cryptodev_sym_session *sess, - const struct cperf_options *options __rte_unused, - const struct cperf_test_vector *test_vector __rte_unused, - uint16_t iv_offset __rte_unused, uint32_t *imix_idx) + const struct cperf_options *options, + const struct cperf_test_vector *test_vector, + uint16_t iv_offset __rte_unused, uint32_t *imix_idx, + uint64_t *tsc_start) { + uint64_t tsc_start_temp, tsc_end_temp; uint16_t i; for (i = 0; i < nb_ops; i++) { @@ -62,10 +80,27 @@ cperf_set_ops_security(struct rte_crypto_op **ops, sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] + src_buf_offset); - if (options->op_type == CPERF_PDCP) { + if (options->op_type == CPERF_PDCP || + options->op_type == CPERF_IPSEC) { + /* In case of IPsec, headroom is consumed by PMD, + * hence resetting it. + */ + sym_op->m_src->data_off = options->headroom_sz; + sym_op->m_src->buf_len = options->segment_sz; sym_op->m_src->data_len = options->test_buffer_size; sym_op->m_src->pkt_len = sym_op->m_src->data_len; + + if ((options->op_type == CPERF_IPSEC) && + (options->test_file == NULL) && + (options->test == CPERF_TEST_TYPE_THROUGHPUT)) { + tsc_start_temp = rte_rdtsc_precise(); + test_ipsec_vec_populate(sym_op->m_src, options, + test_vector); + tsc_end_temp = rte_rdtsc_precise(); + + *tsc_start += (tsc_end_temp - tsc_start_temp); + } } if (options->op_type == CPERF_DOCSIS) { @@ -111,7 +146,8 @@ cperf_set_ops_null_cipher(struct rte_crypto_op **ops, uint16_t nb_ops, struct rte_cryptodev_sym_session *sess, const struct cperf_options *options, const struct cperf_test_vector *test_vector __rte_unused, - uint16_t iv_offset __rte_unused, uint32_t *imix_idx) + uint16_t iv_offset __rte_unused, uint32_t *imix_idx, + uint64_t *tsc_start __rte_unused) { uint16_t i; @@ -150,7 +186,8 @@ cperf_set_ops_null_auth(struct rte_crypto_op **ops, uint16_t nb_ops, struct rte_cryptodev_sym_session *sess, const struct cperf_options *options, const struct cperf_test_vector *test_vector __rte_unused, - uint16_t iv_offset __rte_unused, uint32_t *imix_idx) + uint16_t iv_offset __rte_unused, uint32_t *imix_idx, + uint64_t *tsc_start __rte_unused) { uint16_t i; @@ -189,7 +226,8 @@ cperf_set_ops_cipher(struct rte_crypto_op **ops, uint16_t nb_ops, struct rte_cryptodev_sym_session *sess, const struct cperf_options *options, const struct cperf_test_vector *test_vector, - uint16_t iv_offset, uint32_t *imix_idx) + uint16_t iv_offset, uint32_t *imix_idx, + uint64_t *tsc_start __rte_unused) { uint16_t i; @@ -245,7 +283,8 @@ cperf_set_ops_auth(struct rte_crypto_op **ops, uint16_t nb_ops, struct rte_cryptodev_sym_session *sess, const struct cperf_options *options, const struct cperf_test_vector *test_vector, - uint16_t iv_offset, uint32_t *imix_idx) + uint16_t iv_offset, uint32_t *imix_idx, + uint64_t *tsc_start __rte_unused) { uint16_t i; @@ -345,7 +384,8 @@ cperf_set_ops_cipher_auth(struct rte_crypto_op **ops, uint16_t nb_ops, struct rte_cryptodev_sym_session *sess, const struct cperf_options *options, const struct cperf_test_vector *test_vector, - uint16_t iv_offset, uint32_t *imix_idx) + uint16_t iv_offset, uint32_t *imix_idx, + uint64_t *tsc_start __rte_unused) { uint16_t i; @@ -460,7 +500,8 @@ cperf_set_ops_aead(struct rte_crypto_op **ops, uint16_t nb_ops, struct rte_cryptodev_sym_session *sess, const struct cperf_options *options, const struct cperf_test_vector *test_vector, - uint16_t iv_offset, uint32_t *imix_idx) + uint16_t iv_offset, uint32_t *imix_idx, + uint64_t *tsc_start __rte_unused) { uint16_t i; /* AAD is placed after the IV */ @@ -565,6 +606,123 @@ cperf_set_ops_aead(struct rte_crypto_op **ops, return 0; } +static struct rte_cryptodev_sym_session * +create_ipsec_session(struct rte_mempool *sess_mp, + struct rte_mempool *priv_mp, + uint8_t dev_id, + const struct cperf_options *options, + const struct cperf_test_vector *test_vector, + uint16_t iv_offset) +{ + struct rte_crypto_sym_xform xform = {0}; + struct rte_crypto_sym_xform auth_xform = {0}; + + if (options->aead_algo != 0) { + /* Setup AEAD Parameters */ + xform.type = RTE_CRYPTO_SYM_XFORM_AEAD; + xform.next = NULL; + xform.aead.algo = options->aead_algo; + xform.aead.op = options->aead_op; + xform.aead.iv.offset = iv_offset; + xform.aead.key.data = test_vector->aead_key.data; + xform.aead.key.length = test_vector->aead_key.length; + xform.aead.iv.length = test_vector->aead_iv.length; + xform.aead.digest_length = options->digest_sz; + xform.aead.aad_length = options->aead_aad_sz; + } else if (options->cipher_algo != 0 && options->auth_algo != 0) { + /* Setup Cipher Parameters */ + xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER; + xform.next = NULL; + xform.cipher.algo = options->cipher_algo; + xform.cipher.op = options->cipher_op; + xform.cipher.iv.offset = iv_offset; + xform.cipher.iv.length = test_vector->cipher_iv.length; + /* cipher different than null */ + if (options->cipher_algo != RTE_CRYPTO_CIPHER_NULL) { + xform.cipher.key.data = test_vector->cipher_key.data; + xform.cipher.key.length = + test_vector->cipher_key.length; + } else { + xform.cipher.key.data = NULL; + xform.cipher.key.length = 0; + } + + /* Setup Auth Parameters */ + auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH; + auth_xform.next = NULL; + auth_xform.auth.algo = options->auth_algo; + auth_xform.auth.op = options->auth_op; + auth_xform.auth.iv.offset = iv_offset + + xform.cipher.iv.length; + /* auth different than null */ + if (options->auth_algo != RTE_CRYPTO_AUTH_NULL) { + auth_xform.auth.digest_length = options->digest_sz; + auth_xform.auth.key.length = + test_vector->auth_key.length; + auth_xform.auth.key.data = test_vector->auth_key.data; + auth_xform.auth.iv.length = test_vector->auth_iv.length; + } else { + auth_xform.auth.digest_length = 0; + auth_xform.auth.key.length = 0; + auth_xform.auth.key.data = NULL; + auth_xform.auth.iv.length = 0; + } + + xform.next = &auth_xform; + } else { + return NULL; + } + +#define CPERF_IPSEC_SRC_IP 0x01010101 +#define CPERF_IPSEC_DST_IP 0x02020202 +#define CPERF_IPSEC_SALT 0x0 +#define CPERF_IPSEC_DEFTTL 64 + struct rte_security_ipsec_tunnel_param tunnel = { + .type = RTE_SECURITY_IPSEC_TUNNEL_IPV4, + {.ipv4 = { + .src_ip = { .s_addr = CPERF_IPSEC_SRC_IP}, + .dst_ip = { .s_addr = CPERF_IPSEC_DST_IP}, + .dscp = 0, + .df = 0, + .ttl = CPERF_IPSEC_DEFTTL, + } }, + }; + struct rte_security_session_conf sess_conf = { + .action_type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL, + .protocol = RTE_SECURITY_PROTOCOL_IPSEC, + {.ipsec = { + .spi = rte_lcore_id(), + /**< For testing sake, lcore_id is taken as SPI so that + * for every core a different session is created. + */ + .salt = CPERF_IPSEC_SALT, + .options = { 0 }, + .replay_win_sz = 0, + .direction = + ((options->cipher_op == + RTE_CRYPTO_CIPHER_OP_ENCRYPT) && + (options->auth_op == + RTE_CRYPTO_AUTH_OP_GENERATE)) || + (options->aead_op == + RTE_CRYPTO_AEAD_OP_ENCRYPT) ? + RTE_SECURITY_IPSEC_SA_DIR_EGRESS : + RTE_SECURITY_IPSEC_SA_DIR_INGRESS, + .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP, + .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL, + .tunnel = tunnel, + } }, + .userdata = NULL, + .crypto_xform = &xform + }; + + struct rte_security_ctx *ctx = (struct rte_security_ctx *) + rte_cryptodev_get_sec_ctx(dev_id); + + /* Create security session */ + return (void *)rte_security_session_create(ctx, + &sess_conf, sess_mp, priv_mp); +} + static struct rte_cryptodev_sym_session * cperf_create_session(struct rte_mempool *sess_mp, struct rte_mempool *priv_mp, @@ -675,6 +833,12 @@ cperf_create_session(struct rte_mempool *sess_mp, return (void *)rte_security_session_create(ctx, &sess_conf, sess_mp, priv_mp); } + + if (options->op_type == CPERF_IPSEC) { + return create_ipsec_session(sess_mp, priv_mp, dev_id, + options, test_vector, iv_offset); + } + if (options->op_type == CPERF_DOCSIS) { enum rte_security_docsis_direction direction; @@ -872,44 +1036,40 @@ cperf_get_op_functions(const struct cperf_options *options, op_fns->sess_create = cperf_create_session; - if (options->op_type == CPERF_ASYM_MODEX) { - op_fns->populate_ops = cperf_set_ops_asym; - return 0; - } - - if (options->op_type == CPERF_AEAD) { + switch (options->op_type) { + case CPERF_AEAD: op_fns->populate_ops = cperf_set_ops_aead; - return 0; - } + break; - if (options->op_type == CPERF_AUTH_THEN_CIPHER - || options->op_type == CPERF_CIPHER_THEN_AUTH) { + case CPERF_AUTH_THEN_CIPHER: + case CPERF_CIPHER_THEN_AUTH: op_fns->populate_ops = cperf_set_ops_cipher_auth; - return 0; - } - if (options->op_type == CPERF_AUTH_ONLY) { + break; + case CPERF_AUTH_ONLY: if (options->auth_algo == RTE_CRYPTO_AUTH_NULL) op_fns->populate_ops = cperf_set_ops_null_auth; else op_fns->populate_ops = cperf_set_ops_auth; - return 0; - } - if (options->op_type == CPERF_CIPHER_ONLY) { + break; + case CPERF_CIPHER_ONLY: if (options->cipher_algo == RTE_CRYPTO_CIPHER_NULL) op_fns->populate_ops = cperf_set_ops_null_cipher; else op_fns->populate_ops = cperf_set_ops_cipher; - return 0; - } + break; + case CPERF_ASYM_MODEX: + op_fns->populate_ops = cperf_set_ops_asym; + break; #ifdef RTE_LIB_SECURITY - if (options->op_type == CPERF_PDCP) { - op_fns->populate_ops = cperf_set_ops_security; - return 0; - } - if (options->op_type == CPERF_DOCSIS) { + case CPERF_PDCP: + case CPERF_IPSEC: + case CPERF_DOCSIS: op_fns->populate_ops = cperf_set_ops_security; - return 0; - } + break; #endif - return -1; + default: + return -1; + } + + return 0; } diff --git a/app/test-crypto-perf/cperf_ops.h b/app/test-crypto-perf/cperf_ops.h index ff125d12cd..30d38f90e3 100644 --- a/app/test-crypto-perf/cperf_ops.h +++ b/app/test-crypto-perf/cperf_ops.h @@ -23,7 +23,8 @@ typedef int (*cperf_populate_ops_t)(struct rte_crypto_op **ops, uint16_t nb_ops, struct rte_cryptodev_sym_session *sess, const struct cperf_options *options, const struct cperf_test_vector *test_vector, - uint16_t iv_offset, uint32_t *imix_idx); + uint16_t iv_offset, uint32_t *imix_idx, + uint64_t *tsc_start); struct cperf_op_fns { cperf_sessions_create_t sess_create; diff --git a/app/test-crypto-perf/cperf_options.h b/app/test-crypto-perf/cperf_options.h index f5ea2b90a5..031b238b20 100644 --- a/app/test-crypto-perf/cperf_options.h +++ b/app/test-crypto-perf/cperf_options.h @@ -80,6 +80,7 @@ enum cperf_op_type { CPERF_AEAD, CPERF_PDCP, CPERF_DOCSIS, + CPERF_IPSEC, CPERF_ASYM_MODEX }; diff --git a/app/test-crypto-perf/cperf_options_parsing.c b/app/test-crypto-perf/cperf_options_parsing.c index 2a7acb0111..c244f81bbf 100644 --- a/app/test-crypto-perf/cperf_options_parsing.c +++ b/app/test-crypto-perf/cperf_options_parsing.c @@ -458,6 +458,10 @@ parse_op_type(struct cperf_options *opts, const char *arg) cperf_op_type_strs[CPERF_DOCSIS], CPERF_DOCSIS }, + { + cperf_op_type_strs[CPERF_IPSEC], + CPERF_IPSEC + }, { cperf_op_type_strs[CPERF_ASYM_MODEX], CPERF_ASYM_MODEX diff --git a/app/test-crypto-perf/cperf_test_latency.c b/app/test-crypto-perf/cperf_test_latency.c index 159fe8492b..69f55de50a 100644 --- a/app/test-crypto-perf/cperf_test_latency.c +++ b/app/test-crypto-perf/cperf_test_latency.c @@ -200,7 +200,7 @@ cperf_latency_test_runner(void *arg) ctx->dst_buf_offset, burst_size, ctx->sess, ctx->options, ctx->test_vector, iv_offset, - &imix_idx); + &imix_idx, NULL); tsc_start = rte_rdtsc_precise(); diff --git a/app/test-crypto-perf/cperf_test_pmd_cyclecount.c b/app/test-crypto-perf/cperf_test_pmd_cyclecount.c index 844659aeca..fda97e8ab9 100644 --- a/app/test-crypto-perf/cperf_test_pmd_cyclecount.c +++ b/app/test-crypto-perf/cperf_test_pmd_cyclecount.c @@ -181,7 +181,7 @@ pmd_cyclecount_bench_ops(struct pmd_cyclecount_state *state, uint32_t cur_op, burst_size, state->ctx->sess, state->opts, state->ctx->test_vector, iv_offset, - &imix_idx); + &imix_idx, NULL); #ifdef CPERF_LINEARIZATION_ENABLE /* Check if source mbufs require coalescing */ @@ -232,7 +232,7 @@ pmd_cyclecount_build_ops(struct pmd_cyclecount_state *state, burst_size, state->ctx->sess, state->opts, state->ctx->test_vector, iv_offset, - &imix_idx); + &imix_idx, NULL); } return 0; } diff --git a/app/test-crypto-perf/cperf_test_throughput.c b/app/test-crypto-perf/cperf_test_throughput.c index 76fcda47ff..739ed9e573 100644 --- a/app/test-crypto-perf/cperf_test_throughput.c +++ b/app/test-crypto-perf/cperf_test_throughput.c @@ -42,7 +42,8 @@ cperf_throughput_test_free(struct cperf_throughput_ctx *ctx) } #ifdef RTE_LIB_SECURITY else if (ctx->options->op_type == CPERF_PDCP || - ctx->options->op_type == CPERF_DOCSIS) { + ctx->options->op_type == CPERF_DOCSIS || + ctx->options->op_type == CPERF_IPSEC) { struct rte_security_ctx *sec_ctx = (struct rte_security_ctx *) rte_cryptodev_get_sec_ctx(ctx->dev_id); @@ -185,7 +186,7 @@ cperf_throughput_test_runner(void *test_ctx) ctx->dst_buf_offset, ops_needed, ctx->sess, ctx->options, ctx->test_vector, - iv_offset, &imix_idx); + iv_offset, &imix_idx, &tsc_start); /** * When ops_needed is smaller than ops_enqd, the diff --git a/app/test-crypto-perf/cperf_test_vectors.c b/app/test-crypto-perf/cperf_test_vectors.c index 7da1a8fa2e..e578ec1434 100644 --- a/app/test-crypto-perf/cperf_test_vectors.c +++ b/app/test-crypto-perf/cperf_test_vectors.c @@ -428,6 +428,18 @@ uint8_t aead_key[] = { /* Digests */ uint8_t digest[2048] = { 0x00 }; +uint8_t ipsec_plaintext[2048] = { + /* IP */ + 0x45, 0x00, 0x00, 0x28, 0xa4, 0xad, 0x40, 0x00, + 0x40, 0x06, 0x78, 0x80, 0x0a, 0x01, 0x03, 0x8f, + 0x0a, 0x01, 0x06, 0x12, + + /* TCP */ + 0x80, 0x23, 0x06, 0xb8, 0xcb, 0x71, 0x26, 0x02, + 0xdd, 0x6b, 0xb0, 0x3e, 0x50, 0x10, 0x16, 0xd0, + 0x75, 0x67, 0x00, 0x01 +}; + struct cperf_test_vector* cperf_test_vector_get_dummy(struct cperf_options *options) { @@ -448,7 +460,8 @@ cperf_test_vector_get_dummy(struct cperf_options *options) t_vec->modex.elen = sizeof(perf_mod_e); } - if (options->op_type == CPERF_PDCP) { + if (options->op_type == CPERF_PDCP || + options->op_type == CPERF_IPSEC) { if (options->cipher_algo == RTE_CRYPTO_CIPHER_NULL) { t_vec->cipher_key.length = 0; t_vec->ciphertext.data = plaintext; @@ -459,6 +472,9 @@ cperf_test_vector_get_dummy(struct cperf_options *options) t_vec->cipher_key.data = cipher_key; } + if (options->op_type == CPERF_IPSEC) + t_vec->plaintext.data = ipsec_plaintext; + /* Init IV data ptr */ t_vec->cipher_iv.data = NULL; @@ -579,7 +595,8 @@ cperf_test_vector_get_dummy(struct cperf_options *options) t_vec->auth_iv.length = options->auth_iv_sz; } - if (options->op_type == CPERF_AEAD) { + if (options->op_type == CPERF_AEAD || + options->op_type == CPERF_IPSEC) { t_vec->aead_key.length = options->aead_key_sz; t_vec->aead_key.data = aead_key; diff --git a/app/test-crypto-perf/cperf_test_verify.c b/app/test-crypto-perf/cperf_test_verify.c index 2939aeaa93..1962438034 100644 --- a/app/test-crypto-perf/cperf_test_verify.c +++ b/app/test-crypto-perf/cperf_test_verify.c @@ -299,7 +299,7 @@ cperf_verify_test_runner(void *test_ctx) (ctx->populate_ops)(ops, ctx->src_buf_offset, ctx->dst_buf_offset, ops_needed, ctx->sess, ctx->options, - ctx->test_vector, iv_offset, &imix_idx); + ctx->test_vector, iv_offset, &imix_idx, NULL); /* Populate the mbuf with the test vector, for verification */ diff --git a/app/test-crypto-perf/main.c b/app/test-crypto-perf/main.c index 390380898e..6fdb92fb7c 100644 --- a/app/test-crypto-perf/main.c +++ b/app/test-crypto-perf/main.c @@ -41,6 +41,7 @@ const char *cperf_op_type_strs[] = { [CPERF_AEAD] = "aead", [CPERF_PDCP] = "pdcp", [CPERF_DOCSIS] = "docsis", + [CPERF_IPSEC] = "ipsec", [CPERF_ASYM_MODEX] = "modex" }; @@ -278,9 +279,9 @@ cperf_initialize_cryptodev(struct cperf_options *opts, uint8_t *enabled_cdevs) /* Fall through */ case CPERF_PDCP: case CPERF_DOCSIS: + case CPERF_IPSEC: /* Fall through */ default: - conf.ff_disable |= RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO; } diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst index 43bec779e1..30175246c7 100644 --- a/doc/guides/rel_notes/release_21_11.rst +++ b/doc/guides/rel_notes/release_21_11.rst @@ -175,6 +175,7 @@ New Features * Added support for asymmetric crypto throughput performance measurement. Only modex is supported for now. + * Added support for lookaside IPsec protocol offload throughput measurement. * **Added lookaside protocol (IPsec) tests in dpdk-test.** -- 2.20.1