DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH 0/1] Add security perf application
@ 2022-08-11  3:59 Anoob Joseph
  2022-08-11  3:59 ` [PATCH 1/1] app/test-security-perf: add security perf app Anoob Joseph
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Anoob Joseph @ 2022-08-11  3:59 UTC (permalink / raw)
  To: Akhil Goyal, Jerin Jacob, Thomas Monjalon, Hemant Agrawal,
	Sachin Saxena, Ciara Power
  Cc: Aakash Sasidharan, dev

Add performance application to test security session create & destroy
rates supported by the security enabled cryptodev PMD. The
application would create specified number of sessions and captures the
time taken for the same before proceeding to destroy of the same. When
operating on multi-core, the number of sessions would be evenly
distributed across all cores.

The application would test with all combinations of cipher & auth
algorithms supported by the PMD.

The app is similar to 'test-flow-perf' tool which captures the rate
at which flow rules can be created and destroyed.

Anoob Joseph (1):
  app/test-security-perf: add security perf app

 MAINTAINERS                                 |   6 +
 app/meson.build                             |   1 +
 app/test-security-perf/meson.build          |  14 +
 app/test-security-perf/test_security_perf.c | 554 ++++++++++++++++++++
 doc/guides/tools/index.rst                  |   1 +
 doc/guides/tools/securityperf.rst           |  47 ++
 6 files changed, 623 insertions(+)
 create mode 100644 app/test-security-perf/meson.build
 create mode 100644 app/test-security-perf/test_security_perf.c
 create mode 100644 doc/guides/tools/securityperf.rst

--
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/1] app/test-security-perf: add security perf app
  2022-08-11  3:59 [PATCH 0/1] Add security perf application Anoob Joseph
@ 2022-08-11  3:59 ` Anoob Joseph
  2022-08-18  9:31 ` [PATCH 0/1] Add security perf application Akhil Goyal
  2022-10-21 16:38 ` [PATCH v2] app/test-security-perf: add security perf app Anoob Joseph
  2 siblings, 0 replies; 12+ messages in thread
From: Anoob Joseph @ 2022-08-11  3:59 UTC (permalink / raw)
  To: Akhil Goyal, Jerin Jacob, Thomas Monjalon, Hemant Agrawal,
	Sachin Saxena, Ciara Power
  Cc: Aakash Sasidharan, dev

Add app to test rte_security session create/destroy rates.

Signed-off-by: Anoob Joseph <anoobj@marvell.com>
Signed-off-by: Aakash Sasidharan <asasidharan@marvell.com>
---
 MAINTAINERS                                 |   6 +
 app/meson.build                             |   1 +
 app/test-security-perf/meson.build          |  14 +
 app/test-security-perf/test_security_perf.c | 554 ++++++++++++++++++++
 doc/guides/tools/index.rst                  |   1 +
 doc/guides/tools/securityperf.rst           |  47 ++
 6 files changed, 623 insertions(+)
 create mode 100644 app/test-security-perf/meson.build
 create mode 100644 app/test-security-perf/test_security_perf.c
 create mode 100644 doc/guides/tools/securityperf.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 32ffdd1a61..6f3a6363bd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1739,6 +1739,12 @@ M: Reshma Pattan <reshma.pattan@intel.com>
 F: app/proc-info/
 F: doc/guides/tools/proc_info.rst

+Security performance tool
+M: Anoob Joseph <anoobj@marvell.com>
+T: git://dpdk.org/next/dpdk-next-crypto
+F: app/test-security-perf/
+F: doc/guides/tools/securityperf.rst
+

 Other Example Applications
 --------------------------
diff --git a/app/meson.build b/app/meson.build
index 93d8c15032..ef54b90d36 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -18,6 +18,7 @@ apps = [
         'test-pmd',
         'test-regex',
         'test-sad',
+        'test-security-perf',
 ]

 default_cflags = machine_args + ['-DALLOW_EXPERIMENTAL_API']
diff --git a/app/test-security-perf/meson.build b/app/test-security-perf/meson.build
new file mode 100644
index 0000000000..076999022e
--- /dev/null
+++ b/app/test-security-perf/meson.build
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(C) 2022 Marvell.
+
+if is_windows
+    build = false
+    reason = 'not supported on Windows'
+    subdir_done()
+endif
+
+sources = files(
+        'test_security_perf.c',
+        '../test/test_cryptodev_security_ipsec.c',
+)
+deps += ['security', 'cmdline']
diff --git a/app/test-security-perf/test_security_perf.c b/app/test-security-perf/test_security_perf.c
new file mode 100644
index 0000000000..d28c7fc83c
--- /dev/null
+++ b/app/test-security-perf/test_security_perf.c
@@ -0,0 +1,554 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022, Marvell
+ */
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_cryptodev.h>
+#include <rte_eal.h>
+#include <rte_lcore.h>
+#include <rte_malloc.h>
+#include <rte_security.h>
+
+#include <app/test/test_cryptodev.h>
+#include <app/test/test_cryptodev_security_ipsec.h>
+#include <app/test/test_cryptodev_security_ipsec_test_vectors.h>
+
+#define NB_DESC 4096
+#define DEF_NB_SESSIONS (16 * 10 * 1024) /* 16 * 10K tunnels */
+
+struct lcore_conf {
+	struct rte_crypto_sym_xform cipher_xform;
+	struct rte_crypto_sym_xform auth_xform;
+	struct rte_crypto_sym_xform aead_xform;
+	uint8_t dev_id;
+	uint8_t qp_id;
+	struct test_ctx *ctx;
+};
+
+struct test_ctx {
+	struct lcore_conf lconf[RTE_MAX_LCORE];
+	void *sec_ctx;
+	struct rte_mempool *sess_mp;
+	struct rte_mempool *sess_priv_mp;
+	struct ipsec_test_data *td;
+	int nb_sess;
+	unsigned long td_idx;
+	uint8_t nb_lcores;
+	uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS];
+	bool is_inbound;
+};
+
+static struct test_ctx ctx;
+
+static int
+cryptodev_init(struct test_ctx *ctx, uint8_t nb_lcores)
+{
+	const char dev_names[][RTE_CRYPTODEV_NAME_MAX_LEN] = {
+		"crypto_cn10k",
+		"crypto_cn9k",
+		"crypto_dpaa_sec",
+		"crypto_dpaa2_sec",
+	};
+	struct rte_cryptodev_qp_conf qp_conf;
+	struct rte_cryptodev_info dev_info;
+	struct rte_cryptodev_config config;
+	unsigned int j, nb_qp, qps_reqd;
+	unsigned long i;
+	uint8_t socket_id;
+	uint32_t dev_cnt;
+	int ret, core_id;
+	void *sec_ctx;
+
+	i = 0;
+	do {
+		dev_cnt = rte_cryptodev_devices_get(dev_names[i],
+						     ctx->enabled_cdevs,
+						     RTE_CRYPTO_MAX_DEVS);
+		i++;
+	} while (dev_cnt == 0 && i < RTE_DIM(dev_names));
+
+	if (dev_cnt == 0)
+		return -1;
+
+	/* Check first device for capabilities */
+	rte_cryptodev_info_get(0, &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_SECURITY)) {
+		RTE_LOG(ERR, USER1,
+			"Security not supported by the cryptodev\n");
+		return -1;
+	}
+
+	sec_ctx = rte_cryptodev_get_sec_ctx(0);
+	ctx->sec_ctx = sec_ctx;
+
+	socket_id = rte_socket_id();
+	qps_reqd = nb_lcores;
+	core_id = 0;
+	i = 0;
+
+	do {
+		rte_cryptodev_info_get(i, &dev_info);
+		qps_reqd = RTE_MIN(dev_info.max_nb_queue_pairs, qps_reqd);
+
+		for (j = 0; j < qps_reqd; j++) {
+			ctx->lconf[core_id].dev_id = i;
+			ctx->lconf[core_id].qp_id = j;
+			ctx->lconf[core_id].ctx = ctx;
+			core_id++;
+			if (core_id == RTE_MAX_LCORE)
+				break;
+		}
+
+		nb_qp = j;
+
+		memset(&config, 0, sizeof(config));
+		config.nb_queue_pairs = nb_qp;
+		config.socket_id = socket_id;
+
+		ret = rte_cryptodev_configure(i, &config);
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1,
+				"Could not configure cryptodev - %" PRIu64 "\n",
+				i);
+			return -1;
+		}
+
+		memset(&qp_conf, 0, sizeof(qp_conf));
+		qp_conf.nb_descriptors = NB_DESC;
+
+		for (j = 0; j < nb_qp; j++) {
+			ret = rte_cryptodev_queue_pair_setup(i, j, &qp_conf,
+							     socket_id);
+			if (ret < 0) {
+				RTE_LOG(ERR, USER1,
+					"Could not configure queue pair:"
+					" %" PRIu64 " - %d", i, j);
+				return -1;
+			}
+		}
+
+		ret = rte_cryptodev_start(i);
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1, "Could not start cryptodev");
+			return -1;
+		}
+
+		i++;
+		qps_reqd -= j;
+
+	} while (i < dev_cnt && core_id < RTE_MAX_LCORE);
+
+	return 0;
+}
+
+static int
+mempool_init(struct test_ctx *ctx, uint8_t nb_lcores)
+{
+	struct rte_mempool *sess_mpool, *sess_priv_mpool;
+	unsigned int sec_sess_sz;
+	int nb_sess_total;
+
+	nb_sess_total = ctx->nb_sess + RTE_MEMPOOL_CACHE_MAX_SIZE * nb_lcores;
+
+	sec_sess_sz = rte_security_session_get_size(ctx->sec_ctx);
+
+	sess_mpool = rte_cryptodev_sym_session_pool_create("test_sess_mp",
+			nb_sess_total, 0, RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
+			SOCKET_ID_ANY);
+	if (sess_mpool == NULL) {
+		RTE_LOG(ERR, USER1, "Could not create mempool\n");
+		return -1;
+	}
+
+	sess_priv_mpool = rte_mempool_create("test_sess_mp_priv",
+					     nb_sess_total, sec_sess_sz,
+					     RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
+					     NULL, NULL, NULL, NULL,
+					     SOCKET_ID_ANY, 0);
+	if (sess_priv_mpool == NULL) {
+		RTE_LOG(ERR, USER1, "Could not create session priv mempool");
+		rte_mempool_free(sess_mpool);
+		return -1;
+	}
+
+	ctx->sess_mp = sess_mpool;
+	ctx->sess_priv_mp = sess_priv_mpool;
+
+	return 0;
+}
+
+static int
+sec_conf_init(struct lcore_conf *conf,
+	      struct rte_security_session_conf *sess_conf,
+	      struct rte_security_ipsec_xform *ipsec_xform,
+	      const struct ipsec_test_data *td)
+{
+	uint16_t v6_src[8] = {0x2607, 0xf8b0, 0x400c, 0x0c03, 0x0000, 0x0000,
+				0x0000, 0x001a};
+	uint16_t v6_dst[8] = {0x2001, 0x0470, 0xe5bf, 0xdead, 0x4957, 0x2174,
+				0xe82c, 0x4887};
+	const struct rte_ipv4_hdr *ipv4 =
+			(const struct rte_ipv4_hdr *)td->output_text.data;
+	struct rte_security_capability_idx sec_cap_idx;
+	const struct rte_security_capability *sec_cap;
+	enum rte_security_ipsec_sa_direction dir;
+	uint32_t src, dst;
+	int salt_len;
+
+	/* Copy IPsec xform */
+	memcpy(ipsec_xform, &td->ipsec_xform, sizeof(*ipsec_xform));
+
+	dir = ipsec_xform->direction;
+
+	memcpy(&src, &ipv4->src_addr, sizeof(ipv4->src_addr));
+	memcpy(&dst, &ipv4->dst_addr, sizeof(ipv4->dst_addr));
+
+	if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
+		if (td->ipsec_xform.tunnel.type ==
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
+			memcpy(&ipsec_xform->tunnel.ipv4.src_ip, &src,
+			       sizeof(src));
+			memcpy(&ipsec_xform->tunnel.ipv4.dst_ip, &dst,
+			       sizeof(dst));
+
+		} else {
+			memcpy(&ipsec_xform->tunnel.ipv6.src_addr, &v6_src,
+			       sizeof(v6_src));
+			memcpy(&ipsec_xform->tunnel.ipv6.dst_addr, &v6_dst,
+			       sizeof(v6_dst));
+		}
+	}
+
+	sec_cap_idx.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sec_cap_idx.protocol = RTE_SECURITY_PROTOCOL_IPSEC;
+	sec_cap_idx.ipsec.proto = ipsec_xform->proto;
+	sec_cap_idx.ipsec.mode = ipsec_xform->mode;
+	sec_cap_idx.ipsec.direction = ipsec_xform->direction;
+
+	sec_cap = rte_security_capability_get(conf->ctx->sec_ctx, &sec_cap_idx);
+	if (sec_cap == NULL) {
+		RTE_LOG(ERR, USER1, "Could not get capabilities");
+		return -1;
+	}
+
+	/* Copy cipher session parameters */
+	if (td[0].aead) {
+		memcpy(&conf->aead_xform, &td[0].xform.aead,
+		       sizeof(conf->aead_xform));
+		conf->aead_xform.aead.key.data = td[0].key.data;
+		conf->aead_xform.aead.iv.offset = IV_OFFSET;
+
+		/* Verify crypto capabilities */
+		if (test_ipsec_crypto_caps_aead_verify(
+				sec_cap,
+				&conf->aead_xform) != 0) {
+			RTE_LOG(ERR, USER1,
+				"Crypto capabilities not supported\n");
+			return -1;
+		}
+	} else if (td[0].auth_only) {
+		memcpy(&conf->auth_xform, &td[0].xform.chain.auth,
+		       sizeof(conf->auth_xform));
+		conf->auth_xform.auth.key.data = td[0].auth_key.data;
+
+		if (test_ipsec_crypto_caps_auth_verify(
+				sec_cap,
+				&conf->auth_xform) != 0) {
+			RTE_LOG(INFO, USER1,
+				"Auth crypto capabilities not supported\n");
+			return -1;
+		}
+	} else {
+		memcpy(&conf->cipher_xform, &td[0].xform.chain.cipher,
+		       sizeof(conf->cipher_xform));
+		memcpy(&conf->auth_xform, &td[0].xform.chain.auth,
+		       sizeof(conf->auth_xform));
+		conf->cipher_xform.cipher.key.data = td[0].key.data;
+		conf->cipher_xform.cipher.iv.offset = IV_OFFSET;
+		conf->auth_xform.auth.key.data = td[0].auth_key.data;
+
+		/* Verify crypto capabilities */
+
+		if (test_ipsec_crypto_caps_cipher_verify(
+				sec_cap,
+				&conf->cipher_xform) != 0) {
+			RTE_LOG(ERR, USER1,
+				"Cipher crypto capabilities not supported\n");
+			return -1;
+		}
+
+		if (test_ipsec_crypto_caps_auth_verify(
+				sec_cap,
+				&conf->auth_xform) != 0) {
+			RTE_LOG(ERR, USER1,
+				"Auth crypto capabilities not supported\n");
+			return -1;
+		}
+	}
+
+	if (test_ipsec_sec_caps_verify(ipsec_xform, sec_cap, 0) != 0)
+		return -1;
+
+	sess_conf->action_type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sess_conf->protocol = RTE_SECURITY_PROTOCOL_IPSEC;
+
+	if (td[0].aead || td[0].aes_gmac) {
+		salt_len = RTE_MIN(sizeof(ipsec_xform->salt), td[0].salt.len);
+		memcpy(&ipsec_xform->salt, td[0].salt.data, salt_len);
+	}
+
+	if (td[0].aead) {
+		sess_conf->ipsec = *ipsec_xform;
+		sess_conf->crypto_xform = &conf->aead_xform;
+	} else if (td[0].auth_only) {
+		sess_conf->ipsec = *ipsec_xform;
+		sess_conf->crypto_xform = &conf->auth_xform;
+	} else {
+		sess_conf->ipsec = *ipsec_xform;
+		if (dir == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
+			sess_conf->crypto_xform = &conf->cipher_xform;
+			conf->cipher_xform.next = &conf->auth_xform;
+		} else {
+			sess_conf->crypto_xform = &conf->auth_xform;
+			conf->auth_xform.next = &conf->cipher_xform;
+		}
+	}
+
+	return 0;
+}
+
+static int
+test_security_session_perf(void *arg)
+{
+	uint64_t tsc_start, tsc_mid, tsc_end, tsc_setup_dur, tsc_destroy_dur;
+	struct rte_security_ipsec_xform ipsec_xform;
+	struct rte_security_session_conf sess_conf;
+	struct rte_mempool *sess_mp, *sess_priv_mp;
+	int i, ret, nb_sessions, nb_sess_total;
+	struct rte_security_session **sess;
+	struct rte_security_ctx *sec_ctx;
+	double setup_rate, destroy_rate;
+	uint64_t setup_ms, destroy_ms;
+	struct lcore_conf *conf = arg;
+	uint8_t nb_lcores;
+
+	nb_lcores = conf->ctx->nb_lcores;
+	nb_sess_total = conf->ctx->nb_sess;
+	sec_ctx = conf->ctx->sec_ctx;
+	sess_mp = conf->ctx->sess_mp;
+	sess_priv_mp = conf->ctx->sess_priv_mp;
+
+	nb_sessions = nb_sess_total / nb_lcores;
+
+	if (conf->qp_id == 0)
+		nb_sessions += (nb_sess_total - nb_sessions * nb_lcores);
+
+	ret = sec_conf_init(conf, &sess_conf, &ipsec_xform,
+			    &ctx.td[ctx.td_idx]);
+	if (ret) {
+		RTE_LOG(ERR, USER1, "Could not initialize session conf\n");
+		return EXIT_FAILURE;
+	}
+
+	sess = rte_zmalloc(NULL, sizeof(void *) * nb_sessions, 0);
+
+	tsc_start = rte_rdtsc_precise();
+
+	for (i = 0; i < nb_sessions; i++) {
+		sess[i] = rte_security_session_create(sec_ctx,
+						      &sess_conf,
+						      sess_mp,
+						      sess_priv_mp);
+		if (unlikely(sess[i] == NULL)) {
+			RTE_LOG(ERR, USER1, "Could not create session\n");
+			return EXIT_FAILURE;
+		}
+	}
+
+	tsc_mid = rte_rdtsc_precise();
+
+	for (i = 0; i < nb_sessions; i++) {
+		ret = rte_security_session_destroy(sec_ctx, sess[i]);
+		if (unlikely(ret < 0)) {
+			RTE_LOG(ERR, USER1, "Could not destroy session\n");
+			return EXIT_FAILURE;
+		}
+	}
+
+	tsc_end = rte_rdtsc_precise();
+
+	tsc_setup_dur = tsc_mid - tsc_start;
+	tsc_destroy_dur = tsc_end - tsc_mid;
+
+	setup_ms = tsc_setup_dur * 1000 / rte_get_tsc_hz();
+	destroy_ms = tsc_destroy_dur * 1000 / rte_get_tsc_hz();
+
+	setup_rate = (double)nb_sessions * rte_get_tsc_hz() / tsc_setup_dur;
+	destroy_rate = (double)nb_sessions * rte_get_tsc_hz() / tsc_destroy_dur;
+
+	printf("%20u%20u%20"PRIu64"%20"PRIu64"%20.2f%20.2f\n",
+			rte_lcore_id(),
+			nb_sessions,
+			setup_ms,
+			destroy_ms,
+			setup_rate,
+			destroy_rate);
+
+	return EXIT_SUCCESS;
+}
+
+static void
+usage(char *progname)
+{
+	printf("\nusage: %s\n", progname);
+	printf("  --help     : display this message and exit\n"
+	       "  --inbound  : test for inbound direction\n"
+		"           default outbound direction is tested\n"
+	       "  --nb-sess=N: to set the number of sessions\n"
+		"           to be created, default is %d\n", DEF_NB_SESSIONS);
+}
+
+static void
+args_parse(int argc, char **argv)
+{
+	char **argvopt;
+	int n, opt;
+	int opt_idx;
+
+	static const struct option lgopts[] = {
+		/* Control */
+		{ "help",    0, 0, 0 },
+		{ "inbound", 0, 0, 0 },
+		{ "nb-sess", 1, 0, 0 },
+		{ NULL, 0, 0, 0 }
+	};
+
+	argvopt = argv;
+
+	while ((opt = getopt_long(argc, argvopt, "",
+				lgopts, &opt_idx)) != EOF) {
+		switch (opt) {
+		case 0:
+			if (strcmp(lgopts[opt_idx].name, "help") == 0) {
+				usage(argv[0]);
+				exit(EXIT_SUCCESS);
+			}
+
+			if (strcmp(lgopts[opt_idx].name, "nb-sess") == 0) {
+				n = atoi(optarg);
+				if (n >= 0)
+					ctx.nb_sess = n;
+				else
+					rte_exit(EXIT_FAILURE,
+						"nb-sess should be >= 0\n");
+				printf("nb-sess %d / ", ctx.nb_sess);
+			} else if (strcmp(lgopts[opt_idx].name, "inbound") ==
+				   0) {
+				ctx.is_inbound = true;
+				printf("inbound / ");
+			}
+
+			break;
+
+		default:
+			usage(argv[0]);
+			rte_exit(EXIT_FAILURE, "Invalid option: %s\n",
+					argv[opt_idx - 1]);
+			break;
+		}
+	}
+
+	printf("\n\n");
+}
+
+int
+main(int argc, char **argv)
+{
+	struct ipsec_test_data td_outb[RTE_DIM(alg_list)];
+	struct ipsec_test_data td_inb[RTE_DIM(alg_list)];
+	struct ipsec_test_flags flags;
+	uint32_t lcore_id;
+	uint8_t nb_lcores;
+	unsigned long i;
+	int ret;
+
+	memset(&ctx, 0, sizeof(struct test_ctx));
+	memset(&flags, 0, sizeof(flags));
+
+	ret = rte_eal_init(argc, argv);
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Invalid EAL arguments!\n");
+	argc -= ret;
+	argv += ret;
+
+	nb_lcores = rte_lcore_count() - 1;
+	if (nb_lcores < 1) {
+		RTE_LOG(ERR, USER1,
+			"Number of worker cores need to be higher than 1\n");
+		return -EINVAL;
+	}
+
+	ctx.nb_sess = DEF_NB_SESSIONS + RTE_MEMPOOL_CACHE_MAX_SIZE * nb_lcores;
+
+	if (argc > 1)
+		args_parse(argc, argv);
+
+	ctx.nb_lcores = nb_lcores;
+
+	ret = cryptodev_init(&ctx, nb_lcores);
+	if (ret)
+		return EXIT_FAILURE;
+
+	ret = mempool_init(&ctx, nb_lcores);
+	if (ret)
+		return EXIT_FAILURE;
+
+	test_ipsec_alg_list_populate();
+
+	for (i = 0; i < RTE_DIM(alg_list); i++) {
+		test_ipsec_td_prepare(alg_list[i].param1,
+				      alg_list[i].param2,
+				      &flags,
+				      &td_outb[i],
+				      1);
+		if (ctx.is_inbound)
+			test_ipsec_td_in_from_out(&td_outb[i], &td_inb[i]);
+	}
+
+	ctx.td = td_outb;
+	if (ctx.is_inbound)
+		ctx.td = td_inb;
+
+	for (ctx.td_idx = 0; ctx.td_idx < RTE_DIM(alg_list); ctx.td_idx++) {
+
+		printf("\n\n    Algorithm combination:");
+		test_ipsec_display_alg(alg_list[ctx.td_idx].param1,
+				       alg_list[ctx.td_idx].param2);
+		printf("    ----------------------");
+
+		printf("\n%20s%20s%20s%20s%20s%20s\n\n",
+			"lcore id", "nb_sessions",
+			"Setup time(ms)", "Destroy time(ms)",
+			"Setup rate(sess/s)",
+			"Destroy rate(sess/sec)");
+
+		i = 0;
+		RTE_LCORE_FOREACH_WORKER(lcore_id) {
+			rte_eal_remote_launch(test_security_session_perf,
+					      &ctx.lconf[i],
+					      lcore_id);
+			i++;
+		}
+
+		RTE_LCORE_FOREACH_WORKER(lcore_id) {
+			ret |= rte_eal_wait_lcore(lcore_id);
+		}
+
+	}
+
+	return EXIT_SUCCESS;
+}
diff --git a/doc/guides/tools/index.rst b/doc/guides/tools/index.rst
index 0e5041a3f0..cee07a71b0 100644
--- a/doc/guides/tools/index.rst
+++ b/doc/guides/tools/index.rst
@@ -18,5 +18,6 @@ DPDK Tools User Guides
     testbbdev
     cryptoperf
     comp_perf
