xref: /dpdk/app/test/test_cryptodev_security_ipsec.c (revision 4677de0a4c2ba803d0e1adc26774f2c6c8b5b6df)
1474f1202SAnoob Joseph /* SPDX-License-Identifier: BSD-3-Clause
2474f1202SAnoob Joseph  * Copyright(C) 2021 Marvell.
3474f1202SAnoob Joseph  */
4474f1202SAnoob Joseph 
5474f1202SAnoob Joseph #include <rte_common.h>
6474f1202SAnoob Joseph #include <rte_cryptodev.h>
7cd928003STejasree Kondoj #include <rte_esp.h>
8474f1202SAnoob Joseph #include <rte_ip.h>
9474f1202SAnoob Joseph #include <rte_security.h>
1083243502SArchana Muniganti #include <rte_tcp.h>
11c8234341STejasree Kondoj #include <rte_udp.h>
12474f1202SAnoob Joseph 
13474f1202SAnoob Joseph #include "test.h"
14474f1202SAnoob Joseph #include "test_cryptodev_security_ipsec.h"
15474f1202SAnoob Joseph 
16cd928003STejasree Kondoj #define IV_LEN_MAX 16
17757bb461SVidya Sagar Velumuri #define UDP_CUSTOM_SPORT 4650
18757bb461SVidya Sagar Velumuri #define UDP_CUSTOM_DPORT 4660
19cd928003STejasree Kondoj 
20456ed793STyler Retzlaff #ifndef IPVERSION
21456ed793STyler Retzlaff #define IPVERSION 4
22456ed793STyler Retzlaff #endif
23456ed793STyler Retzlaff 
249fb87fbfSTejasree Kondoj static bool
259fb87fbfSTejasree Kondoj is_valid_ipv4_pkt(const struct rte_ipv4_hdr *pkt)
269fb87fbfSTejasree Kondoj {
279fb87fbfSTejasree Kondoj 	/* The IP version number must be 4 */
289fb87fbfSTejasree Kondoj 	if (((pkt->version_ihl) >> 4) != 4)
299fb87fbfSTejasree Kondoj 		return false;
309fb87fbfSTejasree Kondoj 	/*
319fb87fbfSTejasree Kondoj 	 * The IP header length field must be large enough to hold the
329fb87fbfSTejasree Kondoj 	 * minimum length legal IP datagram (20 bytes = 5 words).
339fb87fbfSTejasree Kondoj 	 */
349fb87fbfSTejasree Kondoj 	if ((pkt->version_ihl & 0xf) < 5)
359fb87fbfSTejasree Kondoj 		return false;
369fb87fbfSTejasree Kondoj 
379fb87fbfSTejasree Kondoj 	/*
389fb87fbfSTejasree Kondoj 	 * The IP total length field must be large enough to hold the IP
399fb87fbfSTejasree Kondoj 	 * datagram header, whose length is specified in the IP header length
409fb87fbfSTejasree Kondoj 	 * field.
419fb87fbfSTejasree Kondoj 	 */
429fb87fbfSTejasree Kondoj 	if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct rte_ipv4_hdr))
439fb87fbfSTejasree Kondoj 		return false;
449fb87fbfSTejasree Kondoj 
459fb87fbfSTejasree Kondoj 	return true;
469fb87fbfSTejasree Kondoj }
479fb87fbfSTejasree Kondoj 
489fb87fbfSTejasree Kondoj static bool
499fb87fbfSTejasree Kondoj is_valid_ipv6_pkt(const struct rte_ipv6_hdr *pkt)
509fb87fbfSTejasree Kondoj {
519fb87fbfSTejasree Kondoj 	/* The IP version number must be 6 */
529fb87fbfSTejasree Kondoj 	if ((rte_be_to_cpu_32((pkt->vtc_flow)) >> 28) != 6)
539fb87fbfSTejasree Kondoj 		return false;
549fb87fbfSTejasree Kondoj 
559fb87fbfSTejasree Kondoj 	return true;
569fb87fbfSTejasree Kondoj }
579fb87fbfSTejasree Kondoj 
58474f1202SAnoob Joseph int
59474f1202SAnoob Joseph test_ipsec_sec_caps_verify(struct rte_security_ipsec_xform *ipsec_xform,
60474f1202SAnoob Joseph 			   const struct rte_security_capability *sec_cap,
61474f1202SAnoob Joseph 			   bool silent)
62474f1202SAnoob Joseph {
63474f1202SAnoob Joseph 	/* Verify security capabilities */
64474f1202SAnoob Joseph 
65474f1202SAnoob Joseph 	if (ipsec_xform->options.esn == 1 && sec_cap->ipsec.options.esn == 0) {
66474f1202SAnoob Joseph 		if (!silent)
67474f1202SAnoob Joseph 			RTE_LOG(INFO, USER1, "ESN is not supported\n");
68474f1202SAnoob Joseph 		return -ENOTSUP;
69474f1202SAnoob Joseph 	}
70474f1202SAnoob Joseph 
71474f1202SAnoob Joseph 	if (ipsec_xform->options.udp_encap == 1 &&
72474f1202SAnoob Joseph 	    sec_cap->ipsec.options.udp_encap == 0) {
73474f1202SAnoob Joseph 		if (!silent)
74474f1202SAnoob Joseph 			RTE_LOG(INFO, USER1, "UDP encapsulation is not supported\n");
75474f1202SAnoob Joseph 		return -ENOTSUP;
76474f1202SAnoob Joseph 	}
77474f1202SAnoob Joseph 
789ec50a52STejasree Kondoj 	if (ipsec_xform->options.udp_ports_verify == 1 &&
799ec50a52STejasree Kondoj 	    sec_cap->ipsec.options.udp_ports_verify == 0) {
809ec50a52STejasree Kondoj 		if (!silent)
819ec50a52STejasree Kondoj 			RTE_LOG(INFO, USER1, "UDP encapsulation ports "
829ec50a52STejasree Kondoj 				"verification is not supported\n");
839ec50a52STejasree Kondoj 		return -ENOTSUP;
849ec50a52STejasree Kondoj 	}
859ec50a52STejasree Kondoj 
86474f1202SAnoob Joseph 	if (ipsec_xform->options.copy_dscp == 1 &&
87474f1202SAnoob Joseph 	    sec_cap->ipsec.options.copy_dscp == 0) {
88474f1202SAnoob Joseph 		if (!silent)
89474f1202SAnoob Joseph 			RTE_LOG(INFO, USER1, "Copy DSCP is not supported\n");
90474f1202SAnoob Joseph 		return -ENOTSUP;
91474f1202SAnoob Joseph 	}
92474f1202SAnoob Joseph 
93474f1202SAnoob Joseph 	if (ipsec_xform->options.copy_flabel == 1 &&
94474f1202SAnoob Joseph 	    sec_cap->ipsec.options.copy_flabel == 0) {
95474f1202SAnoob Joseph 		if (!silent)
96474f1202SAnoob Joseph 			RTE_LOG(INFO, USER1, "Copy Flow Label is not supported\n");
97474f1202SAnoob Joseph 		return -ENOTSUP;
98474f1202SAnoob Joseph 	}
99474f1202SAnoob Joseph 
100474f1202SAnoob Joseph 	if (ipsec_xform->options.copy_df == 1 &&
101474f1202SAnoob Joseph 	    sec_cap->ipsec.options.copy_df == 0) {
102474f1202SAnoob Joseph 		if (!silent)
103474f1202SAnoob Joseph 			RTE_LOG(INFO, USER1, "Copy DP bit is not supported\n");
104474f1202SAnoob Joseph 		return -ENOTSUP;
105474f1202SAnoob Joseph 	}
106474f1202SAnoob Joseph 
107474f1202SAnoob Joseph 	if (ipsec_xform->options.dec_ttl == 1 &&
108474f1202SAnoob Joseph 	    sec_cap->ipsec.options.dec_ttl == 0) {
109474f1202SAnoob Joseph 		if (!silent)
110474f1202SAnoob Joseph 			RTE_LOG(INFO, USER1, "Decrement TTL is not supported\n");
111474f1202SAnoob Joseph 		return -ENOTSUP;
112474f1202SAnoob Joseph 	}
113474f1202SAnoob Joseph 
114474f1202SAnoob Joseph 	if (ipsec_xform->options.ecn == 1 && sec_cap->ipsec.options.ecn == 0) {
115474f1202SAnoob Joseph 		if (!silent)
116474f1202SAnoob Joseph 			RTE_LOG(INFO, USER1, "ECN is not supported\n");
117474f1202SAnoob Joseph 		return -ENOTSUP;
118474f1202SAnoob Joseph 	}
119474f1202SAnoob Joseph 
120474f1202SAnoob Joseph 	if (ipsec_xform->options.stats == 1 &&
121474f1202SAnoob Joseph 	    sec_cap->ipsec.options.stats == 0) {
122474f1202SAnoob Joseph 		if (!silent)
123474f1202SAnoob Joseph 			RTE_LOG(INFO, USER1, "Stats is not supported\n");
124474f1202SAnoob Joseph 		return -ENOTSUP;
125474f1202SAnoob Joseph 	}
126474f1202SAnoob Joseph 
1270532f50cSAnoob Joseph 	if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) &&
1280532f50cSAnoob Joseph 	    (ipsec_xform->options.iv_gen_disable == 1) &&
1290532f50cSAnoob Joseph 	    (sec_cap->ipsec.options.iv_gen_disable != 1)) {
1300532f50cSAnoob Joseph 		if (!silent)
1310532f50cSAnoob Joseph 			RTE_LOG(INFO, USER1,
1320532f50cSAnoob Joseph 				"Application provided IV is not supported\n");
1330532f50cSAnoob Joseph 		return -ENOTSUP;
1340532f50cSAnoob Joseph 	}
1350532f50cSAnoob Joseph 
136270470eeSTejasree Kondoj 	if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
137270470eeSTejasree Kondoj 	    (ipsec_xform->options.tunnel_hdr_verify >
138270470eeSTejasree Kondoj 	    sec_cap->ipsec.options.tunnel_hdr_verify)) {
139270470eeSTejasree Kondoj 		if (!silent)
140270470eeSTejasree Kondoj 			RTE_LOG(INFO, USER1,
141270470eeSTejasree Kondoj 				"Tunnel header verify is not supported\n");
142270470eeSTejasree Kondoj 		return -ENOTSUP;
143270470eeSTejasree Kondoj 	}
144270470eeSTejasree Kondoj 
14583243502SArchana Muniganti 	if (ipsec_xform->options.ip_csum_enable == 1 &&
14683243502SArchana Muniganti 	    sec_cap->ipsec.options.ip_csum_enable == 0) {
14783243502SArchana Muniganti 		if (!silent)
14883243502SArchana Muniganti 			RTE_LOG(INFO, USER1,
14983243502SArchana Muniganti 				"Inner IP checksum is not supported\n");
15083243502SArchana Muniganti 		return -ENOTSUP;
15183243502SArchana Muniganti 	}
15283243502SArchana Muniganti 
15383243502SArchana Muniganti 	if (ipsec_xform->options.l4_csum_enable == 1 &&
15483243502SArchana Muniganti 	    sec_cap->ipsec.options.l4_csum_enable == 0) {
15583243502SArchana Muniganti 		if (!silent)
15683243502SArchana Muniganti 			RTE_LOG(INFO, USER1,
15783243502SArchana Muniganti 				"Inner L4 checksum is not supported\n");
15883243502SArchana Muniganti 		return -ENOTSUP;
15983243502SArchana Muniganti 	}
16083243502SArchana Muniganti 
1612eddc594SVidya Sagar Velumuri 	if (ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
162d02c6bfcSTejasree Kondoj 		if (ipsec_xform->replay_win_sz > sec_cap->ipsec.replay_win_sz_max) {
163d02c6bfcSTejasree Kondoj 			if (!silent)
164d02c6bfcSTejasree Kondoj 				RTE_LOG(INFO, USER1,
165d02c6bfcSTejasree Kondoj 					"Replay window size is not supported\n");
166d02c6bfcSTejasree Kondoj 			return -ENOTSUP;
167d02c6bfcSTejasree Kondoj 		}
1682eddc594SVidya Sagar Velumuri 	}
169d02c6bfcSTejasree Kondoj 
1701d63855bSNithin Dabilpuram 	if (ipsec_xform->options.ingress_oop == 1 &&
1711d63855bSNithin Dabilpuram 	    sec_cap->ipsec.options.ingress_oop == 0) {
1721d63855bSNithin Dabilpuram 		if (!silent)
1731d63855bSNithin Dabilpuram 			RTE_LOG(INFO, USER1,
1741d63855bSNithin Dabilpuram 				"Inline Ingress OOP processing is not supported\n");
1751d63855bSNithin Dabilpuram 		return -ENOTSUP;
1761d63855bSNithin Dabilpuram 	}
1771d63855bSNithin Dabilpuram 
178474f1202SAnoob Joseph 	return 0;
179474f1202SAnoob Joseph }
180474f1202SAnoob Joseph 
181474f1202SAnoob Joseph void
182474f1202SAnoob Joseph test_ipsec_td_in_from_out(const struct ipsec_test_data *td_out,
183474f1202SAnoob Joseph 			  struct ipsec_test_data *td_in)
184474f1202SAnoob Joseph {
185474f1202SAnoob Joseph 	memcpy(td_in, td_out, sizeof(*td_in));
186474f1202SAnoob Joseph 
187474f1202SAnoob Joseph 	/* Populate output text of td_in with input text of td_out */
188474f1202SAnoob Joseph 	memcpy(td_in->output_text.data, td_out->input_text.data,
189474f1202SAnoob Joseph 	       td_out->input_text.len);
190474f1202SAnoob Joseph 	td_in->output_text.len = td_out->input_text.len;
191474f1202SAnoob Joseph 
192474f1202SAnoob Joseph 	/* Populate input text of td_in with output text of td_out */
193474f1202SAnoob Joseph 	memcpy(td_in->input_text.data, td_out->output_text.data,
194474f1202SAnoob Joseph 	       td_out->output_text.len);
195474f1202SAnoob Joseph 	td_in->input_text.len = td_out->output_text.len;
196474f1202SAnoob Joseph 
197474f1202SAnoob Joseph 	td_in->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
198474f1202SAnoob Joseph 
199474f1202SAnoob Joseph 	if (td_in->aead) {
200474f1202SAnoob Joseph 		td_in->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
201474f1202SAnoob Joseph 	} else {
202474f1202SAnoob Joseph 		td_in->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
203474f1202SAnoob Joseph 		td_in->xform.chain.cipher.cipher.op =
204474f1202SAnoob Joseph 				RTE_CRYPTO_CIPHER_OP_DECRYPT;
205474f1202SAnoob Joseph 	}
206474f1202SAnoob Joseph }
207474f1202SAnoob Joseph 
20883243502SArchana Muniganti static bool
20983243502SArchana Muniganti is_ipv4(void *ip)
21083243502SArchana Muniganti {
21183243502SArchana Muniganti 	struct rte_ipv4_hdr *ipv4 = ip;
21283243502SArchana Muniganti 	uint8_t ip_ver;
21383243502SArchana Muniganti 
21483243502SArchana Muniganti 	ip_ver = (ipv4->version_ihl & 0xf0) >> RTE_IPV4_IHL_MULTIPLIER;
21583243502SArchana Muniganti 	if (ip_ver == IPVERSION)
21683243502SArchana Muniganti 		return true;
21783243502SArchana Muniganti 	else
21883243502SArchana Muniganti 		return false;
21983243502SArchana Muniganti }
22083243502SArchana Muniganti 
22183243502SArchana Muniganti static void
22283243502SArchana Muniganti test_ipsec_csum_init(void *ip, bool l3, bool l4)
22383243502SArchana Muniganti {
22483243502SArchana Muniganti 	struct rte_ipv4_hdr *ipv4;
22583243502SArchana Muniganti 	struct rte_tcp_hdr *tcp;
22683243502SArchana Muniganti 	struct rte_udp_hdr *udp;
22783243502SArchana Muniganti 	uint8_t next_proto;
22883243502SArchana Muniganti 	uint8_t size;
22983243502SArchana Muniganti 
23083243502SArchana Muniganti 	if (is_ipv4(ip)) {
23183243502SArchana Muniganti 		ipv4 = ip;
23283243502SArchana Muniganti 		size = sizeof(struct rte_ipv4_hdr);
23383243502SArchana Muniganti 		next_proto = ipv4->next_proto_id;
23483243502SArchana Muniganti 
23583243502SArchana Muniganti 		if (l3)
23683243502SArchana Muniganti 			ipv4->hdr_checksum = 0;
23783243502SArchana Muniganti 	} else {
23883243502SArchana Muniganti 		size = sizeof(struct rte_ipv6_hdr);
23983243502SArchana Muniganti 		next_proto = ((struct rte_ipv6_hdr *)ip)->proto;
24083243502SArchana Muniganti 	}
24183243502SArchana Muniganti 
24283243502SArchana Muniganti 	if (l4) {
24383243502SArchana Muniganti 		switch (next_proto) {
24483243502SArchana Muniganti 		case IPPROTO_TCP:
24583243502SArchana Muniganti 			tcp = (struct rte_tcp_hdr *)RTE_PTR_ADD(ip, size);
24683243502SArchana Muniganti 			tcp->cksum = 0;
24783243502SArchana Muniganti 			break;
24883243502SArchana Muniganti 		case IPPROTO_UDP:
24983243502SArchana Muniganti 			udp = (struct rte_udp_hdr *)RTE_PTR_ADD(ip, size);
25083243502SArchana Muniganti 			udp->dgram_cksum = 0;
25183243502SArchana Muniganti 			break;
25283243502SArchana Muniganti 		default:
25383243502SArchana Muniganti 			return;
25483243502SArchana Muniganti 		}
25583243502SArchana Muniganti 	}
25683243502SArchana Muniganti }
25783243502SArchana Muniganti 
2586622d9c9SAnoob Joseph void
2596622d9c9SAnoob Joseph test_ipsec_td_prepare(const struct crypto_param *param1,
2606622d9c9SAnoob Joseph 		      const struct crypto_param *param2,
2616622d9c9SAnoob Joseph 		      const struct ipsec_test_flags *flags,
2626622d9c9SAnoob Joseph 		      struct ipsec_test_data *td_array,
2636622d9c9SAnoob Joseph 		      int nb_td)
2646622d9c9SAnoob Joseph 
2656622d9c9SAnoob Joseph {
2666622d9c9SAnoob Joseph 	struct ipsec_test_data *td;
2676622d9c9SAnoob Joseph 	int i;
2686622d9c9SAnoob Joseph 
2696622d9c9SAnoob Joseph 	memset(td_array, 0, nb_td * sizeof(*td));
2706622d9c9SAnoob Joseph 
2716622d9c9SAnoob Joseph 	for (i = 0; i < nb_td; i++) {
2726622d9c9SAnoob Joseph 		td = &td_array[i];
2738d290523SAnoob Joseph 
2748d290523SAnoob Joseph 		/* Prepare fields based on param */
2758d290523SAnoob Joseph 
2768d290523SAnoob Joseph 		if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
2776622d9c9SAnoob Joseph 			/* Copy template for packet & key fields */
2789fb87fbfSTejasree Kondoj 			if (flags->ipv6)
2799fb87fbfSTejasree Kondoj 				memcpy(td, &pkt_aes_256_gcm_v6, sizeof(*td));
2809fb87fbfSTejasree Kondoj 			else
2816622d9c9SAnoob Joseph 				memcpy(td, &pkt_aes_256_gcm, sizeof(*td));
2826622d9c9SAnoob Joseph 
283d3142999SArchana Muniganti 			if (param1->alg.aead == RTE_CRYPTO_AEAD_AES_CCM)
284d3142999SArchana Muniganti 				td->salt.len = 3;
285d3142999SArchana Muniganti 
2866622d9c9SAnoob Joseph 			td->aead = true;
2876622d9c9SAnoob Joseph 			td->xform.aead.aead.algo = param1->alg.aead;
2886622d9c9SAnoob Joseph 			td->xform.aead.aead.key.length = param1->key_length;
2898d290523SAnoob Joseph 		} else {
2908d290523SAnoob Joseph 			/* Copy template for packet & key fields */
2919fb87fbfSTejasree Kondoj 			if (flags->ipv6)
2929fb87fbfSTejasree Kondoj 				memcpy(td, &pkt_aes_128_cbc_hmac_sha256_v6,
2939fb87fbfSTejasree Kondoj 					sizeof(*td));
2949fb87fbfSTejasree Kondoj 			else
2959fb87fbfSTejasree Kondoj 				memcpy(td, &pkt_aes_128_cbc_hmac_sha256,
2969fb87fbfSTejasree Kondoj 					sizeof(*td));
2978d290523SAnoob Joseph 
2988d290523SAnoob Joseph 			td->aead = false;
299663d78beSArchana Muniganti 
300663d78beSArchana Muniganti 			if (param1->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
301663d78beSArchana Muniganti 				td->xform.chain.auth.auth.algo =
302663d78beSArchana Muniganti 						param1->alg.auth;
303663d78beSArchana Muniganti 				td->xform.chain.auth.auth.key.length =
304663d78beSArchana Muniganti 						param1->key_length;
305663d78beSArchana Muniganti 				td->xform.chain.auth.auth.digest_length =
306663d78beSArchana Muniganti 						param1->digest_length;
307663d78beSArchana Muniganti 				td->auth_only = true;
3080e4cc244SArchana Muniganti 
3090e4cc244SArchana Muniganti 				if (td->xform.chain.auth.auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
3100e4cc244SArchana Muniganti 					td->xform.chain.auth.auth.iv.length =
3110e4cc244SArchana Muniganti 						param1->iv_length;
3120e4cc244SArchana Muniganti 					td->aes_gmac = true;
3130e4cc244SArchana Muniganti 				}
314663d78beSArchana Muniganti 			} else {
315663d78beSArchana Muniganti 				td->xform.chain.cipher.cipher.algo =
316663d78beSArchana Muniganti 						param1->alg.cipher;
3178d290523SAnoob Joseph 				td->xform.chain.cipher.cipher.key.length =
3188d290523SAnoob Joseph 						param1->key_length;
31967b5428dSAnoob Joseph 				td->xform.chain.cipher.cipher.iv.length =
32067b5428dSAnoob Joseph 						param1->iv_length;
321663d78beSArchana Muniganti 				td->xform.chain.auth.auth.algo =
322663d78beSArchana Muniganti 						param2->alg.auth;
3238d290523SAnoob Joseph 				td->xform.chain.auth.auth.key.length =
3248d290523SAnoob Joseph 						param2->key_length;
3258d290523SAnoob Joseph 				td->xform.chain.auth.auth.digest_length =
3268d290523SAnoob Joseph 						param2->digest_length;
3270e4cc244SArchana Muniganti 
3280e4cc244SArchana Muniganti 				if (td->xform.chain.auth.auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
3290e4cc244SArchana Muniganti 					td->xform.chain.auth.auth.iv.length =
3300e4cc244SArchana Muniganti 						param2->iv_length;
3310e4cc244SArchana Muniganti 					td->aes_gmac = true;
3320e4cc244SArchana Muniganti 				}
333663d78beSArchana Muniganti 			}
334663d78beSArchana Muniganti 		}
3358d290523SAnoob Joseph 
3363edd1197SNithin Dabilpuram 		/* Adjust the data to requested length */
3373edd1197SNithin Dabilpuram 		if (flags->plaintext_len && flags->ipv6) {
3383edd1197SNithin Dabilpuram 			struct rte_ipv6_hdr *ip6 = (struct rte_ipv6_hdr *)td->input_text.data;
3393edd1197SNithin Dabilpuram 			struct rte_tcp_hdr *tcp;
3403edd1197SNithin Dabilpuram 			int64_t payload_len;
3413edd1197SNithin Dabilpuram 			uint8_t *data;
3423edd1197SNithin Dabilpuram 			int64_t i;
3433edd1197SNithin Dabilpuram 
3443edd1197SNithin Dabilpuram 			payload_len = RTE_MIN(flags->plaintext_len, IPSEC_TEXT_MAX_LEN);
3453edd1197SNithin Dabilpuram 			payload_len -= sizeof(struct rte_ipv6_hdr);
3463edd1197SNithin Dabilpuram 			payload_len -= sizeof(struct rte_tcp_hdr);
3473edd1197SNithin Dabilpuram 			if (payload_len <= 16)
3483edd1197SNithin Dabilpuram 				payload_len = 16;
3493edd1197SNithin Dabilpuram 
3503edd1197SNithin Dabilpuram 			/* IPv6 */
3513edd1197SNithin Dabilpuram 			ip6->proto = IPPROTO_TCP;
3523edd1197SNithin Dabilpuram 			ip6->payload_len = sizeof(*tcp) + payload_len;
3533edd1197SNithin Dabilpuram 			ip6->payload_len = rte_cpu_to_be_16(ip6->payload_len);
3543edd1197SNithin Dabilpuram 
3553edd1197SNithin Dabilpuram 			/* TCP */
3563edd1197SNithin Dabilpuram 			tcp = (struct rte_tcp_hdr *)(ip6 + 1);
3573edd1197SNithin Dabilpuram 			data = (uint8_t *)(tcp + 1);
3583edd1197SNithin Dabilpuram 			for (i = 0; i < payload_len; i++)
3593edd1197SNithin Dabilpuram 				data[i] = i;
3603edd1197SNithin Dabilpuram 			tcp->cksum = 0;
3613edd1197SNithin Dabilpuram 			tcp->cksum = rte_ipv6_udptcp_cksum(ip6, tcp);
3623edd1197SNithin Dabilpuram 			td->input_text.len = payload_len + sizeof(struct rte_ipv6_hdr) +
3633edd1197SNithin Dabilpuram 				sizeof(struct rte_tcp_hdr);
3643edd1197SNithin Dabilpuram 		} else if (flags->plaintext_len) {
3653edd1197SNithin Dabilpuram 			struct rte_ipv4_hdr *ip = (struct rte_ipv4_hdr *)td->input_text.data;
3663edd1197SNithin Dabilpuram 			struct rte_tcp_hdr *tcp;
3673edd1197SNithin Dabilpuram 			int64_t payload_len;
3683edd1197SNithin Dabilpuram 			uint8_t *data;
3693edd1197SNithin Dabilpuram 			int64_t i;
3703edd1197SNithin Dabilpuram 
3713edd1197SNithin Dabilpuram 			payload_len = RTE_MIN(flags->plaintext_len, IPSEC_TEXT_MAX_LEN);
3723edd1197SNithin Dabilpuram 			payload_len -= sizeof(struct rte_ipv4_hdr);
3733edd1197SNithin Dabilpuram 			payload_len -= sizeof(struct rte_tcp_hdr);
3743edd1197SNithin Dabilpuram 			if (payload_len <= 8)
3753edd1197SNithin Dabilpuram 				payload_len = 8;
3763edd1197SNithin Dabilpuram 
3773edd1197SNithin Dabilpuram 			/* IPv4 */
3783edd1197SNithin Dabilpuram 			ip->next_proto_id = IPPROTO_TCP;
3793edd1197SNithin Dabilpuram 			ip->total_length = sizeof(*ip) + sizeof(*tcp) + payload_len;
3803edd1197SNithin Dabilpuram 			ip->total_length = rte_cpu_to_be_16(ip->total_length);
3813edd1197SNithin Dabilpuram 			ip->hdr_checksum = 0;
3823edd1197SNithin Dabilpuram 			ip->hdr_checksum = rte_ipv4_cksum(ip);
3833edd1197SNithin Dabilpuram 
3843edd1197SNithin Dabilpuram 			/* TCP */
3853edd1197SNithin Dabilpuram 			tcp = (struct rte_tcp_hdr *)(ip + 1);
3863edd1197SNithin Dabilpuram 			data = (uint8_t *)(tcp + 1);
3873edd1197SNithin Dabilpuram 			for (i = 0; i < payload_len; i++)
3883edd1197SNithin Dabilpuram 				data[i] = i;
3893edd1197SNithin Dabilpuram 			tcp->cksum = 0;
3903edd1197SNithin Dabilpuram 			tcp->cksum = rte_ipv4_udptcp_cksum(ip, tcp);
3913edd1197SNithin Dabilpuram 			td->input_text.len = payload_len + sizeof(struct rte_ipv4_hdr) +
3923edd1197SNithin Dabilpuram 				sizeof(struct rte_tcp_hdr);
3933edd1197SNithin Dabilpuram 		}
3943edd1197SNithin Dabilpuram 
395663d78beSArchana Muniganti 		if (flags->ah) {
396663d78beSArchana Muniganti 			td->ipsec_xform.proto =
397663d78beSArchana Muniganti 					RTE_SECURITY_IPSEC_SA_PROTO_AH;
3988d290523SAnoob Joseph 		}
3990532f50cSAnoob Joseph 
4000532f50cSAnoob Joseph 		if (flags->iv_gen)
4010532f50cSAnoob Joseph 			td->ipsec_xform.options.iv_gen_disable = 0;
4024aa52f21SAnoob Joseph 
4034aa52f21SAnoob Joseph 		if (flags->sa_expiry_pkts_soft)
404838e8decSVidya Sagar Velumuri 			td->ipsec_xform.life.packets_soft_limit = TEST_SEC_PKTS_MAX - 1;
40583243502SArchana Muniganti 
40683243502SArchana Muniganti 		if (flags->ip_csum) {
40783243502SArchana Muniganti 			td->ipsec_xform.options.ip_csum_enable = 1;
40883243502SArchana Muniganti 			test_ipsec_csum_init(&td->input_text.data, true, false);
40983243502SArchana Muniganti 		}
41083243502SArchana Muniganti 
41183243502SArchana Muniganti 		if (flags->l4_csum) {
41283243502SArchana Muniganti 			td->ipsec_xform.options.l4_csum_enable = 1;
41383243502SArchana Muniganti 			test_ipsec_csum_init(&td->input_text.data, false, true);
41483243502SArchana Muniganti 		}
41583243502SArchana Muniganti 
41665d68c7cSAnoob Joseph 		if (flags->transport) {
41765d68c7cSAnoob Joseph 			td->ipsec_xform.mode =
41865d68c7cSAnoob Joseph 					RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT;
41965d68c7cSAnoob Joseph 		} else {
42065d68c7cSAnoob Joseph 			td->ipsec_xform.mode =
42165d68c7cSAnoob Joseph 					RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
42265d68c7cSAnoob Joseph 
4239fb87fbfSTejasree Kondoj 			if (flags->tunnel_ipv6)
4249fb87fbfSTejasree Kondoj 				td->ipsec_xform.tunnel.type =
4259fb87fbfSTejasree Kondoj 						RTE_SECURITY_IPSEC_TUNNEL_IPV6;
4269fb87fbfSTejasree Kondoj 			else
4279fb87fbfSTejasree Kondoj 				td->ipsec_xform.tunnel.type =
4289fb87fbfSTejasree Kondoj 						RTE_SECURITY_IPSEC_TUNNEL_IPV4;
42965d68c7cSAnoob Joseph 		}
43065d68c7cSAnoob Joseph 
4312c85598cSAnkur Dwivedi 		if (flags->stats_success)
4322c85598cSAnkur Dwivedi 			td->ipsec_xform.options.stats = 1;
4339fb87fbfSTejasree Kondoj 
434825ab5c3STejasree Kondoj 		if (flags->fragment) {
435825ab5c3STejasree Kondoj 			struct rte_ipv4_hdr *ip;
436825ab5c3STejasree Kondoj 			ip = (struct rte_ipv4_hdr *)&td->input_text.data;
437825ab5c3STejasree Kondoj 			ip->fragment_offset = 4;
438825ab5c3STejasree Kondoj 			ip->hdr_checksum = rte_ipv4_cksum(ip);
439825ab5c3STejasree Kondoj 		}
440825ab5c3STejasree Kondoj 
441e2cbb384SAnoob Joseph 		if (flags->df == TEST_IPSEC_COPY_DF_INNER_0 ||
442e2cbb384SAnoob Joseph 		    flags->df == TEST_IPSEC_COPY_DF_INNER_1)
443e2cbb384SAnoob Joseph 			td->ipsec_xform.options.copy_df = 1;
44470c60cfdSAnoob Joseph 
44570c60cfdSAnoob Joseph 		if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_0 ||
44670c60cfdSAnoob Joseph 		    flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1)
44770c60cfdSAnoob Joseph 			td->ipsec_xform.options.copy_dscp = 1;
44842902e81SVolodymyr Fialko 
44991d1d052SVamsi Attunuru 		if (flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_0 ||
45091d1d052SVamsi Attunuru 		    flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1)
45191d1d052SVamsi Attunuru 			td->ipsec_xform.options.copy_flabel = 1;
45291d1d052SVamsi Attunuru 
45342902e81SVolodymyr Fialko 		if (flags->dec_ttl_or_hop_limit)
45442902e81SVolodymyr Fialko 			td->ipsec_xform.options.dec_ttl = 1;
455757bb461SVidya Sagar Velumuri 
456757bb461SVidya Sagar Velumuri 		if (flags->udp_encap && flags->udp_encap_custom_ports) {
457757bb461SVidya Sagar Velumuri 			td->ipsec_xform.udp.sport = UDP_CUSTOM_SPORT;
458757bb461SVidya Sagar Velumuri 			td->ipsec_xform.udp.dport = UDP_CUSTOM_DPORT;
459757bb461SVidya Sagar Velumuri 		}
4606622d9c9SAnoob Joseph 	}
4616622d9c9SAnoob Joseph }
4626622d9c9SAnoob Joseph 
4636622d9c9SAnoob Joseph void
4646622d9c9SAnoob Joseph test_ipsec_td_update(struct ipsec_test_data td_inb[],
4656622d9c9SAnoob Joseph 		     const struct ipsec_test_data td_outb[],
4666622d9c9SAnoob Joseph 		     int nb_td,
4676622d9c9SAnoob Joseph 		     const struct ipsec_test_flags *flags)
4686622d9c9SAnoob Joseph {
4696622d9c9SAnoob Joseph 	int i;
4706622d9c9SAnoob Joseph 
4716622d9c9SAnoob Joseph 	for (i = 0; i < nb_td; i++) {
4726622d9c9SAnoob Joseph 		memcpy(td_inb[i].output_text.data, td_outb[i].input_text.data,
4736622d9c9SAnoob Joseph 		       td_outb[i].input_text.len);
4746622d9c9SAnoob Joseph 		td_inb[i].output_text.len = td_outb->input_text.len;
4756622d9c9SAnoob Joseph 
4760f453190STejasree Kondoj 		if (flags->icv_corrupt) {
4770f453190STejasree Kondoj 			int icv_pos = td_inb[i].input_text.len - 4;
4780f453190STejasree Kondoj 			td_inb[i].input_text.data[icv_pos] += 1;
4790f453190STejasree Kondoj 		}
480c8234341STejasree Kondoj 
4816978f51eSAnoob Joseph 		if (flags->sa_expiry_pkts_hard)
482838e8decSVidya Sagar Velumuri 			td_inb[i].ipsec_xform.life.packets_hard_limit = TEST_SEC_PKTS_MAX - 1;
4836978f51eSAnoob Joseph 
484c8234341STejasree Kondoj 		if (flags->udp_encap)
485c8234341STejasree Kondoj 			td_inb[i].ipsec_xform.options.udp_encap = 1;
4860532f50cSAnoob Joseph 
4879ec50a52STejasree Kondoj 		if (flags->udp_ports_verify)
4889ec50a52STejasree Kondoj 			td_inb[i].ipsec_xform.options.udp_ports_verify = 1;
4899ec50a52STejasree Kondoj 
490270470eeSTejasree Kondoj 		td_inb[i].ipsec_xform.options.tunnel_hdr_verify =
491270470eeSTejasree Kondoj 			flags->tunnel_hdr_verify;
492270470eeSTejasree Kondoj 
49383243502SArchana Muniganti 		if (flags->ip_csum)
49483243502SArchana Muniganti 			td_inb[i].ipsec_xform.options.ip_csum_enable = 1;
49583243502SArchana Muniganti 
49683243502SArchana Muniganti 		if (flags->l4_csum)
49783243502SArchana Muniganti 			td_inb[i].ipsec_xform.options.l4_csum_enable = 1;
49883243502SArchana Muniganti 
4990532f50cSAnoob Joseph 		/* Clear outbound specific flags */
5000532f50cSAnoob Joseph 		td_inb[i].ipsec_xform.options.iv_gen_disable = 0;
5010f453190STejasree Kondoj 	}
5026622d9c9SAnoob Joseph }
5036622d9c9SAnoob Joseph 
504474f1202SAnoob Joseph static int
505474f1202SAnoob Joseph test_ipsec_tunnel_hdr_len_get(const struct ipsec_test_data *td)
506474f1202SAnoob Joseph {
507474f1202SAnoob Joseph 	int len = 0;
508474f1202SAnoob Joseph 
509474f1202SAnoob Joseph 	if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
510474f1202SAnoob Joseph 		if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
511474f1202SAnoob Joseph 			if (td->ipsec_xform.tunnel.type ==
512474f1202SAnoob Joseph 					RTE_SECURITY_IPSEC_TUNNEL_IPV4)
513474f1202SAnoob Joseph 				len += sizeof(struct rte_ipv4_hdr);
514474f1202SAnoob Joseph 			else
515474f1202SAnoob Joseph 				len += sizeof(struct rte_ipv6_hdr);
516474f1202SAnoob Joseph 		}
517474f1202SAnoob Joseph 	}
518474f1202SAnoob Joseph 
519474f1202SAnoob Joseph 	return len;
520474f1202SAnoob Joseph }
521474f1202SAnoob Joseph 
522474f1202SAnoob Joseph static int
523c36d7c0dSVolodymyr Fialko test_ipsec_iv_verify_push(const uint8_t *output_text, const struct ipsec_test_data *td)
524cd928003STejasree Kondoj {
525838e8decSVidya Sagar Velumuri 	static uint8_t iv_queue[IV_LEN_MAX * TEST_SEC_PKTS_MAX];
526cd928003STejasree Kondoj 	int i, iv_pos, iv_len;
527cd928003STejasree Kondoj 	static int index;
528c36d7c0dSVolodymyr Fialko 	uint8_t *iv_tmp;
529cd928003STejasree Kondoj 
530cd928003STejasree Kondoj 	if (td->aead)
531cd928003STejasree Kondoj 		iv_len = td->xform.aead.aead.iv.length - td->salt.len;
532cd928003STejasree Kondoj 	else
533cd928003STejasree Kondoj 		iv_len = td->xform.chain.cipher.cipher.iv.length;
534cd928003STejasree Kondoj 
535cd928003STejasree Kondoj 	iv_pos = test_ipsec_tunnel_hdr_len_get(td) + sizeof(struct rte_esp_hdr);
536cd928003STejasree Kondoj 	output_text += iv_pos;
537cd928003STejasree Kondoj 
538cd928003STejasree Kondoj 	TEST_ASSERT(iv_len <= IV_LEN_MAX, "IV length greater than supported");
539cd928003STejasree Kondoj 
540cd928003STejasree Kondoj 	/* Compare against previous values */
541cd928003STejasree Kondoj 	for (i = 0; i < index; i++) {
542cd928003STejasree Kondoj 		iv_tmp = &iv_queue[i * IV_LEN_MAX];
543cd928003STejasree Kondoj 
544cd928003STejasree Kondoj 		if (memcmp(output_text, iv_tmp, iv_len) == 0) {
545cd928003STejasree Kondoj 			printf("IV repeated");
546cd928003STejasree Kondoj 			return TEST_FAILED;
547cd928003STejasree Kondoj 		}
548cd928003STejasree Kondoj 	}
549cd928003STejasree Kondoj 
550cd928003STejasree Kondoj 	/* Save IV for future comparisons */
551cd928003STejasree Kondoj 
552cd928003STejasree Kondoj 	iv_tmp = &iv_queue[index * IV_LEN_MAX];
553cd928003STejasree Kondoj 	memcpy(iv_tmp, output_text, iv_len);
554cd928003STejasree Kondoj 	index++;
555cd928003STejasree Kondoj 
556838e8decSVidya Sagar Velumuri 	if (index == TEST_SEC_PKTS_MAX)
557cd928003STejasree Kondoj 		index = 0;
558cd928003STejasree Kondoj 
559cd928003STejasree Kondoj 	return TEST_SUCCESS;
560cd928003STejasree Kondoj }
561cd928003STejasree Kondoj 
562cd928003STejasree Kondoj static int
563c36d7c0dSVolodymyr Fialko test_ipsec_l3_csum_verify(uint8_t *output_text)
56483243502SArchana Muniganti {
56583243502SArchana Muniganti 	uint16_t actual_cksum, expected_cksum;
56683243502SArchana Muniganti 	struct rte_ipv4_hdr *ip;
56783243502SArchana Muniganti 
568c36d7c0dSVolodymyr Fialko 	ip = (struct rte_ipv4_hdr *)output_text;
56983243502SArchana Muniganti 
57083243502SArchana Muniganti 	if (!is_ipv4((void *)ip))
57183243502SArchana Muniganti 		return TEST_SKIPPED;
57283243502SArchana Muniganti 
57383243502SArchana Muniganti 	actual_cksum = ip->hdr_checksum;
57483243502SArchana Muniganti 
57583243502SArchana Muniganti 	ip->hdr_checksum = 0;
57683243502SArchana Muniganti 
57783243502SArchana Muniganti 	expected_cksum = rte_ipv4_cksum(ip);
57883243502SArchana Muniganti 
57983243502SArchana Muniganti 	if (actual_cksum != expected_cksum)
58083243502SArchana Muniganti 		return TEST_FAILED;
58183243502SArchana Muniganti 
58283243502SArchana Muniganti 	return TEST_SUCCESS;
58383243502SArchana Muniganti }
58483243502SArchana Muniganti 
58583243502SArchana Muniganti static int
586c36d7c0dSVolodymyr Fialko test_ipsec_l4_csum_verify(uint8_t *output_text)
58783243502SArchana Muniganti {
58883243502SArchana Muniganti 	uint16_t actual_cksum = 0, expected_cksum = 0;
58983243502SArchana Muniganti 	struct rte_ipv4_hdr *ipv4;
59083243502SArchana Muniganti 	struct rte_ipv6_hdr *ipv6;
59183243502SArchana Muniganti 	struct rte_tcp_hdr *tcp;
59283243502SArchana Muniganti 	struct rte_udp_hdr *udp;
59383243502SArchana Muniganti 	void *ip, *l4;
59483243502SArchana Muniganti 
595c36d7c0dSVolodymyr Fialko 	ip = output_text;
59683243502SArchana Muniganti 
59783243502SArchana Muniganti 	if (is_ipv4(ip)) {
59883243502SArchana Muniganti 		ipv4 = ip;
59983243502SArchana Muniganti 		l4 = RTE_PTR_ADD(ipv4, sizeof(struct rte_ipv4_hdr));
60083243502SArchana Muniganti 
60183243502SArchana Muniganti 		switch (ipv4->next_proto_id) {
60283243502SArchana Muniganti 		case IPPROTO_TCP:
60383243502SArchana Muniganti 			tcp = (struct rte_tcp_hdr *)l4;
60483243502SArchana Muniganti 			actual_cksum = tcp->cksum;
60583243502SArchana Muniganti 			tcp->cksum = 0;
60683243502SArchana Muniganti 			expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4);
60783243502SArchana Muniganti 			break;
60883243502SArchana Muniganti 		case IPPROTO_UDP:
60983243502SArchana Muniganti 			udp = (struct rte_udp_hdr *)l4;
61083243502SArchana Muniganti 			actual_cksum = udp->dgram_cksum;
61183243502SArchana Muniganti 			udp->dgram_cksum = 0;
61283243502SArchana Muniganti 			expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4);
61383243502SArchana Muniganti 			break;
61483243502SArchana Muniganti 		default:
61583243502SArchana Muniganti 			break;
61683243502SArchana Muniganti 		}
61783243502SArchana Muniganti 	} else {
61883243502SArchana Muniganti 		ipv6 = ip;
61983243502SArchana Muniganti 		l4 = RTE_PTR_ADD(ipv6, sizeof(struct rte_ipv6_hdr));
62083243502SArchana Muniganti 
62183243502SArchana Muniganti 		switch (ipv6->proto) {
62283243502SArchana Muniganti 		case IPPROTO_TCP:
62383243502SArchana Muniganti 			tcp = (struct rte_tcp_hdr *)l4;
62483243502SArchana Muniganti 			actual_cksum = tcp->cksum;
62583243502SArchana Muniganti 			tcp->cksum = 0;
62683243502SArchana Muniganti 			expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4);
62783243502SArchana Muniganti 			break;
62883243502SArchana Muniganti 		case IPPROTO_UDP:
62983243502SArchana Muniganti 			udp = (struct rte_udp_hdr *)l4;
63083243502SArchana Muniganti 			actual_cksum = udp->dgram_cksum;
63183243502SArchana Muniganti 			udp->dgram_cksum = 0;
63283243502SArchana Muniganti 			expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4);
63383243502SArchana Muniganti 			break;
63483243502SArchana Muniganti 		default:
63583243502SArchana Muniganti 			break;
63683243502SArchana Muniganti 		}
63783243502SArchana Muniganti 	}
63883243502SArchana Muniganti 
63983243502SArchana Muniganti 	if (actual_cksum != expected_cksum)
64083243502SArchana Muniganti 		return TEST_FAILED;
64183243502SArchana Muniganti 
64283243502SArchana Muniganti 	return TEST_SUCCESS;
64383243502SArchana Muniganti }
64483243502SArchana Muniganti 
64583243502SArchana Muniganti static int
64642902e81SVolodymyr Fialko test_ipsec_ttl_or_hop_decrement_verify(void *received, void *expected)
64742902e81SVolodymyr Fialko {
64842902e81SVolodymyr Fialko 	struct rte_ipv4_hdr *iph4_ex, *iph4_re;
64942902e81SVolodymyr Fialko 	struct rte_ipv6_hdr *iph6_ex, *iph6_re;
65042902e81SVolodymyr Fialko 
65142902e81SVolodymyr Fialko 	if (is_ipv4(received) && is_ipv4(expected)) {
65242902e81SVolodymyr Fialko 		iph4_ex = expected;
65342902e81SVolodymyr Fialko 		iph4_re = received;
65442902e81SVolodymyr Fialko 		iph4_ex->time_to_live -= 1;
65542902e81SVolodymyr Fialko 		if (iph4_re->time_to_live != iph4_ex->time_to_live)
65642902e81SVolodymyr Fialko 			return TEST_FAILED;
65742902e81SVolodymyr Fialko 	} else if (!is_ipv4(received) && !is_ipv4(expected)) {
65842902e81SVolodymyr Fialko 		iph6_ex = expected;
65942902e81SVolodymyr Fialko 		iph6_re = received;
66042902e81SVolodymyr Fialko 		iph6_ex->hop_limits -= 1;
66142902e81SVolodymyr Fialko 		if (iph6_re->hop_limits != iph6_ex->hop_limits)
66242902e81SVolodymyr Fialko 			return TEST_FAILED;
66342902e81SVolodymyr Fialko 	} else {
66442902e81SVolodymyr Fialko 		printf("IP header version miss match\n");
66542902e81SVolodymyr Fialko 		return TEST_FAILED;
66642902e81SVolodymyr Fialko 	}
66742902e81SVolodymyr Fialko 
66842902e81SVolodymyr Fialko 	return TEST_SUCCESS;
66942902e81SVolodymyr Fialko }
67042902e81SVolodymyr Fialko 
67142902e81SVolodymyr Fialko static int
672c36d7c0dSVolodymyr Fialko test_ipsec_td_verify(uint8_t *output_text, uint32_t len, uint32_t ol_flags,
673c36d7c0dSVolodymyr Fialko 		const struct ipsec_test_data *td, bool silent, const struct ipsec_test_flags *flags)
674474f1202SAnoob Joseph {
6753edd1197SNithin Dabilpuram 	uint8_t td_output_text[IPSEC_TEXT_MAX_LEN];
676c36d7c0dSVolodymyr Fialko 	uint32_t skip;
67783243502SArchana Muniganti 	int ret;
678474f1202SAnoob Joseph 
6796978f51eSAnoob Joseph 	/* For tests with status as error for test success, skip verification */
6806978f51eSAnoob Joseph 	if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
6816978f51eSAnoob Joseph 	    (flags->icv_corrupt ||
682270470eeSTejasree Kondoj 	     flags->sa_expiry_pkts_hard ||
683d02c6bfcSTejasree Kondoj 	     flags->tunnel_hdr_verify ||
684d02c6bfcSTejasree Kondoj 	     td->ar_packet))
6850f453190STejasree Kondoj 		return TEST_SUCCESS;
6860f453190STejasree Kondoj 
687c8234341STejasree Kondoj 	if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
688c8234341STejasree Kondoj 	   flags->udp_encap) {
689c8234341STejasree Kondoj 
690c8234341STejasree Kondoj 		len -= sizeof(struct rte_udp_hdr);
691c8234341STejasree Kondoj 		output_text += sizeof(struct rte_udp_hdr);
692c8234341STejasree Kondoj 	}
693c8234341STejasree Kondoj 
694474f1202SAnoob Joseph 	if (len != td->output_text.len) {
695474f1202SAnoob Joseph 		printf("Output length (%d) not matching with expected (%d)\n",
696474f1202SAnoob Joseph 			len, td->output_text.len);
697474f1202SAnoob Joseph 		return TEST_FAILED;
698474f1202SAnoob Joseph 	}
699474f1202SAnoob Joseph 
700b7986bdeSTejasree Kondoj 	if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) &&
701b7986bdeSTejasree Kondoj 				flags->fragment) {
702b7986bdeSTejasree Kondoj 		const struct rte_ipv4_hdr *iph4;
703b7986bdeSTejasree Kondoj 		iph4 = (const struct rte_ipv4_hdr *)output_text;
704b7986bdeSTejasree Kondoj 		if (iph4->fragment_offset) {
705b7986bdeSTejasree Kondoj 			printf("Output packet is fragmented");
706b7986bdeSTejasree Kondoj 			return TEST_FAILED;
707b7986bdeSTejasree Kondoj 		}
708b7986bdeSTejasree Kondoj 	}
709b7986bdeSTejasree Kondoj 
71083243502SArchana Muniganti 	if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
71183243502SArchana Muniganti 				flags->ip_csum) {
712c36d7c0dSVolodymyr Fialko 		if (ol_flags & RTE_MBUF_F_RX_IP_CKSUM_GOOD)
713c36d7c0dSVolodymyr Fialko 			ret = test_ipsec_l3_csum_verify(output_text);
71483243502SArchana Muniganti 		else
71583243502SArchana Muniganti 			ret = TEST_FAILED;
71683243502SArchana Muniganti 
71783243502SArchana Muniganti 		if (ret == TEST_FAILED)
71883243502SArchana Muniganti 			printf("Inner IP checksum test failed\n");
71983243502SArchana Muniganti 
72083243502SArchana Muniganti 		return ret;
72183243502SArchana Muniganti 	}
72283243502SArchana Muniganti 
72383243502SArchana Muniganti 	if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
72483243502SArchana Muniganti 				flags->l4_csum) {
725c36d7c0dSVolodymyr Fialko 		if (ol_flags & RTE_MBUF_F_RX_L4_CKSUM_GOOD)
726c36d7c0dSVolodymyr Fialko 			ret = test_ipsec_l4_csum_verify(output_text);
72783243502SArchana Muniganti 		else
72883243502SArchana Muniganti 			ret = TEST_FAILED;
72983243502SArchana Muniganti 
73083243502SArchana Muniganti 		if (ret == TEST_FAILED)
73183243502SArchana Muniganti 			printf("Inner L4 checksum test failed\n");
73283243502SArchana Muniganti 
73383243502SArchana Muniganti 		return ret;
73483243502SArchana Muniganti 	}
73583243502SArchana Muniganti 
736c36d7c0dSVolodymyr Fialko 	skip = test_ipsec_tunnel_hdr_len_get(td);
737c36d7c0dSVolodymyr Fialko 
738c36d7c0dSVolodymyr Fialko 	len -= skip;
739c36d7c0dSVolodymyr Fialko 	output_text += skip;
740c36d7c0dSVolodymyr Fialko 
741e2cbb384SAnoob Joseph 	memcpy(td_output_text, td->output_text.data + skip, len);
74283243502SArchana Muniganti 
74342902e81SVolodymyr Fialko 	if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
74442902e81SVolodymyr Fialko 				flags->dec_ttl_or_hop_limit) {
74542902e81SVolodymyr Fialko 		if (test_ipsec_ttl_or_hop_decrement_verify(output_text, td_output_text)) {
74642902e81SVolodymyr Fialko 			printf("Inner TTL/hop limit decrement test failed\n");
74742902e81SVolodymyr Fialko 			return TEST_FAILED;
74842902e81SVolodymyr Fialko 		}
74942902e81SVolodymyr Fialko 	}
75042902e81SVolodymyr Fialko 
751e2cbb384SAnoob Joseph 	if (test_ipsec_pkt_update(td_output_text, flags)) {
752e2cbb384SAnoob Joseph 		printf("Could not update expected vector");
753e2cbb384SAnoob Joseph 		return TEST_FAILED;
754e2cbb384SAnoob Joseph 	}
755e2cbb384SAnoob Joseph 
756e2cbb384SAnoob Joseph 	if (memcmp(output_text, td_output_text, len)) {
757474f1202SAnoob Joseph 		if (silent)
758474f1202SAnoob Joseph 			return TEST_FAILED;
759474f1202SAnoob Joseph 
760474f1202SAnoob Joseph 		printf("TestCase %s line %d: %s\n", __func__, __LINE__,
761474f1202SAnoob Joseph 			"output text not as expected\n");
762474f1202SAnoob Joseph 
763e2cbb384SAnoob Joseph 		rte_hexdump(stdout, "expected", td_output_text, len);
764474f1202SAnoob Joseph 		rte_hexdump(stdout, "actual", output_text, len);
765474f1202SAnoob Joseph 		return TEST_FAILED;
766474f1202SAnoob Joseph 	}
767474f1202SAnoob Joseph 
7686622d9c9SAnoob Joseph 	return TEST_SUCCESS;
7696622d9c9SAnoob Joseph }
7706622d9c9SAnoob Joseph 
7716622d9c9SAnoob Joseph static int
772c36d7c0dSVolodymyr Fialko test_ipsec_res_d_prepare(const uint8_t *output_text, uint32_t len,
773c36d7c0dSVolodymyr Fialko 		const struct ipsec_test_data *td, struct ipsec_test_data *res_d)
7746622d9c9SAnoob Joseph {
7756622d9c9SAnoob Joseph 	memcpy(res_d, td, sizeof(*res_d));
7763edd1197SNithin Dabilpuram 
777c36d7c0dSVolodymyr Fialko 	memcpy(&res_d->input_text.data, output_text, len);
778c36d7c0dSVolodymyr Fialko 	res_d->input_text.len = len;
7796622d9c9SAnoob Joseph 
7806622d9c9SAnoob Joseph 	res_d->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
7816622d9c9SAnoob Joseph 	if (res_d->aead) {
7826622d9c9SAnoob Joseph 		res_d->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
7836622d9c9SAnoob Joseph 	} else {
7848d290523SAnoob Joseph 		res_d->xform.chain.cipher.cipher.op =
7858d290523SAnoob Joseph 				RTE_CRYPTO_CIPHER_OP_DECRYPT;
7868d290523SAnoob Joseph 		res_d->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
7876622d9c9SAnoob Joseph 	}
7886622d9c9SAnoob Joseph 
789474f1202SAnoob Joseph 	return TEST_SUCCESS;
790474f1202SAnoob Joseph }
791474f1202SAnoob Joseph 
79270c60cfdSAnoob Joseph static int
79370c60cfdSAnoob Joseph test_ipsec_iph4_hdr_validate(const struct rte_ipv4_hdr *iph4,
79470c60cfdSAnoob Joseph 			     const struct ipsec_test_flags *flags)
79570c60cfdSAnoob Joseph {
79670c60cfdSAnoob Joseph 	uint8_t tos, dscp;
79770c60cfdSAnoob Joseph 	uint16_t f_off;
79870c60cfdSAnoob Joseph 
79970c60cfdSAnoob Joseph 	if (!is_valid_ipv4_pkt(iph4)) {
80070c60cfdSAnoob Joseph 		printf("Tunnel outer header is not IPv4\n");
80170c60cfdSAnoob Joseph 		return -1;
80270c60cfdSAnoob Joseph 	}
80370c60cfdSAnoob Joseph 
804663d78beSArchana Muniganti 	if (flags->ah && iph4->next_proto_id != IPPROTO_AH) {
805663d78beSArchana Muniganti 		printf("Tunnel outer header proto is not AH\n");
806663d78beSArchana Muniganti 		return -1;
807663d78beSArchana Muniganti 	}
808663d78beSArchana Muniganti 
80970c60cfdSAnoob Joseph 	f_off = rte_be_to_cpu_16(iph4->fragment_offset);
81070c60cfdSAnoob Joseph 	if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 ||
81170c60cfdSAnoob Joseph 	    flags->df == TEST_IPSEC_SET_DF_1_INNER_0) {
81270c60cfdSAnoob Joseph 		if (!(f_off & RTE_IPV4_HDR_DF_FLAG)) {
81370c60cfdSAnoob Joseph 			printf("DF bit is not set\n");
81470c60cfdSAnoob Joseph 			return -1;
81570c60cfdSAnoob Joseph 		}
81670c60cfdSAnoob Joseph 	} else {
81770c60cfdSAnoob Joseph 		if (f_off & RTE_IPV4_HDR_DF_FLAG) {
81870c60cfdSAnoob Joseph 			printf("DF bit is set\n");
81970c60cfdSAnoob Joseph 			return -1;
82070c60cfdSAnoob Joseph 		}
82170c60cfdSAnoob Joseph 	}
82270c60cfdSAnoob Joseph 
82370c60cfdSAnoob Joseph 	tos = iph4->type_of_service;
82470c60cfdSAnoob Joseph 	dscp = (tos & RTE_IPV4_HDR_DSCP_MASK) >> 2;
82570c60cfdSAnoob Joseph 
82670c60cfdSAnoob Joseph 	if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
82770c60cfdSAnoob Joseph 	    flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0) {
82870c60cfdSAnoob Joseph 		if (dscp != TEST_IPSEC_DSCP_VAL) {
82970c60cfdSAnoob Joseph 			printf("DSCP value is not matching [exp: %x, actual: %x]\n",
83070c60cfdSAnoob Joseph 			       TEST_IPSEC_DSCP_VAL, dscp);
83170c60cfdSAnoob Joseph 			return -1;
83270c60cfdSAnoob Joseph 		}
83370c60cfdSAnoob Joseph 	} else {
83470c60cfdSAnoob Joseph 		if (dscp != 0) {
83570c60cfdSAnoob Joseph 			printf("DSCP value is set [exp: 0, actual: %x]\n",
83670c60cfdSAnoob Joseph 			       dscp);
83770c60cfdSAnoob Joseph 			return -1;
83870c60cfdSAnoob Joseph 		}
83970c60cfdSAnoob Joseph 	}
84070c60cfdSAnoob Joseph 
84170c60cfdSAnoob Joseph 	return 0;
84270c60cfdSAnoob Joseph }
84370c60cfdSAnoob Joseph 
84470c60cfdSAnoob Joseph static int
84570c60cfdSAnoob Joseph test_ipsec_iph6_hdr_validate(const struct rte_ipv6_hdr *iph6,
84670c60cfdSAnoob Joseph 			     const struct ipsec_test_flags *flags)
84770c60cfdSAnoob Joseph {
84870c60cfdSAnoob Joseph 	uint32_t vtc_flow;
84991d1d052SVamsi Attunuru 	uint32_t flabel;
85070c60cfdSAnoob Joseph 	uint8_t dscp;
85170c60cfdSAnoob Joseph 
85270c60cfdSAnoob Joseph 	if (!is_valid_ipv6_pkt(iph6)) {
85370c60cfdSAnoob Joseph 		printf("Tunnel outer header is not IPv6\n");
85470c60cfdSAnoob Joseph 		return -1;
85570c60cfdSAnoob Joseph 	}
85670c60cfdSAnoob Joseph 
85770c60cfdSAnoob Joseph 	vtc_flow = rte_be_to_cpu_32(iph6->vtc_flow);
85870c60cfdSAnoob Joseph 	dscp = (vtc_flow & RTE_IPV6_HDR_DSCP_MASK) >>
85970c60cfdSAnoob Joseph 	       (RTE_IPV6_HDR_TC_SHIFT + 2);
86070c60cfdSAnoob Joseph 
86170c60cfdSAnoob Joseph 	if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
86270c60cfdSAnoob Joseph 	    flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0) {
86370c60cfdSAnoob Joseph 		if (dscp != TEST_IPSEC_DSCP_VAL) {
86470c60cfdSAnoob Joseph 			printf("DSCP value is not matching [exp: %x, actual: %x]\n",
86570c60cfdSAnoob Joseph 			       TEST_IPSEC_DSCP_VAL, dscp);
86670c60cfdSAnoob Joseph 			return -1;
86770c60cfdSAnoob Joseph 		}
86870c60cfdSAnoob Joseph 	} else {
86970c60cfdSAnoob Joseph 		if (dscp != 0) {
87070c60cfdSAnoob Joseph 			printf("DSCP value is set [exp: 0, actual: %x]\n",
87170c60cfdSAnoob Joseph 			       dscp);
87270c60cfdSAnoob Joseph 			return -1;
87370c60cfdSAnoob Joseph 		}
87470c60cfdSAnoob Joseph 	}
87570c60cfdSAnoob Joseph 
87691d1d052SVamsi Attunuru 	flabel = vtc_flow & RTE_IPV6_HDR_FL_MASK;
87791d1d052SVamsi Attunuru 
87891d1d052SVamsi Attunuru 	if (flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1 ||
87991d1d052SVamsi Attunuru 	    flags->flabel == TEST_IPSEC_SET_FLABEL_1_INNER_0) {
88091d1d052SVamsi Attunuru 		if (flabel != TEST_IPSEC_FLABEL_VAL) {
88191d1d052SVamsi Attunuru 			printf("FLABEL value is not matching [exp: %x, actual: %x]\n",
88291d1d052SVamsi Attunuru 			       TEST_IPSEC_FLABEL_VAL, flabel);
88391d1d052SVamsi Attunuru 			return -1;
88491d1d052SVamsi Attunuru 		}
88591d1d052SVamsi Attunuru 	} else {
88691d1d052SVamsi Attunuru 		if (flabel != 0) {
88791d1d052SVamsi Attunuru 			printf("FLABEL value is set [exp: 0, actual: %x]\n",
88891d1d052SVamsi Attunuru 			       flabel);
88991d1d052SVamsi Attunuru 			return -1;
89091d1d052SVamsi Attunuru 		}
89191d1d052SVamsi Attunuru 	}
89291d1d052SVamsi Attunuru 
89370c60cfdSAnoob Joseph 	return 0;
89470c60cfdSAnoob Joseph }
89570c60cfdSAnoob Joseph 
896474f1202SAnoob Joseph int
897c36d7c0dSVolodymyr Fialko test_ipsec_post_process(const struct rte_mbuf *m, const struct ipsec_test_data *td,
8986622d9c9SAnoob Joseph 			struct ipsec_test_data *res_d, bool silent,
8996622d9c9SAnoob Joseph 			const struct ipsec_test_flags *flags)
900474f1202SAnoob Joseph {
901fcb03b8dSNithin Dabilpuram 	uint32_t len = rte_pktmbuf_pkt_len(m), data_len;
902c36d7c0dSVolodymyr Fialko 	uint8_t output_text[IPSEC_TEXT_MAX_LEN];
903fcb03b8dSNithin Dabilpuram 	const struct rte_mbuf *seg;
904c36d7c0dSVolodymyr Fialko 	const uint8_t *output;
905cd928003STejasree Kondoj 	int ret;
906cd928003STejasree Kondoj 
907fcb03b8dSNithin Dabilpuram 	memset(output_text, 0, IPSEC_TEXT_MAX_LEN);
908fcb03b8dSNithin Dabilpuram 	/* Actual data in packet might be less in error cases,
909fcb03b8dSNithin Dabilpuram 	 * hence take minimum of pkt_len and sum of data_len.
910fcb03b8dSNithin Dabilpuram 	 * This is done to run through negative test cases.
911fcb03b8dSNithin Dabilpuram 	 */
912fcb03b8dSNithin Dabilpuram 	data_len = 0;
913fcb03b8dSNithin Dabilpuram 	seg = m;
914fcb03b8dSNithin Dabilpuram 	while (seg) {
915fcb03b8dSNithin Dabilpuram 		data_len += seg->data_len;
916fcb03b8dSNithin Dabilpuram 		seg = seg->next;
917fcb03b8dSNithin Dabilpuram 	}
918fcb03b8dSNithin Dabilpuram 	len = RTE_MIN(len, data_len);
919*4677de0aSSrujana Challa 	TEST_ASSERT(len <= IPSEC_TEXT_MAX_LEN, "Invalid packet length: %u", len);
920c36d7c0dSVolodymyr Fialko 	/* Copy mbuf payload to continuous buffer */
921c36d7c0dSVolodymyr Fialko 	output = rte_pktmbuf_read(m, 0, len, output_text);
922c36d7c0dSVolodymyr Fialko 	if (output != output_text)
923c36d7c0dSVolodymyr Fialko 		/* Single segment mbuf, copy manually */
924c36d7c0dSVolodymyr Fialko 		memcpy(output_text, output, len);
925c36d7c0dSVolodymyr Fialko 
92665d68c7cSAnoob Joseph 	if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
92765d68c7cSAnoob Joseph 		const struct rte_ipv4_hdr *iph4;
92865d68c7cSAnoob Joseph 		const struct rte_ipv6_hdr *iph6;
92965d68c7cSAnoob Joseph 
93065d68c7cSAnoob Joseph 		if (flags->iv_gen) {
931c36d7c0dSVolodymyr Fialko 			ret = test_ipsec_iv_verify_push(output_text, td);
932cd928003STejasree Kondoj 			if (ret != TEST_SUCCESS)
933cd928003STejasree Kondoj 				return ret;
934cd928003STejasree Kondoj 		}
935cd928003STejasree Kondoj 
93665d68c7cSAnoob Joseph 		iph4 = (const struct rte_ipv4_hdr *)output_text;
9379fb87fbfSTejasree Kondoj 
93865d68c7cSAnoob Joseph 		if (td->ipsec_xform.mode ==
93965d68c7cSAnoob Joseph 				RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) {
94065d68c7cSAnoob Joseph 			if (flags->ipv6) {
94165d68c7cSAnoob Joseph 				iph6 = (const struct rte_ipv6_hdr *)output_text;
94265d68c7cSAnoob Joseph 				if (is_valid_ipv6_pkt(iph6) == false) {
94365d68c7cSAnoob Joseph 					printf("Transport packet is not IPv6\n");
94465d68c7cSAnoob Joseph 					return TEST_FAILED;
94565d68c7cSAnoob Joseph 				}
94665d68c7cSAnoob Joseph 			} else {
94765d68c7cSAnoob Joseph 				if (is_valid_ipv4_pkt(iph4) == false) {
94865d68c7cSAnoob Joseph 					printf("Transport packet is not IPv4\n");
94965d68c7cSAnoob Joseph 					return TEST_FAILED;
95065d68c7cSAnoob Joseph 				}
951663d78beSArchana Muniganti 
952663d78beSArchana Muniganti 				if (flags->ah && iph4->next_proto_id != IPPROTO_AH) {
953663d78beSArchana Muniganti 					printf("Transport IPv4 header proto is not AH\n");
954663d78beSArchana Muniganti 					return -1;
955663d78beSArchana Muniganti 				}
95665d68c7cSAnoob Joseph 			}
95765d68c7cSAnoob Joseph 		} else {
9589fb87fbfSTejasree Kondoj 			if (td->ipsec_xform.tunnel.type ==
9599fb87fbfSTejasree Kondoj 					RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
96070c60cfdSAnoob Joseph 				if (test_ipsec_iph4_hdr_validate(iph4, flags))
9619fb87fbfSTejasree Kondoj 					return TEST_FAILED;
9629fb87fbfSTejasree Kondoj 			} else {
9639fb87fbfSTejasree Kondoj 				iph6 = (const struct rte_ipv6_hdr *)output_text;
96470c60cfdSAnoob Joseph 				if (test_ipsec_iph6_hdr_validate(iph6, flags))
9659fb87fbfSTejasree Kondoj 					return TEST_FAILED;
9669fb87fbfSTejasree Kondoj 			}
9679fb87fbfSTejasree Kondoj 		}
9689fb87fbfSTejasree Kondoj 	}
9699fb87fbfSTejasree Kondoj 
970757bb461SVidya Sagar Velumuri 	if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
971757bb461SVidya Sagar Velumuri 	   flags->udp_encap) {
972757bb461SVidya Sagar Velumuri 		const struct rte_ipv4_hdr *iph4;
973757bb461SVidya Sagar Velumuri 		const struct rte_ipv6_hdr *iph6;
974757bb461SVidya Sagar Velumuri 
975757bb461SVidya Sagar Velumuri 		if (td->ipsec_xform.tunnel.type ==
976757bb461SVidya Sagar Velumuri 				RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
977757bb461SVidya Sagar Velumuri 			iph4 = (const struct rte_ipv4_hdr *)output_text;
978757bb461SVidya Sagar Velumuri 
979757bb461SVidya Sagar Velumuri 			if (iph4->next_proto_id != IPPROTO_UDP) {
980757bb461SVidya Sagar Velumuri 				printf("UDP header is not found\n");
981757bb461SVidya Sagar Velumuri 				return TEST_FAILED;
982757bb461SVidya Sagar Velumuri 			}
983757bb461SVidya Sagar Velumuri 
984757bb461SVidya Sagar Velumuri 			if (flags->udp_encap_custom_ports) {
985757bb461SVidya Sagar Velumuri 				const struct rte_udp_hdr *udph;
986757bb461SVidya Sagar Velumuri 
987757bb461SVidya Sagar Velumuri 				udph = (const struct rte_udp_hdr *)(output_text +
988757bb461SVidya Sagar Velumuri 					sizeof(struct rte_ipv4_hdr));
989757bb461SVidya Sagar Velumuri 				if ((rte_be_to_cpu_16(udph->src_port) != UDP_CUSTOM_SPORT) ||
990757bb461SVidya Sagar Velumuri 				    (rte_be_to_cpu_16(udph->dst_port) != UDP_CUSTOM_DPORT)) {
991757bb461SVidya Sagar Velumuri 					printf("UDP custom ports not matching.\n");
992757bb461SVidya Sagar Velumuri 					return TEST_FAILED;
993757bb461SVidya Sagar Velumuri 				}
994757bb461SVidya Sagar Velumuri 			}
995757bb461SVidya Sagar Velumuri 		} else {
996757bb461SVidya Sagar Velumuri 			iph6 = (const struct rte_ipv6_hdr *)output_text;
997757bb461SVidya Sagar Velumuri 
998757bb461SVidya Sagar Velumuri 			if (iph6->proto != IPPROTO_UDP) {
999757bb461SVidya Sagar Velumuri 				printf("UDP header is not found\n");
1000757bb461SVidya Sagar Velumuri 				return TEST_FAILED;
1001757bb461SVidya Sagar Velumuri 			}
1002757bb461SVidya Sagar Velumuri 
1003757bb461SVidya Sagar Velumuri 			if (flags->udp_encap_custom_ports) {
1004757bb461SVidya Sagar Velumuri 				const struct rte_udp_hdr *udph;
1005757bb461SVidya Sagar Velumuri 
1006757bb461SVidya Sagar Velumuri 				udph = (const struct rte_udp_hdr *)(output_text +
1007757bb461SVidya Sagar Velumuri 					sizeof(struct rte_ipv6_hdr));
1008757bb461SVidya Sagar Velumuri 				if ((rte_be_to_cpu_16(udph->src_port) != UDP_CUSTOM_SPORT) ||
1009757bb461SVidya Sagar Velumuri 				    (rte_be_to_cpu_16(udph->dst_port) != UDP_CUSTOM_DPORT)) {
1010757bb461SVidya Sagar Velumuri 					printf("UDP custom ports not matching.\n");
1011757bb461SVidya Sagar Velumuri 					return TEST_FAILED;
1012757bb461SVidya Sagar Velumuri 				}
1013757bb461SVidya Sagar Velumuri 			}
1014757bb461SVidya Sagar Velumuri 		}
1015757bb461SVidya Sagar Velumuri 	}
1016757bb461SVidya Sagar Velumuri 
1017474f1202SAnoob Joseph 	/*
1018474f1202SAnoob Joseph 	 * In case of known vector tests & all inbound tests, res_d provided
1019474f1202SAnoob Joseph 	 * would be NULL and output data need to be validated against expected.
1020474f1202SAnoob Joseph 	 * For inbound, output_text would be plain packet and for outbound
1021474f1202SAnoob Joseph 	 * output_text would IPsec packet. Validate by comparing against
1022474f1202SAnoob Joseph 	 * known vectors.
10236622d9c9SAnoob Joseph 	 *
10246622d9c9SAnoob Joseph 	 * In case of combined mode tests, the output_text from outbound
10256622d9c9SAnoob Joseph 	 * operation (ie, IPsec packet) would need to be inbound processed to
10266622d9c9SAnoob Joseph 	 * obtain the plain text. Copy output_text to result data, 'res_d', so
10276622d9c9SAnoob Joseph 	 * that inbound processing can be done.
1028474f1202SAnoob Joseph 	 */
10296622d9c9SAnoob Joseph 
10306622d9c9SAnoob Joseph 	if (res_d == NULL)
1031c36d7c0dSVolodymyr Fialko 		return test_ipsec_td_verify(output_text, len, m->ol_flags, td, silent, flags);
10326622d9c9SAnoob Joseph 	else
1033c36d7c0dSVolodymyr Fialko 		return test_ipsec_res_d_prepare(output_text, len, td, res_d);
1034474f1202SAnoob Joseph }
1035474f1202SAnoob Joseph 
1036474f1202SAnoob Joseph int
1037d02c6bfcSTejasree Kondoj test_ipsec_status_check(const struct ipsec_test_data *td,
1038d02c6bfcSTejasree Kondoj 			struct rte_crypto_op *op,
10396622d9c9SAnoob Joseph 			const struct ipsec_test_flags *flags,
10404aa52f21SAnoob Joseph 			enum rte_security_ipsec_sa_direction dir,
10414aa52f21SAnoob Joseph 			int pkt_num)
1042474f1202SAnoob Joseph {
1043474f1202SAnoob Joseph 	int ret = TEST_SUCCESS;
1044474f1202SAnoob Joseph 
1045d02c6bfcSTejasree Kondoj 	if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
1046d02c6bfcSTejasree Kondoj 	    td->ar_packet) {
1047d02c6bfcSTejasree Kondoj 		if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1048d02c6bfcSTejasree Kondoj 			printf("Anti replay test case failed\n");
1049d02c6bfcSTejasree Kondoj 			return TEST_FAILED;
1050d02c6bfcSTejasree Kondoj 		} else {
1051d02c6bfcSTejasree Kondoj 			return TEST_SUCCESS;
1052d02c6bfcSTejasree Kondoj 		}
1053d02c6bfcSTejasree Kondoj 	}
1054d02c6bfcSTejasree Kondoj 
10556978f51eSAnoob Joseph 	if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
10566978f51eSAnoob Joseph 	    flags->sa_expiry_pkts_hard &&
1057838e8decSVidya Sagar Velumuri 	    pkt_num == TEST_SEC_PKTS_MAX) {
10586978f51eSAnoob Joseph 		if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
10596978f51eSAnoob Joseph 			printf("SA hard expiry (pkts) test failed\n");
10606978f51eSAnoob Joseph 			return TEST_FAILED;
10616978f51eSAnoob Joseph 		} else {
10626978f51eSAnoob Joseph 			return TEST_SUCCESS;
10636978f51eSAnoob Joseph 		}
10646978f51eSAnoob Joseph 	}
10656978f51eSAnoob Joseph 
1066270470eeSTejasree Kondoj 	if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
1067270470eeSTejasree Kondoj 	    flags->tunnel_hdr_verify) {
1068270470eeSTejasree Kondoj 		if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1069270470eeSTejasree Kondoj 			printf("Tunnel header verify test case failed\n");
1070270470eeSTejasree Kondoj 			return TEST_FAILED;
1071270470eeSTejasree Kondoj 		} else {
1072270470eeSTejasree Kondoj 			return TEST_SUCCESS;
1073270470eeSTejasree Kondoj 		}
1074270470eeSTejasree Kondoj 	}
1075270470eeSTejasree Kondoj 
10760f453190STejasree Kondoj 	if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && flags->icv_corrupt) {
10770f453190STejasree Kondoj 		if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
10780f453190STejasree Kondoj 			printf("ICV corruption test case failed\n");
10790f453190STejasree Kondoj 			ret = TEST_FAILED;
10800f453190STejasree Kondoj 		}
10810f453190STejasree Kondoj 	} else {
1082474f1202SAnoob Joseph 		if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
10834aa52f21SAnoob Joseph 			printf("Security op processing failed [pkt_num: %d]\n",
10844aa52f21SAnoob Joseph 			       pkt_num);
10854aa52f21SAnoob Joseph 			ret = TEST_FAILED;
10864aa52f21SAnoob Joseph 		}
10874aa52f21SAnoob Joseph 	}
10884aa52f21SAnoob Joseph 
1089838e8decSVidya Sagar Velumuri 	if (flags->sa_expiry_pkts_soft && pkt_num == TEST_SEC_PKTS_MAX) {
10904aa52f21SAnoob Joseph 		if (!(op->aux_flags &
10914aa52f21SAnoob Joseph 		      RTE_CRYPTO_OP_AUX_FLAGS_IPSEC_SOFT_EXPIRY)) {
10924aa52f21SAnoob Joseph 			printf("SA soft expiry (pkts) test failed\n");
1093474f1202SAnoob Joseph 			ret = TEST_FAILED;
1094474f1202SAnoob Joseph 		}
10950f453190STejasree Kondoj 	}
1096474f1202SAnoob Joseph 
1097474f1202SAnoob Joseph 	return ret;
1098474f1202SAnoob Joseph }
10992c85598cSAnkur Dwivedi 
11002c85598cSAnkur Dwivedi int
110179bdb787SAkhil Goyal test_ipsec_stats_verify(void *ctx,
11022973dbf9SAkhil Goyal 			void *sess,
11032c85598cSAnkur Dwivedi 			const struct ipsec_test_flags *flags,
11042c85598cSAnkur Dwivedi 			enum rte_security_ipsec_sa_direction dir)
11052c85598cSAnkur Dwivedi {
11062c85598cSAnkur Dwivedi 	struct rte_security_stats stats = {0};
1107db65855aSAnoob Joseph 	int retries = 0, ret = TEST_SUCCESS;
11082c85598cSAnkur Dwivedi 
11092c85598cSAnkur Dwivedi 	if (flags->stats_success) {
1110db65855aSAnoob Joseph stats_get:
1111db65855aSAnoob Joseph 		ret = TEST_SUCCESS;
1112db65855aSAnoob Joseph 
11132c85598cSAnkur Dwivedi 		if (rte_security_session_stats_get(ctx, sess, &stats) < 0)
11142c85598cSAnkur Dwivedi 			return TEST_FAILED;
11152c85598cSAnkur Dwivedi 
11162c85598cSAnkur Dwivedi 		if (dir == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
11172c85598cSAnkur Dwivedi 			if (stats.ipsec.opackets != 1 ||
11182c85598cSAnkur Dwivedi 			    stats.ipsec.oerrors != 0)
11192c85598cSAnkur Dwivedi 				ret = TEST_FAILED;
11202c85598cSAnkur Dwivedi 		} else {
11212c85598cSAnkur Dwivedi 			if (stats.ipsec.ipackets != 1 ||
11222c85598cSAnkur Dwivedi 			    stats.ipsec.ierrors != 0)
11232c85598cSAnkur Dwivedi 				ret = TEST_FAILED;
11242c85598cSAnkur Dwivedi 		}
1125db65855aSAnoob Joseph 
1126db65855aSAnoob Joseph 		if (ret == TEST_FAILED && retries < TEST_STATS_RETRIES) {
1127db65855aSAnoob Joseph 			retries++;
1128db65855aSAnoob Joseph 			rte_delay_ms(1);
1129db65855aSAnoob Joseph 			goto stats_get;
1130db65855aSAnoob Joseph 		}
11312c85598cSAnkur Dwivedi 	}
11322c85598cSAnkur Dwivedi 
11332c85598cSAnkur Dwivedi 	return ret;
11342c85598cSAnkur Dwivedi }
1135e2cbb384SAnoob Joseph 
1136e2cbb384SAnoob Joseph int
1137e2cbb384SAnoob Joseph test_ipsec_pkt_update(uint8_t *pkt, const struct ipsec_test_flags *flags)
1138e2cbb384SAnoob Joseph {
1139e2cbb384SAnoob Joseph 	struct rte_ipv4_hdr *iph4;
114070c60cfdSAnoob Joseph 	struct rte_ipv6_hdr *iph6;
1141e2cbb384SAnoob Joseph 	bool cksum_dirty = false;
1142e2cbb384SAnoob Joseph 
1143e2cbb384SAnoob Joseph 	iph4 = (struct rte_ipv4_hdr *)pkt;
1144e2cbb384SAnoob Joseph 
1145e2cbb384SAnoob Joseph 	if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 ||
1146e2cbb384SAnoob Joseph 	    flags->df == TEST_IPSEC_SET_DF_0_INNER_1 ||
1147e2cbb384SAnoob Joseph 	    flags->df == TEST_IPSEC_COPY_DF_INNER_0 ||
1148e2cbb384SAnoob Joseph 	    flags->df == TEST_IPSEC_SET_DF_1_INNER_0) {
114970c60cfdSAnoob Joseph 		uint16_t frag_off;
1150e2cbb384SAnoob Joseph 
1151e2cbb384SAnoob Joseph 		if (!is_ipv4(iph4)) {
115270c60cfdSAnoob Joseph 			printf("Invalid packet type\n");
1153e2cbb384SAnoob Joseph 			return -1;
1154e2cbb384SAnoob Joseph 		}
1155e2cbb384SAnoob Joseph 
1156e2cbb384SAnoob Joseph 		frag_off = rte_be_to_cpu_16(iph4->fragment_offset);
1157e2cbb384SAnoob Joseph 
1158e2cbb384SAnoob Joseph 		if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 ||
1159e2cbb384SAnoob Joseph 		    flags->df == TEST_IPSEC_SET_DF_0_INNER_1)
1160e2cbb384SAnoob Joseph 			frag_off |= RTE_IPV4_HDR_DF_FLAG;
1161e2cbb384SAnoob Joseph 		else
1162e2cbb384SAnoob Joseph 			frag_off &= ~RTE_IPV4_HDR_DF_FLAG;
1163e2cbb384SAnoob Joseph 
1164e2cbb384SAnoob Joseph 		iph4->fragment_offset = rte_cpu_to_be_16(frag_off);
1165e2cbb384SAnoob Joseph 		cksum_dirty = true;
1166e2cbb384SAnoob Joseph 	}
1167e2cbb384SAnoob Joseph 
116870c60cfdSAnoob Joseph 	if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
116970c60cfdSAnoob Joseph 	    flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1 ||
117070c60cfdSAnoob Joseph 	    flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_0 ||
117191d1d052SVamsi Attunuru 	    flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0 ||
117291d1d052SVamsi Attunuru 	    flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1 ||
117391d1d052SVamsi Attunuru 	    flags->flabel == TEST_IPSEC_SET_FLABEL_0_INNER_1 ||
117491d1d052SVamsi Attunuru 	    flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_0 ||
117591d1d052SVamsi Attunuru 	    flags->flabel == TEST_IPSEC_SET_FLABEL_1_INNER_0) {
117670c60cfdSAnoob Joseph 
117770c60cfdSAnoob Joseph 		if (is_ipv4(iph4)) {
117870c60cfdSAnoob Joseph 			uint8_t tos;
117970c60cfdSAnoob Joseph 
118070c60cfdSAnoob Joseph 			tos = iph4->type_of_service;
118170c60cfdSAnoob Joseph 			if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
118270c60cfdSAnoob Joseph 			    flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1)
118370c60cfdSAnoob Joseph 				tos |= (RTE_IPV4_HDR_DSCP_MASK &
118470c60cfdSAnoob Joseph 					(TEST_IPSEC_DSCP_VAL << 2));
118570c60cfdSAnoob Joseph 			else
118670c60cfdSAnoob Joseph 				tos &= ~RTE_IPV4_HDR_DSCP_MASK;
118770c60cfdSAnoob Joseph 
118870c60cfdSAnoob Joseph 			iph4->type_of_service = tos;
118970c60cfdSAnoob Joseph 			cksum_dirty = true;
119070c60cfdSAnoob Joseph 		} else {
119170c60cfdSAnoob Joseph 			uint32_t vtc_flow;
119270c60cfdSAnoob Joseph 
119370c60cfdSAnoob Joseph 			iph6 = (struct rte_ipv6_hdr *)pkt;
119470c60cfdSAnoob Joseph 
119570c60cfdSAnoob Joseph 			vtc_flow = rte_be_to_cpu_32(iph6->vtc_flow);
119670c60cfdSAnoob Joseph 			if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
119770c60cfdSAnoob Joseph 			    flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1)
119870c60cfdSAnoob Joseph 				vtc_flow |= (RTE_IPV6_HDR_DSCP_MASK &
119970c60cfdSAnoob Joseph 					     (TEST_IPSEC_DSCP_VAL << (RTE_IPV6_HDR_TC_SHIFT + 2)));
120070c60cfdSAnoob Joseph 			else
120170c60cfdSAnoob Joseph 				vtc_flow &= ~RTE_IPV6_HDR_DSCP_MASK;
120270c60cfdSAnoob Joseph 
120391d1d052SVamsi Attunuru 			if (flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1 ||
120491d1d052SVamsi Attunuru 			    flags->flabel == TEST_IPSEC_SET_FLABEL_0_INNER_1)
120591d1d052SVamsi Attunuru 				vtc_flow |= (RTE_IPV6_HDR_FL_MASK &
120691d1d052SVamsi Attunuru 					     (TEST_IPSEC_FLABEL_VAL << RTE_IPV6_HDR_FL_SHIFT));
120791d1d052SVamsi Attunuru 			else
120891d1d052SVamsi Attunuru 				vtc_flow &= ~RTE_IPV6_HDR_FL_MASK;
120991d1d052SVamsi Attunuru 
121070c60cfdSAnoob Joseph 			iph6->vtc_flow = rte_cpu_to_be_32(vtc_flow);
121170c60cfdSAnoob Joseph 		}
121270c60cfdSAnoob Joseph 	}
121370c60cfdSAnoob Joseph 
1214e2cbb384SAnoob Joseph 	if (cksum_dirty && is_ipv4(iph4)) {
1215e2cbb384SAnoob Joseph 		iph4->hdr_checksum = 0;
1216e2cbb384SAnoob Joseph 		iph4->hdr_checksum = rte_ipv4_cksum(iph4);
1217e2cbb384SAnoob Joseph 	}
1218e2cbb384SAnoob Joseph 
1219e2cbb384SAnoob Joseph 	return 0;
1220e2cbb384SAnoob Joseph }
1221