[v3,2/5] test/crypto: add combined mode tests

Message ID 1630644420-1256-3-git-send-email-anoobj@marvell.com (mailing list archive)
State Superseded, archived
Delegated to: akhil goyal
Headers
Series Add lookaside IPsec tests |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Anoob Joseph Sept. 3, 2021, 4:46 a.m. UTC
  Add framework to test IPsec features with all supported
combinations of ciphers.

Signed-off-by: Anoob Joseph <anoobj@marvell.com>
Signed-off-by: Tejasree Kondoj <ktejasree@marvell.com>
---
 app/test/test_cryptodev.c                |  73 +++++++++++++++++++--
 app/test/test_cryptodev_security_ipsec.c | 107 +++++++++++++++++++++++++++++--
 app/test/test_cryptodev_security_ipsec.h |  52 ++++++++++++++-
 3 files changed, 223 insertions(+), 9 deletions(-)
  

Comments

Power, Ciara Sept. 3, 2021, 9:42 a.m. UTC | #1
Hi Anoob, 

>-----Original Message-----
>From: Anoob Joseph <anoobj@marvell.com>
>Sent: Friday 3 September 2021 05:47
>To: Akhil Goyal <gakhil@marvell.com>; Doherty, Declan
><declan.doherty@intel.com>; Zhang, Roy Fan <roy.fan.zhang@intel.com>;
>Ananyev, Konstantin <konstantin.ananyev@intel.com>
>Cc: Anoob Joseph <anoobj@marvell.com>; Jerin Jacob <jerinj@marvell.com>;
>Archana Muniganti <marchana@marvell.com>; Tejasree Kondoj
><ktejasree@marvell.com>; Hemant Agrawal <hemant.agrawal@nxp.com>;
>Nicolau, Radu <radu.nicolau@intel.com>; Power, Ciara
><ciara.power@intel.com>; Gagandeep Singh <g.singh@nxp.com>; dev@dpdk.org
>Subject: [PATCH v3 2/5] test/crypto: add combined mode tests
>
>Add framework to test IPsec features with all supported combinations of ciphers.
>
>Signed-off-by: Anoob Joseph <anoobj@marvell.com>
>Signed-off-by: Tejasree Kondoj <ktejasree@marvell.com>
>---
<snip>

>+static int
>+test_ipsec_proto_all(const struct ipsec_test_flags *flags) {
>+	struct ipsec_test_data td_outb[IPSEC_TEST_PACKETS_MAX];
>+	struct ipsec_test_data td_inb[IPSEC_TEST_PACKETS_MAX];
>+	unsigned int i, nb_pkts = 1, pass_cnt = 0;
>+	int ret;
>+

Is this testcase actually running multiple testcases under the hood?
I wonder could it be suited to use a sub-testsuite structure to bring the testcase results up to the top level, as done with cryptodev blockcipher tests.
Have you considered this approach?

Thanks,
Ciara

>+	for (i = 0; i < RTE_DIM(aead_list); i++) {
>+		test_ipsec_td_prepare(&aead_list[i],
>+				      NULL,
>+				      flags,
>+				      td_outb,
>+				      nb_pkts);
>+
>+		ret = test_ipsec_proto_process(td_outb, td_inb, nb_pkts, true,
>+					       flags);
>+		if (ret == TEST_SKIPPED)
>+			continue;
>+
>+		if (ret == TEST_FAILED)
>+			return TEST_FAILED;
>+
>+		test_ipsec_td_update(td_inb, td_outb, nb_pkts, flags);
>+
>+		ret = test_ipsec_proto_process(td_inb, NULL, nb_pkts, true,
>+					       flags);
>+		if (ret == TEST_SKIPPED)
>+			continue;
>+
>+		if (ret == TEST_FAILED)
>+			return TEST_FAILED;
>+
>+		if (flags->display_alg)
>+			test_ipsec_display_alg(&aead_list[i], NULL);
>+
>+		pass_cnt++;
>+	}
>+
>+	if (pass_cnt > 0)
>+		return TEST_SUCCESS;
>+	else
>+		return TEST_SKIPPED;
>+}
>+
<snip>
  
Anoob Joseph Sept. 3, 2021, 10:04 a.m. UTC | #2
Hi Ciara,

Please see inline.

Thanks,
Anoob