+    securityperf
     testeventdev
     testregex
diff --git a/doc/guides/tools/securityperf.rst b/doc/guides/tools/securityperf.rst
new file mode 100644
index 0000000000..d8f9c93d4c
--- /dev/null
+++ b/doc/guides/tools/securityperf.rst
@@ -0,0 +1,47 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2022 Marvell.
+
+dpdk-test-security-perf Application
+===================================
+
+The ``dpdk-test-security-perf`` tool is a Data Plane Development Kit (DPDK)
+utility to test rte_security session create/destroy rates. Test covers supported
+combinations of cipher and auth algorithms.
+
+Limitations
+~~~~~~~~~~~
+
+* Tests only ESP tunnel mode with IPv4.
+
+Running the Application
+-----------------------
+
+EAL Command-line Options
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Please refer to :doc:`EAL parameters (Linux) <../linux_gsg/linux_eal_parameters>`
+or :doc:`EAL parameters (FreeBSD) <../freebsd_gsg/freebsd_eal_parameters>` for
+a list of available EAL command-line options.
+
+Security Performance Options
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following are the command-line options for the security performance
+application. They must be separated from the EAL options, shown in the previous section,
+with a ``--`` separator:
+
+.. code-block:: console
+
+	sudo ./dpdk-test-security-perf -- --nb-sess=163840 --inbound
+
+The command-line options are:
+
+*	``--help``
+	Display a help message and quit.
+
+*	``--nb-sess``
+	Set the number of sessions to be created, default value is 163840.
+
+*	``--inbound``
+	IPsec SA direction to be tested with. By default if this option is not
+	provided, outbound direction will be tested.
--
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH 0/1] Add security perf application
  2022-08-11  3:59 [PATCH 0/1] Add security perf application Anoob Joseph
  2022-08-11  3:59 ` [PATCH 1/1] app/test-security-perf: add security perf app Anoob Joseph
@ 2022-08-18  9:31 ` Akhil Goyal
  2022-08-19  7:20   ` Anoob Joseph
  2022-10-21 16:38 ` [PATCH v2] app/test-security-perf: add security perf app Anoob Joseph
  2 siblings, 1 reply; 12+ messages in thread
From: Akhil Goyal @ 2022-08-18  9:31 UTC (permalink / raw)
  To: Anoob Joseph, Jerin Jacob Kollanukkaran, Thomas Monjalon,
	Hemant Agrawal, Sachin Saxena, Ciara Power
  Cc: Aakash Sasidharan, dev

Hi Anoob,
> Subject: [PATCH 0/1] Add security perf application
> 
> Add performance application to test security session create & destroy
> rates supported by the security enabled cryptodev PMD. The
> application would create specified number of sessions and captures the
> time taken for the same before proceeding to destroy of the same. When
> operating on multi-core, the number of sessions would be evenly
> distributed across all cores.
> 
> The application would test with all combinations of cipher & auth
> algorithms supported by the PMD.
> 
> The app is similar to 'test-flow-perf' tool which captures the rate
> at which flow rules can be created and destroyed.
> 
Is it not good to add this into dpdk-test-crypto-perf?
Can we add as a separate .c file, say, cperf_test_sec_session.c
in test-crypto-perf folder and use the existing framework.
This way we can leverage it for crypto sessions also.


> Anoob Joseph (1):
>   app/test-security-perf: add security perf app
> 
>  MAINTAINERS                                 |   6 +
>  app/meson.build                             |   1 +
>  app/test-security-perf/meson.build          |  14 +
>  app/test-security-perf/test_security_perf.c | 554 ++++++++++++++++++++
>  doc/guides/tools/index.rst                  |   1 +
>  doc/guides/tools/securityperf.rst           |  47 ++
>  6 files changed, 623 insertions(+)
>  create mode 100644 app/test-security-perf/meson.build
>  create mode 100644 app/test-security-perf/test_security_perf.c
>  create mode 100644 doc/guides/tools/securityperf.rst
> 
> --
> 2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH 0/1] Add security perf application
  2022-08-18  9:31 ` [PATCH 0/1] Add security perf application Akhil Goyal
@ 2022-08-19  7:20   ` Anoob Joseph
  2022-09-26  9:25     ` Anoob Joseph
  0 siblings, 1 reply; 12+ messages in thread
From: Anoob Joseph @ 2022-08-19  7:20 UTC (permalink / raw)
  To: Akhil Goyal
  Cc: Aakash Sasidharan, dev, techboard, Jerin Jacob Kollanukkaran,
	Thomas Monjalon, Hemant Agrawal, Sachin Saxena, Ciara Power

Hi Akhil,

Please see inline.

Thanks,
Anoob

> 
> Hi Anoob,
> > Subject: [PATCH 0/1] Add security perf application
> >
> > Add performance application to test security session create & destroy
> > rates supported by the security enabled cryptodev PMD. The application
> > would create specified number of sessions and captures the time taken
> > for the same before proceeding to destroy of the same. When operating
> > on multi-core, the number of sessions would be evenly distributed
> > across all cores.
> >
> > The application would test with all combinations of cipher & auth
> > algorithms supported by the PMD.
> >
> > The app is similar to 'test-flow-perf' tool which captures the rate at
> > which flow rules can be created and destroyed.
> >
> Is it not good to add this into dpdk-test-crypto-perf?

[Anoob] IMO, It is not good. Following are the reasons,

Dpdk-test-crypto-perf is primarily for capturing crypto operation throughputs. And so the framework allocates minimal number of sessions and the datapath function pointer etc deals with only one session. The entire framework available in that application is for populating crypto_op and mbuf, which is not required for this app. Touching that framework would mean throughput tests would get affected, which I don't think is the right thing to do. And for PMDs like Intel's (which don't have security support), it would be an unnecessary performance drop.

The proposed app currently runs for all supported ciphers while in dpdk-test-crypto-perf, it runs only for a specific algorithm combination. If we want to limit the functionality of the proposed app to match dpdk-test-crypto-perf usage, that also calls for a major rework.

And the only thing that can be reused is probably cryptodev init & queue pair configuration. As you are well aware, security device can be cryptodev or an ethdev. Dpdk-test-crypto-perf doesn't have support for initializing ethdev and rightfully so. Adding this to an already complicated framework will be counter productive in the long run.

> Can we add as a separate .c file, say, cperf_test_sec_session.c in test-crypto-
> perf folder and use the existing framework.

[Anoob] As I mentioned earlier, nothing from the framework can be leveraged for this application. If you insist on not having a new app, then all this can be integrated into dpdk-test-crypto-perf, but that will follow it's own path from very early stage (mempool allocations etc need to happen differently). And it would mean adding more command line options (which is currently at 37) as we add more options for measuring security perf.

> This way we can leverage it for crypto sessions also.
> 
> 
> > Anoob Joseph (1):
> >   app/test-security-perf: add security perf app
> >
> >  MAINTAINERS                                 |   6 +
> >  app/meson.build                             |   1 +
> >  app/test-security-perf/meson.build          |  14 +
> >  app/test-security-perf/test_security_perf.c | 554
> ++++++++++++++++++++
> >  doc/guides/tools/index.rst                  |   1 +
> >  doc/guides/tools/securityperf.rst           |  47 ++
> >  6 files changed, 623 insertions(+)
> >  create mode 100644 app/test-security-perf/meson.build
> >  create mode 100644 app/test-security-perf/test_security_perf.c
> >  create mode 100644 doc/guides/tools/securityperf.rst
> >
> > --
> > 2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH 0/1] Add security perf application
  2022-08-19  7:20   ` Anoob Joseph
@ 2022-09-26  9:25     ` Anoob Joseph
  2022-09-27 19:16       ` Akhil Goyal
  0 siblings, 1 reply; 12+ messages in thread
From: Anoob Joseph @ 2022-09-26  9:25 UTC (permalink / raw)
  To: Anoob Joseph, Akhil Goyal
  Cc: Aakash Sasidharan, dev, techboard, Jerin Jacob Kollanukkaran,
	Thomas Monjalon, Hemant Agrawal, Sachin Saxena, Ciara Power

Hi Akhil,

Do you have any further comments?

Thanks,
Anoob

