[v4,2/2] test/cryptodev: add Rx inject test

Message ID 20231010103212.1900-2-anoobj@marvell.com (mailing list archive)
State Accepted, archived
Delegated to: akhil goyal
Headers
Series [v4,1/2] security: add fallback security processing and Rx inject |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/intel-Functional success Functional PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-compile-amd64-testing success Testing PASS
ci/iol-unit-amd64-testing success Testing PASS
ci/iol-unit-arm64-testing success Testing PASS
ci/iol-compile-arm64-testing success Testing PASS
ci/iol-sample-apps-testing warning Testing issues
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS

Commit Message

Anoob Joseph Oct. 10, 2023, 10:32 a.m. UTC
  From: Vidya Sagar Velumuri <vvelumuri@marvell.com>

Add test to verify Rx inject. The test case added would push a known
vector to cryptodev which would be injected to ethdev Rx. The test
case verifies that the packet is received from ethdev Rx and is
processed successfully. It also verifies that the userdata matches with
the expectation.

Signed-off-by: Anoob Joseph <anoobj@marvell.com>
Signed-off-by: Vidya Sagar Velumuri <vvelumuri@marvell.com>
Acked-by: Akhil Goyal <gakhil@marvell.com>
---
 app/test/test_cryptodev.c                | 340 +++++++++++++++++++----
 app/test/test_cryptodev_security_ipsec.h |   1 +
 2 files changed, 288 insertions(+), 53 deletions(-)
  

Patch

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index f2112e181e..b645cb32f1 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -17,6 +17,7 @@ 
 
 #include <rte_crypto.h>
 #include <rte_cryptodev.h>
+#include <rte_ethdev.h>
 #include <rte_ip.h>
 #include <rte_string_fns.h>
 #include <rte_tcp.h>
@@ -1426,6 +1427,93 @@  ut_setup_security(void)
 	return dev_configure_and_start(0);
 }
 
+static int
+ut_setup_security_rx_inject(void)
+{
+	struct rte_mempool *mbuf_pool = rte_mempool_lookup("CRYPTO_MBUFPOOL");
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct rte_eth_conf port_conf = {
+		.rxmode = {
+			.offloads = RTE_ETH_RX_OFFLOAD_CHECKSUM |
+				    RTE_ETH_RX_OFFLOAD_SECURITY,
+		},
+		.txmode = {
+			.offloads = RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE,
+		},
+		.lpbk_mode = 1,  /* Enable loopback */
+	};
+	struct rte_cryptodev_info dev_info;
+	struct rte_eth_rxconf rx_conf = {
+		.rx_thresh = {
+			.pthresh = 8,
+			.hthresh = 8,
+			.wthresh = 8,
+		},
+		.rx_free_thresh = 32,
+	};
+	uint16_t nb_ports;
+	void *sec_ctx;
+	int ret;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_SECURITY_RX_INJECT) ||
+	    !(dev_info.feature_flags & RTE_CRYPTODEV_FF_SECURITY)) {
+		RTE_LOG(INFO, USER1,
+			"Feature requirements for IPsec Rx inject test case not met\n");
+		return TEST_SKIPPED;
+	}
+
+	sec_ctx = rte_cryptodev_get_sec_ctx(ts_params->valid_devs[0]);
+	if (sec_ctx == NULL)
+		return TEST_SKIPPED;
+
+	nb_ports = rte_eth_dev_count_avail();
+	if (nb_ports == 0)
+		return TEST_SKIPPED;
+
+	ret = rte_eth_dev_configure(0 /* port_id */,
+				    1 /* nb_rx_queue */,
+				    0 /* nb_tx_queue */,
+				    &port_conf);
+	if (ret) {
+		printf("Could not configure ethdev port 0 [err=%d]\n", ret);
+		return TEST_SKIPPED;
+	}
+
+	/* Rx queue setup */
+	ret = rte_eth_rx_queue_setup(0 /* port_id */,
+				     0 /* rx_queue_id */,
+				     1024 /* nb_rx_desc */,
+				     SOCKET_ID_ANY,
+				     &rx_conf,
+				     mbuf_pool);
+	if (ret) {
+		printf("Could not setup eth port 0 queue 0\n");
+		return TEST_SKIPPED;
+	}
+
+	ret = rte_security_rx_inject_configure(sec_ctx, 0, true);
+	if (ret) {
+		printf("Could not enable Rx inject offload");
+		return TEST_SKIPPED;
+	}
+
+	ret = rte_eth_dev_start(0);
+	if (ret) {
+		printf("Could not start ethdev");
+		return TEST_SKIPPED;
+	}
+
+	ret = rte_eth_promiscuous_enable(0);
+	if (ret) {
+		printf("Could not enable promiscuous mode");
+		return TEST_SKIPPED;
+	}
+
+	/* Configure and start cryptodev with no features disabled */
+	return dev_configure_and_start(0);
+}
+
 void
 ut_teardown(void)
 {
@@ -1478,6 +1566,33 @@  ut_teardown(void)
 	rte_cryptodev_stop(ts_params->valid_devs[0]);
 }
 