> 
> External Email
> 
> ----------------------------------------------------------------------
> Hi Anoob,
> 
> >-----Original Message-----
> >From: Anoob Joseph <anoobj@marvell.com>
> >Sent: Friday 3 September 2021 05:47
> >To: Akhil Goyal <gakhil@marvell.com>; Doherty, Declan
> ><declan.doherty@intel.com>; Zhang, Roy Fan <roy.fan.zhang@intel.com>;
> >Ananyev, Konstantin <konstantin.ananyev@intel.com>
> >Cc: Anoob Joseph <anoobj@marvell.com>; Jerin Jacob
> ><jerinj@marvell.com>; Archana Muniganti <marchana@marvell.com>;
> >Tejasree Kondoj <ktejasree@marvell.com>; Hemant Agrawal
> ><hemant.agrawal@nxp.com>; Nicolau, Radu <radu.nicolau@intel.com>;
> >Power, Ciara <ciara.power@intel.com>; Gagandeep Singh
> ><g.singh@nxp.com>; dev@dpdk.org
> >Subject: [PATCH v3 2/5] test/crypto: add combined mode tests
> >
> >Add framework to test IPsec features with all supported combinations of
> ciphers.
> >
> >Signed-off-by: Anoob Joseph <anoobj@marvell.com>
> >Signed-off-by: Tejasree Kondoj <ktejasree@marvell.com>
> >---
> <snip>
> 
> >+static int
> >+test_ipsec_proto_all(const struct ipsec_test_flags *flags) {
> >+	struct ipsec_test_data td_outb[IPSEC_TEST_PACKETS_MAX];
> >+	struct ipsec_test_data td_inb[IPSEC_TEST_PACKETS_MAX];
> >+	unsigned int i, nb_pkts = 1, pass_cnt = 0;
> >+	int ret;
> >+
> 
> Is this testcase actually running multiple testcases under the hood?
> I wonder could it be suited to use a sub-testsuite structure to bring the
> testcase results up to the top level, as done with cryptodev blockcipher tests.
> Have you considered this approach?

[Anoob] The idea behind this framework is to test an IPsec feature (like UDP encapsulation) without tying it to any specific algorithm. So what this does is, it loops over a list of possible combinations and then runs the test for each combination. The test would be like this,

1. Do outbound processing to generate encrypted packet
2. Basic checks or validation as required for the test (for example, with UDP encapsulation, we would validate UDP hdr in the processed packet).
3. Any manipulations required (like for ICV corruption negative test)
4. Do inbound processing to get decrypted packet
5. Validate results based on the type of test (ICV corruption would give expect an error while normal tests would have the operation return original plain text packet)

It's actually the array (aead_list) and this loop which initiates the test to be run for all algos. And, since we are not having static vectors for each test case, this approach seemed more straightforward. Do you think sub-testsuite makes more sense here?
 
> 
> Thanks,
> Ciara
> 
> >+	for (i = 0; i < RTE_DIM(aead_list); i++) {
> >+		test_ipsec_td_prepare(&aead_list[i],
> >+				      NULL,
> >+				      flags,
> >+				      td_outb,
> >+				      nb_pkts);
> >+
> >+		ret = test_ipsec_proto_process(td_outb, td_inb, nb_pkts,
> true,
> >+					       flags);
> >+		if (ret == TEST_SKIPPED)
> >+			continue;
> >+
> >+		if (ret == TEST_FAILED)
> >+			return TEST_FAILED;
> >+
> >+		test_ipsec_td_update(td_inb, td_outb, nb_pkts, flags);
> >+
> >+		ret = test_ipsec_proto_process(td_inb, NULL, nb_pkts, true,
> >+					       flags);
> >+		if (ret == TEST_SKIPPED)
> >+			continue;
> >+
> >+		if (ret == TEST_FAILED)
> >+			return TEST_FAILED;
> >+
> >+		if (flags->display_alg)
> >+			test_ipsec_display_alg(&aead_list[i], NULL);
> >+
> >+		pass_cnt++;
> >+	}
> >+
> >+	if (pass_cnt > 0)
> >+		return TEST_SUCCESS;
> >+	else
> >+		return TEST_SKIPPED;
> >+}
> >+
> <snip>
  
Power, Ciara Sept. 3, 2021, 3:04 p.m. UTC | #3
Hi Anoob,


