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 meter policies list */
21 TAILQ_INIT(&p->mtr.meter_policies);
23 /* Initialize MTR objects list */
24 TAILQ_INIT(&p->mtr.mtrs);
30 softnic_mtr_free(struct pmd_internals *p)
32 /* Remove MTR objects */
34 struct softnic_mtr *m;
36 m = TAILQ_FIRST(&p->mtr.mtrs);
40 TAILQ_REMOVE(&p->mtr.mtrs, m, node);
44 /* Remove meter profiles */
46 struct softnic_mtr_meter_profile *mp;
48 mp = TAILQ_FIRST(&p->mtr.meter_profiles);
52 TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
57 struct softnic_mtr_meter_profile *
58 softnic_mtr_meter_profile_find(struct pmd_internals *p,
59 uint32_t meter_profile_id)
61 struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
62 struct softnic_mtr_meter_profile *mp;
64 TAILQ_FOREACH(mp, mpl, node)
65 if (meter_profile_id == mp->meter_profile_id)
72 meter_profile_check(struct rte_eth_dev *dev,
73 uint32_t meter_profile_id,
74 struct rte_mtr_meter_profile *profile,
75 struct rte_mtr_error *error)
77 struct pmd_internals *p = dev->data->dev_private;
78 struct softnic_mtr_meter_profile *mp;
80 /* Meter profile ID must be valid. */
81 if (meter_profile_id == UINT32_MAX)
82 return -rte_mtr_error_set(error,
84 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
86 "Meter profile id not valid");
88 /* Meter profile must not exist. */
89 mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
91 return -rte_mtr_error_set(error,
93 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
95 "Meter prfile already exists");
97 /* Profile must not be NULL. */
99 return -rte_mtr_error_set(error,
101 RTE_MTR_ERROR_TYPE_METER_PROFILE,
105 /* Traffic metering algorithm : TRTCM_RFC2698 */
106 if (profile->alg != RTE_MTR_TRTCM_RFC2698)
107 return -rte_mtr_error_set(error,
109 RTE_MTR_ERROR_TYPE_METER_PROFILE,
111 "Metering alg not supported");
113 /* Not support packet mode, just support byte mode. */
114 if (profile->packet_mode)
115 return -rte_mtr_error_set(error,
117 RTE_MTR_ERROR_TYPE_METER_PROFILE_PACKET_MODE,
119 "Meter packet mode not supported");
124 /* MTR meter profile add */
126 pmd_mtr_meter_profile_add(struct rte_eth_dev *dev,
127 uint32_t meter_profile_id,
128 struct rte_mtr_meter_profile *profile,
129 struct rte_mtr_error *error)
131 struct pmd_internals *p = dev->data->dev_private;
132 struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
133 struct softnic_mtr_meter_profile *mp;
136 /* Check input params */
137 status = meter_profile_check(dev, meter_profile_id, profile, error);
141 /* Memory allocation */
142 mp = calloc(1, sizeof(struct softnic_mtr_meter_profile));
144 return -rte_mtr_error_set(error,
146 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
148 "Memory alloc failed");
151 mp->meter_profile_id = meter_profile_id;
152 memcpy(&mp->params, profile, sizeof(mp->params));
155 TAILQ_INSERT_TAIL(mpl, mp, node);
160 /* MTR meter profile delete */
162 pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,
163 uint32_t meter_profile_id,
164 struct rte_mtr_error *error)
166 struct pmd_internals *p = dev->data->dev_private;
167 struct softnic_mtr_meter_profile *mp;
169 /* Meter profile must exist */
170 mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
172 return -rte_mtr_error_set(error,
174 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
176 "Meter profile id invalid");
180 return -rte_mtr_error_set(error,
182 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
184 "Meter profile in use");
186 /* Remove from list */
187 TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
193 struct softnic_mtr_meter_policy *
194 softnic_mtr_meter_policy_find(struct pmd_internals *p,
195 uint32_t meter_policy_id)
197 struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
198 struct softnic_mtr_meter_policy *mp;
200 TAILQ_FOREACH(mp, mpl, node)
201 if (meter_policy_id == mp->meter_policy_id)
207 /* MTR meter policy add */
209 pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
210 uint32_t meter_policy_id,
211 struct rte_mtr_meter_policy_params *policy,
212 struct rte_mtr_error *error)
214 struct pmd_internals *p = dev->data->dev_private;
215 struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
216 struct softnic_mtr_meter_policy *mp;
217 const struct rte_flow_action *act;
218 const struct rte_flow_action_meter_color *recolor;
220 bool valid_act_found;
223 return -rte_mtr_error_set(error,
225 RTE_MTR_ERROR_TYPE_METER_POLICY,
227 "Null meter policy invalid");
229 /* Meter policy must not exist. */
230 mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
232 return -rte_mtr_error_set(error,
234 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
236 "Meter policy already exists");
238 for (i = 0; i < RTE_COLORS; i++) {
239 if (policy->actions[i] == NULL)
240 return -rte_mtr_error_set(error,
242 RTE_MTR_ERROR_TYPE_METER_POLICY,
245 for (act = policy->actions[i], valid_act_found = false;
246 act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
247 if (act->type == RTE_FLOW_ACTION_TYPE_VOID)
250 * Support one (and one only) of
251 * METER_COLOR or DROP action.
253 if ((act->type != RTE_FLOW_ACTION_TYPE_METER_COLOR &&
254 act->type != RTE_FLOW_ACTION_TYPE_DROP) ||
256 return -rte_mtr_error_set(error,
258 RTE_MTR_ERROR_TYPE_METER_POLICY,
261 valid_act_found = true;
263 if (!valid_act_found)
264 return -rte_mtr_error_set(error,
266 RTE_MTR_ERROR_TYPE_METER_POLICY,
268 "No valid action found");
271 /* Memory allocation */
272 mp = calloc(1, sizeof(struct softnic_mtr_meter_policy));
274 return -rte_mtr_error_set(error,
276 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
278 "Memory alloc failed");
281 mp->meter_policy_id = meter_policy_id;
282 for (i = 0; i < RTE_COLORS; i++) {
283 mp->policer[i] = RTE_TABLE_ACTION_POLICER_DROP;
284 act = policy->actions[i];
287 if (act->type == RTE_FLOW_ACTION_TYPE_METER_COLOR) {
289 switch (recolor->color) {
290 case RTE_COLOR_GREEN:
292 RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
294 case RTE_COLOR_YELLOW:
296 RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
300 RTE_TABLE_ACTION_POLICER_COLOR_RED;
309 TAILQ_INSERT_TAIL(mpl, mp, node);
314 /* MTR meter policy delete */
316 pmd_mtr_meter_policy_delete(struct rte_eth_dev *dev,
317 uint32_t meter_policy_id,
318 struct rte_mtr_error *error)
320 struct pmd_internals *p = dev->data->dev_private;
321 struct softnic_mtr_meter_policy *mp;
323 /* Meter policy must exist */
324 mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
326 return -rte_mtr_error_set(error,
328 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
330 "Meter policy id invalid");
334 return -rte_mtr_error_set(error,
336 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
338 "Meter policy in use");
340 /* Remove from list */
341 TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
348 softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
350 struct softnic_mtr_list *ml = &p->mtr.mtrs;
351 struct softnic_mtr *m;
353 TAILQ_FOREACH(m, ml, node)
354 if (m->mtr_id == mtr_id)
362 mtr_check(struct pmd_internals *p,
364 struct rte_mtr_params *params,
366 struct rte_mtr_error *error)
369 if (softnic_mtr_find(p, mtr_id))
370 return -rte_mtr_error_set(error,
372 RTE_MTR_ERROR_TYPE_MTR_ID,
374 "MTR object already exists");
376 /* MTR params must not be NULL */
378 return -rte_mtr_error_set(error,
380 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
382 "MTR object params null");
384 /* Previous meter color not supported */
385 if (params->use_prev_mtr_color)
386 return -rte_mtr_error_set(error,
388 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
390 "Previous meter color not supported");
392 /* Shared MTR object not supported */
394 return -rte_mtr_error_set(error,
396 RTE_MTR_ERROR_TYPE_SHARED,
398 "Shared MTR object not supported");
403 /* MTR object create */
405 pmd_mtr_create(struct rte_eth_dev *dev,
407 struct rte_mtr_params *params,
409 struct rte_mtr_error *error)
411 struct pmd_internals *p = dev->data->dev_private;
412 struct softnic_mtr_list *ml = &p->mtr.mtrs;
413 struct softnic_mtr_meter_profile *mp;
414 struct softnic_mtr_meter_policy *policy;
415 struct softnic_mtr *m;
418 /* Check parameters */
419 status = mtr_check(p, mtr_id, params, shared, error);
423 /* Meter profile must exist */
424 mp = softnic_mtr_meter_profile_find(p, params->meter_profile_id);
426 return -rte_mtr_error_set(error,
428 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
430 "Meter profile id not valid");
432 /* Meter policy must exist */
433 policy = softnic_mtr_meter_policy_find(p, params->meter_policy_id);
434 if (policy == NULL) {
435 return -rte_mtr_error_set(error,
437 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
439 "Meter policy id invalid");
442 /* Memory allocation */
443 m = calloc(1, sizeof(struct softnic_mtr));
445 return -rte_mtr_error_set(error,
447 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
449 "Memory alloc failed");
453 memcpy(&m->params, params, sizeof(m->params));
456 TAILQ_INSERT_TAIL(ml, m, node);
458 /* Update dependencies */
465 /* MTR object destroy */
467 pmd_mtr_destroy(struct rte_eth_dev *dev,
469 struct rte_mtr_error *error)
471 struct pmd_internals *p = dev->data->dev_private;
472 struct softnic_mtr_list *ml = &p->mtr.mtrs;
473 struct softnic_mtr_meter_profile *mp;
474 struct softnic_mtr *m;
475 struct softnic_mtr_meter_policy *policy;
477 /* MTR object must exist */
478 m = softnic_mtr_find(p, mtr_id);
480 return -rte_mtr_error_set(error,
482 RTE_MTR_ERROR_TYPE_MTR_ID,
484 "MTR object id not valid");
486 /* MTR object must not have any owner */
488 return -rte_mtr_error_set(error,
490 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
492 "MTR object is being used");
494 /* Get meter profile */
495 mp = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
497 return -rte_mtr_error_set(error,
499 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
501 "MTR object meter profile invalid");
503 /* Meter policy must exist */
504 policy = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
506 return -rte_mtr_error_set(error,
508 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
510 "MTR object meter policy invalid");
512 /* Update dependencies */
516 /* Remove from list */
517 TAILQ_REMOVE(ml, m, node);
523 /* MTR object meter profile update */
525 pmd_mtr_meter_profile_update(struct rte_eth_dev *dev,
527 uint32_t meter_profile_id,
528 struct rte_mtr_error *error)
530 struct pmd_internals *p = dev->data->dev_private;
531 struct softnic_mtr_meter_profile *mp_new, *mp_old;
532 struct softnic_mtr *m;
535 /* MTR object id must be valid */
536 m = softnic_mtr_find(p, mtr_id);
538 return -rte_mtr_error_set(error,
540 RTE_MTR_ERROR_TYPE_MTR_ID,
542 "MTR object id not valid");
544 /* Meter profile id must be valid */
545 mp_new = softnic_mtr_meter_profile_find(p, meter_profile_id);
547 return -rte_mtr_error_set(error,
549 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
551 "Meter profile not valid");
553 /* MTR object already set to meter profile id */
554 if (m->params.meter_profile_id == meter_profile_id)
557 /* MTR object owner table update */
559 uint32_t table_id = m->flow->table_id;
560 struct softnic_table *table = &m->flow->pipeline->table[table_id];
561 struct softnic_table_rule_action action;
563 if (!softnic_pipeline_table_meter_profile_find(table,
565 struct rte_table_action_meter_profile profile;
567 memset(&profile, 0, sizeof(profile));
569 profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
570 profile.trtcm.cir = mp_new->params.trtcm_rfc2698.cir;
571 profile.trtcm.pir = mp_new->params.trtcm_rfc2698.pir;
572 profile.trtcm.cbs = mp_new->params.trtcm_rfc2698.cbs;
573 profile.trtcm.pbs = mp_new->params.trtcm_rfc2698.pbs;
575 /* Add meter profile to pipeline table */
576 status = softnic_pipeline_table_mtr_profile_add(p,
577 m->flow->pipeline->name,
582 return -rte_mtr_error_set(error,
584 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
586 "Table meter profile add failed");
589 /* Set meter action */
590 memcpy(&action, &m->flow->action, sizeof(action));
592 action.mtr.mtr[0].meter_profile_id = meter_profile_id;
595 status = softnic_pipeline_table_rule_add(p,
596 m->flow->pipeline->name,
602 return -rte_mtr_error_set(error,
604 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
606 "Pipeline table rule add failed");
608 /* Flow: update meter action */
609 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
612 mp_old = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
614 /* Meter: Set meter profile */
615 m->params.meter_profile_id = meter_profile_id;
617 /* Update dependencies*/
624 /* MTR object meter DSCP table update */
626 pmd_mtr_meter_dscp_table_update(struct rte_eth_dev *dev,
628 enum rte_color *dscp_table,
629 struct rte_mtr_error *error)
631 struct pmd_internals *p = dev->data->dev_private;
632 struct rte_table_action_dscp_table dt;
633 struct pipeline *pipeline;
634 struct softnic_table *table;
635 struct softnic_mtr *m;
636 uint32_t table_id, i;
639 /* MTR object id must be valid */
640 m = softnic_mtr_find(p, mtr_id);
642 return -rte_mtr_error_set(error,
644 RTE_MTR_ERROR_TYPE_MTR_ID,
646 "MTR object id not valid");
648 /* MTR object owner valid? */
652 pipeline = m->flow->pipeline;
653 table_id = m->flow->table_id;
654 table = &pipeline->table[table_id];
656 memcpy(&dt, &table->dscp_table, sizeof(dt));
657 for (i = 0; i < RTE_DIM(dt.entry); i++)
658 dt.entry[i].color = (enum rte_color)dscp_table[i];
661 status = softnic_pipeline_table_dscp_table_update(p,
667 return -rte_mtr_error_set(error,
669 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
671 "Table action dscp table update failed");
676 /* MTR object policy update */
678 pmd_mtr_meter_policy_update(struct rte_eth_dev *dev,
680 uint32_t meter_policy_id,
681 struct rte_mtr_error *error)
683 struct pmd_internals *p = dev->data->dev_private;
684 struct softnic_mtr *m;
687 struct softnic_mtr_meter_policy *mp_new, *mp_old;
689 /* MTR object id must be valid */
690 m = softnic_mtr_find(p, mtr_id);
692 return -rte_mtr_error_set(error,
694 RTE_MTR_ERROR_TYPE_MTR_ID,
696 "MTR object id not valid");
698 if (m->params.meter_policy_id == meter_policy_id)
701 /* Meter policy must exist */
702 mp_new = softnic_mtr_meter_policy_find(p, meter_policy_id);
704 return -rte_mtr_error_set(error,
706 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
708 "Meter policy id invalid");
710 /* MTR object owner valid? */
712 struct pipeline *pipeline = m->flow->pipeline;
713 struct softnic_table *table = &pipeline->table[m->flow->table_id];
714 struct softnic_table_rule_action action;
716 memcpy(&action, &m->flow->action, sizeof(action));
719 for (i = 0; i < RTE_COLORS; i++)
720 action.mtr.mtr[0].policer[i] = mp_new->policer[i];
722 /* Re-add the rule */
723 status = softnic_pipeline_table_rule_add(p,
730 return -rte_mtr_error_set(error,
732 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
734 "Pipeline table rule re-add failed");
736 /* Flow: Update meter action */
737 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
739 /* Reset the meter stats */
740 rte_table_action_meter_read(table->a, m->flow->data,
744 mp_old = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
746 return -rte_mtr_error_set(error,
748 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
750 "Old meter policy id invalid");
752 /* Meter: Set meter profile */
753 m->params.meter_policy_id = meter_policy_id;
755 /* Update dependencies*/
762 #define MTR_STATS_PKTS_DEFAULT (RTE_MTR_STATS_N_PKTS_GREEN | \
763 RTE_MTR_STATS_N_PKTS_YELLOW | \
764 RTE_MTR_STATS_N_PKTS_RED | \
765 RTE_MTR_STATS_N_PKTS_DROPPED)
767 #define MTR_STATS_BYTES_DEFAULT (RTE_MTR_STATS_N_BYTES_GREEN | \
768 RTE_MTR_STATS_N_BYTES_YELLOW | \
769 RTE_MTR_STATS_N_BYTES_RED | \
770 RTE_MTR_STATS_N_BYTES_DROPPED)
772 /* MTR object stats read */
774 mtr_stats_convert(struct pmd_internals *p,
775 struct softnic_mtr *m,
776 struct rte_table_action_mtr_counters_tc *in,
777 struct rte_mtr_stats *out,
780 struct softnic_mtr_meter_policy *mp;
782 memset(&out, 0, sizeof(out));
785 /* Meter policy must exist */
786 mp = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
790 if (in->n_packets_valid) {
793 for (i = 0; i < RTE_COLORS; i++) {
794 if (mp->policer[i] ==
795 RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
796 out->n_pkts[RTE_COLOR_GREEN] += in->n_packets[i];
798 if (mp->policer[i] ==
799 RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
800 out->n_pkts[RTE_COLOR_YELLOW] += in->n_packets[i];
802 if (mp->policer[i] ==
803 RTE_TABLE_ACTION_POLICER_COLOR_RED)
804 out->n_pkts[RTE_COLOR_RED] += in->n_packets[i];
806 if (mp->policer[i] ==
807 RTE_TABLE_ACTION_POLICER_DROP)
808 out->n_pkts_dropped += in->n_packets[i];
811 *out_mask |= MTR_STATS_PKTS_DEFAULT;
814 if (in->n_bytes_valid) {
817 for (i = 0; i < RTE_COLORS; i++) {
818 if (mp->policer[i] ==
819 RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
820 out->n_bytes[RTE_COLOR_GREEN] += in->n_bytes[i];
822 if (mp->policer[i] ==
823 RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
824 out->n_bytes[RTE_COLOR_YELLOW] += in->n_bytes[i];
826 if (mp->policer[i] ==
827 RTE_TABLE_ACTION_POLICER_COLOR_RED)
828 out->n_bytes[RTE_COLOR_RED] += in->n_bytes[i];
830 if (mp->policer[i] ==
831 RTE_TABLE_ACTION_POLICER_DROP)
832 out->n_bytes_dropped += in->n_bytes[i];
835 *out_mask |= MTR_STATS_BYTES_DEFAULT;
839 /* MTR object stats read */
841 pmd_mtr_stats_read(struct rte_eth_dev *dev,
843 struct rte_mtr_stats *stats,
844 uint64_t *stats_mask,
846 struct rte_mtr_error *error)
848 struct pmd_internals *p = dev->data->dev_private;
849 struct rte_table_action_mtr_counters counters;
850 struct pipeline *pipeline;
851 struct softnic_table *table;
852 struct softnic_mtr *m;
855 /* MTR object id must be valid */
856 m = softnic_mtr_find(p, mtr_id);
858 return -rte_mtr_error_set(error,
860 RTE_MTR_ERROR_TYPE_MTR_ID,
862 "MTR object id not valid");
864 /* MTR meter object owner valid? */
865 if (m->flow == NULL) {
867 memset(stats, 0, sizeof(*stats));
870 *stats_mask = MTR_STATS_PKTS_DEFAULT |
871 MTR_STATS_BYTES_DEFAULT;
876 pipeline = m->flow->pipeline;
877 table = &pipeline->table[m->flow->table_id];
879 /* Meter stats read. */
880 status = rte_table_action_meter_read(table->a,
886 return -rte_mtr_error_set(error,
888 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
890 "Meter stats read failed");
892 /* Stats format conversion. */
893 if (stats || stats_mask) {
894 struct rte_mtr_stats s;
904 memcpy(stats, &s, sizeof(*stats));
907 *stats_mask = s_mask;
913 const struct rte_mtr_ops pmd_mtr_ops = {
914 .capabilities_get = NULL,
916 .meter_profile_add = pmd_mtr_meter_profile_add,
917 .meter_profile_delete = pmd_mtr_meter_profile_delete,
919 .meter_policy_add = pmd_mtr_meter_policy_add,
920 .meter_policy_delete = pmd_mtr_meter_policy_delete,
922 .create = pmd_mtr_create,
923 .destroy = pmd_mtr_destroy,
924 .meter_enable = NULL,
925 .meter_disable = NULL,
927 .meter_profile_update = pmd_mtr_meter_profile_update,
928 .meter_dscp_table_update = pmd_mtr_meter_dscp_table_update,
929 .meter_policy_update = pmd_mtr_meter_policy_update,
930 .stats_update = NULL,
932 .stats_read = pmd_mtr_stats_read,