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