net/mlx5: add policer rules operations
[dpdk.git] / drivers / net / mlx5 / mlx5_flow.c
index 61afc48..2016ead 100644 (file)
@@ -344,6 +344,7 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev,
 {
        struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_dev_config *config = &priv->config;
+       enum modify_reg start_reg;
 
        switch (feature) {
        case MLX5_HAIRPIN_RX:
@@ -375,24 +376,53 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev,
                }
                break;
        case MLX5_COPY_MARK:
-               return REG_C_3;
+       case MLX5_MTR_SFX:
+               /*
+                * Metadata COPY_MARK register using is in meter suffix sub
+                * flow while with meter. It's safe to share the same register.
+                */
+               return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : REG_C_3;
+       case MLX5_MTR_COLOR:
+               RTE_ASSERT(priv->mtr_color_reg != REG_NONE);
+               return priv->mtr_color_reg;
        case MLX5_APP_TAG:
                /*
-                * Suppose engaging reg_c_2 .. reg_c_7 registers.
-                * reg_c_2 is reserved for coloring by meters.
-                * reg_c_3 is reserved for split flows TAG.
+                * If meter is enable, it will engage two registers for color
+                * match and flow match. If meter color match is not using the
+                * REG_C_2, need to skip the REG_C_x be used by meter color
+                * match.
+                * If meter is disable, free to use all available registers.
                 */
-               if (id > (REG_C_7 - REG_C_4))
-                       return rte_flow_error_set
-                                       (error, EINVAL,
-                                        RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-                                        NULL, "invalid tag id");
-               if (config->flow_mreg_c[id + REG_C_4 - REG_C_0] == REG_NONE)
-                       return rte_flow_error_set
-                                       (error, ENOTSUP,
-                                        RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-                                        NULL, "unsupported tag id");
-               return config->flow_mreg_c[id + REG_C_4 - REG_C_0];
+               if (priv->mtr_color_reg != REG_NONE)
+                       start_reg = priv->mtr_color_reg != REG_C_2 ? REG_C_3 :
+                                   REG_C_4;
+               else
+                       start_reg = REG_C_2;
+               if (id > (REG_C_7 - start_reg))
+                       return rte_flow_error_set(error, EINVAL,
+                                                 RTE_FLOW_ERROR_TYPE_ITEM,
+                                                 NULL, "invalid tag id");
+               if (config->flow_mreg_c[id + start_reg - REG_C_0] == REG_NONE)
+                       return rte_flow_error_set(error, ENOTSUP,
+                                                 RTE_FLOW_ERROR_TYPE_ITEM,
+                                                 NULL, "unsupported tag id");
+               /*
+                * This case means meter is using the REG_C_x great than 2.
+                * Take care not to conflict with meter color REG_C_x.
+                * If the available index REG_C_y >= REG_C_x, skip the
+                * color register.
+                */
+               if (start_reg == REG_C_3 && config->flow_mreg_c
+                   [id + REG_C_3 - REG_C_0] >= priv->mtr_color_reg) {
+                       if (config->flow_mreg_c[id + 1 + REG_C_3 - REG_C_0] !=
+                           REG_NONE)
+                               return config->flow_mreg_c
+                                               [id + 1 + REG_C_3 - REG_C_0];
+                       return rte_flow_error_set(error, ENOTSUP,
+                                                 RTE_FLOW_ERROR_TYPE_ITEM,
+                                                 NULL, "unsupported tag id");
+               }
+               return config->flow_mreg_c[id + start_reg - REG_C_0];
        }
        assert(false);
        return rte_flow_error_set(error, EINVAL,
@@ -4881,6 +4911,91 @@ mlx5_dev_filter_ctrl(struct rte_eth_dev *dev,
        return 0;
 }
 
+/**
+ * Create the needed meter and suffix tables.
+ *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
+ *
+ * @return
+ *   Pointer to table set on success, NULL otherwise.
+ */
+struct mlx5_meter_domains_infos *
+mlx5_flow_create_mtr_tbls(struct rte_eth_dev *dev)
+{
+       const struct mlx5_flow_driver_ops *fops;
+
+       fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
+       return fops->create_mtr_tbls(dev);
+}
+
+/**
+ * Destroy the meter table set.
+ *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
+ * @param[in] tbl
+ *   Pointer to the meter table set.
+ *
+ * @return
+ *   0 on success.
+ */
+int
+mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
+                          struct mlx5_meter_domains_infos *tbls)
+{
+       const struct mlx5_flow_driver_ops *fops;
+
+       fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
+       return fops->destroy_mtr_tbls(dev, tbls);
+}
+
+/**
+ * Create policer rules.
+ *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
+ * @param[in] fm
+ *   Pointer to flow meter structure.
+ * @param[in] attr
+ *   Pointer to flow attributes.
+ *
+ * @return
+ *   0 on success, -1 otherwise.
+ */
+int
+mlx5_flow_create_policer_rules(struct rte_eth_dev *dev,
+                              struct mlx5_flow_meter *fm,
+                              const struct rte_flow_attr *attr)
+{
+       const struct mlx5_flow_driver_ops *fops;
+
+       fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
+       return fops->create_policer_rules(dev, fm, attr);
+}
+
+/**
+ * Destroy policer rules.
+ *
+ * @param[in] fm
+ *   Pointer to flow meter structure.
+ * @param[in] attr
+ *   Pointer to flow attributes.
+ *
+ * @return
+ *   0 on success, -1 otherwise.
+ */
+int
+mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,
+                               struct mlx5_flow_meter *fm,
+                               const struct rte_flow_attr *attr)
+{
+       const struct mlx5_flow_driver_ops *fops;
+
+       fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
+       return fops->destroy_policer_rules(dev, fm, attr);
+}
+
 #define MLX5_POOL_QUERY_FREQ_US 1000000
 
 /**