+static void
+ut_teardown_rx_inject(void)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	void *sec_ctx;
+	int ret;
+
+	if  (rte_eth_dev_count_avail() != 0) {
+		ret = rte_eth_dev_reset(0);
+		if (ret)
+			printf("Could not reset eth port 0");
+
+	}
+
+	ut_teardown();
+
+	sec_ctx = rte_cryptodev_get_sec_ctx(ts_params->valid_devs[0]);
+	if (sec_ctx == NULL)
+		return;
+
+	ret = rte_security_rx_inject_configure(sec_ctx, 0, false);
+	if (ret) {
+		printf("Could not disable Rx inject offload");
+		return;
+	}
+}
+
 static int
 test_device_configure_invalid_dev_id(void)
 {
@@ -9875,6 +9990,136 @@  ext_mbuf_create(struct rte_mempool *mbuf_pool, int pkt_len,
 	return NULL;
 }
 
+static int
+test_ipsec_proto_crypto_op_enq(struct crypto_testsuite_params *ts_params,
+			       struct crypto_unittest_params *ut_params,
+			       struct rte_security_ipsec_xform *ipsec_xform,
+			       const struct ipsec_test_data *td,
+			       const struct ipsec_test_flags *flags,
+			       int pkt_num)
+{
+	uint8_t dev_id = ts_params->valid_devs[0];
+	enum rte_security_ipsec_sa_direction dir;
+	int ret;
+
+	dir = ipsec_xform->direction;
+
+	/* Generate crypto op data structure */
+	ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+				RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	if (!ut_params->op) {
+		printf("Could not allocate crypto op");
+		return TEST_FAILED;
+	}
+
+	/* Attach session to operation */
+	rte_security_attach_session(ut_params->op, ut_params->sec_session);
+
+	/* Set crypto operation mbufs */
+	ut_params->op->sym->m_src = ut_params->ibuf;
+	ut_params->op->sym->m_dst = NULL;
+
+	/* Copy IV in crypto operation when IV generation is disabled */
+	if (dir == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
+	    ipsec_xform->options.iv_gen_disable == 1) {
+		uint8_t *iv = rte_crypto_op_ctod_offset(ut_params->op,
+							uint8_t *,
+							IV_OFFSET);
+		int len;
+
+		if (td->aead)
+			len = td->xform.aead.aead.iv.length;
+		else if (td->aes_gmac)
+			len = td->xform.chain.auth.auth.iv.length;
+		else
+			len = td->xform.chain.cipher.cipher.iv.length;
+
+		memcpy(iv, td->iv.data, len);
+	}
+
+	/* Process crypto operation */
+	process_crypto_request(dev_id, ut_params->op);
+
+	ret = test_ipsec_status_check(td, ut_params->op, flags, dir, pkt_num);
+
+	rte_crypto_op_free(ut_params->op);
+	ut_params->op = NULL;
+
+	return ret;
+}
+
+static int
+test_ipsec_proto_mbuf_enq(struct crypto_testsuite_params *ts_params,
+			  struct crypto_unittest_params *ut_params,
+			  void *ctx)
+{
+	uint64_t timeout, userdata;
+	struct rte_ether_hdr *hdr;
+	struct rte_mbuf *m;
+	void **sec_sess;
+	int ret;
+
+	RTE_SET_USED(ts_params);
+
+	hdr = (void *)rte_pktmbuf_prepend(ut_params->ibuf, sizeof(struct rte_ether_hdr));
+	hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+
+	ut_params->ibuf->l2_len = sizeof(struct rte_ether_hdr);
+
+	sec_sess = &ut_params->sec_session;
+	ret = rte_security_inb_pkt_rx_inject(ctx, &ut_params->ibuf, sec_sess, 1);
+
+	if (ret != 1)
+		return TEST_FAILED;
+
+	ut_params->ibuf = NULL;
+
+	/* Add a timeout for 1 s */
+	timeout = rte_get_tsc_cycles() + rte_get_tsc_hz();
+
+	do {
+		/* Get packet from port 0, queue 0 */
+		ret = rte_eth_rx_burst(0, 0, &m, 1);
+	} while ((ret == 0) && (rte_get_tsc_cycles() > timeout));
+
+	if (ret == 0) {
+		printf("Could not receive packets from ethdev\n");
+		return TEST_FAILED;
+	}
+
+	if (m == NULL) {
+		printf("Received mbuf is NULL\n");
+		return TEST_FAILED;
+	}
+
+	ut_params->ibuf = m;
+
+	if (!(m->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD)) {
+		printf("Received packet is not Rx security processed\n");
+		return TEST_FAILED;
+	}
+
+	if (m->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED) {
+		printf("Received packet has failed Rx security processing\n");
+		return TEST_FAILED;
+	}
+
+	/*
+	 * 'ut_params' is set as userdata. Verify that the field is returned
+	 * correctly.
+	 */
+	userdata = *(uint64_t *)rte_security_dynfield(m);
+	if (userdata != (uint64_t)ut_params) {
+		printf("Userdata retrieved not matching expected\n");
+		return TEST_FAILED;
+	}
+
+	/* Trim L2 header */
+	rte_pktmbuf_adj(m, sizeof(struct rte_ether_hdr));
+
+	return TEST_SUCCESS;
+}
+
 static int
 test_ipsec_proto_process(const struct ipsec_test_data td[],
 			 struct ipsec_test_data res_d[],
@@ -10064,6 +10309,9 @@  test_ipsec_proto_process(const struct ipsec_test_data td[],
 		}
 	}
 
+	if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && flags->rx_inject)
+		sess_conf.userdata = ut_params;
+
 	/* Create security session */
 	ut_params->sec_session = rte_security_session_create(ctx, &sess_conf,
 					ts_params->session_mpool);
