xref: /dpdk/app/test/test_security_inline_macsec.c (revision 993ea577a0060ea75de4ad951d743f830f265416)
1*993ea577SAkhil Goyal /* SPDX-License-Identifier: BSD-3-Clause
2*993ea577SAkhil Goyal  * Copyright(C) 2023 Marvell.
3*993ea577SAkhil Goyal  */
4*993ea577SAkhil Goyal 
5*993ea577SAkhil Goyal #include <stdio.h>
6*993ea577SAkhil Goyal #include <inttypes.h>
7*993ea577SAkhil Goyal 
8*993ea577SAkhil Goyal #include <rte_ethdev.h>
9*993ea577SAkhil Goyal #include <rte_malloc.h>
10*993ea577SAkhil Goyal #include <rte_security.h>
11*993ea577SAkhil Goyal 
12*993ea577SAkhil Goyal #include "test.h"
13*993ea577SAkhil Goyal #include "test_security_inline_macsec_vectors.h"
14*993ea577SAkhil Goyal 
15*993ea577SAkhil Goyal #ifdef RTE_EXEC_ENV_WINDOWS
16*993ea577SAkhil Goyal static int
17*993ea577SAkhil Goyal test_inline_macsec(void)
18*993ea577SAkhil Goyal {
19*993ea577SAkhil Goyal 	printf("Inline MACsec not supported on Windows, skipping test\n");
20*993ea577SAkhil Goyal 	return TEST_SKIPPED;
21*993ea577SAkhil Goyal }
22*993ea577SAkhil Goyal 
23*993ea577SAkhil Goyal #else
24*993ea577SAkhil Goyal 
25*993ea577SAkhil Goyal #define NB_ETHPORTS_USED		1
26*993ea577SAkhil Goyal #define MEMPOOL_CACHE_SIZE		32
27*993ea577SAkhil Goyal #define RTE_TEST_RX_DESC_DEFAULT	1024
28*993ea577SAkhil Goyal #define RTE_TEST_TX_DESC_DEFAULT	1024
29*993ea577SAkhil Goyal #define RTE_PORT_ALL		(~(uint16_t)0x0)
30*993ea577SAkhil Goyal 
31*993ea577SAkhil Goyal #define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
32*993ea577SAkhil Goyal #define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
33*993ea577SAkhil Goyal #define RX_WTHRESH 0 /**< Default values of RX write-back threshold reg. */
34*993ea577SAkhil Goyal 
35*993ea577SAkhil Goyal #define TX_PTHRESH 32 /**< Default values of TX prefetch threshold reg. */
36*993ea577SAkhil Goyal #define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
37*993ea577SAkhil Goyal #define TX_WTHRESH 0  /**< Default values of TX write-back threshold reg. */
38*993ea577SAkhil Goyal 
39*993ea577SAkhil Goyal #define MAX_TRAFFIC_BURST		2048
40*993ea577SAkhil Goyal #define NB_MBUF				10240
41*993ea577SAkhil Goyal 
42*993ea577SAkhil Goyal #define MCS_INVALID_SA			0xFFFF
43*993ea577SAkhil Goyal #define MCS_DEFAULT_PN_THRESHOLD	0xFFFFF
44*993ea577SAkhil Goyal 
45*993ea577SAkhil Goyal static struct rte_mempool *mbufpool;
46*993ea577SAkhil Goyal static struct rte_mempool *sess_pool;
47*993ea577SAkhil Goyal /* ethernet addresses of ports */
48*993ea577SAkhil Goyal static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
49*993ea577SAkhil Goyal 
50*993ea577SAkhil Goyal struct mcs_test_opts {
51*993ea577SAkhil Goyal 	int val_frames;
52*993ea577SAkhil Goyal 	int nb_td;
53*993ea577SAkhil Goyal 	uint16_t mtu;
54*993ea577SAkhil Goyal 	uint8_t sa_in_use;
55*993ea577SAkhil Goyal 	bool encrypt;
56*993ea577SAkhil Goyal 	bool protect_frames;
57*993ea577SAkhil Goyal 	uint8_t sectag_insert_mode;
58*993ea577SAkhil Goyal 	uint8_t nb_vlan;
59*993ea577SAkhil Goyal 	uint32_t replay_win_sz;
60*993ea577SAkhil Goyal 	uint8_t replay_protect;
61*993ea577SAkhil Goyal 	uint8_t rekey_en;
62*993ea577SAkhil Goyal 	const struct mcs_test_vector *rekey_td;
63*993ea577SAkhil Goyal 	bool dump_all_stats;
64*993ea577SAkhil Goyal 	uint8_t check_untagged_rx;
65*993ea577SAkhil Goyal 	uint8_t check_bad_tag_cnt;
66*993ea577SAkhil Goyal 	uint8_t check_sa_not_in_use;
67*993ea577SAkhil Goyal 	uint8_t check_decap_stats;
68*993ea577SAkhil Goyal 	uint8_t check_verify_only_stats;
69*993ea577SAkhil Goyal 	uint8_t check_pkts_invalid_stats;
70*993ea577SAkhil Goyal 	uint8_t check_pkts_unchecked_stats;
71*993ea577SAkhil Goyal 	uint8_t check_out_pkts_untagged;
72*993ea577SAkhil Goyal 	uint8_t check_out_pkts_toolong;
73*993ea577SAkhil Goyal 	uint8_t check_encap_stats;
74*993ea577SAkhil Goyal 	uint8_t check_auth_only_stats;
75*993ea577SAkhil Goyal 	uint8_t check_sectag_interrupts;
76*993ea577SAkhil Goyal };
77*993ea577SAkhil Goyal 
78*993ea577SAkhil Goyal static struct rte_eth_conf port_conf = {
79*993ea577SAkhil Goyal 	.rxmode = {
80*993ea577SAkhil Goyal 		.mq_mode = RTE_ETH_MQ_RX_NONE,
81*993ea577SAkhil Goyal 		.offloads = RTE_ETH_RX_OFFLOAD_CHECKSUM |
82*993ea577SAkhil Goyal 			    RTE_ETH_RX_OFFLOAD_MACSEC_STRIP,
83*993ea577SAkhil Goyal 	},
84*993ea577SAkhil Goyal 	.txmode = {
85*993ea577SAkhil Goyal 		.mq_mode = RTE_ETH_MQ_TX_NONE,
86*993ea577SAkhil Goyal 		.offloads = RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
87*993ea577SAkhil Goyal 			    RTE_ETH_TX_OFFLOAD_MACSEC_INSERT,
88*993ea577SAkhil Goyal 	},
89*993ea577SAkhil Goyal 	.lpbk_mode = 1,  /* enable loopback */
90*993ea577SAkhil Goyal };
91*993ea577SAkhil Goyal 
92*993ea577SAkhil Goyal static struct rte_eth_rxconf rx_conf = {
93*993ea577SAkhil Goyal 	.rx_thresh = {
94*993ea577SAkhil Goyal 		.pthresh = RX_PTHRESH,
95*993ea577SAkhil Goyal 		.hthresh = RX_HTHRESH,
96*993ea577SAkhil Goyal 		.wthresh = RX_WTHRESH,
97*993ea577SAkhil Goyal 	},
98*993ea577SAkhil Goyal 	.rx_free_thresh = 32,
99*993ea577SAkhil Goyal };
100*993ea577SAkhil Goyal 
101*993ea577SAkhil Goyal static struct rte_eth_txconf tx_conf = {
102*993ea577SAkhil Goyal 	.tx_thresh = {
103*993ea577SAkhil Goyal 		.pthresh = TX_PTHRESH,
104*993ea577SAkhil Goyal 		.hthresh = TX_HTHRESH,
105*993ea577SAkhil Goyal 		.wthresh = TX_WTHRESH,
106*993ea577SAkhil Goyal 	},
107*993ea577SAkhil Goyal 	.tx_free_thresh = 32, /* Use PMD default values */
108*993ea577SAkhil Goyal 	.tx_rs_thresh = 32, /* Use PMD default values */
109*993ea577SAkhil Goyal };
110*993ea577SAkhil Goyal 
111*993ea577SAkhil Goyal static uint16_t port_id;
112*993ea577SAkhil Goyal 
113*993ea577SAkhil Goyal static uint64_t link_mbps;
114*993ea577SAkhil Goyal 
115*993ea577SAkhil Goyal static struct rte_flow *default_tx_flow[RTE_MAX_ETHPORTS];
116*993ea577SAkhil Goyal static struct rte_flow *default_rx_flow[RTE_MAX_ETHPORTS];
117*993ea577SAkhil Goyal 
118*993ea577SAkhil Goyal static struct rte_mbuf **tx_pkts_burst;
119*993ea577SAkhil Goyal static struct rte_mbuf **rx_pkts_burst;
120*993ea577SAkhil Goyal 
121*993ea577SAkhil Goyal static inline struct rte_mbuf *
122*993ea577SAkhil Goyal init_packet(struct rte_mempool *mp, const uint8_t *data, unsigned int len)
123*993ea577SAkhil Goyal {
124*993ea577SAkhil Goyal 	struct rte_mbuf *pkt;
125*993ea577SAkhil Goyal 
126*993ea577SAkhil Goyal 	pkt = rte_pktmbuf_alloc(mp);
127*993ea577SAkhil Goyal 	if (pkt == NULL)
128*993ea577SAkhil Goyal 		return NULL;
129*993ea577SAkhil Goyal 
130*993ea577SAkhil Goyal 	rte_memcpy(rte_pktmbuf_append(pkt, len), data, len);
131*993ea577SAkhil Goyal 
132*993ea577SAkhil Goyal 	return pkt;
133*993ea577SAkhil Goyal }
134*993ea577SAkhil Goyal 
135*993ea577SAkhil Goyal static int
136*993ea577SAkhil Goyal init_mempools(unsigned int nb_mbuf)
137*993ea577SAkhil Goyal {
138*993ea577SAkhil Goyal 	struct rte_security_ctx *sec_ctx;
139*993ea577SAkhil Goyal 	uint16_t nb_sess = 512;
140*993ea577SAkhil Goyal 	uint32_t sess_sz;
141*993ea577SAkhil Goyal 	char s[64];
142*993ea577SAkhil Goyal 
143*993ea577SAkhil Goyal 	if (mbufpool == NULL) {
144*993ea577SAkhil Goyal 		snprintf(s, sizeof(s), "mbuf_pool");
145*993ea577SAkhil Goyal 		mbufpool = rte_pktmbuf_pool_create(s, nb_mbuf,
146*993ea577SAkhil Goyal 				MEMPOOL_CACHE_SIZE, 0,
147*993ea577SAkhil Goyal 				RTE_MBUF_DEFAULT_BUF_SIZE, SOCKET_ID_ANY);
148*993ea577SAkhil Goyal 		if (mbufpool == NULL) {
149*993ea577SAkhil Goyal 			printf("Cannot init mbuf pool\n");
150*993ea577SAkhil Goyal 			return TEST_FAILED;
151*993ea577SAkhil Goyal 		}
152*993ea577SAkhil Goyal 		printf("Allocated mbuf pool\n");
153*993ea577SAkhil Goyal 	}
154*993ea577SAkhil Goyal 
155*993ea577SAkhil Goyal 	sec_ctx = rte_eth_dev_get_sec_ctx(port_id);
156*993ea577SAkhil Goyal 	if (sec_ctx == NULL) {
157*993ea577SAkhil Goyal 		printf("Device does not support Security ctx\n");
158*993ea577SAkhil Goyal 		return TEST_SKIPPED;
159*993ea577SAkhil Goyal 	}
160*993ea577SAkhil Goyal 	sess_sz = rte_security_session_get_size(sec_ctx);
161*993ea577SAkhil Goyal 	if (sess_pool == NULL) {
162*993ea577SAkhil Goyal 		snprintf(s, sizeof(s), "sess_pool");
163*993ea577SAkhil Goyal 		sess_pool = rte_mempool_create(s, nb_sess, sess_sz,
164*993ea577SAkhil Goyal 				MEMPOOL_CACHE_SIZE, 0,
165*993ea577SAkhil Goyal 				NULL, NULL, NULL, NULL,
166*993ea577SAkhil Goyal 				SOCKET_ID_ANY, 0);
167*993ea577SAkhil Goyal 		if (sess_pool == NULL) {
168*993ea577SAkhil Goyal 			printf("Cannot init sess pool\n");
169*993ea577SAkhil Goyal 			return TEST_FAILED;
170*993ea577SAkhil Goyal 		}
171*993ea577SAkhil Goyal 		printf("Allocated sess pool\n");
172*993ea577SAkhil Goyal 	}
173*993ea577SAkhil Goyal 
174*993ea577SAkhil Goyal 	return 0;
175*993ea577SAkhil Goyal }
176*993ea577SAkhil Goyal 
177*993ea577SAkhil Goyal static void
178*993ea577SAkhil Goyal fill_macsec_sa_conf(const struct mcs_test_vector *td, struct rte_security_macsec_sa *sa,
179*993ea577SAkhil Goyal 			enum rte_security_macsec_direction dir, uint8_t an, uint8_t tci_off)
180*993ea577SAkhil Goyal {
181*993ea577SAkhil Goyal 	sa->dir = dir;
182*993ea577SAkhil Goyal 
183*993ea577SAkhil Goyal 	sa->key.data = td->sa_key.data;
184*993ea577SAkhil Goyal 	sa->key.length = td->sa_key.len;
185*993ea577SAkhil Goyal 
186*993ea577SAkhil Goyal 	memcpy((uint8_t *)sa->salt, (const uint8_t *)td->salt, RTE_SECURITY_MACSEC_SALT_LEN);
187*993ea577SAkhil Goyal 
188*993ea577SAkhil Goyal 	/* AN is set as per the value in secure packet in test vector */
189*993ea577SAkhil Goyal 	sa->an = an & RTE_MACSEC_AN_MASK;
190*993ea577SAkhil Goyal 
191*993ea577SAkhil Goyal 	sa->ssci = td->ssci;
192*993ea577SAkhil Goyal 	sa->xpn = td->xpn;
193*993ea577SAkhil Goyal 	/* Starting packet number which is expected to come next.
194*993ea577SAkhil Goyal 	 * It is take from the test vector so that we can match the out packet.
195*993ea577SAkhil Goyal 	 */
196*993ea577SAkhil Goyal 	sa->next_pn = *(const uint32_t *)(&td->secure_pkt.data[tci_off + 2]);
197*993ea577SAkhil Goyal }
198*993ea577SAkhil Goyal 
199*993ea577SAkhil Goyal static void
200*993ea577SAkhil Goyal fill_macsec_sc_conf(const struct mcs_test_vector *td,
201*993ea577SAkhil Goyal 		    struct rte_security_macsec_sc *sc_conf,
202*993ea577SAkhil Goyal 		    const struct mcs_test_opts *opts,
203*993ea577SAkhil Goyal 		    enum rte_security_macsec_direction dir,
204*993ea577SAkhil Goyal 		    uint16_t sa_id[], uint8_t tci_off)
205*993ea577SAkhil Goyal {
206*993ea577SAkhil Goyal 	uint8_t i;
207*993ea577SAkhil Goyal 
208*993ea577SAkhil Goyal 	sc_conf->dir = dir;
209*993ea577SAkhil Goyal 	if (dir == RTE_SECURITY_MACSEC_DIR_TX) {
210*993ea577SAkhil Goyal 		sc_conf->sc_tx.sa_id = sa_id[0];
211*993ea577SAkhil Goyal 		if (sa_id[1] != MCS_INVALID_SA) {
212*993ea577SAkhil Goyal 			sc_conf->sc_tx.sa_id_rekey = sa_id[1];
213*993ea577SAkhil Goyal 			sc_conf->sc_tx.re_key_en = 1;
214*993ea577SAkhil Goyal 		}
215*993ea577SAkhil Goyal 		sc_conf->sc_tx.active = 1;
216*993ea577SAkhil Goyal 		/* is SCI valid */
217*993ea577SAkhil Goyal 		if (td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_SC) {
218*993ea577SAkhil Goyal 			memcpy(&sc_conf->sc_tx.sci, &td->secure_pkt.data[tci_off + 6],
219*993ea577SAkhil Goyal 					sizeof(sc_conf->sc_tx.sci));
220*993ea577SAkhil Goyal 			sc_conf->sc_tx.sci = rte_be_to_cpu_64(sc_conf->sc_tx.sci);
221*993ea577SAkhil Goyal 		} else if (td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_ES) {
222*993ea577SAkhil Goyal 			/* sci = source_mac + port_id when ES.bit = 1 & SC.bit = 0 */
223*993ea577SAkhil Goyal 			const uint8_t *smac = td->plain_pkt.data + RTE_ETHER_ADDR_LEN;
224*993ea577SAkhil Goyal 			uint8_t *ptr = (uint8_t *)&sc_conf->sc_tx.sci;
225*993ea577SAkhil Goyal 
226*993ea577SAkhil Goyal 			ptr[0] = 0x01;
227*993ea577SAkhil Goyal 			ptr[1] = 0;
228*993ea577SAkhil Goyal 			for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
229*993ea577SAkhil Goyal 				ptr[2 + i] = smac[RTE_ETHER_ADDR_LEN - 1 - i];
230*993ea577SAkhil Goyal 		} else {
231*993ea577SAkhil Goyal 			/* use some default SCI */
232*993ea577SAkhil Goyal 			sc_conf->sc_tx.sci = 0xf1341e023a2b1c5d;
233*993ea577SAkhil Goyal 		}
234*993ea577SAkhil Goyal 	} else {
235*993ea577SAkhil Goyal 		for (i = 0; i < RTE_SECURITY_MACSEC_NUM_AN; i++) {
236*993ea577SAkhil Goyal 			sc_conf->sc_rx.sa_id[i] = sa_id[i];
237*993ea577SAkhil Goyal 			sc_conf->sc_rx.sa_in_use[i] = opts->sa_in_use;
238*993ea577SAkhil Goyal 		}
239*993ea577SAkhil Goyal 		sc_conf->sc_rx.active = 1;
240*993ea577SAkhil Goyal 	}
241*993ea577SAkhil Goyal }
242*993ea577SAkhil Goyal 
243*993ea577SAkhil Goyal 
244*993ea577SAkhil Goyal /* Create Inline MACsec session */
245*993ea577SAkhil Goyal static int
246*993ea577SAkhil Goyal fill_session_conf(const struct mcs_test_vector *td, uint16_t portid __rte_unused,
247*993ea577SAkhil Goyal 		const struct mcs_test_opts *opts,
248*993ea577SAkhil Goyal 		struct rte_security_session_conf *sess_conf,
249*993ea577SAkhil Goyal 		enum rte_security_macsec_direction dir,
250*993ea577SAkhil Goyal 		uint16_t sc_id,
251*993ea577SAkhil Goyal 		uint8_t tci_off)
252*993ea577SAkhil Goyal {
253*993ea577SAkhil Goyal 	sess_conf->action_type = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL;
254*993ea577SAkhil Goyal 	sess_conf->protocol = RTE_SECURITY_PROTOCOL_MACSEC;
255*993ea577SAkhil Goyal 	sess_conf->macsec.dir = dir;
256*993ea577SAkhil Goyal 	sess_conf->macsec.alg = td->alg;
257*993ea577SAkhil Goyal 	sess_conf->macsec.cipher_off = 0;
258*993ea577SAkhil Goyal 	if (td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_SC) {
259*993ea577SAkhil Goyal 		sess_conf->macsec.sci = rte_be_to_cpu_64(*(const uint64_t *)
260*993ea577SAkhil Goyal 					(&td->secure_pkt.data[tci_off + 6]));
261*993ea577SAkhil Goyal 	} else if (td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_ES) {
262*993ea577SAkhil Goyal 		/* sci = source_mac + port_id when ES.bit = 1 & SC.bit = 0 */
263*993ea577SAkhil Goyal 		const uint8_t *smac = td->plain_pkt.data + RTE_ETHER_ADDR_LEN;
264*993ea577SAkhil Goyal 		uint8_t *ptr = (uint8_t *)&sess_conf->macsec.sci;
265*993ea577SAkhil Goyal 		uint8_t j;
266*993ea577SAkhil Goyal 
267*993ea577SAkhil Goyal 		ptr[0] = 0x01;
268*993ea577SAkhil Goyal 		ptr[1] = 0;
269*993ea577SAkhil Goyal 		for (j = 0; j < RTE_ETHER_ADDR_LEN; j++)
270*993ea577SAkhil Goyal 			ptr[2 + j] = smac[RTE_ETHER_ADDR_LEN - 1 - j];
271*993ea577SAkhil Goyal 	}
272*993ea577SAkhil Goyal 	sess_conf->macsec.sc_id = sc_id;
273*993ea577SAkhil Goyal 	if (dir == RTE_SECURITY_MACSEC_DIR_TX) {
274*993ea577SAkhil Goyal 		sess_conf->macsec.tx_secy.mtu = opts->mtu;
275*993ea577SAkhil Goyal 		sess_conf->macsec.tx_secy.sectag_off = (opts->sectag_insert_mode == 1) ?
276*993ea577SAkhil Goyal 							2 * RTE_ETHER_ADDR_LEN :
277*993ea577SAkhil Goyal 							RTE_VLAN_HLEN;
278*993ea577SAkhil Goyal 		sess_conf->macsec.tx_secy.sectag_insert_mode = opts->sectag_insert_mode;
279*993ea577SAkhil Goyal 		sess_conf->macsec.tx_secy.ctrl_port_enable = 1;
280*993ea577SAkhil Goyal 		sess_conf->macsec.tx_secy.sectag_version = 0;
281*993ea577SAkhil Goyal 		sess_conf->macsec.tx_secy.end_station =
282*993ea577SAkhil Goyal 					(td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_ES) >> 6;
283*993ea577SAkhil Goyal 		sess_conf->macsec.tx_secy.send_sci =
284*993ea577SAkhil Goyal 					(td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_SC) >> 5;
285*993ea577SAkhil Goyal 		sess_conf->macsec.tx_secy.scb =
286*993ea577SAkhil Goyal 					(td->secure_pkt.data[tci_off] & RTE_MACSEC_TCI_SCB) >> 4;
287*993ea577SAkhil Goyal 		sess_conf->macsec.tx_secy.encrypt = opts->encrypt;
288*993ea577SAkhil Goyal 		sess_conf->macsec.tx_secy.protect_frames = opts->protect_frames;
289*993ea577SAkhil Goyal 		sess_conf->macsec.tx_secy.icv_include_da_sa = 1;
290*993ea577SAkhil Goyal 	} else {
291*993ea577SAkhil Goyal 		sess_conf->macsec.rx_secy.replay_win_sz = opts->replay_win_sz;
292*993ea577SAkhil Goyal 		sess_conf->macsec.rx_secy.replay_protect = opts->replay_protect;
293*993ea577SAkhil Goyal 		sess_conf->macsec.rx_secy.icv_include_da_sa = 1;
294*993ea577SAkhil Goyal 		sess_conf->macsec.rx_secy.ctrl_port_enable = 1;
295*993ea577SAkhil Goyal 		sess_conf->macsec.rx_secy.preserve_sectag = 0;
296*993ea577SAkhil Goyal 		sess_conf->macsec.rx_secy.preserve_icv = 0;
297*993ea577SAkhil Goyal 		sess_conf->macsec.rx_secy.validate_frames = opts->val_frames;
298*993ea577SAkhil Goyal 	}
299*993ea577SAkhil Goyal 
300*993ea577SAkhil Goyal 	return 0;
301*993ea577SAkhil Goyal }
302*993ea577SAkhil Goyal 
303*993ea577SAkhil Goyal static int
304*993ea577SAkhil Goyal create_default_flow(const struct mcs_test_vector *td, uint16_t portid,
305*993ea577SAkhil Goyal 		    enum rte_security_macsec_direction dir, void *sess)
306*993ea577SAkhil Goyal {
307*993ea577SAkhil Goyal 	struct rte_flow_action action[2];
308*993ea577SAkhil Goyal 	struct rte_flow_item pattern[2];
309*993ea577SAkhil Goyal 	struct rte_flow_attr attr = {0};
310*993ea577SAkhil Goyal 	struct rte_flow_error err;
311*993ea577SAkhil Goyal 	struct rte_flow *flow;
312*993ea577SAkhil Goyal 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
313*993ea577SAkhil Goyal 	static const struct rte_flow_item_eth eth_mask = {
314*993ea577SAkhil Goyal 		.hdr.dst_addr.addr_bytes = "\x00\x00\x00\x00\x00\x00",
315*993ea577SAkhil Goyal 		.hdr.src_addr.addr_bytes = "\x00\x00\x00\x00\x00\x00",
316*993ea577SAkhil Goyal 		.hdr.ether_type = RTE_BE16(0x0000),
317*993ea577SAkhil Goyal 	};
318*993ea577SAkhil Goyal 
319*993ea577SAkhil Goyal 	int ret;
320*993ea577SAkhil Goyal 
321*993ea577SAkhil Goyal 	eth.has_vlan = 0;
322*993ea577SAkhil Goyal 	if (dir == RTE_SECURITY_MACSEC_DIR_TX)
323*993ea577SAkhil Goyal 		memcpy(&eth.hdr, td->plain_pkt.data, RTE_ETHER_HDR_LEN);
324*993ea577SAkhil Goyal 	else
325*993ea577SAkhil Goyal 		memcpy(&eth.hdr, td->secure_pkt.data, RTE_ETHER_HDR_LEN);
326*993ea577SAkhil Goyal 
327*993ea577SAkhil Goyal 	pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
328*993ea577SAkhil Goyal 	pattern[0].spec = &eth;
329*993ea577SAkhil Goyal 	pattern[0].mask = &eth_mask;
330*993ea577SAkhil Goyal 	pattern[0].last = NULL;
331*993ea577SAkhil Goyal 	pattern[1].type = RTE_FLOW_ITEM_TYPE_END;
332*993ea577SAkhil Goyal 
333*993ea577SAkhil Goyal 	action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
334*993ea577SAkhil Goyal 	action[0].conf = sess;
335*993ea577SAkhil Goyal 	action[1].type = RTE_FLOW_ACTION_TYPE_END;
336*993ea577SAkhil Goyal 	action[1].conf = NULL;
337*993ea577SAkhil Goyal 
338*993ea577SAkhil Goyal 	attr.ingress = (dir == RTE_SECURITY_MACSEC_DIR_RX) ? 1 : 0;
339*993ea577SAkhil Goyal 	attr.egress = (dir == RTE_SECURITY_MACSEC_DIR_TX) ? 1 : 0;
340*993ea577SAkhil Goyal 
341*993ea577SAkhil Goyal 	ret = rte_flow_validate(portid, &attr, pattern, action, &err);
342*993ea577SAkhil Goyal 	if (ret) {
343*993ea577SAkhil Goyal 		printf("\nValidate flow failed, ret = %d\n", ret);
344*993ea577SAkhil Goyal 		return -1;
345*993ea577SAkhil Goyal 	}
346*993ea577SAkhil Goyal 	flow = rte_flow_create(portid, &attr, pattern, action, &err);
347*993ea577SAkhil Goyal 	if (flow == NULL) {
348*993ea577SAkhil Goyal 		printf("\nDefault flow rule create failed\n");
349*993ea577SAkhil Goyal 		return -1;
350*993ea577SAkhil Goyal 	}
351*993ea577SAkhil Goyal 
352*993ea577SAkhil Goyal 	if (dir == RTE_SECURITY_MACSEC_DIR_TX)
353*993ea577SAkhil Goyal 		default_tx_flow[portid] = flow;
354*993ea577SAkhil Goyal 	else
355*993ea577SAkhil Goyal 		default_rx_flow[portid] = flow;
356*993ea577SAkhil Goyal 
357*993ea577SAkhil Goyal 	return 0;
358*993ea577SAkhil Goyal }
359*993ea577SAkhil Goyal 
360*993ea577SAkhil Goyal static void
361*993ea577SAkhil Goyal destroy_default_flow(uint16_t portid)
362*993ea577SAkhil Goyal {
363*993ea577SAkhil Goyal 	struct rte_flow_error err;
364*993ea577SAkhil Goyal 	int ret;
365*993ea577SAkhil Goyal 
366*993ea577SAkhil Goyal 	if (default_tx_flow[portid]) {
367*993ea577SAkhil Goyal 		ret = rte_flow_destroy(portid, default_tx_flow[portid], &err);
368*993ea577SAkhil Goyal 		if (ret) {
369*993ea577SAkhil Goyal 			printf("\nDefault Tx flow rule destroy failed\n");
370*993ea577SAkhil Goyal 			return;
371*993ea577SAkhil Goyal 		}
372*993ea577SAkhil Goyal 		default_tx_flow[portid] = NULL;
373*993ea577SAkhil Goyal 	}
374*993ea577SAkhil Goyal 	if (default_rx_flow[portid]) {
375*993ea577SAkhil Goyal 		ret = rte_flow_destroy(portid, default_rx_flow[portid], &err);
376*993ea577SAkhil Goyal 		if (ret) {
377*993ea577SAkhil Goyal 			printf("\nDefault Rx flow rule destroy failed\n");
378*993ea577SAkhil Goyal 			return;
379*993ea577SAkhil Goyal 		}
380*993ea577SAkhil Goyal 		default_rx_flow[portid] = NULL;
381*993ea577SAkhil Goyal 	}
382*993ea577SAkhil Goyal }
383*993ea577SAkhil Goyal 
384*993ea577SAkhil Goyal static void
385*993ea577SAkhil Goyal print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr)
386*993ea577SAkhil Goyal {
387*993ea577SAkhil Goyal 	char buf[RTE_ETHER_ADDR_FMT_SIZE];
388*993ea577SAkhil Goyal 	rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
389*993ea577SAkhil Goyal 	printf("%s%s", name, buf);
390*993ea577SAkhil Goyal }
391*993ea577SAkhil Goyal 
392*993ea577SAkhil Goyal /* Check the link status of all ports in up to 3s, and print them finally */
393*993ea577SAkhil Goyal static void
394*993ea577SAkhil Goyal check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
395*993ea577SAkhil Goyal {
396*993ea577SAkhil Goyal #define CHECK_INTERVAL 100 /* 100ms */
397*993ea577SAkhil Goyal #define MAX_CHECK_TIME 30 /* 3s (30 * 100ms) in total */
398*993ea577SAkhil Goyal 	uint16_t portid;
399*993ea577SAkhil Goyal 	uint8_t count, all_ports_up, print_flag = 0;
400*993ea577SAkhil Goyal 	struct rte_eth_link link;
401*993ea577SAkhil Goyal 	int ret;
402*993ea577SAkhil Goyal 	char link_status[RTE_ETH_LINK_MAX_STR_LEN];
403*993ea577SAkhil Goyal 
404*993ea577SAkhil Goyal 	printf("Checking link statuses...\n");
405*993ea577SAkhil Goyal 	fflush(stdout);
406*993ea577SAkhil Goyal 	for (count = 0; count <= MAX_CHECK_TIME; count++) {
407*993ea577SAkhil Goyal 		all_ports_up = 1;
408*993ea577SAkhil Goyal 		for (portid = 0; portid < port_num; portid++) {
409*993ea577SAkhil Goyal 			if ((port_mask & (1 << portid)) == 0)
410*993ea577SAkhil Goyal 				continue;
411*993ea577SAkhil Goyal 			memset(&link, 0, sizeof(link));
412*993ea577SAkhil Goyal 			ret = rte_eth_link_get_nowait(portid, &link);
413*993ea577SAkhil Goyal 			if (ret < 0) {
414*993ea577SAkhil Goyal 				all_ports_up = 0;
415*993ea577SAkhil Goyal 				if (print_flag == 1)
416*993ea577SAkhil Goyal 					printf("Port %u link get failed: %s\n",
417*993ea577SAkhil Goyal 						portid, rte_strerror(-ret));
418*993ea577SAkhil Goyal 				continue;
419*993ea577SAkhil Goyal 			}
420*993ea577SAkhil Goyal 
421*993ea577SAkhil Goyal 			/* print link status if flag set */
422*993ea577SAkhil Goyal 			if (print_flag == 1) {
423*993ea577SAkhil Goyal 				if (link.link_status && link_mbps == 0)
424*993ea577SAkhil Goyal 					link_mbps = link.link_speed;
425*993ea577SAkhil Goyal 
426*993ea577SAkhil Goyal 				rte_eth_link_to_str(link_status,
427*993ea577SAkhil Goyal 					sizeof(link_status), &link);
428*993ea577SAkhil Goyal 				printf("Port %d %s\n", portid, link_status);
429*993ea577SAkhil Goyal 				continue;
430*993ea577SAkhil Goyal 			}
431*993ea577SAkhil Goyal 			/* clear all_ports_up flag if any link down */
432*993ea577SAkhil Goyal 			if (link.link_status == RTE_ETH_LINK_DOWN) {
433*993ea577SAkhil Goyal 				all_ports_up = 0;
434*993ea577SAkhil Goyal 				break;
435*993ea577SAkhil Goyal 			}
436*993ea577SAkhil Goyal 		}
437*993ea577SAkhil Goyal 		/* after finally printing all link status, get out */
438*993ea577SAkhil Goyal 		if (print_flag == 1)
439*993ea577SAkhil Goyal 			break;
440*993ea577SAkhil Goyal 
441*993ea577SAkhil Goyal 		if (all_ports_up == 0)
442*993ea577SAkhil Goyal 			fflush(stdout);
443*993ea577SAkhil Goyal 
444*993ea577SAkhil Goyal 		/* set the print_flag if all ports up or timeout */
445*993ea577SAkhil Goyal 		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1))
446*993ea577SAkhil Goyal 			print_flag = 1;
447*993ea577SAkhil Goyal 	}
448*993ea577SAkhil Goyal }
449*993ea577SAkhil Goyal 
450*993ea577SAkhil Goyal static int
451*993ea577SAkhil Goyal test_macsec_post_process(struct rte_mbuf *m, const struct mcs_test_vector *td,
452*993ea577SAkhil Goyal 			enum mcs_op op, uint8_t check_out_pkts_untagged)
453*993ea577SAkhil Goyal {
454*993ea577SAkhil Goyal 	const uint8_t *dptr;
455*993ea577SAkhil Goyal 	uint16_t pkt_len;
456*993ea577SAkhil Goyal 
457*993ea577SAkhil Goyal 	if (op == MCS_DECAP || op == MCS_ENCAP_DECAP ||
458*993ea577SAkhil Goyal 			op == MCS_VERIFY_ONLY || op == MCS_AUTH_VERIFY ||
459*993ea577SAkhil Goyal 			check_out_pkts_untagged == 1) {
460*993ea577SAkhil Goyal 		dptr = td->plain_pkt.data;
461*993ea577SAkhil Goyal 		pkt_len = td->plain_pkt.len;
462*993ea577SAkhil Goyal 	} else {
463*993ea577SAkhil Goyal 		dptr = td->secure_pkt.data;
464*993ea577SAkhil Goyal 		pkt_len = td->secure_pkt.len;
465*993ea577SAkhil Goyal 	}
466*993ea577SAkhil Goyal 
467*993ea577SAkhil Goyal 	if (memcmp(rte_pktmbuf_mtod(m, uint8_t *), dptr, pkt_len)) {
468*993ea577SAkhil Goyal 		printf("\nData comparison failed for td.");
469*993ea577SAkhil Goyal 		rte_pktmbuf_dump(stdout, m, m->pkt_len);
470*993ea577SAkhil Goyal 		rte_hexdump(stdout, "expected_data", dptr, pkt_len);
471*993ea577SAkhil Goyal 		return TEST_FAILED;
472*993ea577SAkhil Goyal 	}
473*993ea577SAkhil Goyal 
474*993ea577SAkhil Goyal 	return TEST_SUCCESS;
475*993ea577SAkhil Goyal }
476*993ea577SAkhil Goyal 
477*993ea577SAkhil Goyal static void
478*993ea577SAkhil Goyal mcs_stats_dump(struct rte_security_ctx *ctx, enum mcs_op op,
479*993ea577SAkhil Goyal 	       void *rx_sess, void *tx_sess,
480*993ea577SAkhil Goyal 	       uint8_t rx_sc_id, uint8_t tx_sc_id,
481*993ea577SAkhil Goyal 	       uint16_t rx_sa_id[], uint16_t tx_sa_id[])
482*993ea577SAkhil Goyal {
483*993ea577SAkhil Goyal 	struct rte_security_stats sess_stats = {0};
484*993ea577SAkhil Goyal 	struct rte_security_macsec_secy_stats *secy_stat;
485*993ea577SAkhil Goyal 	struct rte_security_macsec_sc_stats sc_stat = {0};
486*993ea577SAkhil Goyal 	struct rte_security_macsec_sa_stats sa_stat = {0};
487*993ea577SAkhil Goyal 	int i;
488*993ea577SAkhil Goyal 
489*993ea577SAkhil Goyal 	if (op == MCS_DECAP || op == MCS_ENCAP_DECAP ||
490*993ea577SAkhil Goyal 			op == MCS_VERIFY_ONLY || op == MCS_AUTH_VERIFY) {
491*993ea577SAkhil Goyal 		printf("\n********* RX SECY STATS ************\n");
492*993ea577SAkhil Goyal 		rte_security_session_stats_get(ctx, rx_sess, &sess_stats);
493*993ea577SAkhil Goyal 		secy_stat = &sess_stats.macsec;
494*993ea577SAkhil Goyal 
495*993ea577SAkhil Goyal 		if (secy_stat->ctl_pkt_bcast_cnt)
496*993ea577SAkhil Goyal 			printf("RX: ctl_pkt_bcast_cnt: 0x%" PRIx64 "\n",
497*993ea577SAkhil Goyal 					secy_stat->ctl_pkt_bcast_cnt);
498*993ea577SAkhil Goyal 		if (secy_stat->ctl_pkt_mcast_cnt)
499*993ea577SAkhil Goyal 			printf("RX: ctl_pkt_mcast_cnt: 0x%" PRIx64 "\n",
500*993ea577SAkhil Goyal 					secy_stat->ctl_pkt_mcast_cnt);
501*993ea577SAkhil Goyal 		if (secy_stat->ctl_pkt_ucast_cnt)
502*993ea577SAkhil Goyal 			printf("RX: ctl_pkt_ucast_cnt: 0x%" PRIx64 "\n",
503*993ea577SAkhil Goyal 					secy_stat->ctl_pkt_ucast_cnt);
504*993ea577SAkhil Goyal 		if (secy_stat->ctl_octet_cnt)
505*993ea577SAkhil Goyal 			printf("RX: ctl_octet_cnt: 0x%" PRIx64 "\n", secy_stat->ctl_octet_cnt);
506*993ea577SAkhil Goyal 		if (secy_stat->unctl_pkt_bcast_cnt)
507*993ea577SAkhil Goyal 			printf("RX: unctl_pkt_bcast_cnt: 0x%" PRIx64 "\n",
508*993ea577SAkhil Goyal 					secy_stat->unctl_pkt_bcast_cnt);
509*993ea577SAkhil Goyal 		if (secy_stat->unctl_pkt_mcast_cnt)
510*993ea577SAkhil Goyal 			printf("RX: unctl_pkt_mcast_cnt: 0x%" PRIx64 "\n",
511*993ea577SAkhil Goyal 					secy_stat->unctl_pkt_mcast_cnt);
512*993ea577SAkhil Goyal 		if (secy_stat->unctl_pkt_ucast_cnt)
513*993ea577SAkhil Goyal 			printf("RX: unctl_pkt_ucast_cnt: 0x%" PRIx64 "\n",
514*993ea577SAkhil Goyal 					secy_stat->unctl_pkt_ucast_cnt);
515*993ea577SAkhil Goyal 		if (secy_stat->unctl_octet_cnt)
516*993ea577SAkhil Goyal 			printf("RX: unctl_octet_cnt: 0x%" PRIx64 "\n", secy_stat->unctl_octet_cnt);
517*993ea577SAkhil Goyal 		/* Valid only for RX */
518*993ea577SAkhil Goyal 		if (secy_stat->octet_decrypted_cnt)
519*993ea577SAkhil Goyal 			printf("RX: octet_decrypted_cnt: 0x%" PRIx64 "\n",
520*993ea577SAkhil Goyal 					secy_stat->octet_decrypted_cnt);
521*993ea577SAkhil Goyal 		if (secy_stat->octet_validated_cnt)
522*993ea577SAkhil Goyal 			printf("RX: octet_validated_cnt: 0x%" PRIx64 "\n",
523*993ea577SAkhil Goyal 					secy_stat->octet_validated_cnt);
524*993ea577SAkhil Goyal 		if (secy_stat->pkt_port_disabled_cnt)
525*993ea577SAkhil Goyal 			printf("RX: pkt_port_disabled_cnt: 0x%" PRIx64 "\n",
526*993ea577SAkhil Goyal 					secy_stat->pkt_port_disabled_cnt);
527*993ea577SAkhil Goyal 		if (secy_stat->pkt_badtag_cnt)
528*993ea577SAkhil Goyal 			printf("RX: pkt_badtag_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_badtag_cnt);
529*993ea577SAkhil Goyal 		if (secy_stat->pkt_nosa_cnt)
530*993ea577SAkhil Goyal 			printf("RX: pkt_nosa_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_nosa_cnt);
531*993ea577SAkhil Goyal 		if (secy_stat->pkt_nosaerror_cnt)
532*993ea577SAkhil Goyal 			printf("RX: pkt_nosaerror_cnt: 0x%" PRIx64 "\n",
533*993ea577SAkhil Goyal 					secy_stat->pkt_nosaerror_cnt);
534*993ea577SAkhil Goyal 		if (secy_stat->pkt_tagged_ctl_cnt)
535*993ea577SAkhil Goyal 			printf("RX: pkt_tagged_ctl_cnt: 0x%" PRIx64 "\n",
536*993ea577SAkhil Goyal 					secy_stat->pkt_tagged_ctl_cnt);
537*993ea577SAkhil Goyal 		if (secy_stat->pkt_untaged_cnt)
538*993ea577SAkhil Goyal 			printf("RX: pkt_untaged_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_untaged_cnt);
539*993ea577SAkhil Goyal 		if (secy_stat->pkt_ctl_cnt)
540*993ea577SAkhil Goyal 			printf("RX: pkt_ctl_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_ctl_cnt);
541*993ea577SAkhil Goyal 		if (secy_stat->pkt_notag_cnt)
542*993ea577SAkhil Goyal 			printf("RX: pkt_notag_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_notag_cnt);
543*993ea577SAkhil Goyal 		printf("\n");
544*993ea577SAkhil Goyal 		printf("\n********** RX SC[%u] STATS **************\n", rx_sc_id);
545*993ea577SAkhil Goyal 
546*993ea577SAkhil Goyal 		rte_security_macsec_sc_stats_get(ctx, rx_sc_id, RTE_SECURITY_MACSEC_DIR_RX,
547*993ea577SAkhil Goyal 						 &sc_stat);
548*993ea577SAkhil Goyal 		/* RX */
549*993ea577SAkhil Goyal 		if (sc_stat.hit_cnt)
550*993ea577SAkhil Goyal 			printf("RX hit_cnt: 0x%" PRIx64 "\n", sc_stat.hit_cnt);
551*993ea577SAkhil Goyal 		if (sc_stat.pkt_invalid_cnt)
552*993ea577SAkhil Goyal 			printf("RX pkt_invalid_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_invalid_cnt);
553*993ea577SAkhil Goyal 		if (sc_stat.pkt_late_cnt)
554*993ea577SAkhil Goyal 			printf("RX pkt_late_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_late_cnt);
555*993ea577SAkhil Goyal 		if (sc_stat.pkt_notvalid_cnt)
556*993ea577SAkhil Goyal 			printf("RX pkt_notvalid_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_notvalid_cnt);
557*993ea577SAkhil Goyal 		if (sc_stat.pkt_unchecked_cnt)
558*993ea577SAkhil Goyal 			printf("RX pkt_unchecked_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_unchecked_cnt);
559*993ea577SAkhil Goyal 		if (sc_stat.pkt_delay_cnt)
560*993ea577SAkhil Goyal 			printf("RX pkt_delay_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_delay_cnt);
561*993ea577SAkhil Goyal 		if (sc_stat.pkt_ok_cnt)
562*993ea577SAkhil Goyal 			printf("RX pkt_ok_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_ok_cnt);
563*993ea577SAkhil Goyal 		if (sc_stat.octet_decrypt_cnt)
564*993ea577SAkhil Goyal 			printf("RX octet_decrypt_cnt: 0x%" PRIx64 "\n", sc_stat.octet_decrypt_cnt);
565*993ea577SAkhil Goyal 		if (sc_stat.octet_validate_cnt)
566*993ea577SAkhil Goyal 			printf("RX octet_validate_cnt: 0x%" PRIx64 "\n",
567*993ea577SAkhil Goyal 					sc_stat.octet_validate_cnt);
568*993ea577SAkhil Goyal 		printf("\n");
569*993ea577SAkhil Goyal 		for (i = 0; i < RTE_SECURITY_MACSEC_NUM_AN; i++) {
570*993ea577SAkhil Goyal 			printf("\n********** RX SA[%u] STATS ****************\n", rx_sa_id[i]);
571*993ea577SAkhil Goyal 			memset(&sa_stat, 0, sizeof(struct rte_security_macsec_sa_stats));
572*993ea577SAkhil Goyal 			rte_security_macsec_sa_stats_get(ctx, rx_sa_id[i],
573*993ea577SAkhil Goyal 					RTE_SECURITY_MACSEC_DIR_RX, &sa_stat);
574*993ea577SAkhil Goyal 
575*993ea577SAkhil Goyal 			/* RX */
576*993ea577SAkhil Goyal 			if (sa_stat.pkt_invalid_cnt)
577*993ea577SAkhil Goyal 				printf("RX pkt_invalid_cnt: 0x%" PRIx64 "\n",
578*993ea577SAkhil Goyal 						sa_stat.pkt_invalid_cnt);
579*993ea577SAkhil Goyal 			if (sa_stat.pkt_nosaerror_cnt)
580*993ea577SAkhil Goyal 				printf("RX pkt_nosaerror_cnt: 0x%" PRIx64 "\n",
581*993ea577SAkhil Goyal 						sa_stat.pkt_nosaerror_cnt);
582*993ea577SAkhil Goyal 			if (sa_stat.pkt_notvalid_cnt)
583*993ea577SAkhil Goyal 				printf("RX pkt_notvalid_cnt: 0x%" PRIx64 "\n",
584*993ea577SAkhil Goyal 						sa_stat.pkt_notvalid_cnt);
585*993ea577SAkhil Goyal 			if (sa_stat.pkt_ok_cnt)
586*993ea577SAkhil Goyal 				printf("RX pkt_ok_cnt: 0x%" PRIx64 "\n", sa_stat.pkt_ok_cnt);
587*993ea577SAkhil Goyal 			if (sa_stat.pkt_nosa_cnt)
588*993ea577SAkhil Goyal 				printf("RX pkt_nosa_cnt: 0x%" PRIx64 "\n", sa_stat.pkt_nosa_cnt);
589*993ea577SAkhil Goyal 			printf("\n");
590*993ea577SAkhil Goyal 		}
591*993ea577SAkhil Goyal 	}
592*993ea577SAkhil Goyal 
593*993ea577SAkhil Goyal 	if (op == MCS_ENCAP || op == MCS_ENCAP_DECAP ||
594*993ea577SAkhil Goyal 			op == MCS_AUTH_ONLY || op == MCS_AUTH_VERIFY) {
595*993ea577SAkhil Goyal 		memset(&sess_stats, 0, sizeof(struct rte_security_stats));
596*993ea577SAkhil Goyal 		rte_security_session_stats_get(ctx, tx_sess, &sess_stats);
597*993ea577SAkhil Goyal 		secy_stat = &sess_stats.macsec;
598*993ea577SAkhil Goyal 
599*993ea577SAkhil Goyal 		printf("\n********* TX SECY STATS ************\n");
600*993ea577SAkhil Goyal 		if (secy_stat->ctl_pkt_bcast_cnt)
601*993ea577SAkhil Goyal 			printf("TX: ctl_pkt_bcast_cnt: 0x%" PRIx64 "\n",
602*993ea577SAkhil Goyal 					secy_stat->ctl_pkt_bcast_cnt);
603*993ea577SAkhil Goyal 		if (secy_stat->ctl_pkt_mcast_cnt)
604*993ea577SAkhil Goyal 			printf("TX: ctl_pkt_mcast_cnt: 0x%" PRIx64 "\n",
605*993ea577SAkhil Goyal 					secy_stat->ctl_pkt_mcast_cnt);
606*993ea577SAkhil Goyal 		if (secy_stat->ctl_pkt_ucast_cnt)
607*993ea577SAkhil Goyal 			printf("TX: ctl_pkt_ucast_cnt: 0x%" PRIx64 "\n",
608*993ea577SAkhil Goyal 					secy_stat->ctl_pkt_ucast_cnt);
609*993ea577SAkhil Goyal 		if (secy_stat->ctl_octet_cnt)
610*993ea577SAkhil Goyal 			printf("TX: ctl_octet_cnt: 0x%" PRIx64 "\n", secy_stat->ctl_octet_cnt);
611*993ea577SAkhil Goyal 		if (secy_stat->unctl_pkt_bcast_cnt)
612*993ea577SAkhil Goyal 			printf("TX: unctl_pkt_bcast_cnt: 0x%" PRIx64 "\n",
613*993ea577SAkhil Goyal 					secy_stat->unctl_pkt_bcast_cnt);
614*993ea577SAkhil Goyal 		if (secy_stat->unctl_pkt_mcast_cnt)
615*993ea577SAkhil Goyal 			printf("TX: unctl_pkt_mcast_cnt: 0x%" PRIx64 "\n",
616*993ea577SAkhil Goyal 					secy_stat->unctl_pkt_mcast_cnt);
617*993ea577SAkhil Goyal 		if (secy_stat->unctl_pkt_ucast_cnt)
618*993ea577SAkhil Goyal 			printf("TX: unctl_pkt_ucast_cnt: 0x%" PRIx64 "\n",
619*993ea577SAkhil Goyal 					secy_stat->unctl_pkt_ucast_cnt);
620*993ea577SAkhil Goyal 		if (secy_stat->unctl_octet_cnt)
621*993ea577SAkhil Goyal 			printf("TX: unctl_octet_cnt: 0x%" PRIx64 "\n",
622*993ea577SAkhil Goyal 					secy_stat->unctl_octet_cnt);
623*993ea577SAkhil Goyal 		/* Valid only for TX */
624*993ea577SAkhil Goyal 		if (secy_stat->octet_encrypted_cnt)
625*993ea577SAkhil Goyal 			printf("TX: octet_encrypted_cnt: 0x%" PRIx64 "\n",
626*993ea577SAkhil Goyal 					secy_stat->octet_encrypted_cnt);
627*993ea577SAkhil Goyal 		if (secy_stat->octet_protected_cnt)
628*993ea577SAkhil Goyal 			printf("TX: octet_protected_cnt: 0x%" PRIx64 "\n",
629*993ea577SAkhil Goyal 					secy_stat->octet_protected_cnt);
630*993ea577SAkhil Goyal 		if (secy_stat->pkt_noactivesa_cnt)
631*993ea577SAkhil Goyal 			printf("TX: pkt_noactivesa_cnt: 0x%" PRIx64 "\n",
632*993ea577SAkhil Goyal 					secy_stat->pkt_noactivesa_cnt);
633*993ea577SAkhil Goyal 		if (secy_stat->pkt_toolong_cnt)
634*993ea577SAkhil Goyal 			printf("TX: pkt_toolong_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_toolong_cnt);
635*993ea577SAkhil Goyal 		if (secy_stat->pkt_untagged_cnt)
636*993ea577SAkhil Goyal 			printf("TX: pkt_untagged_cnt: 0x%" PRIx64 "\n",
637*993ea577SAkhil Goyal 					secy_stat->pkt_untagged_cnt);
638*993ea577SAkhil Goyal 
639*993ea577SAkhil Goyal 
640*993ea577SAkhil Goyal 		memset(&sc_stat, 0, sizeof(struct rte_security_macsec_sc_stats));
641*993ea577SAkhil Goyal 		rte_security_macsec_sc_stats_get(ctx, tx_sc_id, RTE_SECURITY_MACSEC_DIR_TX,
642*993ea577SAkhil Goyal 						 &sc_stat);
643*993ea577SAkhil Goyal 		printf("\n********** TX SC[%u] STATS **************\n", tx_sc_id);
644*993ea577SAkhil Goyal 		if (sc_stat.pkt_encrypt_cnt)
645*993ea577SAkhil Goyal 			printf("TX pkt_encrypt_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_encrypt_cnt);
646*993ea577SAkhil Goyal 		if (sc_stat.pkt_protected_cnt)
647*993ea577SAkhil Goyal 			printf("TX pkt_protected_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_protected_cnt);
648*993ea577SAkhil Goyal 		if (sc_stat.octet_encrypt_cnt)
649*993ea577SAkhil Goyal 			printf("TX octet_encrypt_cnt: 0x%" PRIx64 "\n", sc_stat.octet_encrypt_cnt);
650*993ea577SAkhil Goyal 
651*993ea577SAkhil Goyal 		memset(&sa_stat, 0, sizeof(struct rte_security_macsec_sa_stats));
652*993ea577SAkhil Goyal 		rte_security_macsec_sa_stats_get(ctx, tx_sa_id[0],
653*993ea577SAkhil Goyal 				RTE_SECURITY_MACSEC_DIR_TX, &sa_stat);
654*993ea577SAkhil Goyal 		printf("\n********** TX SA[%u] STATS ****************\n", tx_sa_id[0]);
655*993ea577SAkhil Goyal 		if (sa_stat.pkt_encrypt_cnt)
656*993ea577SAkhil Goyal 			printf("TX pkt_encrypt_cnt: 0x%" PRIx64 "\n", sa_stat.pkt_encrypt_cnt);
657*993ea577SAkhil Goyal 		if (sa_stat.pkt_protected_cnt)
658*993ea577SAkhil Goyal 			printf("TX pkt_protected_cnt: 0x%" PRIx64 "\n", sa_stat.pkt_protected_cnt);
659*993ea577SAkhil Goyal 	}
660*993ea577SAkhil Goyal }
661*993ea577SAkhil Goyal 
662*993ea577SAkhil Goyal static int
663*993ea577SAkhil Goyal test_macsec(const struct mcs_test_vector *td[], enum mcs_op op, const struct mcs_test_opts *opts)
664*993ea577SAkhil Goyal {
665*993ea577SAkhil Goyal 	uint16_t rx_sa_id[MCS_MAX_FLOWS][RTE_SECURITY_MACSEC_NUM_AN] = {{0}};
666*993ea577SAkhil Goyal 	uint16_t tx_sa_id[MCS_MAX_FLOWS][2] = {{0}};
667*993ea577SAkhil Goyal 	uint16_t rx_sc_id[MCS_MAX_FLOWS] = {0};
668*993ea577SAkhil Goyal 	uint16_t tx_sc_id[MCS_MAX_FLOWS] = {0};
669*993ea577SAkhil Goyal 	void *rx_sess[MCS_MAX_FLOWS] = {0};
670*993ea577SAkhil Goyal 	void *tx_sess[MCS_MAX_FLOWS] = {0};
671*993ea577SAkhil Goyal 	struct rte_security_session_conf sess_conf = {0};
672*993ea577SAkhil Goyal 	struct rte_security_macsec_sa sa_conf = {0};
673*993ea577SAkhil Goyal 	struct rte_security_macsec_sc sc_conf = {0};
674*993ea577SAkhil Goyal 	struct rte_security_ctx *ctx;
675*993ea577SAkhil Goyal 	int nb_rx = 0, nb_sent;
676*993ea577SAkhil Goyal 	int i, j = 0, ret, id, an = 0;
677*993ea577SAkhil Goyal 	uint8_t tci_off;
678*993ea577SAkhil Goyal 
679*993ea577SAkhil Goyal 	memset(rx_pkts_burst, 0, sizeof(rx_pkts_burst[0]) * opts->nb_td);
680*993ea577SAkhil Goyal 
681*993ea577SAkhil Goyal 	ctx = (struct rte_security_ctx *)rte_eth_dev_get_sec_ctx(port_id);
682*993ea577SAkhil Goyal 	if (ctx == NULL) {
683*993ea577SAkhil Goyal 		printf("Ethernet device doesn't support security features.\n");
684*993ea577SAkhil Goyal 		return TEST_SKIPPED;
685*993ea577SAkhil Goyal 	}
686*993ea577SAkhil Goyal 
687*993ea577SAkhil Goyal 	tci_off = (opts->sectag_insert_mode == 1) ? RTE_ETHER_HDR_LEN :
688*993ea577SAkhil Goyal 			RTE_ETHER_HDR_LEN + (opts->nb_vlan * RTE_VLAN_HLEN);
689*993ea577SAkhil Goyal 
690*993ea577SAkhil Goyal 	for (i = 0, j = 0; i < opts->nb_td; i++) {
691*993ea577SAkhil Goyal 		if (op == MCS_DECAP || op == MCS_VERIFY_ONLY)
692*993ea577SAkhil Goyal 			tx_pkts_burst[j] = init_packet(mbufpool, td[i]->secure_pkt.data,
693*993ea577SAkhil Goyal 							td[i]->secure_pkt.len);
694*993ea577SAkhil Goyal 		else {
695*993ea577SAkhil Goyal 			tx_pkts_burst[j] = init_packet(mbufpool, td[i]->plain_pkt.data,
696*993ea577SAkhil Goyal 							td[i]->plain_pkt.len);
697*993ea577SAkhil Goyal 
698*993ea577SAkhil Goyal 			tx_pkts_burst[j]->ol_flags |= RTE_MBUF_F_TX_MACSEC;
699*993ea577SAkhil Goyal 		}
700*993ea577SAkhil Goyal 		if (tx_pkts_burst[j] == NULL) {
701*993ea577SAkhil Goyal 			while (j--)
702*993ea577SAkhil Goyal 				rte_pktmbuf_free(tx_pkts_burst[j]);
703*993ea577SAkhil Goyal 			ret = TEST_FAILED;
704*993ea577SAkhil Goyal 			goto out;
705*993ea577SAkhil Goyal 		}
706*993ea577SAkhil Goyal 		j++;
707*993ea577SAkhil Goyal 
708*993ea577SAkhil Goyal 		if (op == MCS_DECAP || op == MCS_ENCAP_DECAP ||
709*993ea577SAkhil Goyal 				op == MCS_VERIFY_ONLY || op == MCS_AUTH_VERIFY) {
710*993ea577SAkhil Goyal 			for (an = 0; an < RTE_SECURITY_MACSEC_NUM_AN; an++) {
711*993ea577SAkhil Goyal 				/* For simplicity, using same SA conf for all AN */
712*993ea577SAkhil Goyal 				fill_macsec_sa_conf(td[i], &sa_conf,
713*993ea577SAkhil Goyal 						RTE_SECURITY_MACSEC_DIR_RX, an, tci_off);
714*993ea577SAkhil Goyal 				id = rte_security_macsec_sa_create(ctx, &sa_conf);
715*993ea577SAkhil Goyal 				if (id < 0) {
716*993ea577SAkhil Goyal 					printf("MACsec SA create failed : %d.\n", id);
717*993ea577SAkhil Goyal 					return TEST_FAILED;
718*993ea577SAkhil Goyal 				}
719*993ea577SAkhil Goyal 				rx_sa_id[i][an] = (uint16_t)id;
720*993ea577SAkhil Goyal 			}
721*993ea577SAkhil Goyal 			fill_macsec_sc_conf(td[i], &sc_conf, opts,
722*993ea577SAkhil Goyal 					RTE_SECURITY_MACSEC_DIR_RX, rx_sa_id[i], tci_off);
723*993ea577SAkhil Goyal 			id = rte_security_macsec_sc_create(ctx, &sc_conf);
724*993ea577SAkhil Goyal 			if (id < 0) {
725*993ea577SAkhil Goyal 				printf("MACsec SC create failed : %d.\n", id);
726*993ea577SAkhil Goyal 				goto out;
727*993ea577SAkhil Goyal 			}
728*993ea577SAkhil Goyal 			rx_sc_id[i] = (uint16_t)id;
729*993ea577SAkhil Goyal 
730*993ea577SAkhil Goyal 			/* Create Inline IPsec session. */
731*993ea577SAkhil Goyal 			ret = fill_session_conf(td[i], port_id, opts, &sess_conf,
732*993ea577SAkhil Goyal 					RTE_SECURITY_MACSEC_DIR_RX, rx_sc_id[i], tci_off);
733*993ea577SAkhil Goyal 			if (ret)
734*993ea577SAkhil Goyal 				return TEST_FAILED;
735*993ea577SAkhil Goyal 
736*993ea577SAkhil Goyal 			rx_sess[i] = rte_security_session_create(ctx, &sess_conf,
737*993ea577SAkhil Goyal 					sess_pool);
738*993ea577SAkhil Goyal 			if (rx_sess[i] == NULL) {
739*993ea577SAkhil Goyal 				printf("SEC Session init failed.\n");
740*993ea577SAkhil Goyal 				return TEST_FAILED;
741*993ea577SAkhil Goyal 			}
742*993ea577SAkhil Goyal 			ret = create_default_flow(td[i], port_id,
743*993ea577SAkhil Goyal 					RTE_SECURITY_MACSEC_DIR_RX, rx_sess[i]);
744*993ea577SAkhil Goyal 			if (ret)
745*993ea577SAkhil Goyal 				goto out;
746*993ea577SAkhil Goyal 		}
747*993ea577SAkhil Goyal 		if (op == MCS_ENCAP || op == MCS_ENCAP_DECAP ||
748*993ea577SAkhil Goyal 				op == MCS_AUTH_ONLY || op == MCS_AUTH_VERIFY) {
749*993ea577SAkhil Goyal 			int id;
750*993ea577SAkhil Goyal 
751*993ea577SAkhil Goyal 			fill_macsec_sa_conf(td[i], &sa_conf,
752*993ea577SAkhil Goyal 					RTE_SECURITY_MACSEC_DIR_TX,
753*993ea577SAkhil Goyal 					td[i]->secure_pkt.data[tci_off] & RTE_MACSEC_AN_MASK,
754*993ea577SAkhil Goyal 					tci_off);
755*993ea577SAkhil Goyal 			id = rte_security_macsec_sa_create(ctx, &sa_conf);
756*993ea577SAkhil Goyal 			if (id < 0) {
757*993ea577SAkhil Goyal 				printf("MACsec SA create failed : %d.\n", id);
758*993ea577SAkhil Goyal 				return TEST_FAILED;
759*993ea577SAkhil Goyal 			}
760*993ea577SAkhil Goyal 			tx_sa_id[i][0] = (uint16_t)id;
761*993ea577SAkhil Goyal 			tx_sa_id[i][1] = MCS_INVALID_SA;
762*993ea577SAkhil Goyal 			fill_macsec_sc_conf(td[i], &sc_conf, opts,
763*993ea577SAkhil Goyal 					RTE_SECURITY_MACSEC_DIR_TX, tx_sa_id[i], tci_off);
764*993ea577SAkhil Goyal 			id = rte_security_macsec_sc_create(ctx, &sc_conf);
765*993ea577SAkhil Goyal 			if (id < 0) {
766*993ea577SAkhil Goyal 				printf("MACsec SC create failed : %d.\n", id);
767*993ea577SAkhil Goyal 				goto out;
768*993ea577SAkhil Goyal 			}
769*993ea577SAkhil Goyal 			tx_sc_id[i] = (uint16_t)id;
770*993ea577SAkhil Goyal 
771*993ea577SAkhil Goyal 			/* Create Inline IPsec session. */
772*993ea577SAkhil Goyal 			ret = fill_session_conf(td[i], port_id, opts, &sess_conf,
773*993ea577SAkhil Goyal 					RTE_SECURITY_MACSEC_DIR_TX, tx_sc_id[i], tci_off);
774*993ea577SAkhil Goyal 			if (ret)
775*993ea577SAkhil Goyal 				return TEST_FAILED;
776*993ea577SAkhil Goyal 
777*993ea577SAkhil Goyal 			tx_sess[i] = rte_security_session_create(ctx, &sess_conf,
778*993ea577SAkhil Goyal 					sess_pool);
779*993ea577SAkhil Goyal 			if (tx_sess[i] == NULL) {
780*993ea577SAkhil Goyal 				printf("SEC Session init failed.\n");
781*993ea577SAkhil Goyal 				return TEST_FAILED;
782*993ea577SAkhil Goyal 			}
783*993ea577SAkhil Goyal 			ret = create_default_flow(td[i], port_id,
784*993ea577SAkhil Goyal 					RTE_SECURITY_MACSEC_DIR_TX, tx_sess[i]);
785*993ea577SAkhil Goyal 			if (ret)
786*993ea577SAkhil Goyal 				goto out;
787*993ea577SAkhil Goyal 		}
788*993ea577SAkhil Goyal 	}
789*993ea577SAkhil Goyal 
790*993ea577SAkhil Goyal 	/* Send packet to ethdev for inline MACsec processing. */
791*993ea577SAkhil Goyal 	nb_sent = rte_eth_tx_burst(port_id, 0, tx_pkts_burst, j);
792*993ea577SAkhil Goyal 
793*993ea577SAkhil Goyal 	if (nb_sent != j) {
794*993ea577SAkhil Goyal 		printf("\nUnable to TX %d packets, sent: %i", j, nb_sent);
795*993ea577SAkhil Goyal 		for ( ; nb_sent < j; nb_sent++)
796*993ea577SAkhil Goyal 			rte_pktmbuf_free(tx_pkts_burst[nb_sent]);
797*993ea577SAkhil Goyal 		ret = TEST_FAILED;
798*993ea577SAkhil Goyal 		goto out;
799*993ea577SAkhil Goyal 	}
800*993ea577SAkhil Goyal 
801*993ea577SAkhil Goyal 	rte_pause();
802*993ea577SAkhil Goyal 
803*993ea577SAkhil Goyal 	/* Receive back packet on loopback interface. */
804*993ea577SAkhil Goyal 	do {
805*993ea577SAkhil Goyal 		nb_rx += rte_eth_rx_burst(port_id, 0,
806*993ea577SAkhil Goyal 				&rx_pkts_burst[nb_rx],
807*993ea577SAkhil Goyal 				nb_sent - nb_rx);
808*993ea577SAkhil Goyal 		if (nb_rx >= nb_sent)
809*993ea577SAkhil Goyal 			break;
810*993ea577SAkhil Goyal 		rte_delay_ms(1);
811*993ea577SAkhil Goyal 	} while (j++ < 5 && nb_rx == 0);
812*993ea577SAkhil Goyal 
813*993ea577SAkhil Goyal 	if (nb_rx != nb_sent) {
814*993ea577SAkhil Goyal 		printf("\nUnable to RX all %d packets, received(%i)",
815*993ea577SAkhil Goyal 				nb_sent, nb_rx);
816*993ea577SAkhil Goyal 		while (--nb_rx >= 0)
817*993ea577SAkhil Goyal 			rte_pktmbuf_free(rx_pkts_burst[nb_rx]);
818*993ea577SAkhil Goyal 		ret = TEST_FAILED;
819*993ea577SAkhil Goyal 		goto out;
820*993ea577SAkhil Goyal 	}
821*993ea577SAkhil Goyal 
822*993ea577SAkhil Goyal 	for (i = 0; i < nb_rx; i++) {
823*993ea577SAkhil Goyal 		ret = test_macsec_post_process(rx_pkts_burst[i], td[i], op,
824*993ea577SAkhil Goyal 				opts->check_out_pkts_untagged);
825*993ea577SAkhil Goyal 		if (ret != TEST_SUCCESS) {
826*993ea577SAkhil Goyal 			for ( ; i < nb_rx; i++)
827*993ea577SAkhil Goyal 				rte_pktmbuf_free(rx_pkts_burst[i]);
828*993ea577SAkhil Goyal 			goto out;
829*993ea577SAkhil Goyal 		}
830*993ea577SAkhil Goyal 
831*993ea577SAkhil Goyal 		rte_pktmbuf_free(rx_pkts_burst[i]);
832*993ea577SAkhil Goyal 		rx_pkts_burst[i] = NULL;
833*993ea577SAkhil Goyal 	}
834*993ea577SAkhil Goyal out:
835*993ea577SAkhil Goyal 	for (i = 0; i < opts->nb_td; i++) {
836*993ea577SAkhil Goyal 		if (opts->dump_all_stats) {
837*993ea577SAkhil Goyal 			mcs_stats_dump(ctx, op,
838*993ea577SAkhil Goyal 					rx_sess[i], tx_sess[i],
839*993ea577SAkhil Goyal 					rx_sc_id[i], tx_sc_id[i],
840*993ea577SAkhil Goyal 					rx_sa_id[i], tx_sa_id[i]);
841*993ea577SAkhil Goyal 		}
842*993ea577SAkhil Goyal 	}
843*993ea577SAkhil Goyal 
844*993ea577SAkhil Goyal 	destroy_default_flow(port_id);
845*993ea577SAkhil Goyal 
846*993ea577SAkhil Goyal 	/* Destroy session so that other cases can create the session again */
847*993ea577SAkhil Goyal 	for (i = 0; i < opts->nb_td; i++) {
848*993ea577SAkhil Goyal 		if (op == MCS_ENCAP || op == MCS_ENCAP_DECAP ||
849*993ea577SAkhil Goyal 				op == MCS_AUTH_ONLY || op == MCS_AUTH_VERIFY) {
850*993ea577SAkhil Goyal 			rte_security_session_destroy(ctx, tx_sess[i]);
851*993ea577SAkhil Goyal 			tx_sess[i] = NULL;
852*993ea577SAkhil Goyal 			rte_security_macsec_sc_destroy(ctx, tx_sc_id[i],
853*993ea577SAkhil Goyal 						RTE_SECURITY_MACSEC_DIR_TX);
854*993ea577SAkhil Goyal 			rte_security_macsec_sa_destroy(ctx, tx_sa_id[i][0],
855*993ea577SAkhil Goyal 						RTE_SECURITY_MACSEC_DIR_TX);
856*993ea577SAkhil Goyal 		}
857*993ea577SAkhil Goyal 		if (op == MCS_DECAP || op == MCS_ENCAP_DECAP ||
858*993ea577SAkhil Goyal 				op == MCS_VERIFY_ONLY || op == MCS_AUTH_VERIFY) {
859*993ea577SAkhil Goyal 			rte_security_session_destroy(ctx, rx_sess[i]);
860*993ea577SAkhil Goyal 			rx_sess[i] = NULL;
861*993ea577SAkhil Goyal 			rte_security_macsec_sc_destroy(ctx, rx_sc_id[i],
862*993ea577SAkhil Goyal 						RTE_SECURITY_MACSEC_DIR_RX);
863*993ea577SAkhil Goyal 			for (j = 0; j < RTE_SECURITY_MACSEC_NUM_AN; j++) {
864*993ea577SAkhil Goyal 				rte_security_macsec_sa_destroy(ctx, rx_sa_id[i][j],
865*993ea577SAkhil Goyal 						RTE_SECURITY_MACSEC_DIR_RX);
866*993ea577SAkhil Goyal 			}
867*993ea577SAkhil Goyal 		}
868*993ea577SAkhil Goyal 	}
869*993ea577SAkhil Goyal 
870*993ea577SAkhil Goyal 	return ret;
871*993ea577SAkhil Goyal }
872*993ea577SAkhil Goyal 
873*993ea577SAkhil Goyal static int
874*993ea577SAkhil Goyal test_inline_macsec_encap_all(const void *data __rte_unused)
875*993ea577SAkhil Goyal {
876*993ea577SAkhil Goyal 	const struct mcs_test_vector *cur_td;
877*993ea577SAkhil Goyal 	struct mcs_test_opts opts = {0};
878*993ea577SAkhil Goyal 	int err, all_err = 0;
879*993ea577SAkhil Goyal 	int i, size;
880*993ea577SAkhil Goyal 
881*993ea577SAkhil Goyal 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
882*993ea577SAkhil Goyal 	opts.encrypt = true;
883*993ea577SAkhil Goyal 	opts.protect_frames = true;
884*993ea577SAkhil Goyal 	opts.sa_in_use = 1;
885*993ea577SAkhil Goyal 	opts.nb_td = 1;
886*993ea577SAkhil Goyal 	opts.sectag_insert_mode = 1;
887*993ea577SAkhil Goyal 	opts.mtu = RTE_ETHER_MTU;
888*993ea577SAkhil Goyal 
889*993ea577SAkhil Goyal 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
890*993ea577SAkhil Goyal 	for (i = 0; i < size; i++) {
891*993ea577SAkhil Goyal 		cur_td = &list_mcs_cipher_vectors[i];
892*993ea577SAkhil Goyal 		err = test_macsec(&cur_td, MCS_ENCAP, &opts);
893*993ea577SAkhil Goyal 		if (err) {
894*993ea577SAkhil Goyal 			printf("\nCipher Auth Encryption case %d failed", cur_td->test_idx);
895*993ea577SAkhil Goyal 			err = -1;
896*993ea577SAkhil Goyal 		} else {
897*993ea577SAkhil Goyal 			printf("\nCipher Auth Encryption case %d Passed", cur_td->test_idx);
898*993ea577SAkhil Goyal 			err = 0;
899*993ea577SAkhil Goyal 		}
900*993ea577SAkhil Goyal 		all_err += err;
901*993ea577SAkhil Goyal 	}
902*993ea577SAkhil Goyal 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
903*993ea577SAkhil Goyal 
904*993ea577SAkhil Goyal 	return all_err;
905*993ea577SAkhil Goyal }
906*993ea577SAkhil Goyal 
907*993ea577SAkhil Goyal static int
908*993ea577SAkhil Goyal test_inline_macsec_decap_all(const void *data __rte_unused)
909*993ea577SAkhil Goyal {
910*993ea577SAkhil Goyal 	const struct mcs_test_vector *cur_td;
911*993ea577SAkhil Goyal 	struct mcs_test_opts opts = {0};
912*993ea577SAkhil Goyal 	int err, all_err = 0;
913*993ea577SAkhil Goyal 	int i, size;
914*993ea577SAkhil Goyal 
915*993ea577SAkhil Goyal 	opts.val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT;
916*993ea577SAkhil Goyal 	opts.sa_in_use = 1;
917*993ea577SAkhil Goyal 	opts.nb_td = 1;
918*993ea577SAkhil Goyal 	opts.sectag_insert_mode = 1;
919*993ea577SAkhil Goyal 	opts.mtu = RTE_ETHER_MTU;
920*993ea577SAkhil Goyal 
921*993ea577SAkhil Goyal 	size = (sizeof(list_mcs_cipher_vectors) / sizeof((list_mcs_cipher_vectors)[0]));
922*993ea577SAkhil Goyal 	for (i = 0; i < size; i++) {
923*993ea577SAkhil Goyal 		cur_td = &list_mcs_cipher_vectors[i];
924*993ea577SAkhil Goyal 		err = test_macsec(&cur_td, MCS_DECAP, &opts);
925*993ea577SAkhil Goyal 		if (err) {
926*993ea577SAkhil Goyal 			printf("\nCipher Auth Decryption case %d failed", cur_td->test_idx);
927*993ea577SAkhil Goyal 			err = -1;
928*993ea577SAkhil Goyal 		} else {
929*993ea577SAkhil Goyal 			printf("\nCipher Auth Decryption case %d Passed", cur_td->test_idx);
930*993ea577SAkhil Goyal 			err = 0;
931*993ea577SAkhil Goyal 		}
932*993ea577SAkhil Goyal 		all_err += err;
933*993ea577SAkhil Goyal 	}
934*993ea577SAkhil Goyal 	printf("\n%s: Success: %d, Failure: %d\n", __func__, size + all_err, -all_err);
935*993ea577SAkhil Goyal 
936*993ea577SAkhil Goyal 	return all_err;
937*993ea577SAkhil Goyal }
938*993ea577SAkhil Goyal 
939*993ea577SAkhil Goyal static int
940*993ea577SAkhil Goyal ut_setup_inline_macsec(void)
941*993ea577SAkhil Goyal {
942*993ea577SAkhil Goyal 	int ret;
943*993ea577SAkhil Goyal 
944*993ea577SAkhil Goyal 	/* Start device */
945*993ea577SAkhil Goyal 	ret = rte_eth_dev_start(port_id);
946*993ea577SAkhil Goyal 	if (ret < 0) {
947*993ea577SAkhil Goyal 		printf("rte_eth_dev_start: err=%d, port=%d\n",
948*993ea577SAkhil Goyal 			ret, port_id);
949*993ea577SAkhil Goyal 		return ret;
950*993ea577SAkhil Goyal 	}
951*993ea577SAkhil Goyal 	/* always enable promiscuous */
952*993ea577SAkhil Goyal 	ret = rte_eth_promiscuous_enable(port_id);
953*993ea577SAkhil Goyal 	if (ret != 0) {
954*993ea577SAkhil Goyal 		printf("rte_eth_promiscuous_enable: err=%s, port=%d\n",
955*993ea577SAkhil Goyal 			rte_strerror(-ret), port_id);
956*993ea577SAkhil Goyal 		return ret;
957*993ea577SAkhil Goyal 	}
958*993ea577SAkhil Goyal 
959*993ea577SAkhil Goyal 	check_all_ports_link_status(1, RTE_PORT_ALL);
960*993ea577SAkhil Goyal 
961*993ea577SAkhil Goyal 	return 0;
962*993ea577SAkhil Goyal }
963*993ea577SAkhil Goyal 
964*993ea577SAkhil Goyal static void
965*993ea577SAkhil Goyal ut_teardown_inline_macsec(void)
966*993ea577SAkhil Goyal {
967*993ea577SAkhil Goyal 	uint16_t portid;
968*993ea577SAkhil Goyal 	int ret;
969*993ea577SAkhil Goyal 
970*993ea577SAkhil Goyal 	/* port tear down */
971*993ea577SAkhil Goyal 	RTE_ETH_FOREACH_DEV(portid) {
972*993ea577SAkhil Goyal 		ret = rte_eth_dev_stop(portid);
973*993ea577SAkhil Goyal 		if (ret != 0)
974*993ea577SAkhil Goyal 			printf("rte_eth_dev_stop: err=%s, port=%u\n",
975*993ea577SAkhil Goyal 			       rte_strerror(-ret), portid);
976*993ea577SAkhil Goyal 
977*993ea577SAkhil Goyal 	}
978*993ea577SAkhil Goyal }
979*993ea577SAkhil Goyal 
980*993ea577SAkhil Goyal static int
981*993ea577SAkhil Goyal inline_macsec_testsuite_setup(void)
982*993ea577SAkhil Goyal {
983*993ea577SAkhil Goyal 	uint16_t nb_rxd;
984*993ea577SAkhil Goyal 	uint16_t nb_txd;
985*993ea577SAkhil Goyal 	uint16_t nb_ports;
986*993ea577SAkhil Goyal 	int ret;
987*993ea577SAkhil Goyal 	uint16_t nb_rx_queue = 1, nb_tx_queue = 1;
988*993ea577SAkhil Goyal 
989*993ea577SAkhil Goyal 	printf("Start inline MACsec test.\n");
990*993ea577SAkhil Goyal 
991*993ea577SAkhil Goyal 	nb_ports = rte_eth_dev_count_avail();
992*993ea577SAkhil Goyal 	if (nb_ports < NB_ETHPORTS_USED) {
993*993ea577SAkhil Goyal 		printf("At least %u port(s) used for test\n",
994*993ea577SAkhil Goyal 		       NB_ETHPORTS_USED);
995*993ea577SAkhil Goyal 		return TEST_SKIPPED;
996*993ea577SAkhil Goyal 	}
997*993ea577SAkhil Goyal 
998*993ea577SAkhil Goyal 	ret = init_mempools(NB_MBUF);
999*993ea577SAkhil Goyal 	if (ret)
1000*993ea577SAkhil Goyal 		return ret;
1001*993ea577SAkhil Goyal 
1002*993ea577SAkhil Goyal 	if (tx_pkts_burst == NULL) {
1003*993ea577SAkhil Goyal 		tx_pkts_burst = (struct rte_mbuf **)rte_calloc("tx_buff",
1004*993ea577SAkhil Goyal 					  MAX_TRAFFIC_BURST,
1005*993ea577SAkhil Goyal 					  sizeof(void *),
1006*993ea577SAkhil Goyal 					  RTE_CACHE_LINE_SIZE);
1007*993ea577SAkhil Goyal 		if (!tx_pkts_burst)
1008*993ea577SAkhil Goyal 			return TEST_FAILED;
1009*993ea577SAkhil Goyal 
1010*993ea577SAkhil Goyal 		rx_pkts_burst = (struct rte_mbuf **)rte_calloc("rx_buff",
1011*993ea577SAkhil Goyal 					  MAX_TRAFFIC_BURST,
1012*993ea577SAkhil Goyal 					  sizeof(void *),
1013*993ea577SAkhil Goyal 					  RTE_CACHE_LINE_SIZE);
1014*993ea577SAkhil Goyal 		if (!rx_pkts_burst)
1015*993ea577SAkhil Goyal 			return TEST_FAILED;
1016*993ea577SAkhil Goyal 	}
1017*993ea577SAkhil Goyal 
1018*993ea577SAkhil Goyal 	printf("Generate %d packets\n", MAX_TRAFFIC_BURST);
1019*993ea577SAkhil Goyal 
1020*993ea577SAkhil Goyal 	nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
1021*993ea577SAkhil Goyal 	nb_txd = RTE_TEST_TX_DESC_DEFAULT;
1022*993ea577SAkhil Goyal 
1023*993ea577SAkhil Goyal 	/* configuring port 0 for the test is enough */
1024*993ea577SAkhil Goyal 	port_id = 0;
1025*993ea577SAkhil Goyal 	/* port configure */
1026*993ea577SAkhil Goyal 	ret = rte_eth_dev_configure(port_id, nb_rx_queue,
1027*993ea577SAkhil Goyal 				    nb_tx_queue, &port_conf);
1028*993ea577SAkhil Goyal 	if (ret < 0) {
1029*993ea577SAkhil Goyal 		printf("Cannot configure device: err=%d, port=%d\n",
1030*993ea577SAkhil Goyal 			 ret, port_id);
1031*993ea577SAkhil Goyal 		return ret;
1032*993ea577SAkhil Goyal 	}
1033*993ea577SAkhil Goyal 	ret = rte_eth_macaddr_get(port_id, &ports_eth_addr[port_id]);
1034*993ea577SAkhil Goyal 	if (ret < 0) {
1035*993ea577SAkhil Goyal 		printf("Cannot get mac address: err=%d, port=%d\n",
1036*993ea577SAkhil Goyal 			 ret, port_id);
1037*993ea577SAkhil Goyal 		return ret;
1038*993ea577SAkhil Goyal 	}
1039*993ea577SAkhil Goyal 	printf("Port %u ", port_id);
1040*993ea577SAkhil Goyal 	print_ethaddr("Address:", &ports_eth_addr[port_id]);
1041*993ea577SAkhil Goyal 	printf("\n");
1042*993ea577SAkhil Goyal 
1043*993ea577SAkhil Goyal 	/* tx queue setup */
1044*993ea577SAkhil Goyal 	ret = rte_eth_tx_queue_setup(port_id, 0, nb_txd,
1045*993ea577SAkhil Goyal 				     SOCKET_ID_ANY, &tx_conf);
1046*993ea577SAkhil Goyal 	if (ret < 0) {
1047*993ea577SAkhil Goyal 		printf("rte_eth_tx_queue_setup: err=%d, port=%d\n",
1048*993ea577SAkhil Goyal 				ret, port_id);
1049*993ea577SAkhil Goyal 		return ret;
1050*993ea577SAkhil Goyal 	}
1051*993ea577SAkhil Goyal 	/* rx queue steup */
1052*993ea577SAkhil Goyal 	ret = rte_eth_rx_queue_setup(port_id, 0, nb_rxd, SOCKET_ID_ANY,
1053*993ea577SAkhil Goyal 				     &rx_conf, mbufpool);
1054*993ea577SAkhil Goyal 	if (ret < 0) {
1055*993ea577SAkhil Goyal 		printf("rte_eth_rx_queue_setup: err=%d, port=%d\n",
1056*993ea577SAkhil Goyal 				ret, port_id);
1057*993ea577SAkhil Goyal 		return ret;
1058*993ea577SAkhil Goyal 	}
1059*993ea577SAkhil Goyal 
1060*993ea577SAkhil Goyal 	return 0;
1061*993ea577SAkhil Goyal }
1062*993ea577SAkhil Goyal 
1063*993ea577SAkhil Goyal static void
1064*993ea577SAkhil Goyal inline_macsec_testsuite_teardown(void)
1065*993ea577SAkhil Goyal {
1066*993ea577SAkhil Goyal 	uint16_t portid;
1067*993ea577SAkhil Goyal 	int ret;
1068*993ea577SAkhil Goyal 
1069*993ea577SAkhil Goyal 	/* port tear down */
1070*993ea577SAkhil Goyal 	RTE_ETH_FOREACH_DEV(portid) {
1071*993ea577SAkhil Goyal 		ret = rte_eth_dev_reset(portid);
1072*993ea577SAkhil Goyal 		if (ret != 0)
1073*993ea577SAkhil Goyal 			printf("rte_eth_dev_reset: err=%s, port=%u\n",
1074*993ea577SAkhil Goyal 			       rte_strerror(-ret), port_id);
1075*993ea577SAkhil Goyal 	}
1076*993ea577SAkhil Goyal 	rte_free(tx_pkts_burst);
1077*993ea577SAkhil Goyal 	rte_free(rx_pkts_burst);
1078*993ea577SAkhil Goyal }
1079*993ea577SAkhil Goyal 
1080*993ea577SAkhil Goyal 
1081*993ea577SAkhil Goyal static struct unit_test_suite inline_macsec_testsuite  = {
1082*993ea577SAkhil Goyal 	.suite_name = "Inline MACsec Ethernet Device Unit Test Suite",
1083*993ea577SAkhil Goyal 	.unit_test_cases = {
1084*993ea577SAkhil Goyal 		TEST_CASE_NAMED_ST(
1085*993ea577SAkhil Goyal 			"MACsec encap(Cipher+Auth) known vector",
1086*993ea577SAkhil Goyal 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1087*993ea577SAkhil Goyal 			test_inline_macsec_encap_all),
1088*993ea577SAkhil Goyal 		TEST_CASE_NAMED_ST(
1089*993ea577SAkhil Goyal 			"MACsec decap(De-cipher+verify) known vector",
1090*993ea577SAkhil Goyal 			ut_setup_inline_macsec, ut_teardown_inline_macsec,
1091*993ea577SAkhil Goyal 			test_inline_macsec_decap_all),
1092*993ea577SAkhil Goyal 
1093*993ea577SAkhil Goyal 		TEST_CASES_END() /**< NULL terminate unit test array */
1094*993ea577SAkhil Goyal 	},
1095*993ea577SAkhil Goyal };
1096*993ea577SAkhil Goyal 
1097*993ea577SAkhil Goyal static int
1098*993ea577SAkhil Goyal test_inline_macsec(void)
1099*993ea577SAkhil Goyal {
1100*993ea577SAkhil Goyal 	inline_macsec_testsuite.setup = inline_macsec_testsuite_setup;
1101*993ea577SAkhil Goyal 	inline_macsec_testsuite.teardown = inline_macsec_testsuite_teardown;
1102*993ea577SAkhil Goyal 	return unit_test_suite_runner(&inline_macsec_testsuite);
1103*993ea577SAkhil Goyal }
1104*993ea577SAkhil Goyal 
1105*993ea577SAkhil Goyal #endif /* !RTE_EXEC_ENV_WINDOWS */
1106*993ea577SAkhil Goyal 
1107*993ea577SAkhil Goyal REGISTER_TEST_COMMAND(inline_macsec_autotest, test_inline_macsec);
1108