This adds the validation when creating a policy with meter action.

Currently meter action is only allowed for green color in policy, and
8 meters are supported at maximum in one meter hierarchy.

Signed-off-by: Shun Hao <sh...@nvidia.com>
Acked-by: Matan Azrad <ma...@nvidia.com>
---
 doc/guides/nics/mlx5.rst               | 15 ++++
 doc/guides/rel_notes/release_21_08.rst |  6 ++
 drivers/net/mlx5/mlx5_flow_dv.c        | 98 ++++++++++++++++++++++++++
 3 files changed, 119 insertions(+)

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;
                /*
-- 
2.21.0

Reply via email to