@@ -10086,8 +10334,10 @@  test_ipsec_proto_process(const struct ipsec_test_data td[],
 
 		/* Copy test data before modification */
 		memcpy(input_text, td[i].input_text.data, td[i].input_text.len);
-		if (test_ipsec_pkt_update(input_text, flags))
-			return TEST_FAILED;
+		if (test_ipsec_pkt_update(input_text, flags)) {
+			ret = TEST_FAILED;
+			goto mbuf_free;
+		}
 
 		/* Setup source mbuf payload */
 		if (flags->use_ext_mbuf) {
@@ -10099,50 +10349,18 @@  test_ipsec_proto_process(const struct ipsec_test_data td[],
 			pktmbuf_write(ut_params->ibuf, 0, td[i].input_text.len, input_text);
 		}
 
-		/* Generate crypto op data structure */
-		ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
-					RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-		if (!ut_params->op) {
-			printf("TestCase %s line %d: %s\n",
-				__func__, __LINE__,
-				"failed to allocate crypto op");
-			ret = TEST_FAILED;
-			goto crypto_op_free;
-		}
-
-		/* Attach session to operation */
-		rte_security_attach_session(ut_params->op,
-					    ut_params->sec_session);
-
-		/* Set crypto operation mbufs */
-		ut_params->op->sym->m_src = ut_params->ibuf;
-		ut_params->op->sym->m_dst = NULL;
-
-		/* Copy IV in crypto operation when IV generation is disabled */
-		if (dir == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
-		    ipsec_xform.options.iv_gen_disable == 1) {
-			uint8_t *iv = rte_crypto_op_ctod_offset(ut_params->op,
-								uint8_t *,
-								IV_OFFSET);
-			int len;
-
-			if (td[i].aead)
-				len = td[i].xform.aead.aead.iv.length;
-			else if (td[i].aes_gmac)
-				len = td[i].xform.chain.auth.auth.iv.length;
-			else
-				len = td[i].xform.chain.cipher.cipher.iv.length;
-
-			memcpy(iv, td[i].iv.data, len);
-		}
-
-		/* Process crypto operation */
-		process_crypto_request(dev_id, ut_params->op);
+		if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && flags->rx_inject)
+			ret = test_ipsec_proto_mbuf_enq(ts_params, ut_params,
+							ctx);
+		else
+			ret = test_ipsec_proto_crypto_op_enq(ts_params,
+							     ut_params,
+							     &ipsec_xform,
+							     &td[i], flags,
+							     i + 1);
 
-		ret = test_ipsec_status_check(&td[i], ut_params->op, flags, dir,
-					      i + 1);
 		if (ret != TEST_SUCCESS)
-			goto crypto_op_free;
+			goto mbuf_free;
 
 		if (res_d != NULL)
 			res_d_tmp = &res_d[i];
@@ -10150,24 +10368,18 @@  test_ipsec_proto_process(const struct ipsec_test_data td[],
 		ret = test_ipsec_post_process(ut_params->ibuf, &td[i],
 					      res_d_tmp, silent, flags);
 		if (ret != TEST_SUCCESS)
-			goto crypto_op_free;
+			goto mbuf_free;
 
 		ret = test_ipsec_stats_verify(ctx, ut_params->sec_session,
 					      flags, dir);
 		if (ret != TEST_SUCCESS)
-			goto crypto_op_free;
-
-		rte_crypto_op_free(ut_params->op);
-		ut_params->op = NULL;
+			goto mbuf_free;
 
 		rte_pktmbuf_free(ut_params->ibuf);
 		ut_params->ibuf = NULL;
 	}
 
-crypto_op_free:
-	rte_crypto_op_free(ut_params->op);
-	ut_params->op = NULL;
-
+mbuf_free:
 	if (flags->use_ext_mbuf)
 		ext_mbuf_memzone_free(nb_segs);
 
@@ -10256,6 +10468,24 @@  test_ipsec_proto_known_vec_fragmented(const void *test_data)
 	return test_ipsec_proto_process(&td_outb, NULL, 1, false, &flags);
 }
 
