xref: /dpdk/app/test/test_security_inline_macsec.c (revision 339b93549cbf028c036935eaa21cf3cb9a7f936c)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2023 Marvell.
3  */
4 
5 #include <stdio.h>
6 #include <inttypes.h>
7 
8 #include <rte_ethdev.h>
9 #include <rte_malloc.h>
10 #include <rte_security.h>
11 
12 #include "test.h"
13 #include "test_security_inline_macsec_vectors.h"
14 
15 #ifdef RTE_EXEC_ENV_WINDOWS
16 static int
17 test_inline_macsec(void)
18 {
19 	printf("Inline MACsec not supported on Windows, skipping test\n");
20 	return TEST_SKIPPED;
21 }
22 
23 #else
24 
25 #define NB_ETHPORTS_USED		1
26 #define MEMPOOL_CACHE_SIZE		32
27 #define RTE_TEST_RX_DESC_DEFAULT	1024
28 #define RTE_TEST_TX_DESC_DEFAULT	1024
29 #define RTE_PORT_ALL		(~(uint16_t)0x0)
30 
31 #define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
32 #define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
33 #define RX_WTHRESH 0 /**< Default values of RX write-back threshold reg. */
34 
35 #define TX_PTHRESH 32 /**< Default values of TX prefetch threshold reg. */
36 #define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
37 #define TX_WTHRESH 0  /**< Default values of TX write-back threshold reg. */
38 
39 #define MAX_TRAFFIC_BURST		2048
40 #define NB_MBUF				10240
41 
42 #define MCS_INVALID_SA			0xFFFF
43 #define MCS_DEFAULT_PN_THRESHOLD	0xFFFFF
44 
45 static struct rte_mempool *mbufpool;
46 static struct rte_mempool *sess_pool;
47 /* ethernet addresses of ports */
48 static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
49 
50 struct mcs_test_opts {
51 	int val_frames;
52 	int nb_td;
53 	uint16_t mtu;
54 	uint8_t sa_in_use;
55 	bool encrypt;
56 	bool protect_frames;
57 	uint8_t sectag_insert_mode;
58 	uint8_t nb_vlan;
59 	uint32_t replay_win_sz;
60 	uint8_t replay_protect;
61 	uint8_t rekey_en;
62 	const struct mcs_test_vector *rekey_td;
63 	bool dump_all_stats;
64 	uint8_t check_untagged_rx;
65 	uint8_t check_bad_tag_cnt;
66 	uint8_t check_sa_not_in_use;
67 	uint8_t check_decap_stats;
68 	uint8_t check_verify_only_stats;
69 	uint8_t check_pkts_invalid_stats;
70 	uint8_t check_pkts_unchecked_stats;
71 	uint8_t check_out_pkts_untagged;
72 	uint8_t check_out_pkts_toolong;
73 	uint8_t check_encap_stats;
74 	uint8_t check_auth_only_stats;
75 	uint8_t check_sectag_interrupts;
76 };
77 
78 static struct rte_eth_conf port_conf = {
79 	.rxmode = {
80 		.mq_mode = RTE_ETH_MQ_RX_NONE,
81 		.offloads = RTE_ETH_RX_OFFLOAD_CHECKSUM |
82 			    RTE_ETH_RX_OFFLOAD_MACSEC_STRIP,
83 	},
84 	.txmode = {
85 		.mq_mode = RTE_ETH_MQ_TX_NONE,
86 		.offloads = RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
87 			    RTE_ETH_TX_OFFLOAD_MACSEC_INSERT,
88 	},
89 	.lpbk_mode = 1,  /* enable loopback */
90 };
91 
92 static struct rte_eth_rxconf rx_conf = {
93 	.rx_thresh = {
94 		.pthresh = RX_PTHRESH,
95 		.hthresh = RX_HTHRESH,
96 		.wthresh = RX_WTHRESH,
97 	},
98 	.rx_free_thresh = 32,
99 };
100 
101 static struct rte_eth_txconf tx_conf = {
102 	.tx_thresh = {
103 		.pthresh = TX_PTHRESH,
104 		.hthresh = TX_HTHRESH,
105 		.wthresh = TX_WTHRESH,
106 	},
107 	.tx_free_thresh = 32, /* Use PMD default values */
108 	.tx_rs_thresh = 32, /* Use PMD default values */
109 };
110 
111 static uint16_t port_id;
112 
113 static uint64_t link_mbps;
114 
115 static struct rte_flow *default_tx_flow[RTE_MAX_ETHPORTS];
116 static struct rte_flow *default_rx_flow[RTE_MAX_ETHPORTS];
117 
118 static struct rte_mbuf **tx_pkts_burst;
119 static struct rte_mbuf **rx_pkts_burst;
120 
121 static inline struct rte_mbuf *
122 init_packet(struct rte_mempool *mp, const uint8_t *data, unsigned int len)
123 {
124 	struct rte_mbuf *pkt;
125 
126 	pkt = rte_pktmbuf_alloc(mp);
127 	if (pkt == NULL)
128 		return NULL;
129 
130 	rte_memcpy(rte_pktmbuf_append(pkt, len), data, len);
131 
132 	return pkt;
133 }
134 
135 static int
136 init_mempools(unsigned int nb_mbuf)
137 {
138 	struct rte_security_ctx *sec_ctx;
139 	uint16_t nb_sess = 512;
140 	uint32_t sess_sz;
141 	char s[64];
142 
143 	if (mbufpool == NULL) {
144 		snprintf(s, sizeof(s), "mbuf_pool");
145 		mbufpool = rte_pktmbuf_pool_create(s, nb_mbuf,
146 				MEMPOOL_CACHE_SIZE, 0,
147 				RTE_MBUF_DEFAULT_BUF_SIZE, SOCKET_ID_ANY);
148 		if (mbufpool == NULL) {
149 			printf("Cannot init mbuf pool\n");
150 			return TEST_FAILED;
151 		}
152 		printf("Allocated mbuf pool\n");
153 	}
154 
155 	sec_ctx = rte_eth_dev_get_sec_ctx(port_id);
156 	if (sec_ctx == NULL) {
157 		printf("Device does not support Security ctx\n");
158 		return TEST_SKIPPED;
159 	}
160 	sess_sz = rte_security_session_get_size(sec_ctx);
161 	if (sess_pool == NULL) {
162 		snprintf(s, sizeof(s), "sess_pool");
163 		sess_pool = rte_mempool_create(s, nb_sess, sess_sz,
164 				MEMPOOL_CACHE_SIZE, 0,
165 				NULL, NULL, NULL, NULL,
166 				SOCKET_ID_ANY, 0);
167 		if (sess_pool == NULL) {
168 			printf("Cannot init sess pool\n");
169 			return TEST_FAILED;
170 		}
171 		printf("Allocated sess pool\n");
172 	}
173 
174 	return 0;
175 }
176 
177 static void
178 fill_macsec_sa_conf(const struct mcs_test_vector *td, struct rte_security_macsec_sa *sa,
179 			enum rte_security_macsec_direction dir, uint8_t an, uint8_t tci_off)
180 {
181 	sa->dir = dir;
182 
183 	sa->key.data = td->sa_key.data;
184 	sa->key.length = td->sa_key.len;
185 
186 	memcpy((uint8_t *)sa->salt, (const uint8_t *)td->salt, RTE_SECURITY_MACSEC_SALT_LEN);
187 
188 	/* AN is set as per the value in secure packet in test vector */
189 	sa->an = an & RTE_MACSEC_AN_MASK;
190 
191 	sa->ssci = td->ssci;
192 	sa->xpn = td->xpn;
193 	/* Starting packet number which is expected to come next.
194 	 * It is take from the test vector so that we can match the out packet.
195 	 */
196 	sa->next_pn = *(const uint32_t *)(&td->secure_pkt.data[tci_off + 2]);
197 }
198 
199 static void
200 fill_macsec_sc_conf(const struct mcs_test_vector *td,
201 		    struct rte_security_macsec_sc *sc_conf,
202 		    const struct mcs_test_opts *opts,
203 		    enum rte_security_macsec_direction dir,
204 		    uint16_t sa_id[], uint8_t tci_off)
205 {
206 	uint8_t i;
207 
208 	sc_conf->dir = dir;
209 	if (dir == RTE_SECURITY_MACSEC_DIR_TX) {
210 		sc_conf->sc_tx.sa_id = sa_id[0];
211 		if (sa_id[1] != MCS_INVALID_SA) {
212 			sc_conf->sc_tx.sa_id_rekey = sa_id[1];
213 			sc_conf->sc_tx.re_key_en = 1;
214 		}
215 		sc_conf->sc_tx.active = 1;
216 		/* is SCI valid */
217 		if (td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_SC) {
218 			memcpy(&sc_conf->sc_tx.sci, &td->secure_pkt.data[tci_off + 6],
219 					sizeof(sc_conf->sc_tx.sci));
220 			sc_conf->sc_tx.sci = rte_be_to_cpu_64(sc_conf->sc_tx.sci);
221 		} else if (td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_ES) {
222 			/* sci = source_mac + port_id when ES.bit = 1 & SC.bit = 0 */
223 			const uint8_t *smac = td->plain_pkt.data + RTE_ETHER_ADDR_LEN;
224 			uint8_t *ptr = (uint8_t *)&sc_conf->sc_tx.sci;
225 
226 			ptr[0] = 0x01;
227 			ptr[1] = 0;
228 			for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
229 				ptr[2 + i] = smac[RTE_ETHER_ADDR_LEN - 1 - i];
230 		} else {
231 			/* use some default SCI */
232 			sc_conf->sc_tx.sci = 0xf1341e023a2b1c5d;
233 		}
234 	} else {
235 		for (i = 0; i < RTE_SECURITY_MACSEC_NUM_AN; i++) {
236 			sc_conf->sc_rx.sa_id[i] = sa_id[i];
237 			sc_conf->sc_rx.sa_in_use[i] = opts->sa_in_use;
238 		}
239 		sc_conf->sc_rx.active = 1;
240 	}
241 }
242 
243 
244 /* Create Inline MACsec session */
245 static int
246 fill_session_conf(const struct mcs_test_vector *td, uint16_t portid __rte_unused,
247 		const struct mcs_test_opts *opts,
248 		struct rte_security_session_conf *sess_conf,
249 		enum rte_security_macsec_direction dir,
250 		uint16_t sc_id,
251 		uint8_t tci_off)
252 {
253 	sess_conf->action_type = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL;
254 	sess_conf->protocol = RTE_SECURITY_PROTOCOL_MACSEC;
255 	sess_conf->macsec.dir = dir;
256 	sess_conf->macsec.alg = td->alg;
257 	sess_conf->macsec.cipher_off = 0;
258 	if (td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_SC) {
259 		sess_conf->macsec.sci = rte_be_to_cpu_64(*(const uint64_t *)
260 					(&td->secure_pkt.data[tci_off + 6]));
261 	} else if (td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_ES) {
262 		/* sci = source_mac + port_id when ES.bit = 1 & SC.bit = 0 */
263 		const uint8_t *smac = td->plain_pkt.data + RTE_ETHER_ADDR_LEN;
264 		uint8_t *ptr = (uint8_t *)&sess_conf->macsec.sci;
265 		uint8_t j;
266 
267 		ptr[0] = 0x01;
268 		ptr[1] = 0;
269 		for (j = 0; j < RTE_ETHER_ADDR_LEN; j++)
270 			ptr[2 + j] = smac[RTE_ETHER_ADDR_LEN - 1 - j];
271 	}
272 	sess_conf->macsec.sc_id = sc_id;
273 	if (dir == RTE_SECURITY_MACSEC_DIR_TX) {
274 		sess_conf->macsec.tx_secy.mtu = opts->mtu;
275 		sess_conf->macsec.tx_secy.sectag_off = (opts->sectag_insert_mode == 1) ?
276 							2 * RTE_ETHER_ADDR_LEN :
277 							RTE_VLAN_HLEN;
278 		sess_conf->macsec.tx_secy.sectag_insert_mode = opts->sectag_insert_mode;
279 		sess_conf->macsec.tx_secy.ctrl_port_enable = 1;
280 		sess_conf->macsec.tx_secy.sectag_version = 0;
281 		sess_conf->macsec.tx_secy.end_station =
282 					(td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_ES) >> 6;
283 		sess_conf->macsec.tx_secy.send_sci =
284 					(td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_SC) >> 5;
285 		sess_conf->macsec.tx_secy.scb =
286 					(td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_SCB) >> 4;
287 		sess_conf->macsec.tx_secy.encrypt = opts->encrypt;
288 		sess_conf->macsec.tx_secy.protect_frames = opts->protect_frames;
289 		sess_conf->macsec.tx_secy.icv_include_da_sa = 1;
290 	} else {
291 		sess_conf->macsec.rx_secy.replay_win_sz = opts->replay_win_sz;
292 		sess_conf->macsec.rx_secy.replay_protect = opts->replay_protect;
293 		sess_conf->macsec.rx_secy.icv_include_da_sa = 1;
294 		sess_conf->macsec.rx_secy.ctrl_port_enable = 1;
295 		sess_conf->macsec.rx_secy.preserve_sectag = 0;
296 		sess_conf->macsec.rx_secy.preserve_icv = 0;
297 		sess_conf->macsec.rx_secy.validate_frames = opts->val_frames;
298 	}
299 
300 	return 0;
301 }
302 
303 static int
304 create_default_flow(const struct mcs_test_vector *td, uint16_t portid,
305 		    enum rte_security_macsec_direction dir, void *sess)
306 {
307 	struct rte_flow_action action[2];
308 	struct rte_flow_item pattern[2];
309 	struct rte_flow_attr attr = {0};
310 	struct rte_flow_error err;
311 	struct rte_flow *flow;
312 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
313 	static const struct rte_flow_item_eth eth_mask = {
314 		.hdr.dst_addr.addr_bytes = "\x00\x00\x00\x00\x00\x00",
315 		.hdr.src_addr.addr_bytes = "\x00\x00\x00\x00\x00\x00",
316 		.hdr.ether_type = RTE_BE16(0x0000),
317 	};
318 
319 	int ret;
320 
321 	eth.has_vlan = 0;
322 	if (dir == RTE_SECURITY_MACSEC_DIR_TX)
323 		memcpy(&eth.hdr, td->plain_pkt.data, RTE_ETHER_HDR_LEN);
324 	else
325 		memcpy(&eth.hdr, td->secure_pkt.data, RTE_ETHER_HDR_LEN);
326 
327 	pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
328 	pattern[0].spec = &eth;
329 	pattern[0].mask = &eth_mask;
330 	pattern[0].last = NULL;
331 	pattern[1].type = RTE_FLOW_ITEM_TYPE_END;
332 
333 	action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
334 	action[0].conf = sess;
335 	action[1].type = RTE_FLOW_ACTION_TYPE_END;
336 	action[1].conf = NULL;
337 
338 	attr.ingress = (dir == RTE_SECURITY_MACSEC_DIR_RX) ? 1 : 0;
339 	attr.egress = (dir == RTE_SECURITY_MACSEC_DIR_TX) ? 1 : 0;
340 
341 	ret = rte_flow_validate(portid, &attr, pattern, action, &err);
342 	if (ret) {
343 		printf("\nValidate flow failed, ret = %d\n", ret);
344 		return -1;
345 	}
346 	flow = rte_flow_create(portid, &attr, pattern, action, &err);
347 	if (flow == NULL) {
348 		printf("\nDefault flow rule create failed\n");
349 		return -1;
350 	}
351 
352 	if (dir == RTE_SECURITY_MACSEC_DIR_TX)
353 		default_tx_flow[portid] = flow;
354 	else
355 		default_rx_flow[portid] = flow;
356 
357 	return 0;
358 }
359 
360 static void
361 destroy_default_flow(uint16_t portid)
362 {
363 	struct rte_flow_error err;
364 	int ret;
365 
366 	if (default_tx_flow[portid]) {
367 		ret = rte_flow_destroy(portid, default_tx_flow[portid], &err);
368 		if (ret) {
369 			printf("\nDefault Tx flow rule destroy failed\n");
370 			return;
371 		}
372 		default_tx_flow[portid] = NULL;
373 	}
374 	if (default_rx_flow[portid]) {
375 		ret = rte_flow_destroy(portid, default_rx_flow[portid], &err);
376 		if (ret) {
377 			printf("\nDefault Rx flow rule destroy failed\n");
378 			return;
379 		}
380 		default_rx_flow[portid] = NULL;
381 	}
382 }
383 
384 static void
385 print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr)
386 {
387 	char buf[RTE_ETHER_ADDR_FMT_SIZE];
388 	rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
389 	printf("%s%s", name, buf);
390 }
391 
392 /* Check the link status of all ports in up to 3s, and print them finally */
393 static void
394 check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
395 {
396 #define CHECK_INTERVAL 100 /* 100ms */
397 #define MAX_CHECK_TIME 30 /* 3s (30 * 100ms) in total */
398 	uint16_t portid;
399 	uint8_t count, all_ports_up, print_flag = 0;
400 	struct rte_eth_link link;
401 	int ret;
402 	char link_status[RTE_ETH_LINK_MAX_STR_LEN];
403 
404 	printf("Checking link statuses...\n");
405 	fflush(stdout);
406 	for (count = 0; count <= MAX_CHECK_TIME; count++) {
407 		all_ports_up = 1;
408 		for (portid = 0; portid < port_num; portid++) {
409 			if ((port_mask & (1 << portid)) == 0)
410 				continue;
411 			memset(&link, 0, sizeof(link));
412 			ret = rte_eth_link_get_nowait(portid, &link);
413 			if (ret < 0) {
414 				all_ports_up = 0;
415 				if (print_flag == 1)
416 					printf("Port %u link get failed: %s\n",
417 						portid, rte_strerror(-ret));
418 				continue;
419 			}
420 
421 			/* print link status if flag set */
422 			if (print_flag == 1) {
423 				if (link.link_status && link_mbps == 0)
424 					link_mbps = link.link_speed;
425 
426 				rte_eth_link_to_str(link_status,
427 					sizeof(link_status), &link);
428 				printf("Port %d %s\n", portid, link_status);
429 				continue;
430 			}
431 			/* clear all_ports_up flag if any link down */
432 			if (link.link_status == RTE_ETH_LINK_DOWN) {
433 				all_ports_up = 0;
434 				break;
435 			}
436 		}
437 		/* after finally printing all link status, get out */
438 		if (print_flag == 1)
439 			break;
440 
441 		if (all_ports_up == 0)
442 			fflush(stdout);
443 
444 		/* set the print_flag if all ports up or timeout */
445 		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1))
446 			print_flag = 1;
447 	}
448 }
449 
450 static int
451 test_macsec_post_process(struct rte_mbuf *m, const struct mcs_test_vector *td,
452 			enum mcs_op op, uint8_t check_out_pkts_untagged)
453 {
454 	const uint8_t *dptr;
455 	uint16_t pkt_len;
456 
457 	if (op == MCS_DECAP || op == MCS_ENCAP_DECAP ||
458 			op == MCS_VERIFY_ONLY || op == MCS_AUTH_VERIFY ||
459 			check_out_pkts_untagged == 1) {
460 		dptr = td->plain_pkt.data;
461 		pkt_len = td->plain_pkt.len;
462 	} else {
463 		dptr = td->secure_pkt.data;
464 		pkt_len = td->secure_pkt.len;
465 	}
466 
467 	if (memcmp(rte_pktmbuf_mtod(m, uint8_t *), dptr, pkt_len)) {
468 		printf("\nData comparison failed for td.");
469 		rte_pktmbuf_dump(stdout, m, m->pkt_len);
470 		rte_hexdump(stdout, "expected_data", dptr, pkt_len);
471 		return TEST_FAILED;
472 	}
473 
474 	return TEST_SUCCESS;
475 }
476 
477 static void
478 mcs_stats_dump(struct rte_security_ctx *ctx, enum mcs_op op,
479 	       void *rx_sess, void *tx_sess,
480 	       uint8_t rx_sc_id, uint8_t tx_sc_id,
481 	       uint16_t rx_sa_id[], uint16_t tx_sa_id[])
482 {
483 	struct rte_security_stats sess_stats = {0};
484 	struct rte_security_macsec_secy_stats *secy_stat;
485 	struct rte_security_macsec_sc_stats sc_stat = {0};
486 	struct rte_security_macsec_sa_stats sa_stat = {0};
487 	int i;
488 
489 	if (op == MCS_DECAP || op == MCS_ENCAP_DECAP ||
490 			op == MCS_VERIFY_ONLY || op == MCS_AUTH_VERIFY) {
491 		printf("\n********* RX SECY STATS ************\n");
492 		rte_security_session_stats_get(ctx, rx_sess, &sess_stats);
493 		secy_stat = &sess_stats.macsec;
494 
495 		if (secy_stat->ctl_pkt_bcast_cnt)
496 			printf("RX: ctl_pkt_bcast_cnt: 0x%" PRIx64 "\n",
497 					secy_stat->ctl_pkt_bcast_cnt);
498 		if (secy_stat->ctl_pkt_mcast_cnt)
499 			printf("RX: ctl_pkt_mcast_cnt: 0x%" PRIx64 "\n",
500 					secy_stat->ctl_pkt_mcast_cnt);
501 		if (secy_stat->ctl_pkt_ucast_cnt)
502 			printf("RX: ctl_pkt_ucast_cnt: 0x%" PRIx64 "\n",
503 					secy_stat->ctl_pkt_ucast_cnt);
504 		if (secy_stat->ctl_octet_cnt)
505 			printf("RX: ctl_octet_cnt: 0x%" PRIx64 "\n", secy_stat->ctl_octet_cnt);
506 		if (secy_stat->unctl_pkt_bcast_cnt)
507 			printf("RX: unctl_pkt_bcast_cnt: 0x%" PRIx64 "\n",
508 					secy_stat->unctl_pkt_bcast_cnt);
509 		if (secy_stat->unctl_pkt_mcast_cnt)
510 			printf("RX: unctl_pkt_mcast_cnt: 0x%" PRIx64 "\n",
511 					secy_stat->unctl_pkt_mcast_cnt);
512 		if (secy_stat->unctl_pkt_ucast_cnt)
513 			printf("RX: unctl_pkt_ucast_cnt: 0x%" PRIx64 "\n",
514 					secy_stat->unctl_pkt_ucast_cnt);
515 		if (secy_stat->unctl_octet_cnt)
516 			printf("RX: unctl_octet_cnt: 0x%" PRIx64 "\n", secy_stat->unctl_octet_cnt);
517 		/* Valid only for RX */
518 		if (secy_stat->octet_decrypted_cnt)
519 			printf("RX: octet_decrypted_cnt: 0x%" PRIx64 "\n",
520 					secy_stat->octet_decrypted_cnt);
521 		if (secy_stat->octet_validated_cnt)
522 			printf("RX: octet_validated_cnt: 0x%" PRIx64 "\n",
523 					secy_stat->octet_validated_cnt);
524 		if (secy_stat->pkt_port_disabled_cnt)
525 			printf("RX: pkt_port_disabled_cnt: 0x%" PRIx64 "\n",
526 					secy_stat->pkt_port_disabled_cnt);
527 		if (secy_stat->pkt_badtag_cnt)
528 			printf("RX: pkt_badtag_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_badtag_cnt);
529 		if (secy_stat->pkt_nosa_cnt)
530 			printf("RX: pkt_nosa_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_nosa_cnt);
531 		if (secy_stat->pkt_nosaerror_cnt)
532 			printf("RX: pkt_nosaerror_cnt: 0x%" PRIx64 "\n",
533 					secy_stat->pkt_nosaerror_cnt);
534 		if (secy_stat->pkt_tagged_ctl_cnt)
535 			printf("RX: pkt_tagged_ctl_cnt: 0x%" PRIx64 "\n",
536 					secy_stat->pkt_tagged_ctl_cnt);
537 		if (secy_stat->pkt_untaged_cnt)
538 			printf("RX: pkt_untaged_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_untaged_cnt);
539 		if (secy_stat->pkt_ctl_cnt)
540 			printf("RX: pkt_ctl_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_ctl_cnt);
541 		if (secy_stat->pkt_notag_cnt)
542 			printf("RX: pkt_notag_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_notag_cnt);
543 		printf("\n");
544 		printf("\n********** RX SC[%u] STATS **************\n", rx_sc_id);
545 
546 		rte_security_macsec_sc_stats_get(ctx, rx_sc_id, RTE_SECURITY_MACSEC_DIR_RX,
547 						 &sc_stat);
548 		/* RX */
549 		if (sc_stat.hit_cnt)
550 			printf("RX hit_cnt: 0x%" PRIx64 "\n", sc_stat.hit_cnt);
551 		if (sc_stat.pkt_invalid_cnt)
552 			printf("RX pkt_invalid_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_invalid_cnt);
553 		if (sc_stat.pkt_late_cnt)
554 			printf("RX pkt_late_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_late_cnt);
555 		if (sc_stat.pkt_notvalid_cnt)
556 			printf("RX pkt_notvalid_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_notvalid_cnt);
557 		if (sc_stat.pkt_unchecked_cnt)
558 			printf("RX pkt_unchecked_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_unchecked_cnt);
559 		if (sc_stat.pkt_delay_cnt)
560 			printf("RX pkt_delay_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_delay_cnt);
561 		if (sc_stat.pkt_ok_cnt)
562 			printf("RX pkt_ok_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_ok_cnt);
563 		if (sc_stat.octet_decrypt_cnt)
564 			printf("RX octet_decrypt_cnt: 0x%" PRIx64 "\n", sc_stat.octet_decrypt_cnt);
565 		if (sc_stat.octet_validate_cnt)
566 			printf("RX octet_validate_cnt: 0x%" PRIx64 "\n",
567 					sc_stat.octet_validate_cnt);
568 		printf("\n");
569 		for (i = 0; i < RTE_SECURITY_MACSEC_NUM_AN; i++) {
570 			printf("\n********** RX SA[%u] STATS ****************\n", rx_sa_id[i]);
571 			memset(&sa_stat, 0, sizeof(struct rte_security_macsec_sa_stats));
572 			rte_security_macsec_sa_stats_get(ctx, rx_sa_id[i],
573 					RTE_SECURITY_MACSEC_DIR_RX, &sa_stat);
574 
575 			/* RX */
576 			if (sa_stat.pkt_invalid_cnt)
577 				printf("RX pkt_invalid_cnt: 0x%" PRIx64 "\n",
578 						sa_stat.pkt_invalid_cnt);
579 			if (sa_stat.pkt_nosaerror_cnt)
580 				printf("RX pkt_nosaerror_cnt: 0x%" PRIx64 "\n",
581 						sa_stat.pkt_nosaerror_cnt);
582 			if (sa_stat.pkt_notvalid_cnt)
583 				printf("RX pkt_notvalid_cnt: 0x%" PRIx64 "\n",
584 						sa_stat.pkt_notvalid_cnt);
585 			if (sa_stat.pkt_ok_cnt)
586 				printf("RX pkt_ok_cnt: 0x%" PRIx64 "\n", sa_stat.pkt_ok_cnt);
587 			if (sa_stat.pkt_nosa_cnt)
588 				printf("RX pkt_nosa_cnt: 0x%" PRIx64 "\n", sa_stat.pkt_nosa_cnt);
589 			printf("\n");
590 		}
591 	}
592 
593 	if (op == MCS_ENCAP || op == MCS_ENCAP_DECAP ||
594 			op == MCS_AUTH_ONLY || op == MCS_AUTH_VERIFY) {
595 		memset(&sess_stats, 0, sizeof(struct rte_security_stats));
596 		rte_security_session_stats_get(ctx, tx_sess, &sess_stats);
597 		secy_stat = &sess_stats.macsec;
598 
599 		printf("\n********* TX SECY STATS ************\n");
600 		if (secy_stat->ctl_pkt_bcast_cnt)
601 			printf("TX: ctl_pkt_bcast_cnt: 0x%" PRIx64 "\n",
602 					secy_stat->ctl_pkt_bcast_cnt);
603 		if (secy_stat->ctl_pkt_mcast_cnt)
604 			printf("TX: ctl_pkt_mcast_cnt: 0x%" PRIx64 "\n",
605 					secy_stat->ctl_pkt_mcast_cnt);
606 		if (secy_stat->ctl_pkt_ucast_cnt)
607 			printf("TX: ctl_pkt_ucast_cnt: 0x%" PRIx64 "\n",
608 					secy_stat->ctl_pkt_ucast_cnt);
609 		if (secy_stat->ctl_octet_cnt)
610 			printf("TX: ctl_octet_cnt: 0x%" PRIx64 "\n", secy_stat->ctl_octet_cnt);
611 		if (secy_stat->unctl_pkt_bcast_cnt)
612 			printf("TX: unctl_pkt_bcast_cnt: 0x%" PRIx64 "\n",
613 					secy_stat->unctl_pkt_bcast_cnt);
614 		if (secy_stat->unctl_pkt_mcast_cnt)
615 			printf("TX: unctl_pkt_mcast_cnt: 0x%" PRIx64 "\n",
616 					secy_stat->unctl_pkt_mcast_cnt);
617 		if (secy_stat->unctl_pkt_ucast_cnt)
618 			printf("TX: unctl_pkt_ucast_cnt: 0x%" PRIx64 "\n",
619 					secy_stat->unctl_pkt_ucast_cnt);
620 		if (secy_stat->unctl_octet_cnt)
621 			printf("TX: unctl_octet_cnt: 0x%" PRIx64 "\n",
622 					secy_stat->unctl_octet_cnt);
623 		/* Valid only for TX */
624 		if (secy_stat->octet_encrypted_cnt)
625 			printf("TX: octet_encrypted_cnt: 0x%" PRIx64 "\n",
626 					secy_stat->octet_encrypted_cnt);
627 		if (secy_stat->octet_protected_cnt)
628 			printf("TX: octet_protected_cnt: 0x%" PRIx64 "\n",
629 					secy_stat->octet_protected_cnt);
630 		if (secy_stat->pkt_noactivesa_cnt)
631 			printf("TX: pkt_noactivesa_cnt: 0x%" PRIx64 "\n",
632 					secy_stat->pkt_noactivesa_cnt);
633 		if (secy_stat->pkt_toolong_cnt)
634 			printf("TX: pkt_toolong_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_toolong_cnt);
635 		if (secy_stat->pkt_untagged_cnt)
636 			printf("TX: pkt_untagged_cnt: 0x%" PRIx64 "\n",
637 					secy_stat->pkt_untagged_cnt);
638 
639 
640 		memset(&sc_stat, 0, sizeof(struct rte_security_macsec_sc_stats));
641 		rte_security_macsec_sc_stats_get(ctx, tx_sc_id, RTE_SECURITY_MACSEC_DIR_TX,
642 						 &sc_stat);
643 		printf("\n********** TX SC[%u] STATS **************\n", tx_sc_id);
644 		if (sc_stat.pkt_encrypt_cnt)
645 			printf("TX pkt_encrypt_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_encrypt_cnt);
646 		if (sc_stat.pkt_protected_cnt)
647 			printf("TX pkt_protected_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_protected_cnt);
648 		if (sc_stat.octet_encrypt_cnt)
649 			printf("TX octet_encrypt_cnt: 0x%" PRIx64 "\n", sc_stat.octet_encrypt_cnt);
650 
651 		memset(&sa_stat, 0, sizeof(struct rte_security_macsec_sa_stats));
652 		rte_security_macsec_sa_stats_get(ctx, tx_sa_id[0],
653 				RTE_SECURITY_MACSEC_DIR_TX, &sa_stat);
654 		printf("\n********** TX SA[%u] STATS ****************\n", tx_sa_id[0]);
655 		if (sa_stat.pkt_encrypt_cnt)
656 			printf("TX pkt_encrypt_cnt: 0x%" PRIx64 "\n", sa_stat.pkt_encrypt_cnt);
657 		if (sa_stat.pkt_protected_cnt)
658 			printf("TX pkt_protected_cnt: 0x%" PRIx64 "\n", sa_stat.pkt_protected_cnt);
659 	}
660 }
661 
662 static int
663 mcs_stats_check(struct rte_security_ctx *ctx, enum mcs_op op,
664 		const struct mcs_test_opts *opts,
665 		const struct mcs_test_vector *td,
666 		void *rx_sess, void *tx_sess,
667 		uint8_t rx_sc_id, uint8_t tx_sc_id,
668 		uint16_t rx_sa_id[], uint16_t tx_sa_id[])
669 {
670 	struct rte_security_stats sess_stats = {0};
671 	struct rte_security_macsec_secy_stats *secy_stat;
672 	struct rte_security_macsec_sc_stats sc_stat = {0};
673 	struct rte_security_macsec_sa_stats sa_stat = {0};
674 	int i;
675 
676 	if (op == MCS_DECAP || op == MCS_ENCAP_DECAP ||
677 			op == MCS_VERIFY_ONLY || op == MCS_AUTH_VERIFY) {
678 		rte_security_session_stats_get(ctx, rx_sess, &sess_stats);
679 		secy_stat = &sess_stats.macsec;
680 
681 		if ((opts->check_untagged_rx && secy_stat->pkt_notag_cnt != 1) ||
682 				(opts->check_untagged_rx && secy_stat->pkt_untaged_cnt != 1))
683 			return TEST_FAILED;
684 
685 		if (opts->check_bad_tag_cnt && secy_stat->pkt_badtag_cnt != 1)
686 			return TEST_FAILED;
687 
688 		if (opts->check_sa_not_in_use && secy_stat->pkt_nosaerror_cnt != 1)
689 			return TEST_FAILED;
690 
691 		if (opts->check_decap_stats && secy_stat->octet_decrypted_cnt !=
692 				(uint16_t)(td->plain_pkt.len - 2 * RTE_ETHER_ADDR_LEN))
693 			return TEST_FAILED;
694 
695 		if (opts->check_verify_only_stats && secy_stat->octet_validated_cnt !=
696 				(uint16_t)(td->plain_pkt.len - 2 * RTE_ETHER_ADDR_LEN))
697 			return TEST_FAILED;
698 
699 		rte_security_macsec_sc_stats_get(ctx, rx_sc_id,
700 				RTE_SECURITY_MACSEC_DIR_RX, &sc_stat);
701 
702 		if ((opts->check_decap_stats || opts->check_verify_only_stats) &&
703 				sc_stat.pkt_ok_cnt != 1)
704 			return TEST_FAILED;
705 
706 		if (opts->check_pkts_invalid_stats && sc_stat.pkt_notvalid_cnt != 1)
707 			return TEST_FAILED;
708 
709 		if (opts->check_pkts_unchecked_stats && sc_stat.pkt_unchecked_cnt != 1)
710 			return TEST_FAILED;
711 
712 		for (i = 0; i < RTE_SECURITY_MACSEC_NUM_AN; i++) {
713 			memset(&sa_stat, 0, sizeof(struct rte_security_macsec_sa_stats));
714 			rte_security_macsec_sa_stats_get(ctx, rx_sa_id[i],
715 					RTE_SECURITY_MACSEC_DIR_RX, &sa_stat);
716 
717 		}
718 	}
719 
720 	if (op == MCS_ENCAP || op == MCS_ENCAP_DECAP ||
721 			op == MCS_AUTH_ONLY || op == MCS_AUTH_VERIFY) {
722 		memset(&sess_stats, 0, sizeof(struct rte_security_stats));
723 		rte_security_session_stats_get(ctx, tx_sess, &sess_stats);
724 		secy_stat = &sess_stats.macsec;
725 
726 		if (opts->check_out_pkts_untagged && secy_stat->pkt_untagged_cnt != 1)
727 			return TEST_FAILED;
728 
729 		if (opts->check_out_pkts_toolong && secy_stat->pkt_toolong_cnt != 1)
730 			return TEST_FAILED;
731 
732 		if (opts->check_encap_stats && secy_stat->octet_encrypted_cnt !=
733 				(uint16_t)(td->plain_pkt.len - 2 * RTE_ETHER_ADDR_LEN))
734 			return TEST_FAILED;
735 
736 		if (opts->check_auth_only_stats && secy_stat->octet_protected_cnt !=
737 				(uint16_t)(td->plain_pkt.len - 2 * RTE_ETHER_ADDR_LEN))
738 			return TEST_FAILED;
739 
740 
741 		memset(&sc_stat, 0, sizeof(struct rte_security_macsec_sc_stats));
742 		rte_security_macsec_sc_stats_get(ctx, tx_sc_id, RTE_SECURITY_MACSEC_DIR_TX,
743 						 &sc_stat);
744 
745 		if (opts->check_encap_stats && sc_stat.pkt_encrypt_cnt != 1)
746 			return TEST_FAILED;
747 
748 		if (opts->check_auth_only_stats && sc_stat.pkt_protected_cnt != 1)
749 			return TEST_FAILED;
750 
751 		memset(&sa_stat, 0, sizeof(struct rte_security_macsec_sa_stats));
752 		rte_security_macsec_sa_stats_get(ctx, tx_sa_id[0],
753 				RTE_SECURITY_MACSEC_DIR_TX, &sa_stat);
754 	}
755 
756 	return 0;
757 }
758 
759 static int
760 test_macsec_event_callback(uint16_t port_id, enum rte_eth_event_type type,
761 			   void *param, void *ret_param)
762 {
763 	struct mcs_err_vector *vector = (struct mcs_err_vector *)param;
764 	struct rte_eth_event_macsec_desc *event_desc = NULL;
765 
766 	RTE_SET_USED(port_id);
767 
768 	if (type != RTE_ETH_EVENT_MACSEC)
769 		return -1;
770 
771 	event_desc = ret_param;
772 	if (event_desc == NULL) {
773 		printf("Event descriptor not set\n");
774 		return -1;
775 	}
776 	vector->notify_event = true;
777 
778 	switch (event_desc->type) {
779 	case RTE_ETH_EVENT_MACSEC_SECTAG_VAL_ERR:
780 		vector->event = RTE_ETH_EVENT_MACSEC_SECTAG_VAL_ERR;
781 		switch (event_desc->subtype) {
782 		case RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_V_EQ1:
783 			vector->event_subtype = RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_V_EQ1;
784 			break;
785 		case RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_E_EQ0_C_EQ1:
786 			vector->event_subtype = RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_E_EQ0_C_EQ1;
787 			break;
788 		case RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_SL_GTE48:
789 			vector->event_subtype = RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_SL_GTE48;
790 			break;
791 		case RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_ES_EQ1_SC_EQ1:
792 			vector->event_subtype = RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_ES_EQ1_SC_EQ1;
793 			break;
794 		case RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_SC_EQ1_SCB_EQ1:
795 			vector->event_subtype = RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_SC_EQ1_SCB_EQ1;
796 			break;
797 		default:
798 			printf("\nUnknown Macsec event subtype: %d", event_desc->subtype);
799 		}
800 		break;
801 	case RTE_ETH_EVENT_MACSEC_RX_SA_PN_HARD_EXP:
802 		vector->event = RTE_ETH_EVENT_MACSEC_RX_SA_PN_HARD_EXP;
803 		break;
804 	case RTE_ETH_EVENT_MACSEC_RX_SA_PN_SOFT_EXP:
805 		vector->event = RTE_ETH_EVENT_MACSEC_RX_SA_PN_SOFT_EXP;
806 		break;
807 	case RTE_ETH_EVENT_MACSEC_TX_SA_PN_HARD_EXP:
808 		vector->event = RTE_ETH_EVENT_MACSEC_TX_SA_PN_HARD_EXP;
809 		break;
810 	case RTE_ETH_EVENT_MACSEC_TX_SA_PN_SOFT_EXP:
811 		vector->event = RTE_ETH_EVENT_MACSEC_TX_SA_PN_SOFT_EXP;
812 		break;
813 	case RTE_ETH_EVENT_MACSEC_SA_NOT_VALID:
814 		vector->event = RTE_ETH_EVENT_MACSEC_SA_NOT_VALID;
815 		break;
816 	default:
817 		printf("Invalid MACsec event reported\n");
818 		return -1;
819 	}
820 
821 	return 0;
822 }
823 
824 static int
825 test_macsec(const struct mcs_test_vector *td[], enum mcs_op op, const struct mcs_test_opts *opts)
826 {
827 	uint16_t rx_sa_id[MCS_MAX_FLOWS][RTE_SECURITY_MACSEC_NUM_AN] = {{0}};
828 	uint16_t tx_sa_id[MCS_MAX_FLOWS][2] = {{0}};
829 	uint16_t rx_sc_id[MCS_MAX_FLOWS] = {0};
830 	uint16_t tx_sc_id[MCS_MAX_FLOWS] = {0};
831 	void *rx_sess[MCS_MAX_FLOWS] = {0};
832 	void *tx_sess[MCS_MAX_FLOWS] = {0};
833 	struct rte_security_session_conf sess_conf = {0};
834 	struct rte_security_macsec_sa sa_conf = {0};
835 	struct rte_security_macsec_sc sc_conf = {0};
836 	struct rte_security_ctx *ctx;
837 	int nb_rx = 0, nb_sent;
838 	int i, j = 0, ret, id, an = 0;
839 	uint8_t tci_off;
840 
841 	memset(rx_pkts_burst, 0, sizeof(rx_pkts_burst[0]) * opts->nb_td);
842 
843 	ctx = (struct rte_security_ctx *)rte_eth_dev_get_sec_ctx(port_id);
844 	if (ctx == NULL) {
845 		printf("Ethernet device doesn't support security features.\n");
846 		return TEST_SKIPPED;
847 	}
848 
849 	tci_off = (opts->sectag_insert_mode == 1) ? RTE_ETHER_HDR_LEN :
850 			RTE_ETHER_HDR_LEN + (opts->nb_vlan * RTE_VLAN_HLEN);
851 
852 	for (i = 0, j = 0; i < opts->nb_td; i++) {
853 		if (op == MCS_DECAP || op == MCS_VERIFY_ONLY)
854 			tx_pkts_burst[j] = init_packet(mbufpool, td[i]->secure_pkt.data,
855 							td[i]->secure_pkt.len);
856 		else {
857 			tx_pkts_burst[j] = init_packet(mbufpool, td[i]->plain_pkt.data,
858 							td[i]->plain_pkt.len);
859 
860 			tx_pkts_burst[j]->ol_flags |= RTE_MBUF_F_TX_MACSEC;
861 		}
862 		if (tx_pkts_burst[j] == NULL) {
863 			while (j--)
864 				rte_pktmbuf_free(tx_pkts_burst[j]);
865 			ret = TEST_FAILED;
866 			goto out;
867 		}
868 		j++;
869 
870 		if (op == MCS_DECAP || op == MCS_ENCAP_DECAP ||
871 				op == MCS_VERIFY_ONLY || op == MCS_AUTH_VERIFY) {
872 			for (an = 0; an < RTE_SECURITY_MACSEC_NUM_AN; an++) {
873 				/* For simplicity, using same SA conf for all AN */
874 				fill_macsec_sa_conf(td[i], &sa_conf,
875 						RTE_SECURITY_MACSEC_DIR_RX, an, tci_off);
876 				id = rte_security_macsec_sa_create(ctx, &sa_conf);
877 				if (id < 0) {
878 					printf("MACsec SA create failed : %d.\n", id);
879 					return TEST_FAILED;
880 				}
881 				rx_sa_id[i][an] = (uint16_t)id;
882 			}
883 			fill_macsec_sc_conf(td[i], &sc_conf, opts,
884 					RTE_SECURITY_MACSEC_DIR_RX, rx_sa_id[i], tci_off);
885 			id = rte_security_macsec_sc_create(ctx, &sc_conf);
886 			if (id < 0) {
887 				printf("MACsec SC create failed : %d.\n", id);
888 				goto out;
889 			}
890 			rx_sc_id[i] = (uint16_t)id;
891 
892 			/* Create Inline IPsec session. */
893 			ret = fill_session_conf(td[i], port_id, opts, &sess_conf,
894 					RTE_SECURITY_MACSEC_DIR_RX, rx_sc_id[i], tci_off);
895 			if (ret)
896 				return TEST_FAILED;
897 
898 			rx_sess[i] = rte_security_session_create(ctx, &sess_conf,
899 					sess_pool);
900 			if (rx_sess[i] == NULL) {
901 				printf("SEC Session init failed.\n");
902 				return TEST_FAILED;
903 			}
904 			ret = create_default_flow(td[i], port_id,
905 					RTE_SECURITY_MACSEC_DIR_RX, rx_sess[i]);
906 			if (ret)
907 				goto out;
908 		}
909 		if (op == MCS_ENCAP || op == MCS_ENCAP_DECAP ||
910 				op == MCS_AUTH_ONLY || op == MCS_AUTH_VERIFY) {
911 			int id;
912 
913 			fill_macsec_sa_conf(td[i], &sa_conf,
914 					RTE_SECURITY_MACSEC_DIR_TX,
915 					td[i]->secure_pkt.data[tci_off] & RTE_MACSEC_AN_MASK,
916 					tci_off);
917 			id = rte_security_macsec_sa_create(ctx, &sa_conf);
918 			if (id < 0) {
919 				printf("MACsec SA create failed : %d.\n", id);
920 				return TEST_FAILED;
921 			}
922 			tx_sa_id[i][0] = (uint16_t)id;
923 			tx_sa_id[i][1] = MCS_INVALID_SA;
924 			fill_macsec_sc_conf(td[i], &sc_conf, opts,
925 					RTE_SECURITY_MACSEC_DIR_TX, tx_sa_id[i], tci_off);
926 			id = rte_security_macsec_sc_create(ctx, &sc_conf);
927 			if (id < 0) {
928 				printf("MACsec SC create failed : %d.\n", id);
929 				goto out;
930 			}
931 			tx_sc_id[i] = (uint16_t)id;
932 
933 			/* Create Inline IPsec session. */
934 			ret = fill_session_conf(td[i], port_id, opts, &sess_conf,
935 					RTE_SECURITY_MACSEC_DIR_TX, tx_sc_id[i], tci_off);
936 			if (ret)
937 				return TEST_FAILED;
938 
939 			tx_sess[i] = rte_security_session_create(ctx, &sess_conf,
940 					sess_pool);
941 			if (tx_sess[i] == NULL) {
942 				printf("SEC Session init failed.\n");
943 				return TEST_FAILED;
944 			}
945 			ret = create_default_flow(td[i], port_id,
946 					RTE_SECURITY_MACSEC_DIR_TX, tx_sess[i]);
947 			if (ret)
948 				goto out;
949 		}
950 	}
951 
952 	/* Send packet to ethdev for inline MACsec processing. */
953 	nb_sent = rte_eth_tx_burst(port_id, 0, tx_pkts_burst, j);
954 
955 	if (nb_sent != j) {
956 		printf("\nUnable to TX %d packets, sent: %i", j, nb_sent);
957 		for ( ; nb_sent < j; nb_sent++)
958 			rte_pktmbuf_free(tx_pkts_burst[nb_sent]);
959 		ret = TEST_FAILED;
960 		goto out;
961 	}
962 
963 	rte_pause();
964 
965 	/* Receive back packet on loopback interface. */
966 	do {
967 		nb_rx += rte_eth_rx_burst(port_id, 0,
968 				&rx_pkts_burst[nb_rx],
969 				nb_sent - nb_rx);
970 		if (nb_rx >= nb_sent)
971 			break;
972 		rte_delay_ms(1);
973 	} while (j++ < 5 && nb_rx == 0);
974 
975 	if (nb_rx != nb_sent) {
976 		printf("\nUnable to RX all %d packets, received(%i)",
977 				nb_sent, nb_rx);
978 		while (--nb_rx >= 0)
979 			rte_pktmbuf_free(rx_pkts_burst[nb_rx]);
980 		ret = TEST_FAILED;
981 		if (opts->check_sectag_interrupts == 1)
982 			ret = TEST_SUCCESS;
983 		goto out;
984 	}
985 
986 	for (i = 0; i < nb_rx; i++) {
987 		ret = test_macsec_post_process(rx_pkts_burst[i], td[i], op,
988 				opts->check_out_pkts_untagged);
989 		if (ret != TEST_SUCCESS) {
990 			for ( ; i < nb_rx; i++)
991 				rte_pktmbuf_free(rx_pkts_burst[i]);
992 			goto out;
993 		}
994 
995 		rte_pktmbuf_free(rx_pkts_burst[i]);
996 		rx_pkts_burst[i] = NULL;
997 	}
998 out:
999 	if (opts->check_out_pkts_toolong == 1 ||
1000 			opts->check_sa_not_in_use == 1 ||
1001 			opts->check_bad_tag_cnt == 1)
1002 		ret = TEST_SUCCESS;
1003 
1004 	for (i = 0; i < opts->nb_td; i++) {
1005 		if (opts->dump_all_stats) {
1006 			mcs_stats_dump(ctx, op,
1007 					rx_sess[i], tx_sess[i],
1008 					rx_sc_id[i], tx_sc_id[i],
1009 					rx_sa_id[i], tx_sa_id[i]);
1010 		} else {
1011 			if (ret == TEST_SUCCESS)
1012 				ret = mcs_stats_check(ctx, op, opts, td[i],
1013 					rx_sess[i], tx_sess[i],
1014 					rx_sc_id[i], tx_sc_id[i],
1015 					rx_sa_id[i], tx_sa_id[i]);
1016 		}
1017 	}
1018 
1019 	destroy_default_flow(port_id);
1020 
1021 	/* Destroy session so that other cases can create the session again */
1022 	for (i = 0; i < opts->nb_td; i++) {
1023 		if (op == MCS_ENCAP || op == MCS_ENCAP_DECAP ||
1024 				op == MCS_AUTH_ONLY || op == MCS_AUTH_VERIFY) {
1025 			rte_security_session_destroy(ctx, tx_sess[i]);
1026 			tx_sess[i] = NULL;
1027 			rte_security_macsec_sc_destroy(ctx, tx_sc_id[i],
1028 						RTE_SECURITY_MACSEC_DIR_TX);
1029 			rte_security_macsec_sa_destroy(ctx, tx_sa_id[i][0],
1030 						RTE_SECURITY_MACSEC_DIR_TX);
1031 		}
1032 		if (op == MCS_DECAP || op == MCS_ENCAP_DECAP ||
1033 				op == MCS_VERIFY_ONLY || op == MCS_AUTH_VERIFY) {
1034 			rte_security_session_destroy(ctx, rx_sess[i]);
1035 			rx_sess[i] = NULL;
1036 			rte_security_macsec_sc_destroy(ctx, rx_sc_id[i],
1037 						RTE_SECURITY_MACSEC_DIR_RX);
1038 			for (j = 0; j < RTE_SECURITY_MACSEC_NUM_AN; j++) {
1039 				rte_security_macsec_sa_destroy(ctx, rx_sa_id[i][j],
1040 						RTE_SECURITY_MACSEC_DIR_RX);
1041 			}
1042 		}
1043 	}
1044 
1045 	return ret;
1046 }
1047 
1048 static int
1049 test_inline_macsec_encap_all(const void *data __rte_unused)
1050 {
1051 	const struct mcs_test_vector *cur_td;
1052 	struct mcs_test_opts opts = {0};
1053 	int err, all_err = 0;
1054 	int i, size;
1055 
1056 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1057 	opts.encrypt = true;
1058 	opts.protect_frames = true;
1059 	opts.sa_in_use = 1;
1060 	opts.nb_td = 1;
1061 	opts.sectag_insert_mode = 1;
1062 	opts.mtu = RTE_ETHER_MTU;
1063 
1064 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1065 	for (i = 0; i < size; i++) {
1066 		cur_td = &list_mcs_cipher_vectors[i];
1067 		err = test_macsec(&cur_td, MCS_ENCAP, &opts);
1068 		if (err) {
1069 			printf("\nCipher Auth Encryption case %d failed", cur_td->test_idx);
1070 			err = -1;
1071 		} else {
1072 			printf("\nCipher Auth Encryption case %d Passed", cur_td->test_idx);
1073 			err = 0;
1074 		}
1075 		all_err += err;
1076 	}
1077 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1078 
1079 	return all_err;
1080 }
1081 
1082 static int
1083 test_inline_macsec_decap_all(const void *data __rte_unused)
1084 {
1085 	const struct mcs_test_vector *cur_td;
1086 	struct mcs_test_opts opts = {0};
1087 	int err, all_err = 0;
1088 	int i, size;
1089 
1090 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1091 	opts.sa_in_use = 1;
1092 	opts.nb_td = 1;
1093 	opts.sectag_insert_mode = 1;
1094 	opts.mtu = RTE_ETHER_MTU;
1095 
1096 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1097 	for (i = 0; i < size; i++) {
1098 		cur_td = &list_mcs_cipher_vectors[i];
1099 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1100 		if (err) {
1101 			printf("\nCipher Auth Decryption case %d failed", cur_td->test_idx);
1102 			err = -1;
1103 		} else {
1104 			printf("\nCipher Auth Decryption case %d Passed", cur_td->test_idx);
1105 			err = 0;
1106 		}
1107 		all_err += err;
1108 	}
1109 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1110 
1111 	return all_err;
1112 }
1113 
1114 static int
1115 test_inline_macsec_auth_only_all(const void *data __rte_unused)
1116 {
1117 	const struct mcs_test_vector *cur_td;
1118 	struct mcs_test_opts opts = {0};
1119 	int err, all_err = 0;
1120 	int i, size;
1121 
1122 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1123 	opts.protect_frames = true;
1124 	opts.sa_in_use = 1;
1125 	opts.nb_td = 1;
1126 	opts.sectag_insert_mode = 1;
1127 	opts.mtu = RTE_ETHER_MTU;
1128 
1129 	size = (sizeof(list_mcs_integrity_vectors) / sizeof((list_mcs_integrity_vectors)[0]));
1130 
1131 	for (i = 0; i < size; i++) {
1132 		cur_td = &list_mcs_integrity_vectors[i];
1133 		err = test_macsec(&cur_td, MCS_AUTH_ONLY, &opts);
1134 		if (err) {
1135 			printf("\nAuth Generate case %d failed", cur_td->test_idx);
1136 			err = -1;
1137 		} else {
1138 			printf("\nAuth Generate case %d Passed", cur_td->test_idx);
1139 			err = 0;
1140 		}
1141 		all_err += err;
1142 	}
1143 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1144 
1145 	return all_err;
1146 }
1147 
1148 static int
1149 test_inline_macsec_verify_only_all(const void *data __rte_unused)
1150 {
1151 	const struct mcs_test_vector *cur_td;
1152 	struct mcs_test_opts opts = {0};
1153 	int err, all_err = 0;
1154 	int i, size;
1155 
1156 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1157 	opts.sa_in_use = 1;
1158 	opts.nb_td = 1;
1159 	opts.sectag_insert_mode = 1;
1160 	opts.mtu = RTE_ETHER_MTU;
1161 
1162 	size = (sizeof(list_mcs_integrity_vectors) / sizeof((list_mcs_integrity_vectors)[0]));
1163 
1164 	for (i = 0; i < size; i++) {
1165 		cur_td = &list_mcs_integrity_vectors[i];
1166 		err = test_macsec(&cur_td, MCS_VERIFY_ONLY, &opts);
1167 		if (err) {
1168 			printf("\nAuth Verify case %d failed", cur_td->test_idx);
1169 			err = -1;
1170 		} else {
1171 			printf("\nAuth Verify case %d Passed", cur_td->test_idx);
1172 			err = 0;
1173 		}
1174 		all_err += err;
1175 	}
1176 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1177 
1178 	return all_err;
1179 }
1180 
1181 static int
1182 test_inline_macsec_encap_decap_all(const void *data __rte_unused)
1183 {
1184 	const struct mcs_test_vector *cur_td;
1185 	struct mcs_test_opts opts = {0};
1186 	int err, all_err = 0;
1187 	int i, size;
1188 
1189 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1190 	opts.encrypt = true;
1191 	opts.protect_frames = true;
1192 	opts.sa_in_use = 1;
1193 	opts.nb_td = 1;
1194 	opts.sectag_insert_mode = 1;
1195 	opts.mtu = RTE_ETHER_MTU;
1196 
1197 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1198 
1199 	for (i = 0; i < size; i++) {
1200 		cur_td = &list_mcs_cipher_vectors[i];
1201 		err = test_macsec(&cur_td, MCS_ENCAP_DECAP, &opts);
1202 		if (err) {
1203 			printf("\nCipher Auth Encap-decap case %d failed", cur_td->test_idx);
1204 			err = -1;
1205 		} else {
1206 			printf("\nCipher Auth Encap-decap case %d Passed", cur_td->test_idx);
1207 			err = 0;
1208 		}
1209 		all_err += err;
1210 	}
1211 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1212 
1213 	return all_err;
1214 }
1215 
1216 
1217 static int
1218 test_inline_macsec_auth_verify_all(const void *data __rte_unused)
1219 {
1220 	const struct mcs_test_vector *cur_td;
1221 	struct mcs_test_opts opts = {0};
1222 	int err, all_err = 0;
1223 	int i, size;
1224 
1225 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1226 	opts.protect_frames = true;
1227 	opts.sa_in_use = 1;
1228 	opts.nb_td = 1;
1229 	opts.sectag_insert_mode = 1;
1230 	opts.mtu = RTE_ETHER_MTU;
1231 
1232 	size = (sizeof(list_mcs_integrity_vectors) / sizeof((list_mcs_integrity_vectors)[0]));
1233 
1234 	for (i = 0; i < size; i++) {
1235 		cur_td = &list_mcs_integrity_vectors[i];
1236 		err = test_macsec(&cur_td, MCS_AUTH_VERIFY, &opts);
1237 		if (err) {
1238 			printf("\nAuth Generate + Verify case %d failed", cur_td->test_idx);
1239 			err = -1;
1240 		} else {
1241 			printf("\nAuth Generate + Verify case %d Passed", cur_td->test_idx);
1242 			err = 0;
1243 		}
1244 		all_err += err;
1245 	}
1246 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1247 
1248 	return all_err;
1249 }
1250 
1251 static int
1252 test_inline_macsec_multi_flow(const void *data __rte_unused)
1253 {
1254 	const struct mcs_test_vector *tv[MCS_MAX_FLOWS];
1255 	struct mcs_test_vector iter[MCS_MAX_FLOWS];
1256 	struct mcs_test_opts opts = {0};
1257 	int i, err;
1258 
1259 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1260 	opts.encrypt = true;
1261 	opts.protect_frames = true;
1262 	opts.sa_in_use = 1;
1263 	opts.nb_td = MCS_MAX_FLOWS;
1264 	opts.sectag_insert_mode = 1;
1265 	opts.mtu = RTE_ETHER_MTU;
1266 
1267 	for (i = 0; i < MCS_MAX_FLOWS; i++) {
1268 		memcpy(&iter[i].sa_key.data, sa_key, MCS_MULTI_FLOW_TD_KEY_SZ);
1269 		memcpy(&iter[i].plain_pkt.data, eth_addrs[i], 2 * RTE_ETHER_ADDR_LEN);
1270 		memcpy(&iter[i].plain_pkt.data[2 * RTE_ETHER_ADDR_LEN], plain_user_data,
1271 		       MCS_MULTI_FLOW_TD_PLAIN_DATA_SZ);
1272 		memcpy(&iter[i].secure_pkt.data, eth_addrs[i], 2 * RTE_ETHER_ADDR_LEN);
1273 		memcpy(&iter[i].secure_pkt.data[2 * RTE_ETHER_ADDR_LEN], secure_user_data,
1274 		       MCS_MULTI_FLOW_TD_SECURE_DATA_SZ);
1275 		iter[i].sa_key.len = MCS_MULTI_FLOW_TD_KEY_SZ;
1276 		iter[i].plain_pkt.len = MCS_MULTI_FLOW_TD_PLAIN_DATA_SZ +
1277 					(2 * RTE_ETHER_ADDR_LEN);
1278 		iter[i].secure_pkt.len = MCS_MULTI_FLOW_TD_SECURE_DATA_SZ +
1279 					(2 * RTE_ETHER_ADDR_LEN);
1280 		iter[i].alg = RTE_SECURITY_MACSEC_ALG_GCM_128;
1281 		iter[i].ssci = 0x0;
1282 		iter[i].xpn = 0x0;
1283 		tv[i] = (const struct mcs_test_vector *)&iter[i];
1284 	}
1285 	err = test_macsec(tv, MCS_ENCAP_DECAP, &opts);
1286 	if (err) {
1287 		printf("\nCipher Auth Encryption multi flow failed");
1288 		err = -1;
1289 	} else {
1290 		printf("\nCipher Auth Encryption multi flow Passed");
1291 		err = 0;
1292 	}
1293 	return err;
1294 }
1295 
1296 static int
1297 test_inline_macsec_with_vlan(const void *data __rte_unused)
1298 {
1299 	const struct mcs_test_vector *cur_td;
1300 	struct mcs_test_opts opts = {0};
1301 	int err, all_err = 0;
1302 	int i, size;
1303 
1304 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1305 	opts.protect_frames = true;
1306 	opts.sa_in_use = 1;
1307 	opts.nb_td = 1;
1308 	opts.mtu = RTE_ETHER_MTU;
1309 
1310 	size = (sizeof(list_mcs_vlan_vectors) / sizeof((list_mcs_vlan_vectors)[0]));
1311 
1312 	for (i = 0; i < size; i++) {
1313 		cur_td = &list_mcs_vlan_vectors[i];
1314 		if (i == 0) {
1315 			opts.sectag_insert_mode = 1;
1316 		} else if (i == 1) {
1317 			opts.sectag_insert_mode = 0; /* offset from special E-type */
1318 			opts.nb_vlan = 1;
1319 		} else if (i == 2) {
1320 			opts.sectag_insert_mode = 0; /* offset from special E-type */
1321 			opts.nb_vlan = 2;
1322 		}
1323 		err = test_macsec(&cur_td, MCS_ENCAP, &opts);
1324 		if (err) {
1325 			printf("\n VLAN Encap case %d failed", cur_td->test_idx);
1326 			err = -1;
1327 		} else {
1328 			printf("\n VLAN Encap case %d passed", cur_td->test_idx);
1329 			err = 0;
1330 		}
1331 		all_err += err;
1332 	}
1333 	for (i = 0; i < size; i++) {
1334 		cur_td = &list_mcs_vlan_vectors[i];
1335 		if (i == 0) {
1336 			opts.sectag_insert_mode = 1;
1337 		} else if (i == 1) {
1338 			opts.sectag_insert_mode = 0; /* offset from special E-type */
1339 			opts.nb_vlan = 1;
1340 		} else if (i == 2) {
1341 			opts.sectag_insert_mode = 0; /* offset from special E-type */
1342 			opts.nb_vlan = 2;
1343 		}
1344 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1345 		if (err) {
1346 			printf("\n VLAN Decap case %d failed", cur_td->test_idx);
1347 			err = -1;
1348 		} else {
1349 			printf("\n VLAN Decap case %d passed", cur_td->test_idx);
1350 			err = 0;
1351 		}
1352 		all_err += err;
1353 	}
1354 
1355 	printf("\n%s: Success: %d, Failure: %d\n", __func__, (2 * size) + all_err, -all_err);
1356 	return all_err;
1357 }
1358 
1359 static int
1360 test_inline_macsec_pkt_drop(const void *data __rte_unused)
1361 {
1362 	const struct mcs_test_vector *cur_td;
1363 	struct mcs_test_opts opts = {0};
1364 	int err, all_err = 0;
1365 	int i, size;
1366 
1367 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1368 	opts.encrypt = true;
1369 	opts.protect_frames = true;
1370 	opts.sa_in_use = 1;
1371 	opts.nb_td = 1;
1372 	opts.sectag_insert_mode = 1;
1373 	opts.mtu = RTE_ETHER_MTU;
1374 
1375 	size = (sizeof(list_mcs_err_cipher_vectors) / sizeof((list_mcs_err_cipher_vectors)[0]));
1376 
1377 	for (i = 0; i < size; i++) {
1378 		cur_td = &list_mcs_err_cipher_vectors[i];
1379 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1380 		if (err) {
1381 			printf("\nPacket drop case %d passed", cur_td->test_idx);
1382 			err = 0;
1383 		} else {
1384 			printf("\nPacket drop case %d failed", cur_td->test_idx);
1385 			err = -1;
1386 		}
1387 		all_err += err;
1388 	}
1389 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1390 
1391 	return all_err;
1392 }
1393 
1394 static int
1395 test_inline_macsec_untagged_rx(const void *data __rte_unused)
1396 {
1397 	const struct mcs_test_vector *cur_td;
1398 	struct mcs_test_opts opts = {0};
1399 	int err, all_err = 0;
1400 	int i, size;
1401 
1402 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1403 	opts.sa_in_use = 1;
1404 	opts.nb_td = 1;
1405 	opts.sectag_insert_mode = 1;
1406 	opts.mtu = RTE_ETHER_MTU;
1407 	opts.check_untagged_rx = 1;
1408 
1409 	size = (sizeof(list_mcs_untagged_cipher_vectors) /
1410 		sizeof((list_mcs_untagged_cipher_vectors)[0]));
1411 
1412 	for (i = 0; i < size; i++) {
1413 		cur_td = &list_mcs_untagged_cipher_vectors[i];
1414 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1415 		if (err)
1416 			err = 0;
1417 		else
1418 			err = -1;
1419 
1420 		all_err += err;
1421 	}
1422 
1423 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_NO_DISCARD;
1424 	for (i = 0; i < size; i++) {
1425 		cur_td = &list_mcs_untagged_cipher_vectors[i];
1426 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1427 		if (err)
1428 			err = 0;
1429 		else
1430 			err = -1;
1431 
1432 		all_err += err;
1433 	}
1434 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1435 
1436 	return all_err;
1437 }
1438 
1439 static int
1440 test_inline_macsec_bad_tag_rx(const void *data __rte_unused)
1441 {
1442 	const struct mcs_test_vector *cur_td;
1443 	struct mcs_test_opts opts = {0};
1444 	int err, all_err = 0;
1445 	int i, size;
1446 
1447 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1448 	opts.protect_frames = true;
1449 	opts.sa_in_use = 1;
1450 	opts.nb_td = 1;
1451 	opts.sectag_insert_mode = 1;
1452 	opts.mtu = RTE_ETHER_MTU;
1453 	opts.check_bad_tag_cnt = 1;
1454 
1455 	size = (sizeof(list_mcs_bad_tag_vectors) / sizeof((list_mcs_bad_tag_vectors)[0]));
1456 
1457 	for (i = 0; i < size; i++) {
1458 		cur_td = &list_mcs_bad_tag_vectors[i];
1459 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1460 		if (err)
1461 			err = -1;
1462 		else
1463 			err = 0;
1464 
1465 		all_err += err;
1466 	}
1467 
1468 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1469 
1470 	return all_err;
1471 }
1472 
1473 static int
1474 test_inline_macsec_sa_not_in_use(const void *data __rte_unused)
1475 {
1476 	const struct mcs_test_vector *cur_td;
1477 	struct mcs_test_opts opts = {0};
1478 	int err, all_err = 0;
1479 	int i, size;
1480 
1481 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1482 	opts.protect_frames = true;
1483 	opts.sa_in_use = 0;
1484 	opts.nb_td = 1;
1485 	opts.sectag_insert_mode = 1;
1486 	opts.mtu = RTE_ETHER_MTU;
1487 	opts.check_sa_not_in_use = 1;
1488 
1489 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1490 
1491 	for (i = 0; i < size; i++) {
1492 		cur_td = &list_mcs_cipher_vectors[i];
1493 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1494 		if (err)
1495 			err = -1;
1496 		else
1497 			err = 0;
1498 
1499 		all_err += err;
1500 	}
1501 
1502 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1503 
1504 	return all_err;
1505 }
1506 
1507 static int
1508 test_inline_macsec_decap_stats(const void *data __rte_unused)
1509 {
1510 	const struct mcs_test_vector *cur_td;
1511 	struct mcs_test_opts opts = {0};
1512 	int err, all_err = 0;
1513 	int i, size;
1514 
1515 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1516 	opts.protect_frames = true;
1517 	opts.sa_in_use = 1;
1518 	opts.nb_td = 1;
1519 	opts.sectag_insert_mode = 1;
1520 	opts.mtu = RTE_ETHER_MTU;
1521 	opts.check_decap_stats = 1;
1522 
1523 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1524 
1525 	for (i = 0; i < size; i++) {
1526 		cur_td = &list_mcs_cipher_vectors[i];
1527 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1528 		if (err) {
1529 			printf("\nDecap stats case %d failed", cur_td->test_idx);
1530 			err = -1;
1531 		} else {
1532 			printf("\nDecap stats case %d passed", cur_td->test_idx);
1533 			err = 0;
1534 		}
1535 		all_err += err;
1536 	}
1537 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1538 
1539 	return all_err;
1540 }
1541 
1542 static int
1543 test_inline_macsec_verify_only_stats(const void *data __rte_unused)
1544 {
1545 	const struct mcs_test_vector *cur_td;
1546 	struct mcs_test_opts opts = {0};
1547 	int err, all_err = 0;
1548 	int i, size;
1549 
1550 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1551 	opts.protect_frames = true;
1552 	opts.sa_in_use = 1;
1553 	opts.nb_td = 1;
1554 	opts.sectag_insert_mode = 1;
1555 	opts.mtu = RTE_ETHER_MTU;
1556 	opts.check_verify_only_stats = 1;
1557 
1558 	size = (sizeof(list_mcs_integrity_vectors) / sizeof((list_mcs_integrity_vectors)[0]));
1559 
1560 	for (i = 0; i < size; i++) {
1561 		cur_td = &list_mcs_integrity_vectors[i];
1562 		err = test_macsec(&cur_td, MCS_VERIFY_ONLY, &opts);
1563 		if (err) {
1564 			printf("\nVerify only stats case %d failed", cur_td->test_idx);
1565 			err = -1;
1566 		} else {
1567 			printf("\nVerify only stats case %d Passed", cur_td->test_idx);
1568 			err = 0;
1569 		}
1570 		all_err += err;
1571 	}
1572 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1573 
1574 	return all_err;
1575 }
1576 
1577 static int
1578 test_inline_macsec_pkts_invalid_stats(const void *data __rte_unused)
1579 {
1580 	const struct mcs_test_vector *cur_td;
1581 	struct mcs_test_opts opts = {0};
1582 	int err, all_err = 0;
1583 	int i, size;
1584 
1585 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1586 	opts.protect_frames = true;
1587 	opts.sa_in_use = 1;
1588 	opts.nb_td = 1;
1589 	opts.sectag_insert_mode = 1;
1590 	opts.mtu = RTE_ETHER_MTU;
1591 
1592 	size = (sizeof(list_mcs_err_cipher_vectors) / sizeof((list_mcs_err_cipher_vectors)[0]));
1593 
1594 	for (i = 0; i < size; i++) {
1595 		cur_td = &list_mcs_err_cipher_vectors[i];
1596 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1597 		if (err)
1598 			err = 0;
1599 		else
1600 			err = -1;
1601 
1602 		all_err += err;
1603 	}
1604 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1605 	return all_err;
1606 }
1607 
1608 static int
1609 test_inline_macsec_pkts_unchecked_stats(const void *data __rte_unused)
1610 {
1611 	const struct mcs_test_vector *cur_td;
1612 	struct mcs_test_opts opts = {0};
1613 	int err, all_err = 0;
1614 	int i, size;
1615 
1616 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_DISABLE;
1617 	opts.protect_frames = true;
1618 	opts.sa_in_use = 1;
1619 	opts.nb_td = 1;
1620 	opts.sectag_insert_mode = 1;
1621 	opts.mtu = RTE_ETHER_MTU;
1622 	opts.check_pkts_unchecked_stats = 1;
1623 
1624 	size = (sizeof(list_mcs_integrity_vectors) / sizeof((list_mcs_integrity_vectors)[0]));
1625 
1626 	for (i = 0; i < size; i++) {
1627 		cur_td = &list_mcs_integrity_vectors[i];
1628 		err = test_macsec(&cur_td, MCS_VERIFY_ONLY, &opts);
1629 		if (err)
1630 			err = -1;
1631 		else
1632 			err = 0;
1633 
1634 		all_err += err;
1635 	}
1636 
1637 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1638 	return all_err;
1639 }
1640 
1641 static int
1642 test_inline_macsec_out_pkts_untagged(const void *data __rte_unused)
1643 {
1644 	const struct mcs_test_vector *cur_td;
1645 	struct mcs_test_opts opts = {0};
1646 	int err, all_err = 0;
1647 	int i, size;
1648 
1649 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1650 	opts.encrypt = false;
1651 	opts.protect_frames = false;
1652 	opts.sa_in_use = 1;
1653 	opts.nb_td = 1;
1654 	opts.sectag_insert_mode = 1;
1655 	opts.mtu = RTE_ETHER_MTU;
1656 	opts.check_out_pkts_untagged = 1;
1657 
1658 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1659 	for (i = 0; i < size; i++) {
1660 		cur_td = &list_mcs_cipher_vectors[i];
1661 		err = test_macsec(&cur_td, MCS_ENCAP, &opts);
1662 		if (err)
1663 			err = -1;
1664 		else
1665 			err = 0;
1666 
1667 		all_err += err;
1668 	}
1669 
1670 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1671 	return all_err;
1672 }
1673 
1674 static int
1675 test_inline_macsec_out_pkts_toolong(const void *data __rte_unused)
1676 {
1677 	const struct mcs_test_vector *cur_td;
1678 	struct mcs_test_opts opts = {0};
1679 	int err, all_err = 0;
1680 	int i, size;
1681 
1682 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_NO_DISCARD;
1683 	opts.encrypt = true;
1684 	opts.protect_frames = true;
1685 	opts.sa_in_use = 1;
1686 	opts.nb_td = 1;
1687 	opts.sectag_insert_mode = 1;
1688 	opts.mtu = 50;
1689 	opts.check_out_pkts_toolong = 1;
1690 
1691 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1692 	for (i = 0; i < size; i++) {
1693 		cur_td = &list_mcs_cipher_vectors[i];
1694 		err = test_macsec(&cur_td, MCS_ENCAP, &opts);
1695 		if (err)
1696 			err = -1;
1697 		else
1698 			err = 0;
1699 
1700 		all_err += err;
1701 	}
1702 
1703 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1704 	return all_err;
1705 }
1706 
1707 static int
1708 test_inline_macsec_encap_stats(const void *data __rte_unused)
1709 {
1710 	const struct mcs_test_vector *cur_td;
1711 	struct mcs_test_opts opts = {0};
1712 	int err, all_err = 0;
1713 	int i, size;
1714 
1715 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1716 	opts.encrypt = true;
1717 	opts.protect_frames = true;
1718 	opts.sa_in_use = 1;
1719 	opts.nb_td = 1;
1720 	opts.sectag_insert_mode = 1;
1721 	opts.mtu = RTE_ETHER_MTU;
1722 	opts.check_encap_stats = 1;
1723 
1724 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1725 	for (i = 0; i < size; i++) {
1726 		cur_td = &list_mcs_cipher_vectors[i];
1727 		err = test_macsec(&cur_td, MCS_ENCAP, &opts);
1728 		if (err)
1729 			err = -1;
1730 		else
1731 			err = 0;
1732 		all_err += err;
1733 	}
1734 
1735 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1736 	return all_err;
1737 }
1738 
1739 static int
1740 test_inline_macsec_auth_only_stats(const void *data __rte_unused)
1741 {
1742 	const struct mcs_test_vector *cur_td;
1743 	struct mcs_test_opts opts = {0};
1744 	int err, all_err = 0;
1745 	int i, size;
1746 
1747 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1748 	opts.protect_frames = true;
1749 	opts.sa_in_use = 1;
1750 	opts.nb_td = 1;
1751 	opts.sectag_insert_mode = 1;
1752 	opts.mtu = RTE_ETHER_MTU;
1753 	opts.check_auth_only_stats = 1;
1754 
1755 	size = (sizeof(list_mcs_integrity_vectors) / sizeof((list_mcs_integrity_vectors)[0]));
1756 
1757 	for (i = 0; i < size; i++) {
1758 		cur_td = &list_mcs_integrity_vectors[i];
1759 		err = test_macsec(&cur_td, MCS_AUTH_ONLY, &opts);
1760 		if (err)
1761 			err = -1;
1762 		else
1763 			err = 0;
1764 		all_err += err;
1765 	}
1766 
1767 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1768 	return all_err;
1769 }
1770 
1771 static int
1772 test_inline_macsec_interrupts_all(const void *data __rte_unused)
1773 {
1774 	struct mcs_err_vector err_vector = {0};
1775 	const struct mcs_test_vector *cur_td;
1776 	struct mcs_test_opts opts = {0};
1777 	int i, size;
1778 	int err, all_err = 0;
1779 	enum rte_eth_event_macsec_subtype subtype[] =  {
1780 		RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_V_EQ1,
1781 		RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_E_EQ0_C_EQ1,
1782 		RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_SL_GTE48,
1783 		RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_ES_EQ1_SC_EQ1,
1784 		RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_SC_EQ1_SCB_EQ1,
1785 	};
1786 
1787 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1788 	opts.protect_frames = true;
1789 	opts.sa_in_use = 1;
1790 	opts.nb_td = 1;
1791 	opts.sectag_insert_mode = 1;
1792 	opts.mtu = RTE_ETHER_MTU;
1793 	opts.check_sectag_interrupts = 1;
1794 
1795 	err_vector.event = RTE_ETH_EVENT_MACSEC_UNKNOWN;
1796 	err_vector.event_subtype = RTE_ETH_SUBEVENT_MACSEC_UNKNOWN;
1797 	rte_eth_dev_callback_register(port_id, RTE_ETH_EVENT_MACSEC,
1798 			test_macsec_event_callback, &err_vector);
1799 
1800 	size = (sizeof(list_mcs_intr_test_vectors) / sizeof((list_mcs_intr_test_vectors)[0]));
1801 
1802 	for (i = 0; i < size; i++) {
1803 		cur_td = &list_mcs_intr_test_vectors[i];
1804 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1805 		if ((err_vector.event == RTE_ETH_EVENT_MACSEC_SECTAG_VAL_ERR) &&
1806 		    (err_vector.event_subtype == subtype[i])) {
1807 			printf("\nSectag val err interrupt test case %d passed",
1808 			       cur_td->test_idx);
1809 			err = 0;
1810 		} else {
1811 			printf("\nSectag val err interrupt test case %d failed",
1812 			       cur_td->test_idx);
1813 			err = -1;
1814 		}
1815 		all_err += err;
1816 	}
1817 	rte_eth_dev_callback_unregister(port_id, RTE_ETH_EVENT_MACSEC,
1818 			test_macsec_event_callback, &err_vector);
1819 
1820 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1821 	return all_err;
1822 }
1823 
1824 static int
1825 ut_setup_inline_macsec(void)
1826 {
1827 	int ret;
1828 
1829 	/* Start device */
1830 	ret = rte_eth_dev_start(port_id);
1831 	if (ret < 0) {
1832 		printf("rte_eth_dev_start: err=%d, port=%d\n",
1833 			ret, port_id);
1834 		return ret;
1835 	}
1836 	/* always enable promiscuous */
1837 	ret = rte_eth_promiscuous_enable(port_id);
1838 	if (ret != 0) {
1839 		printf("rte_eth_promiscuous_enable: err=%s, port=%d\n",
1840 			rte_strerror(-ret), port_id);
1841 		return ret;
1842 	}
1843 
1844 	check_all_ports_link_status(1, RTE_PORT_ALL);
1845 
1846 	return 0;
1847 }
1848 
1849 static void
1850 ut_teardown_inline_macsec(void)
1851 {
1852 	uint16_t portid;
1853 	int ret;
1854 
1855 	/* port tear down */
1856 	RTE_ETH_FOREACH_DEV(portid) {
1857 		ret = rte_eth_dev_stop(portid);
1858 		if (ret != 0)
1859 			printf("rte_eth_dev_stop: err=%s, port=%u\n",
1860 			       rte_strerror(-ret), portid);
1861 
1862 	}
1863 }
1864 
1865 static int
1866 inline_macsec_testsuite_setup(void)
1867 {
1868 	uint16_t nb_rxd;
1869 	uint16_t nb_txd;
1870 	uint16_t nb_ports;
1871 	int ret;
1872 	uint16_t nb_rx_queue = 1, nb_tx_queue = 1;
1873 
1874 	printf("Start inline MACsec test.\n");
1875 
1876 	nb_ports = rte_eth_dev_count_avail();
1877 	if (nb_ports < NB_ETHPORTS_USED) {
1878 		printf("At least %u port(s) used for test\n",
1879 		       NB_ETHPORTS_USED);
1880 		return TEST_SKIPPED;
1881 	}
1882 
1883 	ret = init_mempools(NB_MBUF);
1884 	if (ret)
1885 		return ret;
1886 
1887 	if (tx_pkts_burst == NULL) {
1888 		tx_pkts_burst = (struct rte_mbuf **)rte_calloc("tx_buff",
1889 					  MAX_TRAFFIC_BURST,
1890 					  sizeof(void *),
1891 					  RTE_CACHE_LINE_SIZE);
1892 		if (!tx_pkts_burst)
1893 			return TEST_FAILED;
1894 
1895 		rx_pkts_burst = (struct rte_mbuf **)rte_calloc("rx_buff",
1896 					  MAX_TRAFFIC_BURST,
1897 					  sizeof(void *),
1898 					  RTE_CACHE_LINE_SIZE);
1899 		if (!rx_pkts_burst)
1900 			return TEST_FAILED;
1901 	}
1902 
1903 	printf("Generate %d packets\n", MAX_TRAFFIC_BURST);
1904 
1905 	nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
1906 	nb_txd = RTE_TEST_TX_DESC_DEFAULT;
1907 
1908 	/* configuring port 0 for the test is enough */
1909 	port_id = 0;
1910 	/* port configure */
1911 	ret = rte_eth_dev_configure(port_id, nb_rx_queue,
1912 				    nb_tx_queue, &port_conf);
1913 	if (ret < 0) {
1914 		printf("Cannot configure device: err=%d, port=%d\n",
1915 			 ret, port_id);
1916 		return ret;
1917 	}
1918 	ret = rte_eth_macaddr_get(port_id, &ports_eth_addr[port_id]);
1919 	if (ret < 0) {
1920 		printf("Cannot get mac address: err=%d, port=%d\n",
1921 			 ret, port_id);
1922 		return ret;
1923 	}
1924 	printf("Port %u ", port_id);
1925 	print_ethaddr("Address:", &ports_eth_addr[port_id]);
1926 	printf("\n");
1927 
1928 	/* tx queue setup */
1929 	ret = rte_eth_tx_queue_setup(port_id, 0, nb_txd,
1930 				     SOCKET_ID_ANY, &tx_conf);
1931 	if (ret < 0) {
1932 		printf("rte_eth_tx_queue_setup: err=%d, port=%d\n",
1933 				ret, port_id);
1934 		return ret;
1935 	}
1936 	/* rx queue steup */
1937 	ret = rte_eth_rx_queue_setup(port_id, 0, nb_rxd, SOCKET_ID_ANY,
1938 				     &rx_conf, mbufpool);
1939 	if (ret < 0) {
1940 		printf("rte_eth_rx_queue_setup: err=%d, port=%d\n",
1941 				ret, port_id);
1942 		return ret;
1943 	}
1944 
1945 	return 0;
1946 }
1947 
1948 static void
1949 inline_macsec_testsuite_teardown(void)
1950 {
1951 	uint16_t portid;
1952 	int ret;
1953 
1954 	/* port tear down */
1955 	RTE_ETH_FOREACH_DEV(portid) {
1956 		ret = rte_eth_dev_reset(portid);
1957 		if (ret != 0)
1958 			printf("rte_eth_dev_reset: err=%s, port=%u\n",
1959 			       rte_strerror(-ret), port_id);
1960 	}
1961 	rte_free(tx_pkts_burst);
1962 	rte_free(rx_pkts_burst);
1963 }
1964 
1965 
1966 static struct unit_test_suite inline_macsec_testsuite  = {
1967 	.suite_name = "Inline MACsec Ethernet Device Unit Test Suite",
1968 	.unit_test_cases = {
1969 		TEST_CASE_NAMED_ST(
1970 			"MACsec Encap + decap Multi flow",
1971 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1972 			test_inline_macsec_multi_flow),
1973 		TEST_CASE_NAMED_ST(
1974 			"MACsec encap(Cipher+Auth) known vector",
1975 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1976 			test_inline_macsec_encap_all),
1977 		TEST_CASE_NAMED_ST(
1978 			"MACsec decap(De-cipher+verify) known vector",
1979 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1980 			test_inline_macsec_decap_all),
1981 		TEST_CASE_NAMED_ST(
1982 			"MACsec auth only known vector",
1983 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1984 			test_inline_macsec_auth_only_all),
1985 		TEST_CASE_NAMED_ST(
1986 			"MACsec verify only known vector",
1987 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1988 			test_inline_macsec_verify_only_all),
1989 		TEST_CASE_NAMED_ST(
1990 			"MACsec encap + decap known vector",
1991 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1992 			test_inline_macsec_encap_decap_all),
1993 		TEST_CASE_NAMED_ST(
1994 			"MACsec auth + verify known vector",
1995 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1996 			test_inline_macsec_auth_verify_all),
1997 		TEST_CASE_NAMED_ST(
1998 			"MACsec Encap and decap with VLAN",
1999 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2000 			test_inline_macsec_with_vlan),
2001 		TEST_CASE_NAMED_ST(
2002 			"MACsec packet drop",
2003 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2004 			test_inline_macsec_pkt_drop),
2005 		TEST_CASE_NAMED_ST(
2006 			"MACsec untagged Rx",
2007 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2008 			test_inline_macsec_untagged_rx),
2009 		TEST_CASE_NAMED_ST(
2010 			"MACsec bad tag Rx",
2011 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2012 			test_inline_macsec_bad_tag_rx),
2013 		TEST_CASE_NAMED_ST(
2014 			"MACsec SA not in use",
2015 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2016 			test_inline_macsec_sa_not_in_use),
2017 		TEST_CASE_NAMED_ST(
2018 			"MACsec decap stats",
2019 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2020 			test_inline_macsec_decap_stats),
2021 		TEST_CASE_NAMED_ST(
2022 			"MACsec verify only stats",
2023 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2024 			test_inline_macsec_verify_only_stats),
2025 		TEST_CASE_NAMED_ST(
2026 			"MACsec pkts invalid stats",
2027 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2028 			test_inline_macsec_pkts_invalid_stats),
2029 		TEST_CASE_NAMED_ST(
2030 			"MACsec pkts unchecked stats",
2031 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2032 			test_inline_macsec_pkts_unchecked_stats),
2033 		TEST_CASE_NAMED_ST(
2034 			"MACsec out pkts untagged",
2035 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2036 			test_inline_macsec_out_pkts_untagged),
2037 		TEST_CASE_NAMED_ST(
2038 			"MACsec out pkts too long",
2039 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2040 			test_inline_macsec_out_pkts_toolong),
2041 		TEST_CASE_NAMED_ST(
2042 			"MACsec Encap stats",
2043 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2044 			test_inline_macsec_encap_stats),
2045 		TEST_CASE_NAMED_ST(
2046 			"MACsec auth only stats",
2047 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2048 			test_inline_macsec_auth_only_stats),
2049 		TEST_CASE_NAMED_ST(
2050 			"MACsec interrupts all",
2051 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
2052 			test_inline_macsec_interrupts_all),
2053 
2054 		TEST_CASES_END() /**< NULL terminate unit test array */
2055 	},
2056 };
2057 
2058 static int
2059 test_inline_macsec(void)
2060 {
2061 	inline_macsec_testsuite.setup = inline_macsec_testsuite_setup;
2062 	inline_macsec_testsuite.teardown = inline_macsec_testsuite_teardown;
2063 	return unit_test_suite_runner(&inline_macsec_testsuite);
2064 }
2065 
2066 #endif /* !RTE_EXEC_ENV_WINDOWS */
2067 
2068 REGISTER_TEST_COMMAND(inline_macsec_autotest, test_inline_macsec);
2069