> -----Original Message-----
> From: Anoob Joseph <anoobj@marvell.com>
> Sent: Friday, August 19, 2022 12:50 PM
> To: Akhil Goyal <gakhil@marvell.com>
> Cc: Aakash Sasidharan <asasidharan@marvell.com>; dev@dpdk.org;
> techboard@dpdk.org; Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Thomas
> Monjalon <thomas@monjalon.net>; Hemant Agrawal
> <hemant.agrawal@nxp.com>; Sachin Saxena <sachin.saxena@oss.nxp.com>;
> Ciara Power <ciara.power@intel.com>
> Subject: [EXT] RE: [PATCH 0/1] Add security perf application
> 
> External Email
> 
> ----------------------------------------------------------------------
> Hi Akhil,
> 
> Please see inline.
> 
> Thanks,
> Anoob
> 
> >
> > Hi Anoob,
> > > Subject: [PATCH 0/1] Add security perf application
> > >
> > > Add performance application to test security session create &
> > > destroy rates supported by the security enabled cryptodev PMD. The
> > > application would create specified number of sessions and captures
> > > the time taken for the same before proceeding to destroy of the
> > > same. When operating on multi-core, the number of sessions would be
> > > evenly distributed across all cores.
> > >
> > > The application would test with all combinations of cipher & auth
> > > algorithms supported by the PMD.
> > >
> > > The app is similar to 'test-flow-perf' tool which captures the rate
> > > at which flow rules can be created and destroyed.
> > >
> > Is it not good to add this into dpdk-test-crypto-perf?
> 
> [Anoob] IMO, It is not good. Following are the reasons,
> 
> Dpdk-test-crypto-perf is primarily for capturing crypto operation throughputs.
> And so the framework allocates minimal number of sessions and the datapath
> function pointer etc deals with only one session. The entire framework available
> in that application is for populating crypto_op and mbuf, which is not required
> for this app. Touching that framework would mean throughput tests would get
> affected, which I don't think is the right thing to do. And for PMDs like Intel's
> (which don't have security support), it would be an unnecessary performance
> drop.
> 
> The proposed app currently runs for all supported ciphers while in dpdk-test-
> crypto-perf, it runs only for a specific algorithm combination. If we want to limit
> the functionality of the proposed app to match dpdk-test-crypto-perf usage,
> that also calls for a major rework.
> 
> And the only thing that can be reused is probably cryptodev init & queue pair
> configuration. As you are well aware, security device can be cryptodev or an
> ethdev. Dpdk-test-crypto-perf doesn't have support for initializing ethdev and
> rightfully so. Adding this to an already complicated framework will be counter
> productive in the long run.
> 
> > Can we add as a separate .c file, say, cperf_test_sec_session.c in
> > test-crypto- perf folder and use the existing framework.
> 
> [Anoob] As I mentioned earlier, nothing from the framework can be leveraged
> for this application. If you insist on not having a new app, then all this can be
> integrated into dpdk-test-crypto-perf, but that will follow it's own path from
> very early stage (mempool allocations etc need to happen differently). And it
> would mean adding more command line options (which is currently at 37) as we
> add more options for measuring security perf.
> 
> > This way we can leverage it for crypto sessions also.
> >
> >
> > > Anoob Joseph (1):
> > >   app/test-security-perf: add security perf app
> > >
> > >  MAINTAINERS                                 |   6 +
> > >  app/meson.build                             |   1 +
> > >  app/test-security-perf/meson.build          |  14 +
> > >  app/test-security-perf/test_security_perf.c | 554
> > ++++++++++++++++++++
> > >  doc/guides/tools/index.rst                  |   1 +
> > >  doc/guides/tools/securityperf.rst           |  47 ++
> > >  6 files changed, 623 insertions(+)
> > >  create mode 100644 app/test-security-perf/meson.build
> > >  create mode 100644 app/test-security-perf/test_security_perf.c
> > >  create mode 100644 doc/guides/tools/securityperf.rst
> > >
> > > --
> > > 2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH 0/1] Add security perf application
  2022-09-26  9:25     ` Anoob Joseph
@ 2022-09-27 19:16       ` Akhil Goyal
  2022-09-28  7:39         ` Anoob Joseph
  0 siblings, 1 reply; 12+ messages in thread
From: Akhil Goyal @ 2022-09-27 19:16 UTC (permalink / raw)
  To: Anoob Joseph
  Cc: Aakash Sasidharan, dev, techboard, Jerin Jacob Kollanukkaran,
	Thomas Monjalon, Hemant Agrawal, Sachin Saxena, Ciara Power

Hi Anoob,
> Hi Akhil,
> 
> Do you have any further comments?
> > > > Subject: [PATCH 0/1] Add security perf application
> > > >
> > > > Add performance application to test security session create &
> > > > destroy rates supported by the security enabled cryptodev PMD. The
> > > > application would create specified number of sessions and captures
> > > > the time taken for the same before proceeding to destroy of the
> > > > same. When operating on multi-core, the number of sessions would be
> > > > evenly distributed across all cores.
> > > >
> > > > The application would test with all combinations of cipher & auth
> > > > algorithms supported by the PMD.
> > > >
> > > > The app is similar to 'test-flow-perf' tool which captures the rate
> > > > at which flow rules can be created and destroyed.
> > > >
> > > Is it not good to add this into dpdk-test-crypto-perf?
> >
> > [Anoob] IMO, It is not good. Following are the reasons,
> >
> > Dpdk-test-crypto-perf is primarily for capturing crypto operation throughputs.
> > And so the framework allocates minimal number of sessions and the datapath
> > function pointer etc deals with only one session. The entire framework
> available
> > in that application is for populating crypto_op and mbuf, which is not required
> > for this app. Touching that framework would mean throughput tests would get
> > affected, which I don't think is the right thing to do. And for PMDs like Intel's
> > (which don't have security support), it would be an unnecessary performance
> > drop.
> >
> > The proposed app currently runs for all supported ciphers while in dpdk-test-
> > crypto-perf, it runs only for a specific algorithm combination. If we want to
> limit
> > the functionality of the proposed app to match dpdk-test-crypto-perf usage,
> > that also calls for a major rework.
> >
> > And the only thing that can be reused is probably cryptodev init & queue pair
> > configuration. As you are well aware, security device can be cryptodev or an
> > ethdev. Dpdk-test-crypto-perf doesn't have support for initializing ethdev and
> > rightfully so. Adding this to an already complicated framework will be counter
> > productive in the long run.
> >
> > > Can we add as a separate .c file, say, cperf_test_sec_session.c in
> > > test-crypto- perf folder and use the existing framework.
> >
> > [Anoob] As I mentioned earlier, nothing from the framework can be leveraged
> > for this application. If you insist on not having a new app, then all this can be
> > integrated into dpdk-test-crypto-perf, but that will follow it's own path from
> > very early stage (mempool allocations etc need to happen differently). And it
> > would mean adding more command line options (which is currently at 37) as
> we
> > add more options for measuring security perf.
> >
Are you planning to add more options is that app?
if not, then adding just one more option about nb_sess would do trick in test-crypto-perf.
You would just need to add 2 new functions (test_security_session_perf and sec_conf_init)
in a new .c file in app/test-crypto-perf/ and the mempool_init is being called from
cperf_initialize_cryptodev() which we can hook to get the nb_sessions from the command line arguments.
I do not suspect any changes in datapath - so it won't be an issue.
The point is not about the things being common in the two apps. The point is whether we can
accommodate in existing app or not. We cannot have too many different apps.
We only introduce apps which are not possible to accommodate in existing ones.
I remember, there was discussion in past about having a new app for testing multi-process for crypto.
But that was dropped as we do not want too many apps.
I agree that common part would be init only but it can scale for non-security sessions easily.

Regards,
Akhil

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH 0/1] Add security perf application
  2022-09-27 19:16       ` Akhil Goyal
@ 2022-09-28  7:39         ` Anoob Joseph
  2022-10-21 15:13           ` Akhil Goyal
  0 siblings, 1 reply; 12+ messages in thread
From: Anoob Joseph @ 2022-09-28  7:39 UTC (permalink / raw)
  To: Akhil Goyal, techboard
  Cc: Aakash Sasidharan, dev, Jerin Jacob Kollanukkaran,
	Thomas Monjalon, Hemant Agrawal, Sachin Saxena, Ciara Power

Hi Akhil,

+Techboard for guidance

> I agree that common part would be init only but it can scale for non-security
> sessions easily.

Currently, dpdk-test-crypto-perf has a data path framework which prepares crypto_operations based on session. The proposed application is about measuring performance when creating and destroying sessions. So it would take rte_security_conf as the argument and current data path framework would be completely bypassed. Current dpdk-test-crypto-perf creates mbuf_pool etc and creates one session per core. This app would need larger pool for sessions and no pool for crypto_op or mbuf. Moreover, dpdk-test-crypto-perf works on cryptodev while security-perf can work on rte_ethdevs as well. I still do not see any community feedback on whether plugging rte_ethdev init etc in dpdk-test-crypto-perf is the right thing to do.

So other than basic eal_init(), I do not see anything common and even in the long run, this gulf is bound to grow. If the app has to be integrated into dpdk-test-crypto-perf, then it will be separate .c & .h files and completely branch out after very early init phase. The testing methodology and philosophy would also be different (for security-perf, we are running all algos supported as there is no need for command line parsing of all algos. CL parsing would be added for protocol features like custom AR window size). DPDK community had earlier encountered same issue with "test-flow-perf" which could have been integrated into "test-pmd" in a similar manner. But DPDK community decided to allow "test-flow-perf" and so the same logic can be applied here as well.

Thanks,
Anoob

> -----Original Message-----
> From: Akhil Goyal <gakhil@marvell.com>
> Sent: Wednesday, September 28, 2022 12:47 AM
> To: Anoob Joseph <anoobj@marvell.com>
> Cc: Aakash Sasidharan <asasidharan@marvell.com>; dev@dpdk.org;
> techboard@dpdk.org; Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
> Thomas Monjalon <thomas@monjalon.net>; Hemant Agrawal
> <hemant.agrawal@nxp.com>; Sachin Saxena
> <sachin.saxena@oss.nxp.com>; Ciara Power <ciara.power@intel.com>
> Subject: RE: [PATCH 0/1] Add security perf application
> 
> Hi Anoob,
> > Hi Akhil,
> >
> > Do you have any further comments?
> > > > > Subject: [PATCH 0/1] Add security perf application
> > > > >
> > > > > Add performance application to test security session create &
> > > > > destroy rates supported by the security enabled cryptodev PMD.
> > > > > The application would create specified number of sessions and
> > > > > captures the time taken for the same before proceeding to
> > > > > destroy of the same. When operating on multi-core, the number of
> > > > > sessions would be evenly distributed across all cores.
> > > > >
> > > > > The application would test with all combinations of cipher &
> > > > > auth algorithms supported by the PMD.
> > > > >
> > > > > The app is similar to 'test-flow-perf' tool which captures the
> > > > > rate at which flow rules can be created and destroyed.
> > > > >
> > > > Is it not good to add this into dpdk-test-crypto-perf?
> > >
> > > [Anoob] IMO, It is not good. Following are the reasons,
> > >
> > > Dpdk-test-crypto-perf is primarily for capturing crypto operation
> throughputs.
> > > And so the framework allocates minimal number of sessions and the
> > > datapath function pointer etc deals with only one session. The
> > > entire framework
> > available
> > > in that application is for populating crypto_op and mbuf, which is
> > > not required for this app. Touching that framework would mean
> > > throughput tests would get affected, which I don't think is the
> > > right thing to do. And for PMDs like Intel's (which don't have
> > > security support), it would be an unnecessary performance drop.
> > >
> > > The proposed app currently runs for all supported ciphers while in
> > > dpdk-test- crypto-perf, it runs only for a specific algorithm
> > > combination. If we want to
> > limit
> > > the functionality of the proposed app to match dpdk-test-crypto-perf
> > > usage, that also calls for a major rework.
> > >
> > > And the only thing that can be reused is probably cryptodev init &
> > > queue pair configuration. As you are well aware, security device can
> > > be cryptodev or an ethdev. Dpdk-test-crypto-perf doesn't have
> > > support for initializing ethdev and rightfully so. Adding this to an
> > > already complicated framework will be counter productive in the long
> run.
> > >
> > > > Can we add as a separate .c file, say, cperf_test_sec_session.c in
> > > > test-crypto- perf folder and use the existing framework.
> > >
> > > [Anoob] As I mentioned earlier, nothing from the framework can be
> > > leveraged for this application. If you insist on not having a new
> > > app, then all this can be integrated into dpdk-test-crypto-perf, but
> > > that will follow it's own path from very early stage (mempool
> > > allocations etc need to happen differently). And it would mean
> > > adding more command line options (which is currently at 37) as
> > we
> > > add more options for measuring security perf.
> > >
> Are you planning to add more options is that app?
> if not, then adding just one more option about nb_sess would do trick in
> test-crypto-perf.
> You would just need to add 2 new functions (test_security_session_perf and
> sec_conf_init) in a new .c file in app/test-crypto-perf/ and the mempool_init
> is being called from
> cperf_initialize_cryptodev() which we can hook to get the nb_sessions from
> the command line arguments.
> I do not suspect any changes in datapath - so it won't be an issue.
> The point is not about the things being common in the two apps. The point is
> whether we can accommodate in existing app or not. We cannot have too
> many different apps.
> We only introduce apps which are not possible to accommodate in existing
> ones.
> I remember, there was discussion in past about having a new app for testing
> multi-process for crypto.
> But that was dropped as we do not want too many apps.
> I agree that common part would be init only but it can scale for non-security
> sessions easily.
> 
> Regards,
> Akhil

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH 0/1] Add security perf application
  2022-09-28  7:39         ` Anoob Joseph
@ 2022-10-21 15:13           ` Akhil Goyal
  0 siblings, 0 replies; 12+ messages in thread
From: Akhil Goyal @ 2022-10-21 15:13 UTC (permalink / raw)
  To: Anoob Joseph, techboard
  Cc: Aakash Sasidharan, dev, Jerin Jacob Kollanukkaran,
	Thomas Monjalon, Hemant Agrawal, Sachin Saxena, Ciara Power

> Hi Akhil,
> 
> +Techboard for guidance
> 
The proposal is accepted in techboard.

Please fix compilation issues reported in CI.