>-----Original Message-----
>From: Anoob Joseph <anoobj@marvell.com>
>Sent: Friday 3 September 2021 11:05
>To: Power, Ciara <ciara.power@intel.com>; Akhil Goyal <gakhil@marvell.com>;
>Doherty, Declan <declan.doherty@intel.com>; Zhang, Roy Fan
><roy.fan.zhang@intel.com>; Ananyev, Konstantin
><konstantin.ananyev@intel.com>
>Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Archana Muniganti
><marchana@marvell.com>; Tejasree Kondoj <ktejasree@marvell.com>; Hemant
>Agrawal <hemant.agrawal@nxp.com>; Nicolau, Radu <radu.nicolau@intel.com>;
>Gagandeep Singh <g.singh@nxp.com>; dev@dpdk.org
>Subject: RE: [PATCH v3 2/5] test/crypto: add combined mode tests
>
>Hi Ciara,
>
>Please see inline.
>
>Thanks,
>Anoob
>
>>
>> External Email
>>
>> ----------------------------------------------------------------------
>> Hi Anoob,
>>
>> >-----Original Message-----
>> >From: Anoob Joseph <anoobj@marvell.com>
>> >Sent: Friday 3 September 2021 05:47
>> >To: Akhil Goyal <gakhil@marvell.com>; Doherty, Declan
>> ><declan.doherty@intel.com>; Zhang, Roy Fan <roy.fan.zhang@intel.com>;
>> >Ananyev, Konstantin <konstantin.ananyev@intel.com>
>> >Cc: Anoob Joseph <anoobj@marvell.com>; Jerin Jacob
>> ><jerinj@marvell.com>; Archana Muniganti <marchana@marvell.com>;
>> >Tejasree Kondoj <ktejasree@marvell.com>; Hemant Agrawal
>> ><hemant.agrawal@nxp.com>; Nicolau, Radu <radu.nicolau@intel.com>;
>> >Power, Ciara <ciara.power@intel.com>; Gagandeep Singh
>> ><g.singh@nxp.com>; dev@dpdk.org
>> >Subject: [PATCH v3 2/5] test/crypto: add combined mode tests
>> >
>> >Add framework to test IPsec features with all supported combinations
>> >of
>> ciphers.
>> >
>> >Signed-off-by: Anoob Joseph <anoobj@marvell.com>
>> >Signed-off-by: Tejasree Kondoj <ktejasree@marvell.com>
>> >---
>> <snip>
>>
>> >+static int
>> >+test_ipsec_proto_all(const struct ipsec_test_flags *flags) {
>> >+	struct ipsec_test_data td_outb[IPSEC_TEST_PACKETS_MAX];
>> >+	struct ipsec_test_data td_inb[IPSEC_TEST_PACKETS_MAX];
>> >+	unsigned int i, nb_pkts = 1, pass_cnt = 0;
>> >+	int ret;
>> >+
>>
>> Is this testcase actually running multiple testcases under the hood?
>> I wonder could it be suited to use a sub-testsuite structure to bring
>> the testcase results up to the top level, as done with cryptodev blockcipher
>tests.
>> Have you considered this approach?
>
>[Anoob] The idea behind this framework is to test an IPsec feature (like UDP
>encapsulation) without tying it to any specific algorithm. So what this does is, it
>loops over a list of possible combinations and then runs the test for each
>combination. The test would be like this,
>
>1. Do outbound processing to generate encrypted packet 2. Basic checks or
>validation as required for the test (for example, with UDP encapsulation, we
>would validate UDP hdr in the processed packet).
>3. Any manipulations required (like for ICV corruption negative test) 4. Do
>inbound processing to get decrypted packet 5. Validate results based on the type
>of test (ICV corruption would give expect an error while normal tests would have
>the operation return original plain text packet)
>
>It's actually the array (aead_list) and this loop which initiates the test to be run for
>all algos. And, since we are not having static vectors for each test case, this
>approach seemed more straightforward. Do you think sub-testsuite makes more
>sense here?
>

Thanks for the explanation.
I still think having each test reporting its individual result to the top level provides more clarity when running tests,
rather than having multiple tests being run under the disguise of one, and reporting one result.

Even without the sub-testsuite approach, I wonder could something such as the following be more descriptive when looking at results?

static struct unit_test_suite ipsec_proto_testsuite  = {
	.suite_name = "IPsec Proto Unit Test Suite",
	.setup = ipsec_proto_testsuite_setup,
	.unit_test_cases = {
		< Inbound known vector test cases as before >
		
		TEST_CASE_NAMED_WITH_DATA(
			"Combination test (AES-GCM 128)",
			ut_setup_security, ut_teardown,
			test_ipsec_proto_display_list, &aead_list[0]),
		TEST_CASE_NAMED_WITH_DATA(
			"Combination test (AES-GCM 192)",
			ut_setup_security, ut_teardown,
			test_ipsec_proto_display_list, &aead_list[1]),
		TEST_CASE_NAMED_WITH_DATA(
			"Combination test (AES-GCM 256)",
			ut_setup_security, ut_teardown,
			test_ipsec_proto_display_list, &aead_list[2]),

		TEST_CASE_NAMED_WITH_DATA(
			"IV Generation (AES-GCM 128)",
			ut_setup_security, ut_teardown,
			test_ipsec_proto_iv_gen, &aead_list[0]),

		etc.
}

static int
test_ipsec_proto_display_list(const void *data)
{
	struct ipsec_test_flags flags;

	memset(&flags, 0, sizeof(flags));

	flags.display_alg = true;

	return test_ipsec_proto(&flags, (const struct crypto_param *)data);
}

static int
test_ipsec_proto(const struct ipsec_test_flags *flags, const struct crypto_param *data)
{
	struct ipsec_test_data td_outb[IPSEC_TEST_PACKETS_MAX];
	struct ipsec_test_data td_inb[IPSEC_TEST_PACKETS_MAX];
	unsigned int i, nb_pkts = 1, pass_cnt = 0;
	int ret;

	if (flags->iv_gen)
		nb_pkts = IPSEC_TEST_PACKETS_MAX;

	
	test_ipsec_td_prepare(&data,
				      NULL,
				      flags,
				      td_outb,
				      nb_pkts);

< the rest of the function as before but without the loop, using data instead of looping aead values >


Thanks,
Ciara

>>
>> Thanks,
>> Ciara
>>
>> >+	for (i = 0; i < RTE_DIM(aead_list); i++) {
>> >+		test_ipsec_td_prepare(&aead_list[i],
>> >+				      NULL,
>> >+				      flags,
>> >+				      td_outb,
>> >+				      nb_pkts);
>> >+
>> >+		ret = test_ipsec_proto_process(td_outb, td_inb, nb_pkts,
>> true,
>> >+					       flags);
>> >+		if (ret == TEST_SKIPPED)
>> >+			continue;
>> >+
>> >+		if (ret == TEST_FAILED)
>> >+			return TEST_FAILED;
>> >+
>> >+		test_ipsec_td_update(td_inb, td_outb, nb_pkts, flags);
>> >+
>> >+		ret = test_ipsec_proto_process(td_inb, NULL, nb_pkts, true,
>> >+					       flags);
>> >+		if (ret == TEST_SKIPPED)
>> >+			continue;
>> >+
>> >+		if (ret == TEST_FAILED)
>> >+			return TEST_FAILED;
>> >+
>> >+		if (flags->display_alg)
>> >+			test_ipsec_display_alg(&aead_list[i], NULL);
>> >+
>> >+		pass_cnt++;
>> >+	}
>> >+
>> >+	if (pass_cnt > 0)
>> >+		return TEST_SUCCESS;
>> >+	else
>> >+		return TEST_SKIPPED;
>> >+}
>> >+
>> <snip>
  
Anoob Joseph Sept. 3, 2021, 4:14 p.m. UTC | #4
HI Ciara,

Please see inline.

Thanks,
Anoob

> 
> External Email
> 
> ----------------------------------------------------------------------
> Hi Anoob,
> 
> 
> >-----Original Message-----
> >From: Anoob Joseph <anoobj@marvell.com>
> >Sent: Friday 3 September 2021 11:05
> >To: Power, Ciara <ciara.power@intel.com>; Akhil Goyal
> ><gakhil@marvell.com>; Doherty, Declan <declan.doherty@intel.com>;
> >Zhang, Roy Fan <roy.fan.zhang@intel.com>; Ananyev, Konstantin
> ><konstantin.ananyev@intel.com>
> >Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Archana Muniganti
> ><marchana@marvell.com>; Tejasree Kondoj <ktejasree@marvell.com>;
> Hemant
> >Agrawal <hemant.agrawal@nxp.com>; Nicolau, Radu
> ><radu.nicolau@intel.com>; Gagandeep Singh <g.singh@nxp.com>;
> >dev@dpdk.org
> >Subject: RE: [PATCH v3 2/5] test/crypto: add combined mode tests
> >
> >Hi Ciara,
> >
> >Please see inline.
> >
> >Thanks,
> >Anoob
> >
> >>
> >> External Email
> >>
> >> ---------------------------------------------------------------------
> >> -
> >> Hi Anoob,
> >>
> >> >-----Original Message-----
> >> >From: Anoob Joseph <anoobj@marvell.com>
> >> >Sent: Friday 3 September 2021 05:47
> >> >To: Akhil Goyal <gakhil@marvell.com>; Doherty, Declan
> >> ><declan.doherty@intel.com>; Zhang, Roy Fan
> >> ><roy.fan.zhang@intel.com>; Ananyev, Konstantin
> >> ><konstantin.ananyev@intel.com>
> >> >Cc: Anoob Joseph <anoobj@marvell.com>; Jerin Jacob
> >> ><jerinj@marvell.com>; Archana Muniganti <marchana@marvell.com>;
> >> >Tejasree Kondoj <ktejasree@marvell.com>; Hemant Agrawal
> >> ><hemant.agrawal@nxp.com>; Nicolau, Radu <radu.nicolau@intel.com>;
> >> >Power, Ciara <ciara.power@intel.com>; Gagandeep Singh
> >> ><g.singh@nxp.com>; dev@dpdk.org
> >> >Subject: [PATCH v3 2/5] test/crypto: add combined mode tests
> >> >
> >> >Add framework to test IPsec features with all supported combinations
> >> >of
> >> ciphers.
> >> >
> >> >Signed-off-by: Anoob Joseph <anoobj@marvell.com>
> >> >Signed-off-by: Tejasree Kondoj <ktejasree@marvell.com>
> >> >---
> >> <snip>
> >>
> >> >+static int
> >> >+test_ipsec_proto_all(const struct ipsec_test_flags *flags) {
> >> >+	struct ipsec_test_data td_outb[IPSEC_TEST_PACKETS_MAX];
> >> >+	struct ipsec_test_data td_inb[IPSEC_TEST_PACKETS_MAX];
> >> >+	unsigned int i, nb_pkts = 1, pass_cnt = 0;
> >> >+	int ret;
> >> >+
> >>
> >> Is this testcase actually running multiple testcases under the hood?
> >> I wonder could it be suited to use a sub-testsuite structure to bring
> >> the testcase results up to the top level, as done with cryptodev
> >> blockcipher
> >tests.
> >> Have you considered this approach?
> >
> >[Anoob] The idea behind this framework is to test an IPsec feature
> >(like UDP
> >encapsulation) without tying it to any specific algorithm. So what this
> >does is, it loops over a list of possible combinations and then runs
> >the test for each combination. The test would be like this,
> >
> >1. Do outbound processing to generate encrypted packet 2. Basic checks
> >or validation as required for the test (for example, with UDP
> >encapsulation, we would validate UDP hdr in the processed packet).
> >3. Any manipulations required (like for ICV corruption negative test)
> >4. Do inbound processing to get decrypted packet 5. Validate results
> >based on the type of test (ICV corruption would give expect an error
> >while normal tests would have the operation return original plain text
> >packet)
> >
> >It's actually the array (aead_list) and this loop which initiates the
> >test to be run for all algos. And, since we are not having static
> >vectors for each test case, this approach seemed more straightforward.
> >Do you think sub-testsuite makes more sense here?
> >
> 
> Thanks for the explanation.
> I still think having each test reporting its individual result to the top level
> provides more clarity when running tests, rather than having multiple tests
> being run under the disguise of one, and reporting one result.
> 
> Even without the sub-testsuite approach, I wonder could something such as
> the following be more descriptive when looking at results?
> 
> static struct unit_test_suite ipsec_proto_testsuite  = {
> 	.suite_name = "IPsec Proto Unit Test Suite",
> 	.setup = ipsec_proto_testsuite_setup,
> 	.unit_test_cases = {
> 		< Inbound known vector test cases as before >
> 
> 		TEST_CASE_NAMED_WITH_DATA(
> 			"Combination test (AES-GCM 128)",
> 			ut_setup_security, ut_teardown,
> 			test_ipsec_proto_display_list, &aead_list[0]),
> 		TEST_CASE_NAMED_WITH_DATA(
> 			"Combination test (AES-GCM 192)",
> 			ut_setup_security, ut_teardown,
> 			test_ipsec_proto_display_list, &aead_list[1]),
> 		TEST_CASE_NAMED_WITH_DATA(
> 			"Combination test (AES-GCM 256)",
> 			ut_setup_security, ut_teardown,
> 			test_ipsec_proto_display_list, &aead_list[2]),
> 
> 		TEST_CASE_NAMED_WITH_DATA(
> 			"IV Generation (AES-GCM 128)",
> 			ut_setup_security, ut_teardown,
> 			test_ipsec_proto_iv_gen, &aead_list[0]),
> 
> 		etc.
> }
> 
> static int
> test_ipsec_proto_display_list(const void *data) {
> 	struct ipsec_test_flags flags;
> 
> 	memset(&flags, 0, sizeof(flags));
> 
> 	flags.display_alg = true;
> 
> 	return test_ipsec_proto(&flags, (const struct crypto_param *)data); }
> 
> static int
> test_ipsec_proto(const struct ipsec_test_flags *flags, const struct
> crypto_param *data) {
> 	struct ipsec_test_data td_outb[IPSEC_TEST_PACKETS_MAX];
> 	struct ipsec_test_data td_inb[IPSEC_TEST_PACKETS_MAX];
> 	unsigned int i, nb_pkts = 1, pass_cnt = 0;
> 	int ret;
> 
> 	if (flags->iv_gen)
> 		nb_pkts = IPSEC_TEST_PACKETS_MAX;
> 
> 
> 	test_ipsec_td_prepare(&data,
> 				      NULL,
> 				      flags,
> 				      td_outb,
> 				      nb_pkts);
> 
> < the rest of the function as before but without the loop, using data instead
> of looping aead values >

[Anoob] Your suggestion is to not have the loop walk through `aead_list` but instead let the list be defined by test-suite, right?

I agree regarding result reporting part. Squashing all results into one may not be the most desired. But then I didn't want to bombard with large number of prints from IPsec tests, either.

The only issue I see is with a long list of tests. We are actually preparing chained mode tests which would have combinations. Like, if we have AES-CBC & 3DES-CBC supported as ciphers and NULL, SHA1, SHA2 as auth supported, then we are talking about 6 combinations. And currently we have the following tests,

1. ICV corruption
2. IV generation
3. UDP encapsulation

In pipeline (submitted with proposals)
1. Soft expiry
2. Hard expiry
3. IP hdr verify
4. UDP port verify

And if we consider some of the more fundamental tests that we would add like
1. AH
2. Transport
3. Tunnel (IPv4 in IPv4)
4. Tunnel (IPv4 in IPv6)
5. Tunnel (IPv6 in IPv4)
6. Tunnel (IPv6 in IPv6)

Each of the above would become more like test suite on its own and then we would have the list just duplicated for each kind of feature test. But then, let me check an alternate approach. More like,

1. Let the common test suite setup function set flags etc to denote the IPsec feature (be it ICV corruption or UDP encap)
2. The list of tests (cipher combinations) would be common for all feature tests. 

Would something like this work?
  

Patch

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 73923f1..d89307d 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -8860,7 +8860,8 @@  static int
 test_ipsec_proto_process(const struct ipsec_test_data td[],
 			 struct ipsec_test_data res_d[],
 			 int nb_td,
-			 bool silent)
+			 bool silent,
+			 const struct ipsec_test_flags *flags)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
 	struct crypto_unittest_params *ut_params = &unittest_params;
@@ -8977,7 +8978,7 @@  test_ipsec_proto_process(const struct ipsec_test_data td[],
 		/* Process crypto operation */
 		process_crypto_request(dev_id, ut_params->op);
 
-		ret = test_ipsec_status_check(ut_params->op, dir);
+		ret = test_ipsec_status_check(ut_params->op, flags, dir);
 		if (ret != TEST_SUCCESS)
 			goto crypto_op_free;
 
@@ -8985,7 +8986,7 @@  test_ipsec_proto_process(const struct ipsec_test_data td[],
 			res_d_tmp = &res_d[i];
 
 		ret = test_ipsec_post_process(ut_params->ibuf, &td[i],
-					      res_d_tmp, silent);
+					      res_d_tmp, silent, flags);
 		if (ret != TEST_SUCCESS)
 			goto crypto_op_free;
 
@@ -9013,11 +9014,71 @@  test_ipsec_proto_process(const struct ipsec_test_data td[],
 static int
 test_ipsec_proto_known_vec_inb(const void *td_outb)
 {
+	struct ipsec_test_flags flags;
 	struct ipsec_test_data td_inb;
 
+	memset(&flags, 0, sizeof(flags));
+
 	test_ipsec_td_in_from_out(td_outb, &td_inb);
 
-	return test_ipsec_proto_process(&td_inb, NULL, 1, false);
+	return test_ipsec_proto_process(&td_inb, NULL, 1, false, &flags);
+}
+
+static int
+test_ipsec_proto_all(const struct ipsec_test_flags *flags)
+{
+	struct ipsec_test_data td_outb[IPSEC_TEST_PACKETS_MAX];
+	struct ipsec_test_data td_inb[IPSEC_TEST_PACKETS_MAX];
+	unsigned int i, nb_pkts = 1, pass_cnt = 0;
+	int ret;
+
+	for (i = 0; i < RTE_DIM(aead_list); i++) {
+		test_ipsec_td_prepare(&aead_list[i],
+				      NULL,
+				      flags,
+				      td_outb,
+				      nb_pkts);
+
+		ret = test_ipsec_proto_process(td_outb, td_inb, nb_pkts, true,
+					       flags);
+		if (ret == TEST_SKIPPED)
+			continue;
+
+		if (ret == TEST_FAILED)
+			return TEST_FAILED;
+
+		test_ipsec_td_update(td_inb, td_outb, nb_pkts, flags);
+
+		ret = test_ipsec_proto_process(td_inb, NULL, nb_pkts, true,
+					       flags);
+		if (ret == TEST_SKIPPED)
+			continue;
+
+		if (ret == TEST_FAILED)
+			return TEST_FAILED;
+
+		if (flags->display_alg)
+			test_ipsec_display_alg(&aead_list[i], NULL);
+
+		pass_cnt++;
+	}
+
+	if (pass_cnt > 0)
+		return TEST_SUCCESS;
+	else
+		return TEST_SKIPPED;
+}
+
+static int
+test_ipsec_proto_display_list(const void *data __rte_unused)
+{
+	struct ipsec_test_flags flags;
+
+	memset(&flags, 0, sizeof(flags));
+
+	flags.display_alg = true;
+
+	return test_ipsec_proto_all(&flags);
 }
 
 static int
@@ -13926,6 +13987,10 @@  static struct unit_test_suite ipsec_proto_testsuite  = {
 			"Inbound known vector (ESP tunnel mode IPv4 AES-GCM 256)",
 			ut_setup_security, ut_teardown,
 			test_ipsec_proto_known_vec_inb, &pkt_aes_256_gcm),
+		TEST_CASE_NAMED_ST(
+			"Combined test alg list",
+			ut_setup_security, ut_teardown,
+			test_ipsec_proto_display_list),
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
 };
diff --git a/app/test/test_cryptodev_security_ipsec.c b/app/test/test_cryptodev_security_ipsec.c
index 2431fcb..d08e093 100644
--- a/app/test/test_cryptodev_security_ipsec.c
+++ b/app/test/test_cryptodev_security_ipsec.c
@@ -10,6 +10,8 @@ 
 #include "test.h"
 #include "test_cryptodev_security_ipsec.h"
 
+extern struct ipsec_test_data pkt_aes_256_gcm;
+
 int
 test_ipsec_sec_caps_verify(struct rte_security_ipsec_xform *ipsec_xform,
 			   const struct rte_security_capability *sec_cap,
@@ -128,6 +130,68 @@  test_ipsec_td_in_from_out(const struct ipsec_test_data *td_out,
 	}
 }
 
+void
+test_ipsec_td_prepare(const struct crypto_param *param1,
+		      const struct crypto_param *param2,
+		      const struct ipsec_test_flags *flags,
+		      struct ipsec_test_data *td_array,
+		      int nb_td)
+
+{
+	struct ipsec_test_data *td;
+	int i;
+
+	memset(td_array, 0, nb_td * sizeof(*td));
+
+	for (i = 0; i < nb_td; i++) {
+		td = &td_array[i];
+		/* Copy template for packet & key fields */
+		memcpy(td, &pkt_aes_256_gcm, sizeof(*td));
+
+		/* Override fields based on param */
+
+		if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD)
+			td->aead = true;
+		else
+			td->aead = false;
+
+		td->xform.aead.aead.algo = param1->alg.aead;
+		td->xform.aead.aead.key.length = param1->key_length;
+	}
+
+	RTE_SET_USED(flags);
+	RTE_SET_USED(param2);
+}
+
+void
+test_ipsec_td_update(struct ipsec_test_data td_inb[],
+		     const struct ipsec_test_data td_outb[],
+		     int nb_td,
+		     const struct ipsec_test_flags *flags)
+{
+	int i;
+
+	for (i = 0; i < nb_td; i++) {
+		memcpy(td_inb[i].output_text.data, td_outb[i].input_text.data,
+		       td_outb[i].input_text.len);
+		td_inb[i].output_text.len = td_outb->input_text.len;
+	}
+
+	RTE_SET_USED(flags);
+}
+
+void
+test_ipsec_display_alg(const struct crypto_param *param1,
+		       const struct crypto_param *param2)
+{
+	if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD)
+		printf("\t%s [%d]\n",
+		       rte_crypto_aead_algorithm_strings[param1->alg.aead],
+		       param1->key_length);
+
+	RTE_SET_USED(param2);
+}
+
 static int
 test_ipsec_tunnel_hdr_len_get(const struct ipsec_test_data *td)
 {
@@ -148,7 +212,7 @@  test_ipsec_tunnel_hdr_len_get(const struct ipsec_test_data *td)
 
 static int
 test_ipsec_td_verify(struct rte_mbuf *m, const struct ipsec_test_data *td,
-		     bool silent)
+		     bool silent, const struct ipsec_test_flags *flags)
 {
 	uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *);
 	uint32_t skip, len = rte_pktmbuf_pkt_len(m);
@@ -177,12 +241,37 @@  test_ipsec_td_verify(struct rte_mbuf *m, const struct ipsec_test_data *td,
 		return TEST_FAILED;
 	}
 
+	RTE_SET_USED(flags);
+
+	return TEST_SUCCESS;
+}
+
+static int
+test_ipsec_res_d_prepare(struct rte_mbuf *m, const struct ipsec_test_data *td,
+		   struct ipsec_test_data *res_d)
+{
+	uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *);
+	uint32_t len = rte_pktmbuf_pkt_len(m);
+
+	memcpy(res_d, td, sizeof(*res_d));
+	memcpy(res_d->input_text.data, output_text, len);
+	res_d->input_text.len = len;
+
+	res_d->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+	if (res_d->aead) {
+		res_d->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
+	} else {
+		printf("Only AEAD supported\n");
+		return TEST_SKIPPED;
+	}
+
 	return TEST_SUCCESS;
 }
 
 int
 test_ipsec_post_process(struct rte_mbuf *m, const struct ipsec_test_data *td,
-			struct ipsec_test_data *res_d, bool silent)
+			struct ipsec_test_data *res_d, bool silent,
+			const struct ipsec_test_flags *flags)
 {
 	/*
 	 * In case of known vector tests & all inbound tests, res_d provided
@@ -190,13 +279,22 @@  test_ipsec_post_process(struct rte_mbuf *m, const struct ipsec_test_data *td,
 	 * For inbound, output_text would be plain packet and for outbound
 	 * output_text would IPsec packet. Validate by comparing against
 	 * known vectors.
+	 *
+	 * In case of combined mode tests, the output_text from outbound
+	 * operation (ie, IPsec packet) would need to be inbound processed to
+	 * obtain the plain text. Copy output_text to result data, 'res_d', so
+	 * that inbound processing can be done.
 	 */
-	RTE_SET_USED(res_d);
-	return test_ipsec_td_verify(m, td, silent);
+
+	if (res_d == NULL)
+		return test_ipsec_td_verify(m, td, silent, flags);
+	else
+		return test_ipsec_res_d_prepare(m, td, res_d);
 }
 
 int
 test_ipsec_status_check(struct rte_crypto_op *op,
+			const struct ipsec_test_flags *flags,
 			enum rte_security_ipsec_sa_direction dir)
 {
 	int ret = TEST_SUCCESS;
@@ -206,6 +304,7 @@  test_ipsec_status_check(struct rte_crypto_op *op,
 		ret = TEST_FAILED;
 	}
 
+	RTE_SET_USED(flags);
 	RTE_SET_USED(dir);
 
 	return ret;
diff --git a/app/test/test_cryptodev_security_ipsec.h b/app/test/test_cryptodev_security_ipsec.h
index 5f1b46d..cbb3ee4 100644
--- a/app/test/test_cryptodev_security_ipsec.h
+++ b/app/test/test_cryptodev_security_ipsec.h
@@ -8,6 +8,8 @@ 
 #include <rte_cryptodev.h>
 #include <rte_security.h>
 
+#define IPSEC_TEST_PACKETS_MAX 32
+
 struct ipsec_test_data {
 	struct {
 		uint8_t data[32];
@@ -45,6 +47,38 @@  struct ipsec_test_data {
 	} xform;
 };
 
+struct ipsec_test_flags {
+	bool display_alg;
+};
+
+struct crypto_param {
+	enum rte_crypto_sym_xform_type type;
+	union {
+		enum rte_crypto_cipher_algorithm cipher;
+		enum rte_crypto_auth_algorithm auth;
+		enum rte_crypto_aead_algorithm aead;
+	} alg;
+	uint16_t key_length;
+};
+
+static const struct crypto_param aead_list[] = {
+	{
+		.type = RTE_CRYPTO_SYM_XFORM_AEAD,
+		.alg.aead =  RTE_CRYPTO_AEAD_AES_GCM,
+		.key_length = 16,
+	},
+	{
+		.type = RTE_CRYPTO_SYM_XFORM_AEAD,
+		.alg.aead = RTE_CRYPTO_AEAD_AES_GCM,
+		.key_length = 24,
+	},
+	{
+		.type = RTE_CRYPTO_SYM_XFORM_AEAD,
+		.alg.aead = RTE_CRYPTO_AEAD_AES_GCM,
+		.key_length = 32
+	},
+};
+
 int test_ipsec_sec_caps_verify(struct rte_security_ipsec_xform *ipsec_xform,
 			       const struct rte_security_capability *sec_cap,
 			       bool silent);
@@ -56,11 +90,27 @@  int test_ipsec_crypto_caps_aead_verify(
 void test_ipsec_td_in_from_out(const struct ipsec_test_data *td_out,
 			       struct ipsec_test_data *td_in);
 
+void test_ipsec_td_prepare(const struct crypto_param *param1,
+			   const struct crypto_param *param2,
+			   const struct ipsec_test_flags *flags,
+			   struct ipsec_test_data *td_array,
+			   int nb_td);
+
+void test_ipsec_td_update(struct ipsec_test_data td_inb[],
+			  const struct ipsec_test_data td_outb[],
+			  int nb_td,
+			  const struct ipsec_test_flags *flags);
+
+void test_ipsec_display_alg(const struct crypto_param *param1,
+			    const struct crypto_param *param2);
+
 int test_ipsec_post_process(struct rte_mbuf *m,
 			    const struct ipsec_test_data *td,
-			    struct ipsec_test_data *res_d, bool silent);
+			    struct ipsec_test_data *res_d, bool silent,
+			    const struct ipsec_test_flags *flags);
 
 int test_ipsec_status_check(struct rte_crypto_op *op,
+			    const struct ipsec_test_flags *flags,
 			    enum rte_security_ipsec_sa_direction dir);
 
 #endif