1
2
3
4
5#include "cnxk_ethdev.h"
6#include <rte_mtr_driver.h>
7
8#define NIX_MTR_COUNT_MAX 73
9#define NIX_MTR_COUNT_PER_FLOW 3
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
26static 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
30static struct rte_mtr_capabilities mtr_capa = {
31 .n_shared_max = NIX_MTR_COUNT_PER_FLOW,
32
33 .shared_identical = true,
34
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
53static struct cnxk_meter_node *
54nix_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
65static struct cnxk_mtr_profile_node *
66nix_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
78static struct cnxk_mtr_policy_node *
79nix_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
90static int
91nix_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
177static int
178cnxk_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 = ð_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
222static int
223cnxk_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
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
259static int
260cnxk_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
288static int
289update_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 }
321notsup:
322 return -rte_mtr_error_set(error, ENOTSUP,
323 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, str);
324notvalid:
325 return -rte_mtr_error_set(error, EINVAL,
326 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, str);
327}
328
329static int
330cnxk_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;
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
368static void
369cnxk_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
401static int
402cnxk_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
434exit:
435 plt_free(fmp);
436 return rc;
437}
438
439static int
440cnxk_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
464static int
465cnxk_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 ¶ms->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 ¶ms->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
544static int
545cnxk_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
625exit:
626 return rc;
627}
628
629static int
630cnxk_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
658static int
659cnxk_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
687static int
688cnxk_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
733exit:
734 return rc;
735}
736
737static int
738cnxk_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
760static int
761cnxk_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
857exit:
858 return rc;
859}
860
861const 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
877int
878cnxk_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
886int
887nix_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
909int
910nix_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
930int
931nix_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
953int
954nix_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
979int
980nix_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
1014struct cnxk_meter_node *
1015nix_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
1027int
1028nix_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
1041static void
1042nix_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
1092static void
1093nix_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
1113int
1114nix_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
1120int
1121nix_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
1153int
1154nix_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
1269int
1270nix_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
1399int
1400nix_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