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");
113 /* MTR meter profile add */
115 pmd_mtr_meter_profile_add(struct rte_eth_dev *dev,
116 uint32_t meter_profile_id,
117 struct rte_mtr_meter_profile *profile,
118 struct rte_mtr_error *error)
120 struct pmd_internals *p = dev->data->dev_private;
121 struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
122 struct softnic_mtr_meter_profile *mp;
125 /* Check input params */
126 status = meter_profile_check(dev, meter_profile_id, profile, error);
130 /* Memory allocation */
131 mp = calloc(1, sizeof(struct softnic_mtr_meter_profile));
133 return -rte_mtr_error_set(error,
135 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
137 "Memory alloc failed");
140 mp->meter_profile_id = meter_profile_id;
141 memcpy(&mp->params, profile, sizeof(mp->params));
144 TAILQ_INSERT_TAIL(mpl, mp, node);
149 /* MTR meter profile delete */
151 pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,
152 uint32_t meter_profile_id,
153 struct rte_mtr_error *error)
155 struct pmd_internals *p = dev->data->dev_private;
156 struct softnic_mtr_meter_profile *mp;
158 /* Meter profile must exist */
159 mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
161 return -rte_mtr_error_set(error,
163 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
165 "Meter profile id invalid");
169 return -rte_mtr_error_set(error,
171 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
173 "Meter profile in use");
175 /* Remove from list */
176 TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
183 softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
185 struct softnic_mtr_list *ml = &p->mtr.mtrs;
186 struct softnic_mtr *m;
188 TAILQ_FOREACH(m, ml, node)
189 if (m->mtr_id == mtr_id)
197 mtr_check(struct pmd_internals *p,
199 struct rte_mtr_params *params,
201 struct rte_mtr_error *error)
204 if (softnic_mtr_find(p, mtr_id))
205 return -rte_mtr_error_set(error,
207 RTE_MTR_ERROR_TYPE_MTR_ID,
209 "MTR object already exists");
211 /* MTR params must not be NULL */
213 return -rte_mtr_error_set(error,
215 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
217 "MTR object params null");
219 /* Previous meter color not supported */
220 if (params->use_prev_mtr_color)
221 return -rte_mtr_error_set(error,
223 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
225 "Previous meter color not supported");
227 /* Shared MTR object not supported */
229 return -rte_mtr_error_set(error,
231 RTE_MTR_ERROR_TYPE_SHARED,
233 "Shared MTR object not supported");
238 /* MTR object create */
240 pmd_mtr_create(struct rte_eth_dev *dev,
242 struct rte_mtr_params *params,
244 struct rte_mtr_error *error)
246 struct pmd_internals *p = dev->data->dev_private;
247 struct softnic_mtr_list *ml = &p->mtr.mtrs;
248 struct softnic_mtr_meter_profile *mp;
249 struct softnic_mtr *m;
252 /* Check parameters */
253 status = mtr_check(p, mtr_id, params, shared, error);
257 /* Meter profile must exist */
258 mp = softnic_mtr_meter_profile_find(p, params->meter_profile_id);
260 return -rte_mtr_error_set(error,
262 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
264 "Meter profile id not valid");
266 /* Memory allocation */
267 m = calloc(1, sizeof(struct softnic_mtr));
269 return -rte_mtr_error_set(error,
271 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
273 "Memory alloc failed");
277 memcpy(&m->params, params, sizeof(m->params));
280 TAILQ_INSERT_TAIL(ml, m, node);
282 /* Update dependencies */
288 /* MTR object destroy */
290 pmd_mtr_destroy(struct rte_eth_dev *dev,
292 struct rte_mtr_error *error)
294 struct pmd_internals *p = dev->data->dev_private;
295 struct softnic_mtr_list *ml = &p->mtr.mtrs;
296 struct softnic_mtr_meter_profile *mp;
297 struct softnic_mtr *m;
299 /* MTR object must exist */
300 m = softnic_mtr_find(p, mtr_id);
302 return -rte_mtr_error_set(error,
304 RTE_MTR_ERROR_TYPE_MTR_ID,
306 "MTR object id not valid");
308 /* MTR object must not have any owner */
310 return -rte_mtr_error_set(error,
312 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
314 "MTR object is being used");
316 /* Get meter profile */
317 mp = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
319 return -rte_mtr_error_set(error,
321 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
323 "MTR object meter profile invalid");
325 /* Update dependencies */
328 /* Remove from list */
329 TAILQ_REMOVE(ml, m, node);
335 /* MTR object meter profile update */
337 pmd_mtr_meter_profile_update(struct rte_eth_dev *dev,
339 uint32_t meter_profile_id,
340 struct rte_mtr_error *error)
342 struct pmd_internals *p = dev->data->dev_private;
343 struct softnic_mtr_meter_profile *mp_new, *mp_old;
344 struct softnic_mtr *m;
347 /* MTR object id must be valid */
348 m = softnic_mtr_find(p, mtr_id);
350 return -rte_mtr_error_set(error,
352 RTE_MTR_ERROR_TYPE_MTR_ID,
354 "MTR object id not valid");
356 /* Meter profile id must be valid */
357 mp_new = softnic_mtr_meter_profile_find(p, meter_profile_id);
359 return -rte_mtr_error_set(error,
361 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
363 "Meter profile not valid");
365 /* MTR object already set to meter profile id */
366 if (m->params.meter_profile_id == meter_profile_id)
369 /* MTR object owner table update */
371 uint32_t table_id = m->flow->table_id;
372 struct softnic_table *table = &m->flow->pipeline->table[table_id];
373 struct softnic_table_rule_action action;
375 if (!softnic_pipeline_table_meter_profile_find(table,
377 struct rte_table_action_meter_profile profile;
379 memset(&profile, 0, sizeof(profile));
381 profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
382 profile.trtcm.cir = mp_new->params.trtcm_rfc2698.cir;
383 profile.trtcm.pir = mp_new->params.trtcm_rfc2698.pir;
384 profile.trtcm.cbs = mp_new->params.trtcm_rfc2698.cbs;
385 profile.trtcm.pbs = mp_new->params.trtcm_rfc2698.pbs;
387 /* Add meter profile to pipeline table */
388 status = softnic_pipeline_table_mtr_profile_add(p,
389 m->flow->pipeline->name,
394 return -rte_mtr_error_set(error,
396 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
398 "Table meter profile add failed");
401 /* Set meter action */
402 memcpy(&action, &m->flow->action, sizeof(action));
404 action.mtr.mtr[0].meter_profile_id = meter_profile_id;
407 status = softnic_pipeline_table_rule_add(p,
408 m->flow->pipeline->name,
414 return -rte_mtr_error_set(error,
416 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
418 "Pipeline table rule add failed");
420 /* Flow: update meter action */
421 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
424 mp_old = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
426 /* Meter: Set meter profile */
427 m->params.meter_profile_id = meter_profile_id;
429 /* Update dependencies*/
436 /* MTR object meter DSCP table update */
438 pmd_mtr_meter_dscp_table_update(struct rte_eth_dev *dev,
440 enum rte_mtr_color *dscp_table,
441 struct rte_mtr_error *error)
443 struct pmd_internals *p = dev->data->dev_private;
444 struct rte_table_action_dscp_table dt;
445 struct pipeline *pipeline;
446 struct softnic_table *table;
447 struct softnic_mtr *m;
448 uint32_t table_id, i;
451 /* MTR object id must be valid */
452 m = softnic_mtr_find(p, mtr_id);
454 return -rte_mtr_error_set(error,
456 RTE_MTR_ERROR_TYPE_MTR_ID,
458 "MTR object id not valid");
460 /* MTR object owner valid? */
464 pipeline = m->flow->pipeline;
465 table_id = m->flow->table_id;
466 table = &pipeline->table[table_id];
468 memcpy(&dt, &table->dscp_table, sizeof(dt));
469 for (i = 0; i < RTE_DIM(dt.entry); i++)
470 dt.entry[i].color = (enum rte_meter_color)dscp_table[i];
473 status = softnic_pipeline_table_dscp_table_update(p,
479 return -rte_mtr_error_set(error,
481 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
483 "Table action dscp table update failed");
488 /* MTR object policer action update */
490 pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,
492 uint32_t action_mask,
493 enum rte_mtr_policer_action *actions,
494 struct rte_mtr_error *error)
496 struct pmd_internals *p = dev->data->dev_private;
497 struct softnic_mtr *m;
501 /* MTR object id must be valid */
502 m = softnic_mtr_find(p, mtr_id);
504 return -rte_mtr_error_set(error,
506 RTE_MTR_ERROR_TYPE_MTR_ID,
508 "MTR object id not valid");
510 /* Valid policer actions */
512 return -rte_mtr_error_set(error,
514 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
518 for (i = 0; i < RTE_MTR_COLORS; i++) {
519 if (action_mask & (1 << i)) {
520 if (actions[i] != MTR_POLICER_ACTION_COLOR_GREEN &&
521 actions[i] != MTR_POLICER_ACTION_COLOR_YELLOW &&
522 actions[i] != MTR_POLICER_ACTION_COLOR_RED &&
523 actions[i] != MTR_POLICER_ACTION_DROP) {
524 return -rte_mtr_error_set(error,
526 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
528 " Invalid action value");
533 /* MTR object owner valid? */
535 struct pipeline *pipeline = m->flow->pipeline;
536 struct softnic_table *table = &pipeline->table[m->flow->table_id];
537 struct softnic_table_rule_action action;
539 memcpy(&action, &m->flow->action, sizeof(action));
542 for (i = 0; i < RTE_MTR_COLORS; i++)
543 if (action_mask & (1 << i))
544 action.mtr.mtr[0].policer[i] =
545 (enum rte_table_action_policer)actions[i];
547 /* Re-add the rule */
548 status = softnic_pipeline_table_rule_add(p,
555 return -rte_mtr_error_set(error,
557 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
559 "Pipeline table rule re-add failed");
561 /* Flow: Update meter action */
562 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
564 /* Reset the meter stats */
565 rte_table_action_meter_read(table->a, m->flow->data,
569 /* Meter: Update policer actions */
570 for (i = 0; i < RTE_MTR_COLORS; i++)
571 if (action_mask & (1 << i))
572 m->params.action[i] = actions[i];
577 #define MTR_STATS_PKTS_DEFAULT (RTE_MTR_STATS_N_PKTS_GREEN | \
578 RTE_MTR_STATS_N_PKTS_YELLOW | \
579 RTE_MTR_STATS_N_PKTS_RED | \
580 RTE_MTR_STATS_N_PKTS_DROPPED)
582 #define MTR_STATS_BYTES_DEFAULT (RTE_MTR_STATS_N_BYTES_GREEN | \
583 RTE_MTR_STATS_N_BYTES_YELLOW | \
584 RTE_MTR_STATS_N_BYTES_RED | \
585 RTE_MTR_STATS_N_BYTES_DROPPED)
587 /* MTR object stats read */
589 mtr_stats_convert(struct softnic_mtr *m,
590 struct rte_table_action_mtr_counters_tc *in,
591 struct rte_mtr_stats *out,
594 memset(&out, 0, sizeof(out));
597 if (in->n_packets_valid) {
600 for (i = 0; i < RTE_MTR_COLORS; i++) {
601 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_GREEN)
602 out->n_pkts[RTE_MTR_GREEN] += in->n_packets[i];
604 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_YELLOW)
605 out->n_pkts[RTE_MTR_YELLOW] += in->n_packets[i];
607 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_RED)
608 out->n_pkts[RTE_MTR_RED] += in->n_packets[i];
610 if (m->params.action[i] == MTR_POLICER_ACTION_DROP)
611 out->n_pkts_dropped += in->n_packets[i];
614 *out_mask |= MTR_STATS_PKTS_DEFAULT;
617 if (in->n_bytes_valid) {
620 for (i = 0; i < RTE_MTR_COLORS; i++) {
621 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_GREEN)
622 out->n_bytes[RTE_MTR_GREEN] += in->n_bytes[i];
624 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_YELLOW)
625 out->n_bytes[RTE_MTR_YELLOW] += in->n_bytes[i];
627 if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_RED)
628 out->n_bytes[RTE_MTR_RED] += in->n_bytes[i];
630 if (m->params.action[i] == MTR_POLICER_ACTION_DROP)
631 out->n_bytes_dropped += in->n_bytes[i];
634 *out_mask |= MTR_STATS_BYTES_DEFAULT;
638 /* MTR object stats read */
640 pmd_mtr_stats_read(struct rte_eth_dev *dev,
642 struct rte_mtr_stats *stats,
643 uint64_t *stats_mask,
645 struct rte_mtr_error *error)
647 struct pmd_internals *p = dev->data->dev_private;
648 struct rte_table_action_mtr_counters counters;
649 struct pipeline *pipeline;
650 struct softnic_table *table;
651 struct softnic_mtr *m;
654 /* MTR object id must be valid */
655 m = softnic_mtr_find(p, mtr_id);
657 return -rte_mtr_error_set(error,
659 RTE_MTR_ERROR_TYPE_MTR_ID,
661 "MTR object id not valid");
663 /* MTR meter object owner valid? */
664 if (m->flow == NULL) {
666 memset(stats, 0, sizeof(*stats));
669 *stats_mask = MTR_STATS_PKTS_DEFAULT |
670 MTR_STATS_BYTES_DEFAULT;
675 pipeline = m->flow->pipeline;
676 table = &pipeline->table[m->flow->table_id];
678 /* Meter stats read. */
679 status = rte_table_action_meter_read(table->a,
685 return -rte_mtr_error_set(error,
687 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
689 "Meter stats read failed");
691 /* Stats format conversion. */
692 if (stats || stats_mask) {
693 struct rte_mtr_stats s;
702 memcpy(stats, &s, sizeof(*stats));
705 *stats_mask = s_mask;
711 const struct rte_mtr_ops pmd_mtr_ops = {
712 .capabilities_get = NULL,
714 .meter_profile_add = pmd_mtr_meter_profile_add,
715 .meter_profile_delete = pmd_mtr_meter_profile_delete,
717 .create = pmd_mtr_create,
718 .destroy = pmd_mtr_destroy,
719 .meter_enable = NULL,
720 .meter_disable = NULL,
722 .meter_profile_update = pmd_mtr_meter_profile_update,
723 .meter_dscp_table_update = pmd_mtr_meter_dscp_table_update,
724 .policer_actions_update = pmd_mtr_policer_actions_update,
725 .stats_update = NULL,
727 .stats_read = pmd_mtr_stats_read,