xref: /dpdk/drivers/net/cnxk/cnxk_ethdev_mtr.c (revision 0cd91fd3)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 
5 #include "cnxk_ethdev.h"
6 #include <rte_mtr_driver.h>
7 
8 #define NIX_MTR_COUNT_MAX      73 /* 64(leaf) + 8(mid) + 1(top) */
9 #define NIX_MTR_COUNT_PER_FLOW 3  /* 1(leaf) + 1(mid) + 1(top) */
10 
11 #define NIX_BPF_STATS_MASK_ALL                                                 \
12 	{                                                                      \
13 		ROC_NIX_BPF_GREEN_PKT_F_PASS | ROC_NIX_BPF_GREEN_OCTS_F_PASS | \
14 			ROC_NIX_BPF_GREEN_PKT_F_DROP |                         \
15 			ROC_NIX_BPF_GREEN_OCTS_F_DROP |                        \
16 			ROC_NIX_BPF_YELLOW_PKT_F_PASS |                        \
17 			ROC_NIX_BPF_YELLOW_OCTS_F_PASS |                       \
18 			ROC_NIX_BPF_YELLOW_PKT_F_DROP |                        \
19 			ROC_NIX_BPF_YELLOW_OCTS_F_DROP |                       \
20 			ROC_NIX_BPF_RED_PKT_F_PASS |                           \
21 			ROC_NIX_BPF_RED_OCTS_F_PASS |                          \
22 			ROC_NIX_BPF_RED_PKT_F_DROP |                           \
23 			ROC_NIX_BPF_RED_OCTS_F_DROP                            \
24 	}
25 
26 static const enum roc_nix_bpf_level_flag lvl_map[] = {ROC_NIX_BPF_LEVEL_F_LEAF,
27 						      ROC_NIX_BPF_LEVEL_F_MID,
28 						      ROC_NIX_BPF_LEVEL_F_TOP};
29 
30 static struct rte_mtr_capabilities mtr_capa = {
31 	.n_shared_max = NIX_MTR_COUNT_PER_FLOW,
32 	/* .identical = , */
33 	.shared_identical = true,
34 	/* .shared_n_flows_per_mtr_max = ,*/
35 	.chaining_n_mtrs_per_flow_max = NIX_MTR_COUNT_PER_FLOW,
36 	.chaining_use_prev_mtr_color_supported = true,
37 	.chaining_use_prev_mtr_color_enforced = true,
38 	.meter_rate_max = NIX_BPF_RATE_MAX / 8, /* Bytes per second */
39 	.color_aware_srtcm_rfc2697_supported = true,
40 	.color_aware_trtcm_rfc2698_supported = true,
41 	.color_aware_trtcm_rfc4115_supported = true,
42 	.srtcm_rfc2697_byte_mode_supported = true,
43 	.srtcm_rfc2697_packet_mode_supported = true,
44 	.trtcm_rfc2698_byte_mode_supported = true,
45 	.trtcm_rfc2698_packet_mode_supported = true,
46 	.trtcm_rfc4115_byte_mode_supported = true,
47 	.trtcm_rfc4115_packet_mode_supported = true,
48 	.stats_mask = RTE_MTR_STATS_N_PKTS_GREEN | RTE_MTR_STATS_N_PKTS_YELLOW |
49 		      RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_PKTS_DROPPED |
50 		      RTE_MTR_STATS_N_BYTES_GREEN |
51 		      RTE_MTR_STATS_N_BYTES_YELLOW | RTE_MTR_STATS_N_BYTES_RED |
52 		      RTE_MTR_STATS_N_BYTES_DROPPED};
53 
54 static struct cnxk_meter_node *
55 nix_mtr_find(struct cnxk_eth_dev *dev, uint32_t meter_id)
56 {
57 	struct cnxk_mtr *fms = &dev->mtr;
58 	struct cnxk_meter_node *fm;
59 
60 	TAILQ_FOREACH(fm, fms, next)
61 		if (meter_id == fm->id)
62 			return fm;
63 	return NULL;
64 }
65 
66 static struct cnxk_mtr_profile_node *
67 nix_mtr_profile_find(struct cnxk_eth_dev *dev, uint32_t profile_id)
68 {
69 	struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
70 	struct cnxk_mtr_profile_node *fmp;
71 
72 	TAILQ_FOREACH(fmp, fmps, next)
73 		if (profile_id == fmp->id)
74 			return fmp;
75 
76 	return NULL;
77 }
78 
79 static struct cnxk_mtr_policy_node *
80 nix_mtr_policy_find(struct cnxk_eth_dev *dev, uint32_t meter_policy_id)
81 {
82 	struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
83 	struct cnxk_mtr_policy_node *fmp;
84 
85 	TAILQ_FOREACH(fmp, fmps, next)
86 		if (meter_policy_id == fmp->id)
87 			return fmp;
88 	return NULL;
89 }
90 
91 static int
92 nix_mtr_profile_validate(struct cnxk_eth_dev *dev, uint32_t profile_id,
93 			 struct rte_mtr_meter_profile *profile,
94 			 struct rte_mtr_error *error)
95 {
96 	int rc = 0;
97 
98 	PLT_SET_USED(dev);
99 
100 	if (profile == NULL)
101 		return -rte_mtr_error_set(error, EINVAL,
102 					  RTE_MTR_ERROR_TYPE_METER_PROFILE,
103 					  NULL, "Meter profile is null.");
104 
105 	if (profile_id == UINT32_MAX)
106 		return -rte_mtr_error_set(error, EINVAL,
107 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
108 					  NULL, "Meter profile id not valid.");
109 
110 	switch (profile->alg) {
111 	case RTE_MTR_SRTCM_RFC2697:
112 		if (profile->srtcm_rfc2697.cir > mtr_capa.meter_rate_max)
113 			rc = -rte_mtr_error_set(error, EINVAL,
114 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
115 				"CIR exceeds max meter rate");
116 
117 		if (profile->srtcm_rfc2697.cbs > NIX_BPF_BURST_MAX)
118 			rc = -rte_mtr_error_set(error, EINVAL,
119 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
120 				"CBS exceeds max meter burst size");
121 
122 		if (profile->srtcm_rfc2697.ebs > NIX_BPF_BURST_MAX)
123 			rc = -rte_mtr_error_set(error, EINVAL,
124 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
125 				"EBS exceeds max meter burst size");
126 		break;
127 
128 	case RTE_MTR_TRTCM_RFC2698:
129 		if (profile->trtcm_rfc2698.cir > mtr_capa.meter_rate_max)
130 			rc = -rte_mtr_error_set(error, EINVAL,
131 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
132 				"CIR exceeds max meter rate");
133 
134 		if (profile->trtcm_rfc2698.pir > mtr_capa.meter_rate_max)
135 			rc = -rte_mtr_error_set(error, EINVAL,
136 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
137 				"PIR exceeds max meter rate");
138 
139 		if (profile->trtcm_rfc2698.cbs > NIX_BPF_BURST_MAX)
140 			rc = -rte_mtr_error_set(error, EINVAL,
141 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
142 				"CBS exceeds max meter burst size");
143 
144 		if (profile->trtcm_rfc2698.pbs > NIX_BPF_BURST_MAX)
145 			rc = -rte_mtr_error_set(error, EINVAL,
146 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
147 				"PBS exceeds max meter burst size");
148 		break;
149 
150 	case RTE_MTR_TRTCM_RFC4115:
151 		if ((profile->trtcm_rfc4115.cir + profile->trtcm_rfc4115.eir) >
152 		    mtr_capa.meter_rate_max)
153 			rc = -rte_mtr_error_set(error, EINVAL,
154 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
155 				"PIR + EIR exceeds max rate");
156 
157 		if (profile->trtcm_rfc4115.cbs > NIX_BPF_BURST_MAX)
158 			rc = -rte_mtr_error_set(error, EINVAL,
159 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
160 				"CBS exceeds max meter burst size");
161 
162 		if (profile->trtcm_rfc4115.ebs > NIX_BPF_BURST_MAX)
163 			rc = -rte_mtr_error_set(error, EINVAL,
164 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
165 				"PBS exceeds max meter burst size");
166 		break;
167 
168 	default:
169 		rc = -rte_mtr_error_set(error, EINVAL,
170 					RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
171 					"alg is invalid");
172 		break;
173 	}
174 
175 	return rc;
176 }
177 
178 static int
179 cnxk_nix_mtr_capabilities_get(struct rte_eth_dev *dev,
180 			      struct rte_mtr_capabilities *capa,
181 			      struct rte_mtr_error *error)
182 {
183 	struct cnxk_eth_dev *eth_dev = cnxk_eth_pmd_priv(dev);
184 	uint16_t count[ROC_NIX_BPF_LEVEL_MAX] = {0};
185 	uint8_t lvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF | ROC_NIX_BPF_LEVEL_F_MID |
186 			   ROC_NIX_BPF_LEVEL_F_TOP;
187 	struct roc_nix *nix = &eth_dev->nix;
188 	int rc;
189 	int i;
190 
191 	RTE_SET_USED(dev);
192 
193 	if (!capa)
194 		return -rte_mtr_error_set(error, EINVAL,
195 				RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
196 				"NULL input parameter");
197 
198 	rc = roc_nix_bpf_count_get(nix, lvl_mask, count);
199 	if (rc)
200 		return rc;
201 
202 	for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++)
203 		mtr_capa.n_max += count[i];
204 
205 	mtr_capa.meter_srtcm_rfc2697_n_max = mtr_capa.n_max;
206 	mtr_capa.meter_trtcm_rfc2698_n_max = mtr_capa.n_max;
207 	mtr_capa.meter_trtcm_rfc4115_n_max = mtr_capa.n_max;
208 	mtr_capa.meter_policy_n_max = mtr_capa.n_max;
209 
210 	*capa = mtr_capa;
211 	return 0;
212 }
213 
214 static int
215 cnxk_nix_mtr_profile_add(struct rte_eth_dev *eth_dev, uint32_t profile_id,
216 			 struct rte_mtr_meter_profile *profile,
217 			 struct rte_mtr_error *error)
218 {
219 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
220 	struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
221 	struct cnxk_mtr_profile_node *fmp;
222 	int ret;
223 
224 	/* Check input params. */
225 	ret = nix_mtr_profile_validate(dev, profile_id, profile, error);
226 	if (ret)
227 		return ret;
228 
229 	fmp = nix_mtr_profile_find(dev, profile_id);
230 	if (fmp) {
231 		return -rte_mtr_error_set(error, EEXIST,
232 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
233 					  NULL, "Profile already exist");
234 	}
235 
236 	fmp = plt_zmalloc(sizeof(struct cnxk_mtr_profile_node), ROC_ALIGN);
237 	if (fmp == NULL)
238 		return -rte_mtr_error_set(error, ENOMEM,
239 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
240 					  "Meter profile memory "
241 					  "alloc failed.");
242 
243 	fmp->id = profile_id;
244 	fmp->profile = *profile;
245 
246 	TAILQ_INSERT_TAIL(fmps, fmp, next);
247 
248 	return 0;
249 }
250 
251 static int
252 cnxk_nix_mtr_profile_delete(struct rte_eth_dev *eth_dev, uint32_t profile_id,
253 			    struct rte_mtr_error *error)
254 {
255 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
256 	struct cnxk_mtr_profile_node *fmp;
257 
258 	if (profile_id == UINT32_MAX)
259 		return -rte_mtr_error_set(error, EINVAL,
260 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
261 					  NULL, "Meter profile id not valid.");
262 
263 	fmp = nix_mtr_profile_find(dev, profile_id);
264 	if (fmp == NULL)
265 		return -rte_mtr_error_set(error, ENOENT,
266 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
267 					  &profile_id,
268 					  "Meter profile is invalid.");
269 
270 	if (fmp->ref_cnt)
271 		return -rte_mtr_error_set(error, EBUSY,
272 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
273 					  NULL, "Meter profile is in use.");
274 
275 	TAILQ_REMOVE(&dev->mtr_profiles, fmp, next);
276 	plt_free(fmp);
277 	return 0;
278 }
279 
280 static int
281 cnxk_nix_mtr_policy_validate(struct rte_eth_dev *dev,
282 			     struct rte_mtr_meter_policy_params *policy,
283 			     struct rte_mtr_error *error)
284 {
285 	static const char *const action_color[] = {"Green", "Yellow", "Red"};
286 	bool supported[RTE_COLORS] = {false, false, false};
287 	const struct rte_flow_action *action;
288 	char message[1024];
289 	uint32_t i;
290 
291 	RTE_SET_USED(dev);
292 
293 	if (!policy)
294 		return 0; /* Nothing to be validated */
295 
296 	for (i = 0; i < RTE_COLORS; i++) {
297 		if (policy->actions[i]) {
298 			for (action = policy->actions[i];
299 			     action->type != RTE_FLOW_ACTION_TYPE_END;
300 			     action++) {
301 				if (action->type == RTE_FLOW_ACTION_TYPE_METER)
302 					supported[i] = true;
303 
304 				if (action->type == RTE_FLOW_ACTION_TYPE_DROP)
305 					supported[i] = true;
306 
307 				if (!supported[i]) {
308 					sprintf(message,
309 						"%s action is not valid",
310 						action_color[i]);
311 					return -rte_mtr_error_set(error,
312 					  ENOTSUP,
313 					  RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
314 					  message);
315 				}
316 			}
317 		} else {
318 			sprintf(message, "%s action is null", action_color[i]);
319 			return -rte_mtr_error_set(error, EINVAL,
320 				RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
321 				message);
322 		}
323 	}
324 
325 	return 0;
326 }
327 
328 static void
329 cnxk_fill_policy_actions(struct cnxk_mtr_policy_node *fmp,
330 			 struct rte_mtr_meter_policy_params *policy)
331 
332 {
333 	const struct rte_flow_action_meter *mtr;
334 	const struct rte_flow_action *action;
335 	int i;
336 
337 	for (i = 0; i < RTE_COLORS; i++) {
338 		if (policy->actions[i]) {
339 			for (action = policy->actions[i];
340 			     action->type != RTE_FLOW_ACTION_TYPE_END;
341 			     action++) {
342 				if (action->type ==
343 				    RTE_FLOW_ACTION_TYPE_METER) {
344 					fmp->actions[i].action_fate =
345 						action->type;
346 					mtr = (const struct
347 					       rte_flow_action_meter *)
348 						      action->conf;
349 					fmp->actions[i].mtr_id = mtr->mtr_id;
350 				}
351 
352 				if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
353 					fmp->actions[i].action_fate =
354 						action->type;
355 				}
356 			}
357 		}
358 	}
359 }
360 
361 static int
362 cnxk_nix_mtr_policy_add(struct rte_eth_dev *eth_dev, uint32_t policy_id,
363 			struct rte_mtr_meter_policy_params *policy,
364 			struct rte_mtr_error *error)
365 {
366 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
367 	struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
368 	struct cnxk_mtr_policy_node *fmp;
369 	int rc;
370 
371 	fmp = nix_mtr_policy_find(dev, policy_id);
372 	if (fmp) {
373 		return -rte_mtr_error_set(error, EEXIST,
374 					  RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
375 					  NULL, "Policy already exist");
376 	}
377 
378 	fmp = plt_zmalloc(sizeof(struct cnxk_mtr_policy_node), ROC_ALIGN);
379 	if (fmp == NULL) {
380 		return -rte_mtr_error_set(error, ENOMEM,
381 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
382 					  "Memory allocation failure");
383 	} else {
384 		rc = cnxk_nix_mtr_policy_validate(eth_dev, policy, error);
385 		if (rc)
386 			goto exit;
387 	}
388 
389 	fmp->id = policy_id;
390 	cnxk_fill_policy_actions(fmp, policy);
391 	TAILQ_INSERT_TAIL(fmps, fmp, next);
392 	return 0;
393 
394 exit:
395 	plt_free(fmp);
396 	return rc;
397 }
398 
399 static int
400 cnxk_nix_mtr_policy_delete(struct rte_eth_dev *eth_dev, uint32_t policy_id,
401 			   struct rte_mtr_error *error)
402 {
403 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
404 	struct cnxk_mtr_policy_node *fmp;
405 
406 	fmp = nix_mtr_policy_find(dev, policy_id);
407 	if (fmp == NULL) {
408 		return -rte_mtr_error_set(error, ENOENT,
409 					  RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
410 					  NULL, "No policy found");
411 	}
412 
413 	if (fmp->ref_cnt)
414 		return -rte_mtr_error_set(error, EBUSY,
415 					  RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
416 					  NULL, "Meter policy is in use.");
417 
418 	TAILQ_REMOVE(&dev->mtr_policy, fmp, next);
419 	plt_free(fmp);
420 
421 	return 0;
422 }
423 
424 static int
425 cnxk_nix_mtr_create(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
426 		    struct rte_mtr_params *params, int shared,
427 		    struct rte_mtr_error *error)
428 {
429 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
430 	struct cnxk_mtr_profile_node *profile;
431 	struct cnxk_mtr_policy_node *policy;
432 	struct cnxk_mtr *fm = &dev->mtr;
433 	struct cnxk_meter_node *mtr;
434 	int i;
435 
436 	RTE_SET_USED(shared);
437 
438 	if (params == NULL)
439 		return -rte_mtr_error_set(error, ENOENT,
440 					  RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
441 					  "Meter params are invalid.");
442 
443 	profile = nix_mtr_profile_find(dev, params->meter_profile_id);
444 	if (profile == NULL)
445 		return -rte_mtr_error_set(error, ENOENT,
446 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
447 					  &params->meter_profile_id,
448 					  "Meter profile is invalid.");
449 
450 	policy = nix_mtr_policy_find(dev, params->meter_policy_id);
451 	if (policy == NULL)
452 		return -rte_mtr_error_set(error, ENOENT,
453 					  RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
454 					  &params->meter_policy_id,
455 					  "Meter policy is invalid.");
456 
457 	mtr = nix_mtr_find(dev, mtr_id);
458 	if (mtr) {
459 		return -rte_mtr_error_set(error, EEXIST,
460 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
461 					  "Meter already exist");
462 	}
463 
464 	mtr = plt_zmalloc(sizeof(struct cnxk_meter_node), ROC_ALIGN);
465 	if (mtr == NULL) {
466 		return -rte_mtr_error_set(error, ENOMEM,
467 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
468 					  "Meter memory alloc failed.");
469 	}
470 
471 	mtr->id = mtr_id;
472 	mtr->profile = profile;
473 	mtr->policy = policy;
474 	mtr->params = *params;
475 	mtr->bpf_id = ROC_NIX_BPF_ID_INVALID;
476 	mtr->prev_cnt = 0;
477 	for (i = 0; i < MAX_PRV_MTR_NODES; i++)
478 		mtr->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
479 
480 	mtr->next_id = ROC_NIX_BPF_ID_INVALID;
481 	mtr->is_next = false;
482 	mtr->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
483 
484 	if (params->dscp_table) {
485 		mtr->params.dscp_table =
486 			plt_zmalloc(ROC_NIX_BPF_PRE_COLOR_MAX, ROC_ALIGN);
487 		if (mtr->params.dscp_table == NULL) {
488 			plt_free(mtr);
489 			return -rte_mtr_error_set(error, ENOMEM,
490 					RTE_MTR_ERROR_TYPE_UNSPECIFIED,
491 					NULL, "Memory alloc failed.");
492 		}
493 
494 		for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
495 			mtr->params.dscp_table[i] = params->dscp_table[i];
496 	}
497 
498 	profile->ref_cnt++;
499 	policy->ref_cnt++;
500 	TAILQ_INSERT_TAIL(fm, mtr, next);
501 	return 0;
502 }
503 
504 static int
505 cnxk_nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
506 		     struct rte_mtr_error *error)
507 {
508 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
509 	struct roc_nix_bpf_objs profs = {0};
510 	struct cnxk_mtr *fm = &dev->mtr;
511 	struct roc_nix *nix = &dev->nix;
512 	struct cnxk_meter_node *mtr;
513 	struct cnxk_meter_node *mid_mtr;
514 	struct cnxk_meter_node *top_mtr;
515 	int rc = 0;
516 
517 	mtr = nix_mtr_find(dev, mtr_id);
518 	if (mtr == NULL) {
519 		return -rte_mtr_error_set(error, ENOENT,
520 					  RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
521 					  "Meter id is invalid.");
522 	}
523 
524 	if (mtr->ref_cnt) {
525 		return -rte_mtr_error_set(error, EADDRINUSE,
526 					  RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
527 					  "Meter id in use.");
528 	}
529 
530 	switch (lvl_map[mtr->level]) {
531 	case ROC_NIX_BPF_LEVEL_F_LEAF:
532 		if (mtr->is_next) {
533 			rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
534 						 mtr->bpf_id,
535 						 ROC_NIX_BPF_ID_INVALID);
536 		}
537 		break;
538 	case ROC_NIX_BPF_LEVEL_F_MID:
539 		while ((mtr->prev_cnt) + 1) {
540 			mid_mtr =
541 				nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
542 			rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
543 						 mid_mtr->bpf_id,
544 						 ROC_NIX_BPF_ID_INVALID);
545 			mtr->prev_cnt--;
546 		}
547 		if (mtr->is_next) {
548 			rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
549 						 mtr->bpf_id,
550 						 ROC_NIX_BPF_ID_INVALID);
551 		}
552 		break;
553 	case ROC_NIX_BPF_LEVEL_F_TOP:
554 		while (mtr->prev_cnt) {
555 			top_mtr =
556 				nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
557 			rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
558 						 top_mtr->bpf_id,
559 						 ROC_NIX_BPF_ID_INVALID);
560 			mtr->prev_cnt--;
561 		}
562 		break;
563 	default:
564 		return -rte_mtr_error_set(error, EINVAL,
565 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
566 					  "Invalid meter level");
567 	}
568 
569 	if (rc)
570 		goto exit;
571 
572 	profs.level = mtr->level;
573 	profs.count = 1;
574 	profs.ids[0] = mtr->bpf_id;
575 	rc = roc_nix_bpf_free(nix, &profs, 1);
576 	if (rc)
577 		goto exit;
578 
579 	mtr->policy->ref_cnt--;
580 	mtr->profile->ref_cnt--;
581 	TAILQ_REMOVE(fm, mtr, next);
582 	plt_free(mtr->params.dscp_table);
583 	plt_free(mtr);
584 
585 exit:
586 	return rc;
587 }
588 
589 static int
590 cnxk_nix_mtr_enable(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
591 		    struct rte_mtr_error *error)
592 {
593 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
594 	struct roc_nix *nix = &dev->nix;
595 	struct cnxk_meter_node *mtr;
596 	struct roc_nix_rq *rq;
597 	uint32_t i;
598 	int rc = 0;
599 
600 	mtr = nix_mtr_find(dev, mtr_id);
601 	if (mtr == NULL) {
602 		return -rte_mtr_error_set(error, ENOENT,
603 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
604 					  "Meter id is invalid.");
605 	}
606 
607 	if (mtr->level != 0)
608 		return 0;
609 
610 	for (i = 0; i < mtr->rq_num; i++) {
611 		rq = &dev->rqs[mtr->rq_id[i]];
612 		rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, true);
613 	}
614 
615 	return rc;
616 }
617 
618 static int
619 cnxk_nix_mtr_disable(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
620 		     struct rte_mtr_error *error)
621 {
622 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
623 	struct roc_nix *nix = &dev->nix;
624 	struct cnxk_meter_node *mtr;
625 	struct roc_nix_rq *rq;
626 	uint32_t i;
627 	int rc = 0;
628 
629 	mtr = nix_mtr_find(dev, mtr_id);
630 	if (mtr == NULL) {
631 		return -rte_mtr_error_set(error, ENOENT,
632 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
633 					  "Meter id is invalid.");
634 	}
635 
636 	if (mtr->level != 0)
637 		return 0;
638 
639 	for (i = 0; i < mtr->rq_num; i++) {
640 		rq = &dev->rqs[mtr->rq_id[i]];
641 		rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, false);
642 	}
643 
644 	return rc;
645 }
646 
647 static int
648 cnxk_nix_mtr_dscp_table_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
649 			       enum rte_color *dscp_table,
650 			       struct rte_mtr_error *error)
651 {
652 	enum roc_nix_bpf_color nix_dscp_tbl[ROC_NIX_BPF_PRE_COLOR_MAX];
653 	enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
654 					      ROC_NIX_BPF_COLOR_YELLOW,
655 					      ROC_NIX_BPF_COLOR_RED};
656 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
657 	struct roc_nix_bpf_precolor table;
658 	struct roc_nix *nix = &dev->nix;
659 	struct cnxk_meter_node *mtr;
660 	int rc, i;
661 
662 	mtr = nix_mtr_find(dev, mtr_id);
663 	if (mtr == NULL) {
664 		return -rte_mtr_error_set(error, ENOENT,
665 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
666 					  "Meter object not found");
667 	}
668 
669 	if (!dscp_table) {
670 		for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
671 			nix_dscp_tbl[i] = ROC_NIX_BPF_COLOR_GREEN;
672 	} else {
673 		for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
674 			nix_dscp_tbl[i] = color_map[dscp_table[i]];
675 	}
676 
677 	table.count = ROC_NIX_BPF_PRE_COLOR_MAX;
678 	table.mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
679 	for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
680 		table.color[i] = nix_dscp_tbl[i];
681 
682 	rc = roc_nix_bpf_pre_color_tbl_setup(nix, mtr->bpf_id,
683 					     lvl_map[mtr->level], &table);
684 	if (rc) {
685 		rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
686 				  NULL, NULL);
687 		goto exit;
688 	}
689 
690 	for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
691 		dev->precolor_tbl[i] = nix_dscp_tbl[i];
692 
693 exit:
694 	return rc;
695 }
696 
697 static int
698 cnxk_nix_mtr_stats_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
699 			  uint64_t stats_mask, struct rte_mtr_error *error)
700 {
701 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
702 	struct cnxk_meter_node *mtr;
703 
704 	if (!stats_mask)
705 		return -rte_mtr_error_set(error, EINVAL,
706 					  RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
707 					  "no bit is set to stats mask");
708 
709 	mtr = nix_mtr_find(dev, mtr_id);
710 	if (mtr == NULL) {
711 		return -rte_mtr_error_set(error, ENOENT,
712 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
713 					  "Meter object not found");
714 	}
715 
716 	mtr->params.stats_mask = stats_mask;
717 	return 0;
718 }
719 
720 static int
721 cnxk_nix_mtr_stats_read(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
722 			struct rte_mtr_stats *stats, uint64_t *stats_mask,
723 			int clear, struct rte_mtr_error *error)
724 {
725 	uint8_t yellow_pkt_pass, yellow_octs_pass, yellow_pkt_drop;
726 	uint8_t green_octs_drop, yellow_octs_drop, red_octs_drop;
727 	uint8_t green_pkt_pass, green_octs_pass, green_pkt_drop;
728 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
729 	uint8_t red_pkt_pass, red_octs_pass, red_pkt_drop;
730 	uint64_t bpf_stats[ROC_NIX_BPF_STATS_MAX] = {0};
731 	uint64_t mask = NIX_BPF_STATS_MASK_ALL;
732 	struct roc_nix *nix = &dev->nix;
733 	struct cnxk_meter_node *mtr;
734 	int rc;
735 
736 	if (!stats)
737 		return -rte_mtr_error_set(error, EINVAL,
738 					  RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
739 					  "stats pointer is NULL");
740 
741 	mtr = nix_mtr_find(dev, mtr_id);
742 	if (mtr == NULL) {
743 		return -rte_mtr_error_set(error, ENOENT,
744 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
745 					  "Meter object not found");
746 	}
747 
748 	rc = roc_nix_bpf_stats_read(nix, mtr->bpf_id, mask, lvl_map[mtr->level],
749 				    bpf_stats);
750 	if (rc) {
751 		rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
752 				  NULL, NULL);
753 		goto exit;
754 	}
755 
756 	green_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_PASS);
757 	green_octs_pass =
758 		roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_PASS);
759 	green_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_DROP);
760 	green_octs_drop =
761 		roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_DROP);
762 	yellow_pkt_pass =
763 		roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_PASS);
764 	yellow_octs_pass =
765 		roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_PASS);
766 	yellow_pkt_drop =
767 		roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_DROP);
768 	yellow_octs_drop =
769 		roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_DROP);
770 	red_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_PASS);
771 	red_octs_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_PASS);
772 	red_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_DROP);
773 	red_octs_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_DROP);
774 
775 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_GREEN)
776 		stats->n_pkts[RTE_COLOR_GREEN] = bpf_stats[green_pkt_pass];
777 
778 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_YELLOW)
779 		stats->n_pkts[RTE_COLOR_YELLOW] = bpf_stats[yellow_pkt_pass];
780 
781 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_RED)
782 		stats->n_pkts[RTE_COLOR_RED] = bpf_stats[red_pkt_pass];
783 
784 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_GREEN)
785 		stats->n_bytes[RTE_COLOR_GREEN] = bpf_stats[green_octs_pass];
786 
787 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_YELLOW)
788 		stats->n_bytes[RTE_COLOR_YELLOW] = bpf_stats[yellow_octs_pass];
789 
790 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_RED)
791 		stats->n_bytes[RTE_COLOR_RED] = bpf_stats[red_octs_pass];
792 
793 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED)
794 		stats->n_pkts_dropped = bpf_stats[green_pkt_drop] +
795 					bpf_stats[yellow_pkt_drop] +
796 					bpf_stats[red_pkt_drop];
797 
798 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED)
799 		stats->n_bytes_dropped = bpf_stats[green_octs_drop] +
800 					 bpf_stats[yellow_octs_drop] +
801 					 bpf_stats[red_octs_drop];
802 
803 	if (stats_mask)
804 		*stats_mask = mtr->params.stats_mask;
805 
806 	if (clear) {
807 		rc = roc_nix_bpf_stats_reset(nix, mtr->bpf_id, mask,
808 					     lvl_map[mtr->level]);
809 		if (rc) {
810 			rte_mtr_error_set(error, rc,
811 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
812 					  NULL);
813 			goto exit;
814 		}
815 	}
816 
817 exit:
818 	return rc;
819 }
820 
821 const struct rte_mtr_ops nix_mtr_ops = {
822 	.capabilities_get = cnxk_nix_mtr_capabilities_get,
823 	.meter_profile_add = cnxk_nix_mtr_profile_add,
824 	.meter_profile_delete = cnxk_nix_mtr_profile_delete,
825 	.meter_policy_validate = cnxk_nix_mtr_policy_validate,
826 	.meter_policy_add = cnxk_nix_mtr_policy_add,
827 	.meter_policy_delete = cnxk_nix_mtr_policy_delete,
828 	.create = cnxk_nix_mtr_create,
829 	.destroy = cnxk_nix_mtr_destroy,
830 	.meter_enable = cnxk_nix_mtr_enable,
831 	.meter_disable = cnxk_nix_mtr_disable,
832 	.meter_dscp_table_update = cnxk_nix_mtr_dscp_table_update,
833 	.stats_update = cnxk_nix_mtr_stats_update,
834 	.stats_read = cnxk_nix_mtr_stats_read,
835 };
836 
837 int
838 cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops)
839 {
840 	RTE_SET_USED(dev);
841 
842 	*(const void **)ops = &nix_mtr_ops;
843 	return 0;
844 }
845 
846 int
847 nix_mtr_validate(struct rte_eth_dev *eth_dev, uint32_t id)
848 {
849 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
850 	struct cnxk_mtr_profile_node *profile;
851 	struct cnxk_mtr_policy_node *policy;
852 	struct cnxk_meter_node *mtr;
853 
854 	mtr = nix_mtr_find(dev, id);
855 	if (mtr == NULL)
856 		return -EINVAL;
857 
858 	profile = nix_mtr_profile_find(dev, mtr->params.meter_profile_id);
859 	if (profile == NULL)
860 		return -EINVAL;
861 
862 	policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
863 	if (policy == NULL)
864 		return -EINVAL;
865 
866 	return 0;
867 }
868 
869 int
870 nix_mtr_policy_act_get(struct rte_eth_dev *eth_dev, uint32_t id,
871 		       struct cnxk_mtr_policy_node **policy_act)
872 {
873 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
874 	struct cnxk_mtr_policy_node *policy;
875 	struct cnxk_meter_node *mtr;
876 
877 	mtr = nix_mtr_find(dev, id);
878 	if (mtr == NULL)
879 		return -EINVAL;
880 
881 	policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
882 	if (policy == NULL)
883 		return -EINVAL;
884 
885 	*policy_act = policy;
886 
887 	return 0;
888 }
889 
890 int
891 nix_mtr_rq_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t queue_num,
892 		  const uint16_t *queue)
893 {
894 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
895 	struct cnxk_meter_node *mtr;
896 	uint32_t i;
897 
898 	mtr = nix_mtr_find(dev, id);
899 	if (mtr == NULL)
900 		return -EINVAL;
901 
902 	mtr->rq_id = plt_zmalloc(queue_num * sizeof(uint32_t), ROC_ALIGN);
903 	if (mtr->rq_id == NULL)
904 		return -ENOMEM;
905 
906 	mtr->rq_num = queue_num;
907 	for (i = 0; i < queue_num; i++)
908 		mtr->rq_id[i] = queue[i];
909 
910 	return 0;
911 }
912 
913 int
914 nix_mtr_chain_reset(struct rte_eth_dev *eth_dev, uint32_t cur_id)
915 {
916 	struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
917 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
918 	uint32_t mtr_id = cur_id;
919 	int i = 0, j = 0;
920 
921 	for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
922 		mtr[i] = nix_mtr_find(dev, mtr_id);
923 		if (mtr[i])
924 			mtr_id = mtr[i]->next_id;
925 	}
926 	for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
927 		if (mtr[i]) {
928 			for (j = 0; j < MAX_PRV_MTR_NODES; j++)
929 				mtr[i]->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
930 			mtr[i]->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
931 			mtr[i]->next_id = ROC_NIX_BPF_ID_INVALID;
932 			mtr[i]->is_next = false;
933 			mtr[i]->prev_cnt = 0;
934 		}
935 	}
936 	return 0;
937 }
938 
939 int
940 nix_mtr_chain_update(struct rte_eth_dev *eth_dev, uint32_t cur_id,
941 		     uint32_t prev_id, uint32_t next_id)
942 {
943 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
944 	struct cnxk_meter_node *mtr;
945 
946 	mtr = nix_mtr_find(dev, cur_id);
947 	if (mtr == NULL)
948 		return -EINVAL;
949 
950 	switch (lvl_map[mtr->level]) {
951 	case ROC_NIX_BPF_LEVEL_F_LEAF:
952 		mtr->prev_id[mtr->prev_cnt] = ROC_NIX_BPF_ID_INVALID;
953 		mtr->next_id = next_id;
954 		mtr->is_next = true;
955 		break;
956 	case ROC_NIX_BPF_LEVEL_F_MID:
957 		mtr->prev_id[mtr->prev_cnt] = prev_id;
958 		mtr->next_id = next_id;
959 		mtr->is_next = true;
960 		break;
961 	case ROC_NIX_BPF_LEVEL_F_TOP:
962 		mtr->prev_id[mtr->prev_cnt] = prev_id;
963 		mtr->next_id = ROC_NIX_BPF_ID_INVALID;
964 		mtr->is_next = false;
965 		break;
966 	default:
967 		plt_err("Invalid meter level");
968 		return -EINVAL;
969 	}
970 
971 	return 0;
972 }
973 
974 struct cnxk_meter_node *
975 nix_get_mtr(struct rte_eth_dev *eth_dev, uint32_t id)
976 {
977 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
978 	struct cnxk_meter_node *mtr;
979 
980 	mtr = nix_mtr_find(dev, id);
981 	if (mtr == NULL)
982 		return NULL;
983 
984 	return mtr;
985 }
986 
987 int
988 nix_mtr_level_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t level)
989 {
990 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
991 	struct cnxk_meter_node *mtr;
992 
993 	mtr = nix_mtr_find(dev, id);
994 	if (mtr == NULL)
995 		return -EINVAL;
996 
997 	mtr->level = level;
998 	return 0;
999 }
1000 
1001 static void
1002 nix_mtr_config_map(struct cnxk_meter_node *mtr, struct roc_nix_bpf_cfg *cfg)
1003 {
1004 	enum roc_nix_bpf_algo alg_map[] = {
1005 		ROC_NIX_BPF_ALGO_NONE, ROC_NIX_BPF_ALGO_2697,
1006 		ROC_NIX_BPF_ALGO_2698, ROC_NIX_BPF_ALGO_4115};
1007 	struct cnxk_mtr_profile_node *profile = mtr->profile;
1008 	struct cnxk_mtr_policy_node *policy = mtr->policy;
1009 
1010 	cfg->alg = alg_map[profile->profile.alg];
1011 	cfg->lmode = profile->profile.packet_mode;
1012 
1013 	switch (cfg->alg) {
1014 	case ROC_NIX_BPF_ALGO_2697:
1015 		cfg->algo2697.cir = profile->profile.srtcm_rfc2697.cir * 8;
1016 		cfg->algo2697.cbs = profile->profile.srtcm_rfc2697.cbs;
1017 		cfg->algo2697.ebs = profile->profile.srtcm_rfc2697.ebs;
1018 		break;
1019 	case ROC_NIX_BPF_ALGO_2698:
1020 		cfg->algo2698.cir = profile->profile.trtcm_rfc2698.cir * 8;
1021 		cfg->algo2698.pir = profile->profile.trtcm_rfc2698.pir * 8;
1022 		cfg->algo2698.cbs = profile->profile.trtcm_rfc2698.cbs;
1023 		cfg->algo2698.pbs = profile->profile.trtcm_rfc2698.pbs;
1024 		break;
1025 	case ROC_NIX_BPF_ALGO_4115:
1026 		cfg->algo4115.cir = profile->profile.trtcm_rfc4115.cir * 8;
1027 		cfg->algo4115.eir = profile->profile.trtcm_rfc4115.eir * 8;
1028 		cfg->algo4115.cbs = profile->profile.trtcm_rfc4115.cbs;
1029 		cfg->algo4115.ebs = profile->profile.trtcm_rfc4115.ebs;
1030 		break;
1031 	default:
1032 		break;
1033 	}
1034 
1035 	cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_PASS;
1036 	cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_PASS;
1037 	cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_PASS;
1038 
1039 	if (policy->actions[RTE_COLOR_GREEN].action_fate ==
1040 	    RTE_FLOW_ACTION_TYPE_DROP)
1041 		cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_DROP;
1042 
1043 	if (policy->actions[RTE_COLOR_YELLOW].action_fate ==
1044 	    RTE_FLOW_ACTION_TYPE_DROP)
1045 		cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_DROP;
1046 
1047 	if (policy->actions[RTE_COLOR_RED].action_fate ==
1048 	    RTE_FLOW_ACTION_TYPE_DROP)
1049 		cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_DROP;
1050 }
1051 
1052 static void
1053 nix_dscp_table_map(struct cnxk_meter_node *mtr,
1054 		   struct roc_nix_bpf_precolor *tbl)
1055 {
1056 	enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
1057 					      ROC_NIX_BPF_COLOR_YELLOW,
1058 					      ROC_NIX_BPF_COLOR_RED};
1059 	int i;
1060 
1061 	tbl->count = ROC_NIX_BPF_PRE_COLOR_MAX;
1062 	tbl->mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
1063 
1064 	for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
1065 		tbl->color[i] = ROC_NIX_BPF_COLOR_GREEN;
1066 
1067 	if (mtr->params.dscp_table) {
1068 		for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
1069 			tbl->color[i] = color_map[mtr->params.dscp_table[i]];
1070 	}
1071 }
1072 
1073 int
1074 nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t id,
1075 		struct rte_mtr_error *error)
1076 {
1077 	return cnxk_nix_mtr_destroy(eth_dev, id, error);
1078 }
1079 
1080 int
1081 nix_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t id)
1082 {
1083 	enum roc_nix_bpf_level_flag lvl_flag = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1084 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1085 	struct cnxk_meter_node *base_mtr, *next_mtr;
1086 	struct roc_nix *nix = &dev->nix;
1087 	uint32_t cur_mtr_id = id;
1088 	int rc, i;
1089 
1090 	for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1091 		base_mtr = nix_mtr_find(dev, cur_mtr_id);
1092 		if (base_mtr) {
1093 			lvl_flag = lvl_map[base_mtr->level];
1094 			if (base_mtr->is_next) {
1095 				next_mtr = nix_mtr_find(dev, base_mtr->next_id);
1096 				if (next_mtr) {
1097 					if (!base_mtr->is_used) {
1098 						rc = roc_nix_bpf_connect(nix,
1099 							lvl_flag,
1100 							base_mtr->bpf_id,
1101 							next_mtr->bpf_id);
1102 						if (rc)
1103 							return rc;
1104 					}
1105 				}
1106 				cur_mtr_id = base_mtr->next_id;
1107 			}
1108 		}
1109 	}
1110 	return 0;
1111 }
1112 
1113 int
1114 nix_mtr_configure(struct rte_eth_dev *eth_dev, uint32_t id)
1115 {
1116 	struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1117 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1118 	struct roc_nix_bpf_objs profs[ROC_NIX_BPF_LEVEL_MAX];
1119 	uint8_t idx0 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1120 	uint8_t idx1 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1121 	uint8_t idx2 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1122 	uint16_t per_lvl_cnt[ROC_NIX_BPF_LEVEL_MAX];
1123 	int num_mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1124 	struct roc_nix *nix = &dev->nix;
1125 	struct roc_nix_bpf_precolor tbl;
1126 	struct roc_nix_bpf_cfg cfg;
1127 	struct roc_nix_rq *rq;
1128 	uint8_t lvl_mask;
1129 	uint32_t i;
1130 	uint32_t j;
1131 	int rc;
1132 
1133 	mtr[0] = nix_mtr_find(dev, id);
1134 	if (mtr[0] == NULL)
1135 		return -EINVAL;
1136 
1137 	num_mtr[0] = 1;
1138 	idx0 = roc_nix_bpf_level_to_idx(lvl_map[mtr[0]->level]);
1139 	if (idx0 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1140 		return -EINVAL;
1141 
1142 	lvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF;
1143 	if (mtr[0]->is_used)
1144 		per_lvl_cnt[idx0] = 0;
1145 	else
1146 		per_lvl_cnt[idx0] = 1;
1147 
1148 	if (mtr[0]->is_next) {
1149 		mtr[1] = nix_mtr_find(dev, mtr[0]->next_id);
1150 		if (mtr[1] == NULL)
1151 			return -EINVAL;
1152 		num_mtr[1] = 1;
1153 		idx1 = roc_nix_bpf_level_to_idx(lvl_map[mtr[1]->level]);
1154 		if (idx1 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1155 			return -EINVAL;
1156 
1157 		lvl_mask |= ROC_NIX_BPF_LEVEL_F_MID;
1158 		if (mtr[1]->is_used)
1159 			per_lvl_cnt[idx1] = 0;
1160 		else
1161 			per_lvl_cnt[idx1] = 1;
1162 	}
1163 
1164 	if (mtr[1] && mtr[1]->is_next) {
1165 		mtr[2] = nix_mtr_find(dev, mtr[1]->next_id);
1166 		if (mtr[2] == NULL)
1167 			return -EINVAL;
1168 
1169 		num_mtr[2] = 1;
1170 		idx2 = roc_nix_bpf_level_to_idx(lvl_map[mtr[2]->level]);
1171 		if (idx2 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1172 			return -EINVAL;
1173 
1174 		lvl_mask |= ROC_NIX_BPF_LEVEL_F_TOP;
1175 		if (mtr[2]->is_used)
1176 			per_lvl_cnt[idx2] = 0;
1177 		else
1178 			per_lvl_cnt[idx2] = 1;
1179 	}
1180 
1181 	rc = roc_nix_bpf_alloc(nix, lvl_mask, per_lvl_cnt, profs);
1182 	if (rc)
1183 		return rc;
1184 	if (mtr[0]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1185 		mtr[0]->bpf_id = profs[idx0].ids[0];
1186 
1187 	if (num_mtr[0])
1188 		if (mtr[0]->is_next && idx1 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1189 			if (mtr[1]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1190 				mtr[1]->bpf_id = profs[idx1].ids[0];
1191 
1192 	if (num_mtr[1])
1193 		if (mtr[1]->is_next && idx2 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1194 			if (mtr[2]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1195 				mtr[2]->bpf_id = profs[idx2].ids[0];
1196 
1197 	for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1198 		if (num_mtr[i]) {
1199 			if (!mtr[i]->is_used) {
1200 				memset(&cfg, 0, sizeof(struct roc_nix_bpf_cfg));
1201 				nix_mtr_config_map(mtr[i], &cfg);
1202 				rc = roc_nix_bpf_config(nix, mtr[i]->bpf_id,
1203 							lvl_map[mtr[i]->level],
1204 							&cfg);
1205 
1206 				memset(&tbl, 0,
1207 				       sizeof(struct roc_nix_bpf_precolor));
1208 				nix_dscp_table_map(mtr[i], &tbl);
1209 				rc = roc_nix_bpf_pre_color_tbl_setup(nix,
1210 					mtr[i]->bpf_id, lvl_map[mtr[i]->level],
1211 					&tbl);
1212 
1213 				if (mtr[i]->params.meter_enable) {
1214 					for (j = 0; j < mtr[i]->rq_num; j++) {
1215 						rq = &dev->rqs[mtr[i]->rq_id
1216 								       [j]];
1217 						rc = roc_nix_bpf_ena_dis(nix,
1218 							mtr[i]->bpf_id, rq,
1219 							true);
1220 					}
1221 				}
1222 			}
1223 		}
1224 	}
1225 
1226 	return rc;
1227 }
1228 
1229 int
1230 nix_mtr_color_action_validate(struct rte_eth_dev *eth_dev, uint32_t id,
1231 			      uint32_t *prev_id, uint32_t *next_id,
1232 			      struct cnxk_mtr_policy_node *policy,
1233 			      int *tree_level)
1234 {
1235 	uint32_t action_fate_red = policy->actions[RTE_COLOR_RED].action_fate;
1236 	uint32_t action_fate_green =
1237 		policy->actions[RTE_COLOR_GREEN].action_fate;
1238 	uint32_t action_fate_yellow =
1239 		policy->actions[RTE_COLOR_YELLOW].action_fate;
1240 	uint32_t cur_mtr_id = *next_id;
1241 	uint32_t next_mtr_id = 0xffff;
1242 	uint32_t prev_mtr_id = 0xffff;
1243 	struct cnxk_meter_node *mtr;
1244 
1245 	if (action_fate_green == RTE_FLOW_ACTION_TYPE_METER)
1246 		next_mtr_id = policy->actions[RTE_COLOR_GREEN].mtr_id;
1247 
1248 	if (action_fate_yellow == RTE_FLOW_ACTION_TYPE_METER)
1249 		next_mtr_id = policy->actions[RTE_COLOR_YELLOW].mtr_id;
1250 
1251 	if (action_fate_red == RTE_FLOW_ACTION_TYPE_METER)
1252 		next_mtr_id = policy->actions[RTE_COLOR_RED].mtr_id;
1253 
1254 	if (next_mtr_id != 0xffff) {
1255 		switch (*tree_level) {
1256 		case 0:
1257 			mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1258 			if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1259 				nix_mtr_level_update(eth_dev, cur_mtr_id, 0);
1260 				nix_mtr_chain_update(eth_dev, cur_mtr_id, -1,
1261 						     next_mtr_id);
1262 			} else {
1263 				if (mtr->level == 0)
1264 					mtr->is_used = true;
1265 				else
1266 					return -EINVAL;
1267 			}
1268 			(*tree_level)++;
1269 			*next_id = next_mtr_id;
1270 			break;
1271 		case 1:
1272 			mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1273 			if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1274 				nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1275 				prev_mtr_id = id;
1276 				nix_mtr_chain_update(eth_dev, cur_mtr_id,
1277 						     prev_mtr_id, next_mtr_id);
1278 			} else {
1279 				if (mtr->level == 1) {
1280 					mtr->prev_cnt++;
1281 					prev_mtr_id = id;
1282 					nix_mtr_chain_update(eth_dev,
1283 						cur_mtr_id, prev_mtr_id,
1284 						next_mtr_id);
1285 
1286 					mtr->is_used = true;
1287 				} else {
1288 					return -EINVAL;
1289 				}
1290 			}
1291 			(*tree_level)++;
1292 			*next_id = next_mtr_id;
1293 			*prev_id = cur_mtr_id;
1294 			break;
1295 		case 2:
1296 			nix_mtr_chain_reset(eth_dev, id);
1297 			return -EINVAL;
1298 		}
1299 	} else {
1300 		switch (*tree_level) {
1301 		case 0:
1302 			mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1303 			if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1304 				nix_mtr_level_update(eth_dev, cur_mtr_id, 0);
1305 			} else {
1306 				if (mtr->level == 0)
1307 					mtr->is_used = true;
1308 				else
1309 					return -EINVAL;
1310 			}
1311 			break;
1312 		case 1:
1313 			mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1314 			if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1315 				nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1316 				prev_mtr_id = id;
1317 				nix_mtr_chain_update(eth_dev, cur_mtr_id,
1318 						     prev_mtr_id, -1);
1319 			} else {
1320 				if (mtr->level == 1) {
1321 					mtr->prev_cnt++;
1322 					prev_mtr_id = id;
1323 					nix_mtr_chain_update(eth_dev,
1324 							     cur_mtr_id,
1325 							     prev_mtr_id, -1);
1326 					mtr->is_used = true;
1327 				} else {
1328 					return -EINVAL;
1329 				}
1330 			}
1331 			break;
1332 		case 2:
1333 			mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1334 			if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1335 				nix_mtr_level_update(eth_dev, cur_mtr_id, 2);
1336 				prev_mtr_id = *prev_id;
1337 				nix_mtr_chain_update(eth_dev, cur_mtr_id,
1338 						     prev_mtr_id, -1);
1339 			} else {
1340 				if (mtr->level == 2) {
1341 					mtr->prev_cnt++;
1342 					prev_mtr_id = *prev_id;
1343 					nix_mtr_chain_update(eth_dev,
1344 							     cur_mtr_id,
1345 							     prev_mtr_id, -1);
1346 					mtr->is_used = true;
1347 				} else {
1348 					return -EINVAL;
1349 				}
1350 			}
1351 			break;
1352 		}
1353 		*next_id = 0xffff;
1354 	}
1355 
1356 	return 0;
1357 }
1358 
1359 int
1360 nix_mtr_capabilities_init(struct rte_eth_dev *eth_dev)
1361 {
1362 	struct rte_mtr_capabilities capa;
1363 	struct rte_mtr_error error;
1364 
1365 	return cnxk_nix_mtr_capabilities_get(eth_dev, &capa, &error);
1366 }
1367