net/softnic: check meter packet mode
[dpdk.git] / drivers / net / softnic / rte_eth_softnic_meter.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation
3  */
4
5 #include <stdint.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9 #include <rte_mtr.h>
10 #include <rte_mtr_driver.h>
11
12 #include "rte_eth_softnic_internals.h"
13
14 int
15 softnic_mtr_init(struct pmd_internals *p)
16 {
17         /* Initialize meter profiles list */
18         TAILQ_INIT(&p->mtr.meter_profiles);
19
20         /* Initialize MTR objects list */
21         TAILQ_INIT(&p->mtr.mtrs);
22
23         return 0;
24 }
25
26 void
27 softnic_mtr_free(struct pmd_internals *p)
28 {
29         /* Remove MTR objects */
30         for ( ; ; ) {
31                 struct softnic_mtr *m;
32
33                 m = TAILQ_FIRST(&p->mtr.mtrs);
34                 if (m == NULL)
35                         break;
36
37                 TAILQ_REMOVE(&p->mtr.mtrs, m, node);
38                 free(m);
39         }
40
41         /* Remove meter profiles */
42         for ( ; ; ) {
43                 struct softnic_mtr_meter_profile *mp;
44
45                 mp = TAILQ_FIRST(&p->mtr.meter_profiles);
46                 if (mp == NULL)
47                         break;
48
49                 TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
50                 free(mp);
51         }
52 }
53
54 struct softnic_mtr_meter_profile *
55 softnic_mtr_meter_profile_find(struct pmd_internals *p,
56         uint32_t meter_profile_id)
57 {
58         struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
59         struct softnic_mtr_meter_profile *mp;
60
61         TAILQ_FOREACH(mp, mpl, node)
62                 if (meter_profile_id == mp->meter_profile_id)
63                         return mp;
64
65         return NULL;
66 }
67
68 enum rte_table_action_policer
69 softnic_table_action_policer(enum rte_mtr_policer_action action)
70 {
71         switch (action) {
72         case MTR_POLICER_ACTION_COLOR_GREEN:
73                 return RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
74
75                 /* FALLTHROUGH */
76         case MTR_POLICER_ACTION_COLOR_YELLOW:
77                 return RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
78
79                 /* FALLTHROUGH */
80         case MTR_POLICER_ACTION_COLOR_RED:
81                 return RTE_TABLE_ACTION_POLICER_COLOR_RED;
82
83                 /* FALLTHROUGH */
84         default:
85                 return RTE_TABLE_ACTION_POLICER_DROP;
86         }
87 }
88
89 static int
90 meter_profile_check(struct rte_eth_dev *dev,
91         uint32_t meter_profile_id,
92         struct rte_mtr_meter_profile *profile,
93         struct rte_mtr_error *error)
94 {
95         struct pmd_internals *p = dev->data->dev_private;
96         struct softnic_mtr_meter_profile *mp;
97
98         /* Meter profile ID must be valid. */
99         if (meter_profile_id == UINT32_MAX)
100                 return -rte_mtr_error_set(error,
101                         EINVAL,
102                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
103                         NULL,
104                         "Meter profile id not valid");
105
106         /* Meter profile must not exist. */
107         mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
108         if (mp)
109                 return -rte_mtr_error_set(error,
110                         EEXIST,
111                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
112                         NULL,
113                         "Meter prfile already exists");
114
115         /* Profile must not be NULL. */
116         if (profile == NULL)
117                 return -rte_mtr_error_set(error,
118                         EINVAL,
119                         RTE_MTR_ERROR_TYPE_METER_PROFILE,
120                         NULL,
121                         "profile null");
122
123         /* Traffic metering algorithm : TRTCM_RFC2698 */
124         if (profile->alg != RTE_MTR_TRTCM_RFC2698)
125                 return -rte_mtr_error_set(error,
126                         EINVAL,
127                         RTE_MTR_ERROR_TYPE_METER_PROFILE,
128                         NULL,
129                         "Metering alg not supported");
130
131         /* Not support packet mode, just support byte mode. */
132         if (profile->packet_mode)
133                 return -rte_mtr_error_set(error,
134                         EINVAL,
135                         RTE_MTR_ERROR_TYPE_METER_PROFILE_PACKET_MODE,
136                         NULL,
137                         "Meter packet mode not supported");
138
139         return 0;
140 }
141
142 /* MTR meter profile add */
143 static int
144 pmd_mtr_meter_profile_add(struct rte_eth_dev *dev,
145         uint32_t meter_profile_id,
146         struct rte_mtr_meter_profile *profile,
147         struct rte_mtr_error *error)
148 {
149         struct pmd_internals *p = dev->data->dev_private;
150         struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
151         struct softnic_mtr_meter_profile *mp;
152         int status;
153
154         /* Check input params */
155         status = meter_profile_check(dev, meter_profile_id, profile, error);
156         if (status)
157                 return status;
158
159         /* Memory allocation */
160         mp = calloc(1, sizeof(struct softnic_mtr_meter_profile));
161         if (mp == NULL)
162                 return -rte_mtr_error_set(error,
163                         ENOMEM,
164                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
165                         NULL,
166                         "Memory alloc failed");
167
168         /* Fill in */
169         mp->meter_profile_id = meter_profile_id;
170         memcpy(&mp->params, profile, sizeof(mp->params));
171
172         /* Add to list */
173         TAILQ_INSERT_TAIL(mpl, mp, node);
174
175         return 0;
176 }
177
178 /* MTR meter profile delete */
179 static int
180 pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,
181         uint32_t meter_profile_id,
182         struct rte_mtr_error *error)
183 {
184         struct pmd_internals *p = dev->data->dev_private;
185         struct softnic_mtr_meter_profile *mp;
186
187         /* Meter profile must exist */
188         mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
189         if (mp == NULL)
190                 return -rte_mtr_error_set(error,
191                         EINVAL,
192                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
193                         NULL,
194                         "Meter profile id invalid");
195
196         /* Check unused */
197         if (mp->n_users)
198                 return -rte_mtr_error_set(error,
199                         EBUSY,
200                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
201                         NULL,
202                         "Meter profile in use");
203
204         /* Remove from list */
205         TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
206         free(mp);
207
208         return 0;
209 }
210
211 struct softnic_mtr *
212 softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
213 {
214         struct softnic_mtr_list *ml = &p->mtr.mtrs;
215         struct softnic_mtr *m;
216
217         TAILQ_FOREACH(m, ml, node)
218                 if (m->mtr_id == mtr_id)
219                         return m;
220
221         return NULL;
222 }
223
224
225 static int
226 mtr_check(struct pmd_internals *p,
227         uint32_t mtr_id,
228         struct rte_mtr_params *params,
229         int shared,
230         struct rte_mtr_error *error)
231 {
232         /* MTR id valid  */
233         if (softnic_mtr_find(p, mtr_id))
234                 return -rte_mtr_error_set(error,
235                         EEXIST,
236                         RTE_MTR_ERROR_TYPE_MTR_ID,
237                         NULL,
238                         "MTR object already exists");
239
240         /* MTR params must not be NULL */
241         if (params == NULL)
242                 return -rte_mtr_error_set(error,
243                         EINVAL,
244                         RTE_MTR_ERROR_TYPE_MTR_PARAMS,
245                         NULL,
246                         "MTR object params null");
247
248         /* Previous meter color not supported */
249         if (params->use_prev_mtr_color)
250                 return -rte_mtr_error_set(error,
251                         EINVAL,
252                         RTE_MTR_ERROR_TYPE_MTR_PARAMS,
253                         NULL,
254                         "Previous meter color not supported");
255
256         /* Shared MTR object not supported */
257         if (shared)
258                 return -rte_mtr_error_set(error,
259                         EINVAL,
260                         RTE_MTR_ERROR_TYPE_SHARED,
261                         NULL,
262                         "Shared MTR object not supported");
263
264         return 0;
265 }
266
267 /* MTR object create */
268 static int
269 pmd_mtr_create(struct rte_eth_dev *dev,
270         uint32_t mtr_id,
271         struct rte_mtr_params *params,
272         int shared,
273         struct rte_mtr_error *error)
274 {
275         struct pmd_internals *p = dev->data->dev_private;
276         struct softnic_mtr_list *ml = &p->mtr.mtrs;
277         struct softnic_mtr_meter_profile *mp;
278         struct softnic_mtr *m;
279         int status;
280
281         /* Check parameters */
282         status = mtr_check(p, mtr_id, params, shared, error);
283         if (status)
284                 return status;
285
286         /* Meter profile must exist */
287         mp = softnic_mtr_meter_profile_find(p, params->meter_profile_id);
288         if (mp == NULL)
289                 return -rte_mtr_error_set(error,
290                         EINVAL,
291                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
292                         NULL,
293                         "Meter profile id not valid");
294
295         /* Memory allocation */
296         m = calloc(1, sizeof(struct softnic_mtr));
297         if (m == NULL)
298                 return -rte_mtr_error_set(error,
299                         ENOMEM,
300                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
301                         NULL,
302                         "Memory alloc failed");
303
304         /* Fill in */
305         m->mtr_id = mtr_id;
306         memcpy(&m->params, params, sizeof(m->params));
307
308         /* Add to list */
309         TAILQ_INSERT_TAIL(ml, m, node);
310
311         /* Update dependencies */
312         mp->n_users++;
313
314         return 0;
315 }
316
317 /* MTR object destroy */
318 static int
319 pmd_mtr_destroy(struct rte_eth_dev *dev,
320         uint32_t mtr_id,
321         struct rte_mtr_error *error)
322 {
323         struct pmd_internals *p = dev->data->dev_private;
324         struct softnic_mtr_list *ml = &p->mtr.mtrs;
325         struct softnic_mtr_meter_profile *mp;
326         struct softnic_mtr *m;
327
328         /* MTR object must exist */
329         m = softnic_mtr_find(p, mtr_id);
330         if (m == NULL)
331                 return -rte_mtr_error_set(error,
332                         EEXIST,
333                         RTE_MTR_ERROR_TYPE_MTR_ID,
334                         NULL,
335                         "MTR object id not valid");
336
337         /* MTR object must not have any owner */
338         if (m->flow != NULL)
339                 return -rte_mtr_error_set(error,
340                         EINVAL,
341                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
342                         NULL,
343                         "MTR object is being used");
344
345         /* Get meter profile */
346         mp = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
347         if (mp == NULL)
348                 return -rte_mtr_error_set(error,
349                         EINVAL,
350                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
351                         NULL,
352                         "MTR object meter profile invalid");
353
354         /* Update dependencies */
355         mp->n_users--;
356
357         /* Remove from list */
358         TAILQ_REMOVE(ml, m, node);
359         free(m);
360
361         return 0;
362 }
363
364 /* MTR object meter profile update */
365 static int
366 pmd_mtr_meter_profile_update(struct rte_eth_dev *dev,
367         uint32_t mtr_id,
368         uint32_t meter_profile_id,
369         struct rte_mtr_error *error)
370 {
371         struct pmd_internals *p = dev->data->dev_private;
372         struct softnic_mtr_meter_profile *mp_new, *mp_old;
373         struct softnic_mtr *m;
374         int status;
375
376         /* MTR object id must be valid */
377         m = softnic_mtr_find(p, mtr_id);
378         if (m == NULL)
379                 return -rte_mtr_error_set(error,
380                         EEXIST,
381                         RTE_MTR_ERROR_TYPE_MTR_ID,
382                         NULL,
383                         "MTR object id not valid");
384
385         /* Meter profile id must be valid */
386         mp_new = softnic_mtr_meter_profile_find(p, meter_profile_id);
387         if (mp_new == NULL)
388                 return -rte_mtr_error_set(error,
389                         EINVAL,
390                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
391                         NULL,
392                         "Meter profile not valid");
393
394         /* MTR object already set to meter profile id */
395         if (m->params.meter_profile_id == meter_profile_id)
396                 return 0;
397
398         /*  MTR object owner table update */
399         if (m->flow) {
400                 uint32_t table_id = m->flow->table_id;
401                 struct softnic_table *table = &m->flow->pipeline->table[table_id];
402                 struct softnic_table_rule_action action;
403
404                 if (!softnic_pipeline_table_meter_profile_find(table,
405                         meter_profile_id)) {
406                         struct rte_table_action_meter_profile profile;
407
408                         memset(&profile, 0, sizeof(profile));
409
410                         profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
411                         profile.trtcm.cir = mp_new->params.trtcm_rfc2698.cir;
412                         profile.trtcm.pir = mp_new->params.trtcm_rfc2698.pir;
413                         profile.trtcm.cbs = mp_new->params.trtcm_rfc2698.cbs;
414                         profile.trtcm.pbs = mp_new->params.trtcm_rfc2698.pbs;
415
416                         /* Add meter profile to pipeline table */
417                         status = softnic_pipeline_table_mtr_profile_add(p,
418                                         m->flow->pipeline->name,
419                                         table_id,
420                                         meter_profile_id,
421                                         &profile);
422                         if (status)
423                                 return -rte_mtr_error_set(error,
424                                         EINVAL,
425                                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
426                                         NULL,
427                                         "Table meter profile add failed");
428                 }
429
430                 /* Set meter action */
431                 memcpy(&action, &m->flow->action, sizeof(action));
432
433                 action.mtr.mtr[0].meter_profile_id = meter_profile_id;
434
435                 /* Re-add rule */
436                 status = softnic_pipeline_table_rule_add(p,
437                         m->flow->pipeline->name,
438                         table_id,
439                         &m->flow->match,
440                         &action,
441                         &m->flow->data);
442                 if (status)
443                         return -rte_mtr_error_set(error,
444                                 EINVAL,
445                                 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
446                                 NULL,
447                                 "Pipeline table rule add failed");
448
449                 /* Flow: update meter action */
450                 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
451         }
452
453         mp_old = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
454
455         /* Meter: Set meter profile */
456         m->params.meter_profile_id = meter_profile_id;
457
458         /* Update dependencies*/
459         mp_old->n_users--;
460         mp_new->n_users++;
461
462         return 0;
463 }
464
465 /* MTR object meter DSCP table update */
466 static int
467 pmd_mtr_meter_dscp_table_update(struct rte_eth_dev *dev,
468         uint32_t mtr_id,
469         enum rte_color *dscp_table,
470         struct rte_mtr_error *error)
471 {
472         struct pmd_internals *p = dev->data->dev_private;
473         struct rte_table_action_dscp_table dt;
474         struct pipeline *pipeline;
475         struct softnic_table *table;
476         struct softnic_mtr *m;
477         uint32_t table_id, i;
478         int status;
479
480         /* MTR object id must be valid */
481         m = softnic_mtr_find(p, mtr_id);
482         if (m == NULL)
483                 return -rte_mtr_error_set(error,
484                         EEXIST,
485                         RTE_MTR_ERROR_TYPE_MTR_ID,
486                         NULL,
487                         "MTR object id not valid");
488
489         /* MTR object owner valid? */
490         if (m->flow == NULL)
491                 return 0;
492
493         pipeline = m->flow->pipeline;
494         table_id = m->flow->table_id;
495         table = &pipeline->table[table_id];
496
497         memcpy(&dt, &table->dscp_table, sizeof(dt));
498         for (i = 0; i < RTE_DIM(dt.entry); i++)
499                 dt.entry[i].color = (enum rte_color)dscp_table[i];
500
501         /* Update table */
502         status = softnic_pipeline_table_dscp_table_update(p,
503                         pipeline->name,
504                         table_id,
505                         UINT64_MAX,
506                         &dt);
507         if (status)
508                 return -rte_mtr_error_set(error,
509                         EINVAL,
510                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
511                         NULL,
512                         "Table action dscp table update failed");
513
514         return 0;
515 }
516
517 /* MTR object policer action update */
518 static int
519 pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,
520         uint32_t mtr_id,
521         uint32_t action_mask,
522         enum rte_mtr_policer_action *actions,
523         struct rte_mtr_error *error)
524 {
525         struct pmd_internals *p = dev->data->dev_private;
526         struct softnic_mtr *m;
527         uint32_t i;
528         int status;
529
530         /* MTR object id must be valid */
531         m = softnic_mtr_find(p, mtr_id);
532         if (m == NULL)
533                 return -rte_mtr_error_set(error,
534                         EEXIST,
535                         RTE_MTR_ERROR_TYPE_MTR_ID,
536                         NULL,
537                         "MTR object id not valid");
538
539         /* Valid policer actions */
540         if (actions == NULL)
541                 return -rte_mtr_error_set(error,
542                         EINVAL,
543                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
544                         NULL,
545                         "Invalid actions");
546
547         for (i = 0; i < RTE_COLORS; i++) {
548                 if (action_mask & (1 << i)) {
549                         if (actions[i] != MTR_POLICER_ACTION_COLOR_GREEN  &&
550                                 actions[i] != MTR_POLICER_ACTION_COLOR_YELLOW &&
551                                 actions[i] != MTR_POLICER_ACTION_COLOR_RED &&
552                                 actions[i] != MTR_POLICER_ACTION_DROP) {
553                                 return -rte_mtr_error_set(error,
554                                         EINVAL,
555                                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
556                                         NULL,
557                                         " Invalid action value");
558                         }
559                 }
560         }
561
562         /* MTR object owner valid? */
563         if (m->flow) {
564                 struct pipeline *pipeline = m->flow->pipeline;
565                 struct softnic_table *table = &pipeline->table[m->flow->table_id];
566                 struct softnic_table_rule_action action;
567
568                 memcpy(&action, &m->flow->action, sizeof(action));
569
570                 /* Set action */
571                 for (i = 0; i < RTE_COLORS; i++)
572                         if (action_mask & (1 << i))
573                                 action.mtr.mtr[0].policer[i] =
574                                         softnic_table_action_policer(actions[i]);
575
576                 /* Re-add the rule */
577                 status = softnic_pipeline_table_rule_add(p,
578                         pipeline->name,
579                         m->flow->table_id,
580                         &m->flow->match,
581                         &action,
582                         &m->flow->data);
583                 if (status)
584                         return -rte_mtr_error_set(error,
585                                 EINVAL,
586                                 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
587                                 NULL,
588                                 "Pipeline table rule re-add failed");
589
590                 /* Flow: Update meter action */
591                 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
592
593                 /* Reset the meter stats */
594                 rte_table_action_meter_read(table->a, m->flow->data,
595                         1, NULL, 1);
596         }
597
598         /* Meter: Update policer actions */
599         for (i = 0; i < RTE_COLORS; i++)
600                 if (action_mask & (1 << i))
601                         m->params.action[i] = actions[i];
602
603         return 0;
604 }
605
606 #define MTR_STATS_PKTS_DEFAULT (RTE_MTR_STATS_N_PKTS_GREEN | \
607                                 RTE_MTR_STATS_N_PKTS_YELLOW | \
608                                 RTE_MTR_STATS_N_PKTS_RED | \
609                                 RTE_MTR_STATS_N_PKTS_DROPPED)
610
611 #define MTR_STATS_BYTES_DEFAULT (RTE_MTR_STATS_N_BYTES_GREEN | \
612                                 RTE_MTR_STATS_N_BYTES_YELLOW | \
613                                 RTE_MTR_STATS_N_BYTES_RED | \
614                                 RTE_MTR_STATS_N_BYTES_DROPPED)
615
616 /* MTR object stats read */
617 static void
618 mtr_stats_convert(struct softnic_mtr *m,
619         struct rte_table_action_mtr_counters_tc *in,
620         struct rte_mtr_stats *out,
621         uint64_t *out_mask)
622 {
623         memset(&out, 0, sizeof(out));
624         *out_mask = 0;
625
626         if (in->n_packets_valid) {
627                 uint32_t i;
628
629                 for (i = 0; i < RTE_COLORS; i++) {
630                         if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_GREEN)
631                                 out->n_pkts[RTE_COLOR_GREEN] += in->n_packets[i];
632
633                         if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_YELLOW)
634                                 out->n_pkts[RTE_COLOR_YELLOW] += in->n_packets[i];
635
636                         if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_RED)
637                                 out->n_pkts[RTE_COLOR_RED] += in->n_packets[i];
638
639                         if (m->params.action[i] == MTR_POLICER_ACTION_DROP)
640                                 out->n_pkts_dropped += in->n_packets[i];
641                 }
642
643                 *out_mask |= MTR_STATS_PKTS_DEFAULT;
644         }
645
646         if (in->n_bytes_valid) {
647                 uint32_t i;
648
649                 for (i = 0; i < RTE_COLORS; i++) {
650                         if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_GREEN)
651                                 out->n_bytes[RTE_COLOR_GREEN] += in->n_bytes[i];
652
653                         if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_YELLOW)
654                                 out->n_bytes[RTE_COLOR_YELLOW] += in->n_bytes[i];
655
656                         if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_RED)
657                                 out->n_bytes[RTE_COLOR_RED] += in->n_bytes[i];
658
659                         if (m->params.action[i] == MTR_POLICER_ACTION_DROP)
660                                 out->n_bytes_dropped += in->n_bytes[i];
661                 }
662
663                 *out_mask |= MTR_STATS_BYTES_DEFAULT;
664         }
665 }
666
667 /* MTR object stats read */
668 static int
669 pmd_mtr_stats_read(struct rte_eth_dev *dev,
670         uint32_t mtr_id,
671         struct rte_mtr_stats *stats,
672         uint64_t *stats_mask,
673         int clear,
674         struct rte_mtr_error *error)
675 {
676         struct pmd_internals *p = dev->data->dev_private;
677         struct rte_table_action_mtr_counters counters;
678         struct pipeline *pipeline;
679         struct softnic_table *table;
680         struct softnic_mtr *m;
681         int status;
682
683         /* MTR object id must be valid */
684         m = softnic_mtr_find(p, mtr_id);
685         if (m == NULL)
686                 return -rte_mtr_error_set(error,
687                         EEXIST,
688                         RTE_MTR_ERROR_TYPE_MTR_ID,
689                         NULL,
690                         "MTR object id not valid");
691
692         /* MTR meter object owner valid? */
693         if (m->flow == NULL) {
694                 if (stats != NULL)
695                         memset(stats, 0, sizeof(*stats));
696
697                 if (stats_mask)
698                         *stats_mask = MTR_STATS_PKTS_DEFAULT |
699                                 MTR_STATS_BYTES_DEFAULT;
700
701                 return 0;
702         }
703
704         pipeline = m->flow->pipeline;
705         table = &pipeline->table[m->flow->table_id];
706
707         /* Meter stats read. */
708         status = rte_table_action_meter_read(table->a,
709                 m->flow->data,
710                 1,
711                 &counters,
712                 clear);
713         if (status)
714                 return -rte_mtr_error_set(error,
715                         EINVAL,
716                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
717                         NULL,
718                         "Meter stats read failed");
719
720         /* Stats format conversion. */
721         if (stats || stats_mask) {
722                 struct rte_mtr_stats s;
723                 uint64_t s_mask = 0;
724
725                 mtr_stats_convert(m,
726                         &counters.stats[0],
727                         &s,
728                         &s_mask);
729
730                 if (stats)
731                         memcpy(stats, &s, sizeof(*stats));
732
733                 if (stats_mask)
734                         *stats_mask = s_mask;
735         }
736
737         return 0;
738 }
739
740 const struct rte_mtr_ops pmd_mtr_ops = {
741         .capabilities_get = NULL,
742
743         .meter_profile_add = pmd_mtr_meter_profile_add,
744         .meter_profile_delete = pmd_mtr_meter_profile_delete,
745
746         .create = pmd_mtr_create,
747         .destroy = pmd_mtr_destroy,
748         .meter_enable = NULL,
749         .meter_disable = NULL,
750
751         .meter_profile_update = pmd_mtr_meter_profile_update,
752         .meter_dscp_table_update = pmd_mtr_meter_dscp_table_update,
753         .policer_actions_update = pmd_mtr_policer_actions_update,
754         .stats_update = NULL,
755
756         .stats_read = pmd_mtr_stats_read,
757 };