xref: /dpdk/app/test/test_security_inline_macsec.c (revision e3d83ea42031d79b5ed48acb5e85b4b98de6da0e)
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 test_macsec(const struct mcs_test_vector *td[], enum mcs_op op, const struct mcs_test_opts *opts)
664 {
665 	uint16_t rx_sa_id[MCS_MAX_FLOWS][RTE_SECURITY_MACSEC_NUM_AN] = {{0}};
666 	uint16_t tx_sa_id[MCS_MAX_FLOWS][2] = {{0}};
667 	uint16_t rx_sc_id[MCS_MAX_FLOWS] = {0};
668 	uint16_t tx_sc_id[MCS_MAX_FLOWS] = {0};
669 	void *rx_sess[MCS_MAX_FLOWS] = {0};
670 	void *tx_sess[MCS_MAX_FLOWS] = {0};
671 	struct rte_security_session_conf sess_conf = {0};
672 	struct rte_security_macsec_sa sa_conf = {0};
673 	struct rte_security_macsec_sc sc_conf = {0};
674 	struct rte_security_ctx *ctx;
675 	int nb_rx = 0, nb_sent;
676 	int i, j = 0, ret, id, an = 0;
677 	uint8_t tci_off;
678 
679 	memset(rx_pkts_burst, 0, sizeof(rx_pkts_burst[0]) * opts->nb_td);
680 
681 	ctx = (struct rte_security_ctx *)rte_eth_dev_get_sec_ctx(port_id);
682 	if (ctx == NULL) {
683 		printf("Ethernet device doesn't support security features.\n");
684 		return TEST_SKIPPED;
685 	}
686 
687 	tci_off = (opts->sectag_insert_mode == 1) ? RTE_ETHER_HDR_LEN :
688 			RTE_ETHER_HDR_LEN + (opts->nb_vlan * RTE_VLAN_HLEN);
689 
690 	for (i = 0, j = 0; i < opts->nb_td; i++) {
691 		if (op == MCS_DECAP || op == MCS_VERIFY_ONLY)
692 			tx_pkts_burst[j] = init_packet(mbufpool, td[i]->secure_pkt.data,
693 							td[i]->secure_pkt.len);
694 		else {
695 			tx_pkts_burst[j] = init_packet(mbufpool, td[i]->plain_pkt.data,
696 							td[i]->plain_pkt.len);
697 
698 			tx_pkts_burst[j]->ol_flags |= RTE_MBUF_F_TX_MACSEC;
699 		}
700 		if (tx_pkts_burst[j] == NULL) {
701 			while (j--)
702 				rte_pktmbuf_free(tx_pkts_burst[j]);
703 			ret = TEST_FAILED;
704 			goto out;
705 		}
706 		j++;
707 
708 		if (op == MCS_DECAP || op == MCS_ENCAP_DECAP ||
709 				op == MCS_VERIFY_ONLY || op == MCS_AUTH_VERIFY) {
710 			for (an = 0; an < RTE_SECURITY_MACSEC_NUM_AN; an++) {
711 				/* For simplicity, using same SA conf for all AN */
712 				fill_macsec_sa_conf(td[i], &sa_conf,
713 						RTE_SECURITY_MACSEC_DIR_RX, an, tci_off);
714 				id = rte_security_macsec_sa_create(ctx, &sa_conf);
715 				if (id < 0) {
716 					printf("MACsec SA create failed : %d.\n", id);
717 					return TEST_FAILED;
718 				}
719 				rx_sa_id[i][an] = (uint16_t)id;
720 			}
721 			fill_macsec_sc_conf(td[i], &sc_conf, opts,
722 					RTE_SECURITY_MACSEC_DIR_RX, rx_sa_id[i], tci_off);
723 			id = rte_security_macsec_sc_create(ctx, &sc_conf);
724 			if (id < 0) {
725 				printf("MACsec SC create failed : %d.\n", id);
726 				goto out;
727 			}
728 			rx_sc_id[i] = (uint16_t)id;
729 
730 			/* Create Inline IPsec session. */
731 			ret = fill_session_conf(td[i], port_id, opts, &sess_conf,
732 					RTE_SECURITY_MACSEC_DIR_RX, rx_sc_id[i], tci_off);
733 			if (ret)
734 				return TEST_FAILED;
735 
736 			rx_sess[i] = rte_security_session_create(ctx, &sess_conf,
737 					sess_pool);
738 			if (rx_sess[i] == NULL) {
739 				printf("SEC Session init failed.\n");
740 				return TEST_FAILED;
741 			}
742 			ret = create_default_flow(td[i], port_id,
743 					RTE_SECURITY_MACSEC_DIR_RX, rx_sess[i]);
744 			if (ret)
745 				goto out;
746 		}
747 		if (op == MCS_ENCAP || op == MCS_ENCAP_DECAP ||
748 				op == MCS_AUTH_ONLY || op == MCS_AUTH_VERIFY) {
749 			int id;
750 
751 			fill_macsec_sa_conf(td[i], &sa_conf,
752 					RTE_SECURITY_MACSEC_DIR_TX,
753 					td[i]->secure_pkt.data[tci_off] & RTE_MACSEC_AN_MASK,
754 					tci_off);
755 			id = rte_security_macsec_sa_create(ctx, &sa_conf);
756 			if (id < 0) {
757 				printf("MACsec SA create failed : %d.\n", id);
758 				return TEST_FAILED;
759 			}
760 			tx_sa_id[i][0] = (uint16_t)id;
761 			tx_sa_id[i][1] = MCS_INVALID_SA;
762 			fill_macsec_sc_conf(td[i], &sc_conf, opts,
763 					RTE_SECURITY_MACSEC_DIR_TX, tx_sa_id[i], tci_off);
764 			id = rte_security_macsec_sc_create(ctx, &sc_conf);
765 			if (id < 0) {
766 				printf("MACsec SC create failed : %d.\n", id);
767 				goto out;
768 			}
769 			tx_sc_id[i] = (uint16_t)id;
770 
771 			/* Create Inline IPsec session. */
772 			ret = fill_session_conf(td[i], port_id, opts, &sess_conf,
773 					RTE_SECURITY_MACSEC_DIR_TX, tx_sc_id[i], tci_off);
774 			if (ret)
775 				return TEST_FAILED;
776 
777 			tx_sess[i] = rte_security_session_create(ctx, &sess_conf,
778 					sess_pool);
779 			if (tx_sess[i] == NULL) {
780 				printf("SEC Session init failed.\n");
781 				return TEST_FAILED;
782 			}
783 			ret = create_default_flow(td[i], port_id,
784 					RTE_SECURITY_MACSEC_DIR_TX, tx_sess[i]);
785 			if (ret)
786 				goto out;
787 		}
788 	}
789 
790 	/* Send packet to ethdev for inline MACsec processing. */
791 	nb_sent = rte_eth_tx_burst(port_id, 0, tx_pkts_burst, j);
792 
793 	if (nb_sent != j) {
794 		printf("\nUnable to TX %d packets, sent: %i", j, nb_sent);
795 		for ( ; nb_sent < j; nb_sent++)
796 			rte_pktmbuf_free(tx_pkts_burst[nb_sent]);
797 		ret = TEST_FAILED;
798 		goto out;
799 	}
800 
801 	rte_pause();
802 
803 	/* Receive back packet on loopback interface. */
804 	do {
805 		nb_rx += rte_eth_rx_burst(port_id, 0,
806 				&rx_pkts_burst[nb_rx],
807 				nb_sent - nb_rx);
808 		if (nb_rx >= nb_sent)
809 			break;
810 		rte_delay_ms(1);
811 	} while (j++ < 5 && nb_rx == 0);
812 
813 	if (nb_rx != nb_sent) {
814 		printf("\nUnable to RX all %d packets, received(%i)",
815 				nb_sent, nb_rx);
816 		while (--nb_rx >= 0)
817 			rte_pktmbuf_free(rx_pkts_burst[nb_rx]);
818 		ret = TEST_FAILED;
819 		goto out;
820 	}
821 
822 	for (i = 0; i < nb_rx; i++) {
823 		ret = test_macsec_post_process(rx_pkts_burst[i], td[i], op,
824 				opts->check_out_pkts_untagged);
825 		if (ret != TEST_SUCCESS) {
826 			for ( ; i < nb_rx; i++)
827 				rte_pktmbuf_free(rx_pkts_burst[i]);
828 			goto out;
829 		}
830 
831 		rte_pktmbuf_free(rx_pkts_burst[i]);
832 		rx_pkts_burst[i] = NULL;
833 	}
834 out:
835 	for (i = 0; i < opts->nb_td; i++) {
836 		if (opts->dump_all_stats) {
837 			mcs_stats_dump(ctx, op,
838 					rx_sess[i], tx_sess[i],
839 					rx_sc_id[i], tx_sc_id[i],
840 					rx_sa_id[i], tx_sa_id[i]);
841 		}
842 	}
843 
844 	destroy_default_flow(port_id);
845 
846 	/* Destroy session so that other cases can create the session again */
847 	for (i = 0; i < opts->nb_td; i++) {
848 		if (op == MCS_ENCAP || op == MCS_ENCAP_DECAP ||
849 				op == MCS_AUTH_ONLY || op == MCS_AUTH_VERIFY) {
850 			rte_security_session_destroy(ctx, tx_sess[i]);
851 			tx_sess[i] = NULL;
852 			rte_security_macsec_sc_destroy(ctx, tx_sc_id[i],
853 						RTE_SECURITY_MACSEC_DIR_TX);
854 			rte_security_macsec_sa_destroy(ctx, tx_sa_id[i][0],
855 						RTE_SECURITY_MACSEC_DIR_TX);
856 		}
857 		if (op == MCS_DECAP || op == MCS_ENCAP_DECAP ||
858 				op == MCS_VERIFY_ONLY || op == MCS_AUTH_VERIFY) {
859 			rte_security_session_destroy(ctx, rx_sess[i]);
860 			rx_sess[i] = NULL;
861 			rte_security_macsec_sc_destroy(ctx, rx_sc_id[i],
862 						RTE_SECURITY_MACSEC_DIR_RX);
863 			for (j = 0; j < RTE_SECURITY_MACSEC_NUM_AN; j++) {
864 				rte_security_macsec_sa_destroy(ctx, rx_sa_id[i][j],
865 						RTE_SECURITY_MACSEC_DIR_RX);
866 			}
867 		}
868 	}
869 
870 	return ret;
871 }
872 
873 static int
874 test_inline_macsec_encap_all(const void *data __rte_unused)
875 {
876 	const struct mcs_test_vector *cur_td;
877 	struct mcs_test_opts opts = {0};
878 	int err, all_err = 0;
879 	int i, size;
880 
881 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
882 	opts.encrypt = true;
883 	opts.protect_frames = true;
884 	opts.sa_in_use = 1;
885 	opts.nb_td = 1;
886 	opts.sectag_insert_mode = 1;
887 	opts.mtu = RTE_ETHER_MTU;
888 
889 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
890 	for (i = 0; i < size; i++) {
891 		cur_td = &list_mcs_cipher_vectors[i];
892 		err = test_macsec(&cur_td, MCS_ENCAP, &opts);
893 		if (err) {
894 			printf("\nCipher Auth Encryption case %d failed", cur_td->test_idx);
895 			err = -1;
896 		} else {
897 			printf("\nCipher Auth Encryption case %d Passed", cur_td->test_idx);
898 			err = 0;
899 		}
900 		all_err += err;
901 	}
902 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
903 
904 	return all_err;
905 }
906 
907 static int
908 test_inline_macsec_decap_all(const void *data __rte_unused)
909 {
910 	const struct mcs_test_vector *cur_td;
911 	struct mcs_test_opts opts = {0};
912 	int err, all_err = 0;
913 	int i, size;
914 
915 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
916 	opts.sa_in_use = 1;
917 	opts.nb_td = 1;
918 	opts.sectag_insert_mode = 1;
919 	opts.mtu = RTE_ETHER_MTU;
920 
921 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
922 	for (i = 0; i < size; i++) {
923 		cur_td = &list_mcs_cipher_vectors[i];
924 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
925 		if (err) {
926 			printf("\nCipher Auth Decryption case %d failed", cur_td->test_idx);
927 			err = -1;
928 		} else {
929 			printf("\nCipher Auth Decryption case %d Passed", cur_td->test_idx);
930 			err = 0;
931 		}
932 		all_err += err;
933 	}
934 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
935 
936 	return all_err;
937 }
938 
939 static int
940 test_inline_macsec_auth_only_all(const void *data __rte_unused)
941 {
942 	const struct mcs_test_vector *cur_td;
943 	struct mcs_test_opts opts = {0};
944 	int err, all_err = 0;
945 	int i, size;
946 
947 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
948 	opts.protect_frames = true;
949 	opts.sa_in_use = 1;
950 	opts.nb_td = 1;
951 	opts.sectag_insert_mode = 1;
952 	opts.mtu = RTE_ETHER_MTU;
953 
954 	size = (sizeof(list_mcs_integrity_vectors) / sizeof((list_mcs_integrity_vectors)[0]));
955 
956 	for (i = 0; i < size; i++) {
957 		cur_td = &list_mcs_integrity_vectors[i];
958 		err = test_macsec(&cur_td, MCS_AUTH_ONLY, &opts);
959 		if (err) {
960 			printf("\nAuth Generate case %d failed", cur_td->test_idx);
961 			err = -1;
962 		} else {
963 			printf("\nAuth Generate case %d Passed", cur_td->test_idx);
964 			err = 0;
965 		}
966 		all_err += err;
967 	}
968 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
969 
970 	return all_err;
971 }
972 
973 static int
974 test_inline_macsec_verify_only_all(const void *data __rte_unused)
975 {
976 	const struct mcs_test_vector *cur_td;
977 	struct mcs_test_opts opts = {0};
978 	int err, all_err = 0;
979 	int i, size;
980 
981 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
982 	opts.sa_in_use = 1;
983 	opts.nb_td = 1;
984 	opts.sectag_insert_mode = 1;
985 	opts.mtu = RTE_ETHER_MTU;
986 
987 	size = (sizeof(list_mcs_integrity_vectors) / sizeof((list_mcs_integrity_vectors)[0]));
988 
989 	for (i = 0; i < size; i++) {
990 		cur_td = &list_mcs_integrity_vectors[i];
991 		err = test_macsec(&cur_td, MCS_VERIFY_ONLY, &opts);
992 		if (err) {
993 			printf("\nAuth Verify case %d failed", cur_td->test_idx);
994 			err = -1;
995 		} else {
996 			printf("\nAuth Verify case %d Passed", cur_td->test_idx);
997 			err = 0;
998 		}
999 		all_err += err;
1000 	}
1001 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1002 
1003 	return all_err;
1004 }
1005 
1006 static int
1007 test_inline_macsec_encap_decap_all(const void *data __rte_unused)
1008 {
1009 	const struct mcs_test_vector *cur_td;
1010 	struct mcs_test_opts opts = {0};
1011 	int err, all_err = 0;
1012 	int i, size;
1013 
1014 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1015 	opts.encrypt = true;
1016 	opts.protect_frames = true;
1017 	opts.sa_in_use = 1;
1018 	opts.nb_td = 1;
1019 	opts.sectag_insert_mode = 1;
1020 	opts.mtu = RTE_ETHER_MTU;
1021 
1022 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
1023 
1024 	for (i = 0; i < size; i++) {
1025 		cur_td = &list_mcs_cipher_vectors[i];
1026 		err = test_macsec(&cur_td, MCS_ENCAP_DECAP, &opts);
1027 		if (err) {
1028 			printf("\nCipher Auth Encap-decap case %d failed", cur_td->test_idx);
1029 			err = -1;
1030 		} else {
1031 			printf("\nCipher Auth Encap-decap case %d Passed", cur_td->test_idx);
1032 			err = 0;
1033 		}
1034 		all_err += err;
1035 	}
1036 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1037 
1038 	return all_err;
1039 }
1040 
1041 
1042 static int
1043 test_inline_macsec_auth_verify_all(const void *data __rte_unused)
1044 {
1045 	const struct mcs_test_vector *cur_td;
1046 	struct mcs_test_opts opts = {0};
1047 	int err, all_err = 0;
1048 	int i, size;
1049 
1050 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1051 	opts.protect_frames = true;
1052 	opts.sa_in_use = 1;
1053 	opts.nb_td = 1;
1054 	opts.sectag_insert_mode = 1;
1055 	opts.mtu = RTE_ETHER_MTU;
1056 
1057 	size = (sizeof(list_mcs_integrity_vectors) / sizeof((list_mcs_integrity_vectors)[0]));
1058 
1059 	for (i = 0; i < size; i++) {
1060 		cur_td = &list_mcs_integrity_vectors[i];
1061 		err = test_macsec(&cur_td, MCS_AUTH_VERIFY, &opts);
1062 		if (err) {
1063 			printf("\nAuth Generate + Verify case %d failed", cur_td->test_idx);
1064 			err = -1;
1065 		} else {
1066 			printf("\nAuth Generate + Verify case %d Passed", cur_td->test_idx);
1067 			err = 0;
1068 		}
1069 		all_err += err;
1070 	}
1071 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
1072 
1073 	return all_err;
1074 }
1075 
1076 static int
1077 test_inline_macsec_multi_flow(const void *data __rte_unused)
1078 {
1079 	const struct mcs_test_vector *tv[MCS_MAX_FLOWS];
1080 	struct mcs_test_vector iter[MCS_MAX_FLOWS];
1081 	struct mcs_test_opts opts = {0};
1082 	int i, err;
1083 
1084 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
1085 	opts.encrypt = true;
1086 	opts.protect_frames = true;
1087 	opts.sa_in_use = 1;
1088 	opts.nb_td = MCS_MAX_FLOWS;
1089 	opts.sectag_insert_mode = 1;
1090 	opts.mtu = RTE_ETHER_MTU;
1091 
1092 	for (i = 0; i < MCS_MAX_FLOWS; i++) {
1093 		memcpy(&iter[i].sa_key.data, sa_key, MCS_MULTI_FLOW_TD_KEY_SZ);
1094 		memcpy(&iter[i].plain_pkt.data, eth_addrs[i], 2 * RTE_ETHER_ADDR_LEN);
1095 		memcpy(&iter[i].plain_pkt.data[2 * RTE_ETHER_ADDR_LEN], plain_user_data,
1096 		       MCS_MULTI_FLOW_TD_PLAIN_DATA_SZ);
1097 		memcpy(&iter[i].secure_pkt.data, eth_addrs[i], 2 * RTE_ETHER_ADDR_LEN);
1098 		memcpy(&iter[i].secure_pkt.data[2 * RTE_ETHER_ADDR_LEN], secure_user_data,
1099 		       MCS_MULTI_FLOW_TD_SECURE_DATA_SZ);
1100 		iter[i].sa_key.len = MCS_MULTI_FLOW_TD_KEY_SZ;
1101 		iter[i].plain_pkt.len = MCS_MULTI_FLOW_TD_PLAIN_DATA_SZ +
1102 					(2 * RTE_ETHER_ADDR_LEN);
1103 		iter[i].secure_pkt.len = MCS_MULTI_FLOW_TD_SECURE_DATA_SZ +
1104 					(2 * RTE_ETHER_ADDR_LEN);
1105 		iter[i].alg = RTE_SECURITY_MACSEC_ALG_GCM_128;
1106 		iter[i].ssci = 0x0;
1107 		iter[i].xpn = 0x0;
1108 		tv[i] = (const struct mcs_test_vector *)&iter[i];
1109 	}
1110 	err = test_macsec(tv, MCS_ENCAP_DECAP, &opts);
1111 	if (err) {
1112 		printf("\nCipher Auth Encryption multi flow failed");
1113 		err = -1;
1114 	} else {
1115 		printf("\nCipher Auth Encryption multi flow Passed");
1116 		err = 0;
1117 	}
1118 	return err;
1119 }
1120 
1121 static int
1122 ut_setup_inline_macsec(void)
1123 {
1124 	int ret;
1125 
1126 	/* Start device */
1127 	ret = rte_eth_dev_start(port_id);
1128 	if (ret < 0) {
1129 		printf("rte_eth_dev_start: err=%d, port=%d\n",
1130 			ret, port_id);
1131 		return ret;
1132 	}
1133 	/* always enable promiscuous */
1134 	ret = rte_eth_promiscuous_enable(port_id);
1135 	if (ret != 0) {
1136 		printf("rte_eth_promiscuous_enable: err=%s, port=%d\n",
1137 			rte_strerror(-ret), port_id);
1138 		return ret;
1139 	}
1140 
1141 	check_all_ports_link_status(1, RTE_PORT_ALL);
1142 
1143 	return 0;
1144 }
1145 
1146 static void
1147 ut_teardown_inline_macsec(void)
1148 {
1149 	uint16_t portid;
1150 	int ret;
1151 
1152 	/* port tear down */
1153 	RTE_ETH_FOREACH_DEV(portid) {
1154 		ret = rte_eth_dev_stop(portid);
1155 		if (ret != 0)
1156 			printf("rte_eth_dev_stop: err=%s, port=%u\n",
1157 			       rte_strerror(-ret), portid);
1158 
1159 	}
1160 }
1161 
1162 static int
1163 inline_macsec_testsuite_setup(void)
1164 {
1165 	uint16_t nb_rxd;
1166 	uint16_t nb_txd;
1167 	uint16_t nb_ports;
1168 	int ret;
1169 	uint16_t nb_rx_queue = 1, nb_tx_queue = 1;
1170 
1171 	printf("Start inline MACsec test.\n");
1172 
1173 	nb_ports = rte_eth_dev_count_avail();
1174 	if (nb_ports < NB_ETHPORTS_USED) {
1175 		printf("At least %u port(s) used for test\n",
1176 		       NB_ETHPORTS_USED);
1177 		return TEST_SKIPPED;
1178 	}
1179 
1180 	ret = init_mempools(NB_MBUF);
1181 	if (ret)
1182 		return ret;
1183 
1184 	if (tx_pkts_burst == NULL) {
1185 		tx_pkts_burst = (struct rte_mbuf **)rte_calloc("tx_buff",
1186 					  MAX_TRAFFIC_BURST,
1187 					  sizeof(void *),
1188 					  RTE_CACHE_LINE_SIZE);
1189 		if (!tx_pkts_burst)
1190 			return TEST_FAILED;
1191 
1192 		rx_pkts_burst = (struct rte_mbuf **)rte_calloc("rx_buff",
1193 					  MAX_TRAFFIC_BURST,
1194 					  sizeof(void *),
1195 					  RTE_CACHE_LINE_SIZE);
1196 		if (!rx_pkts_burst)
1197 			return TEST_FAILED;
1198 	}
1199 
1200 	printf("Generate %d packets\n", MAX_TRAFFIC_BURST);
1201 
1202 	nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
1203 	nb_txd = RTE_TEST_TX_DESC_DEFAULT;
1204 
1205 	/* configuring port 0 for the test is enough */
1206 	port_id = 0;
1207 	/* port configure */
1208 	ret = rte_eth_dev_configure(port_id, nb_rx_queue,
1209 				    nb_tx_queue, &port_conf);
1210 	if (ret < 0) {
1211 		printf("Cannot configure device: err=%d, port=%d\n",
1212 			 ret, port_id);
1213 		return ret;
1214 	}
1215 	ret = rte_eth_macaddr_get(port_id, &ports_eth_addr[port_id]);
1216 	if (ret < 0) {
1217 		printf("Cannot get mac address: err=%d, port=%d\n",
1218 			 ret, port_id);
1219 		return ret;
1220 	}
1221 	printf("Port %u ", port_id);
1222 	print_ethaddr("Address:", &ports_eth_addr[port_id]);
1223 	printf("\n");
1224 
1225 	/* tx queue setup */
1226 	ret = rte_eth_tx_queue_setup(port_id, 0, nb_txd,
1227 				     SOCKET_ID_ANY, &tx_conf);
1228 	if (ret < 0) {
1229 		printf("rte_eth_tx_queue_setup: err=%d, port=%d\n",
1230 				ret, port_id);
1231 		return ret;
1232 	}
1233 	/* rx queue steup */
1234 	ret = rte_eth_rx_queue_setup(port_id, 0, nb_rxd, SOCKET_ID_ANY,
1235 				     &rx_conf, mbufpool);
1236 	if (ret < 0) {
1237 		printf("rte_eth_rx_queue_setup: err=%d, port=%d\n",
1238 				ret, port_id);
1239 		return ret;
1240 	}
1241 
1242 	return 0;
1243 }
1244 
1245 static void
1246 inline_macsec_testsuite_teardown(void)
1247 {
1248 	uint16_t portid;
1249 	int ret;
1250 
1251 	/* port tear down */
1252 	RTE_ETH_FOREACH_DEV(portid) {
1253 		ret = rte_eth_dev_reset(portid);
1254 		if (ret != 0)
1255 			printf("rte_eth_dev_reset: err=%s, port=%u\n",
1256 			       rte_strerror(-ret), port_id);
1257 	}
1258 	rte_free(tx_pkts_burst);
1259 	rte_free(rx_pkts_burst);
1260 }
1261 
1262 
1263 static struct unit_test_suite inline_macsec_testsuite  = {
1264 	.suite_name = "Inline MACsec Ethernet Device Unit Test Suite",
1265 	.unit_test_cases = {
1266 		TEST_CASE_NAMED_ST(
1267 			"MACsec Encap + decap Multi flow",
1268 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1269 			test_inline_macsec_multi_flow),
1270 		TEST_CASE_NAMED_ST(
1271 			"MACsec encap(Cipher+Auth) known vector",
1272 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1273 			test_inline_macsec_encap_all),
1274 		TEST_CASE_NAMED_ST(
1275 			"MACsec decap(De-cipher+verify) known vector",
1276 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1277 			test_inline_macsec_decap_all),
1278 		TEST_CASE_NAMED_ST(
1279 			"MACsec auth only known vector",
1280 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1281 			test_inline_macsec_auth_only_all),
1282 		TEST_CASE_NAMED_ST(
1283 			"MACsec verify only known vector",
1284 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1285 			test_inline_macsec_verify_only_all),
1286 		TEST_CASE_NAMED_ST(
1287 			"MACsec encap + decap known vector",
1288 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1289 			test_inline_macsec_encap_decap_all),
1290 		TEST_CASE_NAMED_ST(
1291 			"MACsec auth + verify known vector",
1292 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1293 			test_inline_macsec_auth_verify_all),
1294 
1295 		TEST_CASES_END() /**< NULL terminate unit test array */
1296 	},
1297 };
1298 
1299 static int
1300 test_inline_macsec(void)
1301 {
1302 	inline_macsec_testsuite.setup = inline_macsec_testsuite_setup;
1303 	inline_macsec_testsuite.teardown = inline_macsec_testsuite_teardown;
1304 	return unit_test_suite_runner(&inline_macsec_testsuite);
1305 }
1306 
1307 #endif /* !RTE_EXEC_ENV_WINDOWS */
1308 
1309 REGISTER_TEST_COMMAND(inline_macsec_autotest, test_inline_macsec);
1310