1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 
5 #include "roc_api.h"
6 #include "roc_priv.h"
7 
8 #define NPC_MAX_FIELD_NAME_SIZE	   80
9 #define NPC_RX_ACTIONOP_MASK	   GENMASK(3, 0)
10 #define NPC_RX_ACTION_PFFUNC_MASK  GENMASK(19, 4)
11 #define NPC_RX_ACTION_INDEX_MASK   GENMASK(39, 20)
12 #define NPC_RX_ACTION_MATCH_MASK   GENMASK(55, 40)
13 #define NPC_RX_ACTION_FLOWKEY_MASK GENMASK(60, 56)
14 
15 #define NPC_TX_ACTION_INDEX_MASK GENMASK(31, 12)
16 #define NPC_TX_ACTION_MATCH_MASK GENMASK(47, 32)
17 
18 #define NIX_RX_VTAGACT_VTAG0_RELPTR_MASK GENMASK(7, 0)
19 #define NIX_RX_VTAGACT_VTAG0_LID_MASK	 GENMASK(10, 8)
20 #define NIX_RX_VTAGACT_VTAG0_TYPE_MASK	 GENMASK(14, 12)
21 #define NIX_RX_VTAGACT_VTAG0_VALID_MASK	 BIT_ULL(15)
22 
23 #define NIX_RX_VTAGACT_VTAG1_RELPTR_MASK GENMASK(39, 32)
24 #define NIX_RX_VTAGACT_VTAG1_LID_MASK	 GENMASK(42, 40)
25 #define NIX_RX_VTAGACT_VTAG1_TYPE_MASK	 GENMASK(46, 44)
26 #define NIX_RX_VTAGACT_VTAG1_VALID_MASK	 BIT_ULL(47)
27 
28 #define NIX_TX_VTAGACT_VTAG0_RELPTR_MASK GENMASK(7, 0)
29 #define NIX_TX_VTAGACT_VTAG0_LID_MASK	 GENMASK(10, 8)
30 #define NIX_TX_VTAGACT_VTAG0_OP_MASK	 GENMASK(13, 12)
31 #define NIX_TX_VTAGACT_VTAG0_DEF_MASK	 GENMASK(25, 16)
32 
33 #define NIX_TX_VTAGACT_VTAG1_RELPTR_MASK GENMASK(39, 32)
34 #define NIX_TX_VTAGACT_VTAG1_LID_MASK	 GENMASK(42, 40)
35 #define NIX_TX_VTAGACT_VTAG1_OP_MASK	 GENMASK(45, 44)
36 #define NIX_TX_VTAGACT_VTAG1_DEF_MASK	 GENMASK(57, 48)
37 
38 struct npc_rx_parse_nibble_s {
39 	uint16_t chan : 3;
40 	uint16_t errlev : 1;
41 	uint16_t errcode : 2;
42 	uint16_t l2l3bm : 1;
43 	uint16_t laflags : 2;
44 	uint16_t latype : 1;
45 	uint16_t lbflags : 2;
46 	uint16_t lbtype : 1;
47 	uint16_t lcflags : 2;
48 	uint16_t lctype : 1;
49 	uint16_t ldflags : 2;
50 	uint16_t ldtype : 1;
51 	uint16_t leflags : 2;
52 	uint16_t letype : 1;
53 	uint16_t lfflags : 2;
54 	uint16_t lftype : 1;
55 	uint16_t lgflags : 2;
56 	uint16_t lgtype : 1;
57 	uint16_t lhflags : 2;
58 	uint16_t lhtype : 1;
59 } __plt_packed;
60 
61 static const char *const intf_str[] = {
62 	"NIX-RX",
63 	"NIX-TX",
64 };
65 
66 static const char *const ltype_str[NPC_MAX_LID][NPC_MAX_LT] = {
67 	[NPC_LID_LA][0] = "NONE",
68 	[NPC_LID_LA][NPC_LT_LA_ETHER] = "LA_ETHER",
69 	[NPC_LID_LA][NPC_LT_LA_IH_NIX_ETHER] = "LA_IH_NIX_ETHER",
70 	[NPC_LID_LA][NPC_LT_LA_HIGIG2_ETHER] = "LA_HIGIG2_ETHER",
71 	[NPC_LID_LA][NPC_LT_LA_IH_NIX_HIGIG2_ETHER] = "LA_IH_NIX_HIGIG2_ETHER",
72 	[NPC_LID_LA][NPC_LT_LA_CUSTOM_PRE_L2_ETHER] =
73 		"NPC_LT_LA_CUSTOM_PRE_L2_ETHER",
74 	[NPC_LID_LB][0] = "NONE",
75 	[NPC_LID_LB][NPC_LT_LB_CTAG] = "LB_CTAG",
76 	[NPC_LID_LB][NPC_LT_LB_STAG_QINQ] = "LB_STAG_QINQ",
77 	[NPC_LID_LB][NPC_LT_LB_ETAG] = "LB_ETAG",
78 	[NPC_LID_LB][NPC_LT_LB_EXDSA] = "LB_EXDSA",
79 	[NPC_LID_LB][NPC_LT_LB_VLAN_EXDSA] = "LB_VLAN_EXDSA",
80 	[NPC_LID_LC][0] = "NONE",
81 	[NPC_LID_LC][NPC_LT_LC_IP] = "LC_IP",
82 	[NPC_LID_LC][NPC_LT_LC_IP6] = "LC_IP6",
83 	[NPC_LID_LC][NPC_LT_LC_ARP] = "LC_ARP",
84 	[NPC_LID_LC][NPC_LT_LC_IP6_EXT] = "LC_IP6_EXT",
85 	[NPC_LID_LC][NPC_LT_LC_NGIO] = "LC_NGIO",
86 	[NPC_LID_LD][0] = "NONE",
87 	[NPC_LID_LD][NPC_LT_LD_ICMP] = "LD_ICMP",
88 	[NPC_LID_LD][NPC_LT_LD_ICMP6] = "LD_ICMP6",
89 	[NPC_LID_LD][NPC_LT_LD_UDP] = "LD_UDP",
90 	[NPC_LID_LD][NPC_LT_LD_TCP] = "LD_TCP",
91 	[NPC_LID_LD][NPC_LT_LD_SCTP] = "LD_SCTP",
92 	[NPC_LID_LD][NPC_LT_LD_GRE] = "LD_GRE",
93 	[NPC_LID_LD][NPC_LT_LD_NVGRE] = "LD_NVGRE",
94 	[NPC_LID_LE][0] = "NONE",
95 	[NPC_LID_LE][NPC_LT_LE_VXLAN] = "LE_VXLAN",
96 	[NPC_LID_LE][NPC_LT_LE_ESP] = "LE_ESP",
97 	[NPC_LID_LE][NPC_LT_LE_GTPC] = "LE_GTPC",
98 	[NPC_LID_LE][NPC_LT_LE_GTPU] = "LE_GTPU",
99 	[NPC_LID_LE][NPC_LT_LE_GENEVE] = "LE_GENEVE",
100 	[NPC_LID_LE][NPC_LT_LE_VXLANGPE] = "LE_VXLANGPE",
101 	[NPC_LID_LF][0] = "NONE",
102 	[NPC_LID_LF][NPC_LT_LF_TU_ETHER] = "LF_TU_ETHER",
103 	[NPC_LID_LG][0] = "NONE",
104 	[NPC_LID_LG][NPC_LT_LG_TU_IP] = "LG_TU_IP",
105 	[NPC_LID_LG][NPC_LT_LG_TU_IP6] = "LG_TU_IP6",
106 	[NPC_LID_LH][0] = "NONE",
107 	[NPC_LID_LH][NPC_LT_LH_TU_UDP] = "LH_TU_UDP",
108 	[NPC_LID_LH][NPC_LT_LH_TU_TCP] = "LH_TU_TCP",
109 	[NPC_LID_LH][NPC_LT_LH_TU_SCTP] = "LH_TU_SCTP",
110 	[NPC_LID_LH][NPC_LT_LH_TU_ESP] = "LH_TU_ESP",
111 };
112 
113 static uint16_t
npc_get_nibbles(struct roc_npc_flow * flow,uint16_t size,uint32_t bit_offset)114 npc_get_nibbles(struct roc_npc_flow *flow, uint16_t size, uint32_t bit_offset)
115 {
116 	uint32_t byte_index, noffset;
117 	uint16_t data, mask;
118 	uint8_t *bytes;
119 
120 	bytes = (uint8_t *)flow->mcam_data;
121 	mask = (1ULL << (size * 4)) - 1;
122 	byte_index = bit_offset / 8;
123 	noffset = bit_offset % 8;
124 	data = *(unaligned_uint16_t *)&bytes[byte_index];
125 	data >>= noffset;
126 	data &= mask;
127 
128 	return data;
129 }
130 
131 static void
npc_flow_print_parse_nibbles(FILE * file,struct roc_npc_flow * flow,uint64_t parse_nibbles)132 npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
133 			     uint64_t parse_nibbles)
134 {
135 	struct npc_rx_parse_nibble_s *rx_parse;
136 	uint32_t data, offset = 0;
137 
138 	rx_parse = (struct npc_rx_parse_nibble_s *)&parse_nibbles;
139 
140 	if (rx_parse->chan) {
141 		data = npc_get_nibbles(flow, 3, offset);
142 		fprintf(file, "\tNPC_PARSE_NIBBLE_CHAN:%#03X\n", data);
143 		offset += 12;
144 	}
145 
146 	if (rx_parse->errlev) {
147 		data = npc_get_nibbles(flow, 1, offset);
148 		fprintf(file, "\tNPC_PARSE_NIBBLE_ERRLEV:%#X\n", data);
149 		offset += 4;
150 	}
151 
152 	if (rx_parse->errcode) {
153 		data = npc_get_nibbles(flow, 2, offset);
154 		fprintf(file, "\tNPC_PARSE_NIBBLE_ERRCODE:%#02X\n", data);
155 		offset += 8;
156 	}
157 
158 	if (rx_parse->l2l3bm) {
159 		data = npc_get_nibbles(flow, 1, offset);
160 		fprintf(file, "\tNPC_PARSE_NIBBLE_L2L3_BCAST:%#X\n", data);
161 		offset += 4;
162 	}
163 
164 	if (rx_parse->laflags) {
165 		data = npc_get_nibbles(flow, 2, offset);
166 		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_FLAGS:%#02X\n", data);
167 		offset += 8;
168 	}
169 
170 	if (rx_parse->latype) {
171 		data = npc_get_nibbles(flow, 1, offset);
172 		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_LTYPE:%s\n",
173 			ltype_str[NPC_LID_LA][data]);
174 		offset += 4;
175 	}
176 
177 	if (rx_parse->lbflags) {
178 		data = npc_get_nibbles(flow, 2, offset);
179 		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_FLAGS:%#02X\n", data);
180 		offset += 8;
181 	}
182 
183 	if (rx_parse->lbtype) {
184 		data = npc_get_nibbles(flow, 1, offset);
185 		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_LTYPE:%s\n",
186 			ltype_str[NPC_LID_LB][data]);
187 		offset += 4;
188 	}
189 
190 	if (rx_parse->lcflags) {
191 		data = npc_get_nibbles(flow, 2, offset);
192 		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_FLAGS:%#02X\n", data);
193 		offset += 8;
194 	}
195 
196 	if (rx_parse->lctype) {
197 		data = npc_get_nibbles(flow, 1, offset);
198 		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_LTYPE:%s\n",
199 			ltype_str[NPC_LID_LC][data]);
200 		offset += 4;
201 	}
202 
203 	if (rx_parse->ldflags) {
204 		data = npc_get_nibbles(flow, 2, offset);
205 		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_FLAGS:%#02X\n", data);
206 		offset += 8;
207 	}
208 
209 	if (rx_parse->ldtype) {
210 		data = npc_get_nibbles(flow, 1, offset);
211 		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_LTYPE:%s\n",
212 			ltype_str[NPC_LID_LD][data]);
213 		offset += 4;
214 	}
215 
216 	if (rx_parse->leflags) {
217 		data = npc_get_nibbles(flow, 2, offset);
218 		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_FLAGS:%#02X\n", data);
219 		offset += 8;
220 	}
221 
222 	if (rx_parse->letype) {
223 		data = npc_get_nibbles(flow, 1, offset);
224 		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_LTYPE:%s\n",
225 			ltype_str[NPC_LID_LE][data]);
226 		offset += 4;
227 	}
228 
229 	if (rx_parse->lfflags) {
230 		data = npc_get_nibbles(flow, 2, offset);
231 		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_FLAGS:%#02X\n", data);
232 		offset += 8;
233 	}
234 
235 	if (rx_parse->lftype) {
236 		data = npc_get_nibbles(flow, 1, offset);
237 		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_LTYPE:%s\n",
238 			ltype_str[NPC_LID_LF][data]);
239 		offset += 4;
240 	}
241 
242 	if (rx_parse->lgflags) {
243 		data = npc_get_nibbles(flow, 2, offset);
244 		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_FLAGS:%#02X\n", data);
245 		offset += 8;
246 	}
247 
248 	if (rx_parse->lgtype) {
249 		data = npc_get_nibbles(flow, 1, offset);
250 		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_LTYPE:%s\n",
251 			ltype_str[NPC_LID_LG][data]);
252 		offset += 4;
253 	}
254 
255 	if (rx_parse->lhflags) {
256 		data = npc_get_nibbles(flow, 2, offset);
257 		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_FLAGS:%#02X\n", data);
258 	}
259 
260 	if (rx_parse->lhtype) {
261 		data = npc_get_nibbles(flow, 1, offset);
262 		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_LTYPE:%s\n",
263 			ltype_str[NPC_LID_LH][data]);
264 		offset += 4;
265 	}
266 }
267 
268 static void
npc_flow_print_xtractinfo(FILE * file,struct npc_xtract_info * lfinfo,struct roc_npc_flow * flow,int lid,int lt)269 npc_flow_print_xtractinfo(FILE *file, struct npc_xtract_info *lfinfo,
270 			  struct roc_npc_flow *flow, int lid, int lt)
271 {
272 	uint8_t *datastart, *maskstart;
273 	int i;
274 
275 	datastart = (uint8_t *)&flow->mcam_data + lfinfo->key_off;
276 	maskstart = (uint8_t *)&flow->mcam_mask + lfinfo->key_off;
277 
278 	fprintf(file, "\t%s, hdr offset:%#X, len:%#X, key offset:%#X, ",
279 		ltype_str[lid][lt], lfinfo->hdr_off, lfinfo->len,
280 		lfinfo->key_off);
281 
282 	fprintf(file, "Data:0X");
283 	for (i = lfinfo->len - 1; i >= 0; i--)
284 		fprintf(file, "%02X", datastart[i]);
285 
286 	fprintf(file, ", Mask:0X");
287 
288 	for (i = lfinfo->len - 1; i >= 0; i--)
289 		fprintf(file, "%02X", maskstart[i]);
290 
291 	fprintf(file, "\n");
292 }
293 
294 static void
npc_flow_print_item(FILE * file,struct npc * npc,struct npc_xtract_info * xinfo,struct roc_npc_flow * flow,int intf,int lid,int lt,int ld)295 npc_flow_print_item(FILE *file, struct npc *npc, struct npc_xtract_info *xinfo,
296 		    struct roc_npc_flow *flow, int intf, int lid, int lt,
297 		    int ld)
298 {
299 	struct npc_xtract_info *lflags_info;
300 	int i, lf_cfg = 0;
301 
302 	npc_flow_print_xtractinfo(file, xinfo, flow, lid, lt);
303 
304 	if (xinfo->flags_enable) {
305 		lf_cfg = npc->prx_lfcfg[ld].i;
306 
307 		if (lf_cfg != lid)
308 			return;
309 
310 		for (i = 0; i < NPC_MAX_LFL; i++) {
311 			lflags_info = npc->prx_fxcfg[intf][ld][i].xtract;
312 
313 			npc_flow_print_xtractinfo(file, lflags_info, flow, lid,
314 						  lt);
315 		}
316 	}
317 }
318 
319 static void
npc_flow_dump_patterns(FILE * file,struct npc * npc,struct roc_npc_flow * flow)320 npc_flow_dump_patterns(FILE *file, struct npc *npc, struct roc_npc_flow *flow)
321 {
322 	struct npc_lid_lt_xtract_info *lt_xinfo;
323 	struct npc_xtract_info *xinfo;
324 	uint32_t intf, lid, ld, i;
325 	uint64_t parse_nibbles;
326 	uint16_t ltype;
327 
328 	intf = flow->nix_intf;
329 	parse_nibbles = npc->keyx_supp_nmask[intf];
330 	npc_flow_print_parse_nibbles(file, flow, parse_nibbles);
331 
332 	for (i = 0; i < flow->num_patterns; i++) {
333 		lid = flow->dump_data[i].lid;
334 		ltype = flow->dump_data[i].ltype;
335 		lt_xinfo = &npc->prx_dxcfg[intf][lid][ltype];
336 
337 		for (ld = 0; ld < NPC_MAX_LD; ld++) {
338 			xinfo = &lt_xinfo->xtract[ld];
339 			if (!xinfo->enable)
340 				continue;
341 			npc_flow_print_item(file, npc, xinfo, flow, intf, lid,
342 					    ltype, ld);
343 		}
344 	}
345 }
346 
347 static void
npc_flow_dump_tx_action(FILE * file,uint64_t npc_action)348 npc_flow_dump_tx_action(FILE *file, uint64_t npc_action)
349 {
350 	char index_name[NPC_MAX_FIELD_NAME_SIZE] = "Index:";
351 	uint32_t tx_op, index, match_id;
352 
353 	tx_op = npc_action & NPC_RX_ACTIONOP_MASK;
354 
355 	fprintf(file, "\tActionOp:");
356 
357 	switch (tx_op) {
358 	case NIX_TX_ACTIONOP_DROP:
359 		fprintf(file, "NIX_TX_ACTIONOP_DROP (%" PRIu64 ")\n",
360 			(uint64_t)NIX_RX_ACTIONOP_DROP);
361 		break;
362 	case NIX_TX_ACTIONOP_UCAST_DEFAULT:
363 		fprintf(file, "NIX_TX_ACTIONOP_UCAST_DEFAULT (%" PRIu64 ")\n",
364 			(uint64_t)NIX_TX_ACTIONOP_UCAST_DEFAULT);
365 		break;
366 	case NIX_TX_ACTIONOP_UCAST_CHAN:
367 		fprintf(file, "NIX_TX_ACTIONOP_UCAST_DEFAULT (%" PRIu64 ")\n",
368 			(uint64_t)NIX_TX_ACTIONOP_UCAST_CHAN);
369 		plt_strlcpy(index_name,
370 			    "Transmit Channel:", NPC_MAX_FIELD_NAME_SIZE);
371 		break;
372 	case NIX_TX_ACTIONOP_MCAST:
373 		fprintf(file, "NIX_TX_ACTIONOP_MCAST (%" PRIu64 ")\n",
374 			(uint64_t)NIX_TX_ACTIONOP_MCAST);
375 		plt_strlcpy(index_name,
376 			    "Multicast Table Index:", NPC_MAX_FIELD_NAME_SIZE);
377 		break;
378 	case NIX_TX_ACTIONOP_DROP_VIOL:
379 		fprintf(file, "NIX_TX_ACTIONOP_DROP_VIOL (%" PRIu64 ")\n",
380 			(uint64_t)NIX_TX_ACTIONOP_DROP_VIOL);
381 		break;
382 	default:
383 		plt_err("Unknown NIX_TX_ACTIONOP found");
384 		return;
385 	}
386 
387 	index = ((npc_action & NPC_TX_ACTION_INDEX_MASK) >> 12) &
388 		GENMASK(19, 0);
389 
390 	fprintf(file, "\t%s:%#05X\n", index_name, index);
391 
392 	match_id = ((npc_action & NPC_TX_ACTION_MATCH_MASK) >> 32) &
393 		   GENMASK(15, 0);
394 
395 	fprintf(file, "\tMatch Id:%#04X\n", match_id);
396 }
397 
398 static void
npc_flow_dump_rx_action(FILE * file,uint64_t npc_action)399 npc_flow_dump_rx_action(FILE *file, uint64_t npc_action)
400 {
401 	uint32_t rx_op, pf_func, index, match_id, flowkey_alg;
402 	char index_name[NPC_MAX_FIELD_NAME_SIZE] = "Index:";
403 
404 	rx_op = npc_action & NPC_RX_ACTIONOP_MASK;
405 
406 	fprintf(file, "\tActionOp:");
407 
408 	switch (rx_op) {
409 	case NIX_RX_ACTIONOP_DROP:
410 		fprintf(file, "NIX_RX_ACTIONOP_DROP (%" PRIu64 ")\n",
411 			(uint64_t)NIX_RX_ACTIONOP_DROP);
412 		break;
413 	case NIX_RX_ACTIONOP_UCAST:
414 		fprintf(file, "NIX_RX_ACTIONOP_UCAST (%" PRIu64 ")\n",
415 			(uint64_t)NIX_RX_ACTIONOP_UCAST);
416 		plt_strlcpy(index_name, "RQ Index", NPC_MAX_FIELD_NAME_SIZE);
417 		break;
418 	case NIX_RX_ACTIONOP_UCAST_IPSEC:
419 		fprintf(file, "NIX_RX_ACTIONOP_UCAST_IPSEC (%" PRIu64 ")\n",
420 			(uint64_t)NIX_RX_ACTIONOP_UCAST_IPSEC);
421 		plt_strlcpy(index_name, "RQ Index:", NPC_MAX_FIELD_NAME_SIZE);
422 		break;
423 	case NIX_RX_ACTIONOP_MCAST:
424 		fprintf(file, "NIX_RX_ACTIONOP_MCAST (%" PRIu64 ")\n",
425 			(uint64_t)NIX_RX_ACTIONOP_MCAST);
426 		plt_strlcpy(index_name, "Multicast/mirror table index",
427 			    NPC_MAX_FIELD_NAME_SIZE);
428 		break;
429 	case NIX_RX_ACTIONOP_RSS:
430 		fprintf(file, "NIX_RX_ACTIONOP_RSS (%" PRIu64 ")\n",
431 			(uint64_t)NIX_RX_ACTIONOP_RSS);
432 		plt_strlcpy(index_name, "RSS Group Index",
433 			    NPC_MAX_FIELD_NAME_SIZE);
434 		break;
435 	case NIX_RX_ACTIONOP_PF_FUNC_DROP:
436 		fprintf(file, "NIX_RX_ACTIONOP_PF_FUNC_DROP (%" PRIu64 ")\n",
437 			(uint64_t)NIX_RX_ACTIONOP_PF_FUNC_DROP);
438 		break;
439 	case NIX_RX_ACTIONOP_MIRROR:
440 		fprintf(file, "NIX_RX_ACTIONOP_MIRROR (%" PRIu64 ")\n",
441 			(uint64_t)NIX_RX_ACTIONOP_MIRROR);
442 		plt_strlcpy(index_name, "Multicast/mirror table index",
443 			    NPC_MAX_FIELD_NAME_SIZE);
444 		break;
445 	default:
446 		plt_err("Unknown NIX_RX_ACTIONOP found");
447 		return;
448 	}
449 
450 	pf_func = ((npc_action & NPC_RX_ACTION_PFFUNC_MASK) >> 4) &
451 		  GENMASK(15, 0);
452 
453 	fprintf(file, "\tPF_FUNC: %#04X\n", pf_func);
454 
455 	index = ((npc_action & NPC_RX_ACTION_INDEX_MASK) >> 20) &
456 		GENMASK(19, 0);
457 
458 	fprintf(file, "\t%s:%#05X\n", index_name, index);
459 
460 	match_id = ((npc_action & NPC_RX_ACTION_MATCH_MASK) >> 40) &
461 		   GENMASK(15, 0);
462 
463 	fprintf(file, "\tMatch Id:%#04X\n", match_id);
464 
465 	flowkey_alg = ((npc_action & NPC_RX_ACTION_FLOWKEY_MASK) >> 56) &
466 		      GENMASK(4, 0);
467 
468 	fprintf(file, "\tFlow Key Alg:%#X\n", flowkey_alg);
469 }
470 
471 static void
npc_flow_dump_parsed_action(FILE * file,uint64_t npc_action,bool is_rx)472 npc_flow_dump_parsed_action(FILE *file, uint64_t npc_action, bool is_rx)
473 {
474 	if (is_rx) {
475 		fprintf(file, "NPC RX Action:%#016lX\n", npc_action);
476 		npc_flow_dump_rx_action(file, npc_action);
477 	} else {
478 		fprintf(file, "NPC TX Action:%#016lX\n", npc_action);
479 		npc_flow_dump_tx_action(file, npc_action);
480 	}
481 }
482 
483 static void
npc_flow_dump_rx_vtag_action(FILE * file,uint64_t vtag_action)484 npc_flow_dump_rx_vtag_action(FILE *file, uint64_t vtag_action)
485 {
486 	uint32_t type, lid, relptr;
487 
488 	if (vtag_action & NIX_RX_VTAGACT_VTAG0_VALID_MASK) {
489 		relptr = vtag_action & NIX_RX_VTAGACT_VTAG0_RELPTR_MASK;
490 		lid = ((vtag_action & NIX_RX_VTAGACT_VTAG0_LID_MASK) >> 8) &
491 		      GENMASK(2, 0);
492 		type = ((vtag_action & NIX_RX_VTAGACT_VTAG0_TYPE_MASK) >> 12) &
493 		       GENMASK(2, 0);
494 
495 		fprintf(file, "\tVTAG0:relptr:%#X\n", relptr);
496 		fprintf(file, "\tlid:%#X\n", lid);
497 		fprintf(file, "\ttype:%#X\n", type);
498 	}
499 
500 	if (vtag_action & NIX_RX_VTAGACT_VTAG1_VALID_MASK) {
501 		relptr = ((vtag_action & NIX_RX_VTAGACT_VTAG1_RELPTR_MASK) >>
502 			  32) &
503 			 GENMASK(7, 0);
504 		lid = ((vtag_action & NIX_RX_VTAGACT_VTAG1_LID_MASK) >> 40) &
505 		      GENMASK(2, 0);
506 		type = ((vtag_action & NIX_RX_VTAGACT_VTAG1_TYPE_MASK) >> 44) &
507 		       GENMASK(2, 0);
508 
509 		fprintf(file, "\tVTAG1:relptr:%#X\n", relptr);
510 		fprintf(file, "\tlid:%#X\n", lid);
511 		fprintf(file, "\ttype:%#X\n", type);
512 	}
513 }
514 
515 static void
npc_get_vtag_opname(uint32_t op,char * opname,int len)516 npc_get_vtag_opname(uint32_t op, char *opname, int len)
517 {
518 	switch (op) {
519 	case 0x0:
520 		plt_strlcpy(opname, "NOP", len - 1);
521 		break;
522 	case 0x1:
523 		plt_strlcpy(opname, "INSERT", len - 1);
524 		break;
525 	case 0x2:
526 		plt_strlcpy(opname, "REPLACE", len - 1);
527 		break;
528 	default:
529 		plt_err("Unknown vtag op found");
530 		break;
531 	}
532 }
533 
534 static void
npc_flow_dump_tx_vtag_action(FILE * file,uint64_t vtag_action)535 npc_flow_dump_tx_vtag_action(FILE *file, uint64_t vtag_action)
536 {
537 	uint32_t relptr, lid, op, vtag_def;
538 	char opname[10];
539 
540 	relptr = vtag_action & NIX_TX_VTAGACT_VTAG0_RELPTR_MASK;
541 	lid = ((vtag_action & NIX_TX_VTAGACT_VTAG0_LID_MASK) >> 8) &
542 	      GENMASK(2, 0);
543 	op = ((vtag_action & NIX_TX_VTAGACT_VTAG0_OP_MASK) >> 12) &
544 	     GENMASK(1, 0);
545 	vtag_def = ((vtag_action & NIX_TX_VTAGACT_VTAG0_DEF_MASK) >> 16) &
546 		   GENMASK(9, 0);
547 
548 	npc_get_vtag_opname(op, opname, sizeof(opname));
549 
550 	fprintf(file, "\tVTAG0 relptr:%#X\n", relptr);
551 	fprintf(file, "\tlid:%#X\n", lid);
552 	fprintf(file, "\top:%s\n", opname);
553 	fprintf(file, "\tvtag_def:%#X\n", vtag_def);
554 
555 	relptr = ((vtag_action & NIX_TX_VTAGACT_VTAG1_RELPTR_MASK) >> 32) &
556 		 GENMASK(7, 0);
557 	lid = ((vtag_action & NIX_TX_VTAGACT_VTAG1_LID_MASK) >> 40) &
558 	      GENMASK(2, 0);
559 	op = ((vtag_action & NIX_TX_VTAGACT_VTAG1_OP_MASK) >> 44) &
560 	     GENMASK(1, 0);
561 	vtag_def = ((vtag_action & NIX_TX_VTAGACT_VTAG1_DEF_MASK) >> 48) &
562 		   GENMASK(9, 0);
563 
564 	npc_get_vtag_opname(op, opname, sizeof(opname));
565 
566 	fprintf(file, "\tVTAG1:relptr:%#X\n", relptr);
567 	fprintf(file, "\tlid:%#X\n", lid);
568 	fprintf(file, "\top:%s\n", opname);
569 	fprintf(file, "\tvtag_def:%#X\n", vtag_def);
570 }
571 
572 static void
npc_flow_dump_vtag_action(FILE * file,uint64_t vtag_action,bool is_rx)573 npc_flow_dump_vtag_action(FILE *file, uint64_t vtag_action, bool is_rx)
574 {
575 	if (is_rx) {
576 		fprintf(file, "NPC RX VTAG Action:%#016lX\n", vtag_action);
577 		npc_flow_dump_rx_vtag_action(file, vtag_action);
578 	} else {
579 		fprintf(file, "NPC TX VTAG Action:%#016lX\n", vtag_action);
580 		npc_flow_dump_tx_vtag_action(file, vtag_action);
581 	}
582 }
583 
584 void
roc_npc_flow_mcam_dump(FILE * file,struct roc_npc * roc_npc,struct roc_npc_flow * flow)585 roc_npc_flow_mcam_dump(FILE *file, struct roc_npc *roc_npc,
586 		       struct roc_npc_flow *flow)
587 {
588 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
589 	bool is_rx = 0;
590 	int i;
591 
592 	fprintf(file, "MCAM Index:%d\n", flow->mcam_id);
593 	fprintf(file, "Interface :%s (%d)\n", intf_str[flow->nix_intf],
594 		flow->nix_intf);
595 	fprintf(file, "Priority  :%d\n", flow->priority);
596 
597 	if (flow->nix_intf == NIX_INTF_RX)
598 		is_rx = 1;
599 
600 	npc_flow_dump_parsed_action(file, flow->npc_action, is_rx);
601 	npc_flow_dump_vtag_action(file, flow->vtag_action, is_rx);
602 	fprintf(file, "Patterns:\n");
603 	npc_flow_dump_patterns(file, npc, flow);
604 
605 	fprintf(file, "MCAM Raw Data :\n");
606 
607 	for (i = 0; i < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; i++) {
608 		fprintf(file, "\tDW%d     :%016lX\n", i, flow->mcam_data[i]);
609 		fprintf(file, "\tDW%d_Mask:%016lX\n", i, flow->mcam_mask[i]);
610 	}
611 
612 	fprintf(file, "\n");
613 }
614