1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Intel Corporation
10 #include <rte_mtr_driver.h>
12 #include "rte_eth_softnic_internals.h"
15 softnic_mtr_init(struct pmd_internals *p)
17 /* Initialize meter profiles list */
18 TAILQ_INIT(&p->mtr.meter_profiles);
20 /* Initialize MTR objects list */
21 TAILQ_INIT(&p->mtr.mtrs);
27 softnic_mtr_free(struct pmd_internals *p)
29 /* Remove MTR objects */
31 struct softnic_mtr *m;
33 m = TAILQ_FIRST(&p->mtr.mtrs);
37 TAILQ_REMOVE(&p->mtr.mtrs, m, node);
41 /* Remove meter profiles */
43 struct softnic_mtr_meter_profile *mp;
45 mp = TAILQ_FIRST(&p->mtr.meter_profiles);
49 TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
54 struct softnic_mtr_meter_profile *
55 softnic_mtr_meter_profile_find(struct pmd_internals *p,
56 uint32_t meter_profile_id)
58 struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
59 struct softnic_mtr_meter_profile *mp;
61 TAILQ_FOREACH(mp, mpl, node)
62 if (meter_profile_id == mp->meter_profile_id)
68 enum rte_table_action_policer
69 softnic_table_action_policer(enum rte_mtr_policer_action action)
72 case MTR_POLICER_ACTION_COLOR_GREEN:
73 return RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
76 case MTR_POLICER_ACTION_COLOR_YELLOW:
77 return RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
80 case MTR_POLICER_ACTION_COLOR_RED:
81 return RTE_TABLE_ACTION_POLICER_COLOR_RED;
85 return RTE_TABLE_ACTION_POLICER_DROP;
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)
95 struct pmd_internals *p = dev->data->dev_private;
96 struct softnic_mtr_meter_profile *mp;
98 /* Meter profile ID must be valid. */
99 if (meter_profile_id == UINT32_MAX)
100 return -rte_mtr_error_set(error,
102 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
104 "Meter profile id not valid");
106 /* Meter profile must not exist. */
107 mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
109 return -rte_mtr_error_set(error,
111 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
113 "Meter prfile already exists");
115 /* Profile must not be NULL. */
117 return -rte_mtr_error_set(error,
119 RTE_MTR_ERROR_TYPE_METER_PROFILE,
123 /* Traffic metering algorithm : TRTCM_RFC2698 */
124 if (profile->alg != RTE_MTR_TRTCM_RFC2698)
125 return -rte_mtr_error_set(error,
127 RTE_MTR_ERROR_TYPE_METER_PROFILE,
129 "Metering alg not supported");
134 /* MTR meter profile add */
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)
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;
146 /* Check input params */
147 status = meter_profile_check(dev, meter_profile_id, profile, error);
151 /* Memory allocation */
152 mp = calloc(1, sizeof(struct softnic_mtr_meter_profile));
154 return -rte_mtr_error_set(error,
156 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
158 "Memory alloc failed");
161 mp->meter_profile_id = meter_profile_id;
162 memcpy(&mp->params, profile, sizeof(mp->params));
165 TAILQ_INSERT_TAIL(mpl, mp, node);
170 /* MTR meter profile delete */
172 pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,
173 uint32_t meter_profile_id,
174 struct rte_mtr_error *error)
176 struct pmd_internals *p = dev->data->dev_private;
177 struct softnic_mtr_meter_profile *mp;
179 /* Meter profile must exist */
180 mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
182 return -rte_mtr_error_set(error,
184 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
186 "Meter profile id invalid");
190 return -rte_mtr_error_set(error,
192 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
194 "Meter profile in use");
196 /* Remove from list */
197 TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
204 softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
206 struct softnic_mtr_list *ml = &p->mtr.mtrs;
207 struct softnic_mtr *m;
209 TAILQ_FOREACH(m, ml, node)
210 if (m->mtr_id == mtr_id)
218 mtr_check(struct pmd_internals *p,
220 struct rte_mtr_params *params,
222 struct rte_mtr_error *error)
225 if (softnic_mtr_find(p, mtr_id))
226 return -rte_mtr_error_set(error,
228 RTE_MTR_ERROR_TYPE_MTR_ID,
230 "MTR object already exists");
232 /* MTR params must not be NULL */
234 return -rte_mtr_error_set(error,
236 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
238 "MTR object params null");
240 /* Previous meter color not supported */
241 if (params->use_prev_mtr_color)
242 return -rte_mtr_error_set(error,
244 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
246 "Previous meter color not supported");
248 /* Shared MTR object not supported */
250 return -rte_mtr_error_set(error,
252 RTE_MTR_ERROR_TYPE_SHARED,
254 "Shared MTR object not supported");
259 /* MTR object create */
261 pmd_mtr_create(struct rte_eth_dev *dev,
263 struct rte_mtr_params *params,
265 struct rte_mtr_error *error)
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;
273 /* Check parameters */
274 status = mtr_check(p, mtr_id, params, shared, error);
278 /* Meter profile must exist */
279 mp = softnic_mtr_meter_profile_find(p, params->meter_profile_id);
281 return -rte_mtr_error_set(error,
283 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
285 "Meter profile id not valid");
287 /* Memory allocation */
288 m = calloc(1, sizeof(struct softnic_mtr));
290 return -rte_mtr_error_set(error,
292 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
294 "Memory alloc failed");
298 memcpy(&m->params, params, sizeof(m->params));
301 TAILQ_INSERT_TAIL(ml, m, node);
303 /* Update dependencies */
309 /* MTR object destroy */
311 pmd_mtr_destroy(struct rte_eth_dev *dev,
313 struct rte_mtr_error *error)
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;
320 /* MTR object must exist */
321 m = softnic_mtr_find(p, mtr_id);
323 return -rte_mtr_error_set(error,
325 RTE_MTR_ERROR_TYPE_MTR_ID,
327 "MTR object id not valid");
329 /* MTR object must not have any owner */
331 return -rte_mtr_error_set(error,
333 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
335 "MTR object is being used");
337 /* Get meter profile */
338 mp = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
340 return -rte_mtr_error_set(error,
342 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
344 "MTR object meter profile invalid");
346 /* Update dependencies */
349 /* Remove from list */
350 TAILQ_REMOVE(ml, m, node);
356 /* MTR object meter profile update */
358 pmd_mtr_meter_profile_update(struct rte_eth_dev *dev,
360 uint32_t meter_profile_id,
361 struct rte_mtr_error *error)
363 struct pmd_internals *p = dev->data->dev_private;
364 struct softnic_mtr_meter_profile *mp_new, *mp_old;
365 struct softnic_mtr *m;
368 /* MTR object id must be valid */
369 m = softnic_mtr_find(p, mtr_id);
371 return -rte_mtr_error_set(error,
373 RTE_MTR_ERROR_TYPE_MTR_ID,
375 "MTR object id not valid");
377 /* Meter profile id must be valid */
378 mp_new = softnic_mtr_meter_profile_find(p, meter_profile_id);
380 return -rte_mtr_error_set(error,
382 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
384 "Meter profile not valid");
386 /* MTR object already set to meter profile id */
387 if (m->params.meter_profile_id == meter_profile_id)
390 /* MTR object owner table update */
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;
396 if (!softnic_pipeline_table_meter_profile_find(table,
398 struct rte_table_action_meter_profile profile;
400 memset(&profile, 0, sizeof(profile));
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;
408 /* Add meter profile to pipeline table */
409 status = softnic_pipeline_table_mtr_profile_add(p,
410 m->flow->pipeline->name,
415 return -rte_mtr_error_set(error,
417 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
419 "Table meter profile add failed");
422 /* Set meter action */
423 memcpy(&action, &m->flow->action, sizeof(action));
425 action.mtr.mtr[0].meter_profile_id = meter_profile_id;
428 status = softnic_pipeline_table_rule_add(p,
429 m->flow->pipeline->name,
435 return -rte_mtr_error_set(error,
437 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
439 "Pipeline table rule add failed");
441 /* Flow: update meter action */
442 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
445 mp_old = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
447 /* Meter: Set meter profile */
448 m->params.meter_profile_id = meter_profile_id;
450 /* Update dependencies*/
457 /* MTR object meter DSCP table update */
459 pmd_mtr_meter_dscp_table_update(struct rte_eth_dev *dev,
461 enum rte_color *dscp_table,
462 struct rte_mtr_error *error)
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;
472 /* MTR object id must be valid */
473 m = softnic_mtr_find(p, mtr_id);
475 return -rte_mtr_error_set(error,
477 RTE_MTR_ERROR_TYPE_MTR_ID,
479 "MTR object id not valid");
481 /* MTR object owner valid? */
485 pipeline = m->flow->pipeline;
486 table_id = m->flow->table_id;
487 table = &pipeline->table[table_id];
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];
494 status = softnic_pipeline_table_dscp_table_update(p,
500 return -rte_mtr_error_set(error,
502 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
504 "Table action dscp table update failed");
509 /* MTR object policer action update */
511 pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,
513 uint32_t action_mask,
514 enum rte_mtr_policer_action *actions,
515 struct rte_mtr_error *error)
517 struct pmd_internals *p = dev->data->dev_private;
518 struct softnic_mtr *m;
522 /* MTR object id must be valid */
523 m = softnic_mtr_find(p, mtr_id);
525 return -rte_mtr_error_set(error,
527 RTE_MTR_ERROR_TYPE_MTR_ID,
529 "MTR object id not valid");
531 /* Valid policer actions */
533 return -rte_mtr_error_set(error,
535 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
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,
547 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
549 " Invalid action value");
554 /* MTR object owner valid? */
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;
560 memcpy(&action, &m->flow->action, sizeof(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]);
568 /* Re-add the rule */
569 status = softnic_pipeline_table_rule_add(p,
576 return -rte_mtr_error_set(error,
578 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
580 "Pipeline table rule re-add failed");
582 /* Flow: Update meter action */
583 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
585 /* Reset the meter stats */
586 rte_table_action_meter_read(table->a, m->flow->data,
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];
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)
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)
608 /* MTR object stats read */
610 mtr_stats_convert(struct softnic_mtr *m,
611 struct rte_table_action_mtr_counters_tc *in,
612 struct rte_mtr_stats *out,
615 memset(&out, 0, sizeof(out));
618 if (in->n_packets_valid) {
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];
625 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_YELLOW)
626 out->n_pkts[RTE_COLOR_YELLOW] += in->n_packets[i];
628 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_RED)
629 out->n_pkts[RTE_COLOR_RED] += in->n_packets[i];
631 if (m->params.action[i] == MTR_POLICER_ACTION_DROP)
632 out->n_pkts_dropped += in->n_packets[i];
635 *out_mask |= MTR_STATS_PKTS_DEFAULT;
638 if (in->n_bytes_valid) {
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];
645 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_YELLOW)
646 out->n_bytes[RTE_COLOR_YELLOW] += in->n_bytes[i];
648 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_RED)
649 out->n_bytes[RTE_COLOR_RED] += in->n_bytes[i];
651 if (m->params.action[i] == MTR_POLICER_ACTION_DROP)
652 out->n_bytes_dropped += in->n_bytes[i];
655 *out_mask |= MTR_STATS_BYTES_DEFAULT;
659 /* MTR object stats read */
661 pmd_mtr_stats_read(struct rte_eth_dev *dev,
663 struct rte_mtr_stats *stats,
664 uint64_t *stats_mask,
666 struct rte_mtr_error *error)
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;
675 /* MTR object id must be valid */
676 m = softnic_mtr_find(p, mtr_id);
678 return -rte_mtr_error_set(error,
680 RTE_MTR_ERROR_TYPE_MTR_ID,
682 "MTR object id not valid");
684 /* MTR meter object owner valid? */
685 if (m->flow == NULL) {
687 memset(stats, 0, sizeof(*stats));
690 *stats_mask = MTR_STATS_PKTS_DEFAULT |
691 MTR_STATS_BYTES_DEFAULT;
696 pipeline = m->flow->pipeline;
697 table = &pipeline->table[m->flow->table_id];
699 /* Meter stats read. */
700 status = rte_table_action_meter_read(table->a,
706 return -rte_mtr_error_set(error,
708 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
710 "Meter stats read failed");
712 /* Stats format conversion. */
713 if (stats || stats_mask) {
714 struct rte_mtr_stats s;
723 memcpy(stats, &s, sizeof(*stats));
726 *stats_mask = s_mask;
732 const struct rte_mtr_ops pmd_mtr_ops = {
733 .capabilities_get = NULL,
735 .meter_profile_add = pmd_mtr_meter_profile_add,
736 .meter_profile_delete = pmd_mtr_meter_profile_delete,
738 .create = pmd_mtr_create,
739 .destroy = pmd_mtr_destroy,
740 .meter_enable = NULL,
741 .meter_disable = NULL,
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,
748 .stats_read = pmd_mtr_stats_read,