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");
131 /* Not support packet mode, just support byte mode. */
132 if (profile->packet_mode)
133 return -rte_mtr_error_set(error,
135 RTE_MTR_ERROR_TYPE_METER_PROFILE_PACKET_MODE,
137 "Meter packet mode not supported");
142 /* MTR meter profile add */
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)
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;
154 /* Check input params */
155 status = meter_profile_check(dev, meter_profile_id, profile, error);
159 /* Memory allocation */
160 mp = calloc(1, sizeof(struct softnic_mtr_meter_profile));
162 return -rte_mtr_error_set(error,
164 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
166 "Memory alloc failed");
169 mp->meter_profile_id = meter_profile_id;
170 memcpy(&mp->params, profile, sizeof(mp->params));
173 TAILQ_INSERT_TAIL(mpl, mp, node);
178 /* MTR meter profile delete */
180 pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,
181 uint32_t meter_profile_id,
182 struct rte_mtr_error *error)
184 struct pmd_internals *p = dev->data->dev_private;
185 struct softnic_mtr_meter_profile *mp;
187 /* Meter profile must exist */
188 mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
190 return -rte_mtr_error_set(error,
192 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
194 "Meter profile id invalid");
198 return -rte_mtr_error_set(error,
200 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
202 "Meter profile in use");
204 /* Remove from list */
205 TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
212 softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
214 struct softnic_mtr_list *ml = &p->mtr.mtrs;
215 struct softnic_mtr *m;
217 TAILQ_FOREACH(m, ml, node)
218 if (m->mtr_id == mtr_id)
226 mtr_check(struct pmd_internals *p,
228 struct rte_mtr_params *params,
230 struct rte_mtr_error *error)
233 if (softnic_mtr_find(p, mtr_id))
234 return -rte_mtr_error_set(error,
236 RTE_MTR_ERROR_TYPE_MTR_ID,
238 "MTR object already exists");
240 /* MTR params must not be NULL */
242 return -rte_mtr_error_set(error,
244 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
246 "MTR object params null");
248 /* Previous meter color not supported */
249 if (params->use_prev_mtr_color)
250 return -rte_mtr_error_set(error,
252 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
254 "Previous meter color not supported");
256 /* Shared MTR object not supported */
258 return -rte_mtr_error_set(error,
260 RTE_MTR_ERROR_TYPE_SHARED,
262 "Shared MTR object not supported");
267 /* MTR object create */
269 pmd_mtr_create(struct rte_eth_dev *dev,
271 struct rte_mtr_params *params,
273 struct rte_mtr_error *error)
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;
281 /* Check parameters */
282 status = mtr_check(p, mtr_id, params, shared, error);
286 /* Meter profile must exist */
287 mp = softnic_mtr_meter_profile_find(p, params->meter_profile_id);
289 return -rte_mtr_error_set(error,
291 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
293 "Meter profile id not valid");
295 /* Memory allocation */
296 m = calloc(1, sizeof(struct softnic_mtr));
298 return -rte_mtr_error_set(error,
300 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
302 "Memory alloc failed");
306 memcpy(&m->params, params, sizeof(m->params));
309 TAILQ_INSERT_TAIL(ml, m, node);
311 /* Update dependencies */
317 /* MTR object destroy */
319 pmd_mtr_destroy(struct rte_eth_dev *dev,
321 struct rte_mtr_error *error)
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;
328 /* MTR object must exist */
329 m = softnic_mtr_find(p, mtr_id);
331 return -rte_mtr_error_set(error,
333 RTE_MTR_ERROR_TYPE_MTR_ID,
335 "MTR object id not valid");
337 /* MTR object must not have any owner */
339 return -rte_mtr_error_set(error,
341 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
343 "MTR object is being used");
345 /* Get meter profile */
346 mp = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
348 return -rte_mtr_error_set(error,
350 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
352 "MTR object meter profile invalid");
354 /* Update dependencies */
357 /* Remove from list */
358 TAILQ_REMOVE(ml, m, node);
364 /* MTR object meter profile update */
366 pmd_mtr_meter_profile_update(struct rte_eth_dev *dev,
368 uint32_t meter_profile_id,
369 struct rte_mtr_error *error)
371 struct pmd_internals *p = dev->data->dev_private;
372 struct softnic_mtr_meter_profile *mp_new, *mp_old;
373 struct softnic_mtr *m;
376 /* MTR object id must be valid */
377 m = softnic_mtr_find(p, mtr_id);
379 return -rte_mtr_error_set(error,
381 RTE_MTR_ERROR_TYPE_MTR_ID,
383 "MTR object id not valid");
385 /* Meter profile id must be valid */
386 mp_new = softnic_mtr_meter_profile_find(p, meter_profile_id);
388 return -rte_mtr_error_set(error,
390 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
392 "Meter profile not valid");
394 /* MTR object already set to meter profile id */
395 if (m->params.meter_profile_id == meter_profile_id)
398 /* MTR object owner table update */
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;
404 if (!softnic_pipeline_table_meter_profile_find(table,
406 struct rte_table_action_meter_profile profile;
408 memset(&profile, 0, sizeof(profile));
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;
416 /* Add meter profile to pipeline table */
417 status = softnic_pipeline_table_mtr_profile_add(p,
418 m->flow->pipeline->name,
423 return -rte_mtr_error_set(error,
425 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
427 "Table meter profile add failed");
430 /* Set meter action */
431 memcpy(&action, &m->flow->action, sizeof(action));
433 action.mtr.mtr[0].meter_profile_id = meter_profile_id;
436 status = softnic_pipeline_table_rule_add(p,
437 m->flow->pipeline->name,
443 return -rte_mtr_error_set(error,
445 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
447 "Pipeline table rule add failed");
449 /* Flow: update meter action */
450 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
453 mp_old = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
455 /* Meter: Set meter profile */
456 m->params.meter_profile_id = meter_profile_id;
458 /* Update dependencies*/
465 /* MTR object meter DSCP table update */
467 pmd_mtr_meter_dscp_table_update(struct rte_eth_dev *dev,
469 enum rte_color *dscp_table,
470 struct rte_mtr_error *error)
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;
480 /* MTR object id must be valid */
481 m = softnic_mtr_find(p, mtr_id);
483 return -rte_mtr_error_set(error,
485 RTE_MTR_ERROR_TYPE_MTR_ID,
487 "MTR object id not valid");
489 /* MTR object owner valid? */
493 pipeline = m->flow->pipeline;
494 table_id = m->flow->table_id;
495 table = &pipeline->table[table_id];
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];
502 status = softnic_pipeline_table_dscp_table_update(p,
508 return -rte_mtr_error_set(error,
510 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
512 "Table action dscp table update failed");
517 /* MTR object policer action update */
519 pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,
521 uint32_t action_mask,
522 enum rte_mtr_policer_action *actions,
523 struct rte_mtr_error *error)
525 struct pmd_internals *p = dev->data->dev_private;
526 struct softnic_mtr *m;
530 /* MTR object id must be valid */
531 m = softnic_mtr_find(p, mtr_id);
533 return -rte_mtr_error_set(error,
535 RTE_MTR_ERROR_TYPE_MTR_ID,
537 "MTR object id not valid");
539 /* Valid policer actions */
541 return -rte_mtr_error_set(error,
543 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
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,
555 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
557 " Invalid action value");
562 /* MTR object owner valid? */
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;
568 memcpy(&action, &m->flow->action, sizeof(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]);
576 /* Re-add the rule */
577 status = softnic_pipeline_table_rule_add(p,
584 return -rte_mtr_error_set(error,
586 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
588 "Pipeline table rule re-add failed");
590 /* Flow: Update meter action */
591 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
593 /* Reset the meter stats */
594 rte_table_action_meter_read(table->a, m->flow->data,
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];
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)
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)
616 /* MTR object stats read */
618 mtr_stats_convert(struct softnic_mtr *m,
619 struct rte_table_action_mtr_counters_tc *in,
620 struct rte_mtr_stats *out,
623 memset(&out, 0, sizeof(out));
626 if (in->n_packets_valid) {
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];
633 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_YELLOW)
634 out->n_pkts[RTE_COLOR_YELLOW] += in->n_packets[i];
636 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_RED)
637 out->n_pkts[RTE_COLOR_RED] += in->n_packets[i];
639 if (m->params.action[i] == MTR_POLICER_ACTION_DROP)
640 out->n_pkts_dropped += in->n_packets[i];
643 *out_mask |= MTR_STATS_PKTS_DEFAULT;
646 if (in->n_bytes_valid) {
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];
653 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_YELLOW)
654 out->n_bytes[RTE_COLOR_YELLOW] += in->n_bytes[i];
656 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_RED)
657 out->n_bytes[RTE_COLOR_RED] += in->n_bytes[i];
659 if (m->params.action[i] == MTR_POLICER_ACTION_DROP)
660 out->n_bytes_dropped += in->n_bytes[i];
663 *out_mask |= MTR_STATS_BYTES_DEFAULT;
667 /* MTR object stats read */
669 pmd_mtr_stats_read(struct rte_eth_dev *dev,
671 struct rte_mtr_stats *stats,
672 uint64_t *stats_mask,
674 struct rte_mtr_error *error)
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;
683 /* MTR object id must be valid */
684 m = softnic_mtr_find(p, mtr_id);
686 return -rte_mtr_error_set(error,
688 RTE_MTR_ERROR_TYPE_MTR_ID,
690 "MTR object id not valid");
692 /* MTR meter object owner valid? */
693 if (m->flow == NULL) {
695 memset(stats, 0, sizeof(*stats));
698 *stats_mask = MTR_STATS_PKTS_DEFAULT |
699 MTR_STATS_BYTES_DEFAULT;
704 pipeline = m->flow->pipeline;
705 table = &pipeline->table[m->flow->table_id];
707 /* Meter stats read. */
708 status = rte_table_action_meter_read(table->a,
714 return -rte_mtr_error_set(error,
716 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
718 "Meter stats read failed");
720 /* Stats format conversion. */
721 if (stats || stats_mask) {
722 struct rte_mtr_stats s;
731 memcpy(stats, &s, sizeof(*stats));
734 *stats_mask = s_mask;
740 const struct rte_mtr_ops pmd_mtr_ops = {
741 .capabilities_get = NULL,
743 .meter_profile_add = pmd_mtr_meter_profile_add,
744 .meter_profile_delete = pmd_mtr_meter_profile_delete,
746 .create = pmd_mtr_create,
747 .destroy = pmd_mtr_destroy,
748 .meter_enable = NULL,
749 .meter_disable = NULL,
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,
756 .stats_read = pmd_mtr_stats_read,