+static int
+test_ipsec_proto_known_vec_inb_rx_inject(const void *test_data)
+{
+	const struct ipsec_test_data *td = test_data;
+	struct ipsec_test_flags flags;
+	struct ipsec_test_data td_inb;
+
+	memset(&flags, 0, sizeof(flags));
+	flags.rx_inject = true;
+
+	if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
+		test_ipsec_td_in_from_out(td, &td_inb);
+	else
+		memcpy(&td_inb, td, sizeof(td_inb));
+
+	return test_ipsec_proto_process(&td_inb, NULL, 1, false, &flags);
+}
+
 static int
 test_ipsec_proto_all(const struct ipsec_test_flags *flags)
 {
@@ -16319,6 +16549,10 @@  static struct unit_test_suite ipsec_proto_testsuite  = {
 			"Multi-segmented external mbuf mode",
 			ut_setup_security, ut_teardown,
 			test_ipsec_proto_sgl_ext_mbuf),
+		TEST_CASE_NAMED_WITH_DATA(
+			"Inbound known vector (ESP tunnel mode IPv4 AES-GCM 128) Rx inject",
+			ut_setup_security_rx_inject, ut_teardown_rx_inject,
+			test_ipsec_proto_known_vec_inb_rx_inject, &pkt_aes_128_gcm),
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
 };
diff --git a/app/test/test_cryptodev_security_ipsec.h b/app/test/test_cryptodev_security_ipsec.h
index 8587fc4577..d7fc562751 100644
--- a/app/test/test_cryptodev_security_ipsec.h
+++ b/app/test/test_cryptodev_security_ipsec.h
@@ -112,6 +112,7 @@  struct ipsec_test_flags {
 	uint32_t plaintext_len;
 	int nb_segs_in_mbuf;
 	bool inb_oop;
+	bool rx_inject;
 };
 
 struct crypto_param {