6d950fd177e178ab42aba4ebb335e25e2e3cb13e
[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 static const enum roc_nix_bpf_level_flag lvl_map[] = {ROC_NIX_BPF_LEVEL_F_LEAF,
12                                                       ROC_NIX_BPF_LEVEL_F_MID,
13                                                       ROC_NIX_BPF_LEVEL_F_TOP};
14
15 static struct rte_mtr_capabilities mtr_capa = {
16         .n_max = NIX_MTR_COUNT_MAX,
17         .n_shared_max = NIX_MTR_COUNT_PER_FLOW,
18         /* .identical = , */
19         .shared_identical = true,
20         /* .shared_n_flows_per_mtr_max = ,*/
21         .chaining_n_mtrs_per_flow_max = NIX_MTR_COUNT_PER_FLOW,
22         .chaining_use_prev_mtr_color_supported = true,
23         .chaining_use_prev_mtr_color_enforced = true,
24         .meter_srtcm_rfc2697_n_max = NIX_MTR_COUNT_MAX,
25         .meter_trtcm_rfc2698_n_max = NIX_MTR_COUNT_MAX,
26         .meter_trtcm_rfc4115_n_max = NIX_MTR_COUNT_MAX,
27         .meter_rate_max = NIX_BPF_RATE_MAX / 8, /* Bytes per second */
28         .meter_policy_n_max = NIX_MTR_COUNT_MAX,
29         .color_aware_srtcm_rfc2697_supported = true,
30         .color_aware_trtcm_rfc2698_supported = true,
31         .color_aware_trtcm_rfc4115_supported = true,
32         .srtcm_rfc2697_byte_mode_supported = true,
33         .srtcm_rfc2697_packet_mode_supported = true,
34         .trtcm_rfc2698_byte_mode_supported = true,
35         .trtcm_rfc2698_packet_mode_supported = true,
36         .trtcm_rfc4115_byte_mode_supported = true,
37         .trtcm_rfc4115_packet_mode_supported = true,
38         .stats_mask = RTE_MTR_STATS_N_PKTS_GREEN | RTE_MTR_STATS_N_PKTS_YELLOW |
39                       RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_PKTS_DROPPED |
40                       RTE_MTR_STATS_N_BYTES_GREEN |
41                       RTE_MTR_STATS_N_BYTES_YELLOW | RTE_MTR_STATS_N_BYTES_RED |
42                       RTE_MTR_STATS_N_BYTES_DROPPED};
43
44 static struct cnxk_meter_node *
45 nix_mtr_find(struct cnxk_eth_dev *dev, uint32_t meter_id)
46 {
47         struct cnxk_mtr *fms = &dev->mtr;
48         struct cnxk_meter_node *fm;
49
50         TAILQ_FOREACH(fm, fms, next)
51                 if (meter_id == fm->id)
52                         return fm;
53         return NULL;
54 }
55
56 static struct cnxk_mtr_profile_node *
57 nix_mtr_profile_find(struct cnxk_eth_dev *dev, uint32_t profile_id)
58 {
59         struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
60         struct cnxk_mtr_profile_node *fmp;
61
62         TAILQ_FOREACH(fmp, fmps, next)
63                 if (profile_id == fmp->id)
64                         return fmp;
65
66         return NULL;
67 }
68
69 static struct cnxk_mtr_policy_node *
70 nix_mtr_policy_find(struct cnxk_eth_dev *dev, uint32_t meter_policy_id)
71 {
72         struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
73         struct cnxk_mtr_policy_node *fmp;
74
75         TAILQ_FOREACH(fmp, fmps, next)
76                 if (meter_policy_id == fmp->id)
77                         return fmp;
78         return NULL;
79 }
80
81 static int
82 nix_mtr_profile_validate(struct cnxk_eth_dev *dev, uint32_t profile_id,
83                          struct rte_mtr_meter_profile *profile,
84                          struct rte_mtr_error *error)
85 {
86         int rc = 0;
87
88         PLT_SET_USED(dev);
89
90         if (profile == NULL)
91                 return -rte_mtr_error_set(error, EINVAL,
92                                           RTE_MTR_ERROR_TYPE_METER_PROFILE,
93                                           NULL, "Meter profile is null.");
94
95         if (profile_id == UINT32_MAX)
96                 return -rte_mtr_error_set(error, EINVAL,
97                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
98                                           NULL, "Meter profile id not valid.");
99
100         switch (profile->alg) {
101         case RTE_MTR_SRTCM_RFC2697:
102                 if (profile->srtcm_rfc2697.cir > mtr_capa.meter_rate_max)
103                         rc = -rte_mtr_error_set(error, EINVAL,
104                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
105                                 "CIR exceeds max meter rate");
106
107                 if (profile->srtcm_rfc2697.cbs > NIX_BPF_BURST_MAX)
108                         rc = -rte_mtr_error_set(error, EINVAL,
109                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
110                                 "CBS exceeds max meter burst size");
111
112                 if (profile->srtcm_rfc2697.ebs > NIX_BPF_BURST_MAX)
113                         rc = -rte_mtr_error_set(error, EINVAL,
114                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
115                                 "EBS exceeds max meter burst size");
116                 break;
117
118         case RTE_MTR_TRTCM_RFC2698:
119                 if (profile->trtcm_rfc2698.cir > mtr_capa.meter_rate_max)
120                         rc = -rte_mtr_error_set(error, EINVAL,
121                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
122                                 "CIR exceeds max meter rate");
123
124                 if (profile->trtcm_rfc2698.pir > mtr_capa.meter_rate_max)
125                         rc = -rte_mtr_error_set(error, EINVAL,
126                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
127                                 "PIR exceeds max meter rate");
128
129                 if (profile->trtcm_rfc2698.cbs > NIX_BPF_BURST_MAX)
130                         rc = -rte_mtr_error_set(error, EINVAL,
131                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
132                                 "CBS exceeds max meter burst size");
133
134                 if (profile->trtcm_rfc2698.pbs > NIX_BPF_BURST_MAX)
135                         rc = -rte_mtr_error_set(error, EINVAL,
136                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
137                                 "PBS exceeds max meter burst size");
138                 break;
139
140         case RTE_MTR_TRTCM_RFC4115:
141                 if ((profile->trtcm_rfc4115.cir + profile->trtcm_rfc4115.eir) >
142                     mtr_capa.meter_rate_max)
143                         rc = -rte_mtr_error_set(error, EINVAL,
144                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
145                                 "PIR + EIR exceeds max rate");
146
147                 if (profile->trtcm_rfc4115.cbs > NIX_BPF_BURST_MAX)
148                         rc = -rte_mtr_error_set(error, EINVAL,
149                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
150                                 "CBS exceeds max meter burst size");
151
152                 if (profile->trtcm_rfc4115.ebs > NIX_BPF_BURST_MAX)
153                         rc = -rte_mtr_error_set(error, EINVAL,
154                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
155                                 "PBS exceeds max meter burst size");
156                 break;
157
158         default:
159                 rc = -rte_mtr_error_set(error, EINVAL,
160                                         RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
161                                         "alg is invalid");
162                 break;
163         }
164
165         return rc;
166 }
167
168 static int
169 cnxk_nix_mtr_capabilities_get(struct rte_eth_dev *dev,
170                               struct rte_mtr_capabilities *capa,
171                               struct rte_mtr_error *error)
172 {
173         RTE_SET_USED(dev);
174
175         if (!capa)
176                 return -rte_mtr_error_set(error, EINVAL,
177                                           RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
178                                           "NULL input parameter");
179         *capa = mtr_capa;
180         return 0;
181 }
182
183 static int
184 cnxk_nix_mtr_profile_add(struct rte_eth_dev *eth_dev, uint32_t profile_id,
185                          struct rte_mtr_meter_profile *profile,
186                          struct rte_mtr_error *error)
187 {
188         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
189         struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
190         struct cnxk_mtr_profile_node *fmp;
191         int ret;
192
193         /* Check input params. */
194         ret = nix_mtr_profile_validate(dev, profile_id, profile, error);
195         if (ret)
196                 return ret;
197
198         fmp = nix_mtr_profile_find(dev, profile_id);
199         if (fmp) {
200                 return -rte_mtr_error_set(error, EEXIST,
201                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
202                                           NULL, "Profile already exist");
203         }
204
205         fmp = plt_zmalloc(sizeof(struct cnxk_mtr_profile_node), ROC_ALIGN);
206         if (fmp == NULL)
207                 return -rte_mtr_error_set(error, ENOMEM,
208                                           RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
209                                           "Meter profile memory "
210                                           "alloc failed.");
211
212         fmp->id = profile_id;
213         fmp->profile = *profile;
214
215         TAILQ_INSERT_TAIL(fmps, fmp, next);
216
217         return 0;
218 }
219
220 static int
221 cnxk_nix_mtr_profile_delete(struct rte_eth_dev *eth_dev, uint32_t profile_id,
222                             struct rte_mtr_error *error)
223 {
224         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
225         struct cnxk_mtr_profile_node *fmp;
226
227         if (profile_id == UINT32_MAX)
228                 return -rte_mtr_error_set(error, EINVAL,
229                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
230                                           NULL, "Meter profile id not valid.");
231
232         fmp = nix_mtr_profile_find(dev, profile_id);
233         if (fmp == NULL)
234                 return -rte_mtr_error_set(error, ENOENT,
235                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
236                                           &profile_id,
237                                           "Meter profile is invalid.");
238
239         if (fmp->ref_cnt)
240                 return -rte_mtr_error_set(error, EBUSY,
241                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
242                                           NULL, "Meter profile is in use.");
243
244         TAILQ_REMOVE(&dev->mtr_profiles, fmp, next);
245         plt_free(fmp);
246         return 0;
247 }
248
249 static int
250 cnxk_nix_mtr_policy_validate(struct rte_eth_dev *dev,
251                              struct rte_mtr_meter_policy_params *policy,
252                              struct rte_mtr_error *error)
253 {
254         static const char *const action_color[] = {"Green", "Yellow", "Red"};
255         bool supported[RTE_COLORS] = {false, false, false};
256         const struct rte_flow_action *action;
257         char message[1024];
258         uint32_t i;
259
260         RTE_SET_USED(dev);
261
262         if (!policy)
263                 return 0; /* Nothing to be validated */
264
265         for (i = 0; i < RTE_COLORS; i++) {
266                 if (policy->actions[i]) {
267                         for (action = policy->actions[i];
268                              action->type != RTE_FLOW_ACTION_TYPE_END;
269                              action++) {
270                                 if (action->type == RTE_FLOW_ACTION_TYPE_METER)
271                                         supported[i] = true;
272
273                                 if (action->type == RTE_FLOW_ACTION_TYPE_DROP)
274                                         supported[i] = true;
275
276                                 if (!supported[i]) {
277                                         sprintf(message,
278                                                 "%s action is not valid",
279                                                 action_color[i]);
280                                         return -rte_mtr_error_set(error,
281                                           ENOTSUP,
282                                           RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
283                                           message);
284                                 }
285                         }
286                 } else {
287                         sprintf(message, "%s action is null", action_color[i]);
288                         return -rte_mtr_error_set(error, EINVAL,
289                                 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
290                                 message);
291                 }
292         }
293
294         return 0;
295 }
296
297 static void
298 cnxk_fill_policy_actions(struct cnxk_mtr_policy_node *fmp,
299                          struct rte_mtr_meter_policy_params *policy)
300
301 {
302         const struct rte_flow_action_meter *mtr;
303         const struct rte_flow_action *action;
304         int i;
305
306         for (i = 0; i < RTE_COLORS; i++) {
307                 if (policy->actions[i]) {
308                         for (action = policy->actions[i];
309                              action->type != RTE_FLOW_ACTION_TYPE_END;
310                              action++) {
311                                 if (action->type ==
312                                     RTE_FLOW_ACTION_TYPE_METER) {
313                                         fmp->actions[i].action_fate =
314                                                 action->type;
315                                         mtr = (const struct
316                                                rte_flow_action_meter *)
317                                                       action->conf;
318                                         fmp->actions[i].mtr_id = mtr->mtr_id;
319                                 }
320
321                                 if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
322                                         fmp->actions[i].action_fate =
323                                                 action->type;
324                                 }
325                         }
326                 }
327         }
328 }
329
330 static int
331 cnxk_nix_mtr_policy_add(struct rte_eth_dev *eth_dev, uint32_t policy_id,
332                         struct rte_mtr_meter_policy_params *policy,
333                         struct rte_mtr_error *error)
334 {
335         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
336         struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
337         struct cnxk_mtr_policy_node *fmp;
338         int rc;
339
340         fmp = nix_mtr_policy_find(dev, policy_id);
341         if (fmp) {
342                 return -rte_mtr_error_set(error, EEXIST,
343                                           RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
344                                           NULL, "Policy already exist");
345         }
346
347         fmp = plt_zmalloc(sizeof(struct cnxk_mtr_policy_node), ROC_ALIGN);
348         if (fmp == NULL) {
349                 return -rte_mtr_error_set(error, ENOMEM,
350                                           RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
351                                           "Memory allocation failure");
352         } else {
353                 rc = cnxk_nix_mtr_policy_validate(eth_dev, policy, error);
354                 if (rc)
355                         goto exit;
356         }
357
358         fmp->id = policy_id;
359         cnxk_fill_policy_actions(fmp, policy);
360         TAILQ_INSERT_TAIL(fmps, fmp, next);
361         return 0;
362
363 exit:
364         plt_free(fmp);
365         return rc;
366 }
367
368 static int
369 cnxk_nix_mtr_policy_delete(struct rte_eth_dev *eth_dev, uint32_t policy_id,
370                            struct rte_mtr_error *error)
371 {
372         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
373         struct cnxk_mtr_policy_node *fmp;
374
375         fmp = nix_mtr_policy_find(dev, policy_id);
376         if (fmp == NULL) {
377                 return -rte_mtr_error_set(error, ENOENT,
378                                           RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
379                                           NULL, "No policy found");
380         }
381
382         if (fmp->ref_cnt)
383                 return -rte_mtr_error_set(error, EBUSY,
384                                           RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
385                                           NULL, "Meter policy is in use.");
386
387         TAILQ_REMOVE(&dev->mtr_policy, fmp, next);
388         plt_free(fmp);
389
390         return 0;
391 }
392
393 static int
394 cnxk_nix_mtr_create(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
395                     struct rte_mtr_params *params, int shared,
396                     struct rte_mtr_error *error)
397 {
398         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
399         struct cnxk_mtr_profile_node *profile;
400         struct cnxk_mtr_policy_node *policy;
401         struct cnxk_mtr *fm = &dev->mtr;
402         struct cnxk_meter_node *mtr;
403         int i;
404
405         RTE_SET_USED(shared);
406
407         if (params == NULL)
408                 return -rte_mtr_error_set(error, ENOENT,
409                                           RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
410                                           "Meter params are invalid.");
411
412         profile = nix_mtr_profile_find(dev, params->meter_profile_id);
413         if (profile == NULL)
414                 return -rte_mtr_error_set(error, ENOENT,
415                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
416                                           &params->meter_profile_id,
417                                           "Meter profile is invalid.");
418
419         policy = nix_mtr_policy_find(dev, params->meter_policy_id);
420         if (policy == NULL)
421                 return -rte_mtr_error_set(error, ENOENT,
422                                           RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
423                                           &params->meter_policy_id,
424                                           "Meter policy is invalid.");
425
426         mtr = nix_mtr_find(dev, mtr_id);
427         if (mtr) {
428                 return -rte_mtr_error_set(error, EEXIST,
429                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
430                                           "Meter already exist");
431         }
432
433         mtr = plt_zmalloc(sizeof(struct cnxk_meter_node), ROC_ALIGN);
434         if (mtr == NULL) {
435                 return -rte_mtr_error_set(error, ENOMEM,
436                                           RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
437                                           "Meter memory alloc failed.");
438         }
439
440         mtr->id = mtr_id;
441         mtr->profile = profile;
442         mtr->policy = policy;
443         mtr->params = *params;
444         mtr->bpf_id = ROC_NIX_BPF_ID_INVALID;
445         mtr->prev_cnt = 0;
446         for (i = 0; i < MAX_PRV_MTR_NODES; i++)
447                 mtr->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
448
449         mtr->next_id = ROC_NIX_BPF_ID_INVALID;
450         mtr->is_next = false;
451         mtr->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
452
453         if (params->dscp_table) {
454                 mtr->params.dscp_table =
455                         plt_zmalloc(ROC_NIX_BPF_PRE_COLOR_MAX, ROC_ALIGN);
456                 if (mtr->params.dscp_table == NULL) {
457                         plt_free(mtr);
458                         return -rte_mtr_error_set(error, ENOMEM,
459                                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
460                                         NULL, "Memory alloc failed.");
461                 }
462
463                 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
464                         mtr->params.dscp_table[i] = params->dscp_table[i];
465         }
466
467         profile->ref_cnt++;
468         policy->ref_cnt++;
469         TAILQ_INSERT_TAIL(fm, mtr, next);
470         return 0;
471 }
472
473 static int
474 cnxk_nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
475                      struct rte_mtr_error *error)
476 {
477         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
478         struct roc_nix_bpf_objs profs = {0};
479         struct cnxk_mtr *fm = &dev->mtr;
480         struct roc_nix *nix = &dev->nix;
481         struct cnxk_meter_node *mtr;
482         struct cnxk_meter_node *mid_mtr;
483         struct cnxk_meter_node *top_mtr;
484         int rc = 0;
485
486         mtr = nix_mtr_find(dev, mtr_id);
487         if (mtr == NULL) {
488                 return -rte_mtr_error_set(error, ENOENT,
489                                           RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
490                                           "Meter id is invalid.");
491         }
492
493         if (mtr->ref_cnt) {
494                 return -rte_mtr_error_set(error, EADDRINUSE,
495                                           RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
496                                           "Meter id in use.");
497         }
498
499         switch (lvl_map[mtr->level]) {
500         case ROC_NIX_BPF_LEVEL_F_LEAF:
501                 if (mtr->is_next) {
502                         rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
503                                                  mtr->bpf_id,
504                                                  ROC_NIX_BPF_ID_INVALID);
505                 }
506                 break;
507         case ROC_NIX_BPF_LEVEL_F_MID:
508                 while ((mtr->prev_cnt) + 1) {
509                         mid_mtr =
510                                 nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
511                         rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
512                                                  mid_mtr->bpf_id,
513                                                  ROC_NIX_BPF_ID_INVALID);
514                         mtr->prev_cnt--;
515                 }
516                 if (mtr->is_next) {
517                         rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
518                                                  mtr->bpf_id,
519                                                  ROC_NIX_BPF_ID_INVALID);
520                 }
521                 break;
522         case ROC_NIX_BPF_LEVEL_F_TOP:
523                 while (mtr->prev_cnt) {
524                         top_mtr =
525                                 nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
526                         rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
527                                                  top_mtr->bpf_id,
528                                                  ROC_NIX_BPF_ID_INVALID);
529                         mtr->prev_cnt--;
530                 }
531                 break;
532         default:
533                 return -rte_mtr_error_set(error, EINVAL,
534                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
535                                           "Invalid meter level");
536         }
537
538         if (rc)
539                 goto exit;
540
541         profs.level = mtr->level;
542         profs.count = 1;
543         profs.ids[0] = mtr->bpf_id;
544         rc = roc_nix_bpf_free(nix, &profs, 1);
545         if (rc)
546                 goto exit;
547
548         mtr->policy->ref_cnt--;
549         mtr->profile->ref_cnt--;
550         TAILQ_REMOVE(fm, mtr, next);
551         plt_free(mtr->params.dscp_table);
552         plt_free(mtr);
553
554 exit:
555         return rc;
556 }
557
558 const struct rte_mtr_ops nix_mtr_ops = {
559         .capabilities_get = cnxk_nix_mtr_capabilities_get,
560         .meter_profile_add = cnxk_nix_mtr_profile_add,
561         .meter_profile_delete = cnxk_nix_mtr_profile_delete,
562         .meter_policy_validate = cnxk_nix_mtr_policy_validate,
563         .meter_policy_add = cnxk_nix_mtr_policy_add,
564         .meter_policy_delete = cnxk_nix_mtr_policy_delete,
565         .create = cnxk_nix_mtr_create,
566         .destroy = cnxk_nix_mtr_destroy,
567 };
568
569 int
570 cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops)
571 {
572         RTE_SET_USED(dev);
573
574         *(const void **)ops = &nix_mtr_ops;
575         return 0;
576 }