DPDK patches and discussions
 help / color / mirror / Atom feed
From: Shun Hao <shunh@nvidia.com>
To: <orika@nvidia.com>, <viacheslavo@nvidia.com>, <matan@nvidia.com>,
	"Shahaf Shuler" <shahafs@nvidia.com>
Cc: <dev@dpdk.org>, <thomas@monjalon.net>, <rasland@nvidia.com>
Subject: [dpdk-dev] [PATCH v1 3/4] net/mlx5: meter hierarchy destroy and cleanup
Date: Tue, 6 Jul 2021 16:14:49 +0300	[thread overview]
Message-ID: <20210706131450.30917-4-shunh@nvidia.com> (raw)
In-Reply-To: <20210706131450.30917-1-shunh@nvidia.com>

When creating hierarchy meter, its color rules will increase next
meter's reference count, so when destroy the hierarchy meter, also
need to dereference the next meter's count.

During flushing all meters of a port, need to destroy all hierarchy
meters and their policies first, to dereference the last meter in
hierarchy. Then all meters have no reference and can be destroyed.

Signed-off-by: Shun Hao <shunh@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow_dv.c    |  15 +++-
 drivers/net/mlx5/mlx5_flow_meter.c | 132 +++++++++++++++++++++++++++++
 2 files changed, 145 insertions(+), 2 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 119de09809..681e6fb07c 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -14588,12 +14588,20 @@ static void
 __flow_dv_destroy_sub_policy_rules(struct rte_eth_dev *dev,
 			     struct mlx5_flow_meter_sub_policy *sub_policy)
 {
+	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_flow_tbl_data_entry *tbl;
+	struct mlx5_flow_meter_policy *policy = sub_policy->main_policy;
+	struct mlx5_flow_meter_info *next_fm;
 	struct mlx5_sub_policy_color_rule *color_rule;
 	void *tmp;
-	int i;
+	uint32_t i;
 
 	for (i = 0; i < RTE_COLORS; i++) {
+		next_fm = NULL;
+		if (i == RTE_COLOR_GREEN && policy &&
+		    policy->act_cnt[i].fate_action == MLX5_FLOW_FATE_MTR)
+			next_fm = mlx5_flow_meter_find(priv,
+					policy->act_cnt[i].next_mtr_id, NULL);
 		TAILQ_FOREACH_SAFE(color_rule, &sub_policy->color_rules[i],
 				   next_port, tmp) {
 			claim_zero(mlx5_flow_os_destroy_flow(color_rule->rule));
@@ -14604,11 +14612,14 @@ __flow_dv_destroy_sub_policy_rules(struct rte_eth_dev *dev,
 			TAILQ_REMOVE(&sub_policy->color_rules[i],
 					color_rule, next_port);
 			mlx5_free(color_rule);
+			if (next_fm)
+				mlx5_flow_meter_detach(priv, next_fm);
 		}
 	}
 	for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
 		if (sub_policy->rix_hrxq[i]) {
-			mlx5_hrxq_release(dev, sub_policy->rix_hrxq[i]);
+			if (policy && !policy->is_hierarchy)
+				mlx5_hrxq_release(dev, sub_policy->rix_hrxq[i]);
 			sub_policy->rix_hrxq[i] = 0;
 		}
 		if (sub_policy->jump_tbl[i]) {
diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c
index 03f7e120e1..78eb2a60f9 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -1891,6 +1891,136 @@ mlx5_flow_meter_rxq_flush(struct rte_eth_dev *dev)
 	}
 }
 
+/**
+ * Iterate a meter hierarchy and flush all meters and policies if possible.
+ *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
+ * @param[in] fm
+ *   Pointer to flow meter.
+ * @param[in] mtr_idx
+ *   .Meter's index
+ * @param[out] error
+ *   Pointer to rte meter error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+mlx5_flow_meter_flush_hierarchy(struct rte_eth_dev *dev,
+				struct mlx5_flow_meter_info *fm,
+				uint32_t mtr_idx,
+				struct rte_mtr_error *error)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_flow_meter_policy *policy;
+	uint32_t policy_id;
+	struct mlx5_flow_meter_info *next_fm;
+	uint32_t next_mtr_idx;
+	struct mlx5_flow_meter_policy *next_policy = NULL;
+
+	policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
+	MLX5_ASSERT(policy);
+	while (!fm->ref_cnt && policy->is_hierarchy) {
+		policy_id = fm->policy_id;
+		next_fm = mlx5_flow_meter_find(priv,
+				policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
+				&next_mtr_idx);
+		if (next_fm) {
+			next_policy = mlx5_flow_meter_policy_find(dev,
+							next_fm->policy_id,
+							NULL);
+			MLX5_ASSERT(next_policy);
+		}
+		if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
+			return -rte_mtr_error_set(error, ENOTSUP,
+						RTE_MTR_ERROR_TYPE_MTR_ID,
+						NULL,
+						"Failed to flush meter.");
+		if (policy->ref_cnt)
+			break;
+		if (__mlx5_flow_meter_policy_delete(dev, policy_id,
+						policy, error, true))
+			return -rte_errno;
+		mlx5_free(policy);
+		if (!next_fm || !next_policy)
+			break;
+		fm = next_fm;
+		mtr_idx = next_mtr_idx;
+		policy = next_policy;
+	}
+	return 0;
+}
+
+/**
+ * Flush all the hierarchy meters and their policies.
+ *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
+ * @param[out] error
+ *   Pointer to rte meter error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+mlx5_flow_meter_flush_all_hierarchies(struct rte_eth_dev *dev,
+				      struct rte_mtr_error *error)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_flow_meter_info *fm;
+	struct mlx5_flow_meter_policy *policy;
+	struct mlx5_flow_meter_sub_policy *sub_policy;
+	struct mlx5_flow_meter_info *next_fm;
+	struct mlx5_aso_mtr *aso_mtr;
+	uint32_t mtr_idx = 0;
+	uint32_t i, policy_idx;
+	void *entry;
+
+	if (!priv->mtr_idx_tbl || !priv->policy_idx_tbl)
+		return 0;
+	MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
+		mtr_idx = *(uint32_t *)entry;
+		if (!mtr_idx)
+			continue;
+		aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
+		fm = &aso_mtr->fm;
+		if (fm->ref_cnt || fm->def_policy)
+			continue;
+		if (mlx5_flow_meter_flush_hierarchy(dev, fm, mtr_idx, error))
+			return -rte_errno;
+	}
+	MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
+		policy_idx = *(uint32_t *)entry;
+		sub_policy = mlx5_ipool_get
+				(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
+				policy_idx);
+		if (!sub_policy)
+			return -rte_mtr_error_set(error,
+					EINVAL,
+					RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+					NULL, "Meter policy invalid.");
+		policy = sub_policy->main_policy;
+		if (!policy || !policy->is_hierarchy || policy->ref_cnt)
+			continue;
+		next_fm = mlx5_flow_meter_find(priv,
+				policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
+				&mtr_idx);
+		if (__mlx5_flow_meter_policy_delete(dev, i, policy,
+						    error, true))
+			return -rte_mtr_error_set(error,
+					EINVAL,
+					RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+					NULL, "Meter policy invalid.");
+		mlx5_free(policy);
+		if (!next_fm || next_fm->ref_cnt || next_fm->def_policy)
+			continue;
+		if (mlx5_flow_meter_flush_hierarchy(dev, next_fm,
+						    mtr_idx, error))
+			return -rte_errno;
+	}
+	return 0;
+}
 /**
  * Flush meter configuration.
  *
@@ -1919,6 +2049,8 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
 	if (!priv->mtr_en)
 		return 0;
 	if (priv->sh->meter_aso_en) {
+		if (mlx5_flow_meter_flush_all_hierarchies(dev, error))
+			return -rte_errno;
 		if (priv->mtr_idx_tbl) {
 			MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
 				mtr_idx = *(uint32_t *)entry;
-- 
2.21.0


  parent reply	other threads:[~2021-07-06 13:15 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-06 13:14 [dpdk-dev] [PATCH v1 0/4] Add support for meter hierarchy Shun Hao
2021-07-06 13:14 ` [dpdk-dev] [PATCH v1 1/4] net/mlx5: support meter action in meter policy Shun Hao
2021-07-06 13:14 ` [dpdk-dev] [PATCH v1 2/4] net/mlx5: support meter hierarchy drop count Shun Hao
2021-07-06 13:14 ` Shun Hao [this message]
2021-07-06 13:14 ` [dpdk-dev] [PATCH v1 4/4] net/mlx5: validate meter action in policy Shun Hao
2021-07-07  7:19 ` [dpdk-dev] [PATCH v1 0/4] Add support for meter hierarchy Raslan Darawsheh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210706131450.30917-4-shunh@nvidia.com \
    --to=shunh@nvidia.com \
    --cc=dev@dpdk.org \
    --cc=matan@nvidia.com \
    --cc=orika@nvidia.com \
    --cc=rasland@nvidia.com \
    --cc=shahafs@nvidia.com \
    --cc=thomas@monjalon.net \
    --cc=viacheslavo@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).