From 92d74810cbdc4c04045d6a47dc3d867f1fa22de1 Mon Sep 17 00:00:00 2001 From: Vidya Sagar Velumuri Date: Tue, 10 Oct 2023 16:02:12 +0530 Subject: [PATCH] test/crypto: add Rx inject 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 Signed-off-by: Vidya Sagar Velumuri Acked-by: Akhil Goyal --- app/test/test_cryptodev.c | 340 +++++++++++++++++++---- app/test/test_cryptodev_security_ipsec.h | 1 + 2 files changed, 288 insertions(+), 53 deletions(-) diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c index f2112e181e5..b645cb32f1b 100644 --- a/app/test/test_cryptodev.c +++ b/app/test/test_cryptodev.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -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 8587fc45776..d7fc5627516 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 {