> > I agree that common part would be init only but it can scale for non-security
> > sessions easily.
> 
> Currently, dpdk-test-crypto-perf has a data path framework which prepares
> crypto_operations based on session. The proposed application is about
> measuring performance when creating and destroying sessions. So it would take
> rte_security_conf as the argument and current data path framework would be
> completely bypassed. Current dpdk-test-crypto-perf creates mbuf_pool etc and
> creates one session per core. This app would need larger pool for sessions and
> no pool for crypto_op or mbuf. Moreover, dpdk-test-crypto-perf works on
> cryptodev while security-perf can work on rte_ethdevs as well. I still do not see
> any community feedback on whether plugging rte_ethdev init etc in dpdk-test-
> crypto-perf is the right thing to do.
> 
> So other than basic eal_init(), I do not see anything common and even in the
> long run, this gulf is bound to grow. If the app has to be integrated into dpdk-
> test-crypto-perf, then it will be separate .c & .h files and completely branch out
> after very early init phase. The testing methodology and philosophy would also
> be different (for security-perf, we are running all algos supported as there is no
> need for command line parsing of all algos. CL parsing would be added for
> protocol features like custom AR window size). DPDK community had earlier
> encountered same issue with "test-flow-perf" which could have been integrated
> into "test-pmd" in a similar manner. But DPDK community decided to allow
> "test-flow-perf" and so the same logic can be applied here as well.
> 
> Thanks,
> Anoob
> 
> > -----Original Message-----
> > From: Akhil Goyal <gakhil@marvell.com>
> > Sent: Wednesday, September 28, 2022 12:47 AM
> > To: Anoob Joseph <anoobj@marvell.com>
> > Cc: Aakash Sasidharan <asasidharan@marvell.com>; dev@dpdk.org;
> > techboard@dpdk.org; Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
> > Thomas Monjalon <thomas@monjalon.net>; Hemant Agrawal
> > <hemant.agrawal@nxp.com>; Sachin Saxena
> > <sachin.saxena@oss.nxp.com>; Ciara Power <ciara.power@intel.com>
> > Subject: RE: [PATCH 0/1] Add security perf application
> >
> > Hi Anoob,
> > > Hi Akhil,
> > >
> > > Do you have any further comments?
> > > > > > Subject: [PATCH 0/1] Add security perf application
> > > > > >
> > > > > > Add performance application to test security session create &
> > > > > > destroy rates supported by the security enabled cryptodev PMD.
> > > > > > The application would create specified number of sessions and
> > > > > > captures the time taken for the same before proceeding to
> > > > > > destroy of the same. When operating on multi-core, the number of
> > > > > > sessions would be evenly distributed across all cores.
> > > > > >
> > > > > > The application would test with all combinations of cipher &
> > > > > > auth algorithms supported by the PMD.
> > > > > >
> > > > > > The app is similar to 'test-flow-perf' tool which captures the
> > > > > > rate at which flow rules can be created and destroyed.
> > > > > >
> > > > > Is it not good to add this into dpdk-test-crypto-perf?
> > > >
> > > > [Anoob] IMO, It is not good. Following are the reasons,
> > > >
> > > > Dpdk-test-crypto-perf is primarily for capturing crypto operation
> > throughputs.
> > > > And so the framework allocates minimal number of sessions and the
> > > > datapath function pointer etc deals with only one session. The
> > > > entire framework
> > > available
> > > > in that application is for populating crypto_op and mbuf, which is
> > > > not required for this app. Touching that framework would mean
> > > > throughput tests would get affected, which I don't think is the
> > > > right thing to do. And for PMDs like Intel's (which don't have
> > > > security support), it would be an unnecessary performance drop.
> > > >
> > > > The proposed app currently runs for all supported ciphers while in
> > > > dpdk-test- crypto-perf, it runs only for a specific algorithm
> > > > combination. If we want to
> > > limit
> > > > the functionality of the proposed app to match dpdk-test-crypto-perf
> > > > usage, that also calls for a major rework.
> > > >
> > > > And the only thing that can be reused is probably cryptodev init &
> > > > queue pair configuration. As you are well aware, security device can
> > > > be cryptodev or an ethdev. Dpdk-test-crypto-perf doesn't have
> > > > support for initializing ethdev and rightfully so. Adding this to an
> > > > already complicated framework will be counter productive in the long
> > run.
> > > >
> > > > > Can we add as a separate .c file, say, cperf_test_sec_session.c in
> > > > > test-crypto- perf folder and use the existing framework.
> > > >
> > > > [Anoob] As I mentioned earlier, nothing from the framework can be
> > > > leveraged for this application. If you insist on not having a new
> > > > app, then all this can be integrated into dpdk-test-crypto-perf, but
> > > > that will follow it's own path from very early stage (mempool
> > > > allocations etc need to happen differently). And it would mean
> > > > adding more command line options (which is currently at 37) as
> > > we
> > > > add more options for measuring security perf.
> > > >
> > Are you planning to add more options is that app?
> > if not, then adding just one more option about nb_sess would do trick in
> > test-crypto-perf.
> > You would just need to add 2 new functions (test_security_session_perf and
> > sec_conf_init) in a new .c file in app/test-crypto-perf/ and the mempool_init
> > is being called from
> > cperf_initialize_cryptodev() which we can hook to get the nb_sessions from
> > the command line arguments.
> > I do not suspect any changes in datapath - so it won't be an issue.
> > The point is not about the things being common in the two apps. The point is
> > whether we can accommodate in existing app or not. We cannot have too
> > many different apps.
> > We only introduce apps which are not possible to accommodate in existing
> > ones.
> > I remember, there was discussion in past about having a new app for testing
> > multi-process for crypto.
> > But that was dropped as we do not want too many apps.
> > I agree that common part would be init only but it can scale for non-security
> > sessions easily.
> >
> > Regards,
> > Akhil

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2] app/test-security-perf: add security perf app
  2022-08-11  3:59 [PATCH 0/1] Add security perf application Anoob Joseph
  2022-08-11  3:59 ` [PATCH 1/1] app/test-security-perf: add security perf app Anoob Joseph
  2022-08-18  9:31 ` [PATCH 0/1] Add security perf application Akhil Goyal
@ 2022-10-21 16:38 ` Anoob Joseph
  2022-11-02 11:17   ` [PATCH v3] " Anoob Joseph
  2 siblings, 1 reply; 12+ messages in thread
From: Anoob Joseph @ 2022-10-21 16:38 UTC (permalink / raw)
  To: Akhil Goyal, Jerin Jacob, Thomas Monjalon, Hemant Agrawal,
	Sachin Saxena, Ciara Power
  Cc: Aakash Sasidharan, dev

Add performance application to test security session create & destroy
rates supported by the security enabled cryptodev PMD. The
application would create specified number of sessions and captures the
time taken for the same before proceeding to destroy of the same. When
operating on multi-core, the number of sessions would be evenly
distributed across all cores.

The application would test with all combinations of cipher & auth
algorithms supported by the PMD.

Signed-off-by: Aakash Sasidharan <asasidharan@marvell.com>
Signed-off-by: Anoob Joseph <anoobj@marvell.com>
---
v2:
* Rebased on latest code. Made changes to accommodate session rework
* Fixed debug build failure

 MAINTAINERS                                 |   6 +
 app/meson.build                             |   1 +
 app/test-security-perf/meson.build          |  14 +
 app/test-security-perf/test_security_perf.c | 575 ++++++++++++++++++++
 doc/guides/rel_notes/release_22_11.rst      |   6 +
 doc/guides/tools/index.rst                  |   1 +
 doc/guides/tools/securityperf.rst           |  47 ++
 7 files changed, 650 insertions(+)
 create mode 100644 app/test-security-perf/meson.build
 create mode 100644 app/test-security-perf/test_security_perf.c
 create mode 100644 doc/guides/tools/securityperf.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 6f56111323..14dcdd2d7f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1735,6 +1735,12 @@ M: Reshma Pattan <reshma.pattan@intel.com>
 F: app/proc-info/
 F: doc/guides/tools/proc_info.rst

+Security performance tool
+M: Anoob Joseph <anoobj@marvell.com>
+T: git://dpdk.org/next/dpdk-next-crypto
+F: app/test-security-perf/
+F: doc/guides/tools/securityperf.rst
+

 Other Example Applications
 --------------------------
diff --git a/app/meson.build b/app/meson.build
index 93d8c15032..ef54b90d36 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -18,6 +18,7 @@ apps = [
         'test-pmd',
         'test-regex',
         'test-sad',
+        'test-security-perf',
 ]

 default_cflags = machine_args + ['-DALLOW_EXPERIMENTAL_API']
diff --git a/app/test-security-perf/meson.build b/app/test-security-perf/meson.build
new file mode 100644
index 0000000000..076999022e
--- /dev/null
+++ b/app/test-security-perf/meson.build
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(C) 2022 Marvell.
+
+if is_windows
+    build = false
+    reason = 'not supported on Windows'
+    subdir_done()
+endif
+
+sources = files(
+        'test_security_perf.c',
+        '../test/test_cryptodev_security_ipsec.c',
+)
+deps += ['security', 'cmdline']
diff --git a/app/test-security-perf/test_security_perf.c b/app/test-security-perf/test_security_perf.c
new file mode 100644
index 0000000000..9bb50689e3
--- /dev/null
+++ b/app/test-security-perf/test_security_perf.c
@@ -0,0 +1,575 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022, Marvell
+ */
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_cryptodev.h>
+#include <rte_eal.h>
+#include <rte_lcore.h>
+#include <rte_malloc.h>
+#include <rte_security.h>
+
+#include <app/test/test_cryptodev.h>
+#include <app/test/test_cryptodev_security_ipsec.h>
+#include <app/test/test_cryptodev_security_ipsec_test_vectors.h>
+
+#define NB_DESC 4096
+#define DEF_NB_SESSIONS (16 * 10 * 1024) /* 16 * 10K tunnels */
+
+struct lcore_conf {
+	struct rte_crypto_sym_xform cipher_xform;
+	struct rte_crypto_sym_xform auth_xform;
+	struct rte_crypto_sym_xform aead_xform;
+	uint8_t dev_id;
+	uint8_t qp_id;
+	struct test_ctx *ctx;
+};
+
+struct test_ctx {
+	struct lcore_conf lconf[RTE_MAX_LCORE];
+	void *sec_ctx;
+	struct rte_mempool *sess_mp;
+	struct ipsec_test_data *td;
+	int nb_sess;
+	unsigned long td_idx;
+	uint8_t nb_lcores;
+	uint8_t nb_cryptodevs;
+	uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS];
+	bool is_inbound;
+};
+
+static struct test_ctx ctx;
+
+static int
+cryptodev_init(struct test_ctx *ctx, uint8_t nb_lcores)
+{
+	const char dev_names[][RTE_CRYPTODEV_NAME_MAX_LEN] = {
+		"crypto_cn10k",
+		"crypto_cn9k",
+		"crypto_dpaa_sec",
+		"crypto_dpaa2_sec",
+	};
+	struct rte_cryptodev_qp_conf qp_conf;
+	struct rte_cryptodev_info dev_info;
+	struct rte_cryptodev_config config;
+	unsigned int j, nb_qp, qps_reqd;
+	uint8_t socket_id;
+	uint32_t dev_cnt;
+	int ret, core_id;
+	void *sec_ctx;
+	uint64_t i;
+
+	i = 0;
+	do {
+		dev_cnt = rte_cryptodev_devices_get(dev_names[i],
+						     ctx->enabled_cdevs,
+						     RTE_CRYPTO_MAX_DEVS);
+		i++;
+	} while (dev_cnt == 0 && i < RTE_DIM(dev_names));
+
+	if (dev_cnt == 0)
+		return -1;
+
+	/* Check first device for capabilities */
+	rte_cryptodev_info_get(0, &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_SECURITY)) {
+		RTE_LOG(ERR, USER1,
+			"Security not supported by the cryptodev\n");
+		return -1;
+	}
+
+	sec_ctx = rte_cryptodev_get_sec_ctx(0);
+	ctx->sec_ctx = sec_ctx;
+
+	socket_id = rte_socket_id();
+	qps_reqd = nb_lcores;
+	core_id = 0;
+	i = 0;
+
+	do {
+		rte_cryptodev_info_get(i, &dev_info);
+		qps_reqd = RTE_MIN(dev_info.max_nb_queue_pairs, qps_reqd);
+
+		for (j = 0; j < qps_reqd; j++) {
+			ctx->lconf[core_id].dev_id = i;
+			ctx->lconf[core_id].qp_id = j;
+			ctx->lconf[core_id].ctx = ctx;
+			core_id++;
+			if (core_id == RTE_MAX_LCORE)
+				break;
+		}
+
+		nb_qp = j;
+
+		memset(&config, 0, sizeof(config));
+		config.nb_queue_pairs = nb_qp;
+		config.socket_id = socket_id;
+
+		ret = rte_cryptodev_configure(i, &config);
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1,
+				"Could not configure cryptodev - %" PRIu64 "\n",
+				i);
+			return -1;
+		}
+
+		memset(&qp_conf, 0, sizeof(qp_conf));
+		qp_conf.nb_descriptors = NB_DESC;
+
+		for (j = 0; j < nb_qp; j++) {
+			ret = rte_cryptodev_queue_pair_setup(i, j, &qp_conf,
+							     socket_id);
+			if (ret < 0) {
+				RTE_LOG(ERR, USER1,
+					"Could not configure queue pair:"
+					" %" PRIu64 " - %d\n", i, j);
+				return -1;
+			}
+		}
+
+		ret = rte_cryptodev_start(i);
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1, "Could not start cryptodev\n");
+			return -1;
+		}
+
+		i++;
+		qps_reqd -= j;
+
+	} while (i < dev_cnt && core_id < RTE_MAX_LCORE);
+
+	ctx->nb_cryptodevs = i;
+
+	return 0;
+}
+
+static int
+cryptodev_fini(struct test_ctx *ctx)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < ctx->nb_cryptodevs &&
+			i < RTE_CRYPTO_MAX_DEVS; i++) {
+		rte_cryptodev_stop(ctx->enabled_cdevs[i]);
+		ret = rte_cryptodev_close(ctx->enabled_cdevs[i]);
+		if (ret)
+			RTE_LOG(ERR, USER1,
+					"Crypto device close error %d\n", ret);
+	}
+
+	return ret;
+}
+
+static int
+mempool_init(struct test_ctx *ctx, uint8_t nb_lcores)
+{
+	struct rte_mempool *sess_mpool;
+	unsigned int sec_sess_sz;
+	int nb_sess_total;
+
+	nb_sess_total = ctx->nb_sess + RTE_MEMPOOL_CACHE_MAX_SIZE * nb_lcores;
+
+	sec_sess_sz = rte_security_session_get_size(ctx->sec_ctx);
+
+	sess_mpool = rte_cryptodev_sym_session_pool_create("test_sess_mp",
+			nb_sess_total, sec_sess_sz, RTE_MEMPOOL_CACHE_MAX_SIZE,
+			0, SOCKET_ID_ANY);
+	if (sess_mpool == NULL) {
+		RTE_LOG(ERR, USER1, "Could not create mempool\n");
+		return -1;
+	}
+
+	ctx->sess_mp = sess_mpool;
+
+	return 0;
+}
+
+static int
+mempool_fini(struct test_ctx *ctx)
+{
+	rte_mempool_free(ctx->sess_mp);
+
+	return 0;
+}
+
+static int
+sec_conf_init(struct lcore_conf *conf,
+	      struct rte_security_session_conf *sess_conf,
+	      struct rte_security_ipsec_xform *ipsec_xform,
+	      const struct ipsec_test_data *td)
+{
+	uint16_t v6_src[8] = {0x2607, 0xf8b0, 0x400c, 0x0c03, 0x0000, 0x0000,
+				0x0000, 0x001a};
+	uint16_t v6_dst[8] = {0x2001, 0x0470, 0xe5bf, 0xdead, 0x4957, 0x2174,
+				0xe82c, 0x4887};
+	const struct rte_ipv4_hdr *ipv4 =
+			(const struct rte_ipv4_hdr *)td->output_text.data;
+	struct rte_security_capability_idx sec_cap_idx;
+	const struct rte_security_capability *sec_cap;
+	enum rte_security_ipsec_sa_direction dir;
+	uint32_t src, dst;
+	int salt_len;
+
+	/* Copy IPsec xform */
+	memcpy(ipsec_xform, &td->ipsec_xform, sizeof(*ipsec_xform));
+
+	dir = ipsec_xform->direction;
+
+	memcpy(&src, &ipv4->src_addr, sizeof(ipv4->src_addr));
+	memcpy(&dst, &ipv4->dst_addr, sizeof(ipv4->dst_addr));
+
+	if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
+		if (td->ipsec_xform.tunnel.type ==
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
+			memcpy(&ipsec_xform->tunnel.ipv4.src_ip, &src,
+			       sizeof(src));
+			memcpy(&ipsec_xform->tunnel.ipv4.dst_ip, &dst,
+			       sizeof(dst));
+
+		} else {
+			memcpy(&ipsec_xform->tunnel.ipv6.src_addr, &v6_src,
+			       sizeof(v6_src));
+			memcpy(&ipsec_xform->tunnel.ipv6.dst_addr, &v6_dst,
+			       sizeof(v6_dst));
+		}
+	}
+
+	sec_cap_idx.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sec_cap_idx.protocol = RTE_SECURITY_PROTOCOL_IPSEC;
+	sec_cap_idx.ipsec.proto = ipsec_xform->proto;
+	sec_cap_idx.ipsec.mode = ipsec_xform->mode;
+	sec_cap_idx.ipsec.direction = ipsec_xform->direction;
+
+	sec_cap = rte_security_capability_get(conf->ctx->sec_ctx, &sec_cap_idx);
+	if (sec_cap == NULL) {
+		RTE_LOG(ERR, USER1, "Could not get capabilities\n");
+		return -1;
+	}
+
+	/* Copy cipher session parameters */
+	if (td[0].aead) {
+		memcpy(&conf->aead_xform, &td[0].xform.aead,
+		       sizeof(conf->aead_xform));
+		conf->aead_xform.aead.key.data = td[0].key.data;
+		conf->aead_xform.aead.iv.offset = IV_OFFSET;
+
+		/* Verify crypto capabilities */
+		if (test_ipsec_crypto_caps_aead_verify(
+				sec_cap,
+				&conf->aead_xform) != 0) {
+			RTE_LOG(ERR, USER1,
+				"Crypto capabilities not supported\n");
+			return -1;
+		}
+	} else if (td[0].auth_only) {
+		memcpy(&conf->auth_xform, &td[0].xform.chain.auth,
+		       sizeof(conf->auth_xform));
+		conf->auth_xform.auth.key.data = td[0].auth_key.data;
+
+		if (test_ipsec_crypto_caps_auth_verify(
+				sec_cap,
+				&conf->auth_xform) != 0) {
+			RTE_LOG(INFO, USER1,
+				"Auth crypto capabilities not supported\n");
+			return -1;
+		}
+	} else {
+		memcpy(&conf->cipher_xform, &td[0].xform.chain.cipher,
+		       sizeof(conf->cipher_xform));
+		memcpy(&conf->auth_xform, &td[0].xform.chain.auth,
+		       sizeof(conf->auth_xform));
+		conf->cipher_xform.cipher.key.data = td[0].key.data;
+		conf->cipher_xform.cipher.iv.offset = IV_OFFSET;
+		conf->auth_xform.auth.key.data = td[0].auth_key.data;
+
+		/* Verify crypto capabilities */
+
+		if (test_ipsec_crypto_caps_cipher_verify(
+				sec_cap,
+				&conf->cipher_xform) != 0) {
+			RTE_LOG(ERR, USER1,
+				"Cipher crypto capabilities not supported\n");
+			return -1;
+		}
+
+		if (test_ipsec_crypto_caps_auth_verify(
+				sec_cap,
+				&conf->auth_xform) != 0) {
+			RTE_LOG(ERR, USER1,
+				"Auth crypto capabilities not supported\n");
+			return -1;
+		}
+	}
+
+	if (test_ipsec_sec_caps_verify(ipsec_xform, sec_cap, 0) != 0)
+		return -1;
+
+	sess_conf->action_type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sess_conf->protocol = RTE_SECURITY_PROTOCOL_IPSEC;
+
+	if (td[0].aead || td[0].aes_gmac) {
+		salt_len = RTE_MIN(sizeof(ipsec_xform->salt), td[0].salt.len);
+		memcpy(&ipsec_xform->salt, td[0].salt.data, salt_len);
+	}
+
+	if (td[0].aead) {
+		sess_conf->ipsec = *ipsec_xform;
+		sess_conf->crypto_xform = &conf->aead_xform;
+	} else if (td[0].auth_only) {
+		sess_conf->ipsec = *ipsec_xform;
+		sess_conf->crypto_xform = &conf->auth_xform;
+	} else {
+		sess_conf->ipsec = *ipsec_xform;
+		if (dir == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
+			sess_conf->crypto_xform = &conf->cipher_xform;
+			conf->cipher_xform.next = &conf->auth_xform;
+		} else {
+			sess_conf->crypto_xform = &conf->auth_xform;
+			conf->auth_xform.next = &conf->cipher_xform;
+		}
+	}
+
+	return 0;
+}
+
+static int
+test_security_session_perf(void *arg)
+{
+	uint64_t tsc_start, tsc_mid, tsc_end, tsc_setup_dur, tsc_destroy_dur;
+	struct rte_security_ipsec_xform ipsec_xform;
+	struct rte_security_session_conf sess_conf;
+	int i, ret, nb_sessions, nb_sess_total;
+	struct rte_security_session **sess;
+	struct rte_security_ctx *sec_ctx;
+	double setup_rate, destroy_rate;
+	uint64_t setup_ms, destroy_ms;
+	struct lcore_conf *conf = arg;
+	struct rte_mempool *sess_mp;
+	uint8_t nb_lcores;
+
+	nb_lcores = conf->ctx->nb_lcores;
+	nb_sess_total = conf->ctx->nb_sess;
+	sec_ctx = conf->ctx->sec_ctx;
+	sess_mp = conf->ctx->sess_mp;
+
+	nb_sessions = nb_sess_total / nb_lcores;
+
+	if (conf->qp_id == 0)
+		nb_sessions += (nb_sess_total - nb_sessions * nb_lcores);
+
+	ret = sec_conf_init(conf, &sess_conf, &ipsec_xform,
+			    &ctx.td[ctx.td_idx]);
+	if (ret) {
+		RTE_LOG(ERR, USER1, "Could not initialize session conf\n");
+		return EXIT_FAILURE;
+	}
+
+	sess = rte_zmalloc(NULL, sizeof(void *) * nb_sessions, 0);
+
+	tsc_start = rte_rdtsc_precise();
+
+	for (i = 0; i < nb_sessions; i++) {
+		sess[i] = rte_security_session_create(sec_ctx,
+						      &sess_conf,
+						      sess_mp);
+		if (unlikely(sess[i] == NULL)) {
+			RTE_LOG(ERR, USER1, "Could not create session\n");
+			return EXIT_FAILURE;
+		}
+	}
+
+	tsc_mid = rte_rdtsc_precise();
+
+	for (i = 0; i < nb_sessions; i++) {
+		ret = rte_security_session_destroy(sec_ctx, sess[i]);
+		if (unlikely(ret < 0)) {
+			RTE_LOG(ERR, USER1, "Could not destroy session\n");
+			return EXIT_FAILURE;
+		}
+	}
+
+	tsc_end = rte_rdtsc_precise();
+
+	tsc_setup_dur = tsc_mid - tsc_start;
+	tsc_destroy_dur = tsc_end - tsc_mid;
+
+	setup_ms = tsc_setup_dur * 1000 / rte_get_tsc_hz();
+	destroy_ms = tsc_destroy_dur * 1000 / rte_get_tsc_hz();
+
+	setup_rate = (double)nb_sessions * rte_get_tsc_hz() / tsc_setup_dur;
+	destroy_rate = (double)nb_sessions * rte_get_tsc_hz() / tsc_destroy_dur;
+
+	printf("%20u%20u%20"PRIu64"%20"PRIu64"%20.2f%20.2f\n",
+			rte_lcore_id(),
+			nb_sessions,
+			setup_ms,
+			destroy_ms,
+			setup_rate,
+			destroy_rate);
+
+	return EXIT_SUCCESS;
+}
+
+static void
+usage(char *progname)
+{
+	printf("\nusage: %s\n", progname);
+	printf("  --help     : display this message and exit\n"
+	       "  --inbound  : test for inbound direction\n"
+		"           default outbound direction is tested\n"
+	       "  --nb-sess=N: to set the number of sessions\n"
+		"           to be created, default is %d\n", DEF_NB_SESSIONS);
+}
+
+static void
+args_parse(int argc, char **argv)
+{
+	char **argvopt;
+	int n, opt;
+	int opt_idx;
+
+	static const struct option lgopts[] = {
+		/* Control */
+		{ "help",    0, 0, 0 },
+		{ "inbound", 0, 0, 0 },
+		{ "nb-sess", 1, 0, 0 },
+		{ NULL, 0, 0, 0 }
+	};
+
+	argvopt = argv;
+
+	while ((opt = getopt_long(argc, argvopt, "",
+				lgopts, &opt_idx)) != EOF) {
+		switch (opt) {
+		case 0:
+			if (strcmp(lgopts[opt_idx].name, "help") == 0) {
+				usage(argv[0]);
+				exit(EXIT_SUCCESS);
+			}
+
+			if (strcmp(lgopts[opt_idx].name, "nb-sess") == 0) {
+				n = atoi(optarg);
+				if (n >= 0)
+					ctx.nb_sess = n;
+				else
+					rte_exit(EXIT_FAILURE,
+						"nb-sess should be >= 0\n");
+				printf("nb-sess %d / ", ctx.nb_sess);
+			} else if (strcmp(lgopts[opt_idx].name, "inbound") ==
+				   0) {
+				ctx.is_inbound = true;
+				printf("inbound / ");
+			}
+
+			break;
+
+		default:
+			usage(argv[0]);
+			rte_exit(EXIT_FAILURE, "Invalid option: %s\n",
+					argv[opt_idx - 1]);
+			break;
+		}
+	}
+
+	printf("\n\n");
+}
+
+int
+main(int argc, char **argv)
+{
+	struct ipsec_test_data td_outb[RTE_DIM(alg_list)];
+	struct ipsec_test_data td_inb[RTE_DIM(alg_list)];
+	struct ipsec_test_flags flags;
+	uint32_t lcore_id;
+	uint8_t nb_lcores;
+	unsigned long i;
+	int ret;
+
+	memset(&ctx, 0, sizeof(struct test_ctx));
+	memset(&flags, 0, sizeof(flags));
+
+	ret = rte_eal_init(argc, argv);
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Invalid EAL arguments!\n");
+	argc -= ret;
+	argv += ret;
+
+	nb_lcores = rte_lcore_count() - 1;
+	if (nb_lcores < 1) {
+		RTE_LOG(ERR, USER1,
+			"Number of worker cores need to be higher than 1\n");
+		return -EINVAL;
+	}
+
+	ctx.nb_sess = DEF_NB_SESSIONS + RTE_MEMPOOL_CACHE_MAX_SIZE * nb_lcores;
+
+	if (argc > 1)
+		args_parse(argc, argv);
+
+	ctx.nb_lcores = nb_lcores;
+
+	ret = cryptodev_init(&ctx, nb_lcores);
+	if (ret)
+		goto exit;
+
+	ret = mempool_init(&ctx, nb_lcores);
+	if (ret)
+		goto cryptodev_fini;
+
+	test_ipsec_alg_list_populate();
+
+	for (i = 0; i < RTE_DIM(alg_list); i++) {
+		test_ipsec_td_prepare(alg_list[i].param1,
+				      alg_list[i].param2,
+				      &flags,
+				      &td_outb[i],
+				      1);
+		if (ctx.is_inbound)
+			test_ipsec_td_in_from_out(&td_outb[i], &td_inb[i]);
+	}
+
+	ctx.td = td_outb;
+	if (ctx.is_inbound)
+		ctx.td = td_inb;
+
+	for (ctx.td_idx = 0; ctx.td_idx < RTE_DIM(alg_list); ctx.td_idx++) {
+
+		printf("\n\n    Algorithm combination:");
+		test_ipsec_display_alg(alg_list[ctx.td_idx].param1,
+				       alg_list[ctx.td_idx].param2);
+		printf("    ----------------------");
+
+		printf("\n%20s%20s%20s%20s%20s%20s\n\n",
+			"lcore id", "nb_sessions",
+			"Setup time(ms)", "Destroy time(ms)",
+			"Setup rate(sess/s)",
+			"Destroy rate(sess/sec)");
+
+		i = 0;
+		RTE_LCORE_FOREACH_WORKER(lcore_id) {
+			rte_eal_remote_launch(test_security_session_perf,
+					      &ctx.lconf[i],
+					      lcore_id);
+			i++;
+		}
+
+		RTE_LCORE_FOREACH_WORKER(lcore_id) {
+			ret |= rte_eal_wait_lcore(lcore_id);
+		}
+
+	}
+
+	cryptodev_fini(&ctx);
+	mempool_fini(&ctx);
+
+	return EXIT_SUCCESS;
+cryptodev_fini:
+	cryptodev_fini(&ctx);
+exit:
+	return EXIT_FAILURE;
+
+}
diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index 281ba2fc7f..326890a615 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -254,6 +254,12 @@ New Features
   Added support for asymmetric crypto algorithms.
   See the :doc:`../sample_app_ug/fips_validation` for more details.

