From patchwork Thu Dec 22 09:25:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anoob Joseph X-Patchwork-Id: 121284 X-Patchwork-Delegate: gakhil@marvell.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 9287AA034C; Thu, 22 Dec 2022 10:28:18 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 8FFE542D2D; Thu, 22 Dec 2022 10:27:54 +0100 (CET) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 65825400D7 for ; Thu, 22 Dec 2022 10:27:53 +0100 (CET) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 2BM7Mp71015823; Thu, 22 Dec 2022 01:27:51 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=YJcx1vX/4BwAQ+xf0p+F5bUn4Q+s6NodOSUhDuf2mQc=; b=bC1VaplOQdzN9kvzhNiFXlYtYq9iE7i/XYzYfgrTCWw0udAyJfG3j9v4gX6LBOkep5TS 202/65PEqbmnIaJu72oiLKKw3aD1GXsa8kYV+vlrC4g9Ye01k5bqPyAHnHX9G49TjFTr r0smMuqQTdFn+Qz6Wu8rSf/Ug7TghM6MziHBcGZsEyPJomQaGXiS7iecH19L+vVXn2qY GvcIxVD5uqdJc1Ac4DuLuP83iAO5HDHeuR/zaEL2GEDgfMQWsQs1cxlHSWwfvczFQgd0 lSnwrete7rYnMJMS8iosyk5n+s5e748zEiAVns43Ox6lHHKvTSuS75L5JHxgzByuzx6S +A== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3mm79c3stv-6 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Thu, 22 Dec 2022 01:27:51 -0800 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.42; Thu, 22 Dec 2022 01:25:43 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.42 via Frontend Transport; Thu, 22 Dec 2022 01:25:43 -0800 Received: from BG-LT92004.corp.innovium.com (unknown [10.193.66.59]) by maili.marvell.com (Postfix) with ESMTP id A0F793F705D; Thu, 22 Dec 2022 01:25:39 -0800 (PST) From: Anoob Joseph To: Thomas Monjalon , Akhil Goyal , Jerin Jacob , Konstantin Ananyev , Bernard Iremonger CC: Volodymyr Fialko , Hemant Agrawal , =?utf-8?q?Mattias_R=C3=B6nnblom?= , Kiran Kumar K , , Olivier Matz Subject: [PATCH 4/5] app/test: pdcp HFN tests in combined mode Date: Thu, 22 Dec 2022 14:55:21 +0530 Message-ID: <20221222092522.1628-5-anoobj@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221222092522.1628-1-anoobj@marvell.com> References: <20221027052140.155-1-anoobj@marvell.com> <20221222092522.1628-1-anoobj@marvell.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: YWLEWQ6ke7WDMUsllKQxRPEYqoEcy-F6 X-Proofpoint-GUID: YWLEWQ6ke7WDMUsllKQxRPEYqoEcy-F6 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.923,Hydra:6.0.545,FMLib:17.11.122.1 definitions=2022-12-22_04,2022-12-21_01,2022-06-22_01 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Volodymyr Fialko Add tests to verify HFN/SN behaviour. Signed-off-by: Anoob Joseph Signed-off-by: Kiran Kumar K Signed-off-by: Volodymyr Fialko --- app/test/test_pdcp.c | 390 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 363 insertions(+), 27 deletions(-) diff --git a/app/test/test_pdcp.c b/app/test/test_pdcp.c index 10a383ddd7..1e74147579 100644 --- a/app/test/test_pdcp.c +++ b/app/test/test_pdcp.c @@ -4,6 +4,7 @@ #include #include +#include #include "test.h" #include "test_cryptodev.h" @@ -19,17 +20,17 @@ struct pdcp_testsuite_params { static struct pdcp_testsuite_params testsuite_params; -#define PDCP_MAX_TEST_INPUT_LEN 2048 +#define PDCP_MAX_TEST_DATA_LEN 2048 struct pdcp_test_conf { struct rte_pdcp_entity_conf entity; struct rte_crypto_sym_xform c_xfrm; struct rte_crypto_sym_xform a_xfrm; bool is_integrity_protected; - uint8_t input[PDCP_MAX_TEST_INPUT_LEN]; + uint8_t input[PDCP_MAX_TEST_DATA_LEN]; uint32_t input_len; - const uint8_t *expected; - uint32_t expected_len; + uint8_t output[PDCP_MAX_TEST_DATA_LEN]; + uint32_t output_len; }; static inline int @@ -38,6 +39,19 @@ pdcp_hdr_size_get(enum rte_security_pdcp_sn_size sn_size) return RTE_ALIGN_MUL_CEIL(sn_size, 8) / 8; } +static int +pktmbuf_read_into(const struct rte_mbuf *m, void *buf, size_t buf_len) +{ + if (m->pkt_len > buf_len) + return -ENOMEM; + + const void *read = rte_pktmbuf_read(m, 0, m->pkt_len, buf); + if (read != NULL && read != buf) + memcpy(buf, read, m->pkt_len); + + return 0; +} + static int cryptodev_init(int dev_id) { @@ -300,14 +314,45 @@ process_crypto_request(uint8_t dev_id, struct rte_crypto_op *op) return op; } +static uint32_t +pdcp_sn_from_raw_get(const void *data, enum rte_security_pdcp_sn_size size) +{ + uint32_t sn = 0; + + if (size == RTE_SECURITY_PDCP_SN_SIZE_12) { + sn = rte_cpu_to_be_16(*(const uint16_t *)data); + sn = sn & 0xfff; + } else if (size == RTE_SECURITY_PDCP_SN_SIZE_18) { + sn = rte_cpu_to_be_32(*(const uint32_t *)data); + sn = (sn & 0x3ffff00) >> 8; + } + + return sn; +} + +static void +pdcp_sn_to_raw_set(void *data, uint32_t sn, int size) +{ + if (size == RTE_SECURITY_PDCP_SN_SIZE_12) { + struct rte_pdcp_up_data_pdu_sn_12_hdr *pdu_hdr = data; + pdu_hdr->sn_11_8 = ((sn & 0xf00) >> 8); + pdu_hdr->sn_7_0 = (sn & 0xff); + } else if (size == RTE_SECURITY_PDCP_SN_SIZE_18) { + struct rte_pdcp_up_data_pdu_sn_18_hdr *pdu_hdr = data; + pdu_hdr->sn_17_16 = ((sn & 0x30000) >> 16); + pdu_hdr->sn_15_8 = ((sn & 0xff00) >> 8); + pdu_hdr->sn_7_0 = (sn & 0xff); + } +} + static int create_test_conf_from_index(const int index, struct pdcp_test_conf *conf) { const struct pdcp_testsuite_params *ts_params = &testsuite_params; struct rte_crypto_sym_xform c_xfrm, a_xfrm; - uint32_t hfn, sn, count = 0; + uint32_t hfn, sn, expected_len, count = 0; + uint8_t *data, *expected; int pdcp_hdr_sz; - uint8_t *data; memset(conf, 0, sizeof(*conf)); memset(&c_xfrm, 0, sizeof(c_xfrm)); @@ -326,6 +371,7 @@ create_test_conf_from_index(const int index, struct pdcp_test_conf *conf) conf->entity.pdcp_xfrm.pkt_dir = RTE_SECURITY_PDCP_DOWNLINK; conf->entity.pdcp_xfrm.sn_size = pdcp_test_data_sn_size[index]; + /* Zero initialize unsupported flags */ conf->entity.pdcp_xfrm.hfn_threshold = 0; conf->entity.pdcp_xfrm.hfn_ovrd = 0; conf->entity.pdcp_xfrm.sdap_enabled = 0; @@ -414,14 +460,7 @@ create_test_conf_from_index(const int index, struct pdcp_test_conf *conf) pdcp_test_params[index].domain == RTE_SECURITY_PDCP_MODE_DATA) { data = pdcp_test_data_in[index]; hfn = pdcp_test_hfn[index] << pdcp_test_data_sn_size[index]; - sn = 0; - if (pdcp_test_data_sn_size[index] == RTE_SECURITY_PDCP_SN_SIZE_12) { - sn = rte_cpu_to_be_16(*(uint16_t *)data); - sn = sn & 0xfff; - } else if (pdcp_test_data_sn_size[index] == RTE_SECURITY_PDCP_SN_SIZE_18) { - sn = rte_cpu_to_be_32(*(uint32_t *)data); - sn = (sn & 0x3ffff00) >> 8; - } + sn = pdcp_sn_from_raw_get(data, pdcp_test_data_sn_size[index]); count = hfn | sn; } conf->entity.count = count; @@ -448,29 +487,32 @@ create_test_conf_from_index(const int index, struct pdcp_test_conf *conf) } if (conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK) - conf->expected = pdcp_test_data_out[index]; + expected = pdcp_test_data_out[index]; else - conf->expected = pdcp_test_data_in[index]; + expected = pdcp_test_data_in[index]; /* Calculate expected packet length */ - conf->expected_len = pdcp_test_data_in_len[index]; + expected_len = pdcp_test_data_in_len[index]; /* In DL processing, PDCP header would be stripped */ if (conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) { - conf->expected += pdcp_hdr_sz; - conf->expected_len -= pdcp_hdr_sz; + expected += pdcp_hdr_sz; + expected_len -= pdcp_hdr_sz; } /* In UL processing with integrity protection, MAC would be added */ if (conf->is_integrity_protected && conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK) - conf->expected_len += 4; + expected_len += 4; + + memcpy(conf->output, expected, expected_len); + conf->output_len = expected_len; return 0; } static int -test_attempt_single(const struct pdcp_test_conf *t_conf) +test_attempt_single(struct pdcp_test_conf *t_conf) { const struct pdcp_testsuite_params *ts_params = &testsuite_params; struct rte_mbuf *mbuf, *mb, **out_mb = NULL; @@ -584,9 +626,17 @@ test_attempt_single(const struct pdcp_test_conf *t_conf) goto mbuf_free; } - ret = pdcp_known_vec_verify(mbuf, t_conf->expected, t_conf->expected_len); - if (ret) - goto mbuf_free; + /* If expected output provided - verify, else - store for future use */ + if (t_conf->output_len) { + ret = pdcp_known_vec_verify(mbuf, t_conf->output, t_conf->output_len); + if (ret) + goto mbuf_free; + } else { + ret = pktmbuf_read_into(mbuf, t_conf->output, PDCP_MAX_TEST_DATA_LEN); + if (ret) + goto mbuf_free; + t_conf->output_len = mbuf->pkt_len; + } ret = rte_pdcp_entity_suspend(pdcp_entity, out_mb); if (ret) { @@ -609,6 +659,195 @@ test_attempt_single(const struct pdcp_test_conf *t_conf) return TEST_FAILED; } +static void +uplink_to_downlink_convert(const struct pdcp_test_conf *ul_cfg, + struct pdcp_test_conf *dl_cfg) +{ + assert(ul_cfg->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK); + + memcpy(dl_cfg, ul_cfg, sizeof(*dl_cfg)); + dl_cfg->entity.pdcp_xfrm.pkt_dir = RTE_SECURITY_PDCP_DOWNLINK; + dl_cfg->entity.reverse_iv_direction = false; + + if (dl_cfg->is_integrity_protected) { + dl_cfg->entity.crypto_xfrm = &dl_cfg->c_xfrm; + + dl_cfg->c_xfrm.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT; + dl_cfg->c_xfrm.next = &dl_cfg->a_xfrm; + + dl_cfg->a_xfrm.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY; + dl_cfg->a_xfrm.next = NULL; + } else { + dl_cfg->entity.crypto_xfrm = &dl_cfg->c_xfrm; + dl_cfg->c_xfrm.next = NULL; + dl_cfg->c_xfrm.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT; + } + + memcpy(dl_cfg->input, ul_cfg->output, ul_cfg->output_len); + dl_cfg->input_len = ul_cfg->output_len; + + memcpy(dl_cfg->output, ul_cfg->input, ul_cfg->input_len); + dl_cfg->output_len = ul_cfg->input_len; +} + +/* + * According to ETSI TS 138 323 V17.1.0, Section 5.2.2.1, + * SN could be divided into following ranges, + * relatively to current value of RX_DELIV state: + * +-------------+-------------+-------------+-------------+ + * | -Outside | -Window | +Window | +Outside | + * | (valid) | (Invalid) | (Valid) | (Invalid) | + * +-------------+-------------^-------------+-------------+ + * | + * v + * SN(RX_DELIV) + */ +enum sn_range_type { + SN_RANGE_MINUS_OUTSIDE, + SN_RANGE_MINUS_WINDOW, + SN_RANGE_PLUS_WINDOW, + SN_RANGE_PLUS_OUTSIDE, +}; + +#define PDCP_SET_COUNT(hfn, sn, size) ((hfn << size) | (sn & ((1 << size) - 1))) + +/* + * Take uplink test case as base, modify RX_DELIV in state and SN in input + */ +static int +test_sn_range_type_with_config(enum sn_range_type type, struct pdcp_test_conf *conf) +{ + uint32_t rx_deliv_hfn, rx_deliv_sn, rx_deliv, new_hfn, new_sn; + const int domain = conf->entity.pdcp_xfrm.domain; + struct pdcp_test_conf dl_conf; + int ret, expected_ret; + + if (domain != RTE_SECURITY_PDCP_MODE_CONTROL && domain != RTE_SECURITY_PDCP_MODE_DATA) + return TEST_SKIPPED; + + const uint32_t sn_size = conf->entity.pdcp_xfrm.sn_size; + /* According to formula(7.2.a Window_Size) */ + const uint32_t window_size = 1 << (sn_size - 1); + /* Max value of SN that could fit in `sn_size` bits */ + const uint32_t max_sn = (1 << sn_size) - 1; + const uint32_t shift = (max_sn - window_size) / 2; + /* Could be any number up to `shift` value */ + const uint32_t default_sn = RTE_MIN(2u, shift); + + /* Initialize HFN as non zero value, to be able check values before */ + rx_deliv_hfn = 0xa; + + switch (type) { + case SN_RANGE_PLUS_WINDOW: + /* Within window size, HFN stay same */ + new_hfn = rx_deliv_hfn; + rx_deliv_sn = default_sn; + new_sn = rx_deliv_sn + 1; + expected_ret = TEST_SUCCESS; + break; + case SN_RANGE_MINUS_WINDOW: + /* Within window size, HFN stay same */ + new_hfn = rx_deliv_hfn; + rx_deliv_sn = default_sn; + new_sn = rx_deliv_sn - 1; + expected_ret = TEST_FAILED; + break; + case SN_RANGE_PLUS_OUTSIDE: + /* RCVD_SN >= SN(RX_DELIV) + Window_Size */ + new_hfn = rx_deliv_hfn - 1; + rx_deliv_sn = default_sn; + new_sn = rx_deliv_sn + window_size; + expected_ret = TEST_FAILED; + break; + case SN_RANGE_MINUS_OUTSIDE: + /* RCVD_SN < SN(RX_DELIV) - Window_Size */ + new_hfn = rx_deliv_hfn + 1; + rx_deliv_sn = window_size + default_sn; + new_sn = rx_deliv_sn - window_size - 1; + expected_ret = TEST_SUCCESS; + break; + default: + return TEST_FAILED; + } + + rx_deliv = PDCP_SET_COUNT(rx_deliv_hfn, rx_deliv_sn, sn_size); + + /* Configure Uplink to generate expected, encrypted packet */ + pdcp_sn_to_raw_set(conf->input, new_sn, conf->entity.pdcp_xfrm.sn_size); + conf->entity.reverse_iv_direction = true; + conf->entity.count = PDCP_SET_COUNT(new_hfn, new_sn, sn_size); + conf->output_len = 0; + ret = test_attempt_single(conf); + if (ret != TEST_SUCCESS) + return ret; + + /* Flip configuration to downlink */ + uplink_to_downlink_convert(conf, &dl_conf); + /* Modify the rx_deliv to verify the expected behaviour */ + dl_conf.entity.count = rx_deliv; + ret = test_attempt_single(&dl_conf); + if (ret == TEST_SKIPPED) + return TEST_SKIPPED; + TEST_ASSERT_EQUAL(ret, expected_ret, "Unexpected result"); + + return TEST_SUCCESS; +} + +static int +test_sn_range_type(enum sn_range_type type) +{ + int i, ret, passed = 0; + struct pdcp_test_conf t_conf; + + int nb_test = RTE_DIM(pdcp_test_params); + + for (i = 0; i < nb_test; i++) { + create_test_conf_from_index(i, &t_conf); + if (t_conf.entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) + continue; + printf("[%03i] - %s", i, pdcp_test_params[i].name); + ret = test_sn_range_type_with_config(type, &t_conf); + if (ret == TEST_FAILED) { + printf(" - failed\n"); + return ret; + } else if (ret == TEST_SKIPPED) { + printf(" - skipped\n"); + continue; + } + printf(" - passed\n"); + passed += 1; + } + + printf("Passed: %i\n", passed); + + return TEST_SUCCESS; +} + +static int +test_sn_plus_window(void) +{ + return test_sn_range_type(SN_RANGE_PLUS_WINDOW); +} + +static int +test_sn_minus_window(void) +{ + return test_sn_range_type(SN_RANGE_MINUS_WINDOW); +} + + +static int +test_sn_plus_outside(void) +{ + return test_sn_range_type(SN_RANGE_PLUS_OUTSIDE); +} + +static int +test_sn_minus_outside(void) +{ + return test_sn_range_type(SN_RANGE_MINUS_OUTSIDE); +} + static int test_iterate_all(void) { @@ -632,6 +871,7 @@ test_iterate_all(void) printf(" - passed\n"); passed += 1; } + printf("Passed: %i\n", passed); return TEST_SUCCESS; @@ -643,8 +883,52 @@ test_sample(void) return test_iterate_all(); } -static struct unit_test_suite pdcp_testsuite = { - .suite_name = "PDCP Unit Test Suite", +static int +test_combined(void) +{ + struct pdcp_test_conf ul_conf, dl_conf; + int ret, nb_test, i, passed = 0; + + nb_test = RTE_DIM(pdcp_test_params); + + for (i = 0; i < nb_test; i++) { + create_test_conf_from_index(i, &ul_conf); + if (ul_conf.entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) + continue; + + ul_conf.entity.reverse_iv_direction = true; + ul_conf.output_len = 0; + printf("[%03i] - %s", i, pdcp_test_params[i].name); + + ret = test_attempt_single(&ul_conf); + if (ret == TEST_FAILED) { + printf(" - failed\n"); + return ret; + } else if (ret == TEST_SKIPPED) { + printf(" - skipped\n"); + continue; + } + + uplink_to_downlink_convert(&ul_conf, &dl_conf); + ret = test_attempt_single(&dl_conf); + if (ret == TEST_FAILED) { + printf(" - failed\n"); + return ret; + } else if (ret == TEST_SKIPPED) { + printf(" - skipped\n"); + continue; + } + + printf(" - passed\n"); + passed += 1; + } + printf("Passed: %i\n", passed); + + return TEST_SUCCESS; +} + +static struct unit_test_suite known_vector_cases = { + .suite_name = "PDCP known vectors", .setup = testsuite_setup, .teardown = testsuite_teardown, .unit_test_cases = { @@ -654,10 +938,62 @@ static struct unit_test_suite pdcp_testsuite = { } }; +static struct unit_test_suite combined_mode_cases = { + .suite_name = "PDCP combined mode", + .setup = testsuite_setup, + .teardown = testsuite_teardown, + .unit_test_cases = { + TEST_CASE_ST(ut_setup_pdcp, ut_teardown_pdcp, + test_combined), + TEST_CASES_END() /**< NULL terminate unit test array */ + } +}; + +static struct unit_test_suite hfn_sn_test_cases = { + .suite_name = "PDCP HFN/SN", + .setup = testsuite_setup, + .teardown = testsuite_teardown, + .unit_test_cases = { + TEST_CASE_ST(ut_setup_pdcp, ut_teardown_pdcp, + test_sn_plus_window), + TEST_CASE_ST(ut_setup_pdcp, ut_teardown_pdcp, + test_sn_minus_window), + TEST_CASE_ST(ut_setup_pdcp, ut_teardown_pdcp, + test_sn_plus_outside), + TEST_CASE_ST(ut_setup_pdcp, ut_teardown_pdcp, + test_sn_minus_outside), + TEST_CASES_END() /**< NULL terminate unit test array */ + } +}; + static int test_pdcp(void) { - return unit_test_suite_runner(&pdcp_testsuite); + int ret; + + static struct unit_test_suite pdcp_testsuite = { + .suite_name = "PDCP Unit Test Suite", + .unit_test_cases = {TEST_CASES_END()}, + }; + + struct unit_test_suite *static_suites[] = { + &known_vector_cases, + &combined_mode_cases, + &hfn_sn_test_cases, + NULL /* End of suites list */ + }; + + pdcp_testsuite.unit_test_suites = rte_zmalloc(NULL, sizeof(static_suites), 0); + if (pdcp_testsuite.unit_test_suites == NULL) { + RTE_LOG(ERR, USER1, "No memory for: '%s'\n", pdcp_testsuite.suite_name); + return TEST_FAILED; + } + + memcpy(pdcp_testsuite.unit_test_suites, static_suites, sizeof(static_suites)); + + ret = unit_test_suite_runner(&pdcp_testsuite); + rte_free(pdcp_testsuite.unit_test_suites); + return ret; } REGISTER_TEST_COMMAND(pdcp_autotest, test_pdcp);