xref: /dpdk/app/test/test_security_inline_macsec.c (revision 7c3b1decd825e8a8f93f577bf775a673fcbe4c4d)
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(const struct mcs_test_vector *td[], enum mcs_op op, const struct mcs_test_opts *opts)
761 {
762 	uint16_t rx_sa_id[MCS_MAX_FLOWS][RTE_SECURITY_MACSEC_NUM_AN] = {{0}};
763 	uint16_t tx_sa_id[MCS_MAX_FLOWS][2] = {{0}};
764 	uint16_t rx_sc_id[MCS_MAX_FLOWS] = {0};
765 	uint16_t tx_sc_id[MCS_MAX_FLOWS] = {0};
766 	void *rx_sess[MCS_MAX_FLOWS] = {0};
767 	void *tx_sess[MCS_MAX_FLOWS] = {0};
768 	struct rte_security_session_conf sess_conf = {0};
769 	struct rte_security_macsec_sa sa_conf = {0};
770 	struct rte_security_macsec_sc sc_conf = {0};
771 	struct rte_security_ctx *ctx;
772 	int nb_rx = 0, nb_sent;
773 	int i, j = 0, ret, id, an = 0;
774 	uint8_t tci_off;
775 
776 	memset(rx_pkts_burst, 0, sizeof(rx_pkts_burst[0]) * opts->nb_td);
777 
778 	ctx = (struct rte_security_ctx *)rte_eth_dev_get_sec_ctx(port_id);
779 	if (ctx == NULL) {
780 		printf("Ethernet device doesn't support security features.\n");
781 		return TEST_SKIPPED;
782 	}
783 
784 	tci_off = (opts->sectag_insert_mode == 1) ? RTE_ETHER_HDR_LEN :
785 			RTE_ETHER_HDR_LEN + (opts->nb_vlan * RTE_VLAN_HLEN);
786 
787 	for (i = 0, j = 0; i < opts->nb_td; i++) {
788 		if (op == MCS_DECAP || op == MCS_VERIFY_ONLY)
789 			tx_pkts_burst[j] = init_packet(mbufpool, td[i]->secure_pkt.data,
790 							td[i]->secure_pkt.len);
791 		else {
792 			tx_pkts_burst[j] = init_packet(mbufpool, td[i]->plain_pkt.data,
793 							td[i]->plain_pkt.len);
794 
795 			tx_pkts_burst[j]->ol_flags |= RTE_MBUF_F_TX_MACSEC;
796 		}
797 		if (tx_pkts_burst[j] == NULL) {
798 			while (j--)
799 				rte_pktmbuf_free(tx_pkts_burst[j]);
800 			ret = TEST_FAILED;
801 			goto out;
802 		}
803 		j++;
804 
805 		if (op == MCS_DECAP || op == MCS_ENCAP_DECAP ||
806 				op == MCS_VERIFY_ONLY || op == MCS_AUTH_VERIFY) {
807 			for (an = 0; an < RTE_SECURITY_MACSEC_NUM_AN; an++) {
808 				/* For simplicity, using same SA conf for all AN */
809 				fill_macsec_sa_conf(td[i], &sa_conf,
810 						RTE_SECURITY_MACSEC_DIR_RX, an, tci_off);
811 				id = rte_security_macsec_sa_create(ctx, &sa_conf);
812 				if (id < 0) {
813 					printf("MACsec SA create failed : %d.\n", id);
814 					return TEST_FAILED;
815 				}
816 				rx_sa_id[i][an] = (uint16_t)id;
817 			}
818 			fill_macsec_sc_conf(td[i], &sc_conf, opts,
819 					RTE_SECURITY_MACSEC_DIR_RX, rx_sa_id[i], tci_off);
820 			id = rte_security_macsec_sc_create(ctx, &sc_conf);
821 			if (id < 0) {
822 				printf("MACsec SC create failed : %d.\n", id);
823 				goto out;
824 			}
825 			rx_sc_id[i] = (uint16_t)id;
826 
827 			/* Create Inline IPsec session. */
828 			ret = fill_session_conf(td[i], port_id, opts, &sess_conf,
829 					RTE_SECURITY_MACSEC_DIR_RX, rx_sc_id[i], tci_off);
830 			if (ret)
831 				return TEST_FAILED;
832 
833 			rx_sess[i] = rte_security_session_create(ctx, &sess_conf,
834 					sess_pool);
835 			if (rx_sess[i] == NULL) {
836 				printf("SEC Session init failed.\n");
837 				return TEST_FAILED;
838 			}
839 			ret = create_default_flow(td[i], port_id,
840 					RTE_SECURITY_MACSEC_DIR_RX, rx_sess[i]);
841 			if (ret)
842 				goto out;
843 		}
844 		if (op == MCS_ENCAP || op == MCS_ENCAP_DECAP ||
845 				op == MCS_AUTH_ONLY || op == MCS_AUTH_VERIFY) {
846 			int id;
847 
848 			fill_macsec_sa_conf(td[i], &sa_conf,
849 					RTE_SECURITY_MACSEC_DIR_TX,
850 					td[i]->secure_pkt.data[tci_off] & RTE_MACSEC_AN_MASK,
851 					tci_off);
852 			id = rte_security_macsec_sa_create(ctx, &sa_conf);
853 			if (id < 0) {
854 				printf("MACsec SA create failed : %d.\n", id);
855 				return TEST_FAILED;
856 			}
857 			tx_sa_id[i][0] = (uint16_t)id;
858 			tx_sa_id[i][1] = MCS_INVALID_SA;
859 			fill_macsec_sc_conf(td[i], &sc_conf, opts,
860 					RTE_SECURITY_MACSEC_DIR_TX, tx_sa_id[i], tci_off);
861 			id = rte_security_macsec_sc_create(ctx, &sc_conf);
862 			if (id < 0) {
863 				printf("MACsec SC create failed : %d.\n", id);
864 				goto out;
865 			}
866 			tx_sc_id[i] = (uint16_t)id;
867 
868 			/* Create Inline IPsec session. */
869 			ret = fill_session_conf(td[i], port_id, opts, &sess_conf,
870 					RTE_SECURITY_MACSEC_DIR_TX, tx_sc_id[i], tci_off);
871 			if (ret)
872 				return TEST_FAILED;
873 
874 			tx_sess[i] = rte_security_session_create(ctx, &sess_conf,
875 					sess_pool);
876 			if (tx_sess[i] == NULL) {
877 				printf("SEC Session init failed.\n");
878 				return TEST_FAILED;
879 			}
880 			ret = create_default_flow(td[i], port_id,
881 					RTE_SECURITY_MACSEC_DIR_TX, tx_sess[i]);
882 			if (ret)
883 				goto out;
884 		}
885 	}
886 
887 	/* Send packet to ethdev for inline MACsec processing. */
888 	nb_sent = rte_eth_tx_burst(port_id, 0, tx_pkts_burst, j);
889 
890 	if (nb_sent != j) {
891 		printf("\nUnable to TX %d packets, sent: %i", j, nb_sent);
892 		for ( ; nb_sent < j; nb_sent++)
893 			rte_pktmbuf_free(tx_pkts_burst[nb_sent]);
894 		ret = TEST_FAILED;
895 		goto out;
896 	}
897 
898 	rte_pause();
899 
900 	/* Receive back packet on loopback interface. */
901 	do {
902 		nb_rx += rte_eth_rx_burst(port_id, 0,
903 				&rx_pkts_burst[nb_rx],
904 				nb_sent - nb_rx);
905 		if (nb_rx >= nb_sent)
906 			break;
907 		rte_delay_ms(1);
908 	} while (j++ < 5 && nb_rx == 0);
909 
910 	if (nb_rx != nb_sent) {
911 		printf("\nUnable to RX all %d packets, received(%i)",
912 				nb_sent, nb_rx);
913 		while (--nb_rx >= 0)
914 			rte_pktmbuf_free(rx_pkts_burst[nb_rx]);
915 		ret = TEST_FAILED;
916 		goto out;
917 	}
918 
919 	for (i = 0; i < nb_rx; i++) {
920 		ret = test_macsec_post_process(rx_pkts_burst[i], td[i], op,
921 				opts->check_out_pkts_untagged);
922 		if (ret != TEST_SUCCESS) {
923 			for ( ; i < nb_rx; i++)
924 				rte_pktmbuf_free(rx_pkts_burst[i]);
925 			goto out;
926 		}
927 
928 		rte_pktmbuf_free(rx_pkts_burst[i]);
929 		rx_pkts_burst[i] = NULL;
930 	}
931 out:
932 	if (opts->check_out_pkts_toolong == 1 ||
933 			opts->check_sa_not_in_use == 1 ||
934 			opts->check_bad_tag_cnt == 1)
935 		ret = TEST_SUCCESS;
936 
937 	for (i = 0; i < opts->nb_td; i++) {
938 		if (opts->dump_all_stats) {
939 			mcs_stats_dump(ctx, op,
940 					rx_sess[i], tx_sess[i],
941 					rx_sc_id[i], tx_sc_id[i],
942 					rx_sa_id[i], tx_sa_id[i]);
943 		} else {
944 			if (ret == TEST_SUCCESS)
945 				ret = mcs_stats_check(ctx, op, opts, td[i],
946 					rx_sess[i], tx_sess[i],
947 					rx_sc_id[i], tx_sc_id[i],
948 					rx_sa_id[i], tx_sa_id[i]);
949 		}
950 	}
951 
952 	destroy_default_flow(port_id);
953 
954 	/* Destroy session so that other cases can create the session again */
955 	for (i = 0; i < opts->nb_td; i++) {
956 		if (op == MCS_ENCAP || op == MCS_ENCAP_DECAP ||
957 				op == MCS_AUTH_ONLY || op == MCS_AUTH_VERIFY) {
958 			rte_security_session_destroy(ctx, tx_sess[i]);
959 			tx_sess[i] = NULL;
960 			rte_security_macsec_sc_destroy(ctx, tx_sc_id[i],
961 						RTE_SECURITY_MACSEC_DIR_TX);
962 			rte_security_macsec_sa_destroy(ctx, tx_sa_id[i][0],
963 						RTE_SECURITY_MACSEC_DIR_TX);
964 		}
965 		if (op == MCS_DECAP || op == MCS_ENCAP_DECAP ||
966 				op == MCS_VERIFY_ONLY || op == MCS_AUTH_VERIFY) {
967 			rte_security_session_destroy(ctx, rx_sess[i]);
968 			rx_sess[i] = NULL;
969 			rte_security_macsec_sc_destroy(ctx, rx_sc_id[i],
970 						RTE_SECURITY_MACSEC_DIR_RX);
971 			for (j = 0; j < RTE_SECURITY_MACSEC_NUM_AN; j++) {
972 				rte_security_macsec_sa_destroy(ctx, rx_sa_id[i][j],
973 						RTE_SECURITY_MACSEC_DIR_RX);
974 			}
975 		}
976 	}
977 
978 	return ret;
979 }
980 
981 static int
982 test_inline_macsec_encap_all(const void *data __rte_unused)
983 {
984 	const struct mcs_test_vector *cur_td;
985 	struct mcs_test_opts opts = {0};
986 	int err, all_err = 0;
987 	int i, size;
988 
989 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
990 	opts.encrypt = true;
991 	opts.protect_frames = true;
992 	opts.sa_in_use = 1;
993 	opts.nb_td = 1;
994 	opts.sectag_insert_mode = 1;
995 	opts.mtu = RTE_ETHER_MTU;
996 
997 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
998 	for (i = 0; i < size; i++) {
999 		cur_td = &list_mcs_cipher_vectors[i];
1000 		err = test_macsec(&cur_td, MCS_ENCAP, &opts);
1001 		if (err) {
1002 			printf("\nCipher Auth Encryption case %d failed", cur_td->test_idx);
1003 			err = -1;
1004 		} else {
1005 			printf("\nCipher Auth Encryption case %d Passed", cur_td->test_idx);
1006 			err = 0;
1007 		}
1008 		all_err += err;
1009 	}
1010 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1011 
1012 	return all_err;
1013 }
1014 
1015 static int
1016 test_inline_macsec_decap_all(const void *data __rte_unused)
1017 {
1018 	const struct mcs_test_vector *cur_td;
1019 	struct mcs_test_opts opts = {0};
1020 	int err, all_err = 0;
1021 	int i, size;
1022 
1023 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1024 	opts.sa_in_use = 1;
1025 	opts.nb_td = 1;
1026 	opts.sectag_insert_mode = 1;
1027 	opts.mtu = RTE_ETHER_MTU;
1028 
1029 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1030 	for (i = 0; i < size; i++) {
1031 		cur_td = &list_mcs_cipher_vectors[i];
1032 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1033 		if (err) {
1034 			printf("\nCipher Auth Decryption case %d failed", cur_td->test_idx);
1035 			err = -1;
1036 		} else {
1037 			printf("\nCipher Auth Decryption case %d Passed", cur_td->test_idx);
1038 			err = 0;
1039 		}
1040 		all_err += err;
1041 	}
1042 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1043 
1044 	return all_err;
1045 }
1046 
1047 static int
1048 test_inline_macsec_auth_only_all(const void *data __rte_unused)
1049 {
1050 	const struct mcs_test_vector *cur_td;
1051 	struct mcs_test_opts opts = {0};
1052 	int err, all_err = 0;
1053 	int i, size;
1054 
1055 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1056 	opts.protect_frames = true;
1057 	opts.sa_in_use = 1;
1058 	opts.nb_td = 1;
1059 	opts.sectag_insert_mode = 1;
1060 	opts.mtu = RTE_ETHER_MTU;
1061 
1062 	size = (sizeof(list_mcs_integrity_vectors) / sizeof((list_mcs_integrity_vectors)[0]));
1063 
1064 	for (i = 0; i < size; i++) {
1065 		cur_td = &list_mcs_integrity_vectors[i];
1066 		err = test_macsec(&cur_td, MCS_AUTH_ONLY, &opts);
1067 		if (err) {
1068 			printf("\nAuth Generate case %d failed", cur_td->test_idx);
1069 			err = -1;
1070 		} else {
1071 			printf("\nAuth Generate case %d Passed", cur_td->test_idx);
1072 			err = 0;
1073 		}
1074 		all_err += err;
1075 	}
1076 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1077 
1078 	return all_err;
1079 }
1080 
1081 static int
1082 test_inline_macsec_verify_only_all(const void *data __rte_unused)
1083 {
1084 	const struct mcs_test_vector *cur_td;
1085 	struct mcs_test_opts opts = {0};
1086 	int err, all_err = 0;
1087 	int i, size;
1088 
1089 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1090 	opts.sa_in_use = 1;
1091 	opts.nb_td = 1;
1092 	opts.sectag_insert_mode = 1;
1093 	opts.mtu = RTE_ETHER_MTU;
1094 
1095 	size = (sizeof(list_mcs_integrity_vectors) / sizeof((list_mcs_integrity_vectors)[0]));
1096 
1097 	for (i = 0; i < size; i++) {
1098 		cur_td = &list_mcs_integrity_vectors[i];
1099 		err = test_macsec(&cur_td, MCS_VERIFY_ONLY, &opts);
1100 		if (err) {
1101 			printf("\nAuth Verify case %d failed", cur_td->test_idx);
1102 			err = -1;
1103 		} else {
1104 			printf("\nAuth Verify 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_encap_decap_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.encrypt = true;
1124 	opts.protect_frames = true;
1125 	opts.sa_in_use = 1;
1126 	opts.nb_td = 1;
1127 	opts.sectag_insert_mode = 1;
1128 	opts.mtu = RTE_ETHER_MTU;
1129 
1130 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1131 
1132 	for (i = 0; i < size; i++) {
1133 		cur_td = &list_mcs_cipher_vectors[i];
1134 		err = test_macsec(&cur_td, MCS_ENCAP_DECAP, &opts);
1135 		if (err) {
1136 			printf("\nCipher Auth Encap-decap case %d failed", cur_td->test_idx);
1137 			err = -1;
1138 		} else {
1139 			printf("\nCipher Auth Encap-decap case %d Passed", cur_td->test_idx);
1140 			err = 0;
1141 		}
1142 		all_err += err;
1143 	}
1144 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1145 
1146 	return all_err;
1147 }
1148 
1149 
1150 static int
1151 test_inline_macsec_auth_verify_all(const void *data __rte_unused)
1152 {
1153 	const struct mcs_test_vector *cur_td;
1154 	struct mcs_test_opts opts = {0};
1155 	int err, all_err = 0;
1156 	int i, size;
1157 
1158 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1159 	opts.protect_frames = true;
1160 	opts.sa_in_use = 1;
1161 	opts.nb_td = 1;
1162 	opts.sectag_insert_mode = 1;
1163 	opts.mtu = RTE_ETHER_MTU;
1164 
1165 	size = (sizeof(list_mcs_integrity_vectors) / sizeof((list_mcs_integrity_vectors)[0]));
1166 
1167 	for (i = 0; i < size; i++) {
1168 		cur_td = &list_mcs_integrity_vectors[i];
1169 		err = test_macsec(&cur_td, MCS_AUTH_VERIFY, &opts);
1170 		if (err) {
1171 			printf("\nAuth Generate + Verify case %d failed", cur_td->test_idx);
1172 			err = -1;
1173 		} else {
1174 			printf("\nAuth Generate + Verify case %d Passed", cur_td->test_idx);
1175 			err = 0;
1176 		}
1177 		all_err += err;
1178 	}
1179 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1180 
1181 	return all_err;
1182 }
1183 
1184 static int
1185 test_inline_macsec_multi_flow(const void *data __rte_unused)
1186 {
1187 	const struct mcs_test_vector *tv[MCS_MAX_FLOWS];
1188 	struct mcs_test_vector iter[MCS_MAX_FLOWS];
1189 	struct mcs_test_opts opts = {0};
1190 	int i, err;
1191 
1192 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1193 	opts.encrypt = true;
1194 	opts.protect_frames = true;
1195 	opts.sa_in_use = 1;
1196 	opts.nb_td = MCS_MAX_FLOWS;
1197 	opts.sectag_insert_mode = 1;
1198 	opts.mtu = RTE_ETHER_MTU;
1199 
1200 	for (i = 0; i < MCS_MAX_FLOWS; i++) {
1201 		memcpy(&iter[i].sa_key.data, sa_key, MCS_MULTI_FLOW_TD_KEY_SZ);
1202 		memcpy(&iter[i].plain_pkt.data, eth_addrs[i], 2 * RTE_ETHER_ADDR_LEN);
1203 		memcpy(&iter[i].plain_pkt.data[2 * RTE_ETHER_ADDR_LEN], plain_user_data,
1204 		       MCS_MULTI_FLOW_TD_PLAIN_DATA_SZ);
1205 		memcpy(&iter[i].secure_pkt.data, eth_addrs[i], 2 * RTE_ETHER_ADDR_LEN);
1206 		memcpy(&iter[i].secure_pkt.data[2 * RTE_ETHER_ADDR_LEN], secure_user_data,
1207 		       MCS_MULTI_FLOW_TD_SECURE_DATA_SZ);
1208 		iter[i].sa_key.len = MCS_MULTI_FLOW_TD_KEY_SZ;
1209 		iter[i].plain_pkt.len = MCS_MULTI_FLOW_TD_PLAIN_DATA_SZ +
1210 					(2 * RTE_ETHER_ADDR_LEN);
1211 		iter[i].secure_pkt.len = MCS_MULTI_FLOW_TD_SECURE_DATA_SZ +
1212 					(2 * RTE_ETHER_ADDR_LEN);
1213 		iter[i].alg = RTE_SECURITY_MACSEC_ALG_GCM_128;
1214 		iter[i].ssci = 0x0;
1215 		iter[i].xpn = 0x0;
1216 		tv[i] = (const struct mcs_test_vector *)&iter[i];
1217 	}
1218 	err = test_macsec(tv, MCS_ENCAP_DECAP, &opts);
1219 	if (err) {
1220 		printf("\nCipher Auth Encryption multi flow failed");
1221 		err = -1;
1222 	} else {
1223 		printf("\nCipher Auth Encryption multi flow Passed");
1224 		err = 0;
1225 	}
1226 	return err;
1227 }
1228 
1229 static int
1230 test_inline_macsec_with_vlan(const void *data __rte_unused)
1231 {
1232 	const struct mcs_test_vector *cur_td;
1233 	struct mcs_test_opts opts = {0};
1234 	int err, all_err = 0;
1235 	int i, size;
1236 
1237 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1238 	opts.protect_frames = true;
1239 	opts.sa_in_use = 1;
1240 	opts.nb_td = 1;
1241 	opts.mtu = RTE_ETHER_MTU;
1242 
1243 	size = (sizeof(list_mcs_vlan_vectors) / sizeof((list_mcs_vlan_vectors)[0]));
1244 
1245 	for (i = 0; i < size; i++) {
1246 		cur_td = &list_mcs_vlan_vectors[i];
1247 		if (i == 0) {
1248 			opts.sectag_insert_mode = 1;
1249 		} else if (i == 1) {
1250 			opts.sectag_insert_mode = 0; /* offset from special E-type */
1251 			opts.nb_vlan = 1;
1252 		} else if (i == 2) {
1253 			opts.sectag_insert_mode = 0; /* offset from special E-type */
1254 			opts.nb_vlan = 2;
1255 		}
1256 		err = test_macsec(&cur_td, MCS_ENCAP, &opts);
1257 		if (err) {
1258 			printf("\n VLAN Encap case %d failed", cur_td->test_idx);
1259 			err = -1;
1260 		} else {
1261 			printf("\n VLAN Encap case %d passed", cur_td->test_idx);
1262 			err = 0;
1263 		}
1264 		all_err += err;
1265 	}
1266 	for (i = 0; i < size; i++) {
1267 		cur_td = &list_mcs_vlan_vectors[i];
1268 		if (i == 0) {
1269 			opts.sectag_insert_mode = 1;
1270 		} else if (i == 1) {
1271 			opts.sectag_insert_mode = 0; /* offset from special E-type */
1272 			opts.nb_vlan = 1;
1273 		} else if (i == 2) {
1274 			opts.sectag_insert_mode = 0; /* offset from special E-type */
1275 			opts.nb_vlan = 2;
1276 		}
1277 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1278 		if (err) {
1279 			printf("\n VLAN Decap case %d failed", cur_td->test_idx);
1280 			err = -1;
1281 		} else {
1282 			printf("\n VLAN Decap case %d passed", cur_td->test_idx);
1283 			err = 0;
1284 		}
1285 		all_err += err;
1286 	}
1287 
1288 	printf("\n%s: Success: %d, Failure: %d\n", __func__, (2 * size) + all_err, -all_err);
1289 	return all_err;
1290 }
1291 
1292 static int
1293 test_inline_macsec_pkt_drop(const void *data __rte_unused)
1294 {
1295 	const struct mcs_test_vector *cur_td;
1296 	struct mcs_test_opts opts = {0};
1297 	int err, all_err = 0;
1298 	int i, size;
1299 
1300 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1301 	opts.encrypt = true;
1302 	opts.protect_frames = true;
1303 	opts.sa_in_use = 1;
1304 	opts.nb_td = 1;
1305 	opts.sectag_insert_mode = 1;
1306 	opts.mtu = RTE_ETHER_MTU;
1307 
1308 	size = (sizeof(list_mcs_err_cipher_vectors) / sizeof((list_mcs_err_cipher_vectors)[0]));
1309 
1310 	for (i = 0; i < size; i++) {
1311 		cur_td = &list_mcs_err_cipher_vectors[i];
1312 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1313 		if (err) {
1314 			printf("\nPacket drop case %d passed", cur_td->test_idx);
1315 			err = 0;
1316 		} else {
1317 			printf("\nPacket drop case %d failed", cur_td->test_idx);
1318 			err = -1;
1319 		}
1320 		all_err += err;
1321 	}
1322 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1323 
1324 	return all_err;
1325 }
1326 
1327 static int
1328 test_inline_macsec_untagged_rx(const void *data __rte_unused)
1329 {
1330 	const struct mcs_test_vector *cur_td;
1331 	struct mcs_test_opts opts = {0};
1332 	int err, all_err = 0;
1333 	int i, size;
1334 
1335 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1336 	opts.sa_in_use = 1;
1337 	opts.nb_td = 1;
1338 	opts.sectag_insert_mode = 1;
1339 	opts.mtu = RTE_ETHER_MTU;
1340 	opts.check_untagged_rx = 1;
1341 
1342 	size = (sizeof(list_mcs_untagged_cipher_vectors) /
1343 		sizeof((list_mcs_untagged_cipher_vectors)[0]));
1344 
1345 	for (i = 0; i < size; i++) {
1346 		cur_td = &list_mcs_untagged_cipher_vectors[i];
1347 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1348 		if (err)
1349 			err = 0;
1350 		else
1351 			err = -1;
1352 
1353 		all_err += err;
1354 	}
1355 
1356 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_NO_DISCARD;
1357 	for (i = 0; i < size; i++) {
1358 		cur_td = &list_mcs_untagged_cipher_vectors[i];
1359 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1360 		if (err)
1361 			err = 0;
1362 		else
1363 			err = -1;
1364 
1365 		all_err += err;
1366 	}
1367 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1368 
1369 	return all_err;
1370 }
1371 
1372 static int
1373 test_inline_macsec_bad_tag_rx(const void *data __rte_unused)
1374 {
1375 	const struct mcs_test_vector *cur_td;
1376 	struct mcs_test_opts opts = {0};
1377 	int err, all_err = 0;
1378 	int i, size;
1379 
1380 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1381 	opts.protect_frames = true;
1382 	opts.sa_in_use = 1;
1383 	opts.nb_td = 1;
1384 	opts.sectag_insert_mode = 1;
1385 	opts.mtu = RTE_ETHER_MTU;
1386 	opts.check_bad_tag_cnt = 1;
1387 
1388 	size = (sizeof(list_mcs_bad_tag_vectors) / sizeof((list_mcs_bad_tag_vectors)[0]));
1389 
1390 	for (i = 0; i < size; i++) {
1391 		cur_td = &list_mcs_bad_tag_vectors[i];
1392 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1393 		if (err)
1394 			err = -1;
1395 		else
1396 			err = 0;
1397 
1398 		all_err += err;
1399 	}
1400 
1401 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1402 
1403 	return all_err;
1404 }
1405 
1406 static int
1407 test_inline_macsec_sa_not_in_use(const void *data __rte_unused)
1408 {
1409 	const struct mcs_test_vector *cur_td;
1410 	struct mcs_test_opts opts = {0};
1411 	int err, all_err = 0;
1412 	int i, size;
1413 
1414 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1415 	opts.protect_frames = true;
1416 	opts.sa_in_use = 0;
1417 	opts.nb_td = 1;
1418 	opts.sectag_insert_mode = 1;
1419 	opts.mtu = RTE_ETHER_MTU;
1420 	opts.check_sa_not_in_use = 1;
1421 
1422 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1423 
1424 	for (i = 0; i < size; i++) {
1425 		cur_td = &list_mcs_cipher_vectors[i];
1426 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
1427 		if (err)
1428 			err = -1;
1429 		else
1430 			err = 0;
1431 
1432 		all_err += err;
1433 	}
1434 
1435 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1436 
1437 	return all_err;
1438 }
1439 
1440 static int
1441 test_inline_macsec_out_pkts_untagged(const void *data __rte_unused)
1442 {
1443 	const struct mcs_test_vector *cur_td;
1444 	struct mcs_test_opts opts = {0};
1445 	int err, all_err = 0;
1446 	int i, size;
1447 
1448 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1449 	opts.encrypt = false;
1450 	opts.protect_frames = false;
1451 	opts.sa_in_use = 1;
1452 	opts.nb_td = 1;
1453 	opts.sectag_insert_mode = 1;
1454 	opts.mtu = RTE_ETHER_MTU;
1455 	opts.check_out_pkts_untagged = 1;
1456 
1457 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1458 	for (i = 0; i < size; i++) {
1459 		cur_td = &list_mcs_cipher_vectors[i];
1460 		err = test_macsec(&cur_td, MCS_ENCAP, &opts);
1461 		if (err)
1462 			err = -1;
1463 		else
1464 			err = 0;
1465 
1466 		all_err += err;
1467 	}
1468 
1469 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1470 	return all_err;
1471 }
1472 
1473 static int
1474 test_inline_macsec_out_pkts_toolong(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_NO_DISCARD;
1482 	opts.encrypt = true;
1483 	opts.protect_frames = true;
1484 	opts.sa_in_use = 1;
1485 	opts.nb_td = 1;
1486 	opts.sectag_insert_mode = 1;
1487 	opts.mtu = 50;
1488 	opts.check_out_pkts_toolong = 1;
1489 
1490 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1491 	for (i = 0; i < size; i++) {
1492 		cur_td = &list_mcs_cipher_vectors[i];
1493 		err = test_macsec(&cur_td, MCS_ENCAP, &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 	return all_err;
1504 }
1505 
1506 static int
1507 ut_setup_inline_macsec(void)
1508 {
1509 	int ret;
1510 
1511 	/* Start device */
1512 	ret = rte_eth_dev_start(port_id);
1513 	if (ret < 0) {
1514 		printf("rte_eth_dev_start: err=%d, port=%d\n",
1515 			ret, port_id);
1516 		return ret;
1517 	}
1518 	/* always enable promiscuous */
1519 	ret = rte_eth_promiscuous_enable(port_id);
1520 	if (ret != 0) {
1521 		printf("rte_eth_promiscuous_enable: err=%s, port=%d\n",
1522 			rte_strerror(-ret), port_id);
1523 		return ret;
1524 	}
1525 
1526 	check_all_ports_link_status(1, RTE_PORT_ALL);
1527 
1528 	return 0;
1529 }
1530 
1531 static void
1532 ut_teardown_inline_macsec(void)
1533 {
1534 	uint16_t portid;
1535 	int ret;
1536 
1537 	/* port tear down */
1538 	RTE_ETH_FOREACH_DEV(portid) {
1539 		ret = rte_eth_dev_stop(portid);
1540 		if (ret != 0)
1541 			printf("rte_eth_dev_stop: err=%s, port=%u\n",
1542 			       rte_strerror(-ret), portid);
1543 
1544 	}
1545 }
1546 
1547 static int
1548 inline_macsec_testsuite_setup(void)
1549 {
1550 	uint16_t nb_rxd;
1551 	uint16_t nb_txd;
1552 	uint16_t nb_ports;
1553 	int ret;
1554 	uint16_t nb_rx_queue = 1, nb_tx_queue = 1;
1555 
1556 	printf("Start inline MACsec test.\n");
1557 
1558 	nb_ports = rte_eth_dev_count_avail();
1559 	if (nb_ports < NB_ETHPORTS_USED) {
1560 		printf("At least %u port(s) used for test\n",
1561 		       NB_ETHPORTS_USED);
1562 		return TEST_SKIPPED;
1563 	}
1564 
1565 	ret = init_mempools(NB_MBUF);
1566 	if (ret)
1567 		return ret;
1568 
1569 	if (tx_pkts_burst == NULL) {
1570 		tx_pkts_burst = (struct rte_mbuf **)rte_calloc("tx_buff",
1571 					  MAX_TRAFFIC_BURST,
1572 					  sizeof(void *),
1573 					  RTE_CACHE_LINE_SIZE);
1574 		if (!tx_pkts_burst)
1575 			return TEST_FAILED;
1576 
1577 		rx_pkts_burst = (struct rte_mbuf **)rte_calloc("rx_buff",
1578 					  MAX_TRAFFIC_BURST,
1579 					  sizeof(void *),
1580 					  RTE_CACHE_LINE_SIZE);
1581 		if (!rx_pkts_burst)
1582 			return TEST_FAILED;
1583 	}
1584 
1585 	printf("Generate %d packets\n", MAX_TRAFFIC_BURST);
1586 
1587 	nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
1588 	nb_txd = RTE_TEST_TX_DESC_DEFAULT;
1589 
1590 	/* configuring port 0 for the test is enough */
1591 	port_id = 0;
1592 	/* port configure */
1593 	ret = rte_eth_dev_configure(port_id, nb_rx_queue,
1594 				    nb_tx_queue, &port_conf);
1595 	if (ret < 0) {
1596 		printf("Cannot configure device: err=%d, port=%d\n",
1597 			 ret, port_id);
1598 		return ret;
1599 	}
1600 	ret = rte_eth_macaddr_get(port_id, &ports_eth_addr[port_id]);
1601 	if (ret < 0) {
1602 		printf("Cannot get mac address: err=%d, port=%d\n",
1603 			 ret, port_id);
1604 		return ret;
1605 	}
1606 	printf("Port %u ", port_id);
1607 	print_ethaddr("Address:", &ports_eth_addr[port_id]);
1608 	printf("\n");
1609 
1610 	/* tx queue setup */
1611 	ret = rte_eth_tx_queue_setup(port_id, 0, nb_txd,
1612 				     SOCKET_ID_ANY, &tx_conf);
1613 	if (ret < 0) {
1614 		printf("rte_eth_tx_queue_setup: err=%d, port=%d\n",
1615 				ret, port_id);
1616 		return ret;
1617 	}
1618 	/* rx queue steup */
1619 	ret = rte_eth_rx_queue_setup(port_id, 0, nb_rxd, SOCKET_ID_ANY,
1620 				     &rx_conf, mbufpool);
1621 	if (ret < 0) {
1622 		printf("rte_eth_rx_queue_setup: err=%d, port=%d\n",
1623 				ret, port_id);
1624 		return ret;
1625 	}
1626 
1627 	return 0;
1628 }
1629 
1630 static void
1631 inline_macsec_testsuite_teardown(void)
1632 {
1633 	uint16_t portid;
1634 	int ret;
1635 
1636 	/* port tear down */
1637 	RTE_ETH_FOREACH_DEV(portid) {
1638 		ret = rte_eth_dev_reset(portid);
1639 		if (ret != 0)
1640 			printf("rte_eth_dev_reset: err=%s, port=%u\n",
1641 			       rte_strerror(-ret), port_id);
1642 	}
1643 	rte_free(tx_pkts_burst);
1644 	rte_free(rx_pkts_burst);
1645 }
1646 
1647 
1648 static struct unit_test_suite inline_macsec_testsuite  = {
1649 	.suite_name = "Inline MACsec Ethernet Device Unit Test Suite",
1650 	.unit_test_cases = {
1651 		TEST_CASE_NAMED_ST(
1652 			"MACsec Encap + decap Multi flow",
1653 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1654 			test_inline_macsec_multi_flow),
1655 		TEST_CASE_NAMED_ST(
1656 			"MACsec encap(Cipher+Auth) known vector",
1657 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1658 			test_inline_macsec_encap_all),
1659 		TEST_CASE_NAMED_ST(
1660 			"MACsec decap(De-cipher+verify) known vector",
1661 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1662 			test_inline_macsec_decap_all),
1663 		TEST_CASE_NAMED_ST(
1664 			"MACsec auth only known vector",
1665 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1666 			test_inline_macsec_auth_only_all),
1667 		TEST_CASE_NAMED_ST(
1668 			"MACsec verify only known vector",
1669 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1670 			test_inline_macsec_verify_only_all),
1671 		TEST_CASE_NAMED_ST(
1672 			"MACsec encap + decap known vector",
1673 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1674 			test_inline_macsec_encap_decap_all),
1675 		TEST_CASE_NAMED_ST(
1676 			"MACsec auth + verify known vector",
1677 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1678 			test_inline_macsec_auth_verify_all),
1679 		TEST_CASE_NAMED_ST(
1680 			"MACsec Encap and decap with VLAN",
1681 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1682 			test_inline_macsec_with_vlan),
1683 		TEST_CASE_NAMED_ST(
1684 			"MACsec packet drop",
1685 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1686 			test_inline_macsec_pkt_drop),
1687 		TEST_CASE_NAMED_ST(
1688 			"MACsec untagged Rx",
1689 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1690 			test_inline_macsec_untagged_rx),
1691 		TEST_CASE_NAMED_ST(
1692 			"MACsec bad tag Rx",
1693 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1694 			test_inline_macsec_bad_tag_rx),
1695 		TEST_CASE_NAMED_ST(
1696 			"MACsec SA not in use",
1697 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1698 			test_inline_macsec_sa_not_in_use),
1699 		TEST_CASE_NAMED_ST(
1700 			"MACsec out pkts untagged",
1701 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1702 			test_inline_macsec_out_pkts_untagged),
1703 		TEST_CASE_NAMED_ST(
1704 			"MACsec out pkts too long",
1705 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1706 			test_inline_macsec_out_pkts_toolong),
1707 
1708 		TEST_CASES_END() /**< NULL terminate unit test array */
1709 	},
1710 };
1711 
1712 static int
1713 test_inline_macsec(void)
1714 {
1715 	inline_macsec_testsuite.setup = inline_macsec_testsuite_setup;
1716 	inline_macsec_testsuite.teardown = inline_macsec_testsuite_teardown;
1717 	return unit_test_suite_runner(&inline_macsec_testsuite);
1718 }
1719 
1720 #endif /* !RTE_EXEC_ENV_WINDOWS */
1721 
1722 REGISTER_TEST_COMMAND(inline_macsec_autotest, test_inline_macsec);
1723