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