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