xref: /dpdk/drivers/net/cnxk/cnxk_ethdev_mtr.c (revision baa9d96037b98e6c11612367ac449045f11ac1d9)
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_PER_FLOW 3  /* 1(leaf) + 1(mid) + 1(top) */
9 
10 #define NIX_BPF_STATS_MASK_ALL                                                 \
11 	{                                                                      \
12 		ROC_NIX_BPF_GREEN_PKT_F_PASS | ROC_NIX_BPF_GREEN_OCTS_F_PASS | \
13 			ROC_NIX_BPF_GREEN_PKT_F_DROP |                         \
14 			ROC_NIX_BPF_GREEN_OCTS_F_DROP |                        \
15 			ROC_NIX_BPF_YELLOW_PKT_F_PASS |                        \
16 			ROC_NIX_BPF_YELLOW_OCTS_F_PASS |                       \
17 			ROC_NIX_BPF_YELLOW_PKT_F_DROP |                        \
18 			ROC_NIX_BPF_YELLOW_OCTS_F_DROP |                       \
19 			ROC_NIX_BPF_RED_PKT_F_PASS |                           \
20 			ROC_NIX_BPF_RED_OCTS_F_PASS |                          \
21 			ROC_NIX_BPF_RED_PKT_F_DROP |                           \
22 			ROC_NIX_BPF_RED_OCTS_F_DROP                            \
23 	}
24 
25 static const enum roc_nix_bpf_level_flag lvl_map[] = {ROC_NIX_BPF_LEVEL_F_LEAF,
26 						      ROC_NIX_BPF_LEVEL_F_MID,
27 						      ROC_NIX_BPF_LEVEL_F_TOP};
28 
29 static struct rte_mtr_capabilities mtr_capa = {
30 	.n_shared_max = NIX_MTR_COUNT_PER_FLOW,
31 	/* .identical = , */
32 	.shared_identical = true,
33 	/* .shared_n_flows_per_mtr_max = ,*/
34 	.chaining_n_mtrs_per_flow_max = NIX_MTR_COUNT_PER_FLOW,
35 	.chaining_use_prev_mtr_color_supported = true,
36 	.chaining_use_prev_mtr_color_enforced = true,
37 	.color_aware_srtcm_rfc2697_supported = true,
38 	.color_aware_trtcm_rfc2698_supported = true,
39 	.color_aware_trtcm_rfc4115_supported = true,
40 	.srtcm_rfc2697_byte_mode_supported = true,
41 	.srtcm_rfc2697_packet_mode_supported = true,
42 	.trtcm_rfc2698_byte_mode_supported = true,
43 	.trtcm_rfc2698_packet_mode_supported = true,
44 	.trtcm_rfc4115_byte_mode_supported = true,
45 	.trtcm_rfc4115_packet_mode_supported = true,
46 	.stats_mask = RTE_MTR_STATS_N_PKTS_GREEN | RTE_MTR_STATS_N_PKTS_YELLOW |
47 		      RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_PKTS_DROPPED |
48 		      RTE_MTR_STATS_N_BYTES_GREEN |
49 		      RTE_MTR_STATS_N_BYTES_YELLOW | RTE_MTR_STATS_N_BYTES_RED |
50 		      RTE_MTR_STATS_N_BYTES_DROPPED,
51 	.input_color_proto_mask = RTE_MTR_COLOR_IN_PROTO_OUTER_VLAN |
52 			RTE_MTR_COLOR_IN_PROTO_INNER_VLAN |
53 			RTE_MTR_COLOR_IN_PROTO_OUTER_IP |
54 			RTE_MTR_COLOR_IN_PROTO_INNER_IP,
55 	.separate_input_color_table_per_port = true};
56 
57 static struct cnxk_meter_node *
nix_mtr_find(struct cnxk_eth_dev * dev,uint32_t meter_id)58 nix_mtr_find(struct cnxk_eth_dev *dev, uint32_t meter_id)
59 {
60 	struct cnxk_mtr *fms = &dev->mtr;
61 	struct cnxk_meter_node *fm;
62 
63 	TAILQ_FOREACH(fm, fms, next)
64 		if (meter_id == fm->id)
65 			return fm;
66 	return NULL;
67 }
68 
69 static struct cnxk_mtr_profile_node *
nix_mtr_profile_find(struct cnxk_eth_dev * dev,uint32_t profile_id)70 nix_mtr_profile_find(struct cnxk_eth_dev *dev, uint32_t profile_id)
71 {
72 	struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
73 	struct cnxk_mtr_profile_node *fmp;
74 
75 	TAILQ_FOREACH(fmp, fmps, next)
76 		if (profile_id == fmp->id)
77 			return fmp;
78 
79 	return NULL;
80 }
81 
82 static struct cnxk_mtr_policy_node *
nix_mtr_policy_find(struct cnxk_eth_dev * dev,uint32_t meter_policy_id)83 nix_mtr_policy_find(struct cnxk_eth_dev *dev, uint32_t meter_policy_id)
84 {
85 	struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
86 	struct cnxk_mtr_policy_node *fmp;
87 
88 	TAILQ_FOREACH(fmp, fmps, next)
89 		if (meter_policy_id == fmp->id)
90 			return fmp;
91 	return NULL;
92 }
93 
94 static int
nix_mtr_profile_validate(struct cnxk_eth_dev * dev,uint32_t profile_id,struct rte_mtr_meter_profile * profile,struct rte_mtr_error * error)95 nix_mtr_profile_validate(struct cnxk_eth_dev *dev, uint32_t profile_id,
96 			 struct rte_mtr_meter_profile *profile,
97 			 struct rte_mtr_error *error)
98 {
99 	int rc = 0;
100 
101 	PLT_SET_USED(dev);
102 
103 	if (profile == NULL)
104 		return -rte_mtr_error_set(error, EINVAL,
105 					  RTE_MTR_ERROR_TYPE_METER_PROFILE,
106 					  NULL, "Meter profile is null.");
107 
108 	if (profile_id == UINT32_MAX)
109 		return -rte_mtr_error_set(error, EINVAL,
110 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
111 					  NULL, "Meter profile id not valid.");
112 
113 	switch (profile->alg) {
114 	case RTE_MTR_SRTCM_RFC2697:
115 		if (profile->srtcm_rfc2697.cir > mtr_capa.meter_rate_max)
116 			rc = -rte_mtr_error_set(error, EINVAL,
117 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
118 				"CIR exceeds max meter rate");
119 
120 		if (profile->srtcm_rfc2697.cbs > NIX_BPF_BURST_MAX)
121 			rc = -rte_mtr_error_set(error, EINVAL,
122 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
123 				"CBS exceeds max meter burst size");
124 
125 		if (profile->srtcm_rfc2697.ebs > NIX_BPF_BURST_MAX)
126 			rc = -rte_mtr_error_set(error, EINVAL,
127 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
128 				"EBS exceeds max meter burst size");
129 		break;
130 
131 	case RTE_MTR_TRTCM_RFC2698:
132 		if (profile->trtcm_rfc2698.cir > mtr_capa.meter_rate_max)
133 			rc = -rte_mtr_error_set(error, EINVAL,
134 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
135 				"CIR exceeds max meter rate");
136 
137 		if (profile->trtcm_rfc2698.pir > mtr_capa.meter_rate_max)
138 			rc = -rte_mtr_error_set(error, EINVAL,
139 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
140 				"PIR exceeds max meter rate");
141 
142 		if (profile->trtcm_rfc2698.cbs > NIX_BPF_BURST_MAX)
143 			rc = -rte_mtr_error_set(error, EINVAL,
144 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
145 				"CBS exceeds max meter burst size");
146 
147 		if (profile->trtcm_rfc2698.pbs > NIX_BPF_BURST_MAX)
148 			rc = -rte_mtr_error_set(error, EINVAL,
149 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
150 				"PBS exceeds max meter burst size");
151 		break;
152 
153 	case RTE_MTR_TRTCM_RFC4115:
154 		if ((profile->trtcm_rfc4115.cir + profile->trtcm_rfc4115.eir) >
155 		    mtr_capa.meter_rate_max)
156 			rc = -rte_mtr_error_set(error, EINVAL,
157 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
158 				"PIR + EIR exceeds max rate");
159 
160 		if (profile->trtcm_rfc4115.cbs > NIX_BPF_BURST_MAX)
161 			rc = -rte_mtr_error_set(error, EINVAL,
162 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
163 				"CBS exceeds max meter burst size");
164 
165 		if (profile->trtcm_rfc4115.ebs > NIX_BPF_BURST_MAX)
166 			rc = -rte_mtr_error_set(error, EINVAL,
167 				RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
168 				"PBS exceeds max meter burst size");
169 		break;
170 
171 	default:
172 		rc = -rte_mtr_error_set(error, EINVAL,
173 					RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
174 					"alg is invalid");
175 		break;
176 	}
177 
178 	return rc;
179 }
180 
181 static int
cnxk_nix_mtr_capabilities_get(struct rte_eth_dev * dev,struct rte_mtr_capabilities * capa,struct rte_mtr_error * error)182 cnxk_nix_mtr_capabilities_get(struct rte_eth_dev *dev,
183 			      struct rte_mtr_capabilities *capa,
184 			      struct rte_mtr_error *error)
185 {
186 	uint8_t lvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF | ROC_NIX_BPF_LEVEL_F_MID |
187 			   ROC_NIX_BPF_LEVEL_F_TOP;
188 	struct cnxk_eth_dev *eth_dev = cnxk_eth_pmd_priv(dev);
189 	uint16_t count[ROC_NIX_BPF_LEVEL_MAX] = {0};
190 	struct roc_nix *nix = &eth_dev->nix;
191 	uint32_t time_unit;
192 	int rc, i;
193 
194 	RTE_SET_USED(dev);
195 
196 	if (!capa)
197 		return -rte_mtr_error_set(error, EINVAL,
198 				RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
199 				"NULL input parameter");
200 
201 	rc = roc_nix_bpf_count_get(nix, lvl_mask, count);
202 	if (rc)
203 		return rc;
204 
205 	for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++)
206 		mtr_capa.n_max += count[i];
207 
208 	mtr_capa.meter_srtcm_rfc2697_n_max = mtr_capa.n_max;
209 	mtr_capa.meter_trtcm_rfc2698_n_max = mtr_capa.n_max;
210 	mtr_capa.meter_trtcm_rfc4115_n_max = mtr_capa.n_max;
211 	mtr_capa.meter_policy_n_max = mtr_capa.n_max;
212 
213 	rc = roc_nix_bpf_timeunit_get(nix, &time_unit);
214 	if (rc)
215 		return rc;
216 
217 	mtr_capa.meter_rate_max =
218 		NIX_BPF_RATE(time_unit, NIX_BPF_MAX_RATE_EXPONENT,
219 			     NIX_BPF_MAX_RATE_MANTISSA, 0) /
220 		8;
221 
222 	*capa = mtr_capa;
223 	return 0;
224 }
225 
226 static int
cnxk_nix_mtr_profile_add(struct rte_eth_dev * eth_dev,uint32_t profile_id,struct rte_mtr_meter_profile * profile,struct rte_mtr_error * error)227 cnxk_nix_mtr_profile_add(struct rte_eth_dev *eth_dev, uint32_t profile_id,
228 			 struct rte_mtr_meter_profile *profile,
229 			 struct rte_mtr_error *error)
230 {
231 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
232 	struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
233 	struct cnxk_mtr_profile_node *fmp;
234 	int ret;
235 
236 	/* Check input params. */
237 	ret = nix_mtr_profile_validate(dev, profile_id, profile, error);
238 	if (ret)
239 		return ret;
240 
241 	fmp = nix_mtr_profile_find(dev, profile_id);
242 	if (fmp) {
243 		return -rte_mtr_error_set(error, EEXIST,
244 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
245 					  NULL, "Profile already exist");
246 	}
247 
248 	fmp = plt_zmalloc(sizeof(struct cnxk_mtr_profile_node), ROC_ALIGN);
249 	if (fmp == NULL)
250 		return -rte_mtr_error_set(error, ENOMEM,
251 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
252 					  "Meter profile memory "
253 					  "alloc failed.");
254 
255 	fmp->id = profile_id;
256 	fmp->profile = *profile;
257 
258 	TAILQ_INSERT_TAIL(fmps, fmp, next);
259 
260 	return 0;
261 }
262 
263 static int
cnxk_nix_mtr_profile_delete(struct rte_eth_dev * eth_dev,uint32_t profile_id,struct rte_mtr_error * error)264 cnxk_nix_mtr_profile_delete(struct rte_eth_dev *eth_dev, uint32_t profile_id,
265 			    struct rte_mtr_error *error)
266 {
267 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
268 	struct cnxk_mtr_profile_node *fmp;
269 
270 	if (profile_id == UINT32_MAX)
271 		return -rte_mtr_error_set(error, EINVAL,
272 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
273 					  NULL, "Meter profile id not valid.");
274 
275 	fmp = nix_mtr_profile_find(dev, profile_id);
276 	if (fmp == NULL)
277 		return -rte_mtr_error_set(error, ENOENT,
278 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
279 					  &profile_id,
280 					  "Meter profile is invalid.");
281 
282 	if (fmp->ref_cnt)
283 		return -rte_mtr_error_set(error, EBUSY,
284 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
285 					  NULL, "Meter profile is in use.");
286 
287 	TAILQ_REMOVE(&dev->mtr_profiles, fmp, next);
288 	plt_free(fmp);
289 	return 0;
290 }
291 
292 static int
update_mtr_err(uint32_t act_color,struct rte_mtr_error * error,bool action)293 update_mtr_err(uint32_t act_color, struct rte_mtr_error *error, bool action)
294 {
295 	const char *str = NULL;
296 	switch (act_color) {
297 	case RTE_COLOR_GREEN:
298 		if (action) {
299 			str = "Green action is not valid";
300 			goto notsup;
301 		} else {
302 			str = "Green action is null";
303 			goto notvalid;
304 		}
305 		break;
306 	case RTE_COLOR_YELLOW:
307 		if (action) {
308 			str = "Yellow action is not valid";
309 			goto notsup;
310 		} else {
311 			str = "Yellow action is null";
312 			goto notvalid;
313 		}
314 		break;
315 	case RTE_COLOR_RED:
316 		if (action) {
317 			str = "Red action is not valid";
318 			goto notsup;
319 		} else {
320 			str = "Red action is null";
321 			goto notvalid;
322 		}
323 		break;
324 	}
325 notsup:
326 	return -rte_mtr_error_set(error, ENOTSUP,
327 				  RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, str);
328 notvalid:
329 	return -rte_mtr_error_set(error, EINVAL,
330 				  RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, str);
331 }
332 
333 static int
cnxk_nix_mtr_policy_validate(struct rte_eth_dev * dev,struct rte_mtr_meter_policy_params * policy,struct rte_mtr_error * error)334 cnxk_nix_mtr_policy_validate(struct rte_eth_dev *dev,
335 			     struct rte_mtr_meter_policy_params *policy,
336 			     struct rte_mtr_error *error)
337 {
338 	bool supported[RTE_COLORS] = {false, false, false};
339 	const struct rte_flow_action *action;
340 	uint32_t i;
341 
342 	RTE_SET_USED(dev);
343 
344 	if (!policy)
345 		return 0; /* Nothing to be validated */
346 
347 	for (i = 0; i < RTE_COLORS; i++) {
348 		if (policy->actions[i]) {
349 			for (action = policy->actions[i];
350 			     action->type != RTE_FLOW_ACTION_TYPE_END;
351 			     action++) {
352 				if (action->type == RTE_FLOW_ACTION_TYPE_METER)
353 					supported[i] = true;
354 
355 				if (action->type == RTE_FLOW_ACTION_TYPE_DROP)
356 					supported[i] = true;
357 
358 				if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
359 					supported[i] = true;
360 
361 				if (action->type == RTE_FLOW_ACTION_TYPE_SKIP_CMAN)
362 					supported[i] = true;
363 
364 				if (!supported[i])
365 					return update_mtr_err(i, error, true);
366 			}
367 		} else {
368 			return update_mtr_err(i, error, false);
369 		}
370 	}
371 
372 	return 0;
373 }
374 
375 static void
cnxk_fill_policy_actions(struct cnxk_mtr_policy_node * fmp,struct rte_mtr_meter_policy_params * policy)376 cnxk_fill_policy_actions(struct cnxk_mtr_policy_node *fmp,
377 			 struct rte_mtr_meter_policy_params *policy)
378 
379 {
380 	const struct rte_flow_action_meter *mtr;
381 	const struct rte_flow_action *action;
382 	int i;
383 
384 	for (i = 0; i < RTE_COLORS; i++) {
385 		if (policy->actions[i]) {
386 			for (action = policy->actions[i];
387 			     action->type != RTE_FLOW_ACTION_TYPE_END;
388 			     action++) {
389 				if (action->type ==
390 				    RTE_FLOW_ACTION_TYPE_METER) {
391 					fmp->actions[i].action_fate =
392 						action->type;
393 					mtr = (const struct
394 					       rte_flow_action_meter *)
395 						      action->conf;
396 					fmp->actions[i].mtr_id = mtr->mtr_id;
397 				}
398 
399 				if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
400 					fmp->actions[i].action_fate =
401 						action->type;
402 				}
403 
404 				if (action->type ==
405 					RTE_FLOW_ACTION_TYPE_SKIP_CMAN)
406 					fmp->actions[i].skip_red = true;
407 			}
408 		}
409 	}
410 }
411 
412 static int
cnxk_nix_mtr_policy_add(struct rte_eth_dev * eth_dev,uint32_t policy_id,struct rte_mtr_meter_policy_params * policy,struct rte_mtr_error * error)413 cnxk_nix_mtr_policy_add(struct rte_eth_dev *eth_dev, uint32_t policy_id,
414 			struct rte_mtr_meter_policy_params *policy,
415 			struct rte_mtr_error *error)
416 {
417 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
418 	struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
419 	struct cnxk_mtr_policy_node *fmp;
420 	int rc;
421 
422 	fmp = nix_mtr_policy_find(dev, policy_id);
423 	if (fmp) {
424 		return -rte_mtr_error_set(error, EEXIST,
425 					  RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
426 					  NULL, "Policy already exist");
427 	}
428 
429 	fmp = plt_zmalloc(sizeof(struct cnxk_mtr_policy_node), ROC_ALIGN);
430 	if (fmp == NULL) {
431 		return -rte_mtr_error_set(error, ENOMEM,
432 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
433 					  "Memory allocation failure");
434 	} else {
435 		rc = cnxk_nix_mtr_policy_validate(eth_dev, policy, error);
436 		if (rc)
437 			goto exit;
438 	}
439 
440 	fmp->id = policy_id;
441 	cnxk_fill_policy_actions(fmp, policy);
442 	TAILQ_INSERT_TAIL(fmps, fmp, next);
443 	return 0;
444 
445 exit:
446 	plt_free(fmp);
447 	return rc;
448 }
449 
450 static int
cnxk_nix_mtr_policy_delete(struct rte_eth_dev * eth_dev,uint32_t policy_id,struct rte_mtr_error * error)451 cnxk_nix_mtr_policy_delete(struct rte_eth_dev *eth_dev, uint32_t policy_id,
452 			   struct rte_mtr_error *error)
453 {
454 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
455 	struct cnxk_mtr_policy_node *fmp;
456 
457 	fmp = nix_mtr_policy_find(dev, policy_id);
458 	if (fmp == NULL) {
459 		return -rte_mtr_error_set(error, ENOENT,
460 					  RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
461 					  NULL, "No policy found");
462 	}
463 
464 	if (fmp->ref_cnt)
465 		return -rte_mtr_error_set(error, EBUSY,
466 					  RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
467 					  NULL, "Meter policy is in use.");
468 
469 	TAILQ_REMOVE(&dev->mtr_policy, fmp, next);
470 	plt_free(fmp);
471 
472 	return 0;
473 }
474 
475 static int
cnxk_nix_mtr_create(struct rte_eth_dev * eth_dev,uint32_t mtr_id,struct rte_mtr_params * params,int shared,struct rte_mtr_error * error)476 cnxk_nix_mtr_create(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
477 		    struct rte_mtr_params *params, int shared,
478 		    struct rte_mtr_error *error)
479 {
480 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
481 	struct cnxk_mtr_profile_node *profile;
482 	struct cnxk_mtr_policy_node *policy;
483 	struct cnxk_mtr *fm = &dev->mtr;
484 	enum rte_color *table = NULL;
485 	struct cnxk_meter_node *mtr;
486 	int i;
487 
488 	RTE_SET_USED(shared);
489 
490 	if (params == NULL)
491 		return -rte_mtr_error_set(error, ENOENT,
492 					  RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
493 					  "Meter params are invalid.");
494 
495 	profile = nix_mtr_profile_find(dev, params->meter_profile_id);
496 	if (profile == NULL)
497 		return -rte_mtr_error_set(error, ENOENT,
498 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
499 					  &params->meter_profile_id,
500 					  "Meter profile is invalid.");
501 
502 	policy = nix_mtr_policy_find(dev, params->meter_policy_id);
503 	if (policy == NULL)
504 		return -rte_mtr_error_set(error, ENOENT,
505 					  RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
506 					  &params->meter_policy_id,
507 					  "Meter policy is invalid.");
508 
509 	mtr = nix_mtr_find(dev, mtr_id);
510 	if (mtr) {
511 		return -rte_mtr_error_set(error, EEXIST,
512 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
513 					  "Meter already exist");
514 	}
515 
516 	mtr = plt_zmalloc(sizeof(struct cnxk_meter_node), ROC_ALIGN);
517 	if (mtr == NULL) {
518 		return -rte_mtr_error_set(error, ENOMEM,
519 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
520 					  "Meter memory alloc failed.");
521 	}
522 
523 	mtr->id = mtr_id;
524 	mtr->profile = profile;
525 	mtr->policy = policy;
526 	mtr->params = *params;
527 	mtr->bpf_id = ROC_NIX_BPF_ID_INVALID;
528 	mtr->prev_cnt = 0;
529 	for (i = 0; i < MAX_PRV_MTR_NODES; i++)
530 		mtr->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
531 
532 	mtr->next_id = ROC_NIX_BPF_ID_INVALID;
533 	mtr->is_next = false;
534 	mtr->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
535 
536 	/* populate dscp table for input coloring */
537 	if (params->dscp_table) {
538 		table = (enum rte_color *)plt_zmalloc(sizeof(enum rte_color) *
539 			ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP, ROC_ALIGN);
540 		if (table == NULL) {
541 			plt_free(mtr);
542 			return -rte_mtr_error_set(error, ENOMEM,
543 					RTE_MTR_ERROR_TYPE_UNSPECIFIED,
544 					NULL, "Memory alloc failed.");
545 		}
546 
547 		for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
548 			table[i] = params->dscp_table[i];
549 
550 		mtr->params.dscp_table = table;
551 	}
552 
553 
554 	/* populate vlan table for input coloring */
555 	if (params->vlan_table) {
556 		table = (enum rte_color *)plt_zmalloc(sizeof(enum rte_color) *
557 			ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN, ROC_ALIGN);
558 		if (table == NULL) {
559 			plt_free(mtr->params.dscp_table);
560 			plt_free(mtr);
561 			return -rte_mtr_error_set(error, ENOMEM,
562 					RTE_MTR_ERROR_TYPE_UNSPECIFIED,
563 					NULL, "Memory alloc failed.");
564 		}
565 
566 		for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
567 			table[i] = params->vlan_table[i];
568 
569 		mtr->params.vlan_table = table;
570 	}
571 
572 	profile->ref_cnt++;
573 	policy->ref_cnt++;
574 	TAILQ_INSERT_TAIL(fm, mtr, next);
575 	return 0;
576 }
577 
578 static int
cnxk_nix_mtr_destroy(struct rte_eth_dev * eth_dev,uint32_t mtr_id,struct rte_mtr_error * error)579 cnxk_nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
580 		     struct rte_mtr_error *error)
581 {
582 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
583 	struct roc_nix_bpf_objs profs = {0};
584 	struct cnxk_mtr *fm = &dev->mtr;
585 	struct roc_nix *nix = &dev->nix;
586 	struct cnxk_meter_node *mtr;
587 	struct cnxk_meter_node *mid_mtr;
588 	struct cnxk_meter_node *top_mtr;
589 	int rc = 0;
590 
591 	mtr = nix_mtr_find(dev, mtr_id);
592 	if (mtr == NULL) {
593 		return -rte_mtr_error_set(error, ENOENT,
594 					  RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
595 					  "Meter id is invalid.");
596 	}
597 
598 	if (mtr->ref_cnt) {
599 		return -rte_mtr_error_set(error, EADDRINUSE,
600 					  RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
601 					  "Meter id in use.");
602 	}
603 
604 	switch (lvl_map[mtr->level]) {
605 	case ROC_NIX_BPF_LEVEL_F_LEAF:
606 		if (mtr->is_next) {
607 			rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
608 						 mtr->bpf_id,
609 						 ROC_NIX_BPF_ID_INVALID);
610 		}
611 		break;
612 	case ROC_NIX_BPF_LEVEL_F_MID:
613 		while ((mtr->prev_cnt) + 1) {
614 			mid_mtr =
615 				nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
616 			if (mid_mtr == NULL) {
617 				return -rte_mtr_error_set(error, ENOENT,
618 					  RTE_MTR_ERROR_TYPE_MTR_ID, &mtr->prev_id[mtr->prev_cnt],
619 					  "Mid meter id is invalid.");
620 			}
621 			rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
622 						 mid_mtr->bpf_id,
623 						 ROC_NIX_BPF_ID_INVALID);
624 			mtr->prev_cnt--;
625 		}
626 		if (mtr->is_next) {
627 			rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
628 						 mtr->bpf_id,
629 						 ROC_NIX_BPF_ID_INVALID);
630 		}
631 		break;
632 	case ROC_NIX_BPF_LEVEL_F_TOP:
633 		while (mtr->prev_cnt) {
634 			top_mtr =
635 				nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
636 			if (top_mtr == NULL) {
637 				return -rte_mtr_error_set(error, ENOENT,
638 					  RTE_MTR_ERROR_TYPE_MTR_ID, &mtr->prev_id[mtr->prev_cnt],
639 					  "Top meter id is invalid.");
640 			}
641 			rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
642 						 top_mtr->bpf_id,
643 						 ROC_NIX_BPF_ID_INVALID);
644 			mtr->prev_cnt--;
645 		}
646 		break;
647 	default:
648 		return -rte_mtr_error_set(error, EINVAL,
649 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
650 					  "Invalid meter level");
651 	}
652 
653 	if (rc)
654 		goto exit;
655 
656 	profs.level = mtr->level;
657 	profs.count = 1;
658 	profs.ids[0] = mtr->bpf_id;
659 	rc = roc_nix_bpf_free(nix, &profs, 1);
660 	if (rc)
661 		goto exit;
662 
663 	mtr->policy->ref_cnt--;
664 	mtr->profile->ref_cnt--;
665 	TAILQ_REMOVE(fm, mtr, next);
666 
667 	if (mtr->params.dscp_table)
668 		plt_free(mtr->params.dscp_table);
669 
670 	if (mtr->params.vlan_table)
671 		plt_free(mtr->params.vlan_table);
672 
673 	plt_free(mtr);
674 
675 exit:
676 	return rc;
677 }
678 
679 static int
cnxk_nix_mtr_enable(struct rte_eth_dev * eth_dev,uint32_t mtr_id,struct rte_mtr_error * error)680 cnxk_nix_mtr_enable(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
681 		    struct rte_mtr_error *error)
682 {
683 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
684 	struct roc_nix *nix = &dev->nix;
685 	struct cnxk_meter_node *mtr;
686 	struct roc_nix_rq *rq;
687 	uint32_t i;
688 	int rc = 0;
689 
690 	mtr = nix_mtr_find(dev, mtr_id);
691 	if (mtr == NULL) {
692 		return -rte_mtr_error_set(error, ENOENT,
693 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
694 					  "Meter id is invalid.");
695 	}
696 
697 	if (mtr->level != 0)
698 		return 0;
699 
700 	for (i = 0; i < mtr->rq_num; i++) {
701 		rq = &dev->rqs[mtr->rq_id[i]];
702 		rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, true);
703 	}
704 
705 	return rc;
706 }
707 
708 static int
cnxk_nix_mtr_disable(struct rte_eth_dev * eth_dev,uint32_t mtr_id,struct rte_mtr_error * error)709 cnxk_nix_mtr_disable(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
710 		     struct rte_mtr_error *error)
711 {
712 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
713 	struct roc_nix *nix = &dev->nix;
714 	struct cnxk_meter_node *mtr;
715 	struct roc_nix_rq *rq;
716 	uint32_t i;
717 	int rc = 0;
718 
719 	mtr = nix_mtr_find(dev, mtr_id);
720 	if (mtr == NULL) {
721 		return -rte_mtr_error_set(error, ENOENT,
722 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
723 					  "Meter id is invalid.");
724 	}
725 
726 	if (mtr->level != 0)
727 		return 0;
728 
729 	for (i = 0; i < mtr->rq_num; i++) {
730 		rq = &dev->rqs[mtr->rq_id[i]];
731 		rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, false);
732 	}
733 
734 	return rc;
735 }
736 
737 static int
cnxk_nix_mtr_dscp_table_update(struct rte_eth_dev * eth_dev,uint32_t mtr_id,enum rte_mtr_color_in_protocol proto,enum rte_color * dscp_table,struct rte_mtr_error * error)738 cnxk_nix_mtr_dscp_table_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
739 			       enum rte_mtr_color_in_protocol proto,
740 			       enum rte_color *dscp_table,
741 			       struct rte_mtr_error *error)
742 {
743 	enum roc_nix_bpf_color nix_dscp_tbl[ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP];
744 	enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
745 					      ROC_NIX_BPF_COLOR_YELLOW,
746 					      ROC_NIX_BPF_COLOR_RED};
747 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
748 	struct roc_nix_bpf_precolor table;
749 	struct roc_nix *nix = &dev->nix;
750 	struct cnxk_meter_node *mtr;
751 	int rc, i;
752 
753 	mtr = nix_mtr_find(dev, mtr_id);
754 	if (mtr == NULL) {
755 		return -rte_mtr_error_set(error, ENOENT,
756 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
757 					  "Meter object not found");
758 	}
759 
760 	if (!dscp_table) {
761 		for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
762 			nix_dscp_tbl[i] = ROC_NIX_BPF_COLOR_GREEN;
763 	} else {
764 		for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
765 			nix_dscp_tbl[i] = color_map[dscp_table[i]];
766 	}
767 
768 	table.count = ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP;
769 
770 	switch (proto) {
771 	case RTE_MTR_COLOR_IN_PROTO_OUTER_IP:
772 		table.mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
773 		break;
774 	case RTE_MTR_COLOR_IN_PROTO_INNER_IP:
775 		table.mode = ROC_NIX_BPF_PC_MODE_DSCP_INNER;
776 		break;
777 	default:
778 		rc = -rte_mtr_error_set(error, EINVAL,
779 			RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
780 			"Invalid input color protocol");
781 		goto exit;
782 	}
783 
784 	if (dev->proto != proto) {
785 		rc = -rte_mtr_error_set(error, EINVAL,
786 			RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
787 			"input color protocol is not configured");
788 		goto exit;
789 	}
790 
791 	for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
792 		table.color[i] = nix_dscp_tbl[i];
793 
794 	rc = roc_nix_bpf_pre_color_tbl_setup(nix, mtr->bpf_id,
795 					     lvl_map[mtr->level], &table);
796 	if (rc) {
797 		rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
798 				  NULL, NULL);
799 		goto exit;
800 	}
801 
802 	for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
803 		dev->precolor_tbl[i] = nix_dscp_tbl[i];
804 
805 exit:
806 	return rc;
807 }
808 
809 static int
cnxk_nix_mtr_vlan_table_update(struct rte_eth_dev * eth_dev,uint32_t mtr_id,enum rte_mtr_color_in_protocol proto,enum rte_color * vlan_table,struct rte_mtr_error * error)810 cnxk_nix_mtr_vlan_table_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
811 			       enum rte_mtr_color_in_protocol proto,
812 			       enum rte_color *vlan_table,
813 			       struct rte_mtr_error *error)
814 {
815 	enum roc_nix_bpf_color nix_vlan_tbl[ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN];
816 	enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
817 					      ROC_NIX_BPF_COLOR_YELLOW,
818 					      ROC_NIX_BPF_COLOR_RED};
819 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
820 	struct roc_nix_bpf_precolor table;
821 	struct roc_nix *nix = &dev->nix;
822 	struct cnxk_meter_node *mtr;
823 	int rc, i;
824 
825 	mtr = nix_mtr_find(dev, mtr_id);
826 	if (mtr == NULL) {
827 		return -rte_mtr_error_set(error, ENOENT,
828 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
829 					  "Meter object not found");
830 	}
831 
832 	if (!vlan_table) {
833 		for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
834 			nix_vlan_tbl[i] = ROC_NIX_BPF_COLOR_GREEN;
835 	} else {
836 		for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
837 			nix_vlan_tbl[i] = color_map[vlan_table[i]];
838 	}
839 
840 	table.count = ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN;
841 
842 	switch (proto) {
843 	case RTE_MTR_COLOR_IN_PROTO_OUTER_VLAN:
844 		table.mode = ROC_NIX_BPF_PC_MODE_VLAN_OUTER;
845 		break;
846 	case RTE_MTR_COLOR_IN_PROTO_INNER_VLAN:
847 		table.mode = ROC_NIX_BPF_PC_MODE_VLAN_INNER;
848 		break;
849 	default:
850 		rc = -rte_mtr_error_set(error, EINVAL,
851 			RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
852 			"Invalid input color protocol");
853 		goto exit;
854 	}
855 
856 	if (dev->proto != proto) {
857 		rc = -rte_mtr_error_set(error, EINVAL,
858 			RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
859 			"input color protocol is not configured");
860 		goto exit;
861 	}
862 
863 	for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
864 		table.color[i] = nix_vlan_tbl[i];
865 
866 	rc = roc_nix_bpf_pre_color_tbl_setup(nix, mtr->bpf_id,
867 					     lvl_map[mtr->level], &table);
868 	if (rc) {
869 		rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
870 				  NULL, NULL);
871 		goto exit;
872 	}
873 
874 	for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
875 		dev->precolor_tbl[i] = nix_vlan_tbl[i];
876 
877 exit:
878 	return rc;
879 }
880 
881 static int
cnxk_nix_mtr_in_proto_set(struct rte_eth_dev * eth_dev,uint32_t mtr_id,enum rte_mtr_color_in_protocol proto,uint32_t priority,struct rte_mtr_error * error)882 cnxk_nix_mtr_in_proto_set(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
883 			  enum rte_mtr_color_in_protocol proto,
884 			  uint32_t priority, struct rte_mtr_error *error)
885 {
886 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
887 	struct cnxk_meter_node *mtr;
888 
889 	RTE_SET_USED(priority);
890 
891 	mtr = nix_mtr_find(dev, mtr_id);
892 	if (mtr == NULL) {
893 		return -rte_mtr_error_set(error, ENOENT,
894 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
895 					  "Meter object not found");
896 	}
897 
898 	dev->proto = proto;
899 	return 0;
900 }
901 
902 static int
cnxk_nix_mtr_in_proto_get(struct rte_eth_dev * eth_dev,uint32_t mtr_id,uint64_t * proto_mask,struct rte_mtr_error * error)903 cnxk_nix_mtr_in_proto_get(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
904 			  uint64_t *proto_mask, struct rte_mtr_error *error)
905 {
906 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
907 	struct cnxk_meter_node *mtr;
908 
909 	mtr = nix_mtr_find(dev, mtr_id);
910 	if (mtr == NULL) {
911 		return -rte_mtr_error_set(error, ENOENT,
912 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
913 					  "Meter object not found");
914 	}
915 
916 	*proto_mask = dev->proto;
917 	return 0;
918 }
919 
920 static int
cnxk_nix_mtr_in_proto_prio_get(struct rte_eth_dev * eth_dev,uint32_t mtr_id,enum rte_mtr_color_in_protocol proto,uint32_t * priority,struct rte_mtr_error * error)921 cnxk_nix_mtr_in_proto_prio_get(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
922 			       enum rte_mtr_color_in_protocol proto,
923 			       uint32_t *priority, struct rte_mtr_error *error)
924 {
925 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
926 	struct cnxk_meter_node *mtr;
927 
928 	RTE_SET_USED(proto);
929 
930 	mtr = nix_mtr_find(dev, mtr_id);
931 	if (mtr == NULL) {
932 		return -rte_mtr_error_set(error, ENOENT,
933 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
934 					  "Meter object not found");
935 	}
936 
937 	plt_info("Only single priority supported i.e. 0");
938 	*priority = 0;
939 	return 0;
940 }
941 
942 static int
cnxk_nix_mtr_stats_update(struct rte_eth_dev * eth_dev,uint32_t mtr_id,uint64_t stats_mask,struct rte_mtr_error * error)943 cnxk_nix_mtr_stats_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
944 			  uint64_t stats_mask, struct rte_mtr_error *error)
945 {
946 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
947 	struct cnxk_meter_node *mtr;
948 
949 	if (!stats_mask)
950 		return -rte_mtr_error_set(error, EINVAL,
951 					  RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
952 					  "no bit is set to stats mask");
953 
954 	mtr = nix_mtr_find(dev, mtr_id);
955 	if (mtr == NULL) {
956 		return -rte_mtr_error_set(error, ENOENT,
957 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
958 					  "Meter object not found");
959 	}
960 
961 	mtr->params.stats_mask = stats_mask;
962 	return 0;
963 }
964 
965 static int
cnxk_nix_mtr_stats_read(struct rte_eth_dev * eth_dev,uint32_t mtr_id,struct rte_mtr_stats * stats,uint64_t * stats_mask,int clear,struct rte_mtr_error * error)966 cnxk_nix_mtr_stats_read(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
967 			struct rte_mtr_stats *stats, uint64_t *stats_mask,
968 			int clear, struct rte_mtr_error *error)
969 {
970 	uint8_t yellow_pkt_pass, yellow_octs_pass, yellow_pkt_drop;
971 	uint8_t green_octs_drop, yellow_octs_drop, red_octs_drop;
972 	uint8_t green_pkt_pass, green_octs_pass, green_pkt_drop;
973 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
974 	uint8_t red_pkt_pass, red_octs_pass, red_pkt_drop;
975 	uint64_t bpf_stats[ROC_NIX_BPF_STATS_MAX] = {0};
976 	uint64_t mask = NIX_BPF_STATS_MASK_ALL;
977 	struct roc_nix *nix = &dev->nix;
978 	struct cnxk_meter_node *mtr;
979 	int rc;
980 
981 	if (!stats)
982 		return -rte_mtr_error_set(error, EINVAL,
983 					  RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
984 					  "stats pointer is NULL");
985 
986 	mtr = nix_mtr_find(dev, mtr_id);
987 	if (mtr == NULL) {
988 		return -rte_mtr_error_set(error, ENOENT,
989 					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
990 					  "Meter object not found");
991 	}
992 
993 	rc = roc_nix_bpf_stats_read(nix, mtr->bpf_id, mask, lvl_map[mtr->level],
994 				    bpf_stats);
995 	if (rc) {
996 		rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
997 				  NULL, NULL);
998 		goto exit;
999 	}
1000 
1001 	green_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_PASS);
1002 	green_octs_pass =
1003 		roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_PASS);
1004 	green_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_DROP);
1005 	green_octs_drop =
1006 		roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_DROP);
1007 	yellow_pkt_pass =
1008 		roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_PASS);
1009 	yellow_octs_pass =
1010 		roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_PASS);
1011 	yellow_pkt_drop =
1012 		roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_DROP);
1013 	yellow_octs_drop =
1014 		roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_DROP);
1015 	red_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_PASS);
1016 	red_octs_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_PASS);
1017 	red_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_DROP);
1018 	red_octs_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_DROP);
1019 
1020 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_GREEN)
1021 		stats->n_pkts[RTE_COLOR_GREEN] = bpf_stats[green_pkt_pass];
1022 
1023 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_YELLOW)
1024 		stats->n_pkts[RTE_COLOR_YELLOW] = bpf_stats[yellow_pkt_pass];
1025 
1026 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_RED)
1027 		stats->n_pkts[RTE_COLOR_RED] = bpf_stats[red_pkt_pass];
1028 
1029 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_GREEN)
1030 		stats->n_bytes[RTE_COLOR_GREEN] = bpf_stats[green_octs_pass];
1031 
1032 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_YELLOW)
1033 		stats->n_bytes[RTE_COLOR_YELLOW] = bpf_stats[yellow_octs_pass];
1034 
1035 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_RED)
1036 		stats->n_bytes[RTE_COLOR_RED] = bpf_stats[red_octs_pass];
1037 
1038 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED)
1039 		stats->n_pkts_dropped = bpf_stats[green_pkt_drop] +
1040 					bpf_stats[yellow_pkt_drop] +
1041 					bpf_stats[red_pkt_drop];
1042 
1043 	if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED)
1044 		stats->n_bytes_dropped = bpf_stats[green_octs_drop] +
1045 					 bpf_stats[yellow_octs_drop] +
1046 					 bpf_stats[red_octs_drop];
1047 
1048 	if (stats_mask)
1049 		*stats_mask = mtr->params.stats_mask;
1050 
1051 	if (clear) {
1052 		rc = roc_nix_bpf_stats_reset(nix, mtr->bpf_id, mask,
1053 					     lvl_map[mtr->level]);
1054 		if (rc) {
1055 			rte_mtr_error_set(error, rc,
1056 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1057 					  NULL);
1058 			goto exit;
1059 		}
1060 	}
1061 
1062 exit:
1063 	return rc;
1064 }
1065 
1066 const struct rte_mtr_ops nix_mtr_ops = {
1067 	.capabilities_get = cnxk_nix_mtr_capabilities_get,
1068 	.meter_profile_add = cnxk_nix_mtr_profile_add,
1069 	.meter_profile_delete = cnxk_nix_mtr_profile_delete,
1070 	.meter_policy_validate = cnxk_nix_mtr_policy_validate,
1071 	.meter_policy_add = cnxk_nix_mtr_policy_add,
1072 	.meter_policy_delete = cnxk_nix_mtr_policy_delete,
1073 	.create = cnxk_nix_mtr_create,
1074 	.destroy = cnxk_nix_mtr_destroy,
1075 	.meter_enable = cnxk_nix_mtr_enable,
1076 	.meter_disable = cnxk_nix_mtr_disable,
1077 	.meter_dscp_table_update = cnxk_nix_mtr_dscp_table_update,
1078 	.meter_vlan_table_update = cnxk_nix_mtr_vlan_table_update,
1079 	.in_proto_set = cnxk_nix_mtr_in_proto_set,
1080 	.in_proto_get = cnxk_nix_mtr_in_proto_get,
1081 	.in_proto_prio_get = cnxk_nix_mtr_in_proto_prio_get,
1082 	.stats_update = cnxk_nix_mtr_stats_update,
1083 	.stats_read = cnxk_nix_mtr_stats_read,
1084 };
1085 
1086 int
cnxk_nix_mtr_ops_get(struct rte_eth_dev * dev,void * ops)1087 cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops)
1088 {
1089 	RTE_SET_USED(dev);
1090 
1091 	*(const void **)ops = &nix_mtr_ops;
1092 	return 0;
1093 }
1094 
1095 int
nix_mtr_validate(struct rte_eth_dev * eth_dev,uint32_t id)1096 nix_mtr_validate(struct rte_eth_dev *eth_dev, uint32_t id)
1097 {
1098 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1099 	struct cnxk_mtr_profile_node *profile;
1100 	struct cnxk_mtr_policy_node *policy;
1101 	struct cnxk_meter_node *mtr;
1102 
1103 	mtr = nix_mtr_find(dev, id);
1104 	if (mtr == NULL)
1105 		return -EINVAL;
1106 
1107 	profile = nix_mtr_profile_find(dev, mtr->params.meter_profile_id);
1108 	if (profile == NULL)
1109 		return -EINVAL;
1110 
1111 	policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
1112 	if (policy == NULL)
1113 		return -EINVAL;
1114 
1115 	return 0;
1116 }
1117 
1118 int
nix_mtr_policy_act_get(struct rte_eth_dev * eth_dev,uint32_t id,struct cnxk_mtr_policy_node ** policy_act)1119 nix_mtr_policy_act_get(struct rte_eth_dev *eth_dev, uint32_t id,
1120 		       struct cnxk_mtr_policy_node **policy_act)
1121 {
1122 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1123 	struct cnxk_mtr_policy_node *policy;
1124 	struct cnxk_meter_node *mtr;
1125 
1126 	mtr = nix_mtr_find(dev, id);
1127 	if (mtr == NULL)
1128 		return -EINVAL;
1129 
1130 	policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
1131 	if (policy == NULL)
1132 		return -EINVAL;
1133 
1134 	*policy_act = policy;
1135 
1136 	return 0;
1137 }
1138 
1139 int
nix_mtr_rq_update(struct rte_eth_dev * eth_dev,uint32_t id,uint32_t queue_num,const uint16_t * queue)1140 nix_mtr_rq_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t queue_num,
1141 		  const uint16_t *queue)
1142 {
1143 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1144 	struct cnxk_meter_node *mtr;
1145 	uint32_t i;
1146 
1147 	mtr = nix_mtr_find(dev, id);
1148 	if (mtr == NULL)
1149 		return -EINVAL;
1150 
1151 	mtr->rq_id = plt_zmalloc(queue_num * sizeof(uint32_t), ROC_ALIGN);
1152 	if (mtr->rq_id == NULL)
1153 		return -ENOMEM;
1154 
1155 	mtr->rq_num = queue_num;
1156 	for (i = 0; i < queue_num; i++)
1157 		mtr->rq_id[i] = queue[i];
1158 
1159 	return 0;
1160 }
1161 
1162 int
nix_mtr_chain_reset(struct rte_eth_dev * eth_dev,uint32_t cur_id)1163 nix_mtr_chain_reset(struct rte_eth_dev *eth_dev, uint32_t cur_id)
1164 {
1165 	struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1166 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1167 	uint32_t mtr_id = cur_id;
1168 	int i = 0, j = 0;
1169 
1170 	for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1171 		mtr[i] = nix_mtr_find(dev, mtr_id);
1172 		if (mtr[i])
1173 			mtr_id = mtr[i]->next_id;
1174 	}
1175 	for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1176 		if (mtr[i]) {
1177 			for (j = 0; j < MAX_PRV_MTR_NODES; j++)
1178 				mtr[i]->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
1179 			mtr[i]->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1180 			mtr[i]->next_id = ROC_NIX_BPF_ID_INVALID;
1181 			mtr[i]->is_next = false;
1182 			mtr[i]->prev_cnt = 0;
1183 		}
1184 	}
1185 	return 0;
1186 }
1187 
1188 int
nix_mtr_chain_update(struct rte_eth_dev * eth_dev,uint32_t cur_id,uint32_t prev_id,uint32_t next_id)1189 nix_mtr_chain_update(struct rte_eth_dev *eth_dev, uint32_t cur_id,
1190 		     uint32_t prev_id, uint32_t next_id)
1191 {
1192 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1193 	struct cnxk_meter_node *mtr;
1194 
1195 	mtr = nix_mtr_find(dev, cur_id);
1196 	if (mtr == NULL)
1197 		return -EINVAL;
1198 
1199 	switch (lvl_map[mtr->level]) {
1200 	case ROC_NIX_BPF_LEVEL_F_LEAF:
1201 		mtr->prev_id[mtr->prev_cnt] = ROC_NIX_BPF_ID_INVALID;
1202 		mtr->next_id = next_id;
1203 		mtr->is_next = true;
1204 		break;
1205 	case ROC_NIX_BPF_LEVEL_F_MID:
1206 		mtr->prev_id[mtr->prev_cnt] = prev_id;
1207 		mtr->next_id = next_id;
1208 		mtr->is_next = true;
1209 		break;
1210 	case ROC_NIX_BPF_LEVEL_F_TOP:
1211 		mtr->prev_id[mtr->prev_cnt] = prev_id;
1212 		mtr->next_id = ROC_NIX_BPF_ID_INVALID;
1213 		mtr->is_next = false;
1214 		break;
1215 	default:
1216 		plt_err("Invalid meter level");
1217 		return -EINVAL;
1218 	}
1219 
1220 	return 0;
1221 }
1222 
1223 struct cnxk_meter_node *
nix_get_mtr(struct rte_eth_dev * eth_dev,uint32_t id)1224 nix_get_mtr(struct rte_eth_dev *eth_dev, uint32_t id)
1225 {
1226 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1227 	struct cnxk_meter_node *mtr;
1228 
1229 	mtr = nix_mtr_find(dev, id);
1230 	if (mtr == NULL)
1231 		return NULL;
1232 
1233 	return mtr;
1234 }
1235 
1236 int
nix_mtr_level_update(struct rte_eth_dev * eth_dev,uint32_t id,uint32_t level)1237 nix_mtr_level_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t level)
1238 {
1239 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1240 	struct cnxk_meter_node *mtr;
1241 
1242 	mtr = nix_mtr_find(dev, id);
1243 	if (mtr == NULL)
1244 		return -EINVAL;
1245 
1246 	mtr->level = level;
1247 	return 0;
1248 }
1249 
1250 static void
nix_mtr_config_map(struct cnxk_meter_node * mtr,struct roc_nix_bpf_cfg * cfg)1251 nix_mtr_config_map(struct cnxk_meter_node *mtr, struct roc_nix_bpf_cfg *cfg)
1252 {
1253 	enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
1254 					      ROC_NIX_BPF_COLOR_YELLOW,
1255 					      ROC_NIX_BPF_COLOR_RED};
1256 	enum roc_nix_bpf_algo alg_map[] = {
1257 		ROC_NIX_BPF_ALGO_NONE, ROC_NIX_BPF_ALGO_2697,
1258 		ROC_NIX_BPF_ALGO_2698, ROC_NIX_BPF_ALGO_4115};
1259 	struct cnxk_mtr_profile_node *profile = mtr->profile;
1260 	struct cnxk_mtr_policy_node *policy = mtr->policy;
1261 
1262 	cfg->alg = alg_map[profile->profile.alg];
1263 	cfg->lmode = profile->profile.packet_mode;
1264 	cfg->icolor = color_map[mtr->params.default_input_color];
1265 
1266 	switch (RTE_MTR_COLOR_IN_PROTO_OUTER_IP) {
1267 	case RTE_MTR_COLOR_IN_PROTO_OUTER_IP:
1268 		cfg->pc_mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
1269 		cfg->tnl_ena = false;
1270 		break;
1271 	case RTE_MTR_COLOR_IN_PROTO_INNER_IP:
1272 		cfg->pc_mode = ROC_NIX_BPF_PC_MODE_DSCP_INNER;
1273 		cfg->tnl_ena = true;
1274 		break;
1275 	case RTE_MTR_COLOR_IN_PROTO_OUTER_VLAN:
1276 		cfg->pc_mode = ROC_NIX_BPF_PC_MODE_VLAN_OUTER;
1277 		cfg->tnl_ena = false;
1278 		break;
1279 	case RTE_MTR_COLOR_IN_PROTO_INNER_VLAN:
1280 		cfg->pc_mode = ROC_NIX_BPF_PC_MODE_VLAN_INNER;
1281 		cfg->tnl_ena = true;
1282 		break;
1283 	default:
1284 		break;
1285 	}
1286 
1287 	switch (cfg->alg) {
1288 	case ROC_NIX_BPF_ALGO_2697:
1289 		cfg->algo2697.cir = profile->profile.srtcm_rfc2697.cir * 8;
1290 		cfg->algo2697.cbs = profile->profile.srtcm_rfc2697.cbs;
1291 		cfg->algo2697.ebs = profile->profile.srtcm_rfc2697.ebs;
1292 		break;
1293 	case ROC_NIX_BPF_ALGO_2698:
1294 		cfg->algo2698.cir = profile->profile.trtcm_rfc2698.cir * 8;
1295 		cfg->algo2698.pir = profile->profile.trtcm_rfc2698.pir * 8;
1296 		cfg->algo2698.cbs = profile->profile.trtcm_rfc2698.cbs;
1297 		cfg->algo2698.pbs = profile->profile.trtcm_rfc2698.pbs;
1298 		break;
1299 	case ROC_NIX_BPF_ALGO_4115:
1300 		cfg->algo4115.cir = profile->profile.trtcm_rfc4115.cir * 8;
1301 		cfg->algo4115.eir = profile->profile.trtcm_rfc4115.eir * 8;
1302 		cfg->algo4115.cbs = profile->profile.trtcm_rfc4115.cbs;
1303 		cfg->algo4115.ebs = profile->profile.trtcm_rfc4115.ebs;
1304 		break;
1305 	default:
1306 		break;
1307 	}
1308 
1309 	cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_PASS;
1310 	cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_PASS;
1311 	cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_PASS;
1312 
1313 	if (policy->actions[RTE_COLOR_GREEN].action_fate ==
1314 	    RTE_FLOW_ACTION_TYPE_DROP)
1315 		cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_DROP;
1316 
1317 	if (policy->actions[RTE_COLOR_YELLOW].action_fate ==
1318 	    RTE_FLOW_ACTION_TYPE_DROP)
1319 		cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_DROP;
1320 
1321 	if (policy->actions[RTE_COLOR_RED].action_fate ==
1322 	    RTE_FLOW_ACTION_TYPE_DROP)
1323 		cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_DROP;
1324 }
1325 
1326 static void
nix_mtr_config_red(struct cnxk_meter_node * mtr,struct roc_nix_rq * rq,struct roc_nix_bpf_cfg * cfg)1327 nix_mtr_config_red(struct cnxk_meter_node *mtr, struct roc_nix_rq *rq,
1328 		   struct roc_nix_bpf_cfg *cfg)
1329 {
1330 	struct cnxk_mtr_policy_node *policy = mtr->policy;
1331 
1332 	if ((rq->red_pass && rq->red_pass >= rq->red_drop) ||
1333 	   (rq->spb_red_pass && rq->spb_red_pass >= rq->spb_red_drop)	||
1334 	   (rq->xqe_red_pass && rq->xqe_red_pass >= rq->xqe_red_drop)) {
1335 		if (policy->actions[RTE_COLOR_GREEN].action_fate ==
1336 			RTE_FLOW_ACTION_TYPE_DROP) {
1337 			if (policy->actions[RTE_COLOR_GREEN].skip_red)
1338 				cfg->action[ROC_NIX_BPF_COLOR_GREEN] =
1339 						ROC_NIX_BPF_ACTION_DROP;
1340 			else
1341 				cfg->action[ROC_NIX_BPF_COLOR_GREEN] =
1342 						ROC_NIX_BPF_ACTION_RED;
1343 		}
1344 		if (policy->actions[RTE_COLOR_YELLOW].action_fate ==
1345 			RTE_FLOW_ACTION_TYPE_DROP) {
1346 			if (policy->actions[RTE_COLOR_YELLOW].skip_red)
1347 				cfg->action[ROC_NIX_BPF_COLOR_YELLOW] =
1348 						ROC_NIX_BPF_ACTION_DROP;
1349 			else
1350 				cfg->action[ROC_NIX_BPF_COLOR_YELLOW] =
1351 						ROC_NIX_BPF_ACTION_RED;
1352 		}
1353 		if (policy->actions[RTE_COLOR_RED].action_fate ==
1354 			RTE_FLOW_ACTION_TYPE_DROP) {
1355 			if (policy->actions[RTE_COLOR_RED].skip_red)
1356 				cfg->action[ROC_NIX_BPF_COLOR_RED] =
1357 						ROC_NIX_BPF_ACTION_DROP;
1358 			else
1359 				cfg->action[ROC_NIX_BPF_COLOR_RED] =
1360 						ROC_NIX_BPF_ACTION_RED;
1361 		}
1362 	}
1363 }
1364 
1365 static void
nix_precolor_table_map(struct cnxk_meter_node * mtr,struct roc_nix_bpf_precolor * tbl,enum rte_mtr_color_in_protocol proto)1366 nix_precolor_table_map(struct cnxk_meter_node *mtr,
1367 		       struct roc_nix_bpf_precolor *tbl,
1368 		       enum rte_mtr_color_in_protocol proto)
1369 {
1370 	enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
1371 					      ROC_NIX_BPF_COLOR_YELLOW,
1372 					      ROC_NIX_BPF_COLOR_RED};
1373 	int i;
1374 
1375 	switch (proto) {
1376 	case RTE_MTR_COLOR_IN_PROTO_OUTER_IP:
1377 	case RTE_MTR_COLOR_IN_PROTO_INNER_IP:
1378 		tbl->count = ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP;
1379 		tbl->mode = (proto == RTE_MTR_COLOR_IN_PROTO_OUTER_IP) ?
1380 				    ROC_NIX_BPF_PC_MODE_DSCP_OUTER :
1381 				    ROC_NIX_BPF_PC_MODE_DSCP_INNER;
1382 
1383 		for (i = 0; i < tbl->count; i++)
1384 			tbl->color[i] = ROC_NIX_BPF_COLOR_GREEN;
1385 
1386 		if (mtr->params.dscp_table) {
1387 			for (i = 0; i < tbl->count; i++)
1388 				tbl->color[i] =
1389 					color_map[mtr->params.dscp_table[i]];
1390 		}
1391 		break;
1392 	case RTE_MTR_COLOR_IN_PROTO_OUTER_VLAN:
1393 	case RTE_MTR_COLOR_IN_PROTO_INNER_VLAN:
1394 		tbl->count = ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN;
1395 		tbl->mode = (proto == RTE_MTR_COLOR_IN_PROTO_OUTER_VLAN) ?
1396 				    ROC_NIX_BPF_PC_MODE_VLAN_OUTER :
1397 				    ROC_NIX_BPF_PC_MODE_VLAN_INNER;
1398 
1399 		for (i = 0; i < tbl->count; i++)
1400 			tbl->color[i] = ROC_NIX_BPF_COLOR_GREEN;
1401 
1402 		if (mtr->params.vlan_table) {
1403 			for (i = 0; i < tbl->count; i++)
1404 				tbl->color[i] =
1405 					color_map[mtr->params.vlan_table[i]];
1406 		}
1407 		break;
1408 	default:
1409 		break;
1410 	}
1411 }
1412 
1413 int
nix_mtr_destroy(struct rte_eth_dev * eth_dev,uint32_t id,struct rte_mtr_error * error)1414 nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t id,
1415 		struct rte_mtr_error *error)
1416 {
1417 	return cnxk_nix_mtr_destroy(eth_dev, id, error);
1418 }
1419 
1420 int
nix_mtr_connect(struct rte_eth_dev * eth_dev,uint32_t id)1421 nix_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t id)
1422 {
1423 	enum roc_nix_bpf_level_flag lvl_flag = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1424 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1425 	struct cnxk_meter_node *base_mtr, *next_mtr;
1426 	struct roc_nix *nix = &dev->nix;
1427 	uint32_t cur_mtr_id = id;
1428 	int rc, i;
1429 
1430 	for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1431 		base_mtr = nix_mtr_find(dev, cur_mtr_id);
1432 		if (base_mtr) {
1433 			lvl_flag = lvl_map[base_mtr->level];
1434 			if (base_mtr->is_next) {
1435 				next_mtr = nix_mtr_find(dev, base_mtr->next_id);
1436 				if (next_mtr) {
1437 					if (!base_mtr->is_used) {
1438 						rc = roc_nix_bpf_connect(nix,
1439 							lvl_flag,
1440 							base_mtr->bpf_id,
1441 							next_mtr->bpf_id);
1442 						if (rc)
1443 							return rc;
1444 					}
1445 				}
1446 				cur_mtr_id = base_mtr->next_id;
1447 			}
1448 		}
1449 	}
1450 	return 0;
1451 }
1452 
1453 int
nix_mtr_configure(struct rte_eth_dev * eth_dev,uint32_t id)1454 nix_mtr_configure(struct rte_eth_dev *eth_dev, uint32_t id)
1455 {
1456 	struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1457 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1458 	struct roc_nix_bpf_objs profs[ROC_NIX_BPF_LEVEL_MAX];
1459 	uint8_t idx0 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1460 	uint8_t idx1 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1461 	uint8_t idx2 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1462 	uint16_t per_lvl_cnt[ROC_NIX_BPF_LEVEL_MAX];
1463 	int num_mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1464 	struct roc_nix *nix = &dev->nix;
1465 	struct roc_nix_bpf_precolor tbl;
1466 	struct roc_nix_bpf_cfg cfg;
1467 	struct roc_nix_rq *rq;
1468 	uint8_t lvl_mask;
1469 	uint32_t i;
1470 	uint32_t j;
1471 	int rc;
1472 
1473 	mtr[0] = nix_mtr_find(dev, id);
1474 	if (mtr[0] == NULL)
1475 		return -EINVAL;
1476 
1477 	num_mtr[0] = 1;
1478 	idx0 = roc_nix_bpf_level_to_idx(lvl_map[mtr[0]->level]);
1479 	if (idx0 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1480 		return -EINVAL;
1481 
1482 	lvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF;
1483 	if (mtr[0]->is_used)
1484 		per_lvl_cnt[idx0] = 0;
1485 	else
1486 		per_lvl_cnt[idx0] = 1;
1487 
1488 	if (mtr[0]->is_next) {
1489 		mtr[1] = nix_mtr_find(dev, mtr[0]->next_id);
1490 		if (mtr[1] == NULL)
1491 			return -EINVAL;
1492 		num_mtr[1] = 1;
1493 		idx1 = roc_nix_bpf_level_to_idx(lvl_map[mtr[1]->level]);
1494 		if (idx1 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1495 			return -EINVAL;
1496 
1497 		lvl_mask |= ROC_NIX_BPF_LEVEL_F_MID;
1498 		if (mtr[1]->is_used)
1499 			per_lvl_cnt[idx1] = 0;
1500 		else
1501 			per_lvl_cnt[idx1] = 1;
1502 	}
1503 
1504 	if (mtr[1] && mtr[1]->is_next) {
1505 		mtr[2] = nix_mtr_find(dev, mtr[1]->next_id);
1506 		if (mtr[2] == NULL)
1507 			return -EINVAL;
1508 
1509 		num_mtr[2] = 1;
1510 		idx2 = roc_nix_bpf_level_to_idx(lvl_map[mtr[2]->level]);
1511 		if (idx2 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1512 			return -EINVAL;
1513 
1514 		lvl_mask |= ROC_NIX_BPF_LEVEL_F_TOP;
1515 		if (mtr[2]->is_used)
1516 			per_lvl_cnt[idx2] = 0;
1517 		else
1518 			per_lvl_cnt[idx2] = 1;
1519 	}
1520 
1521 	rc = roc_nix_bpf_alloc(nix, lvl_mask, per_lvl_cnt, profs);
1522 	if (rc)
1523 		return rc;
1524 	if (mtr[0]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1525 		mtr[0]->bpf_id = profs[idx0].ids[0];
1526 
1527 	if (num_mtr[0])
1528 		if (mtr[0]->is_next && idx1 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1529 			if (mtr[1]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1530 				mtr[1]->bpf_id = profs[idx1].ids[0];
1531 
1532 	if (num_mtr[1])
1533 		if (mtr[1]->is_next && idx2 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1534 			if (mtr[2]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1535 				mtr[2]->bpf_id = profs[idx2].ids[0];
1536 
1537 	for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1538 		if (num_mtr[i]) {
1539 			if (!mtr[i]->is_used) {
1540 				memset(&cfg, 0, sizeof(struct roc_nix_bpf_cfg));
1541 				nix_mtr_config_map(mtr[i], &cfg);
1542 				for (j = 0; j < mtr[i]->rq_num; j++) {
1543 					rq = &dev->rqs[mtr[i]->rq_id[j]];
1544 					nix_mtr_config_red(mtr[i], rq, &cfg);
1545 				}
1546 				rc = roc_nix_bpf_config(nix, mtr[i]->bpf_id,
1547 							lvl_map[mtr[i]->level],
1548 							&cfg);
1549 
1550 				memset(&tbl, 0,
1551 				       sizeof(struct roc_nix_bpf_precolor));
1552 				nix_precolor_table_map(mtr[i], &tbl,
1553 						       dev->proto);
1554 				rc = roc_nix_bpf_pre_color_tbl_setup(nix,
1555 					mtr[i]->bpf_id, lvl_map[mtr[i]->level],
1556 					&tbl);
1557 
1558 				if (mtr[i]->params.meter_enable) {
1559 					for (j = 0; j < mtr[i]->rq_num; j++) {
1560 						rq = &dev->rqs[mtr[i]->rq_id
1561 								       [j]];
1562 						rc = roc_nix_bpf_ena_dis(nix,
1563 							mtr[i]->bpf_id, rq,
1564 							true);
1565 					}
1566 				}
1567 			}
1568 		}
1569 	}
1570 
1571 	return rc;
1572 }
1573 
1574 int
nix_mtr_color_action_validate(struct rte_eth_dev * eth_dev,uint32_t id,uint32_t * prev_id,uint32_t * next_id,struct cnxk_mtr_policy_node * policy,int * tree_level)1575 nix_mtr_color_action_validate(struct rte_eth_dev *eth_dev, uint32_t id,
1576 			      uint32_t *prev_id, uint32_t *next_id,
1577 			      struct cnxk_mtr_policy_node *policy,
1578 			      int *tree_level)
1579 {
1580 	uint32_t action_fate_red = policy->actions[RTE_COLOR_RED].action_fate;
1581 	uint32_t action_fate_green =
1582 		policy->actions[RTE_COLOR_GREEN].action_fate;
1583 	uint32_t action_fate_yellow =
1584 		policy->actions[RTE_COLOR_YELLOW].action_fate;
1585 	uint32_t cur_mtr_id = *next_id;
1586 	uint32_t next_mtr_id = 0xffff;
1587 	uint32_t prev_mtr_id = 0xffff;
1588 	struct cnxk_meter_node *mtr;
1589 
1590 	if (action_fate_green == RTE_FLOW_ACTION_TYPE_METER)
1591 		next_mtr_id = policy->actions[RTE_COLOR_GREEN].mtr_id;
1592 
1593 	if (action_fate_yellow == RTE_FLOW_ACTION_TYPE_METER)
1594 		next_mtr_id = policy->actions[RTE_COLOR_YELLOW].mtr_id;
1595 
1596 	if (action_fate_red == RTE_FLOW_ACTION_TYPE_METER)
1597 		next_mtr_id = policy->actions[RTE_COLOR_RED].mtr_id;
1598 
1599 	if (next_mtr_id != 0xffff) {
1600 		switch (*tree_level) {
1601 		case 0:
1602 			mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1603 			if (mtr == NULL)
1604 				return -EINVAL;
1605 			if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1606 				nix_mtr_level_update(eth_dev, cur_mtr_id, 0);
1607 				nix_mtr_chain_update(eth_dev, cur_mtr_id, -1,
1608 						     next_mtr_id);
1609 			} else {
1610 				if (mtr->level == 0)
1611 					mtr->is_used = true;
1612 				else
1613 					return -EINVAL;
1614 			}
1615 			(*tree_level)++;
1616 			*next_id = next_mtr_id;
1617 			break;
1618 		case 1:
1619 			mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1620 			if (mtr == NULL)
1621 				return -EINVAL;
1622 			if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1623 				nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1624 				prev_mtr_id = id;
1625 				nix_mtr_chain_update(eth_dev, cur_mtr_id,
1626 						     prev_mtr_id, next_mtr_id);
1627 			} else {
1628 				if (mtr->level == 1) {
1629 					mtr->prev_cnt++;
1630 					prev_mtr_id = id;
1631 					nix_mtr_chain_update(eth_dev,
1632 						cur_mtr_id, prev_mtr_id,
1633 						next_mtr_id);
1634 
1635 					mtr->is_used = true;
1636 				} else {
1637 					return -EINVAL;
1638 				}
1639 			}
1640 			(*tree_level)++;
1641 			*next_id = next_mtr_id;
1642 			*prev_id = cur_mtr_id;
1643 			break;
1644 		case 2:
1645 			nix_mtr_chain_reset(eth_dev, id);
1646 			return -EINVAL;
1647 		}
1648 	} else {
1649 		switch (*tree_level) {
1650 		case 0:
1651 			mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1652 			if (mtr == NULL)
1653 				return -EINVAL;
1654 			if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1655 				nix_mtr_level_update(eth_dev, cur_mtr_id, 0);
1656 			} else {
1657 				if (mtr->level == 0)
1658 					mtr->is_used = true;
1659 				else
1660 					return -EINVAL;
1661 			}
1662 			break;
1663 		case 1:
1664 			mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1665 			if (mtr == NULL)
1666 				return -EINVAL;
1667 			if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1668 				nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1669 				prev_mtr_id = id;
1670 				nix_mtr_chain_update(eth_dev, cur_mtr_id,
1671 						     prev_mtr_id, -1);
1672 			} else {
1673 				if (mtr->level == 1) {
1674 					mtr->prev_cnt++;
1675 					prev_mtr_id = id;
1676 					nix_mtr_chain_update(eth_dev,
1677 							     cur_mtr_id,
1678 							     prev_mtr_id, -1);
1679 					mtr->is_used = true;
1680 				} else {
1681 					return -EINVAL;
1682 				}
1683 			}
1684 			break;
1685 		case 2:
1686 			mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1687 			if (mtr == NULL)
1688 				return -EINVAL;
1689 			if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1690 				nix_mtr_level_update(eth_dev, cur_mtr_id, 2);
1691 				prev_mtr_id = *prev_id;
1692 				nix_mtr_chain_update(eth_dev, cur_mtr_id,
1693 						     prev_mtr_id, -1);
1694 			} else {
1695 				if (mtr->level == 2) {
1696 					mtr->prev_cnt++;
1697 					prev_mtr_id = *prev_id;
1698 					nix_mtr_chain_update(eth_dev,
1699 							     cur_mtr_id,
1700 							     prev_mtr_id, -1);
1701 					mtr->is_used = true;
1702 				} else {
1703 					return -EINVAL;
1704 				}
1705 			}
1706 			break;
1707 		}
1708 		*next_id = 0xffff;
1709 	}
1710 
1711 	return 0;
1712 }
1713 
1714 int
nix_mtr_capabilities_init(struct rte_eth_dev * eth_dev)1715 nix_mtr_capabilities_init(struct rte_eth_dev *eth_dev)
1716 {
1717 	struct rte_mtr_capabilities capa;
1718 	struct rte_mtr_error error;
1719 
1720 	return cnxk_nix_mtr_capabilities_get(eth_dev, &capa, &error);
1721 }
1722