diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index a16af32e67..de04931f80 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -107,6 +107,7 @@ Features
 - 21844 flow priorities for ingress or egress flow groups greater than 0 and for any transfer
   flow group.
 - Flow metering, including meter policy API.
+- Flow meter hierarchy.
 - Flow integrity offload API.
 - Connection tracking.
 - Sub-Function representors.
@@ -1927,3 +1928,17 @@ This section demonstrates how to use the shared meter. A meter M can be created
 on port X and to be shared with a port Y on the same switch domain by the next way:
 
         flow create X ingress transfer pattern eth / port_id id is Y / end actions meter mtr_id M / end
+
+How to use meter hierarchy
+--------------------------
+
+This section demonstrates how to create and use a meter hierarchy.
+A termination meter M can be the policy green action of another termination meter N.
+The two meters are chained together as a chain. Using meter N in a flow will apply
+both the meters in hierarchy on that flow.
+
+        add port meter policy 0 1 g_actions queue index 0 / end y_actions end r_actions drop / end
+        create port meter 0 M 1 1 yes 0xffff 1 0
+        add port meter policy 0 2 g_actions meter mtr_id M / end y_actions end r_actions drop / end
+        create port meter 0 N 2 2 yes 0xffff 1 0
+        flow create 0 ingress group 1 pattern eth / end actions meter mtr_id N / end
diff --git a/doc/guides/rel_notes/release_21_08.rst b/doc/guides/rel_notes/release_21_08.rst
index 0a05cb02fa..b29d78f4de 100644
--- a/doc/guides/rel_notes/release_21_08.rst
+++ b/doc/guides/rel_notes/release_21_08.rst
@@ -68,6 +68,12 @@ New Features
   usecases. Configuration happens via standard rawdev enq/deq operations. See
   the :doc:`../rawdevs/cnxk_bphy` rawdev guide for more details on this driver.
 
+* **Updated Mellanox mlx5 driver.**
+
+  Updated the Mellanox mlx5 driver with new features and improvements, including:
+
+  * Added support for Meter hierarchy.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 681e6fb07c..c085deed50 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -16858,6 +16858,78 @@ flow_dv_action_validate(struct rte_eth_dev *dev,
 	}
 }
 
+/**
+ * Validate the meter hierarchy chain for meter policy.
+ *
+ * @param[in] dev
+ *   Pointer to the Ethernet device structure.
+ * @param[in] meter_id
+ *   Meter id.
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[out] is_rss
+ *   Is RSS or not.
+ * @param[out] hierarchy_domain
+ *   The domain bitmap for hierarchy policy.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. Initialized in case of
+ *   error only.
+ *
+ * @return
+ *   0 on success, otherwise negative errno value with error set.
+ */
+static int
+flow_dv_validate_policy_mtr_hierarchy(struct rte_eth_dev *dev,
+				  uint32_t meter_id,
+				  uint64_t action_flags,
+				  bool *is_rss,
+				  uint8_t *hierarchy_domain,
+				  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;
+	uint8_t cnt = 1;
+
+	if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
+			    MLX5_FLOW_FATE_ESWITCH_ACTIONS))
+		return -rte_mtr_error_set(error, EINVAL,
+					RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
+					NULL,
+					"Multiple fate actions not supported.");
+	while (true) {
+		fm = mlx5_flow_meter_find(priv, meter_id, NULL);
+		if (!fm)
+			return -rte_mtr_error_set(error, EINVAL,
+						RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
+					"Meter not found in meter hierarchy.");
+		if (fm->def_policy)
+			return -rte_mtr_error_set(error, EINVAL,
+					RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
+			"Non termination meter not supported in hierarchy.");
+		policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
+		MLX5_ASSERT(policy);
+		if (!policy->is_hierarchy) {
+			if (policy->transfer)
+				*hierarchy_domain |=
+						MLX5_MTR_DOMAIN_TRANSFER_BIT;
+			if (policy->ingress)
+				*hierarchy_domain |=
+						MLX5_MTR_DOMAIN_INGRESS_BIT;
+			if (policy->egress)
+				*hierarchy_domain |= MLX5_MTR_DOMAIN_EGRESS_BIT;
+			*is_rss = policy->is_rss;
+			break;
+		}
+		meter_id = policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id;
+		if (++cnt >= MLX5_MTR_CHAIN_MAX_NUM)
+			return -rte_mtr_error_set(error, EINVAL,
+					RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
+					"Exceed max hierarchy meter number.");
+	}
+	return 0;
+}
+
 /**
  * Validate meter policy actions.
  * Dispatcher for action type specific validation.
@@ -16893,6 +16965,8 @@ flow_dv_validate_mtr_policy_acts(struct rte_eth_dev *dev,
 	struct rte_flow_error flow_err;
 	uint8_t domain_color[RTE_COLORS] = {0};
 	uint8_t def_domain = MLX5_MTR_ALL_DOMAIN_BIT;
+	uint8_t hierarchy_domain = 0;
+	const struct rte_flow_action_meter *mtr;
 
 	if (!priv->config.dv_esw_en)
 		def_domain &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
@@ -17070,6 +17144,27 @@ flow_dv_validate_mtr_policy_acts(struct rte_eth_dev *dev,
 				++actions_n;
 				action_flags |= MLX5_FLOW_ACTION_JUMP;
 				break;
+			case RTE_FLOW_ACTION_TYPE_METER:
+				if (i != RTE_COLOR_GREEN)
+					return -rte_mtr_error_set(error,
+						ENOTSUP,
+						RTE_MTR_ERROR_TYPE_METER_POLICY,
+						NULL, flow_err.message ?
+						flow_err.message :
+				  "Meter hierarchy only supports GREEN color.");
+				mtr = act->conf;
+				ret = flow_dv_validate_policy_mtr_hierarchy(dev,
+							mtr->mtr_id,
+							action_flags,
+							is_rss,
+							&hierarchy_domain,
+							error);
+				if (ret)
+					return ret;
+				++actions_n;
+				action_flags |=
+				MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;
+				break;
 			default:
 				return -rte_mtr_error_set(error, ENOTSUP,
 					RTE_MTR_ERROR_TYPE_METER_POLICY,
@@ -17090,6 +17185,9 @@ flow_dv_validate_mtr_policy_acts(struct rte_eth_dev *dev,
 			 * so MARK action only in ingress domain.
 			 */
 			domain_color[i] = MLX5_MTR_DOMAIN_INGRESS_BIT;
+		else if (action_flags &
+			MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)
+			domain_color[i] = hierarchy_domain;
 		else
 			domain_color[i] = def_domain;
 		/*
