[PATCH 19/45] net/dpaa2: support meter and policing
Prashant Gupta
prashant.gupta_3 at nxp.com
Thu Sep 3 15:53:27 CEST 2026
From: Gagandeep Singh <g.singh at nxp.com>
Add support for the traffic metering and policing (rte_mtr) API to
the dpaa2 PMD. The implementation registers the rte_mtr operations
through the ".mtr_ops_get" dev_ops hook and maintains software
bookkeeping of meter profiles, policies and meter objects under a
per-device spinlock.
Supported algorithms are trTCM RFC 2698 and trTCM RFC 4115 in both
byte and packet modes. Meter policies support drop and pass-through
actions on the red color.
Signed-off-by: Gagandeep Singh <g.singh at nxp.com>
---
drivers/net/dpaa2/dpaa2_ethdev.c | 1 +
drivers/net/dpaa2/dpaa2_ethdev.h | 29 ++
drivers/net/dpaa2/dpaa2_meter.c | 588 +++++++++++++++++++++++++++++++
drivers/net/dpaa2/mc/fsl_dpni.h | 23 +-
drivers/net/dpaa2/meson.build | 1 +
5 files changed, 638 insertions(+), 4 deletions(-)
create mode 100644 drivers/net/dpaa2/dpaa2_meter.c
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index d79dfa7114..c8abab830f 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -3322,6 +3322,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = {
.rxq_info_get = dpaa2_rxq_info_get,
.txq_info_get = dpaa2_txq_info_get,
.tm_ops_get = dpaa2_tm_ops_get,
+ .mtr_ops_get = dpaa2_mtr_ops_get,
#if defined(RTE_LIBRTE_IEEE1588)
.timesync_enable = dpaa2_timesync_enable,
.timesync_disable = dpaa2_timesync_disable,
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h
index 0366315ec7..c5aac65c28 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.h
+++ b/drivers/net/dpaa2/dpaa2_ethdev.h
@@ -385,6 +385,30 @@ struct extract_s {
uint8_t *tc_extract_param[MAX_TCS];
};
+struct dpaa2_dev_meter_profile {
+ LIST_ENTRY(dpaa2_dev_meter_profile) next;
+ uint32_t profile_id;
+ uint64_t cir;
+ uint64_t cbs;
+ uint64_t pir;
+ uint64_t pbs;
+ enum dpni_policer_mode mode;
+ enum dpni_policer_unit policer_unit;
+};
+
+struct dpaa2_dev_meter_policy {
+ LIST_ENTRY(dpaa2_dev_meter_policy) next;
+ uint32_t policy_id;
+ int red_drop;
+};
+
+struct dpaa2_dev_meter {
+ LIST_ENTRY(dpaa2_dev_meter) next;
+ uint32_t meter_id;
+ uint32_t profile_id;
+ uint32_t policy_id;
+};
+
struct dpaa2_dev_priv {
void *hw;
int32_t hw_id;
@@ -412,6 +436,7 @@ struct dpaa2_dev_priv {
uint8_t en_loose_ordered;
uint8_t max_cgs;
uint8_t cgid_in_use[MAX_RX_QUEUES];
+ rte_spinlock_t meter_lock;
/* Current hash distribution size per RX TC, written by
* dpaa2_setup_flow_dist_size() and read by reta_query / reta_update.
@@ -457,6 +482,9 @@ struct dpaa2_dev_priv {
struct dpaa2_dev_flow *curr;
LIST_HEAD(, dpaa2_dev_flow) flows;
+ LIST_HEAD(, dpaa2_dev_meter_profile) profiles;
+ LIST_HEAD(, dpaa2_dev_meter_policy) policies;
+ LIST_HEAD(, dpaa2_dev_meter) meters;
LIST_HEAD(nodes, dpaa2_tm_node) nodes;
LIST_HEAD(shaper_profiles, dpaa2_tm_shaper_profile) shaper_profiles;
};
@@ -549,6 +577,7 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev);
int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev);
+int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops);
int dpaa2_soft_parser_loaded(void);
void
diff --git a/drivers/net/dpaa2/dpaa2_meter.c b/drivers/net/dpaa2/dpaa2_meter.c
new file mode 100644
index 0000000000..aae88a4d4b
--- /dev/null
+++ b/drivers/net/dpaa2/dpaa2_meter.c
@@ -0,0 +1,588 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2025-2026 NXP
+ */
+
+#include <sys/queue.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+
+#include <rte_ethdev.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_flow_driver.h>
+#include <rte_tailq.h>
+#include <rte_mtr.h>
+#include <rte_mtr_driver.h>
+
+#include <fsl_dpni.h>
+#include <fsl_dpkg.h>
+
+#include <dpaa2_ethdev.h>
+#include <dpaa2_pmd_logs.h>
+
+static char s_err_msg[128];
+
+static struct rte_mtr_capabilities s_dpaa2_mtr_capa = {
+ .color_aware_trtcm_rfc2698_supported = true,
+ .color_aware_trtcm_rfc4115_supported = true,
+ .trtcm_rfc2698_byte_mode_supported = true,
+ .trtcm_rfc2698_packet_mode_supported = true,
+ .trtcm_rfc4115_byte_mode_supported = true,
+ .trtcm_rfc4115_packet_mode_supported = true
+};
+
+static int
+dpaa2_mtr_capabilities_get(struct rte_eth_dev *dev,
+ struct rte_mtr_capabilities *capa,
+ struct rte_mtr_error *error)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+
+ if (capa == NULL) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
+ "NULL input parameter");
+ }
+
+ rte_spinlock_lock(&priv->meter_lock);
+ s_dpaa2_mtr_capa.n_max = priv->num_rx_tc;
+ s_dpaa2_mtr_capa.n_shared_max = priv->num_rx_tc;
+ s_dpaa2_mtr_capa.meter_trtcm_rfc2698_n_max = priv->num_rx_tc;
+ s_dpaa2_mtr_capa.meter_trtcm_rfc4115_n_max = priv->num_rx_tc;
+ s_dpaa2_mtr_capa.meter_policy_n_max = priv->num_rx_tc;
+ s_dpaa2_mtr_capa.shared_n_flows_per_mtr_max = priv->fs_entries;
+ rte_spinlock_unlock(&priv->meter_lock);
+
+ *capa = s_dpaa2_mtr_capa;
+
+ return 0;
+}
+
+static int
+dpaa2_mtr_profile_add(struct rte_eth_dev *dev,
+ uint32_t profile_id, struct rte_mtr_meter_profile *profile,
+ struct rte_mtr_error *error)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_meter_profile *dpaa2_profile;
+ struct dpaa2_dev_meter_profile *curr;
+ int ret = 0;
+
+ dpaa2_profile = rte_zmalloc(NULL,
+ sizeof(struct dpaa2_dev_meter_profile), 0);
+ if (dpaa2_profile == NULL) {
+ return -rte_mtr_error_set(error, ENOMEM,
+ RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Meter profile memory alloc failed!");
+ }
+ if (profile->alg == RTE_MTR_NONE) {
+ dpaa2_profile->mode = DPNI_POLICER_MODE_PASS_THROUGH;
+ } else if (profile->alg == RTE_MTR_TRTCM_RFC2698) {
+ dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_2698;
+ } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) {
+ dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_4115;
+ } else {
+ DPAA2_PMD_ERR("Policer profile alg(%d) not supported!",
+ profile->alg);
+ ret = -ENOTSUP;
+ goto err;
+ }
+
+ if (profile->alg == RTE_MTR_TRTCM_RFC2698) {
+ dpaa2_profile->cir = profile->trtcm_rfc2698.cir;
+ dpaa2_profile->cbs = profile->trtcm_rfc2698.cbs;
+ dpaa2_profile->pir = profile->trtcm_rfc2698.pir;
+ dpaa2_profile->pbs = profile->trtcm_rfc2698.pbs;
+ } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) {
+ dpaa2_profile->cir = profile->trtcm_rfc4115.cir;
+ dpaa2_profile->cbs = profile->trtcm_rfc4115.cbs;
+ dpaa2_profile->pir = profile->trtcm_rfc4115.eir;
+ dpaa2_profile->pbs = profile->trtcm_rfc4115.ebs;
+ }
+
+ /** Align with DPNI policy.*/
+ if (!profile->packet_mode) {
+ dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L3;
+ } else if (profile->packet_mode > DPNI_POLICER_UNIT_FRAMES) {
+ dpaa2_profile->policer_unit =
+ DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS;
+ } else {
+ dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_FRAMES;
+ }
+
+ dpaa2_profile->profile_id = profile_id;
+
+ rte_spinlock_lock(&priv->meter_lock);
+ curr = LIST_FIRST(&priv->profiles);
+ if (curr == NULL) {
+ LIST_INSERT_HEAD(&priv->profiles, dpaa2_profile, next);
+ } else {
+ while (LIST_NEXT(curr, next) != NULL)
+ curr = LIST_NEXT(curr, next);
+ LIST_INSERT_AFTER(curr, dpaa2_profile, next);
+ }
+ rte_spinlock_unlock(&priv->meter_lock);
+
+err:
+ if (ret != 0)
+ rte_free(dpaa2_profile);
+
+ return ret;
+}
+
+static int
+dpaa2_mtr_policy_add(struct rte_eth_dev *dev,
+ uint32_t policy_id, struct rte_mtr_meter_policy_params *policy,
+ struct rte_mtr_error *error)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_meter_policy *dpaa2_policy;
+ struct dpaa2_dev_meter_policy *curr;
+ const struct rte_flow_action *red_action;
+ bool red_drop = false;
+
+ if (policy->actions[RTE_COLOR_GREEN] != NULL) {
+ return -rte_mtr_error_set(error, ENOMEM,
+ RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN, NULL,
+ "Meter green policy action not supported!");
+ }
+ if (policy->actions[RTE_COLOR_YELLOW] != NULL) {
+ return -rte_mtr_error_set(error, ENOMEM,
+ RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW, NULL,
+ "Meter yellow policy action not supported!");
+ }
+
+ red_action = policy->actions[RTE_COLOR_RED];
+
+ if (red_action != NULL) {
+ if (red_action->type == RTE_FLOW_ACTION_TYPE_DROP) {
+ red_drop = true;
+ } else if (red_action->type != RTE_FLOW_ACTION_TYPE_PASSTHRU) {
+ snprintf(s_err_msg, sizeof(s_err_msg),
+ "Meter red policy action(%d) NOT supported!",
+ red_action->type);
+ return -rte_mtr_error_set(error, ENOMEM,
+ RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED, NULL,
+ s_err_msg);
+ }
+ }
+
+ dpaa2_policy = rte_zmalloc(NULL,
+ sizeof(struct dpaa2_dev_meter_policy), 0);
+ if (dpaa2_policy == NULL) {
+ return -rte_mtr_error_set(error, ENOMEM,
+ RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Meter policy memory alloc failed!");
+ }
+
+ dpaa2_policy->policy_id = policy_id;
+ dpaa2_policy->red_drop = red_drop;
+
+ rte_spinlock_lock(&priv->meter_lock);
+ curr = LIST_FIRST(&priv->policies);
+ if (curr == NULL) {
+ LIST_INSERT_HEAD(&priv->policies, dpaa2_policy, next);
+ } else {
+ while (LIST_NEXT(curr, next) != NULL)
+ curr = LIST_NEXT(curr, next);
+ LIST_INSERT_AFTER(curr, dpaa2_policy, next);
+ }
+ rte_spinlock_unlock(&priv->meter_lock);
+
+ return 0;
+}
+
+static struct rte_flow_meter_profile *
+dpaa2_mtr_profile_get(struct rte_eth_dev *dev,
+ uint32_t meter_profile_id, struct rte_mtr_error *error)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_meter_profile *dpaa2_profile;
+
+ RTE_SET_USED(error);
+
+ rte_spinlock_lock(&priv->meter_lock);
+ dpaa2_profile = LIST_FIRST(&priv->profiles);
+ while (dpaa2_profile != NULL) {
+ if (dpaa2_profile->profile_id == meter_profile_id) {
+ rte_spinlock_unlock(&priv->meter_lock);
+ return (struct rte_flow_meter_profile *)dpaa2_profile;
+ }
+ dpaa2_profile = LIST_NEXT(dpaa2_profile, next);
+ }
+ rte_spinlock_unlock(&priv->meter_lock);
+
+ return NULL;
+}
+
+static struct rte_flow_meter_policy *
+dpaa2_mtr_policy_get(struct rte_eth_dev *dev,
+ uint32_t policy_id, struct rte_mtr_error *error)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_meter_policy *dpaa2_policy;
+
+ RTE_SET_USED(error);
+
+ rte_spinlock_lock(&priv->meter_lock);
+ dpaa2_policy = LIST_FIRST(&priv->policies);
+ while (dpaa2_policy != NULL) {
+ if (dpaa2_policy->policy_id == policy_id) {
+ rte_spinlock_unlock(&priv->meter_lock);
+ return (struct rte_flow_meter_policy *)dpaa2_policy;
+ }
+ dpaa2_policy = LIST_NEXT(dpaa2_policy, next);
+ }
+ rte_spinlock_unlock(&priv->meter_lock);
+
+ return NULL;
+}
+
+static int
+dpaa2_mtr_profile_delete(struct rte_eth_dev *dev,
+ uint32_t profile_id, struct rte_mtr_error *error)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_meter_profile *dpaa2_profile = NULL, *curr;
+ struct dpaa2_dev_meter *meter, *tmp;
+
+ rte_spinlock_lock(&priv->meter_lock);
+ curr = LIST_FIRST(&priv->profiles);
+ while (curr != NULL) {
+ if (curr->profile_id == profile_id) {
+ dpaa2_profile = curr;
+ break;
+ }
+ curr = LIST_NEXT(curr, next);
+ }
+ if (dpaa2_profile == NULL) {
+ rte_spinlock_unlock(&priv->meter_lock);
+ return -rte_mtr_error_set(error, ENOENT,
+ RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+ &profile_id, "Meter profile is invalid.");
+ }
+
+ meter = LIST_FIRST(&priv->meters);
+ while (meter != NULL) {
+ if (meter->profile_id == profile_id) {
+ DPAA2_PMD_INFO("Meter(id=%d) with profile(%d) is removed!",
+ meter->meter_id, profile_id);
+ tmp = meter;
+ meter = LIST_NEXT(meter, next);
+ LIST_REMOVE(tmp, next);
+ rte_free(tmp);
+ } else {
+ meter = LIST_NEXT(meter, next);
+ }
+ }
+
+ LIST_REMOVE(dpaa2_profile, next);
+ rte_free(dpaa2_profile);
+ rte_spinlock_unlock(&priv->meter_lock);
+
+ return 0;
+}
+
+static int
+dpaa2_mtr_policy_delete(struct rte_eth_dev *dev,
+ uint32_t policy_id, struct rte_mtr_error *error)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_meter_policy *dpaa2_policy = NULL, *curr;
+ struct dpaa2_dev_meter *meter, *tmp;
+
+ rte_spinlock_lock(&priv->meter_lock);
+ curr = LIST_FIRST(&priv->policies);
+ while (curr != NULL) {
+ if (curr->policy_id == policy_id) {
+ dpaa2_policy = curr;
+ break;
+ }
+ curr = LIST_NEXT(curr, next);
+ }
+ if (dpaa2_policy == NULL) {
+ rte_spinlock_unlock(&priv->meter_lock);
+ return -rte_mtr_error_set(error, ENOENT,
+ RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+ NULL, "Meter policy is invalid.");
+ }
+
+ meter = LIST_FIRST(&priv->meters);
+ while (meter != NULL) {
+ if (meter->policy_id == policy_id) {
+ DPAA2_PMD_INFO("Meter(id=%d) with policy(%d) is removed!",
+ meter->meter_id, policy_id);
+ tmp = meter;
+ meter = LIST_NEXT(meter, next);
+ LIST_REMOVE(tmp, next);
+ rte_free(tmp);
+ } else {
+ meter = LIST_NEXT(meter, next);
+ }
+ }
+
+ LIST_REMOVE(dpaa2_policy, next);
+ rte_free(dpaa2_policy);
+ rte_spinlock_unlock(&priv->meter_lock);
+
+ return 0;
+}
+
+static int
+dpaa2_mtr_meter_create(struct rte_eth_dev *dev,
+ uint32_t mtr_id, struct rte_mtr_params *params,
+ int shared, struct rte_mtr_error *error)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_meter_profile *profile;
+ struct dpaa2_dev_meter_policy *policy;
+ struct dpaa2_dev_meter *meter, *curr;
+ uint32_t profile_id, policy_id;
+ enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE;
+ bool found = false;
+ int ret = 0;
+
+ RTE_SET_USED(shared);
+ profile_id = params->meter_profile_id;
+ policy_id = params->meter_policy_id;
+
+ rte_spinlock_lock(&priv->meter_lock);
+ profile = LIST_FIRST(&priv->profiles);
+ while (profile != NULL) {
+ if (profile->profile_id == profile_id) {
+ found = true;
+ break;
+ }
+ profile = LIST_NEXT(profile, next);
+ }
+ if (!found) {
+ snprintf(s_err_msg, sizeof(s_err_msg),
+ "Meter profile ID(%d) not exist!", profile_id);
+ ret = ENOENT;
+ err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID;
+ goto quit;
+ }
+
+ found = false;
+ policy = LIST_FIRST(&priv->policies);
+ while (policy != NULL) {
+ if (policy->policy_id == policy_id) {
+ found = true;
+ break;
+ }
+ policy = LIST_NEXT(policy, next);
+ }
+ if (!found) {
+ snprintf(s_err_msg, sizeof(s_err_msg),
+ "Meter policy ID(%d) not exist!", policy_id);
+ ret = ENOENT;
+ err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID;
+ goto quit;
+ }
+
+ meter = LIST_FIRST(&priv->meters);
+ while (meter != NULL) {
+ if (meter->meter_id == mtr_id) {
+ snprintf(s_err_msg, sizeof(s_err_msg),
+ "Meter ID(%d) exist!", mtr_id);
+ ret = EEXIST;
+ err_type = RTE_MTR_ERROR_TYPE_MTR_ID;
+ goto quit;
+ }
+ meter = LIST_NEXT(meter, next);
+ }
+ meter = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_meter), 0);
+ if (meter == NULL) {
+ snprintf(s_err_msg, sizeof(s_err_msg),
+ "Meter memory alloc failed!");
+ ret = ENOMEM;
+ err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED;
+ goto quit;
+ }
+ meter->meter_id = mtr_id;
+ meter->profile_id = profile_id;
+ meter->policy_id = policy_id;
+
+ curr = LIST_FIRST(&priv->meters);
+ if (curr == NULL) {
+ LIST_INSERT_HEAD(&priv->meters, meter, next);
+ } else {
+ while (LIST_NEXT(curr, next) != NULL)
+ curr = LIST_NEXT(curr, next);
+ LIST_INSERT_AFTER(curr, meter, next);
+ }
+
+quit:
+ rte_spinlock_unlock(&priv->meter_lock);
+ if (ret != 0)
+ return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg);
+
+ return 0;
+}
+
+static int
+dpaa2_mtr_meter_destroy(struct rte_eth_dev *dev,
+ uint32_t mtr_id, struct rte_mtr_error *error)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_meter *meter;
+
+ rte_spinlock_lock(&priv->meter_lock);
+ meter = LIST_FIRST(&priv->meters);
+ while (meter != NULL) {
+ if (meter->meter_id == mtr_id) {
+ LIST_REMOVE(meter, next);
+ rte_free(meter);
+ rte_spinlock_unlock(&priv->meter_lock);
+
+ return 0;
+ }
+ meter = LIST_NEXT(meter, next);
+ }
+ snprintf(s_err_msg, sizeof(s_err_msg),
+ "Meter ID(%d) does not exist!", mtr_id);
+ rte_spinlock_unlock(&priv->meter_lock);
+ return -rte_mtr_error_set(error, ENOENT,
+ RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg);
+}
+
+static int
+dpaa2_mtr_meter_profile_update(struct rte_eth_dev *dev,
+ uint32_t mtr_id, uint32_t profile_id,
+ struct rte_mtr_error *error)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_meter_profile *profile;
+ struct dpaa2_dev_meter *meter;
+ enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE;
+ bool found = false;
+ int ret = 0;
+
+ rte_spinlock_lock(&priv->meter_lock);
+ meter = LIST_FIRST(&priv->meters);
+ while (meter != NULL) {
+ if (meter->meter_id == mtr_id) {
+ found = true;
+ break;
+ }
+ meter = LIST_NEXT(meter, next);
+ }
+ if (!found) {
+ snprintf(s_err_msg, sizeof(s_err_msg),
+ "Meter ID(%d) not found!", mtr_id);
+ ret = ENOENT;
+ err_type = RTE_MTR_ERROR_TYPE_MTR_ID;
+ goto quit;
+ }
+
+ found = false;
+ profile = LIST_FIRST(&priv->profiles);
+ while (profile != NULL) {
+ if (profile->profile_id == profile_id) {
+ found = true;
+ break;
+ }
+ profile = LIST_NEXT(profile, next);
+ }
+ if (!found) {
+ snprintf(s_err_msg, sizeof(s_err_msg),
+ "Profile ID(%d) not found!", profile_id);
+ ret = ENOENT;
+ err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID;
+ goto quit;
+ }
+ meter->profile_id = profile_id;
+
+quit:
+ rte_spinlock_unlock(&priv->meter_lock);
+ if (ret != 0)
+ return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg);
+
+ return 0;
+}
+
+static int
+dpaa2_mtr_meter_policy_update(struct rte_eth_dev *dev,
+ uint32_t mtr_id, uint32_t policy_id,
+ struct rte_mtr_error *error)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_meter_policy *policy;
+ struct dpaa2_dev_meter *meter;
+ enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE;
+ bool found = false;
+ int ret = 0;
+
+ rte_spinlock_lock(&priv->meter_lock);
+ meter = LIST_FIRST(&priv->meters);
+ while (meter != NULL) {
+ if (meter->meter_id == mtr_id) {
+ found = true;
+ break;
+ }
+ meter = LIST_NEXT(meter, next);
+ }
+ if (!found) {
+ snprintf(s_err_msg, sizeof(s_err_msg),
+ "Meter ID(%d) not found!", mtr_id);
+ ret = ENOENT;
+ err_type = RTE_MTR_ERROR_TYPE_MTR_ID;
+ goto quit;
+ }
+
+ found = false;
+ policy = LIST_FIRST(&priv->policies);
+ while (policy != NULL) {
+ if (policy->policy_id == policy_id) {
+ found = true;
+ break;
+ }
+ policy = LIST_NEXT(policy, next);
+ }
+ if (!found) {
+ snprintf(s_err_msg, sizeof(s_err_msg),
+ "Profile ID(%d) not found!", policy_id);
+ ret = ENOENT;
+ err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID;
+ goto quit;
+ }
+ meter->policy_id = policy_id;
+
+quit:
+ rte_spinlock_unlock(&priv->meter_lock);
+ if (ret != 0)
+ return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg);
+
+ return 0;
+}
+
+static const struct rte_mtr_ops dpaa2_meter_ops = {
+ .capabilities_get = dpaa2_mtr_capabilities_get,
+ .meter_profile_add = dpaa2_mtr_profile_add,
+ .meter_profile_delete = dpaa2_mtr_profile_delete,
+ .meter_policy_add = dpaa2_mtr_policy_add,
+ .meter_policy_delete = dpaa2_mtr_policy_delete,
+ .meter_profile_get = dpaa2_mtr_profile_get,
+ .meter_policy_get = dpaa2_mtr_policy_get,
+ .create = dpaa2_mtr_meter_create,
+ .destroy = dpaa2_mtr_meter_destroy,
+ .meter_profile_update = dpaa2_mtr_meter_profile_update,
+ .meter_policy_update = dpaa2_mtr_meter_policy_update,
+};
+
+int
+dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+
+ rte_spinlock_init(&priv->meter_lock);
+
+ *(const void **)ops = &dpaa2_meter_ops;
+ return 0;
+}
diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h
index 8913b408e7..d227025e01 100644
--- a/drivers/net/dpaa2/mc/fsl_dpni.h
+++ b/drivers/net/dpaa2/mc/fsl_dpni.h
@@ -1111,6 +1111,11 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io,
*/
#define DPNI_POLICER_OPT_DISCARD_RED 0x00000002
+/**
+ * Do NOT reset counters generally for policer update
+ */
+#define DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS 0x00000004
+
/**
* enum dpni_policer_mode - selecting the policer mode
* @DPNI_POLICER_MODE_NONE: Policer is disabled
@@ -1127,12 +1132,17 @@ enum dpni_policer_mode {
/**
* enum dpni_policer_unit - DPNI policer units
- * @DPNI_POLICER_UNIT_BYTES: bytes units
+ * @DPNI_POLICER_UNIT_BYTES_L3: bytes units (for each frame takes into account
+ * FD length - L3 offset)
* @DPNI_POLICER_UNIT_FRAMES: frames units
+ * @DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS: bytes units (for each frame takes
+ * into account FD length - L2 offset, which means L2 size without the 4 bytes
+ * for the FCS)
*/
enum dpni_policer_unit {
- DPNI_POLICER_UNIT_BYTES = 0,
- DPNI_POLICER_UNIT_FRAMES
+ DPNI_POLICER_UNIT_BYTES_L3 = 0,
+ DPNI_POLICER_UNIT_FRAMES,
+ DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS,
};
/**
@@ -1173,13 +1183,18 @@ struct dpni_rx_tc_policing_cfg {
uint32_t ebs;
};
-
int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t tc_id,
const struct dpni_rx_tc_policing_cfg *cfg);
+int dpni_set_rx_tc_policing_v1(struct fsl_mc_io *mc_io,
+ uint32_t cmd_flags,
+ uint16_t token,
+ uint8_t tc_id,
+ const struct dpni_rx_tc_policing_cfg *cfg);
+
int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build
index 4094ea02ba..808dad8112 100644
--- a/drivers/net/dpaa2/meson.build
+++ b/drivers/net/dpaa2/meson.build
@@ -11,6 +11,7 @@ sources = files(
'base/dpaa2_hw_dpni.c',
'base/dpaa2_tlu_hash.c',
'dpaa2_tm.c',
+ 'dpaa2_meter.c',
'dpaa2_mux.c',
'dpaa2_ethdev.c',
'dpaa2_flow.c',
--
2.43.0
More information about the dev
mailing list