xref: /dpdk/app/test/test_cryptodev_security_ipsec.c (revision 8f1d23ece06adff5eae9f1b4365bdbbd3abee2b2)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 
5 #include <rte_common.h>
6 #include <rte_cryptodev.h>
7 #include <rte_esp.h>
8 #include <rte_ip.h>
9 #include <rte_security.h>
10 #include <rte_tcp.h>
11 #include <rte_udp.h>
12 
13 #include "test.h"
14 #include "test_cryptodev_security_ipsec.h"
15 
16 #define IV_LEN_MAX 16
17 
18 #ifndef IPVERSION
19 #define IPVERSION 4
20 #endif
21 
22 struct crypto_param_comb alg_list[RTE_DIM(aead_list) +
23 				  (RTE_DIM(cipher_list) *
24 				   RTE_DIM(auth_list))];
25 
26 struct crypto_param_comb ah_alg_list[2 * (RTE_DIM(auth_list) - 1)];
27 
28 static bool
29 is_valid_ipv4_pkt(const struct rte_ipv4_hdr *pkt)
30 {
31 	/* The IP version number must be 4 */
32 	if (((pkt->version_ihl) >> 4) != 4)
33 		return false;
34 	/*
35 	 * The IP header length field must be large enough to hold the
36 	 * minimum length legal IP datagram (20 bytes = 5 words).
37 	 */
38 	if ((pkt->version_ihl & 0xf) < 5)
39 		return false;
40 
41 	/*
42 	 * The IP total length field must be large enough to hold the IP
43 	 * datagram header, whose length is specified in the IP header length
44 	 * field.
45 	 */
46 	if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct rte_ipv4_hdr))
47 		return false;
48 
49 	return true;
50 }
51 
52 static bool
53 is_valid_ipv6_pkt(const struct rte_ipv6_hdr *pkt)
54 {
55 	/* The IP version number must be 6 */
56 	if ((rte_be_to_cpu_32((pkt->vtc_flow)) >> 28) != 6)
57 		return false;
58 
59 	return true;
60 }
61 
62 void
63 test_ipsec_alg_list_populate(void)
64 {
65 	unsigned long i, j, index = 0;
66 
67 	for (i = 0; i < RTE_DIM(aead_list); i++) {
68 		alg_list[index].param1 = &aead_list[i];
69 		alg_list[index].param2 = NULL;
70 		index++;
71 	}
72 
73 	for (i = 0; i < RTE_DIM(cipher_list); i++) {
74 		for (j = 0; j < RTE_DIM(auth_list); j++) {
75 			alg_list[index].param1 = &cipher_list[i];
76 			alg_list[index].param2 = &auth_list[j];
77 			index++;
78 		}
79 	}
80 }
81 
82 void
83 test_ipsec_ah_alg_list_populate(void)
84 {
85 	unsigned long i, index = 0;
86 
87 	for (i = 1; i < RTE_DIM(auth_list); i++) {
88 		ah_alg_list[index].param1 = &auth_list[i];
89 		ah_alg_list[index].param2 = NULL;
90 		index++;
91 	}
92 
93 	for (i = 1; i < RTE_DIM(auth_list); i++) {
94 		/* NULL cipher */
95 		ah_alg_list[index].param1 = &cipher_list[0];
96 
97 		ah_alg_list[index].param2 = &auth_list[i];
98 		index++;
99 	}
100 }
101 
102 int
103 test_ipsec_sec_caps_verify(struct rte_security_ipsec_xform *ipsec_xform,
104 			   const struct rte_security_capability *sec_cap,
105 			   bool silent)
106 {
107 	/* Verify security capabilities */
108 
109 	if (ipsec_xform->options.esn == 1 && sec_cap->ipsec.options.esn == 0) {
110 		if (!silent)
111 			RTE_LOG(INFO, USER1, "ESN is not supported\n");
112 		return -ENOTSUP;
113 	}
114 
115 	if (ipsec_xform->options.udp_encap == 1 &&
116 	    sec_cap->ipsec.options.udp_encap == 0) {
117 		if (!silent)
118 			RTE_LOG(INFO, USER1, "UDP encapsulation is not supported\n");
119 		return -ENOTSUP;
120 	}
121 
122 	if (ipsec_xform->options.udp_ports_verify == 1 &&
123 	    sec_cap->ipsec.options.udp_ports_verify == 0) {
124 		if (!silent)
125 			RTE_LOG(INFO, USER1, "UDP encapsulation ports "
126 				"verification is not supported\n");
127 		return -ENOTSUP;
128 	}
129 
130 	if (ipsec_xform->options.copy_dscp == 1 &&
131 	    sec_cap->ipsec.options.copy_dscp == 0) {
132 		if (!silent)
133 			RTE_LOG(INFO, USER1, "Copy DSCP is not supported\n");
134 		return -ENOTSUP;
135 	}
136 
137 	if (ipsec_xform->options.copy_flabel == 1 &&
138 	    sec_cap->ipsec.options.copy_flabel == 0) {
139 		if (!silent)
140 			RTE_LOG(INFO, USER1, "Copy Flow Label is not supported\n");
141 		return -ENOTSUP;
142 	}
143 
144 	if (ipsec_xform->options.copy_df == 1 &&
145 	    sec_cap->ipsec.options.copy_df == 0) {
146 		if (!silent)
147 			RTE_LOG(INFO, USER1, "Copy DP bit is not supported\n");
148 		return -ENOTSUP;
149 	}
150 
151 	if (ipsec_xform->options.dec_ttl == 1 &&
152 	    sec_cap->ipsec.options.dec_ttl == 0) {
153 		if (!silent)
154 			RTE_LOG(INFO, USER1, "Decrement TTL is not supported\n");
155 		return -ENOTSUP;
156 	}
157 
158 	if (ipsec_xform->options.ecn == 1 && sec_cap->ipsec.options.ecn == 0) {
159 		if (!silent)
160 			RTE_LOG(INFO, USER1, "ECN is not supported\n");
161 		return -ENOTSUP;
162 	}
163 
164 	if (ipsec_xform->options.stats == 1 &&
165 	    sec_cap->ipsec.options.stats == 0) {
166 		if (!silent)
167 			RTE_LOG(INFO, USER1, "Stats is not supported\n");
168 		return -ENOTSUP;
169 	}
170 
171 	if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) &&
172 	    (ipsec_xform->options.iv_gen_disable == 1) &&
173 	    (sec_cap->ipsec.options.iv_gen_disable != 1)) {
174 		if (!silent)
175 			RTE_LOG(INFO, USER1,
176 				"Application provided IV is not supported\n");
177 		return -ENOTSUP;
178 	}
179 
180 	if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
181 	    (ipsec_xform->options.tunnel_hdr_verify >
182 	    sec_cap->ipsec.options.tunnel_hdr_verify)) {
183 		if (!silent)
184 			RTE_LOG(INFO, USER1,
185 				"Tunnel header verify is not supported\n");
186 		return -ENOTSUP;
187 	}
188 
189 	if (ipsec_xform->options.ip_csum_enable == 1 &&
190 	    sec_cap->ipsec.options.ip_csum_enable == 0) {
191 		if (!silent)
192 			RTE_LOG(INFO, USER1,
193 				"Inner IP checksum is not supported\n");
194 		return -ENOTSUP;
195 	}
196 
197 	if (ipsec_xform->options.l4_csum_enable == 1 &&
198 	    sec_cap->ipsec.options.l4_csum_enable == 0) {
199 		if (!silent)
200 			RTE_LOG(INFO, USER1,
201 				"Inner L4 checksum is not supported\n");
202 		return -ENOTSUP;
203 	}
204 
205 	if (ipsec_xform->replay_win_sz > sec_cap->ipsec.replay_win_sz_max) {
206 		if (!silent)
207 			RTE_LOG(INFO, USER1,
208 				"Replay window size is not supported\n");
209 		return -ENOTSUP;
210 	}
211 
212 	return 0;
213 }
214 
215 int
216 test_ipsec_crypto_caps_aead_verify(
217 		const struct rte_security_capability *sec_cap,
218 		struct rte_crypto_sym_xform *aead)
219 {
220 	const struct rte_cryptodev_symmetric_capability *sym_cap;
221 	const struct rte_cryptodev_capabilities *crypto_cap;
222 	int j = 0;
223 
224 	while ((crypto_cap = &sec_cap->crypto_capabilities[j++])->op !=
225 			RTE_CRYPTO_OP_TYPE_UNDEFINED) {
226 		if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
227 				crypto_cap->sym.xform_type == aead->type &&
228 				crypto_cap->sym.aead.algo == aead->aead.algo) {
229 			sym_cap = &crypto_cap->sym;
230 			if (rte_cryptodev_sym_capability_check_aead(sym_cap,
231 					aead->aead.key.length,
232 					aead->aead.digest_length,
233 					aead->aead.aad_length,
234 					aead->aead.iv.length) == 0)
235 				return 0;
236 		}
237 	}
238 
239 	return -ENOTSUP;
240 }
241 
242 int
243 test_ipsec_crypto_caps_cipher_verify(
244 		const struct rte_security_capability *sec_cap,
245 		struct rte_crypto_sym_xform *cipher)
246 {
247 	const struct rte_cryptodev_symmetric_capability *sym_cap;
248 	const struct rte_cryptodev_capabilities *cap;
249 	int j = 0;
250 
251 	while ((cap = &sec_cap->crypto_capabilities[j++])->op !=
252 			RTE_CRYPTO_OP_TYPE_UNDEFINED) {
253 		if (cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
254 				cap->sym.xform_type == cipher->type &&
255 				cap->sym.cipher.algo == cipher->cipher.algo) {
256 			sym_cap = &cap->sym;
257 			if (rte_cryptodev_sym_capability_check_cipher(sym_cap,
258 					cipher->cipher.key.length,
259 					cipher->cipher.iv.length) == 0)
260 				return 0;
261 		}
262 	}
263 
264 	return -ENOTSUP;
265 }
266 
267 int
268 test_ipsec_crypto_caps_auth_verify(
269 		const struct rte_security_capability *sec_cap,
270 		struct rte_crypto_sym_xform *auth)
271 {
272 	const struct rte_cryptodev_symmetric_capability *sym_cap;
273 	const struct rte_cryptodev_capabilities *cap;
274 	int j = 0;
275 
276 	while ((cap = &sec_cap->crypto_capabilities[j++])->op !=
277 			RTE_CRYPTO_OP_TYPE_UNDEFINED) {
278 		if (cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
279 				cap->sym.xform_type == auth->type &&
280 				cap->sym.auth.algo == auth->auth.algo) {
281 			sym_cap = &cap->sym;
282 			if (rte_cryptodev_sym_capability_check_auth(sym_cap,
283 					auth->auth.key.length,
284 					auth->auth.digest_length,
285 					auth->auth.iv.length) == 0)
286 				return 0;
287 		}
288 	}
289 
290 	return -ENOTSUP;
291 }
292 
293 void
294 test_ipsec_td_in_from_out(const struct ipsec_test_data *td_out,
295 			  struct ipsec_test_data *td_in)
296 {
297 	memcpy(td_in, td_out, sizeof(*td_in));
298 
299 	/* Populate output text of td_in with input text of td_out */
300 	memcpy(td_in->output_text.data, td_out->input_text.data,
301 	       td_out->input_text.len);
302 	td_in->output_text.len = td_out->input_text.len;
303 
304 	/* Populate input text of td_in with output text of td_out */
305 	memcpy(td_in->input_text.data, td_out->output_text.data,
306 	       td_out->output_text.len);
307 	td_in->input_text.len = td_out->output_text.len;
308 
309 	td_in->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
310 
311 	if (td_in->aead) {
312 		td_in->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
313 	} else {
314 		td_in->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
315 		td_in->xform.chain.cipher.cipher.op =
316 				RTE_CRYPTO_CIPHER_OP_DECRYPT;
317 	}
318 }
319 
320 static bool
321 is_ipv4(void *ip)
322 {
323 	struct rte_ipv4_hdr *ipv4 = ip;
324 	uint8_t ip_ver;
325 
326 	ip_ver = (ipv4->version_ihl & 0xf0) >> RTE_IPV4_IHL_MULTIPLIER;
327 	if (ip_ver == IPVERSION)
328 		return true;
329 	else
330 		return false;
331 }
332 
333 static void
334 test_ipsec_csum_init(void *ip, bool l3, bool l4)
335 {
336 	struct rte_ipv4_hdr *ipv4;
337 	struct rte_tcp_hdr *tcp;
338 	struct rte_udp_hdr *udp;
339 	uint8_t next_proto;
340 	uint8_t size;
341 
342 	if (is_ipv4(ip)) {
343 		ipv4 = ip;
344 		size = sizeof(struct rte_ipv4_hdr);
345 		next_proto = ipv4->next_proto_id;
346 
347 		if (l3)
348 			ipv4->hdr_checksum = 0;
349 	} else {
350 		size = sizeof(struct rte_ipv6_hdr);
351 		next_proto = ((struct rte_ipv6_hdr *)ip)->proto;
352 	}
353 
354 	if (l4) {
355 		switch (next_proto) {
356 		case IPPROTO_TCP:
357 			tcp = (struct rte_tcp_hdr *)RTE_PTR_ADD(ip, size);
358 			tcp->cksum = 0;
359 			break;
360 		case IPPROTO_UDP:
361 			udp = (struct rte_udp_hdr *)RTE_PTR_ADD(ip, size);
362 			udp->dgram_cksum = 0;
363 			break;
364 		default:
365 			return;
366 		}
367 	}
368 }
369 
370 void
371 test_ipsec_td_prepare(const struct crypto_param *param1,
372 		      const struct crypto_param *param2,
373 		      const struct ipsec_test_flags *flags,
374 		      struct ipsec_test_data *td_array,
375 		      int nb_td)
376 
377 {
378 	struct ipsec_test_data *td;
379 	int i;
380 
381 	memset(td_array, 0, nb_td * sizeof(*td));
382 
383 	for (i = 0; i < nb_td; i++) {
384 		td = &td_array[i];
385 
386 		/* Prepare fields based on param */
387 
388 		if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
389 			/* Copy template for packet & key fields */
390 			if (flags->ipv6)
391 				memcpy(td, &pkt_aes_256_gcm_v6, sizeof(*td));
392 			else
393 				memcpy(td, &pkt_aes_256_gcm, sizeof(*td));
394 
395 			td->aead = true;
396 			td->xform.aead.aead.algo = param1->alg.aead;
397 			td->xform.aead.aead.key.length = param1->key_length;
398 		} else {
399 			/* Copy template for packet & key fields */
400 			if (flags->ipv6)
401 				memcpy(td, &pkt_aes_128_cbc_hmac_sha256_v6,
402 					sizeof(*td));
403 			else
404 				memcpy(td, &pkt_aes_128_cbc_hmac_sha256,
405 					sizeof(*td));
406 
407 			td->aead = false;
408 
409 			if (param1->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
410 				td->xform.chain.auth.auth.algo =
411 						param1->alg.auth;
412 				td->xform.chain.auth.auth.key.length =
413 						param1->key_length;
414 				td->xform.chain.auth.auth.digest_length =
415 						param1->digest_length;
416 				td->auth_only = true;
417 
418 				if (td->xform.chain.auth.auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
419 					td->xform.chain.auth.auth.iv.length =
420 						param1->iv_length;
421 					td->aes_gmac = true;
422 				}
423 			} else {
424 				td->xform.chain.cipher.cipher.algo =
425 						param1->alg.cipher;
426 				td->xform.chain.cipher.cipher.key.length =
427 						param1->key_length;
428 				td->xform.chain.cipher.cipher.iv.length =
429 						param1->iv_length;
430 				td->xform.chain.auth.auth.algo =
431 						param2->alg.auth;
432 				td->xform.chain.auth.auth.key.length =
433 						param2->key_length;
434 				td->xform.chain.auth.auth.digest_length =
435 						param2->digest_length;
436 
437 				if (td->xform.chain.auth.auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
438 					td->xform.chain.auth.auth.iv.length =
439 						param2->iv_length;
440 					td->aes_gmac = true;
441 				}
442 			}
443 		}
444 
445 		if (flags->ah) {
446 			td->ipsec_xform.proto =
447 					RTE_SECURITY_IPSEC_SA_PROTO_AH;
448 		}
449 
450 		if (flags->iv_gen)
451 			td->ipsec_xform.options.iv_gen_disable = 0;
452 
453 		if (flags->sa_expiry_pkts_soft)
454 			td->ipsec_xform.life.packets_soft_limit =
455 					IPSEC_TEST_PACKETS_MAX - 1;
456 
457 		if (flags->ip_csum) {
458 			td->ipsec_xform.options.ip_csum_enable = 1;
459 			test_ipsec_csum_init(&td->input_text.data, true, false);
460 		}
461 
462 		if (flags->l4_csum) {
463 			td->ipsec_xform.options.l4_csum_enable = 1;
464 			test_ipsec_csum_init(&td->input_text.data, false, true);
465 		}
466 
467 		if (flags->transport) {
468 			td->ipsec_xform.mode =
469 					RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT;
470 		} else {
471 			td->ipsec_xform.mode =
472 					RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
473 
474 			if (flags->tunnel_ipv6)
475 				td->ipsec_xform.tunnel.type =
476 						RTE_SECURITY_IPSEC_TUNNEL_IPV6;
477 			else
478 				td->ipsec_xform.tunnel.type =
479 						RTE_SECURITY_IPSEC_TUNNEL_IPV4;
480 		}
481 
482 		if (flags->stats_success)
483 			td->ipsec_xform.options.stats = 1;
484 
485 		if (flags->fragment) {
486 			struct rte_ipv4_hdr *ip;
487 			ip = (struct rte_ipv4_hdr *)&td->input_text.data;
488 			ip->fragment_offset = 4;
489 			ip->hdr_checksum = rte_ipv4_cksum(ip);
490 		}
491 
492 		if (flags->df == TEST_IPSEC_COPY_DF_INNER_0 ||
493 		    flags->df == TEST_IPSEC_COPY_DF_INNER_1)
494 			td->ipsec_xform.options.copy_df = 1;
495 
496 		if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_0 ||
497 		    flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1)
498 			td->ipsec_xform.options.copy_dscp = 1;
499 
500 		if (flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_0 ||
501 		    flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1)
502 			td->ipsec_xform.options.copy_flabel = 1;
503 
504 		if (flags->dec_ttl_or_hop_limit)
505 			td->ipsec_xform.options.dec_ttl = 1;
506 	}
507 }
508 
509 void
510 test_ipsec_td_update(struct ipsec_test_data td_inb[],
511 		     const struct ipsec_test_data td_outb[],
512 		     int nb_td,
513 		     const struct ipsec_test_flags *flags)
514 {
515 	int i;
516 
517 	for (i = 0; i < nb_td; i++) {
518 		memcpy(td_inb[i].output_text.data, td_outb[i].input_text.data,
519 		       td_outb[i].input_text.len);
520 		td_inb[i].output_text.len = td_outb->input_text.len;
521 
522 		if (flags->icv_corrupt) {
523 			int icv_pos = td_inb[i].input_text.len - 4;
524 			td_inb[i].input_text.data[icv_pos] += 1;
525 		}
526 
527 		if (flags->sa_expiry_pkts_hard)
528 			td_inb[i].ipsec_xform.life.packets_hard_limit =
529 					IPSEC_TEST_PACKETS_MAX - 1;
530 
531 		if (flags->udp_encap)
532 			td_inb[i].ipsec_xform.options.udp_encap = 1;
533 
534 		if (flags->udp_ports_verify)
535 			td_inb[i].ipsec_xform.options.udp_ports_verify = 1;
536 
537 		td_inb[i].ipsec_xform.options.tunnel_hdr_verify =
538 			flags->tunnel_hdr_verify;
539 
540 		if (flags->ip_csum)
541 			td_inb[i].ipsec_xform.options.ip_csum_enable = 1;
542 
543 		if (flags->l4_csum)
544 			td_inb[i].ipsec_xform.options.l4_csum_enable = 1;
545 
546 		/* Clear outbound specific flags */
547 		td_inb[i].ipsec_xform.options.iv_gen_disable = 0;
548 	}
549 }
550 
551 void
552 test_ipsec_display_alg(const struct crypto_param *param1,
553 		       const struct crypto_param *param2)
554 {
555 	if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
556 		printf("\t%s [%d]",
557 		       rte_crypto_aead_algorithm_strings[param1->alg.aead],
558 		       param1->key_length * 8);
559 	} else if (param1->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
560 		printf("\t%s",
561 		       rte_crypto_auth_algorithm_strings[param1->alg.auth]);
562 		if (param1->alg.auth != RTE_CRYPTO_AUTH_NULL)
563 			printf(" [%dB ICV]", param1->digest_length);
564 	} else {
565 		printf("\t%s",
566 		       rte_crypto_cipher_algorithm_strings[param1->alg.cipher]);
567 		if (param1->alg.cipher != RTE_CRYPTO_CIPHER_NULL)
568 			printf(" [%d]", param1->key_length * 8);
569 		printf(" %s",
570 		       rte_crypto_auth_algorithm_strings[param2->alg.auth]);
571 		if (param2->alg.auth != RTE_CRYPTO_AUTH_NULL)
572 			printf(" [%dB ICV]", param2->digest_length);
573 	}
574 	printf("\n");
575 }
576 
577 static int
578 test_ipsec_tunnel_hdr_len_get(const struct ipsec_test_data *td)
579 {
580 	int len = 0;
581 
582 	if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
583 		if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
584 			if (td->ipsec_xform.tunnel.type ==
585 					RTE_SECURITY_IPSEC_TUNNEL_IPV4)
586 				len += sizeof(struct rte_ipv4_hdr);
587 			else
588 				len += sizeof(struct rte_ipv6_hdr);
589 		}
590 	}
591 
592 	return len;
593 }
594 
595 static int
596 test_ipsec_iv_verify_push(struct rte_mbuf *m, const struct ipsec_test_data *td)
597 {
598 	static uint8_t iv_queue[IV_LEN_MAX * IPSEC_TEST_PACKETS_MAX];
599 	uint8_t *iv_tmp, *output_text = rte_pktmbuf_mtod(m, uint8_t *);
600 	int i, iv_pos, iv_len;
601 	static int index;
602 
603 	if (td->aead)
604 		iv_len = td->xform.aead.aead.iv.length - td->salt.len;
605 	else
606 		iv_len = td->xform.chain.cipher.cipher.iv.length;
607 
608 	iv_pos = test_ipsec_tunnel_hdr_len_get(td) + sizeof(struct rte_esp_hdr);
609 	output_text += iv_pos;
610 
611 	TEST_ASSERT(iv_len <= IV_LEN_MAX, "IV length greater than supported");
612 
613 	/* Compare against previous values */
614 	for (i = 0; i < index; i++) {
615 		iv_tmp = &iv_queue[i * IV_LEN_MAX];
616 
617 		if (memcmp(output_text, iv_tmp, iv_len) == 0) {
618 			printf("IV repeated");
619 			return TEST_FAILED;
620 		}
621 	}
622 
623 	/* Save IV for future comparisons */
624 
625 	iv_tmp = &iv_queue[index * IV_LEN_MAX];
626 	memcpy(iv_tmp, output_text, iv_len);
627 	index++;
628 
629 	if (index == IPSEC_TEST_PACKETS_MAX)
630 		index = 0;
631 
632 	return TEST_SUCCESS;
633 }
634 
635 static int
636 test_ipsec_l3_csum_verify(struct rte_mbuf *m)
637 {
638 	uint16_t actual_cksum, expected_cksum;
639 	struct rte_ipv4_hdr *ip;
640 
641 	ip = rte_pktmbuf_mtod(m, struct rte_ipv4_hdr *);
642 
643 	if (!is_ipv4((void *)ip))
644 		return TEST_SKIPPED;
645 
646 	actual_cksum = ip->hdr_checksum;
647 
648 	ip->hdr_checksum = 0;
649 
650 	expected_cksum = rte_ipv4_cksum(ip);
651 
652 	if (actual_cksum != expected_cksum)
653 		return TEST_FAILED;
654 
655 	return TEST_SUCCESS;
656 }
657 
658 static int
659 test_ipsec_l4_csum_verify(struct rte_mbuf *m)
660 {
661 	uint16_t actual_cksum = 0, expected_cksum = 0;
662 	struct rte_ipv4_hdr *ipv4;
663 	struct rte_ipv6_hdr *ipv6;
664 	struct rte_tcp_hdr *tcp;
665 	struct rte_udp_hdr *udp;
666 	void *ip, *l4;
667 
668 	ip = rte_pktmbuf_mtod(m, void *);
669 
670 	if (is_ipv4(ip)) {
671 		ipv4 = ip;
672 		l4 = RTE_PTR_ADD(ipv4, sizeof(struct rte_ipv4_hdr));
673 
674 		switch (ipv4->next_proto_id) {
675 		case IPPROTO_TCP:
676 			tcp = (struct rte_tcp_hdr *)l4;
677 			actual_cksum = tcp->cksum;
678 			tcp->cksum = 0;
679 			expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4);
680 			break;
681 		case IPPROTO_UDP:
682 			udp = (struct rte_udp_hdr *)l4;
683 			actual_cksum = udp->dgram_cksum;
684 			udp->dgram_cksum = 0;
685 			expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4);
686 			break;
687 		default:
688 			break;
689 		}
690 	} else {
691 		ipv6 = ip;
692 		l4 = RTE_PTR_ADD(ipv6, sizeof(struct rte_ipv6_hdr));
693 
694 		switch (ipv6->proto) {
695 		case IPPROTO_TCP:
696 			tcp = (struct rte_tcp_hdr *)l4;
697 			actual_cksum = tcp->cksum;
698 			tcp->cksum = 0;
699 			expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4);
700 			break;
701 		case IPPROTO_UDP:
702 			udp = (struct rte_udp_hdr *)l4;
703 			actual_cksum = udp->dgram_cksum;
704 			udp->dgram_cksum = 0;
705 			expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4);
706 			break;
707 		default:
708 			break;
709 		}
710 	}
711 
712 	if (actual_cksum != expected_cksum)
713 		return TEST_FAILED;
714 
715 	return TEST_SUCCESS;
716 }
717 
718 static int
719 test_ipsec_ttl_or_hop_decrement_verify(void *received, void *expected)
720 {
721 	struct rte_ipv4_hdr *iph4_ex, *iph4_re;
722 	struct rte_ipv6_hdr *iph6_ex, *iph6_re;
723 
724 	if (is_ipv4(received) && is_ipv4(expected)) {
725 		iph4_ex = expected;
726 		iph4_re = received;
727 		iph4_ex->time_to_live -= 1;
728 		if (iph4_re->time_to_live != iph4_ex->time_to_live)
729 			return TEST_FAILED;
730 	} else if (!is_ipv4(received) && !is_ipv4(expected)) {
731 		iph6_ex = expected;
732 		iph6_re = received;
733 		iph6_ex->hop_limits -= 1;
734 		if (iph6_re->hop_limits != iph6_ex->hop_limits)
735 			return TEST_FAILED;
736 	} else {
737 		printf("IP header version miss match\n");
738 		return TEST_FAILED;
739 	}
740 
741 	return TEST_SUCCESS;
742 }
743 
744 static int
745 test_ipsec_td_verify(struct rte_mbuf *m, const struct ipsec_test_data *td,
746 		     bool silent, const struct ipsec_test_flags *flags)
747 {
748 	uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *);
749 	uint32_t skip, len = rte_pktmbuf_pkt_len(m);
750 	uint8_t td_output_text[4096];
751 	int ret;
752 
753 	/* For tests with status as error for test success, skip verification */
754 	if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
755 	    (flags->icv_corrupt ||
756 	     flags->sa_expiry_pkts_hard ||
757 	     flags->tunnel_hdr_verify ||
758 	     td->ar_packet))
759 		return TEST_SUCCESS;
760 
761 	if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
762 	   flags->udp_encap) {
763 		const struct rte_ipv4_hdr *iph4;
764 		const struct rte_ipv6_hdr *iph6;
765 
766 		if (td->ipsec_xform.tunnel.type ==
767 				RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
768 			iph4 = (const struct rte_ipv4_hdr *)output_text;
769 			if (iph4->next_proto_id != IPPROTO_UDP) {
770 				printf("UDP header is not found\n");
771 				return TEST_FAILED;
772 			}
773 		} else {
774 			iph6 = (const struct rte_ipv6_hdr *)output_text;
775 			if (iph6->proto != IPPROTO_UDP) {
776 				printf("UDP header is not found\n");
777 				return TEST_FAILED;
778 			}
779 		}
780 
781 		len -= sizeof(struct rte_udp_hdr);
782 		output_text += sizeof(struct rte_udp_hdr);
783 	}
784 
785 	if (len != td->output_text.len) {
786 		printf("Output length (%d) not matching with expected (%d)\n",
787 			len, td->output_text.len);
788 		return TEST_FAILED;
789 	}
790 
791 	if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) &&
792 				flags->fragment) {
793 		const struct rte_ipv4_hdr *iph4;
794 		iph4 = (const struct rte_ipv4_hdr *)output_text;
795 		if (iph4->fragment_offset) {
796 			printf("Output packet is fragmented");
797 			return TEST_FAILED;
798 		}
799 	}
800 
801 	skip = test_ipsec_tunnel_hdr_len_get(td);
802 
803 	len -= skip;
804 	output_text += skip;
805 
806 	if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
807 				flags->ip_csum) {
808 		if (m->ol_flags & RTE_MBUF_F_RX_IP_CKSUM_GOOD)
809 			ret = test_ipsec_l3_csum_verify(m);
810 		else
811 			ret = TEST_FAILED;
812 
813 		if (ret == TEST_FAILED)
814 			printf("Inner IP checksum test failed\n");
815 
816 		return ret;
817 	}
818 
819 	if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
820 				flags->l4_csum) {
821 		if (m->ol_flags & RTE_MBUF_F_RX_L4_CKSUM_GOOD)
822 			ret = test_ipsec_l4_csum_verify(m);
823 		else
824 			ret = TEST_FAILED;
825 
826 		if (ret == TEST_FAILED)
827 			printf("Inner L4 checksum test failed\n");
828 
829 		return ret;
830 	}
831 
832 	memcpy(td_output_text, td->output_text.data + skip, len);
833 
834 	if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
835 				flags->dec_ttl_or_hop_limit) {
836 		if (test_ipsec_ttl_or_hop_decrement_verify(output_text, td_output_text)) {
837 			printf("Inner TTL/hop limit decrement test failed\n");
838 			return TEST_FAILED;
839 		}
840 	}
841 
842 	if (test_ipsec_pkt_update(td_output_text, flags)) {
843 		printf("Could not update expected vector");
844 		return TEST_FAILED;
845 	}
846 
847 	if (memcmp(output_text, td_output_text, len)) {
848 		if (silent)
849 			return TEST_FAILED;
850 
851 		printf("TestCase %s line %d: %s\n", __func__, __LINE__,
852 			"output text not as expected\n");
853 
854 		rte_hexdump(stdout, "expected", td_output_text, len);
855 		rte_hexdump(stdout, "actual", output_text, len);
856 		return TEST_FAILED;
857 	}
858 
859 	return TEST_SUCCESS;
860 }
861 
862 static int
863 test_ipsec_res_d_prepare(struct rte_mbuf *m, const struct ipsec_test_data *td,
864 		   struct ipsec_test_data *res_d)
865 {
866 	uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *);
867 	uint32_t len = rte_pktmbuf_pkt_len(m);
868 
869 	memcpy(res_d, td, sizeof(*res_d));
870 	memcpy(res_d->input_text.data, output_text, len);
871 	res_d->input_text.len = len;
872 
873 	res_d->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
874 	if (res_d->aead) {
875 		res_d->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
876 	} else {
877 		res_d->xform.chain.cipher.cipher.op =
878 				RTE_CRYPTO_CIPHER_OP_DECRYPT;
879 		res_d->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
880 	}
881 
882 	return TEST_SUCCESS;
883 }
884 
885 static int
886 test_ipsec_iph4_hdr_validate(const struct rte_ipv4_hdr *iph4,
887 			     const struct ipsec_test_flags *flags)
888 {
889 	uint8_t tos, dscp;
890 	uint16_t f_off;
891 
892 	if (!is_valid_ipv4_pkt(iph4)) {
893 		printf("Tunnel outer header is not IPv4\n");
894 		return -1;
895 	}
896 
897 	if (flags->ah && iph4->next_proto_id != IPPROTO_AH) {
898 		printf("Tunnel outer header proto is not AH\n");
899 		return -1;
900 	}
901 
902 	f_off = rte_be_to_cpu_16(iph4->fragment_offset);
903 	if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 ||
904 	    flags->df == TEST_IPSEC_SET_DF_1_INNER_0) {
905 		if (!(f_off & RTE_IPV4_HDR_DF_FLAG)) {
906 			printf("DF bit is not set\n");
907 			return -1;
908 		}
909 	} else {
910 		if (f_off & RTE_IPV4_HDR_DF_FLAG) {
911 			printf("DF bit is set\n");
912 			return -1;
913 		}
914 	}
915 
916 	tos = iph4->type_of_service;
917 	dscp = (tos & RTE_IPV4_HDR_DSCP_MASK) >> 2;
918 
919 	if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
920 	    flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0) {
921 		if (dscp != TEST_IPSEC_DSCP_VAL) {
922 			printf("DSCP value is not matching [exp: %x, actual: %x]\n",
923 			       TEST_IPSEC_DSCP_VAL, dscp);
924 			return -1;
925 		}
926 	} else {
927 		if (dscp != 0) {
928 			printf("DSCP value is set [exp: 0, actual: %x]\n",
929 			       dscp);
930 			return -1;
931 		}
932 	}
933 
934 	return 0;
935 }
936 
937 static int
938 test_ipsec_iph6_hdr_validate(const struct rte_ipv6_hdr *iph6,
939 			     const struct ipsec_test_flags *flags)
940 {
941 	uint32_t vtc_flow;
942 	uint32_t flabel;
943 	uint8_t dscp;
944 
945 	if (!is_valid_ipv6_pkt(iph6)) {
946 		printf("Tunnel outer header is not IPv6\n");
947 		return -1;
948 	}
949 
950 	vtc_flow = rte_be_to_cpu_32(iph6->vtc_flow);
951 	dscp = (vtc_flow & RTE_IPV6_HDR_DSCP_MASK) >>
952 	       (RTE_IPV6_HDR_TC_SHIFT + 2);
953 
954 	if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
955 	    flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0) {
956 		if (dscp != TEST_IPSEC_DSCP_VAL) {
957 			printf("DSCP value is not matching [exp: %x, actual: %x]\n",
958 			       TEST_IPSEC_DSCP_VAL, dscp);
959 			return -1;
960 		}
961 	} else {
962 		if (dscp != 0) {
963 			printf("DSCP value is set [exp: 0, actual: %x]\n",
964 			       dscp);
965 			return -1;
966 		}
967 	}
968 
969 	flabel = vtc_flow & RTE_IPV6_HDR_FL_MASK;
970 
971 	if (flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1 ||
972 	    flags->flabel == TEST_IPSEC_SET_FLABEL_1_INNER_0) {
973 		if (flabel != TEST_IPSEC_FLABEL_VAL) {
974 			printf("FLABEL value is not matching [exp: %x, actual: %x]\n",
975 			       TEST_IPSEC_FLABEL_VAL, flabel);
976 			return -1;
977 		}
978 	} else {
979 		if (flabel != 0) {
980 			printf("FLABEL value is set [exp: 0, actual: %x]\n",
981 			       flabel);
982 			return -1;
983 		}
984 	}
985 
986 	return 0;
987 }
988 
989 int
990 test_ipsec_post_process(struct rte_mbuf *m, const struct ipsec_test_data *td,
991 			struct ipsec_test_data *res_d, bool silent,
992 			const struct ipsec_test_flags *flags)
993 {
994 	uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *);
995 	int ret;
996 
997 	if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
998 		const struct rte_ipv4_hdr *iph4;
999 		const struct rte_ipv6_hdr *iph6;
1000 
1001 		if (flags->iv_gen) {
1002 			ret = test_ipsec_iv_verify_push(m, td);
1003 			if (ret != TEST_SUCCESS)
1004 				return ret;
1005 		}
1006 
1007 		iph4 = (const struct rte_ipv4_hdr *)output_text;
1008 
1009 		if (td->ipsec_xform.mode ==
1010 				RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) {
1011 			if (flags->ipv6) {
1012 				iph6 = (const struct rte_ipv6_hdr *)output_text;
1013 				if (is_valid_ipv6_pkt(iph6) == false) {
1014 					printf("Transport packet is not IPv6\n");
1015 					return TEST_FAILED;
1016 				}
1017 			} else {
1018 				if (is_valid_ipv4_pkt(iph4) == false) {
1019 					printf("Transport packet is not IPv4\n");
1020 					return TEST_FAILED;
1021 				}
1022 
1023 				if (flags->ah && iph4->next_proto_id != IPPROTO_AH) {
1024 					printf("Transport IPv4 header proto is not AH\n");
1025 					return -1;
1026 				}
1027 			}
1028 		} else {
1029 			if (td->ipsec_xform.tunnel.type ==
1030 					RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
1031 				if (test_ipsec_iph4_hdr_validate(iph4, flags))
1032 					return TEST_FAILED;
1033 			} else {
1034 				iph6 = (const struct rte_ipv6_hdr *)output_text;
1035 				if (test_ipsec_iph6_hdr_validate(iph6, flags))
1036 					return TEST_FAILED;
1037 			}
1038 		}
1039 	}
1040 
1041 	/*
1042 	 * In case of known vector tests & all inbound tests, res_d provided
1043 	 * would be NULL and output data need to be validated against expected.
1044 	 * For inbound, output_text would be plain packet and for outbound
1045 	 * output_text would IPsec packet. Validate by comparing against
1046 	 * known vectors.
1047 	 *
1048 	 * In case of combined mode tests, the output_text from outbound
1049 	 * operation (ie, IPsec packet) would need to be inbound processed to
1050 	 * obtain the plain text. Copy output_text to result data, 'res_d', so
1051 	 * that inbound processing can be done.
1052 	 */
1053 
1054 	if (res_d == NULL)
1055 		return test_ipsec_td_verify(m, td, silent, flags);
1056 	else
1057 		return test_ipsec_res_d_prepare(m, td, res_d);
1058 }
1059 
1060 int
1061 test_ipsec_status_check(const struct ipsec_test_data *td,
1062 			struct rte_crypto_op *op,
1063 			const struct ipsec_test_flags *flags,
1064 			enum rte_security_ipsec_sa_direction dir,
1065 			int pkt_num)
1066 {
1067 	int ret = TEST_SUCCESS;
1068 
1069 	if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
1070 	    td->ar_packet) {
1071 		if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1072 			printf("Anti replay test case failed\n");
1073 			return TEST_FAILED;
1074 		} else {
1075 			return TEST_SUCCESS;
1076 		}
1077 	}
1078 
1079 	if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
1080 	    flags->sa_expiry_pkts_hard &&
1081 	    pkt_num == IPSEC_TEST_PACKETS_MAX) {
1082 		if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1083 			printf("SA hard expiry (pkts) test failed\n");
1084 			return TEST_FAILED;
1085 		} else {
1086 			return TEST_SUCCESS;
1087 		}
1088 	}
1089 
1090 	if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
1091 	    flags->tunnel_hdr_verify) {
1092 		if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1093 			printf("Tunnel header verify test case failed\n");
1094 			return TEST_FAILED;
1095 		} else {
1096 			return TEST_SUCCESS;
1097 		}
1098 	}
1099 
1100 	if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && flags->icv_corrupt) {
1101 		if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1102 			printf("ICV corruption test case failed\n");
1103 			ret = TEST_FAILED;
1104 		}
1105 	} else {
1106 		if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
1107 			printf("Security op processing failed [pkt_num: %d]\n",
1108 			       pkt_num);
1109 			ret = TEST_FAILED;
1110 		}
1111 	}
1112 
1113 	if (flags->sa_expiry_pkts_soft && pkt_num == IPSEC_TEST_PACKETS_MAX) {
1114 		if (!(op->aux_flags &
1115 		      RTE_CRYPTO_OP_AUX_FLAGS_IPSEC_SOFT_EXPIRY)) {
1116 			printf("SA soft expiry (pkts) test failed\n");
1117 			ret = TEST_FAILED;
1118 		}
1119 	}
1120 
1121 	return ret;
1122 }
1123 
1124 int
1125 test_ipsec_stats_verify(struct rte_security_ctx *ctx,
1126 			struct rte_security_session *sess,
1127 			const struct ipsec_test_flags *flags,
1128 			enum rte_security_ipsec_sa_direction dir)
1129 {
1130 	struct rte_security_stats stats = {0};
1131 	int ret = TEST_SUCCESS;
1132 
1133 	if (flags->stats_success) {
1134 		if (rte_security_session_stats_get(ctx, sess, &stats) < 0)
1135 			return TEST_FAILED;
1136 
1137 		if (dir == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
1138 			if (stats.ipsec.opackets != 1 ||
1139 			    stats.ipsec.oerrors != 0)
1140 				ret = TEST_FAILED;
1141 		} else {
1142 			if (stats.ipsec.ipackets != 1 ||
1143 			    stats.ipsec.ierrors != 0)
1144 				ret = TEST_FAILED;
1145 		}
1146 	}
1147 
1148 	return ret;
1149 }
1150 
1151 int
1152 test_ipsec_pkt_update(uint8_t *pkt, const struct ipsec_test_flags *flags)
1153 {
1154 	struct rte_ipv4_hdr *iph4;
1155 	struct rte_ipv6_hdr *iph6;
1156 	bool cksum_dirty = false;
1157 
1158 	iph4 = (struct rte_ipv4_hdr *)pkt;
1159 
1160 	if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 ||
1161 	    flags->df == TEST_IPSEC_SET_DF_0_INNER_1 ||
1162 	    flags->df == TEST_IPSEC_COPY_DF_INNER_0 ||
1163 	    flags->df == TEST_IPSEC_SET_DF_1_INNER_0) {
1164 		uint16_t frag_off;
1165 
1166 		if (!is_ipv4(iph4)) {
1167 			printf("Invalid packet type\n");
1168 			return -1;
1169 		}
1170 
1171 		frag_off = rte_be_to_cpu_16(iph4->fragment_offset);
1172 
1173 		if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 ||
1174 		    flags->df == TEST_IPSEC_SET_DF_0_INNER_1)
1175 			frag_off |= RTE_IPV4_HDR_DF_FLAG;
1176 		else
1177 			frag_off &= ~RTE_IPV4_HDR_DF_FLAG;
1178 
1179 		iph4->fragment_offset = rte_cpu_to_be_16(frag_off);
1180 		cksum_dirty = true;
1181 	}
1182 
1183 	if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
1184 	    flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1 ||
1185 	    flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_0 ||
1186 	    flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0 ||
1187 	    flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1 ||
1188 	    flags->flabel == TEST_IPSEC_SET_FLABEL_0_INNER_1 ||
1189 	    flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_0 ||
1190 	    flags->flabel == TEST_IPSEC_SET_FLABEL_1_INNER_0) {
1191 
1192 		if (is_ipv4(iph4)) {
1193 			uint8_t tos;
1194 
1195 			tos = iph4->type_of_service;
1196 			if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
1197 			    flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1)
1198 				tos |= (RTE_IPV4_HDR_DSCP_MASK &
1199 					(TEST_IPSEC_DSCP_VAL << 2));
1200 			else
1201 				tos &= ~RTE_IPV4_HDR_DSCP_MASK;
1202 
1203 			iph4->type_of_service = tos;
1204 			cksum_dirty = true;
1205 		} else {
1206 			uint32_t vtc_flow;
1207 
1208 			iph6 = (struct rte_ipv6_hdr *)pkt;
1209 
1210 			vtc_flow = rte_be_to_cpu_32(iph6->vtc_flow);
1211 			if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
1212 			    flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1)
1213 				vtc_flow |= (RTE_IPV6_HDR_DSCP_MASK &
1214 					     (TEST_IPSEC_DSCP_VAL << (RTE_IPV6_HDR_TC_SHIFT + 2)));
1215 			else
1216 				vtc_flow &= ~RTE_IPV6_HDR_DSCP_MASK;
1217 
1218 			if (flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1 ||
1219 			    flags->flabel == TEST_IPSEC_SET_FLABEL_0_INNER_1)
1220 				vtc_flow |= (RTE_IPV6_HDR_FL_MASK &
1221 					     (TEST_IPSEC_FLABEL_VAL << RTE_IPV6_HDR_FL_SHIFT));
1222 			else
1223 				vtc_flow &= ~RTE_IPV6_HDR_FL_MASK;
1224 
1225 			iph6->vtc_flow = rte_cpu_to_be_32(vtc_flow);
1226 		}
1227 	}
1228 
1229 	if (cksum_dirty && is_ipv4(iph4)) {
1230 		iph4->hdr_checksum = 0;
1231 		iph4->hdr_checksum = rte_ipv4_cksum(iph4);
1232 	}
1233 
1234 	return 0;
1235 }
1236