+* **Added security performance test application.**
+
+  Added new application to test ``rte_security`` session create/destroy
+  performance.
+  See the :doc:`../tools/securityperf` for more details.
+

 Removed Items
 -------------
diff --git a/doc/guides/tools/index.rst b/doc/guides/tools/index.rst
index 0e5041a3f0..cee07a71b0 100644
--- a/doc/guides/tools/index.rst
+++ b/doc/guides/tools/index.rst
@@ -18,5 +18,6 @@ DPDK Tools User Guides
     testbbdev
     cryptoperf
     comp_perf
+    securityperf
     testeventdev
     testregex
diff --git a/doc/guides/tools/securityperf.rst b/doc/guides/tools/securityperf.rst
new file mode 100644
index 0000000000..06e0cf76b7
--- /dev/null
+++ b/doc/guides/tools/securityperf.rst
@@ -0,0 +1,47 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2022 Marvell.
+
+Security Performance Tool
+=========================
+
+The ``dpdk-test-security-perf`` tool is a Data Plane Development Kit (DPDK)
+utility to test rte_security session create/destroy rates. Test covers supported
+combinations of cipher and auth algorithms.
+
+Limitations
+~~~~~~~~~~~
+
+* Tests only ESP tunnel mode with IPv4.
+
+Running the Application
+-----------------------
+
+EAL Command-line Options
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Please refer to :doc:`EAL parameters (Linux) <../linux_gsg/linux_eal_parameters>`
+or :doc:`EAL parameters (FreeBSD) <../freebsd_gsg/freebsd_eal_parameters>` for
+a list of available EAL command-line options.
+
+Security Performance Options
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following are the command-line options for the security performance
+application. They must be separated from the EAL options, shown in the previous section,
+with a ``--`` separator:
+
+.. code-block:: console
+
+	sudo ./dpdk-test-security-perf -- --nb-sess=163840 --inbound
+
+The command-line options are:
+
+*	``--help``
+	Display a help message and quit.
+
+*	``--nb-sess``
+	Set the number of sessions to be created, default value is 163840.
+
+*	``--inbound``
+	IPsec SA direction to be tested with. By default if this option is not
+	provided, outbound direction will be tested.
--
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3] app/test-security-perf: add security perf app
  2022-10-21 16:38 ` [PATCH v2] app/test-security-perf: add security perf app Anoob Joseph
@ 2022-11-02 11:17   ` Anoob Joseph
  2022-11-03 12:46     ` [PATCH v4] " Anoob Joseph
  0 siblings, 1 reply; 12+ messages in thread
From: Anoob Joseph @ 2022-11-02 11:17 UTC (permalink / raw)
  To: Akhil Goyal, Jerin Jacob, Thomas Monjalon, Hemant Agrawal,
	Sachin Saxena, Ciara Power
  Cc: Aakash Sasidharan, dev

Add performance application to test security session create & destroy
rates supported by the security enabled cryptodev PMD. The
application would create specified number of sessions and captures the
time taken for the same before proceeding to destroy of the same. When
operating on multi-core, the number of sessions would be evenly
distributed across all cores.

The application would test with all combinations of cipher & auth
algorithms supported by the PMD.

Signed-off-by: Aakash Sasidharan <asasidharan@marvell.com>
Signed-off-by: Anoob Joseph <anoobj@marvell.com>
---
v3:
* Rebased

v2:
* Rebased on latest code. Made changes to accommodate session rework
* Fixed debug build failure

 MAINTAINERS                                 |   6 +
 app/meson.build                             |   1 +
 app/test-security-perf/meson.build          |  14 +
 app/test-security-perf/test_security_perf.c | 575 ++++++++++++++++++++
 doc/guides/rel_notes/release_22_11.rst      |   6 +
 doc/guides/tools/index.rst                  |   1 +
 doc/guides/tools/securityperf.rst           |  47 ++
 7 files changed, 650 insertions(+)
 create mode 100644 app/test-security-perf/meson.build
 create mode 100644 app/test-security-perf/test_security_perf.c
 create mode 100644 doc/guides/tools/securityperf.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 0d7df177c9..1e0e60847a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1743,6 +1743,12 @@ M: Reshma Pattan <reshma.pattan@intel.com>
 F: app/proc-info/
 F: doc/guides/tools/proc_info.rst
 
+Security performance tool
+M: Anoob Joseph <anoobj@marvell.com>
+T: git://dpdk.org/next/dpdk-next-crypto
+F: app/test-security-perf/
+F: doc/guides/tools/securityperf.rst
+
 
 Other Example Applications
 --------------------------
diff --git a/app/meson.build b/app/meson.build
index 96b9a78d3a..b44a3123ee 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -21,6 +21,7 @@ apps = [
         'test-pmd',
         'test-regex',
         'test-sad',
+        'test-security-perf',
 ]
 
 default_cflags = machine_args + ['-DALLOW_EXPERIMENTAL_API']
diff --git a/app/test-security-perf/meson.build b/app/test-security-perf/meson.build
new file mode 100644
index 0000000000..076999022e
--- /dev/null
+++ b/app/test-security-perf/meson.build
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(C) 2022 Marvell.
+
+if is_windows
+    build = false
+    reason = 'not supported on Windows'
+    subdir_done()
+endif
+
+sources = files(
+        'test_security_perf.c',
+        '../test/test_cryptodev_security_ipsec.c',
+)
+deps += ['security', 'cmdline']
diff --git a/app/test-security-perf/test_security_perf.c b/app/test-security-perf/test_security_perf.c
new file mode 100644
index 0000000000..9bb50689e3
--- /dev/null
+++ b/app/test-security-perf/test_security_perf.c
@@ -0,0 +1,575 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022, Marvell
+ */
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_cryptodev.h>
+#include <rte_eal.h>
+#include <rte_lcore.h>
+#include <rte_malloc.h>
+#include <rte_security.h>
+
+#include <app/test/test_cryptodev.h>
+#include <app/test/test_cryptodev_security_ipsec.h>
+#include <app/test/test_cryptodev_security_ipsec_test_vectors.h>
+
+#define NB_DESC 4096
+#define DEF_NB_SESSIONS (16 * 10 * 1024) /* 16 * 10K tunnels */
+
+struct lcore_conf {
+	struct rte_crypto_sym_xform cipher_xform;
+	struct rte_crypto_sym_xform auth_xform;
+	struct rte_crypto_sym_xform aead_xform;
+	uint8_t dev_id;
+	uint8_t qp_id;
+	struct test_ctx *ctx;
+};
+
+struct test_ctx {
+	struct lcore_conf lconf[RTE_MAX_LCORE];
+	void *sec_ctx;
+	struct rte_mempool *sess_mp;
+	struct ipsec_test_data *td;
+	int nb_sess;
+	unsigned long td_idx;
+	uint8_t nb_lcores;
+	uint8_t nb_cryptodevs;
+	uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS];
+	bool is_inbound;
+};
+
+static struct test_ctx ctx;
+
+static int
+cryptodev_init(struct test_ctx *ctx, uint8_t nb_lcores)
+{
+	const char dev_names[][RTE_CRYPTODEV_NAME_MAX_LEN] = {
+		"crypto_cn10k",
+		"crypto_cn9k",
+		"crypto_dpaa_sec",
+		"crypto_dpaa2_sec",
+	};
+	struct rte_cryptodev_qp_conf qp_conf;
+	struct rte_cryptodev_info dev_info;
+	struct rte_cryptodev_config config;
+	unsigned int j, nb_qp, qps_reqd;
+	uint8_t socket_id;
+	uint32_t dev_cnt;
+	int ret, core_id;
+	void *sec_ctx;
+	uint64_t i;
+
+	i = 0;
+	do {
+		dev_cnt = rte_cryptodev_devices_get(dev_names[i],
+						     ctx->enabled_cdevs,
+						     RTE_CRYPTO_MAX_DEVS);
+		i++;
+	} while (dev_cnt == 0 && i < RTE_DIM(dev_names));
+
+	if (dev_cnt == 0)
+		return -1;
+
+	/* Check first device for capabilities */
+	rte_cryptodev_info_get(0, &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_SECURITY)) {
+		RTE_LOG(ERR, USER1,
+			"Security not supported by the cryptodev\n");
+		return -1;
+	}
+
+	sec_ctx = rte_cryptodev_get_sec_ctx(0);
+	ctx->sec_ctx = sec_ctx;
+
+	socket_id = rte_socket_id();
+	qps_reqd = nb_lcores;
+	core_id = 0;
+	i = 0;
+
+	do {
+		rte_cryptodev_info_get(i, &dev_info);
+		qps_reqd = RTE_MIN(dev_info.max_nb_queue_pairs, qps_reqd);
+
+		for (j = 0; j < qps_reqd; j++) {
+			ctx->lconf[core_id].dev_id = i;
+			ctx->lconf[core_id].qp_id = j;
+			ctx->lconf[core_id].ctx = ctx;
+			core_id++;
+			if (core_id == RTE_MAX_LCORE)
+				break;
+		}
+
+		nb_qp = j;
+
+		memset(&config, 0, sizeof(config));
+		config.nb_queue_pairs = nb_qp;
+		config.socket_id = socket_id;
+
+		ret = rte_cryptodev_configure(i, &config);
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1,
+				"Could not configure cryptodev - %" PRIu64 "\n",
+				i);
+			return -1;
+		}
+
+		memset(&qp_conf, 0, sizeof(qp_conf));
+		qp_conf.nb_descriptors = NB_DESC;
+
+		for (j = 0; j < nb_qp; j++) {
+			ret = rte_cryptodev_queue_pair_setup(i, j, &qp_conf,
+							     socket_id);
+			if (ret < 0) {
+				RTE_LOG(ERR, USER1,
+					"Could not configure queue pair:"
+					" %" PRIu64 " - %d\n", i, j);
+				return -1;
+			}
+		}
+
+		ret = rte_cryptodev_start(i);
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1, "Could not start cryptodev\n");
+			return -1;
+		}
+
+		i++;
+		qps_reqd -= j;
+
+	} while (i < dev_cnt && core_id < RTE_MAX_LCORE);
+
+	ctx->nb_cryptodevs = i;
+
+	return 0;
+}
+
+static int
+cryptodev_fini(struct test_ctx *ctx)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < ctx->nb_cryptodevs &&
+			i < RTE_CRYPTO_MAX_DEVS; i++) {
+		rte_cryptodev_stop(ctx->enabled_cdevs[i]);
+		ret = rte_cryptodev_close(ctx->enabled_cdevs[i]);
+		if (ret)
+			RTE_LOG(ERR, USER1,
+					"Crypto device close error %d\n", ret);
+	}
+
+	return ret;
+}
+
+static int
+mempool_init(struct test_ctx *ctx, uint8_t nb_lcores)
+{
+	struct rte_mempool *sess_mpool;
+	unsigned int sec_sess_sz;
+	int nb_sess_total;
+
+	nb_sess_total = ctx->nb_sess + RTE_MEMPOOL_CACHE_MAX_SIZE * nb_lcores;
+
+	sec_sess_sz = rte_security_session_get_size(ctx->sec_ctx);
+
+	sess_mpool = rte_cryptodev_sym_session_pool_create("test_sess_mp",
+			nb_sess_total, sec_sess_sz, RTE_MEMPOOL_CACHE_MAX_SIZE,
+			0, SOCKET_ID_ANY);
+	if (sess_mpool == NULL) {
+		RTE_LOG(ERR, USER1, "Could not create mempool\n");
+		return -1;
+	}
+
+	ctx->sess_mp = sess_mpool;
+
+	return 0;
+}
+
+static int
+mempool_fini(struct test_ctx *ctx)
+{
+	rte_mempool_free(ctx->sess_mp);
+
+	return 0;
+}
+
+static int
+sec_conf_init(struct lcore_conf *conf,
+	      struct rte_security_session_conf *sess_conf,
+	      struct rte_security_ipsec_xform *ipsec_xform,
+	      const struct ipsec_test_data *td)
+{
+	uint16_t v6_src[8] = {0x2607, 0xf8b0, 0x400c, 0x0c03, 0x0000, 0x0000,
+				0x0000, 0x001a};
+	uint16_t v6_dst[8] = {0x2001, 0x0470, 0xe5bf, 0xdead, 0x4957, 0x2174,
+				0xe82c, 0x4887};
+	const struct rte_ipv4_hdr *ipv4 =
+			(const struct rte_ipv4_hdr *)td->output_text.data;
+	struct rte_security_capability_idx sec_cap_idx;
+	const struct rte_security_capability *sec_cap;
+	enum rte_security_ipsec_sa_direction dir;
+	uint32_t src, dst;
+	int salt_len;
+
+	/* Copy IPsec xform */
+	memcpy(ipsec_xform, &td->ipsec_xform, sizeof(*ipsec_xform));
+
+	dir = ipsec_xform->direction;
+
+	memcpy(&src, &ipv4->src_addr, sizeof(ipv4->src_addr));
+	memcpy(&dst, &ipv4->dst_addr, sizeof(ipv4->dst_addr));
+
+	if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
+		if (td->ipsec_xform.tunnel.type ==
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
+			memcpy(&ipsec_xform->tunnel.ipv4.src_ip, &src,
+			       sizeof(src));
+			memcpy(&ipsec_xform->tunnel.ipv4.dst_ip, &dst,
+			       sizeof(dst));
+
+		} else {
+			memcpy(&ipsec_xform->tunnel.ipv6.src_addr, &v6_src,
+			       sizeof(v6_src));
+			memcpy(&ipsec_xform->tunnel.ipv6.dst_addr, &v6_dst,
+			       sizeof(v6_dst));
+		}
+	}
+
+	sec_cap_idx.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sec_cap_idx.protocol = RTE_SECURITY_PROTOCOL_IPSEC;
+	sec_cap_idx.ipsec.proto = ipsec_xform->proto;
+	sec_cap_idx.ipsec.mode = ipsec_xform->mode;
+	sec_cap_idx.ipsec.direction = ipsec_xform->direction;
+
+	sec_cap = rte_security_capability_get(conf->ctx->sec_ctx, &sec_cap_idx);
+	if (sec_cap == NULL) {
+		RTE_LOG(ERR, USER1, "Could not get capabilities\n");
+		return -1;
+	}
+
+	/* Copy cipher session parameters */
+	if (td[0].aead) {
+		memcpy(&conf->aead_xform, &td[0].xform.aead,
+		       sizeof(conf->aead_xform));
+		conf->aead_xform.aead.key.data = td[0].key.data;
+		conf->aead_xform.aead.iv.offset = IV_OFFSET;
+
+		/* Verify crypto capabilities */
+		if (test_ipsec_crypto_caps_aead_verify(
+				sec_cap,
+				&conf->aead_xform) != 0) {
+			RTE_LOG(ERR, USER1,
+				"Crypto capabilities not supported\n");
+			return -1;
+		}
+	} else if (td[0].auth_only) {
+		memcpy(&conf->auth_xform, &td[0].xform.chain.auth,
+		       sizeof(conf->auth_xform));
+		conf->auth_xform.auth.key.data = td[0].auth_key.data;
+
+		if (test_ipsec_crypto_caps_auth_verify(
+				sec_cap,
+				&conf->auth_xform) != 0) {
+			RTE_LOG(INFO, USER1,
+				"Auth crypto capabilities not supported\n");
+			return -1;
+		}
+	} else {
+		memcpy(&conf->cipher_xform, &td[0].xform.chain.cipher,
+		       sizeof(conf->cipher_xform));
+		memcpy(&conf->auth_xform, &td[0].xform.chain.auth,
+		       sizeof(conf->auth_xform));
+		conf->cipher_xform.cipher.key.data = td[0].key.data;
+		conf->cipher_xform.cipher.iv.offset = IV_OFFSET;
+		conf->auth_xform.auth.key.data = td[0].auth_key.data;
+
+		/* Verify crypto capabilities */
+
+		if (test_ipsec_crypto_caps_cipher_verify(
+				sec_cap,
+				&conf->cipher_xform) != 0) {
+			RTE_LOG(ERR, USER1,
+				"Cipher crypto capabilities not supported\n");
+			return -1;
+		}
+
+		if (test_ipsec_crypto_caps_auth_verify(
+				sec_cap,
+				&conf->auth_xform) != 0) {
+			RTE_LOG(ERR, USER1,
+				"Auth crypto capabilities not supported\n");
+			return -1;
+		}
+	}
+
+	if (test_ipsec_sec_caps_verify(ipsec_xform, sec_cap, 0) != 0)
+		return -1;
+
+	sess_conf->action_type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sess_conf->protocol = RTE_SECURITY_PROTOCOL_IPSEC;
+
+	if (td[0].aead || td[0].aes_gmac) {
+		salt_len = RTE_MIN(sizeof(ipsec_xform->salt), td[0].salt.len);
+		memcpy(&ipsec_xform->salt, td[0].salt.data, salt_len);
+	}
+
+	if (td[0].aead) {
+		sess_conf->ipsec = *ipsec_xform;
+		sess_conf->crypto_xform = &conf->aead_xform;
+	} else if (td[0].auth_only) {
+		sess_conf->ipsec = *ipsec_xform;
+		sess_conf->crypto_xform = &conf->auth_xform;
+	} else {
+		sess_conf->ipsec = *ipsec_xform;
+		if (dir == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
+			sess_conf->crypto_xform = &conf->cipher_xform;
+			conf->cipher_xform.next = &conf->auth_xform;
+		} else {
+			sess_conf->crypto_xform = &conf->auth_xform;
+			conf->auth_xform.next = &conf->cipher_xform;
+		}
+	}
+
+	return 0;
+}
+
+static int
+test_security_session_perf(void *arg)
+{
+	uint64_t tsc_start, tsc_mid, tsc_end, tsc_setup_dur, tsc_destroy_dur;
+	struct rte_security_ipsec_xform ipsec_xform;
+	struct rte_security_session_conf sess_conf;
+	int i, ret, nb_sessions, nb_sess_total;
+	struct rte_security_session **sess;
+	struct rte_security_ctx *sec_ctx;
+	double setup_rate, destroy_rate;
+	uint64_t setup_ms, destroy_ms;
+	struct lcore_conf *conf = arg;
+	struct rte_mempool *sess_mp;
+	uint8_t nb_lcores;
+
+	nb_lcores = conf->ctx->nb_lcores;
+	nb_sess_total = conf->ctx->nb_sess;
+	sec_ctx = conf->ctx->sec_ctx;
+	sess_mp = conf->ctx->sess_mp;
+
+	nb_sessions = nb_sess_total / nb_lcores;
+
+	if (conf->qp_id == 0)
+		nb_sessions += (nb_sess_total - nb_sessions * nb_lcores);
+
+	ret = sec_conf_init(conf, &sess_conf, &ipsec_xform,
+			    &ctx.td[ctx.td_idx]);
+	if (ret) {
+		RTE_LOG(ERR, USER1, "Could not initialize session conf\n");
+		return EXIT_FAILURE;
+	}
+
+	sess = rte_zmalloc(NULL, sizeof(void *) * nb_sessions, 0);
+
+	tsc_start = rte_rdtsc_precise();
+
+	for (i = 0; i < nb_sessions; i++) {
+		sess[i] = rte_security_session_create(sec_ctx,
+						      &sess_conf,
+						      sess_mp);
+		if (unlikely(sess[i] == NULL)) {
+			RTE_LOG(ERR, USER1, "Could not create session\n");
+			return EXIT_FAILURE;
+		}
+	}
+
+	tsc_mid = rte_rdtsc_precise();
+
+	for (i = 0; i < nb_sessions; i++) {
+		ret = rte_security_session_destroy(sec_ctx, sess[i]);
+		if (unlikely(ret < 0)) {
+			RTE_LOG(ERR, USER1, "Could not destroy session\n");
+			return EXIT_FAILURE;
+		}
+	}
+
+	tsc_end = rte_rdtsc_precise();
+
+	tsc_setup_dur = tsc_mid - tsc_start;
+	tsc_destroy_dur = tsc_end - tsc_mid;
+
+	setup_ms = tsc_setup_dur * 1000 / rte_get_tsc_hz();
+	destroy_ms = tsc_destroy_dur * 1000 / rte_get_tsc_hz();
+
+	setup_rate = (double)nb_sessions * rte_get_tsc_hz() / tsc_setup_dur;
+	destroy_rate = (double)nb_sessions * rte_get_tsc_hz() / tsc_destroy_dur;
+
+	printf("%20u%20u%20"PRIu64"%20"PRIu64"%20.2f%20.2f\n",
+			rte_lcore_id(),
+			nb_sessions,
+			setup_ms,
+			destroy_ms,
+			setup_rate,
+			destroy_rate);
+
+	return EXIT_SUCCESS;
+}
+
+static void
+usage(char *progname)
+{
+	printf("\nusage: %s\n", progname);
+	printf("  --help     : display this message and exit\n"
+	       "  --inbound  : test for inbound direction\n"
+		"           default outbound direction is tested\n"
+	       "  --nb-sess=N: to set the number of sessions\n"
+		"           to be created, default is %d\n", DEF_NB_SESSIONS);
+}
+
+static void
+args_parse(int argc, char **argv)
+{
+	char **argvopt;
+	int n, opt;
+	int opt_idx;
+
+	static const struct option lgopts[] = {
+		/* Control */
+		{ "help",    0, 0, 0 },
+		{ "inbound", 0, 0, 0 },
+		{ "nb-sess", 1, 0, 0 },
+		{ NULL, 0, 0, 0 }
+	};
+
+	argvopt = argv;
+
+	while ((opt = getopt_long(argc, argvopt, "",
+				lgopts, &opt_idx)) != EOF) {
+		switch (opt) {
+		case 0:
+			if (strcmp(lgopts[opt_idx].name, "help") == 0) {
+				usage(argv[0]);
+				exit(EXIT_SUCCESS);
+			}
+
+			if (strcmp(lgopts[opt_idx].name, "nb-sess") == 0) {
+				n = atoi(optarg);
+				if (n >= 0)
+					ctx.nb_sess = n;
+				else
+					rte_exit(EXIT_FAILURE,
+						"nb-sess should be >= 0\n");
+				printf("nb-sess %d / ", ctx.nb_sess);
+			} else if (strcmp(lgopts[opt_idx].name, "inbound") ==
+				   0) {
+				ctx.is_inbound = true;
+				printf("inbound / ");
+			}
+
+			break;
+
+		default:
+			usage(argv[0]);
+			rte_exit(EXIT_FAILURE, "Invalid option: %s\n",
+					argv[opt_idx - 1]);
+			break;
+		}
+	}
+
+	printf("\n\n");
+}
+
+int
+main(int argc, char **argv)
+{
+	struct ipsec_test_data td_outb[RTE_DIM(alg_list)];
+	struct ipsec_test_data td_inb[RTE_DIM(alg_list)];
+	struct ipsec_test_flags flags;
+	uint32_t lcore_id;
+	uint8_t nb_lcores;
+	unsigned long i;
+	int ret;
+
+	memset(&ctx, 0, sizeof(struct test_ctx));
+	memset(&flags, 0, sizeof(flags));
+
+	ret = rte_eal_init(argc, argv);
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Invalid EAL arguments!\n");
+	argc -= ret;
+	argv += ret;
+
+	nb_lcores = rte_lcore_count() - 1;
+	if (nb_lcores < 1) {
+		RTE_LOG(ERR, USER1,
+			"Number of worker cores need to be higher than 1\n");
+		return -EINVAL;
+	}
+
+	ctx.nb_sess = DEF_NB_SESSIONS + RTE_MEMPOOL_CACHE_MAX_SIZE * nb_lcores;
+
+	if (argc > 1)
+		args_parse(argc, argv);
+
+	ctx.nb_lcores = nb_lcores;
+
+	ret = cryptodev_init(&ctx, nb_lcores);
+	if (ret)
+		goto exit;
+
+	ret = mempool_init(&ctx, nb_lcores);
+	if (ret)
+		goto cryptodev_fini;
+
+	test_ipsec_alg_list_populate();
+
+	for (i = 0; i < RTE_DIM(alg_list); i++) {
+		test_ipsec_td_prepare(alg_list[i].param1,
+				      alg_list[i].param2,
+				      &flags,
+				      &td_outb[i],
+				      1);
+		if (ctx.is_inbound)
+			test_ipsec_td_in_from_out(&td_outb[i], &td_inb[i]);
+	}
+
+	ctx.td = td_outb;
+	if (ctx.is_inbound)
+		ctx.td = td_inb;
+
+	for (ctx.td_idx = 0; ctx.td_idx < RTE_DIM(alg_list); ctx.td_idx++) {
+
+		printf("\n\n    Algorithm combination:");
+		test_ipsec_display_alg(alg_list[ctx.td_idx].param1,
+				       alg_list[ctx.td_idx].param2);
+		printf("    ----------------------");
+
+		printf("\n%20s%20s%20s%20s%20s%20s\n\n",
+			"lcore id", "nb_sessions",
+			"Setup time(ms)", "Destroy time(ms)",
+			"Setup rate(sess/s)",
+			"Destroy rate(sess/sec)");
+
+		i = 0;
+		RTE_LCORE_FOREACH_WORKER(lcore_id) {
+			rte_eal_remote_launch(test_security_session_perf,
+					      &ctx.lconf[i],
+					      lcore_id);
+			i++;
+		}
+
+		RTE_LCORE_FOREACH_WORKER(lcore_id) {
+			ret |= rte_eal_wait_lcore(lcore_id);
+		}
+
+	}
+
+	cryptodev_fini(&ctx);
+	mempool_fini(&ctx);
+
+	return EXIT_SUCCESS;
+cryptodev_fini:
+	cryptodev_fini(&ctx);
+exit:
+	return EXIT_FAILURE;
+
+}
diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index c59b907465..9f2a8fa9d8 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -306,6 +306,12 @@ New Features
 
      strings $dpdk_binary_or_driver | sed -n 's/^PMD_INFO_STRING= //p'
 
+* **Added security performance test application.**
+
+  Added new application to test ``rte_security`` session create/destroy
+  performance.
+  See the :doc:`../tools/securityperf` for more details.
+
 
 Removed Items
 -------------
diff --git a/doc/guides/tools/index.rst b/doc/guides/tools/index.rst
index 0e5041a3f0..cee07a71b0 100644
--- a/doc/guides/tools/index.rst
+++ b/doc/guides/tools/index.rst
@@ -18,5 +18,6 @@ DPDK Tools User Guides
     testbbdev
     cryptoperf
     comp_perf
+    securityperf
     testeventdev
     testregex
diff --git a/doc/guides/tools/securityperf.rst b/doc/guides/tools/securityperf.rst
new file mode 100644
index 0000000000..06e0cf76b7
--- /dev/null
+++ b/doc/guides/tools/securityperf.rst
@@ -0,0 +1,47 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2022 Marvell.
+
+Security Performance Tool
+=========================
+
+The ``dpdk-test-security-perf`` tool is a Data Plane Development Kit (DPDK)
+utility to test rte_security session create/destroy rates. Test covers supported
+combinations of cipher and auth algorithms.
+
+Limitations
+~~~~~~~~~~~
+
+* Tests only ESP tunnel mode with IPv4.
+
+Running the Application
+-----------------------
+
+EAL Command-line Options
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Please refer to :doc:`EAL parameters (Linux) <../linux_gsg/linux_eal_parameters>`
+or :doc:`EAL parameters (FreeBSD) <../freebsd_gsg/freebsd_eal_parameters>` for
+a list of available EAL command-line options.
+
+Security Performance Options
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following are the command-line options for the security performance
+application. They must be separated from the EAL options, shown in the previous section,
+with a ``--`` separator:
+
+.. code-block:: console
+
+	sudo ./dpdk-test-security-perf -- --nb-sess=163840 --inbound
+
+The command-line options are:
+
+*	``--help``
+	Display a help message and quit.
+
+*	``--nb-sess``
+	Set the number of sessions to be created, default value is 163840.
+
+*	``--inbound``
+	IPsec SA direction to be tested with. By default if this option is not
+	provided, outbound direction will be tested.
-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v4] app/test-security-perf: add security perf app
  2022-11-02 11:17   ` [PATCH v3] " Anoob Joseph
