/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2016-2017 Intel Corporation */ #include #include #include #include "cperf_ops.h" #include "cperf_test_vectors.h" static int cperf_set_ops_asym(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 __rte_unused, uint64_t *tsc_start __rte_unused) { uint16_t i; struct rte_cryptodev_asym_session *asym_sess = (void *)sess; for (i = 0; i < nb_ops; i++) { struct rte_crypto_asym_op *asym_op = ops[i]->asym; ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; asym_op->modex.base.data = perf_base; asym_op->modex.base.length = sizeof(perf_base); asym_op->modex.result.data = perf_mod_result; asym_op->modex.result.length = sizeof(perf_mod_result); rte_crypto_op_attach_asym_session(ops[i], asym_sess); } return 0; } #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->is_outbound) { 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, 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++) { struct rte_crypto_sym_op *sym_op = ops[i]->sym; struct rte_security_session *sec_sess = (struct rte_security_session *)sess; uint32_t buf_sz; uint32_t *per_pkt_hfn = rte_crypto_op_ctod_offset(ops[i], uint32_t *, iv_offset); *per_pkt_hfn = options->pdcp_ses_hfn_en ? 0 : PDCP_DEFAULT_HFN; ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; rte_security_attach_session(ops[i], sec_sess); sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] + src_buf_offset); 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) { if (options->imix_distribution_count) { buf_sz = options->imix_buffer_sizes[*imix_idx]; *imix_idx = (*imix_idx + 1) % options->pool_sz; } else buf_sz = options->test_buffer_size; sym_op->m_src->buf_len = options->segment_sz; sym_op->m_src->data_len = buf_sz; sym_op->m_src->pkt_len = buf_sz; /* DOCSIS header is not CRC'ed */ sym_op->auth.data.offset = options->docsis_hdr_sz; sym_op->auth.data.length = buf_sz - sym_op->auth.data.offset - RTE_ETHER_CRC_LEN; /* * DOCSIS header and SRC and DST MAC addresses are not * ciphered */ sym_op->cipher.data.offset = sym_op->auth.data.offset + RTE_ETHER_HDR_LEN - RTE_ETHER_TYPE_LEN; sym_op->cipher.data.length = buf_sz - sym_op->cipher.data.offset; } /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */ if (dst_buf_offset == 0) sym_op->m_dst = NULL; else sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] + dst_buf_offset); } return 0; } #endif static int cperf_set_ops_null_cipher(struct rte_crypto_op **ops, uint32_t src_buf_offset, uint32_t dst_buf_offset, 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, uint64_t *tsc_start __rte_unused) { uint16_t i; for (i = 0; i < nb_ops; i++) { struct rte_crypto_sym_op *sym_op = ops[i]->sym; ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; rte_crypto_op_attach_sym_session(ops[i], sess); sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] + src_buf_offset); /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */ if (dst_buf_offset == 0) sym_op->m_dst = NULL; else sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] + dst_buf_offset); /* cipher parameters */ if (options->imix_distribution_count) { sym_op->cipher.data.length = options->imix_buffer_sizes[*imix_idx]; *imix_idx = (*imix_idx + 1) % options->pool_sz; } else sym_op->cipher.data.length = options->test_buffer_size; sym_op->cipher.data.offset = 0; } return 0; } static int cperf_set_ops_null_auth(struct rte_crypto_op **ops, uint32_t src_buf_offset, uint32_t dst_buf_offset, 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, uint64_t *tsc_start __rte_unused) { uint16_t i; for (i = 0; i < nb_ops; i++) { struct rte_crypto_sym_op *sym_op = ops[i]->sym; ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; rte_crypto_op_attach_sym_session(ops[i], sess); sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] + src_buf_offset); /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */ if (dst_buf_offset == 0) sym_op->m_dst = NULL; else sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] + dst_buf_offset); /* auth parameters */ if (options->imix_distribution_count) { sym_op->auth.data.length = options->imix_buffer_sizes[*imix_idx]; *imix_idx = (*imix_idx + 1) % options->pool_sz; } else sym_op->auth.data.length = options->test_buffer_size; sym_op->auth.data.offset = 0; } return 0; } static int cperf_set_ops_cipher(struct rte_crypto_op **ops, uint32_t src_buf_offset, uint32_t dst_buf_offset, 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, uint64_t *tsc_start __rte_unused) { uint16_t i; for (i = 0; i < nb_ops; i++) { struct rte_crypto_sym_op *sym_op = ops[i]->sym; ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; rte_crypto_op_attach_sym_session(ops[i], sess); sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] + src_buf_offset); /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */ if (dst_buf_offset == 0) sym_op->m_dst = NULL; else sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] + dst_buf_offset); /* cipher parameters */ if (options->imix_distribution_count) { sym_op->cipher.data.length = options->imix_buffer_sizes[*imix_idx]; *imix_idx = (*imix_idx + 1) % options->pool_sz; } else sym_op->cipher.data.length = options->test_buffer_size; if (options->cipher_algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2 || options->cipher_algo == RTE_CRYPTO_CIPHER_KASUMI_F8 || options->cipher_algo == RTE_CRYPTO_CIPHER_ZUC_EEA3) sym_op->cipher.data.length <<= 3; sym_op->cipher.data.offset = 0; } if (options->test == CPERF_TEST_TYPE_VERIFY) { for (i = 0; i < nb_ops; i++) { uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ops[i], uint8_t *, iv_offset); memcpy(iv_ptr, test_vector->cipher_iv.data, test_vector->cipher_iv.length); } } return 0; } static int cperf_set_ops_auth(struct rte_crypto_op **ops, uint32_t src_buf_offset, uint32_t dst_buf_offset, 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, uint64_t *tsc_start __rte_unused) { uint16_t i; for (i = 0; i < nb_ops; i++) { struct rte_crypto_sym_op *sym_op = ops[i]->sym; ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; rte_crypto_op_attach_sym_session(ops[i], sess); sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] + src_buf_offset); /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */ if (dst_buf_offset == 0) sym_op->m_dst = NULL; else sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] + dst_buf_offset); if (test_vector->auth_iv.length) { uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ops[i], uint8_t *, iv_offset); memcpy(iv_ptr, test_vector->auth_iv.data, test_vector->auth_iv.length); } /* authentication parameters */ if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY) { sym_op->auth.digest.data = test_vector->digest.data; sym_op->auth.digest.phys_addr = test_vector->digest.phys_addr; } else { uint32_t offset = options->test_buffer_size; struct rte_mbuf *buf, *tbuf; if (options->out_of_place) { buf = sym_op->m_dst; } else { tbuf = sym_op->m_src; while ((tbuf->next != NULL) && (offset >= tbuf->data_len)) { offset -= tbuf->data_len; tbuf = tbuf->next; } /* * If there is not enough room in segment, * place the digest in the next segment */ if ((tbuf->data_len - offset) < options->digest_sz) { tbuf = tbuf->next; offset = 0; } buf = tbuf; } sym_op->auth.digest.data = rte_pktmbuf_mtod_offset(buf, uint8_t *, offset); sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(buf, offset); } if (options->imix_distribution_count) { sym_op->auth.data.length = options->imix_buffer_sizes[*imix_idx]; *imix_idx = (*imix_idx + 1) % options->pool_sz; } else sym_op->auth.data.length = options->test_buffer_size; if (options->auth_algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2 || options->auth_algo == RTE_CRYPTO_AUTH_KASUMI_F9 || options->auth_algo == RTE_CRYPTO_AUTH_ZUC_EIA3) sym_op->auth.data.length <<= 3; sym_op->auth.data.offset = 0; } if (options->test == CPERF_TEST_TYPE_VERIFY) { if (test_vector->auth_iv.length) { for (i = 0; i < nb_ops; i++) { uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ops[i], uint8_t *, iv_offset); memcpy(iv_ptr, test_vector->auth_iv.data, test_vector->auth_iv.length); } } } return 0; } static int cperf_set_ops_cipher_auth(struct rte_crypto_op **ops, uint32_t src_buf_offset, uint32_t dst_buf_offset, 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, uint64_t *tsc_start __rte_unused) { uint16_t i; for (i = 0; i < nb_ops; i++) { struct rte_crypto_sym_op *sym_op = ops[i]->sym; ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; rte_crypto_op_attach_sym_session(ops[i], sess); sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] + src_buf_offset); /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */ if (dst_buf_offset == 0) sym_op->m_dst = NULL; else sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] + dst_buf_offset); /* cipher parameters */ if (options->imix_distribution_count) { sym_op->cipher.data.length = options->imix_buffer_sizes[*imix_idx]; *imix_idx = (*imix_idx + 1) % options->pool_sz; } else sym_op->cipher.data.length = options->test_buffer_size; if (options->cipher_algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2 || options->cipher_algo == RTE_CRYPTO_CIPHER_KASUMI_F8 || options->cipher_algo == RTE_CRYPTO_CIPHER_ZUC_EEA3) sym_op->cipher.data.length <<= 3; sym_op->cipher.data.offset = 0; /* authentication parameters */ if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY) { sym_op->auth.digest.data = test_vector->digest.data; sym_op->auth.digest.phys_addr = test_vector->digest.phys_addr; } else { uint32_t offset = options->test_buffer_size; struct rte_mbuf *buf, *tbuf; if (options->out_of_place) { buf = sym_op->m_dst; } else { tbuf = sym_op->m_src; while ((tbuf->next != NULL) && (offset >= tbuf->data_len)) { offset -= tbuf->data_len; tbuf = tbuf->next; } /* * If there is not enough room in segment, * place the digest in the next segment */ if ((tbuf->data_len - offset) < options->digest_sz) { tbuf = tbuf->next; offset = 0; } buf = tbuf; } sym_op->auth.digest.data = rte_pktmbuf_mtod_offset(buf, uint8_t *, offset); sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(buf, offset); } if (options->imix_distribution_count) { sym_op->auth.data.length = options->imix_buffer_sizes[*imix_idx]; *imix_idx = (*imix_idx + 1) % options->pool_sz; } else sym_op->auth.data.length = options->test_buffer_size; if (options->auth_algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2 || options->auth_algo == RTE_CRYPTO_AUTH_KASUMI_F9 || options->auth_algo == RTE_CRYPTO_AUTH_ZUC_EIA3) sym_op->auth.data.length <<= 3; sym_op->auth.data.offset = 0; } if (options->test == CPERF_TEST_TYPE_VERIFY) { for (i = 0; i < nb_ops; i++) { uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ops[i], uint8_t *, iv_offset); memcpy(iv_ptr, test_vector->cipher_iv.data, test_vector->cipher_iv.length); if (test_vector->auth_iv.length) { /* * Copy IV after the crypto operation and * the cipher IV */ iv_ptr += test_vector->cipher_iv.length; memcpy(iv_ptr, test_vector->auth_iv.data, test_vector->auth_iv.length); } } } return 0; } static int cperf_set_ops_aead(struct rte_crypto_op **ops, uint32_t src_buf_offset, uint32_t dst_buf_offset, 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, uint64_t *tsc_start __rte_unused) { uint16_t i; /* AAD is placed after the IV */ uint16_t aad_offset = iv_offset + RTE_ALIGN_CEIL(test_vector->aead_iv.length, 16); for (i = 0; i < nb_ops; i++) { struct rte_crypto_sym_op *sym_op = ops[i]->sym; ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; rte_crypto_op_attach_sym_session(ops[i], sess); sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] + src_buf_offset); /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */ if (dst_buf_offset == 0) sym_op->m_dst = NULL; else sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] + dst_buf_offset); /* AEAD parameters */ if (options->imix_distribution_count) { sym_op->aead.data.length = options->imix_buffer_sizes[*imix_idx]; *imix_idx = (*imix_idx + 1) % options->pool_sz; } else sym_op->aead.data.length = options->test_buffer_size; sym_op->aead.data.offset = 0; sym_op->aead.aad.data = rte_crypto_op_ctod_offset(ops[i], uint8_t *, aad_offset); sym_op->aead.aad.phys_addr = rte_crypto_op_ctophys_offset(ops[i], aad_offset); if (options->aead_op == RTE_CRYPTO_AEAD_OP_DECRYPT) { sym_op->aead.digest.data = test_vector->digest.data; sym_op->aead.digest.phys_addr = test_vector->digest.phys_addr; } else { uint32_t offset = sym_op->aead.data.length + sym_op->aead.data.offset; struct rte_mbuf *buf, *tbuf; if (options->out_of_place) { buf = sym_op->m_dst; } else { tbuf = sym_op->m_src; while ((tbuf->next != NULL) && (offset >= tbuf->data_len)) { offset -= tbuf->data_len; tbuf = tbuf->next; } /* * If there is not enough room in segment, * place the digest in the next segment */ if ((tbuf->data_len - offset) < options->digest_sz) { tbuf = tbuf->next; offset = 0; } buf = tbuf; } sym_op->aead.digest.data = rte_pktmbuf_mtod_offset(buf, uint8_t *, offset); sym_op->aead.digest.phys_addr = rte_pktmbuf_iova_offset(buf, offset); } } if (options->test == CPERF_TEST_TYPE_VERIFY) { for (i = 0; i < nb_ops; i++) { uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ops[i], uint8_t *, iv_offset); /* * If doing AES-CCM, nonce is copied one byte * after the start of IV field, and AAD is copied * 18 bytes after the start of the AAD field. */ if (options->aead_algo == RTE_CRYPTO_AEAD_AES_CCM) { memcpy(iv_ptr + 1, test_vector->aead_iv.data, test_vector->aead_iv.length); memcpy(ops[i]->sym->aead.aad.data + 18, test_vector->aad.data, test_vector->aad.length); } else { memcpy(iv_ptr, test_vector->aead_iv.data, test_vector->aead_iv.length); memcpy(ops[i]->sym->aead.aad.data, test_vector->aad.data, test_vector->aad.length); } } } 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 auth_xform = {0}; struct rte_crypto_sym_xform *crypto_xform; struct rte_crypto_sym_xform 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; crypto_xform = &xform; } else if (options->cipher_algo != 0 && options->auth_algo != 0) { /* Setup Cipher Parameters */ xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER; 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.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; } if (options->is_outbound) { crypto_xform = &xform; xform.next = &auth_xform; auth_xform.next = NULL; } else { crypto_xform = &auth_xform; auth_xform.next = &xform; xform.next = NULL; } } 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() + 1, /**< 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, .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP, .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL, .tunnel = tunnel, } }, .userdata = NULL, .crypto_xform = crypto_xform, }; if (options->is_outbound) sess_conf.ipsec.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS; else sess_conf.ipsec.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS; 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, 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 cipher_xform; struct rte_crypto_sym_xform auth_xform; struct rte_crypto_sym_xform aead_xform; struct rte_cryptodev_sym_session *sess = NULL; struct rte_crypto_asym_xform xform = {0}; int rc; if (options->op_type == CPERF_ASYM_MODEX) { xform.next = NULL; xform.xform_type = RTE_CRYPTO_ASYM_XFORM_MODEX; xform.modex.modulus.data = perf_mod_p; xform.modex.modulus.length = sizeof(perf_mod_p); xform.modex.exponent.data = perf_mod_e; xform.modex.exponent.length = sizeof(perf_mod_e); sess = (void *)rte_cryptodev_asym_session_create(sess_mp); if (sess == NULL) return NULL; rc = rte_cryptodev_asym_session_init(dev_id, (void *)sess, &xform, priv_mp); if (rc < 0) { if (sess != NULL) { rte_cryptodev_asym_session_clear(dev_id, (void *)sess); rte_cryptodev_asym_session_free((void *)sess); } return NULL; } return sess; } #ifdef RTE_LIB_SECURITY /* * security only */ if (options->op_type == CPERF_PDCP) { /* Setup Cipher Parameters */ cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER; cipher_xform.next = NULL; cipher_xform.cipher.algo = options->cipher_algo; cipher_xform.cipher.op = options->cipher_op; cipher_xform.cipher.iv.offset = iv_offset; cipher_xform.cipher.iv.length = 4; /* cipher different than null */ if (options->cipher_algo != RTE_CRYPTO_CIPHER_NULL) { cipher_xform.cipher.key.data = test_vector->cipher_key.data; cipher_xform.cipher.key.length = test_vector->cipher_key.length; } else { cipher_xform.cipher.key.data = NULL; cipher_xform.cipher.key.length = 0; } /* Setup Auth Parameters */ if (options->auth_algo != 0) { 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 + cipher_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; } cipher_xform.next = &auth_xform; } else { cipher_xform.next = NULL; } struct rte_security_session_conf sess_conf = { .action_type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL, .protocol = RTE_SECURITY_PROTOCOL_PDCP, {.pdcp = { .bearer = 0x16, .domain = options->pdcp_domain, .pkt_dir = 0, .sn_size = options->pdcp_sn_sz, .hfn = options->pdcp_ses_hfn_en ? PDCP_DEFAULT_HFN : 0, .hfn_threshold = 0x70C0A, .hfn_ovrd = !(options->pdcp_ses_hfn_en), } }, .crypto_xform = &cipher_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); } 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; cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER; cipher_xform.next = NULL; cipher_xform.cipher.algo = options->cipher_algo; cipher_xform.cipher.op = options->cipher_op; cipher_xform.cipher.iv.offset = iv_offset; if (options->cipher_algo != RTE_CRYPTO_CIPHER_NULL) { cipher_xform.cipher.key.data = test_vector->cipher_key.data; cipher_xform.cipher.key.length = test_vector->cipher_key.length; cipher_xform.cipher.iv.length = test_vector->cipher_iv.length; } else { cipher_xform.cipher.key.data = NULL; cipher_xform.cipher.key.length = 0; cipher_xform.cipher.iv.length = 0; } cipher_xform.next = NULL; if (options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT) direction = RTE_SECURITY_DOCSIS_DOWNLINK; else direction = RTE_SECURITY_DOCSIS_UPLINK; struct rte_security_session_conf sess_conf = { .action_type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL, .protocol = RTE_SECURITY_PROTOCOL_DOCSIS, {.docsis = { .direction = direction, } }, .crypto_xform = &cipher_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); } #endif sess = rte_cryptodev_sym_session_create(sess_mp); /* * cipher only */ if (options->op_type == CPERF_CIPHER_ONLY) { cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER; cipher_xform.next = NULL; cipher_xform.cipher.algo = options->cipher_algo; cipher_xform.cipher.op = options->cipher_op; cipher_xform.cipher.iv.offset = iv_offset; /* cipher different than null */ if (options->cipher_algo != RTE_CRYPTO_CIPHER_NULL) { cipher_xform.cipher.key.data = test_vector->cipher_key.data; cipher_xform.cipher.key.length = test_vector->cipher_key.length; cipher_xform.cipher.iv.length = test_vector->cipher_iv.length; } else { cipher_xform.cipher.key.data = NULL; cipher_xform.cipher.key.length = 0; cipher_xform.cipher.iv.length = 0; } /* create crypto session */ rte_cryptodev_sym_session_init(dev_id, sess, &cipher_xform, priv_mp); /* * auth only */ } else if (options->op_type == CPERF_AUTH_ONLY) { 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; /* 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; } /* create crypto session */ rte_cryptodev_sym_session_init(dev_id, sess, &auth_xform, priv_mp); /* * cipher and auth */ } else if (options->op_type == CPERF_CIPHER_THEN_AUTH || options->op_type == CPERF_AUTH_THEN_CIPHER) { /* * cipher */ cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER; cipher_xform.next = NULL; cipher_xform.cipher.algo = options->cipher_algo; cipher_xform.cipher.op = options->cipher_op; cipher_xform.cipher.iv.offset = iv_offset; /* cipher different than null */ if (options->cipher_algo != RTE_CRYPTO_CIPHER_NULL) { cipher_xform.cipher.key.data = test_vector->cipher_key.data; cipher_xform.cipher.key.length = test_vector->cipher_key.length; cipher_xform.cipher.iv.length = test_vector->cipher_iv.length; } else { cipher_xform.cipher.key.data = NULL; cipher_xform.cipher.key.length = 0; cipher_xform.cipher.iv.length = 0; } /* * auth */ 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 + cipher_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.iv.length = test_vector->auth_iv.length; auth_xform.auth.key.length = test_vector->auth_key.length; auth_xform.auth.key.data = test_vector->auth_key.data; } 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; } /* cipher then auth */ if (options->op_type == CPERF_CIPHER_THEN_AUTH) { cipher_xform.next = &auth_xform; /* create crypto session */ rte_cryptodev_sym_session_init(dev_id, sess, &cipher_xform, priv_mp); } else { /* auth then cipher */ auth_xform.next = &cipher_xform; /* create crypto session */ rte_cryptodev_sym_session_init(dev_id, sess, &auth_xform, priv_mp); } } else { /* options->op_type == CPERF_AEAD */ aead_xform.type = RTE_CRYPTO_SYM_XFORM_AEAD; aead_xform.next = NULL; aead_xform.aead.algo = options->aead_algo; aead_xform.aead.op = options->aead_op; aead_xform.aead.iv.offset = iv_offset; aead_xform.aead.key.data = test_vector->aead_key.data; aead_xform.aead.key.length = test_vector->aead_key.length; aead_xform.aead.iv.length = test_vector->aead_iv.length; aead_xform.aead.digest_length = options->digest_sz; aead_xform.aead.aad_length = options->aead_aad_sz; /* Create crypto session */ rte_cryptodev_sym_session_init(dev_id, sess, &aead_xform, priv_mp); } return sess; } int cperf_get_op_functions(const struct cperf_options *options, struct cperf_op_fns *op_fns) { memset(op_fns, 0, sizeof(struct cperf_op_fns)); op_fns->sess_create = cperf_create_session; switch (options->op_type) { case CPERF_AEAD: op_fns->populate_ops = cperf_set_ops_aead; break; case CPERF_AUTH_THEN_CIPHER: case CPERF_CIPHER_THEN_AUTH: op_fns->populate_ops = cperf_set_ops_cipher_auth; 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; 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; break; case CPERF_ASYM_MODEX: op_fns->populate_ops = cperf_set_ops_asym; break; #ifdef RTE_LIB_SECURITY case CPERF_PDCP: case CPERF_IPSEC: case CPERF_DOCSIS: op_fns->populate_ops = cperf_set_ops_security; break; #endif default: return -1; } return 0; }