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)
69 meter_profile_check(struct rte_eth_dev *dev,
70 uint32_t meter_profile_id,
71 struct rte_mtr_meter_profile *profile,
72 struct rte_mtr_error *error)
74 struct pmd_internals *p = dev->data->dev_private;
75 struct softnic_mtr_meter_profile *mp;
77 /* Meter profile ID must be valid. */
78 if (meter_profile_id == UINT32_MAX)
79 return -rte_mtr_error_set(error,
81 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
83 "Meter profile id not valid");
85 /* Meter profile must not exist. */
86 mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
88 return -rte_mtr_error_set(error,
90 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
92 "Meter prfile already exists");
94 /* Profile must not be NULL. */
96 return -rte_mtr_error_set(error,
98 RTE_MTR_ERROR_TYPE_METER_PROFILE,
102 /* Traffic metering algorithm : TRTCM_RFC2698 */
103 if (profile->alg != RTE_MTR_TRTCM_RFC2698)
104 return -rte_mtr_error_set(error,
106 RTE_MTR_ERROR_TYPE_METER_PROFILE,
108 "Metering alg not supported");
110 /* Not support packet mode, just support byte mode. */
111 if (profile->packet_mode)
112 return -rte_mtr_error_set(error,
114 RTE_MTR_ERROR_TYPE_METER_PROFILE_PACKET_MODE,
116 "Meter packet mode not supported");
121 /* MTR meter profile add */
123 pmd_mtr_meter_profile_add(struct rte_eth_dev *dev,
124 uint32_t meter_profile_id,
125 struct rte_mtr_meter_profile *profile,
126 struct rte_mtr_error *error)
128 struct pmd_internals *p = dev->data->dev_private;
129 struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
130 struct softnic_mtr_meter_profile *mp;
133 /* Check input params */
134 status = meter_profile_check(dev, meter_profile_id, profile, error);
138 /* Memory allocation */
139 mp = calloc(1, sizeof(struct softnic_mtr_meter_profile));
141 return -rte_mtr_error_set(error,
143 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
145 "Memory alloc failed");
148 mp->meter_profile_id = meter_profile_id;
149 memcpy(&mp->params, profile, sizeof(mp->params));
152 TAILQ_INSERT_TAIL(mpl, mp, node);
157 /* MTR meter profile delete */
159 pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,
160 uint32_t meter_profile_id,
161 struct rte_mtr_error *error)
163 struct pmd_internals *p = dev->data->dev_private;
164 struct softnic_mtr_meter_profile *mp;
166 /* Meter profile must exist */
167 mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
169 return -rte_mtr_error_set(error,
171 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
173 "Meter profile id invalid");
177 return -rte_mtr_error_set(error,
179 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
181 "Meter profile in use");
183 /* Remove from list */
184 TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
190 struct softnic_mtr_meter_policy *
191 softnic_mtr_meter_policy_find(struct pmd_internals *p,
192 uint32_t meter_policy_id)
194 struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
195 struct softnic_mtr_meter_policy *mp;
197 TAILQ_FOREACH(mp, mpl, node)
198 if (meter_policy_id == mp->meter_policy_id)
204 /* MTR meter policy add */
206 pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
207 uint32_t meter_policy_id,
208 struct rte_mtr_meter_policy_params *policy,
209 struct rte_mtr_error *error)
211 struct pmd_internals *p = dev->data->dev_private;
212 struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
213 struct softnic_mtr_meter_policy *mp;
214 const struct rte_flow_action *act;
215 const struct rte_flow_action_meter_color *recolor;
217 bool valid_act_found;
220 return -rte_mtr_error_set(error,
222 RTE_MTR_ERROR_TYPE_METER_POLICY,
224 "Null meter policy invalid");
226 /* Meter policy must not exist. */
227 mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
229 return -rte_mtr_error_set(error,
231 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
233 "Meter policy already exists");
235 for (i = 0; i < RTE_COLORS; i++) {
236 if (policy->actions[i] == NULL)
237 return -rte_mtr_error_set(error,
239 RTE_MTR_ERROR_TYPE_METER_POLICY,
242 for (act = policy->actions[i], valid_act_found = false;
243 act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
244 if (act->type == RTE_FLOW_ACTION_TYPE_VOID)
247 * Support one (and one only) of
248 * METER_COLOR or DROP action.
250 if ((act->type != RTE_FLOW_ACTION_TYPE_METER_COLOR &&
251 act->type != RTE_FLOW_ACTION_TYPE_DROP) ||
253 return -rte_mtr_error_set(error,
255 RTE_MTR_ERROR_TYPE_METER_POLICY,
258 valid_act_found = true;
260 if (!valid_act_found)
261 return -rte_mtr_error_set(error,
263 RTE_MTR_ERROR_TYPE_METER_POLICY,
265 "No valid action found");
268 /* Memory allocation */
269 mp = calloc(1, sizeof(struct softnic_mtr_meter_policy));
271 return -rte_mtr_error_set(error,
273 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
275 "Memory alloc failed");
278 mp->meter_policy_id = meter_policy_id;
279 for (i = 0; i < RTE_COLORS; i++) {
280 mp->policer[i] = RTE_TABLE_ACTION_POLICER_DROP;
281 act = policy->actions[i];
284 if (act->type == RTE_FLOW_ACTION_TYPE_METER_COLOR) {
286 switch (recolor->color) {
287 case RTE_COLOR_GREEN:
289 RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
291 case RTE_COLOR_YELLOW:
293 RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
297 RTE_TABLE_ACTION_POLICER_COLOR_RED;
306 TAILQ_INSERT_TAIL(mpl, mp, node);
311 /* MTR meter policy delete */
313 pmd_mtr_meter_policy_delete(struct rte_eth_dev *dev,
314 uint32_t meter_policy_id,
315 struct rte_mtr_error *error)
317 struct pmd_internals *p = dev->data->dev_private;
318 struct softnic_mtr_meter_policy *mp;
320 /* Meter policy must exist */
321 mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
323 return -rte_mtr_error_set(error,
325 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
327 "Meter policy id invalid");
331 return -rte_mtr_error_set(error,
333 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
335 "Meter policy in use");
337 /* Remove from list */
338 TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
345 softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
347 struct softnic_mtr_list *ml = &p->mtr.mtrs;
348 struct softnic_mtr *m;
350 TAILQ_FOREACH(m, ml, node)
351 if (m->mtr_id == mtr_id)
359 mtr_check(struct pmd_internals *p,
361 struct rte_mtr_params *params,
363 struct rte_mtr_error *error)
366 if (softnic_mtr_find(p, mtr_id))
367 return -rte_mtr_error_set(error,
369 RTE_MTR_ERROR_TYPE_MTR_ID,
371 "MTR object already exists");
373 /* MTR params must not be NULL */
375 return -rte_mtr_error_set(error,
377 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
379 "MTR object params null");
381 /* Previous meter color not supported */
382 if (params->use_prev_mtr_color)
383 return -rte_mtr_error_set(error,
385 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
387 "Previous meter color not supported");
389 /* Shared MTR object not supported */
391 return -rte_mtr_error_set(error,
393 RTE_MTR_ERROR_TYPE_SHARED,
395 "Shared MTR object not supported");
400 /* MTR object create */
402 pmd_mtr_create(struct rte_eth_dev *dev,
404 struct rte_mtr_params *params,
406 struct rte_mtr_error *error)
408 struct pmd_internals *p = dev->data->dev_private;
409 struct softnic_mtr_list *ml = &p->mtr.mtrs;
410 struct softnic_mtr_meter_profile *mp;
411 struct softnic_mtr_meter_policy *policy;
412 struct softnic_mtr *m;
415 /* Check parameters */
416 status = mtr_check(p, mtr_id, params, shared, error);
420 /* Meter profile must exist */
421 mp = softnic_mtr_meter_profile_find(p, params->meter_profile_id);
423 return -rte_mtr_error_set(error,
425 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
427 "Meter profile id not valid");
429 /* Meter policy must exist */
430 policy = softnic_mtr_meter_policy_find(p, params->meter_policy_id);
431 if (policy == NULL) {
432 return -rte_mtr_error_set(error,
434 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
436 "Meter policy id invalid");
439 /* Memory allocation */
440 m = calloc(1, sizeof(struct softnic_mtr));
442 return -rte_mtr_error_set(error,
444 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
446 "Memory alloc failed");
450 memcpy(&m->params, params, sizeof(m->params));
453 TAILQ_INSERT_TAIL(ml, m, node);
455 /* Update dependencies */
462 /* MTR object destroy */
464 pmd_mtr_destroy(struct rte_eth_dev *dev,
466 struct rte_mtr_error *error)
468 struct pmd_internals *p = dev->data->dev_private;
469 struct softnic_mtr_list *ml = &p->mtr.mtrs;
470 struct softnic_mtr_meter_profile *mp;
471 struct softnic_mtr *m;
472 struct softnic_mtr_meter_policy *policy;
474 /* MTR object must exist */
475 m = softnic_mtr_find(p, mtr_id);
477 return -rte_mtr_error_set(error,
479 RTE_MTR_ERROR_TYPE_MTR_ID,
481 "MTR object id not valid");
483 /* MTR object must not have any owner */
485 return -rte_mtr_error_set(error,
487 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
489 "MTR object is being used");
491 /* Get meter profile */
492 mp = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
494 return -rte_mtr_error_set(error,
496 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
498 "MTR object meter profile invalid");
500 /* Meter policy must exist */
501 policy = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
503 return -rte_mtr_error_set(error,
505 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
507 "MTR object meter policy invalid");
509 /* Update dependencies */
513 /* Remove from list */
514 TAILQ_REMOVE(ml, m, node);
520 /* MTR object meter profile update */
522 pmd_mtr_meter_profile_update(struct rte_eth_dev *dev,
524 uint32_t meter_profile_id,
525 struct rte_mtr_error *error)
527 struct pmd_internals *p = dev->data->dev_private;
528 struct softnic_mtr_meter_profile *mp_new, *mp_old;
529 struct softnic_mtr *m;
532 /* MTR object id must be valid */
533 m = softnic_mtr_find(p, mtr_id);
535 return -rte_mtr_error_set(error,
537 RTE_MTR_ERROR_TYPE_MTR_ID,
539 "MTR object id not valid");
541 /* Meter profile id must be valid */
542 mp_new = softnic_mtr_meter_profile_find(p, meter_profile_id);
544 return -rte_mtr_error_set(error,
546 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
548 "Meter profile not valid");
550 /* MTR object already set to meter profile id */
551 if (m->params.meter_profile_id == meter_profile_id)
554 /* MTR object owner table update */
556 uint32_t table_id = m->flow->table_id;
557 struct softnic_table *table = &m->flow->pipeline->table[table_id];
558 struct softnic_table_rule_action action;
560 if (!softnic_pipeline_table_meter_profile_find(table,
562 struct rte_table_action_meter_profile profile;
564 memset(&profile, 0, sizeof(profile));
566 profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
567 profile.trtcm.cir = mp_new->params.trtcm_rfc2698.cir;
568 profile.trtcm.pir = mp_new->params.trtcm_rfc2698.pir;
569 profile.trtcm.cbs = mp_new->params.trtcm_rfc2698.cbs;
570 profile.trtcm.pbs = mp_new->params.trtcm_rfc2698.pbs;
572 /* Add meter profile to pipeline table */
573 status = softnic_pipeline_table_mtr_profile_add(p,
574 m->flow->pipeline->name,
579 return -rte_mtr_error_set(error,
581 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
583 "Table meter profile add failed");
586 /* Set meter action */
587 memcpy(&action, &m->flow->action, sizeof(action));
589 action.mtr.mtr[0].meter_profile_id = meter_profile_id;
592 status = softnic_pipeline_table_rule_add(p,
593 m->flow->pipeline->name,
599 return -rte_mtr_error_set(error,
601 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
603 "Pipeline table rule add failed");
605 /* Flow: update meter action */
606 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
609 mp_old = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
611 /* Meter: Set meter profile */
612 m->params.meter_profile_id = meter_profile_id;
614 /* Update dependencies*/
621 /* MTR object meter DSCP table update */
623 pmd_mtr_meter_dscp_table_update(struct rte_eth_dev *dev,
625 enum rte_color *dscp_table,
626 struct rte_mtr_error *error)
628 struct pmd_internals *p = dev->data->dev_private;
629 struct rte_table_action_dscp_table dt;
630 struct pipeline *pipeline;
631 struct softnic_table *table;
632 struct softnic_mtr *m;
633 uint32_t table_id, i;
636 /* MTR object id must be valid */
637 m = softnic_mtr_find(p, mtr_id);
639 return -rte_mtr_error_set(error,
641 RTE_MTR_ERROR_TYPE_MTR_ID,
643 "MTR object id not valid");
645 /* MTR object owner valid? */
649 pipeline = m->flow->pipeline;
650 table_id = m->flow->table_id;
651 table = &pipeline->table[table_id];
653 memcpy(&dt, &table->dscp_table, sizeof(dt));
654 for (i = 0; i < RTE_DIM(dt.entry); i++)
655 dt.entry[i].color = (enum rte_color)dscp_table[i];
658 status = softnic_pipeline_table_dscp_table_update(p,
664 return -rte_mtr_error_set(error,
666 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
668 "Table action dscp table update failed");
673 /* MTR object policy update */
675 pmd_mtr_meter_policy_update(struct rte_eth_dev *dev,
677 uint32_t meter_policy_id,
678 struct rte_mtr_error *error)
680 struct pmd_internals *p = dev->data->dev_private;
681 struct softnic_mtr *m;
684 struct softnic_mtr_meter_policy *mp_new, *mp_old;
686 /* MTR object id must be valid */
687 m = softnic_mtr_find(p, mtr_id);
689 return -rte_mtr_error_set(error,
691 RTE_MTR_ERROR_TYPE_MTR_ID,
693 "MTR object id not valid");
695 if (m->params.meter_policy_id == meter_policy_id)
698 /* Meter policy must exist */
699 mp_new = softnic_mtr_meter_policy_find(p, meter_policy_id);
701 return -rte_mtr_error_set(error,
703 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
705 "Meter policy id invalid");
707 /* MTR object owner valid? */
709 struct pipeline *pipeline = m->flow->pipeline;
710 struct softnic_table *table = &pipeline->table[m->flow->table_id];
711 struct softnic_table_rule_action action;
713 memcpy(&action, &m->flow->action, sizeof(action));
716 for (i = 0; i < RTE_COLORS; i++)
717 action.mtr.mtr[0].policer[i] = mp_new->policer[i];
719 /* Re-add the rule */
720 status = softnic_pipeline_table_rule_add(p,
727 return -rte_mtr_error_set(error,
729 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
731 "Pipeline table rule re-add failed");
733 /* Flow: Update meter action */
734 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
736 /* Reset the meter stats */
737 rte_table_action_meter_read(table->a, m->flow->data,
741 mp_old = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
743 return -rte_mtr_error_set(error,
745 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
747 "Old meter policy id invalid");
749 /* Meter: Set meter profile */
750 m->params.meter_policy_id = meter_policy_id;
752 /* Update dependencies*/
759 #define MTR_STATS_PKTS_DEFAULT (RTE_MTR_STATS_N_PKTS_GREEN | \
760 RTE_MTR_STATS_N_PKTS_YELLOW | \
761 RTE_MTR_STATS_N_PKTS_RED | \
762 RTE_MTR_STATS_N_PKTS_DROPPED)
764 #define MTR_STATS_BYTES_DEFAULT (RTE_MTR_STATS_N_BYTES_GREEN | \
765 RTE_MTR_STATS_N_BYTES_YELLOW | \
766 RTE_MTR_STATS_N_BYTES_RED | \
767 RTE_MTR_STATS_N_BYTES_DROPPED)
769 /* MTR object stats read */
771 mtr_stats_convert(struct pmd_internals *p,
772 struct softnic_mtr *m,
773 struct rte_table_action_mtr_counters_tc *in,
774 struct rte_mtr_stats *out,
777 struct softnic_mtr_meter_policy *mp;
779 memset(&out, 0, sizeof(out));
782 /* Meter policy must exist */
783 mp = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
787 if (in->n_packets_valid) {
790 for (i = 0; i < RTE_COLORS; i++) {
791 if (mp->policer[i] ==
792 RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
793 out->n_pkts[RTE_COLOR_GREEN] += in->n_packets[i];
795 if (mp->policer[i] ==
796 RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
797 out->n_pkts[RTE_COLOR_YELLOW] += in->n_packets[i];
799 if (mp->policer[i] ==
800 RTE_TABLE_ACTION_POLICER_COLOR_RED)
801 out->n_pkts[RTE_COLOR_RED] += in->n_packets[i];
803 if (mp->policer[i] ==
804 RTE_TABLE_ACTION_POLICER_DROP)
805 out->n_pkts_dropped += in->n_packets[i];
808 *out_mask |= MTR_STATS_PKTS_DEFAULT;
811 if (in->n_bytes_valid) {
814 for (i = 0; i < RTE_COLORS; i++) {
815 if (mp->policer[i] ==
816 RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
817 out->n_bytes[RTE_COLOR_GREEN] += in->n_bytes[i];
819 if (mp->policer[i] ==
820 RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
821 out->n_bytes[RTE_COLOR_YELLOW] += in->n_bytes[i];
823 if (mp->policer[i] ==
824 RTE_TABLE_ACTION_POLICER_COLOR_RED)
825 out->n_bytes[RTE_COLOR_RED] += in->n_bytes[i];
827 if (mp->policer[i] ==
828 RTE_TABLE_ACTION_POLICER_DROP)
829 out->n_bytes_dropped += in->n_bytes[i];
832 *out_mask |= MTR_STATS_BYTES_DEFAULT;
836 /* MTR object stats read */
838 pmd_mtr_stats_read(struct rte_eth_dev *dev,
840 struct rte_mtr_stats *stats,
841 uint64_t *stats_mask,
843 struct rte_mtr_error *error)
845 struct pmd_internals *p = dev->data->dev_private;
846 struct rte_table_action_mtr_counters counters;
847 struct pipeline *pipeline;
848 struct softnic_table *table;
849 struct softnic_mtr *m;
852 /* MTR object id must be valid */
853 m = softnic_mtr_find(p, mtr_id);
855 return -rte_mtr_error_set(error,
857 RTE_MTR_ERROR_TYPE_MTR_ID,
859 "MTR object id not valid");
861 /* MTR meter object owner valid? */
862 if (m->flow == NULL) {
864 memset(stats, 0, sizeof(*stats));
867 *stats_mask = MTR_STATS_PKTS_DEFAULT |
868 MTR_STATS_BYTES_DEFAULT;
873 pipeline = m->flow->pipeline;
874 table = &pipeline->table[m->flow->table_id];
876 /* Meter stats read. */
877 status = rte_table_action_meter_read(table->a,
883 return -rte_mtr_error_set(error,
885 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
887 "Meter stats read failed");
889 /* Stats format conversion. */
890 if (stats || stats_mask) {
891 struct rte_mtr_stats s;
901 memcpy(stats, &s, sizeof(*stats));
904 *stats_mask = s_mask;
910 const struct rte_mtr_ops pmd_mtr_ops = {
911 .capabilities_get = NULL,
913 .meter_profile_add = pmd_mtr_meter_profile_add,
914 .meter_profile_delete = pmd_mtr_meter_profile_delete,
916 .meter_policy_add = pmd_mtr_meter_policy_add,
917 .meter_policy_delete = pmd_mtr_meter_policy_delete,
919 .create = pmd_mtr_create,
920 .destroy = pmd_mtr_destroy,
921 .meter_enable = NULL,
922 .meter_disable = NULL,
924 .meter_profile_update = pmd_mtr_meter_profile_update,
925 .meter_dscp_table_update = pmd_mtr_meter_dscp_table_update,
926 .meter_policy_update = pmd_mtr_meter_policy_update,
927 .stats_update = NULL,
929 .stats_read = pmd_mtr_stats_read,