@ 2022-11-03 12:46     ` Anoob Joseph
  2022-11-03 12:58       ` Akhil Goyal
  0 siblings, 1 reply; 12+ messages in thread
From: Anoob Joseph @ 2022-11-03 12:46 UTC (permalink / raw)
  To: Akhil Goyal, Jerin Jacob, Thomas Monjalon, Hemant Agrawal,
	Sachin Saxena, Ciara Power
  Cc: Aakash Sasidharan, dev

Add performance application to test security session create & destroy
rates supported by the security enabled cryptodev PMD. The
application would create specified number of sessions and captures the
time taken for the same before proceeding to destroy of the same. When
operating on multi-core, the number of sessions would be evenly
distributed across all cores.

The application would test with all combinations of cipher & auth
algorithms supported by the PMD.

Signed-off-by: Aakash Sasidharan <asasidharan@marvell.com>
Signed-off-by: Anoob Joseph <anoobj@marvell.com>
---
v4:
* Fixed documentation

v3:
* Rebased

v2:
* Rebased on latest code. Made changes to accommodate session rework
* Fixed debug build failure

 MAINTAINERS                                 |   6 +
 app/meson.build                             |   1 +
 app/test-security-perf/meson.build          |  14 +
 app/test-security-perf/test_security_perf.c | 575 ++++++++++++++++++++
 doc/guides/rel_notes/release_22_11.rst      |   6 +
 doc/guides/tools/index.rst                  |   1 +
 doc/guides/tools/securityperf.rst           |  47 ++
 7 files changed, 650 insertions(+)
 create mode 100644 app/test-security-perf/meson.build
 create mode 100644 app/test-security-perf/test_security_perf.c
 create mode 100644 doc/guides/tools/securityperf.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 0d7df177c9..1e0e60847a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1743,6 +1743,12 @@ M: Reshma Pattan <reshma.pattan@intel.com>
 F: app/proc-info/
 F: doc/guides/tools/proc_info.rst
 
+Security performance tool
+M: Anoob Joseph <anoobj@marvell.com>
+T: git://dpdk.org/next/dpdk-next-crypto
+F: app/test-security-perf/
+F: doc/guides/tools/securityperf.rst
+
 
 Other Example Applications
 --------------------------
diff --git a/app/meson.build b/app/meson.build
index 96b9a78d3a..b44a3123ee 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -21,6 +21,7 @@ apps = [
         'test-pmd',
         'test-regex',
         'test-sad',
+        'test-security-perf',
 ]
 
 default_cflags = machine_args + ['-DALLOW_EXPERIMENTAL_API']
diff --git a/app/test-security-perf/meson.build b/app/test-security-perf/meson.build
new file mode 100644
index 0000000000..076999022e
--- /dev/null
+++ b/app/test-security-perf/meson.build
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(C) 2022 Marvell.
+
+if is_windows
+    build = false
+    reason = 'not supported on Windows'
+    subdir_done()
+endif
+
+sources = files(
+        'test_security_perf.c',
+        '../test/test_cryptodev_security_ipsec.c',
+)
+deps += ['security', 'cmdline']
diff --git a/app/test-security-perf/test_security_perf.c b/app/test-security-perf/test_security_perf.c
new file mode 100644
index 0000000000..9bb50689e3
--- /dev/null
+++ b/app/test-security-perf/test_security_perf.c
@@ -0,0 +1,575 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022, Marvell
+ */
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_cryptodev.h>
+#include <rte_eal.h>
+#include <rte_lcore.h>
+#include <rte_malloc.h>
+#include <rte_security.h>
+
+#include <app/test/test_cryptodev.h>
+#include <app/test/test_cryptodev_security_ipsec.h>
+#include <app/test/test_cryptodev_security_ipsec_test_vectors.h>
+
+#define NB_DESC 4096
+#define DEF_NB_SESSIONS (16 * 10 * 1024) /* 16 * 10K tunnels */
+
+struct lcore_conf {
+	struct rte_crypto_sym_xform cipher_xform;
+	struct rte_crypto_sym_xform auth_xform;
+	struct rte_crypto_sym_xform aead_xform;
+	uint8_t dev_id;
+	uint8_t qp_id;
+	struct test_ctx *ctx;
+};
+
+struct test_ctx {
+	struct lcore_conf lconf[RTE_MAX_LCORE];
+	void *sec_ctx;
+	struct rte_mempool *sess_mp;
+	struct ipsec_test_data *td;
+	int nb_sess;
+	unsigned long td_idx;
+	uint8_t nb_lcores;
+	uint8_t nb_cryptodevs;
+	uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS];
+	bool is_inbound;
+};
+
+static struct test_ctx ctx;
+
+static int
+cryptodev_init(struct test_ctx *ctx, uint8_t nb_lcores)
+{
+	const char dev_names[][RTE_CRYPTODEV_NAME_MAX_LEN] = {
+		"crypto_cn10k",
+		"crypto_cn9k",
+		"crypto_dpaa_sec",
+		"crypto_dpaa2_sec",
+	};
+	struct rte_cryptodev_qp_conf qp_conf;
+	struct rte_cryptodev_info dev_info;
+	struct rte_cryptodev_config config;
+	unsigned int j, nb_qp, qps_reqd;
+	uint8_t socket_id;
+	uint32_t dev_cnt;
+	int ret, core_id;
+	void *sec_ctx;
+	uint64_t i;
+
+	i = 0;
+	do {
+		dev_cnt = rte_cryptodev_devices_get(dev_names[i],
+						     ctx->enabled_cdevs,
+						     RTE_CRYPTO_MAX_DEVS);
+		i++;
+	} while (dev_cnt == 0 && i < RTE_DIM(dev_names));
+
+	if (dev_cnt == 0)
+		return -1;
+
+	/* Check first device for capabilities */
+	rte_cryptodev_info_get(0, &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_SECURITY)) {
+		RTE_LOG(ERR, USER1,
+			"Security not supported by the cryptodev\n");
+		return -1;
+	}
+
+	sec_ctx = rte_cryptodev_get_sec_ctx(0);
+	ctx->sec_ctx = sec_ctx;
+
+	socket_id = rte_socket_id();
+	qps_reqd = nb_lcores;
+	core_id = 0;
+	i = 0;
+
+	do {
+		rte_cryptodev_info_get(i, &dev_info);
+		qps_reqd = RTE_MIN(dev_info.max_nb_queue_pairs, qps_reqd);
+
+		for (j = 0; j < qps_reqd; j++) {
+			ctx->lconf[core_id].dev_id = i;
+			ctx->lconf[core_id].qp_id = j;
+			ctx->lconf[core_id].ctx = ctx;
+			core_id++;
+			if (core_id == RTE_MAX_LCORE)
+				break;
+		}
+
+		nb_qp = j;
+
+		memset(&config, 0, sizeof(config));
+		config.nb_queue_pairs = nb_qp;
+		config.socket_id = socket_id;
+
+		ret = rte_cryptodev_configure(i, &config);
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1,
+				"Could not configure cryptodev - %" PRIu64 "\n",
+				i);
+			return -1;
+		}
+
+		memset(&qp_conf, 0, sizeof(qp_conf));
+		qp_conf.nb_descriptors = NB_DESC;
+
+		for (j = 0; j < nb_qp; j++) {
+			ret = rte_cryptodev_queue_pair_setup(i, j, &qp_conf,
+							     socket_id);
+			if (ret < 0) {
+				RTE_LOG(ERR, USER1,
+					"Could not configure queue pair:"
+					" %" PRIu64 " - %d\n", i, j);
+				return -1;
+			}
+		}
+
+		ret = rte_cryptodev_start(i);
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1, "Could not start cryptodev\n");
+			return -1;
+		}
+
+		i++;
+		qps_reqd -= j;
+
+	} while (i < dev_cnt && core_id < RTE_MAX_LCORE);
+
+	ctx->nb_cryptodevs = i;
+
+	return 0;
+}
+
+static int
+cryptodev_fini(struct test_ctx *ctx)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < ctx->nb_cryptodevs &&
+			i < RTE_CRYPTO_MAX_DEVS; i++) {
+		rte_cryptodev_stop(ctx->enabled_cdevs[i]);
+		ret = rte_cryptodev_close(ctx->enabled_cdevs[i]);
+		if (ret)
+			RTE_LOG(ERR, USER1,
+					"Crypto device close error %d\n", ret);
+	}
+
+	return ret;
+}
+
+static int
+mempool_init(struct test_ctx *ctx, uint8_t nb_lcores)
+{
+	struct rte_mempool *sess_mpool;
+	unsigned int sec_sess_sz;
+	int nb_sess_total;
+
+	nb_sess_total = ctx->nb_sess + RTE_MEMPOOL_CACHE_MAX_SIZE * nb_lcores;
+
+	sec_sess_sz = rte_security_session_get_size(ctx->sec_ctx);
+
+	sess_mpool = rte_cryptodev_sym_session_pool_create("test_sess_mp",
+			nb_sess_total, sec_sess_sz, RTE_MEMPOOL_CACHE_MAX_SIZE,
+			0, SOCKET_ID_ANY);
+	if (sess_mpool == NULL) {
+		RTE_LOG(ERR, USER1, "Could not create mempool\n");
+		return -1;
+	}
+
+	ctx->sess_mp = sess_mpool;
+
+	return 0;
+}
+
+static int
+mempool_fini(struct test_ctx *ctx)
+{
+	rte_mempool_free(ctx->sess_mp);
+
+	return 0;
+}
+
+static int
+sec_conf_init(struct lcore_conf *conf,
+	      struct rte_security_session_conf *sess_conf,
+	      struct rte_security_ipsec_xform *ipsec_xform,
+	      const struct ipsec_test_data *td)
+{
+	uint16_t v6_src[8] = {0x2607, 0xf8b0, 0x400c, 0x0c03, 0x0000, 0x0000,
+				0x0000, 0x001a};
+	uint16_t v6_dst[8] = {0x2001, 0x0470, 0xe5bf, 0xdead, 0x4957, 0x2174,
+				0xe82c, 0x4887};
+	const struct rte_ipv4_hdr *ipv4 =
+			(const struct rte_ipv4_hdr *)td->output_text.data;
+	struct rte_security_capability_idx sec_cap_idx;
+	const struct rte_security_capability *sec_cap;
+	enum rte_security_ipsec_sa_direction dir;
+	uint32_t src, dst;
+	int salt_len;
+
+	/* Copy IPsec xform */
+	memcpy(ipsec_xform, &td->ipsec_xform, sizeof(*ipsec_xform));
+
+	dir = ipsec_xform->direction;
+
+	memcpy(&src, &ipv4->src_addr, sizeof(ipv4->src_addr));
+	memcpy(&dst, &ipv4->dst_addr, sizeof(ipv4->dst_addr));
+
+	if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
+		if (td->ipsec_xform.tunnel.type ==
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
+			memcpy(&ipsec_xform->tunnel.ipv4.src_ip, &src,
+			       sizeof(src));
+			memcpy(&ipsec_xform->tunnel.ipv4.dst_ip, &dst,
+			       sizeof(dst));
+
+		} else {
+			memcpy(&ipsec_xform->tunnel.ipv6.src_addr, &v6_src,
+			       sizeof(v6_src));
+			memcpy(&ipsec_xform->tunnel.ipv6.dst_addr, &v6_dst,
+			       sizeof(v6_dst));
+		}
+	}
+
+	sec_cap_idx.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sec_cap_idx.protocol = RTE_SECURITY_PROTOCOL_IPSEC;
+	sec_cap_idx.ipsec.proto = ipsec_xform->proto;
+	sec_cap_idx.ipsec.mode = ipsec_xform->mode;
+	sec_cap_idx.ipsec.direction = ipsec_xform->direction;
+
+	sec_cap = rte_security_capability_get(conf->ctx->sec_ctx, &sec_cap_idx);
+	if (sec_cap == NULL) {
+		RTE_LOG(ERR, USER1, "Could not get capabilities\n");
+		return -1;
+	}
+
+	/* Copy cipher session parameters */
+	if (td[0].aead) {
+		memcpy(&conf->aead_xform, &td[0].xform.aead,
+		       sizeof(conf->aead_xform));
+		conf->aead_xform.aead.key.data = td[0].key.data;
+		conf->aead_xform.aead.iv.offset = IV_OFFSET;
+
+		/* Verify crypto capabilities */
+		if (test_ipsec_crypto_caps_aead_verify(
+				sec_cap,
+				&conf->aead_xform) != 0) {
+			RTE_LOG(ERR, USER1,
+				"Crypto capabilities not supported\n");
+			return -1;
+		}
+	} else if (td[0].auth_only) {
+		memcpy(&conf->auth_xform, &td[0].xform.chain.auth,
+		       sizeof(conf->auth_xform));
+		conf->auth_xform.auth.key.data = td[0].auth_key.data;
+
+		if (test_ipsec_crypto_caps_auth_verify(
+				sec_cap,
+				&conf->auth_xform) != 0) {
+			RTE_LOG(INFO, USER1,
+				"Auth crypto capabilities not supported\n");
+			return -1;
+		}
+	} else {
+		memcpy(&conf->cipher_xform, &td[0].xform.chain.cipher,
+		       sizeof(conf->cipher_xform));
+		memcpy(&conf->auth_xform, &td[0].xform.chain.auth,
+		       sizeof(conf->auth_xform));
+		conf->cipher_xform.cipher.key.data = td[0].key.data;
+		conf->cipher_xform.cipher.iv.offset = IV_OFFSET;
+		conf->auth_xform.auth.key.data = td[0].auth_key.data;
+
+		/* Verify crypto capabilities */
+
+		if (test_ipsec_crypto_caps_cipher_verify(
+				sec_cap,
+				&conf->cipher_xform) != 0) {
+			RTE_LOG(ERR, USER1,
+				"Cipher crypto capabilities not supported\n");
+			return -1;
+		}
+
+		if (test_ipsec_crypto_caps_auth_verify(
+				sec_cap,
+				&conf->auth_xform) != 0) {
+			RTE_LOG(ERR, USER1,
+				"Auth crypto capabilities not supported\n");
+			return -1;
+		}
+	}
+
+	if (test_ipsec_sec_caps_verify(ipsec_xform, sec_cap, 0) != 0)
+		return -1;
+
+	sess_conf->action_type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sess_conf->protocol = RTE_SECURITY_PROTOCOL_IPSEC;
+
+	if (td[0].aead || td[0].aes_gmac) {
+		salt_len = RTE_MIN(sizeof(ipsec_xform->salt), td[0].salt.len);
+		memcpy(&ipsec_xform->salt, td[0].salt.data, salt_len);
+	}
+
+	if (td[0].aead) {
+		sess_conf->ipsec = *ipsec_xform;
+		sess_conf->crypto_xform = &conf->aead_xform;
+	} else if (td[0].auth_only) {
+		sess_conf->ipsec = *ipsec_xform;
+		sess_conf->crypto_xform = &conf->auth_xform;
+	} else {
+		sess_conf->ipsec = *ipsec_xform;
+		if (dir == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
+			sess_conf->crypto_xform = &conf->cipher_xform;
+			conf->cipher_xform.next = &conf->auth_xform;
+		} else {
+			sess_conf->crypto_xform = &conf->auth_xform;
+			conf->auth_xform.next = &conf->cipher_xform;
+		}
+	}
+
+	return 0;
+}
+
+static int
+test_security_session_perf(void *arg)
+{
+	uint64_t tsc_start, tsc_mid, tsc_end, tsc_setup_dur, tsc_destroy_dur;
+	struct rte_security_ipsec_xform ipsec_xform;
+	struct rte_security_session_conf sess_conf;
+	int i, ret, nb_sessions, nb_sess_total;
+	struct rte_security_session **sess;
+	struct rte_security_ctx *sec_ctx;
+	double setup_rate, destroy_rate;
+	uint64_t setup_ms, destroy_ms;
+	struct lcore_conf *conf = arg;
+	struct rte_mempool *sess_mp;
+	uint8_t nb_lcores;
+
+	nb_lcores = conf->ctx->nb_lcores;
+	nb_sess_total = conf->ctx->nb_sess;
+	sec_ctx = conf->ctx->sec_ctx;
+	sess_mp = conf->ctx->sess_mp;
+
+	nb_sessions = nb_sess_total / nb_lcores;
+
+	if (conf->qp_id == 0)
+		nb_sessions += (nb_sess_total - nb_sessions * nb_lcores);
+
+	ret = sec_conf_init(conf, &sess_conf, &ipsec_xform,
+			    &ctx.td[ctx.td_idx]);
+	if (ret) {
+		RTE_LOG(ERR, USER1, "Could not initialize session conf\n");
+		return EXIT_FAILURE;
+	}
+
+	sess = rte_zmalloc(NULL, sizeof(void *) * nb_sessions, 0);
+
+	tsc_start = rte_rdtsc_precise();
+
+	for (i = 0; i < nb_sessions; i++) {
+		sess[i] = rte_security_session_create(sec_ctx,
+						      &sess_conf,
+						      sess_mp);
+		if (unlikely(sess[i] == NULL)) {
+			RTE_LOG(ERR, USER1, "Could not create session\n");
+			return EXIT_FAILURE;
+		}
+	}
+
+	tsc_mid = rte_rdtsc_precise();
+
+	for (i = 0; i < nb_sessions; i++) {
+		ret = rte_security_session_destroy(sec_ctx, sess[i]);
+		if (unlikely(ret < 0)) {
+			RTE_LOG(ERR, USER1, "Could not destroy session\n");
+			return EXIT_FAILURE;
+		}
+	}
+
+	tsc_end = rte_rdtsc_precise();
+
+	tsc_setup_dur = tsc_mid - tsc_start;
+	tsc_destroy_dur = tsc_end - tsc_mid;
+
+	setup_ms = tsc_setup_dur * 1000 / rte_get_tsc_hz();
+	destroy_ms = tsc_destroy_dur * 1000 / rte_get_tsc_hz();
+
+	setup_rate = (double)nb_sessions * rte_get_tsc_hz() / tsc_setup_dur;
+	destroy_rate = (double)nb_sessions * rte_get_tsc_hz() / tsc_destroy_dur;
+
+	printf("%20u%20u%20"PRIu64"%20"PRIu64"%20.2f%20.2f\n",
+			rte_lcore_id(),
+			nb_sessions,
+			setup_ms,
+			destroy_ms,
+			setup_rate,
+			destroy_rate);
+
+	return EXIT_SUCCESS;
+}
+
+static void
+usage(char *progname)
+{
+	printf("\nusage: %s\n", progname);
+	printf("  --help     : display this message and exit\n"
+	       "  --inbound  : test for inbound direction\n"
+		"           default outbound direction is tested\n"
+	       "  --nb-sess=N: to set the number of sessions\n"
+		"           to be created, default is %d\n", DEF_NB_SESSIONS);
+}
+
+static void
+args_parse(int argc, char **argv)
+{
+	char **argvopt;
+	int n, opt;
+	int opt_idx;
+
+	static const struct option lgopts[] = {
+		/* Control */
+		{ "help",    0, 0, 0 },
+		{ "inbound", 0, 0, 0 },
+		{ "nb-sess", 1, 0, 0 },
+		{ NULL, 0, 0, 0 }
+	};
+
+	argvopt = argv;
+
+	while ((opt = getopt_long(argc, argvopt, "",
+				lgopts, &opt_idx)) != EOF) {
+		switch (opt) {
+		case 0:
+			if (strcmp(lgopts[opt_idx].name, "help") == 0) {
+				usage(argv[0]);
+				exit(EXIT_SUCCESS);
+			}
+
+			if (strcmp(lgopts[opt_idx].name, "nb-sess") == 0) {
+				n = atoi(optarg);
+				if (n >= 0)
+					ctx.nb_sess = n;
+				else
+					rte_exit(EXIT_FAILURE,
+						"nb-sess should be >= 0\n");
+				printf("nb-sess %d / ", ctx.nb_sess);
+			} else if (strcmp(lgopts[opt_idx].name, "inbound") ==
+				   0) {
+				ctx.is_inbound = true;
+				printf("inbound / ");
+			}
+
+			break;
+
+		default:
+			usage(argv[0]);
+			rte_exit(EXIT_FAILURE, "Invalid option: %s\n",
+					argv[opt_idx - 1]);
+			break;
+		}
+	}
+
+	printf("\n\n");
+}
+
+int
+main(int argc, char **argv)
+{
+	struct ipsec_test_data td_outb[RTE_DIM(alg_list)];
+	struct ipsec_test_data td_inb[RTE_DIM(alg_list)];
+	struct ipsec_test_flags flags;
+	uint32_t lcore_id;
+	uint8_t nb_lcores;
+	unsigned long i;
+	int ret;
+
+	memset(&ctx, 0, sizeof(struct test_ctx));
+	memset(&flags, 0, sizeof(flags));
+
+	ret = rte_eal_init(argc, argv);
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Invalid EAL arguments!\n");
+	argc -= ret;
+	argv += ret;
+
+	nb_lcores = rte_lcore_count() - 1;
+	if (nb_lcores < 1) {
+		RTE_LOG(ERR, USER1,
+			"Number of worker cores need to be higher than 1\n");
+		return -EINVAL;
+	}
+
+	ctx.nb_sess = DEF_NB_SESSIONS + RTE_MEMPOOL_CACHE_MAX_SIZE * nb_lcores;
+
+	if (argc > 1)
+		args_parse(argc, argv);
+
+	ctx.nb_lcores = nb_lcores;
+
+	ret = cryptodev_init(&ctx, nb_lcores);
+	if (ret)
+		goto exit;
+
+	ret = mempool_init(&ctx, nb_lcores);
+	if (ret)
+		goto cryptodev_fini;
+
+	test_ipsec_alg_list_populate();
+
+	for (i = 0; i < RTE_DIM(alg_list); i++) {
+		test_ipsec_td_prepare(alg_list[i].param1,
+				      alg_list[i].param2,
+				      &flags,
+				      &td_outb[i],
+				      1);
+		if (ctx.is_inbound)
+			test_ipsec_td_in_from_out(&td_outb[i], &td_inb[i]);
+	}
+
+	ctx.td = td_outb;
+	if (ctx.is_inbound)
+		ctx.td = td_inb;
+
+	for (ctx.td_idx = 0; ctx.td_idx < RTE_DIM(alg_list); ctx.td_idx++) {
+
+		printf("\n\n    Algorithm combination:");
+		test_ipsec_display_alg(alg_list[ctx.td_idx].param1,
+				       alg_list[ctx.td_idx].param2);
+		printf("    ----------------------");
+
+		printf("\n%20s%20s%20s%20s%20s%20s\n\n",
+			"lcore id", "nb_sessions",
+			"Setup time(ms)", "Destroy time(ms)",
+			"Setup rate(sess/s)",
+			"Destroy rate(sess/sec)");
+
+		i = 0;
+		RTE_LCORE_FOREACH_WORKER(lcore_id) {
+			rte_eal_remote_launch(test_security_session_perf,
+					      &ctx.lconf[i],
+					      lcore_id);
+			i++;
+		}
+
+		RTE_LCORE_FOREACH_WORKER(lcore_id) {
+			ret |= rte_eal_wait_lcore(lcore_id);
+		}
+
+	}
+
+	cryptodev_fini(&ctx);
+	mempool_fini(&ctx);
+
+	return EXIT_SUCCESS;
+cryptodev_fini:
+	cryptodev_fini(&ctx);
+exit:
+	return EXIT_FAILURE;
+
+}
diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index c59b907465..9f2a8fa9d8 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -306,6 +306,12 @@ New Features
 
      strings $dpdk_binary_or_driver | sed -n 's/^PMD_INFO_STRING= //p'
 
+* **Added security performance test application.**
+
+  Added new application to test ``rte_security`` session create/destroy
+  performance.
+  See the :doc:`../tools/securityperf` for more details.
+
 
 Removed Items
 -------------
diff --git a/doc/guides/tools/index.rst b/doc/guides/tools/index.rst
index 0e5041a3f0..cee07a71b0 100644
--- a/doc/guides/tools/index.rst
+++ b/doc/guides/tools/index.rst
@@ -18,5 +18,6 @@ DPDK Tools User Guides
     testbbdev
     cryptoperf
     comp_perf
+    securityperf
     testeventdev
     testregex
diff --git a/doc/guides/tools/securityperf.rst b/doc/guides/tools/securityperf.rst
new file mode 100644
index 0000000000..7795c33ef1
--- /dev/null
+++ b/doc/guides/tools/securityperf.rst
@@ -0,0 +1,47 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2022 Marvell.
+
+Security Performance Tool
+=========================
+
+The ``dpdk-test-security-perf`` tool is a Data Plane Development Kit (DPDK)
+utility to test rte_security session create/destroy rates. Test covers supported
+combinations of cipher and auth algorithms.
+
+Limitations
+~~~~~~~~~~~
+
+* Tests only ESP tunnel mode with IPv4.
+
+Running the Application
+~~~~~~~~~~~~~~~~~~~~~~~
+
+EAL Command-line Options
+------------------------
+
+Please refer to :doc:`EAL parameters (Linux) <../linux_gsg/linux_eal_parameters>`
+or :doc:`EAL parameters (FreeBSD) <../freebsd_gsg/freebsd_eal_parameters>` for
+a list of available EAL command-line options.
+
+Security Performance Options
+----------------------------
+
+The following are the command-line options for the security performance
+application. They must be separated from the EAL options, shown in the previous section,
+with a ``--`` separator:
+
+.. code-block:: console
+
+	sudo ./dpdk-test-security-perf -- --nb-sess=163840 --inbound
+
+The command-line options are:
+
+*	``--help``
+	Display a help message and quit.
+
+*	``--nb-sess``
+	Set the number of sessions to be created, default value is 163840.
+
+*	``--inbound``
+	IPsec SA direction to be tested with. By default if this option is not
+	provided, outbound direction will be tested.
-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH v4] app/test-security-perf: add security perf app
  2022-11-03 12:46     ` [PATCH v4] " Anoob Joseph
@ 2022-11-03 12:58       ` Akhil Goyal
  0 siblings, 0 replies; 12+ messages in thread
From: Akhil Goyal @ 2022-11-03 12:58 UTC (permalink / raw)
  To: Anoob Joseph, Jerin Jacob Kollanukkaran, Thomas Monjalon,
	Hemant Agrawal, Sachin Saxena, Ciara Power
  Cc: Aakash Sasidharan, dev

> Subject: [PATCH v4] app/test-security-perf: add security perf app
> 
> Add performance application to test security session create & destroy
> rates supported by the security enabled cryptodev PMD. The
> application would create specified number of sessions and captures the
> time taken for the same before proceeding to destroy of the same. When
> operating on multi-core, the number of sessions would be evenly
> distributed across all cores.
> 
> The application would test with all combinations of cipher & auth
> algorithms supported by the PMD.
> 
> Signed-off-by: Aakash Sasidharan <asasidharan@marvell.com>
> Signed-off-by: Anoob Joseph <anoobj@marvell.com>
> ---
> v4:
> * Fixed documentation
Applied to dpdk-next-crypto

Thanks.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2022-11-03 12:58 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-11  3:59 [PATCH 0/1] Add security perf application Anoob Joseph
2022-08-11  3:59 ` [PATCH 1/1] app/test-security-perf: add security perf app Anoob Joseph
2022-08-18  9:31 ` [PATCH 0/1] Add security perf application Akhil Goyal
2022-08-19  7:20   ` Anoob Joseph
2022-09-26  9:25     ` Anoob Joseph
2022-09-27 19:16       ` Akhil Goyal
2022-09-28  7:39         ` Anoob Joseph
2022-10-21 15:13           ` Akhil Goyal
2022-10-21 16:38 ` [PATCH v2] app/test-security-perf: add security perf app Anoob Joseph
2022-11-02 11:17   ` [PATCH v3] " Anoob Joseph
2022-11-03 12:46     ` [PATCH v4] " Anoob Joseph
2022-11-03 12:58       ` Akhil Goyal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).