1d740eb50SSuanming Mou // SPDX-License-Identifier: BSD-3-Clause 2d740eb50SSuanming Mou /* 3d740eb50SSuanming Mou * Copyright 2018 Mellanox Technologies, Ltd 4d740eb50SSuanming Mou */ 5d740eb50SSuanming Mou #include <math.h> 6d740eb50SSuanming Mou 702e76468SSuanming Mou #include <rte_tailq.h> 83bd26b23SSuanming Mou #include <rte_malloc.h> 9d740eb50SSuanming Mou #include <rte_mtr.h> 10d740eb50SSuanming Mou #include <rte_mtr_driver.h> 11d740eb50SSuanming Mou 127b4f1e6bSMatan Azrad #include <mlx5_devx_cmds.h> 1383c2047cSSuanming Mou #include <mlx5_malloc.h> 147b4f1e6bSMatan Azrad 15d740eb50SSuanming Mou #include "mlx5.h" 166bc327b9SSuanming Mou #include "mlx5_flow.h" 176bc327b9SSuanming Mou 18bf5c4d0bSDariusz Sosnowski #ifdef HAVE_MLX5_HWS_SUPPORT 19bf5c4d0bSDariusz Sosnowski 20ddbb689bSDariusz Sosnowski static void 21ddbb689bSDariusz Sosnowski mlx5_flow_meter_uninit_guest(struct rte_eth_dev *dev) 22ddbb689bSDariusz Sosnowski { 23ddbb689bSDariusz Sosnowski struct mlx5_priv *priv = dev->data->dev_private; 24ddbb689bSDariusz Sosnowski 25ddbb689bSDariusz Sosnowski if (priv->hws_mpool) { 26ddbb689bSDariusz Sosnowski if (priv->hws_mpool->action) { 27ddbb689bSDariusz Sosnowski claim_zero(mlx5dr_action_destroy(priv->hws_mpool->action)); 28ddbb689bSDariusz Sosnowski priv->hws_mpool->action = NULL; 29ddbb689bSDariusz Sosnowski } 30ddbb689bSDariusz Sosnowski priv->hws_mpool->devx_obj = NULL; 31ddbb689bSDariusz Sosnowski priv->hws_mpool->idx_pool = NULL; 32ddbb689bSDariusz Sosnowski mlx5_free(priv->hws_mpool); 33ddbb689bSDariusz Sosnowski priv->hws_mpool = NULL; 34ddbb689bSDariusz Sosnowski } 35ddbb689bSDariusz Sosnowski } 36ddbb689bSDariusz Sosnowski 37bf5c4d0bSDariusz Sosnowski void 38bf5c4d0bSDariusz Sosnowski mlx5_flow_meter_uninit(struct rte_eth_dev *dev) 39bf5c4d0bSDariusz Sosnowski { 40bf5c4d0bSDariusz Sosnowski struct mlx5_priv *priv = dev->data->dev_private; 41bf5c4d0bSDariusz Sosnowski 42ddbb689bSDariusz Sosnowski if (priv->shared_host) { 43ddbb689bSDariusz Sosnowski mlx5_flow_meter_uninit_guest(dev); 44ddbb689bSDariusz Sosnowski return; 45ddbb689bSDariusz Sosnowski } 46bf5c4d0bSDariusz Sosnowski if (priv->mtr_policy_arr) { 47bf5c4d0bSDariusz Sosnowski mlx5_free(priv->mtr_policy_arr); 48bf5c4d0bSDariusz Sosnowski priv->mtr_policy_arr = NULL; 49bf5c4d0bSDariusz Sosnowski } 50bf5c4d0bSDariusz Sosnowski if (priv->mtr_profile_arr) { 51bf5c4d0bSDariusz Sosnowski mlx5_free(priv->mtr_profile_arr); 52bf5c4d0bSDariusz Sosnowski priv->mtr_profile_arr = NULL; 53bf5c4d0bSDariusz Sosnowski } 54bf5c4d0bSDariusz Sosnowski if (priv->hws_mpool) { 55bf5c4d0bSDariusz Sosnowski mlx5_aso_mtr_queue_uninit(priv->sh, priv->hws_mpool, NULL); 56bf5c4d0bSDariusz Sosnowski mlx5_ipool_destroy(priv->hws_mpool->idx_pool); 57bf5c4d0bSDariusz Sosnowski mlx5_free(priv->hws_mpool); 58bf5c4d0bSDariusz Sosnowski priv->hws_mpool = NULL; 59bf5c4d0bSDariusz Sosnowski } 60bf5c4d0bSDariusz Sosnowski if (priv->mtr_bulk.aso) { 61bf5c4d0bSDariusz Sosnowski mlx5_free(priv->mtr_bulk.aso); 62bf5c4d0bSDariusz Sosnowski priv->mtr_bulk.aso = NULL; 63bf5c4d0bSDariusz Sosnowski priv->mtr_bulk.size = 0; 64bf5c4d0bSDariusz Sosnowski mlx5_aso_queue_uninit(priv->sh, ASO_OPC_MOD_POLICER); 65bf5c4d0bSDariusz Sosnowski } 66bf5c4d0bSDariusz Sosnowski if (priv->mtr_bulk.action) { 67bf5c4d0bSDariusz Sosnowski mlx5dr_action_destroy(priv->mtr_bulk.action); 68bf5c4d0bSDariusz Sosnowski priv->mtr_bulk.action = NULL; 69bf5c4d0bSDariusz Sosnowski } 70bf5c4d0bSDariusz Sosnowski if (priv->mtr_bulk.devx_obj) { 71bf5c4d0bSDariusz Sosnowski claim_zero(mlx5_devx_cmd_destroy(priv->mtr_bulk.devx_obj)); 72bf5c4d0bSDariusz Sosnowski priv->mtr_bulk.devx_obj = NULL; 73bf5c4d0bSDariusz Sosnowski } 74bf5c4d0bSDariusz Sosnowski } 75bf5c4d0bSDariusz Sosnowski 76ddbb689bSDariusz Sosnowski static int 77ddbb689bSDariusz Sosnowski mlx5_flow_meter_init_guest(struct rte_eth_dev *dev) 78ddbb689bSDariusz Sosnowski { 79ddbb689bSDariusz Sosnowski struct mlx5_priv *priv = dev->data->dev_private; 80ddbb689bSDariusz Sosnowski struct rte_eth_dev *host_dev = priv->shared_host; 81ddbb689bSDariusz Sosnowski struct mlx5_priv *host_priv = host_dev->data->dev_private; 82ddbb689bSDariusz Sosnowski int reg_id = 0; 83ddbb689bSDariusz Sosnowski uint32_t flags; 84ddbb689bSDariusz Sosnowski int ret = 0; 85ddbb689bSDariusz Sosnowski 86ddbb689bSDariusz Sosnowski MLX5_ASSERT(priv->shared_host); 87ddbb689bSDariusz Sosnowski reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL); 88ddbb689bSDariusz Sosnowski if (reg_id < 0) { 89ddbb689bSDariusz Sosnowski rte_errno = ENOMEM; 90ddbb689bSDariusz Sosnowski ret = -rte_errno; 91ddbb689bSDariusz Sosnowski DRV_LOG(ERR, "Meter register is not available."); 92ddbb689bSDariusz Sosnowski goto err; 93ddbb689bSDariusz Sosnowski } 94ddbb689bSDariusz Sosnowski priv->hws_mpool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_aso_mtr_pool), 95ddbb689bSDariusz Sosnowski RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 96ddbb689bSDariusz Sosnowski if (!priv->hws_mpool) { 97ddbb689bSDariusz Sosnowski rte_errno = ENOMEM; 98ddbb689bSDariusz Sosnowski ret = -rte_errno; 99ddbb689bSDariusz Sosnowski DRV_LOG(ERR, "Meter ipool allocation failed."); 100ddbb689bSDariusz Sosnowski goto err; 101ddbb689bSDariusz Sosnowski } 102ddbb689bSDariusz Sosnowski MLX5_ASSERT(host_priv->hws_mpool->idx_pool); 103ddbb689bSDariusz Sosnowski MLX5_ASSERT(host_priv->hws_mpool->devx_obj); 104ddbb689bSDariusz Sosnowski priv->hws_mpool->idx_pool = host_priv->hws_mpool->idx_pool; 105ddbb689bSDariusz Sosnowski priv->hws_mpool->devx_obj = host_priv->hws_mpool->devx_obj; 106ddbb689bSDariusz Sosnowski flags = MLX5DR_ACTION_FLAG_HWS_RX | MLX5DR_ACTION_FLAG_HWS_TX; 107ddbb689bSDariusz Sosnowski if (priv->sh->config.dv_esw_en && priv->master) 108ddbb689bSDariusz Sosnowski flags |= MLX5DR_ACTION_FLAG_HWS_FDB; 109ddbb689bSDariusz Sosnowski priv->hws_mpool->action = mlx5dr_action_create_aso_meter 110ddbb689bSDariusz Sosnowski (priv->dr_ctx, (struct mlx5dr_devx_obj *)priv->hws_mpool->devx_obj, 111ddbb689bSDariusz Sosnowski reg_id - REG_C_0, flags); 112ddbb689bSDariusz Sosnowski if (!priv->hws_mpool->action) { 113ddbb689bSDariusz Sosnowski rte_errno = ENOMEM; 114ddbb689bSDariusz Sosnowski ret = -rte_errno; 115ddbb689bSDariusz Sosnowski DRV_LOG(ERR, "Meter action creation failed."); 116ddbb689bSDariusz Sosnowski goto err; 117ddbb689bSDariusz Sosnowski } 118ddbb689bSDariusz Sosnowski return 0; 119ddbb689bSDariusz Sosnowski err: 120ddbb689bSDariusz Sosnowski mlx5_flow_meter_uninit(dev); 121ddbb689bSDariusz Sosnowski return ret; 122ddbb689bSDariusz Sosnowski } 123ddbb689bSDariusz Sosnowski 124bf5c4d0bSDariusz Sosnowski int 125bf5c4d0bSDariusz Sosnowski mlx5_flow_meter_init(struct rte_eth_dev *dev, 126bf5c4d0bSDariusz Sosnowski uint32_t nb_meters, 127bf5c4d0bSDariusz Sosnowski uint32_t nb_meter_profiles, 128bf5c4d0bSDariusz Sosnowski uint32_t nb_meter_policies, 129bf5c4d0bSDariusz Sosnowski uint32_t nb_queues) 130bf5c4d0bSDariusz Sosnowski { 131bf5c4d0bSDariusz Sosnowski struct mlx5_priv *priv = dev->data->dev_private; 132bf5c4d0bSDariusz Sosnowski struct mlx5_devx_obj *dcs = NULL; 133bf5c4d0bSDariusz Sosnowski uint32_t log_obj_size; 134bf5c4d0bSDariusz Sosnowski int ret = 0; 135bf5c4d0bSDariusz Sosnowski int reg_id; 136bf5c4d0bSDariusz Sosnowski struct mlx5_aso_mtr *aso; 137bf5c4d0bSDariusz Sosnowski uint32_t i; 138bf5c4d0bSDariusz Sosnowski struct rte_flow_error error; 139bf5c4d0bSDariusz Sosnowski uint32_t flags; 140bf5c4d0bSDariusz Sosnowski uint32_t nb_mtrs = rte_align32pow2(nb_meters); 141bf5c4d0bSDariusz Sosnowski struct mlx5_indexed_pool_config cfg = { 142bf5c4d0bSDariusz Sosnowski .size = sizeof(struct mlx5_aso_mtr), 143bf5c4d0bSDariusz Sosnowski .trunk_size = 1 << 12, 144bf5c4d0bSDariusz Sosnowski .per_core_cache = 1 << 13, 145bf5c4d0bSDariusz Sosnowski .need_lock = 1, 146bf5c4d0bSDariusz Sosnowski .release_mem_en = !!priv->sh->config.reclaim_mode, 147bf5c4d0bSDariusz Sosnowski .malloc = mlx5_malloc, 148bf5c4d0bSDariusz Sosnowski .max_idx = nb_meters, 149bf5c4d0bSDariusz Sosnowski .free = mlx5_free, 150bf5c4d0bSDariusz Sosnowski .type = "mlx5_hw_mtr_mark_action", 151bf5c4d0bSDariusz Sosnowski }; 152bf5c4d0bSDariusz Sosnowski 153ddbb689bSDariusz Sosnowski if (priv->shared_host) 154ddbb689bSDariusz Sosnowski return mlx5_flow_meter_init_guest(dev); 155bf5c4d0bSDariusz Sosnowski if (!nb_meters) { 156bf5c4d0bSDariusz Sosnowski ret = ENOTSUP; 157bf5c4d0bSDariusz Sosnowski rte_flow_error_set(&error, ENOMEM, 158bf5c4d0bSDariusz Sosnowski RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 159bf5c4d0bSDariusz Sosnowski NULL, "Meter configuration is invalid."); 160bf5c4d0bSDariusz Sosnowski goto err; 161bf5c4d0bSDariusz Sosnowski } 162bf5c4d0bSDariusz Sosnowski if (!priv->mtr_en || !priv->sh->meter_aso_en) { 163bf5c4d0bSDariusz Sosnowski ret = ENOTSUP; 164bf5c4d0bSDariusz Sosnowski rte_flow_error_set(&error, ENOMEM, 165bf5c4d0bSDariusz Sosnowski RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 166bf5c4d0bSDariusz Sosnowski NULL, "Meter ASO is not supported."); 167bf5c4d0bSDariusz Sosnowski goto err; 168bf5c4d0bSDariusz Sosnowski } 169bf5c4d0bSDariusz Sosnowski priv->mtr_config.nb_meters = nb_meters; 170bf5c4d0bSDariusz Sosnowski log_obj_size = rte_log2_u32(nb_meters >> 1); 171bf5c4d0bSDariusz Sosnowski dcs = mlx5_devx_cmd_create_flow_meter_aso_obj 172bf5c4d0bSDariusz Sosnowski (priv->sh->cdev->ctx, priv->sh->cdev->pdn, 173bf5c4d0bSDariusz Sosnowski log_obj_size); 174bf5c4d0bSDariusz Sosnowski if (!dcs) { 175bf5c4d0bSDariusz Sosnowski ret = ENOMEM; 176bf5c4d0bSDariusz Sosnowski rte_flow_error_set(&error, ENOMEM, 177bf5c4d0bSDariusz Sosnowski RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 178bf5c4d0bSDariusz Sosnowski NULL, "Meter ASO object allocation failed."); 179bf5c4d0bSDariusz Sosnowski goto err; 180bf5c4d0bSDariusz Sosnowski } 181bf5c4d0bSDariusz Sosnowski priv->mtr_bulk.devx_obj = dcs; 182bf5c4d0bSDariusz Sosnowski reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL); 183bf5c4d0bSDariusz Sosnowski if (reg_id < 0) { 184bf5c4d0bSDariusz Sosnowski ret = ENOTSUP; 185bf5c4d0bSDariusz Sosnowski rte_flow_error_set(&error, ENOMEM, 186bf5c4d0bSDariusz Sosnowski RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 187bf5c4d0bSDariusz Sosnowski NULL, "Meter register is not available."); 188bf5c4d0bSDariusz Sosnowski goto err; 189bf5c4d0bSDariusz Sosnowski } 190bf5c4d0bSDariusz Sosnowski flags = MLX5DR_ACTION_FLAG_HWS_RX | MLX5DR_ACTION_FLAG_HWS_TX; 191bf5c4d0bSDariusz Sosnowski if (priv->sh->config.dv_esw_en && priv->master) 192bf5c4d0bSDariusz Sosnowski flags |= MLX5DR_ACTION_FLAG_HWS_FDB; 193bf5c4d0bSDariusz Sosnowski priv->mtr_bulk.action = mlx5dr_action_create_aso_meter 194bf5c4d0bSDariusz Sosnowski (priv->dr_ctx, (struct mlx5dr_devx_obj *)dcs, 195bf5c4d0bSDariusz Sosnowski reg_id - REG_C_0, flags); 196bf5c4d0bSDariusz Sosnowski if (!priv->mtr_bulk.action) { 197bf5c4d0bSDariusz Sosnowski ret = ENOMEM; 198bf5c4d0bSDariusz Sosnowski rte_flow_error_set(&error, ENOMEM, 199bf5c4d0bSDariusz Sosnowski RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 200bf5c4d0bSDariusz Sosnowski NULL, "Meter action creation failed."); 201bf5c4d0bSDariusz Sosnowski goto err; 202bf5c4d0bSDariusz Sosnowski } 203bf5c4d0bSDariusz Sosnowski priv->mtr_bulk.aso = mlx5_malloc(MLX5_MEM_ZERO, 204bf5c4d0bSDariusz Sosnowski sizeof(struct mlx5_aso_mtr) * 205bf5c4d0bSDariusz Sosnowski nb_meters, 206bf5c4d0bSDariusz Sosnowski RTE_CACHE_LINE_SIZE, 207bf5c4d0bSDariusz Sosnowski SOCKET_ID_ANY); 208bf5c4d0bSDariusz Sosnowski if (!priv->mtr_bulk.aso) { 209bf5c4d0bSDariusz Sosnowski ret = ENOMEM; 210bf5c4d0bSDariusz Sosnowski rte_flow_error_set(&error, ENOMEM, 211bf5c4d0bSDariusz Sosnowski RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 212bf5c4d0bSDariusz Sosnowski NULL, "Meter bulk ASO allocation failed."); 213bf5c4d0bSDariusz Sosnowski goto err; 214bf5c4d0bSDariusz Sosnowski } 215bf5c4d0bSDariusz Sosnowski priv->mtr_bulk.size = nb_meters; 216bf5c4d0bSDariusz Sosnowski aso = priv->mtr_bulk.aso; 217bf5c4d0bSDariusz Sosnowski for (i = 0; i < priv->mtr_bulk.size; i++) { 218bf5c4d0bSDariusz Sosnowski aso->type = ASO_METER_DIRECT; 219bf5c4d0bSDariusz Sosnowski aso->state = ASO_METER_WAIT; 220bf5c4d0bSDariusz Sosnowski aso->offset = i; 221bf5c4d0bSDariusz Sosnowski aso++; 222bf5c4d0bSDariusz Sosnowski } 223bf5c4d0bSDariusz Sosnowski priv->hws_mpool = mlx5_malloc(MLX5_MEM_ZERO, 224bf5c4d0bSDariusz Sosnowski sizeof(struct mlx5_aso_mtr_pool), 225bf5c4d0bSDariusz Sosnowski RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 226bf5c4d0bSDariusz Sosnowski if (!priv->hws_mpool) { 227bf5c4d0bSDariusz Sosnowski ret = ENOMEM; 228bf5c4d0bSDariusz Sosnowski rte_flow_error_set(&error, ENOMEM, 229bf5c4d0bSDariusz Sosnowski RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 230bf5c4d0bSDariusz Sosnowski NULL, "Meter ipool allocation failed."); 231bf5c4d0bSDariusz Sosnowski goto err; 232bf5c4d0bSDariusz Sosnowski } 233bf5c4d0bSDariusz Sosnowski priv->hws_mpool->devx_obj = priv->mtr_bulk.devx_obj; 234bf5c4d0bSDariusz Sosnowski priv->hws_mpool->action = priv->mtr_bulk.action; 235bf5c4d0bSDariusz Sosnowski priv->hws_mpool->nb_sq = nb_queues; 236bf5c4d0bSDariusz Sosnowski if (mlx5_aso_mtr_queue_init(priv->sh, priv->hws_mpool, 237bf5c4d0bSDariusz Sosnowski &priv->sh->mtrmng->pools_mng, nb_queues)) { 238bf5c4d0bSDariusz Sosnowski ret = ENOMEM; 239bf5c4d0bSDariusz Sosnowski rte_flow_error_set(&error, ENOMEM, 240bf5c4d0bSDariusz Sosnowski RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 241bf5c4d0bSDariusz Sosnowski NULL, "Meter ASO queue allocation failed."); 242bf5c4d0bSDariusz Sosnowski goto err; 243bf5c4d0bSDariusz Sosnowski } 244bf5c4d0bSDariusz Sosnowski /* 245bf5c4d0bSDariusz Sosnowski * No need for local cache if Meter number is a small number. 246bf5c4d0bSDariusz Sosnowski * Since flow insertion rate will be very limited in that case. 247bf5c4d0bSDariusz Sosnowski * Here let's set the number to less than default trunk size 4K. 248bf5c4d0bSDariusz Sosnowski */ 249bf5c4d0bSDariusz Sosnowski if (nb_mtrs <= cfg.trunk_size) { 250bf5c4d0bSDariusz Sosnowski cfg.per_core_cache = 0; 251bf5c4d0bSDariusz Sosnowski cfg.trunk_size = nb_mtrs; 252bf5c4d0bSDariusz Sosnowski } else if (nb_mtrs <= MLX5_HW_IPOOL_SIZE_THRESHOLD) { 253bf5c4d0bSDariusz Sosnowski cfg.per_core_cache = MLX5_HW_IPOOL_CACHE_MIN; 254bf5c4d0bSDariusz Sosnowski } 255bf5c4d0bSDariusz Sosnowski priv->hws_mpool->idx_pool = mlx5_ipool_create(&cfg); 256bf5c4d0bSDariusz Sosnowski if (nb_meter_profiles) { 257bf5c4d0bSDariusz Sosnowski priv->mtr_config.nb_meter_profiles = nb_meter_profiles; 258bf5c4d0bSDariusz Sosnowski priv->mtr_profile_arr = 259bf5c4d0bSDariusz Sosnowski mlx5_malloc(MLX5_MEM_ZERO, 260bf5c4d0bSDariusz Sosnowski sizeof(struct mlx5_flow_meter_profile) * 261bf5c4d0bSDariusz Sosnowski nb_meter_profiles, 262bf5c4d0bSDariusz Sosnowski RTE_CACHE_LINE_SIZE, 263bf5c4d0bSDariusz Sosnowski SOCKET_ID_ANY); 264bf5c4d0bSDariusz Sosnowski if (!priv->mtr_profile_arr) { 265bf5c4d0bSDariusz Sosnowski ret = ENOMEM; 266bf5c4d0bSDariusz Sosnowski rte_flow_error_set(&error, ENOMEM, 267bf5c4d0bSDariusz Sosnowski RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 268bf5c4d0bSDariusz Sosnowski NULL, "Meter profile allocation failed."); 269bf5c4d0bSDariusz Sosnowski goto err; 270bf5c4d0bSDariusz Sosnowski } 271bf5c4d0bSDariusz Sosnowski } 272bf5c4d0bSDariusz Sosnowski if (nb_meter_policies) { 273bf5c4d0bSDariusz Sosnowski priv->mtr_config.nb_meter_policies = nb_meter_policies; 274bf5c4d0bSDariusz Sosnowski priv->mtr_policy_arr = 275bf5c4d0bSDariusz Sosnowski mlx5_malloc(MLX5_MEM_ZERO, 276bf5c4d0bSDariusz Sosnowski sizeof(struct mlx5_flow_meter_policy) * 277bf5c4d0bSDariusz Sosnowski nb_meter_policies, 278bf5c4d0bSDariusz Sosnowski RTE_CACHE_LINE_SIZE, 279bf5c4d0bSDariusz Sosnowski SOCKET_ID_ANY); 280bf5c4d0bSDariusz Sosnowski if (!priv->mtr_policy_arr) { 281bf5c4d0bSDariusz Sosnowski ret = ENOMEM; 282bf5c4d0bSDariusz Sosnowski rte_flow_error_set(&error, ENOMEM, 283bf5c4d0bSDariusz Sosnowski RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 284bf5c4d0bSDariusz Sosnowski NULL, "Meter policy allocation failed."); 285bf5c4d0bSDariusz Sosnowski goto err; 286bf5c4d0bSDariusz Sosnowski } 287bf5c4d0bSDariusz Sosnowski } 288bf5c4d0bSDariusz Sosnowski return 0; 289bf5c4d0bSDariusz Sosnowski err: 290bf5c4d0bSDariusz Sosnowski mlx5_flow_meter_uninit(dev); 291bf5c4d0bSDariusz Sosnowski return ret; 292bf5c4d0bSDariusz Sosnowski } 293bf5c4d0bSDariusz Sosnowski 294bf5c4d0bSDariusz Sosnowski #endif /* HAVE_MLX5_HWS_SUPPORT */ 295bf5c4d0bSDariusz Sosnowski 296c3130c78SRongwei Liu static int mlx5_flow_meter_disable(struct rte_eth_dev *dev, 297c3130c78SRongwei Liu uint32_t meter_id, struct rte_mtr_error *error); 298c3130c78SRongwei Liu 2996bc327b9SSuanming Mou /** 300266e9f3dSSuanming Mou * Create the meter action. 301266e9f3dSSuanming Mou * 302266e9f3dSSuanming Mou * @param priv 303266e9f3dSSuanming Mou * Pointer to mlx5_priv. 304266e9f3dSSuanming Mou * @param[in] fm 305266e9f3dSSuanming Mou * Pointer to flow meter to be converted. 306266e9f3dSSuanming Mou * 307266e9f3dSSuanming Mou * @return 308266e9f3dSSuanming Mou * Pointer to the meter action on success, NULL otherwise. 309266e9f3dSSuanming Mou */ 310266e9f3dSSuanming Mou static void * 311266e9f3dSSuanming Mou mlx5_flow_meter_action_create(struct mlx5_priv *priv, 312e6100c7bSLi Zhang struct mlx5_flow_meter_info *fm) 313266e9f3dSSuanming Mou { 314266e9f3dSSuanming Mou #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER 315266e9f3dSSuanming Mou struct mlx5dv_dr_flow_meter_attr mtr_init; 316e6100c7bSLi Zhang uint32_t fmp[MLX5_ST_SZ_DW(flow_meter_parameters)]; 317266e9f3dSSuanming Mou struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = 318266e9f3dSSuanming Mou &fm->profile->srtcm_prm; 319e6100c7bSLi Zhang uint32_t cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir); 320e6100c7bSLi Zhang uint32_t ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir); 321e6100c7bSLi Zhang uint32_t val; 322afb4aa4fSLi Zhang enum mlx5_meter_domain domain = 323afb4aa4fSLi Zhang fm->transfer ? MLX5_MTR_DOMAIN_TRANSFER : 324afb4aa4fSLi Zhang fm->egress ? MLX5_MTR_DOMAIN_EGRESS : 325afb4aa4fSLi Zhang MLX5_MTR_DOMAIN_INGRESS; 326afb4aa4fSLi Zhang struct mlx5_flow_meter_def_policy *def_policy = 327afb4aa4fSLi Zhang priv->sh->mtrmng->def_policy[domain]; 328266e9f3dSSuanming Mou 329e6100c7bSLi Zhang memset(fmp, 0, MLX5_ST_SZ_BYTES(flow_meter_parameters)); 330e6100c7bSLi Zhang MLX5_SET(flow_meter_parameters, fmp, valid, 1); 331e6100c7bSLi Zhang MLX5_SET(flow_meter_parameters, fmp, bucket_overflow, 1); 332e6100c7bSLi Zhang MLX5_SET(flow_meter_parameters, fmp, 333266e9f3dSSuanming Mou start_color, MLX5_FLOW_COLOR_GREEN); 334e6100c7bSLi Zhang MLX5_SET(flow_meter_parameters, fmp, both_buckets_on_green, 0); 335e6100c7bSLi Zhang val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) & ASO_DSEG_EXP_MASK; 336e6100c7bSLi Zhang MLX5_SET(flow_meter_parameters, fmp, cbs_exponent, val); 337e6100c7bSLi Zhang val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) & ASO_DSEG_MAN_MASK; 338e6100c7bSLi Zhang MLX5_SET(flow_meter_parameters, fmp, cbs_mantissa, val); 33933a7493cSBing Zhao val = (cbs_cir >> ASO_DSEG_XIR_EXP_OFFSET) & ASO_DSEG_EXP_MASK; 340e6100c7bSLi Zhang MLX5_SET(flow_meter_parameters, fmp, cir_exponent, val); 341e6100c7bSLi Zhang val = (cbs_cir & ASO_DSEG_MAN_MASK); 342e6100c7bSLi Zhang MLX5_SET(flow_meter_parameters, fmp, cir_mantissa, val); 343e6100c7bSLi Zhang val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) & ASO_DSEG_EXP_MASK; 344e6100c7bSLi Zhang MLX5_SET(flow_meter_parameters, fmp, ebs_exponent, val); 345e6100c7bSLi Zhang val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) & ASO_DSEG_MAN_MASK; 346e6100c7bSLi Zhang MLX5_SET(flow_meter_parameters, fmp, ebs_mantissa, val); 347afb4aa4fSLi Zhang mtr_init.next_table = def_policy->sub_policy.tbl_rsc->obj; 3485e9f9a28SGregory Etelson mtr_init.reg_c_index = priv->sh->registers.aso_reg - REG_C_0; 349e6100c7bSLi Zhang mtr_init.flow_meter_parameter = fmp; 350e6100c7bSLi Zhang mtr_init.flow_meter_parameter_sz = 351e6100c7bSLi Zhang MLX5_ST_SZ_BYTES(flow_meter_parameters); 352266e9f3dSSuanming Mou mtr_init.active = fm->active_state; 353266e9f3dSSuanming Mou return mlx5_glue->dv_create_flow_action_meter(&mtr_init); 354266e9f3dSSuanming Mou #else 355266e9f3dSSuanming Mou (void)priv; 356266e9f3dSSuanming Mou (void)fm; 357266e9f3dSSuanming Mou return NULL; 358266e9f3dSSuanming Mou #endif 359266e9f3dSSuanming Mou } 360266e9f3dSSuanming Mou 361266e9f3dSSuanming Mou /** 3623bd26b23SSuanming Mou * Find meter profile by id. 3633bd26b23SSuanming Mou * 3643bd26b23SSuanming Mou * @param priv 3653bd26b23SSuanming Mou * Pointer to mlx5_priv. 3663bd26b23SSuanming Mou * @param meter_profile_id 3673bd26b23SSuanming Mou * Meter profile id. 3683bd26b23SSuanming Mou * 3693bd26b23SSuanming Mou * @return 3703bd26b23SSuanming Mou * Pointer to the profile found on success, NULL otherwise. 3713bd26b23SSuanming Mou */ 3723bd26b23SSuanming Mou static struct mlx5_flow_meter_profile * 3733bd26b23SSuanming Mou mlx5_flow_meter_profile_find(struct mlx5_priv *priv, uint32_t meter_profile_id) 3743bd26b23SSuanming Mou { 3753bd26b23SSuanming Mou struct mlx5_flow_meter_profile *fmp; 376a295c69aSShun Hao union mlx5_l3t_data data; 377a295c69aSShun Hao int32_t ret; 3783bd26b23SSuanming Mou 37924865366SAlexander Kozyrev if (priv->mtr_profile_arr) 38024865366SAlexander Kozyrev return &priv->mtr_profile_arr[meter_profile_id]; 3814dd46d38SShun Hao if (!priv->mtr_profile_tbl || 3824dd46d38SShun Hao mlx5_l3t_get_entry(priv->mtr_profile_tbl, meter_profile_id, &data) || !data.ptr) 3833bd26b23SSuanming Mou return NULL; 384a295c69aSShun Hao fmp = data.ptr; 385a295c69aSShun Hao /* Remove reference taken by the mlx5_l3t_get_entry. */ 386a295c69aSShun Hao ret = mlx5_l3t_clear_entry(priv->mtr_profile_tbl, 387a295c69aSShun Hao meter_profile_id); 388a295c69aSShun Hao if (!ret || ret == -1) 389a295c69aSShun Hao return NULL; 390a295c69aSShun Hao return fmp; 3913bd26b23SSuanming Mou } 3923bd26b23SSuanming Mou 3933bd26b23SSuanming Mou /** 394e0583a52SSuanming Mou * Validate the MTR profile. 395e0583a52SSuanming Mou * 396e0583a52SSuanming Mou * @param[in] dev 397e0583a52SSuanming Mou * Pointer to Ethernet device. 398e0583a52SSuanming Mou * @param[in] meter_profile_id 399e0583a52SSuanming Mou * Meter profile id. 400e0583a52SSuanming Mou * @param[in] profile 401e0583a52SSuanming Mou * Pointer to meter profile detail. 402e0583a52SSuanming Mou * @param[out] error 403e0583a52SSuanming Mou * Pointer to the error structure. 404e0583a52SSuanming Mou * 405e0583a52SSuanming Mou * @return 406e0583a52SSuanming Mou * 0 on success, a negative errno value otherwise and rte_errno is set. 407e0583a52SSuanming Mou */ 408e0583a52SSuanming Mou static int 409e0583a52SSuanming Mou mlx5_flow_meter_profile_validate(struct rte_eth_dev *dev, 410e0583a52SSuanming Mou uint32_t meter_profile_id, 411e0583a52SSuanming Mou struct rte_mtr_meter_profile *profile, 412e0583a52SSuanming Mou struct rte_mtr_error *error) 413e0583a52SSuanming Mou { 414e0583a52SSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 415e0583a52SSuanming Mou struct mlx5_flow_meter_profile *fmp; 4168a0fca11SBing Zhao uint32_t ls_factor; 4178a0fca11SBing Zhao int ret; 4188a0fca11SBing Zhao uint64_t cir, cbs; 4198a0fca11SBing Zhao uint64_t eir, ebs; 4208a0fca11SBing Zhao uint64_t pir, pbs; 421e0583a52SSuanming Mou 422e0583a52SSuanming Mou /* Profile must not be NULL. */ 423e0583a52SSuanming Mou if (profile == NULL) 424e0583a52SSuanming Mou return -rte_mtr_error_set(error, EINVAL, 425e0583a52SSuanming Mou RTE_MTR_ERROR_TYPE_METER_PROFILE, 426e0583a52SSuanming Mou NULL, "Meter profile is null."); 427e0583a52SSuanming Mou /* Meter profile ID must be valid. */ 42824865366SAlexander Kozyrev if (priv->mtr_profile_arr) { 42924865366SAlexander Kozyrev if (meter_profile_id >= priv->mtr_config.nb_meter_profiles) 43024865366SAlexander Kozyrev return -rte_mtr_error_set(error, EINVAL, 43124865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 43224865366SAlexander Kozyrev NULL, "Meter profile id not valid."); 43324865366SAlexander Kozyrev fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id); 43424865366SAlexander Kozyrev /* Meter profile must not exist. */ 43524865366SAlexander Kozyrev if (fmp->initialized) 43624865366SAlexander Kozyrev return -rte_mtr_error_set(error, EEXIST, 43724865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 43824865366SAlexander Kozyrev NULL, "Meter profile already exists."); 43924865366SAlexander Kozyrev } else { 440e0583a52SSuanming Mou if (meter_profile_id == UINT32_MAX) 441e0583a52SSuanming Mou return -rte_mtr_error_set(error, EINVAL, 442e0583a52SSuanming Mou RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 443e0583a52SSuanming Mou NULL, "Meter profile id not valid."); 444e0583a52SSuanming Mou fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id); 44524865366SAlexander Kozyrev /* Meter profile must not exist. */ 446e0583a52SSuanming Mou if (fmp) 447e0583a52SSuanming Mou return -rte_mtr_error_set(error, EEXIST, 448e0583a52SSuanming Mou RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 44924865366SAlexander Kozyrev NULL, "Meter profile already exists."); 45024865366SAlexander Kozyrev } 4518a0fca11SBing Zhao if (!priv->sh->meter_aso_en) { 4528a0fca11SBing Zhao /* Old version is even not supported. */ 45353820561SMichael Baum if (!priv->sh->cdev->config.hca_attr.qos.flow_meter_old) 454e0583a52SSuanming Mou return -rte_mtr_error_set(error, ENOTSUP, 455e0583a52SSuanming Mou RTE_MTR_ERROR_TYPE_METER_PROFILE, 4568a0fca11SBing Zhao NULL, "Metering is not supported."); 4578a0fca11SBing Zhao /* Old FW metering only supports srTCM. */ 4588a0fca11SBing Zhao if (profile->alg != RTE_MTR_SRTCM_RFC2697) { 4598a0fca11SBing Zhao return -rte_mtr_error_set(error, ENOTSUP, 4608a0fca11SBing Zhao RTE_MTR_ERROR_TYPE_METER_PROFILE, 4618a0fca11SBing Zhao NULL, "Metering algorithm is not supported."); 4628a0fca11SBing Zhao } else if (profile->srtcm_rfc2697.ebs) { 4638a0fca11SBing Zhao /* EBS is not supported for old metering. */ 4648a0fca11SBing Zhao return -rte_mtr_error_set(error, ENOTSUP, 4658a0fca11SBing Zhao RTE_MTR_ERROR_TYPE_METER_PROFILE, 4668a0fca11SBing Zhao NULL, "EBS is not supported."); 4678a0fca11SBing Zhao } 4688a0fca11SBing Zhao if (profile->packet_mode) 4698a0fca11SBing Zhao return -rte_mtr_error_set(error, ENOTSUP, 4708a0fca11SBing Zhao RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, 4718a0fca11SBing Zhao "Metering algorithm packet mode is not supported."); 4728a0fca11SBing Zhao } 4738a0fca11SBing Zhao ls_factor = profile->packet_mode ? MLX5_MTRS_PPS_MAP_BPS_SHIFT : 0; 4748a0fca11SBing Zhao switch (profile->alg) { 4758a0fca11SBing Zhao case RTE_MTR_SRTCM_RFC2697: 4768a0fca11SBing Zhao cir = profile->srtcm_rfc2697.cir << ls_factor; 4778a0fca11SBing Zhao cbs = profile->srtcm_rfc2697.cbs << ls_factor; 4788a0fca11SBing Zhao ebs = profile->srtcm_rfc2697.ebs << ls_factor; 4798a0fca11SBing Zhao /* EBS could be zero for old metering. */ 4808a0fca11SBing Zhao if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX && 4818a0fca11SBing Zhao cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX && 4828a0fca11SBing Zhao ebs <= MLX5_SRTCM_XBS_MAX) { 4838a0fca11SBing Zhao ret = 0; 4848a0fca11SBing Zhao } else { 4858a0fca11SBing Zhao ret = -rte_mtr_error_set(error, ENOTSUP, 4868a0fca11SBing Zhao RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 4878a0fca11SBing Zhao "Profile values out of range."); 4888a0fca11SBing Zhao } 4898a0fca11SBing Zhao break; 4908a0fca11SBing Zhao case RTE_MTR_TRTCM_RFC2698: 4918a0fca11SBing Zhao cir = profile->trtcm_rfc2698.cir << ls_factor; 4928a0fca11SBing Zhao cbs = profile->trtcm_rfc2698.cbs << ls_factor; 4938a0fca11SBing Zhao pir = profile->trtcm_rfc2698.pir << ls_factor; 4948a0fca11SBing Zhao pbs = profile->trtcm_rfc2698.pbs << ls_factor; 4958a0fca11SBing Zhao if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX && 4968a0fca11SBing Zhao cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX && 4978a0fca11SBing Zhao pir >= cir && pir <= (MLX5_SRTCM_XIR_MAX * 2) && 4988a0fca11SBing Zhao pbs >= cbs && pbs <= (MLX5_SRTCM_XBS_MAX * 2)) { 4998a0fca11SBing Zhao ret = 0; 5008a0fca11SBing Zhao } else { 5018a0fca11SBing Zhao ret = -rte_mtr_error_set(error, ENOTSUP, 5028a0fca11SBing Zhao RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 5038a0fca11SBing Zhao "Profile values out of range."); 5048a0fca11SBing Zhao } 5058a0fca11SBing Zhao break; 5068a0fca11SBing Zhao case RTE_MTR_TRTCM_RFC4115: 5078a0fca11SBing Zhao cir = profile->trtcm_rfc4115.cir << ls_factor; 5088a0fca11SBing Zhao cbs = profile->trtcm_rfc4115.cbs << ls_factor; 5098a0fca11SBing Zhao eir = profile->trtcm_rfc4115.eir << ls_factor; 5108a0fca11SBing Zhao ebs = profile->trtcm_rfc4115.ebs << ls_factor; 5118a0fca11SBing Zhao if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX && 5128a0fca11SBing Zhao cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX && 5138a0fca11SBing Zhao eir <= MLX5_SRTCM_XIR_MAX && ebs <= MLX5_SRTCM_XBS_MAX) { 5148a0fca11SBing Zhao ret = 0; 5158a0fca11SBing Zhao } else { 5168a0fca11SBing Zhao ret = -rte_mtr_error_set(error, ENOTSUP, 5178a0fca11SBing Zhao RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 5188a0fca11SBing Zhao "Profile values out of range."); 5198a0fca11SBing Zhao } 5208a0fca11SBing Zhao break; 5218a0fca11SBing Zhao default: 5228a0fca11SBing Zhao ret = -rte_mtr_error_set(error, ENOTSUP, 5238a0fca11SBing Zhao RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 5248a0fca11SBing Zhao "Unknown metering algorithm."); 5258a0fca11SBing Zhao break; 5268a0fca11SBing Zhao } 5278a0fca11SBing Zhao return ret; 528e0583a52SSuanming Mou } 529e0583a52SSuanming Mou 53033a7493cSBing Zhao /* 53133a7493cSBing Zhao * Calculate mantissa and exponent for cir / eir. 5323bd26b23SSuanming Mou * 53333a7493cSBing Zhao * @param[in] xir 5343bd26b23SSuanming Mou * Value to be calculated. 5353bd26b23SSuanming Mou * @param[out] man 5363bd26b23SSuanming Mou * Pointer to the mantissa. 5373bd26b23SSuanming Mou * @param[out] exp 5383bd26b23SSuanming Mou * Pointer to the exp. 5393bd26b23SSuanming Mou */ 54033a7493cSBing Zhao static inline void 54133a7493cSBing Zhao mlx5_flow_meter_xir_man_exp_calc(int64_t xir, uint8_t *man, uint8_t *exp) 5423bd26b23SSuanming Mou { 543a9e3a4a9SBing Zhao int64_t _xir; 5443bd26b23SSuanming Mou int64_t delta = INT64_MAX; 5453bd26b23SSuanming Mou uint8_t _man = 0; 5463bd26b23SSuanming Mou uint8_t _exp = 0; 5473bd26b23SSuanming Mou uint64_t m, e; 5483bd26b23SSuanming Mou 5497be78d02SJosh Soref /* Special case xir == 0 ? both exp and mantissa are 0. */ 550a9e3a4a9SBing Zhao if (xir == 0) { 551a9e3a4a9SBing Zhao *man = 0; 552a9e3a4a9SBing Zhao *exp = 0; 553a9e3a4a9SBing Zhao return; 554a9e3a4a9SBing Zhao } 5553bd26b23SSuanming Mou for (m = 0; m <= 0xFF; m++) { /* man width 8 bit */ 5563bd26b23SSuanming Mou for (e = 0; e <= 0x1F; e++) { /* exp width 5bit */ 557a9e3a4a9SBing Zhao _xir = (1000000000ULL * m) >> e; 558a9e3a4a9SBing Zhao if (llabs(xir - _xir) <= delta) { 559a9e3a4a9SBing Zhao delta = llabs(xir - _xir); 5603bd26b23SSuanming Mou _man = m; 5613bd26b23SSuanming Mou _exp = e; 5623bd26b23SSuanming Mou } 5633bd26b23SSuanming Mou } 5643bd26b23SSuanming Mou } 5653bd26b23SSuanming Mou *man = _man; 5663bd26b23SSuanming Mou *exp = _exp; 5673bd26b23SSuanming Mou } 5683bd26b23SSuanming Mou 56933a7493cSBing Zhao /* 5703bd26b23SSuanming Mou * Calculate mantissa and exponent for xbs. 5713bd26b23SSuanming Mou * 5723bd26b23SSuanming Mou * @param[in] xbs 5733bd26b23SSuanming Mou * Value to be calculated. 5743bd26b23SSuanming Mou * @param[out] man 5753bd26b23SSuanming Mou * Pointer to the mantissa. 5763bd26b23SSuanming Mou * @param[out] exp 5773bd26b23SSuanming Mou * Pointer to the exp. 5783bd26b23SSuanming Mou */ 57933a7493cSBing Zhao static inline void 5803bd26b23SSuanming Mou mlx5_flow_meter_xbs_man_exp_calc(uint64_t xbs, uint8_t *man, uint8_t *exp) 5813bd26b23SSuanming Mou { 5823bd26b23SSuanming Mou int _exp; 5833bd26b23SSuanming Mou double _man; 5843bd26b23SSuanming Mou 5857be78d02SJosh Soref /* Special case xbs == 0 ? both exp and mantissa are 0. */ 5863bd26b23SSuanming Mou if (xbs == 0) { 5873bd26b23SSuanming Mou *man = 0; 5883bd26b23SSuanming Mou *exp = 0; 5893bd26b23SSuanming Mou return; 5903bd26b23SSuanming Mou } 5913bd26b23SSuanming Mou /* xbs = xbs_mantissa * 2^xbs_exponent */ 5923bd26b23SSuanming Mou _man = frexp(xbs, &_exp); 59321fdeab4SAlexander Kozyrev if (_exp >= MLX5_MAN_WIDTH) { 5943bd26b23SSuanming Mou _man = _man * pow(2, MLX5_MAN_WIDTH); 5953bd26b23SSuanming Mou _exp = _exp - MLX5_MAN_WIDTH; 59621fdeab4SAlexander Kozyrev } 5973bd26b23SSuanming Mou *man = (uint8_t)ceil(_man); 5983bd26b23SSuanming Mou *exp = _exp; 5993bd26b23SSuanming Mou } 6003bd26b23SSuanming Mou 6013bd26b23SSuanming Mou /** 6023bd26b23SSuanming Mou * Fill the prm meter parameter. 6033bd26b23SSuanming Mou * 6043bd26b23SSuanming Mou * @param[in,out] fmp 6057be78d02SJosh Soref * Pointer to meter profile to be converted. 6063bd26b23SSuanming Mou * @param[out] error 6073bd26b23SSuanming Mou * Pointer to the error structure. 6083bd26b23SSuanming Mou * 6093bd26b23SSuanming Mou * @return 6103bd26b23SSuanming Mou * 0 on success, a negative errno value otherwise and rte_errno is set. 6113bd26b23SSuanming Mou */ 6123bd26b23SSuanming Mou static int 6133bd26b23SSuanming Mou mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp, 6148a0fca11SBing Zhao struct rte_mtr_error *error) 6153bd26b23SSuanming Mou { 6163bd26b23SSuanming Mou struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fmp->srtcm_prm; 6173bd26b23SSuanming Mou uint8_t man, exp; 618e6100c7bSLi Zhang uint32_t cbs_exp, cbs_man, cir_exp, cir_man; 61933a7493cSBing Zhao uint32_t eir_exp, eir_man, ebs_exp, ebs_man; 62033a7493cSBing Zhao uint64_t cir, cbs, eir, ebs; 6213bd26b23SSuanming Mou 62233a7493cSBing Zhao switch (fmp->profile.alg) { 62333a7493cSBing Zhao case RTE_MTR_SRTCM_RFC2697: 624aa065a9cSLi Zhang cir = fmp->profile.srtcm_rfc2697.cir; 625aa065a9cSLi Zhang cbs = fmp->profile.srtcm_rfc2697.cbs; 62633a7493cSBing Zhao eir = 0; 627aa065a9cSLi Zhang ebs = fmp->profile.srtcm_rfc2697.ebs; 62833a7493cSBing Zhao break; 62933a7493cSBing Zhao case RTE_MTR_TRTCM_RFC2698: 63033a7493cSBing Zhao MLX5_ASSERT(fmp->profile.trtcm_rfc2698.pir > 63133a7493cSBing Zhao fmp->profile.trtcm_rfc2698.cir && 63233a7493cSBing Zhao fmp->profile.trtcm_rfc2698.pbs > 63333a7493cSBing Zhao fmp->profile.trtcm_rfc2698.cbs); 63433a7493cSBing Zhao cir = fmp->profile.trtcm_rfc2698.cir; 63533a7493cSBing Zhao cbs = fmp->profile.trtcm_rfc2698.cbs; 63633a7493cSBing Zhao /* EIR / EBS are filled with PIR / PBS. */ 63733a7493cSBing Zhao eir = fmp->profile.trtcm_rfc2698.pir; 63833a7493cSBing Zhao ebs = fmp->profile.trtcm_rfc2698.pbs; 63933a7493cSBing Zhao break; 64033a7493cSBing Zhao case RTE_MTR_TRTCM_RFC4115: 64133a7493cSBing Zhao cir = fmp->profile.trtcm_rfc4115.cir; 64233a7493cSBing Zhao cbs = fmp->profile.trtcm_rfc4115.cbs; 64333a7493cSBing Zhao eir = fmp->profile.trtcm_rfc4115.eir; 64433a7493cSBing Zhao ebs = fmp->profile.trtcm_rfc4115.ebs; 64533a7493cSBing Zhao break; 64633a7493cSBing Zhao default: 64733a7493cSBing Zhao return -rte_mtr_error_set(error, EINVAL, 64833a7493cSBing Zhao RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, 64933a7493cSBing Zhao "Metering algorithm mode is invalid"); 65033a7493cSBing Zhao } 65133a7493cSBing Zhao /* Adjust the values for PPS mode. */ 65233a7493cSBing Zhao if (fmp->profile.packet_mode) { 65333a7493cSBing Zhao cir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT; 65433a7493cSBing Zhao cbs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT; 65533a7493cSBing Zhao eir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT; 65633a7493cSBing Zhao ebs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT; 657aa065a9cSLi Zhang } 6583bd26b23SSuanming Mou /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */ 65933a7493cSBing Zhao mlx5_flow_meter_xir_man_exp_calc(cir, &man, &exp); 6603bd26b23SSuanming Mou /* Check if cir mantissa is too large. */ 66133a7493cSBing Zhao if (exp > ASO_DSEG_XIR_EXP_MASK) 662e6100c7bSLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 6633bd26b23SSuanming Mou RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 66433a7493cSBing Zhao "meter profile parameter cir is not supported."); 665e6100c7bSLi Zhang cir_man = man; 666e6100c7bSLi Zhang cir_exp = exp; 667e6100c7bSLi Zhang /* cbs = cbs_mantissa * 2^cbs_exponent */ 668aa065a9cSLi Zhang mlx5_flow_meter_xbs_man_exp_calc(cbs, &man, &exp); 669e6100c7bSLi Zhang /* Check if cbs mantissa is too large. */ 670e6100c7bSLi Zhang if (exp > ASO_DSEG_EXP_MASK) 671e6100c7bSLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 672e6100c7bSLi Zhang RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 67333a7493cSBing Zhao "meter profile parameter cbs is not supported."); 674e6100c7bSLi Zhang cbs_man = man; 675e6100c7bSLi Zhang cbs_exp = exp; 676e6100c7bSLi Zhang srtcm->cbs_cir = rte_cpu_to_be_32(cbs_exp << ASO_DSEG_CBS_EXP_OFFSET | 677e6100c7bSLi Zhang cbs_man << ASO_DSEG_CBS_MAN_OFFSET | 67833a7493cSBing Zhao cir_exp << ASO_DSEG_XIR_EXP_OFFSET | 679e6100c7bSLi Zhang cir_man); 68033a7493cSBing Zhao mlx5_flow_meter_xir_man_exp_calc(eir, &man, &exp); 68133a7493cSBing Zhao /* Check if eir mantissa is too large. */ 68233a7493cSBing Zhao if (exp > ASO_DSEG_XIR_EXP_MASK) 68333a7493cSBing Zhao return -rte_mtr_error_set(error, ENOTSUP, 68433a7493cSBing Zhao RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 68533a7493cSBing Zhao "meter profile parameter eir is not supported."); 68633a7493cSBing Zhao eir_man = man; 68733a7493cSBing Zhao eir_exp = exp; 688aa065a9cSLi Zhang mlx5_flow_meter_xbs_man_exp_calc(ebs, &man, &exp); 689e6100c7bSLi Zhang /* Check if ebs mantissa is too large. */ 690e6100c7bSLi Zhang if (exp > ASO_DSEG_EXP_MASK) 691e6100c7bSLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 692e6100c7bSLi Zhang RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 69333a7493cSBing Zhao "meter profile parameter ebs is not supported."); 694e6100c7bSLi Zhang ebs_man = man; 695e6100c7bSLi Zhang ebs_exp = exp; 696e6100c7bSLi Zhang srtcm->ebs_eir = rte_cpu_to_be_32(ebs_exp << ASO_DSEG_EBS_EXP_OFFSET | 69733a7493cSBing Zhao ebs_man << ASO_DSEG_EBS_MAN_OFFSET | 69833a7493cSBing Zhao eir_exp << ASO_DSEG_XIR_EXP_OFFSET | 69933a7493cSBing Zhao eir_man); 7004d648fadSBing Zhao if (srtcm->cbs_cir) 7014d648fadSBing Zhao fmp->g_support = 1; 7024d648fadSBing Zhao if (srtcm->ebs_eir) 7034d648fadSBing Zhao fmp->y_support = 1; 7043bd26b23SSuanming Mou return 0; 7053bd26b23SSuanming Mou } 7063bd26b23SSuanming Mou 7073bd26b23SSuanming Mou /** 708bae983b8SMaayan Kashani * Callback to get MTR maximum objects number. 709bae983b8SMaayan Kashani * 710bae983b8SMaayan Kashani * @param[in] priv 711bae983b8SMaayan Kashani * Pointer to Ethernet device. 712bae983b8SMaayan Kashani * 713bae983b8SMaayan Kashani * @return 714bae983b8SMaayan Kashani * Max number of meters. 715bae983b8SMaayan Kashani */ 716bae983b8SMaayan Kashani uint32_t 717bae983b8SMaayan Kashani mlx5_flow_mtr_max_get(struct mlx5_priv *priv) 718bae983b8SMaayan Kashani { 719bae983b8SMaayan Kashani struct mlx5_hca_qos_attr *qattr = &priv->sh->cdev->config.hca_attr.qos; 720bae983b8SMaayan Kashani 721bae983b8SMaayan Kashani /* Max number of meters. */ 722bae983b8SMaayan Kashani return ((priv->sh->meter_aso_en) ? 723bae983b8SMaayan Kashani 1 << (qattr->log_max_num_meter_aso + 1) : 724bae983b8SMaayan Kashani qattr->log_max_flow_meter); 725bae983b8SMaayan Kashani } 726bae983b8SMaayan Kashani 727bae983b8SMaayan Kashani /** 7286bc327b9SSuanming Mou * Callback to get MTR capabilities. 7296bc327b9SSuanming Mou * 7306bc327b9SSuanming Mou * @param[in] dev 7316bc327b9SSuanming Mou * Pointer to Ethernet device. 7326bc327b9SSuanming Mou * @param[out] cap 7336bc327b9SSuanming Mou * Pointer to save MTR capabilities. 7346bc327b9SSuanming Mou * @param[out] error 7356bc327b9SSuanming Mou * Pointer to the error structure. 7366bc327b9SSuanming Mou * 7376bc327b9SSuanming Mou * @return 7386bc327b9SSuanming Mou * 0 on success, a negative errno value otherwise and rte_errno is set. 7396bc327b9SSuanming Mou */ 7406bc327b9SSuanming Mou static int 7416bc327b9SSuanming Mou mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev, 7426bc327b9SSuanming Mou struct rte_mtr_capabilities *cap, 7436bc327b9SSuanming Mou struct rte_mtr_error *error __rte_unused) 7446bc327b9SSuanming Mou { 7456bc327b9SSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 74653820561SMichael Baum struct mlx5_hca_qos_attr *qattr = &priv->sh->cdev->config.hca_attr.qos; 7476bc327b9SSuanming Mou 748*61a81061SGregory Etelson if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL)) 749*61a81061SGregory Etelson return -rte_mtr_error_set(error, EINVAL, 750*61a81061SGregory Etelson RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 751*61a81061SGregory Etelson "non-template flow engine was not configured"); 7526bc327b9SSuanming Mou if (!priv->mtr_en) 7536bc327b9SSuanming Mou return -rte_mtr_error_set(error, ENOTSUP, 7546bc327b9SSuanming Mou RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 7553efac808SAli Alnubani "Meter is not supported"); 7566bc327b9SSuanming Mou memset(cap, 0, sizeof(*cap)); 757bae983b8SMaayan Kashani cap->n_max = mlx5_flow_mtr_max_get(priv); 758aa065a9cSLi Zhang if (priv->sh->meter_aso_en) { 759aa065a9cSLi Zhang cap->srtcm_rfc2697_packet_mode_supported = 1; 760eb11edd9SAlexander Kozyrev cap->trtcm_rfc2698_packet_mode_supported = 1; 761eb11edd9SAlexander Kozyrev cap->trtcm_rfc4115_packet_mode_supported = 1; 762aa065a9cSLi Zhang } 763aa065a9cSLi Zhang cap->srtcm_rfc2697_byte_mode_supported = 1; 764eb11edd9SAlexander Kozyrev cap->trtcm_rfc2698_byte_mode_supported = 1; 765eb11edd9SAlexander Kozyrev cap->trtcm_rfc4115_byte_mode_supported = 1; 7666bc327b9SSuanming Mou cap->n_shared_max = cap->n_max; 7676bc327b9SSuanming Mou cap->identical = 1; 7686bc327b9SSuanming Mou cap->shared_identical = 1; 7696bc327b9SSuanming Mou cap->shared_n_flows_per_mtr_max = 4 << 20; 7706bc327b9SSuanming Mou /* 2M flows can share the same meter. */ 7716bc327b9SSuanming Mou cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */ 772b6505738SDekel Peled cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0; 773eb11edd9SAlexander Kozyrev cap->meter_trtcm_rfc2698_n_max = qattr->flow_meter_old ? cap->n_max : 0; 774eb11edd9SAlexander Kozyrev cap->meter_trtcm_rfc4115_n_max = qattr->flow_meter_old ? cap->n_max : 0; 7756bc327b9SSuanming Mou cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */ 776eb11edd9SAlexander Kozyrev cap->meter_policy_n_max = cap->n_max; 7776bc327b9SSuanming Mou cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED | 7786bc327b9SSuanming Mou RTE_MTR_STATS_N_PKTS_DROPPED; 7796bc327b9SSuanming Mou return 0; 7806bc327b9SSuanming Mou } 781d740eb50SSuanming Mou 7823bd26b23SSuanming Mou /** 7833bd26b23SSuanming Mou * Callback to add MTR profile. 7843bd26b23SSuanming Mou * 7853bd26b23SSuanming Mou * @param[in] dev 7863bd26b23SSuanming Mou * Pointer to Ethernet device. 7873bd26b23SSuanming Mou * @param[in] meter_profile_id 7883bd26b23SSuanming Mou * Meter profile id. 7893bd26b23SSuanming Mou * @param[in] profile 7903bd26b23SSuanming Mou * Pointer to meter profile detail. 7913bd26b23SSuanming Mou * @param[out] error 7923bd26b23SSuanming Mou * Pointer to the error structure. 7933bd26b23SSuanming Mou * 7943bd26b23SSuanming Mou * @return 7953bd26b23SSuanming Mou * 0 on success, a negative errno value otherwise and rte_errno is set. 7963bd26b23SSuanming Mou */ 7973bd26b23SSuanming Mou static int 7983bd26b23SSuanming Mou mlx5_flow_meter_profile_add(struct rte_eth_dev *dev, 7993bd26b23SSuanming Mou uint32_t meter_profile_id, 8003bd26b23SSuanming Mou struct rte_mtr_meter_profile *profile, 8013bd26b23SSuanming Mou struct rte_mtr_error *error) 8023bd26b23SSuanming Mou { 8033bd26b23SSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 8043bd26b23SSuanming Mou struct mlx5_flow_meter_profile *fmp; 805a295c69aSShun Hao union mlx5_l3t_data data; 8063bd26b23SSuanming Mou int ret; 8073bd26b23SSuanming Mou 8083bd26b23SSuanming Mou if (!priv->mtr_en) 8093bd26b23SSuanming Mou return -rte_mtr_error_set(error, ENOTSUP, 8103bd26b23SSuanming Mou RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 8113efac808SAli Alnubani "Meter is not supported"); 812e0583a52SSuanming Mou /* Check input params. */ 813e0583a52SSuanming Mou ret = mlx5_flow_meter_profile_validate(dev, meter_profile_id, 814e0583a52SSuanming Mou profile, error); 815e0583a52SSuanming Mou if (ret) 816e0583a52SSuanming Mou return ret; 8173bd26b23SSuanming Mou /* Meter profile memory allocation. */ 81883c2047cSSuanming Mou fmp = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_flow_meter_profile), 81983c2047cSSuanming Mou RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 8203bd26b23SSuanming Mou if (fmp == NULL) 8213bd26b23SSuanming Mou return -rte_mtr_error_set(error, ENOMEM, 8223bd26b23SSuanming Mou RTE_MTR_ERROR_TYPE_UNSPECIFIED, 8233bd26b23SSuanming Mou NULL, "Meter profile memory " 8243bd26b23SSuanming Mou "alloc failed."); 8253bd26b23SSuanming Mou /* Fill profile info. */ 826e6100c7bSLi Zhang fmp->id = meter_profile_id; 8273bd26b23SSuanming Mou fmp->profile = *profile; 8283bd26b23SSuanming Mou /* Fill the flow meter parameters for the PRM. */ 8298a0fca11SBing Zhao ret = mlx5_flow_meter_param_fill(fmp, error); 8303bd26b23SSuanming Mou if (ret) 8313bd26b23SSuanming Mou goto error; 832a295c69aSShun Hao data.ptr = fmp; 833a295c69aSShun Hao ret = mlx5_l3t_set_entry(priv->mtr_profile_tbl, 834a295c69aSShun Hao meter_profile_id, &data); 835a295c69aSShun Hao if (ret) 836a295c69aSShun Hao return -rte_mtr_error_set(error, ENOTSUP, 837a295c69aSShun Hao RTE_MTR_ERROR_TYPE_UNSPECIFIED, 838a295c69aSShun Hao NULL, "Meter profile insert fail."); 8393bd26b23SSuanming Mou return 0; 8403bd26b23SSuanming Mou error: 84183c2047cSSuanming Mou mlx5_free(fmp); 8423bd26b23SSuanming Mou return ret; 8433bd26b23SSuanming Mou } 8443bd26b23SSuanming Mou 8453bd26b23SSuanming Mou /** 8463bd26b23SSuanming Mou * Callback to delete MTR profile. 8473bd26b23SSuanming Mou * 8483bd26b23SSuanming Mou * @param[in] dev 8493bd26b23SSuanming Mou * Pointer to Ethernet device. 8503bd26b23SSuanming Mou * @param[in] meter_profile_id 8513bd26b23SSuanming Mou * Meter profile id. 8523bd26b23SSuanming Mou * @param[out] error 8533bd26b23SSuanming Mou * Pointer to the error structure. 8543bd26b23SSuanming Mou * 8553bd26b23SSuanming Mou * @return 8563bd26b23SSuanming Mou * 0 on success, a negative errno value otherwise and rte_errno is set. 8573bd26b23SSuanming Mou */ 8583bd26b23SSuanming Mou static int 8593bd26b23SSuanming Mou mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev, 8603bd26b23SSuanming Mou uint32_t meter_profile_id, 8613bd26b23SSuanming Mou struct rte_mtr_error *error) 8623bd26b23SSuanming Mou { 8633bd26b23SSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 8643bd26b23SSuanming Mou struct mlx5_flow_meter_profile *fmp; 8653bd26b23SSuanming Mou 8663bd26b23SSuanming Mou if (!priv->mtr_en) 8673bd26b23SSuanming Mou return -rte_mtr_error_set(error, ENOTSUP, 8683bd26b23SSuanming Mou RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 8693efac808SAli Alnubani "Meter is not supported"); 8703bd26b23SSuanming Mou /* Meter profile must exist. */ 8713bd26b23SSuanming Mou fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id); 8723bd26b23SSuanming Mou if (fmp == NULL) 8733bd26b23SSuanming Mou return -rte_mtr_error_set(error, ENOENT, 8743bd26b23SSuanming Mou RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 8753bd26b23SSuanming Mou &meter_profile_id, 8763efac808SAli Alnubani "Meter profile id is invalid."); 8773bd26b23SSuanming Mou /* Check profile is unused. */ 8783bd26b23SSuanming Mou if (fmp->ref_cnt) 8793bd26b23SSuanming Mou return -rte_mtr_error_set(error, EBUSY, 8803bd26b23SSuanming Mou RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 8813efac808SAli Alnubani NULL, "Meter profile is in use."); 882a295c69aSShun Hao if (mlx5_l3t_clear_entry(priv->mtr_profile_tbl, meter_profile_id)) 883a295c69aSShun Hao return -rte_mtr_error_set(error, EBUSY, 884a295c69aSShun Hao RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 885a295c69aSShun Hao NULL, "Meter profile remove fail."); 88683c2047cSSuanming Mou mlx5_free(fmp); 8873bd26b23SSuanming Mou return 0; 8883bd26b23SSuanming Mou } 8893bd26b23SSuanming Mou 8903f373f35SSuanming Mou /** 89148fbb0e9SAlexander Kozyrev * Callback to get MTR profile. 89248fbb0e9SAlexander Kozyrev * 89348fbb0e9SAlexander Kozyrev * @param[in] dev 89448fbb0e9SAlexander Kozyrev * Pointer to Ethernet device. 89548fbb0e9SAlexander Kozyrev * @param[in] meter_profile_id 89648fbb0e9SAlexander Kozyrev * Meter profile id. 89748fbb0e9SAlexander Kozyrev * @param[out] error 89848fbb0e9SAlexander Kozyrev * Pointer to the error structure. 89948fbb0e9SAlexander Kozyrev * 90048fbb0e9SAlexander Kozyrev * @return 90148fbb0e9SAlexander Kozyrev * A valid handle in case of success, NULL otherwise. 90248fbb0e9SAlexander Kozyrev */ 90348fbb0e9SAlexander Kozyrev static struct rte_flow_meter_profile * 90448fbb0e9SAlexander Kozyrev mlx5_flow_meter_profile_get(struct rte_eth_dev *dev, 90548fbb0e9SAlexander Kozyrev uint32_t meter_profile_id, 90648fbb0e9SAlexander Kozyrev struct rte_mtr_error *error) 90748fbb0e9SAlexander Kozyrev { 90848fbb0e9SAlexander Kozyrev struct mlx5_priv *priv = dev->data->dev_private; 90948fbb0e9SAlexander Kozyrev 910*61a81061SGregory Etelson if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL)) { 911*61a81061SGregory Etelson rte_mtr_error_set(error, EINVAL, 912*61a81061SGregory Etelson RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 913*61a81061SGregory Etelson "non-template flow engine was not configured"); 914*61a81061SGregory Etelson return NULL; 915*61a81061SGregory Etelson } 91648fbb0e9SAlexander Kozyrev if (!priv->mtr_en) { 91748fbb0e9SAlexander Kozyrev rte_mtr_error_set(error, ENOTSUP, 91848fbb0e9SAlexander Kozyrev RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 91948fbb0e9SAlexander Kozyrev "Meter is not supported"); 92048fbb0e9SAlexander Kozyrev return NULL; 92148fbb0e9SAlexander Kozyrev } 92248fbb0e9SAlexander Kozyrev return (void *)(uintptr_t)mlx5_flow_meter_profile_find(priv, 92348fbb0e9SAlexander Kozyrev meter_profile_id); 92448fbb0e9SAlexander Kozyrev } 92548fbb0e9SAlexander Kozyrev 9267576c32eSGregory Etelson #if defined(HAVE_MLX5_HWS_SUPPORT) 92748fbb0e9SAlexander Kozyrev /** 92824865366SAlexander Kozyrev * Callback to add MTR profile with HWS. 92924865366SAlexander Kozyrev * 93024865366SAlexander Kozyrev * @param[in] dev 93124865366SAlexander Kozyrev * Pointer to Ethernet device. 93224865366SAlexander Kozyrev * @param[in] meter_profile_id 93324865366SAlexander Kozyrev * Meter profile id. 93424865366SAlexander Kozyrev * @param[in] profile 93524865366SAlexander Kozyrev * Pointer to meter profile detail. 93624865366SAlexander Kozyrev * @param[out] error 93724865366SAlexander Kozyrev * Pointer to the error structure. 93824865366SAlexander Kozyrev * 93924865366SAlexander Kozyrev * @return 94024865366SAlexander Kozyrev * 0 on success, a negative errno value otherwise and rte_errno is set. 94124865366SAlexander Kozyrev */ 94224865366SAlexander Kozyrev static int 94324865366SAlexander Kozyrev mlx5_flow_meter_profile_hws_add(struct rte_eth_dev *dev, 94424865366SAlexander Kozyrev uint32_t meter_profile_id, 94524865366SAlexander Kozyrev struct rte_mtr_meter_profile *profile, 94624865366SAlexander Kozyrev struct rte_mtr_error *error) 94724865366SAlexander Kozyrev { 94824865366SAlexander Kozyrev struct mlx5_priv *priv = dev->data->dev_private; 94924865366SAlexander Kozyrev struct mlx5_flow_meter_profile *fmp; 95024865366SAlexander Kozyrev int ret; 95124865366SAlexander Kozyrev 952*61a81061SGregory Etelson if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL)) 953*61a81061SGregory Etelson return -rte_mtr_error_set(error, EINVAL, 954*61a81061SGregory Etelson RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 955*61a81061SGregory Etelson "non-template flow engine was not configured"); 956ddbb689bSDariusz Sosnowski if (priv->shared_host) 957ddbb689bSDariusz Sosnowski return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 958ddbb689bSDariusz Sosnowski "Meter profiles cannot be created on guest port"); 95924865366SAlexander Kozyrev if (!priv->mtr_profile_arr) 960077eb39fSAlexander Kozyrev return mlx5_flow_meter_profile_add(dev, meter_profile_id, profile, error); 96124865366SAlexander Kozyrev /* Check input params. */ 96224865366SAlexander Kozyrev ret = mlx5_flow_meter_profile_validate(dev, meter_profile_id, 96324865366SAlexander Kozyrev profile, error); 96424865366SAlexander Kozyrev if (ret) 96524865366SAlexander Kozyrev return ret; 96624865366SAlexander Kozyrev fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id); 96724865366SAlexander Kozyrev /* Fill profile info. */ 96824865366SAlexander Kozyrev fmp->id = meter_profile_id; 96924865366SAlexander Kozyrev fmp->profile = *profile; 97024865366SAlexander Kozyrev fmp->initialized = 1; 97124865366SAlexander Kozyrev /* Fill the flow meter parameters for the PRM. */ 97224865366SAlexander Kozyrev return mlx5_flow_meter_param_fill(fmp, error); 97324865366SAlexander Kozyrev } 97424865366SAlexander Kozyrev 97524865366SAlexander Kozyrev /** 97624865366SAlexander Kozyrev * Callback to delete MTR profile with HWS. 97724865366SAlexander Kozyrev * 97824865366SAlexander Kozyrev * @param[in] dev 97924865366SAlexander Kozyrev * Pointer to Ethernet device. 98024865366SAlexander Kozyrev * @param[in] meter_profile_id 98124865366SAlexander Kozyrev * Meter profile id. 98224865366SAlexander Kozyrev * @param[out] error 98324865366SAlexander Kozyrev * Pointer to the error structure. 98424865366SAlexander Kozyrev * 98524865366SAlexander Kozyrev * @return 98624865366SAlexander Kozyrev * 0 on success, a negative errno value otherwise and rte_errno is set. 98724865366SAlexander Kozyrev */ 98824865366SAlexander Kozyrev static int 98924865366SAlexander Kozyrev mlx5_flow_meter_profile_hws_delete(struct rte_eth_dev *dev, 99024865366SAlexander Kozyrev uint32_t meter_profile_id, 99124865366SAlexander Kozyrev struct rte_mtr_error *error) 99224865366SAlexander Kozyrev { 99324865366SAlexander Kozyrev struct mlx5_priv *priv = dev->data->dev_private; 99424865366SAlexander Kozyrev struct mlx5_flow_meter_profile *fmp; 99524865366SAlexander Kozyrev 996ddbb689bSDariusz Sosnowski if (priv->shared_host) 997ddbb689bSDariusz Sosnowski return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 998ddbb689bSDariusz Sosnowski "Meter profiles cannot be destroyed through guest port"); 99924865366SAlexander Kozyrev if (!priv->mtr_profile_arr) 1000077eb39fSAlexander Kozyrev return mlx5_flow_meter_profile_delete(dev, meter_profile_id, error); 100124865366SAlexander Kozyrev /* Meter profile must exist. */ 100224865366SAlexander Kozyrev fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id); 100324865366SAlexander Kozyrev if (!fmp->initialized) 100424865366SAlexander Kozyrev return -rte_mtr_error_set(error, ENOENT, 100524865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 100624865366SAlexander Kozyrev &meter_profile_id, 100724865366SAlexander Kozyrev "Meter profile id is invalid."); 100824865366SAlexander Kozyrev /* Check profile is unused. */ 100924865366SAlexander Kozyrev if (fmp->ref_cnt) 101024865366SAlexander Kozyrev return -rte_mtr_error_set(error, EBUSY, 101124865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 101224865366SAlexander Kozyrev NULL, "Meter profile is in use."); 101324865366SAlexander Kozyrev memset(fmp, 0, sizeof(struct mlx5_flow_meter_profile)); 101424865366SAlexander Kozyrev return 0; 101524865366SAlexander Kozyrev } 10167576c32eSGregory Etelson #endif 101724865366SAlexander Kozyrev 101824865366SAlexander Kozyrev /** 1019afb4aa4fSLi Zhang * Find policy by id. 1020afb4aa4fSLi Zhang * 1021afb4aa4fSLi Zhang * @param[in] dev 1022afb4aa4fSLi Zhang * Pointer to Ethernet device. 1023afb4aa4fSLi Zhang * @param policy_id 1024afb4aa4fSLi Zhang * Policy id. 1025afb4aa4fSLi Zhang * 1026afb4aa4fSLi Zhang * @return 1027afb4aa4fSLi Zhang * Pointer to the policy found on success, NULL otherwise. 1028afb4aa4fSLi Zhang */ 1029afb4aa4fSLi Zhang struct mlx5_flow_meter_policy * 1030afb4aa4fSLi Zhang mlx5_flow_meter_policy_find(struct rte_eth_dev *dev, 1031afb4aa4fSLi Zhang uint32_t policy_id, 1032afb4aa4fSLi Zhang uint32_t *policy_idx) 1033afb4aa4fSLi Zhang { 1034afb4aa4fSLi Zhang struct mlx5_priv *priv = dev->data->dev_private; 1035afb4aa4fSLi Zhang struct mlx5_flow_meter_sub_policy *sub_policy = NULL; 1036afb4aa4fSLi Zhang union mlx5_l3t_data data; 1037afb4aa4fSLi Zhang 103824865366SAlexander Kozyrev if (priv->mtr_policy_arr) { 103924865366SAlexander Kozyrev if (policy_idx) 104024865366SAlexander Kozyrev *policy_idx = policy_id; 104124865366SAlexander Kozyrev return &priv->mtr_policy_arr[policy_id]; 104224865366SAlexander Kozyrev } 1043efcce4dcSShun Hao if (policy_id > MLX5_MAX_SUB_POLICY_TBL_NUM || !priv->policy_idx_tbl) 1044afb4aa4fSLi Zhang return NULL; 1045efcce4dcSShun Hao if (mlx5_l3t_get_entry(priv->policy_idx_tbl, policy_id, &data) || 1046afb4aa4fSLi Zhang !data.dword) 1047afb4aa4fSLi Zhang return NULL; 1048afb4aa4fSLi Zhang if (policy_idx) 1049afb4aa4fSLi Zhang *policy_idx = data.dword; 1050afb4aa4fSLi Zhang sub_policy = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY], 1051afb4aa4fSLi Zhang data.dword); 1052afb4aa4fSLi Zhang /* Remove reference taken by the mlx5_l3t_get_entry. */ 1053efcce4dcSShun Hao mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id); 1054afb4aa4fSLi Zhang if (sub_policy) 1055afb4aa4fSLi Zhang if (sub_policy->main_policy_id) 1056afb4aa4fSLi Zhang return sub_policy->main_policy; 1057afb4aa4fSLi Zhang return NULL; 1058afb4aa4fSLi Zhang } 1059afb4aa4fSLi Zhang 1060afb4aa4fSLi Zhang /** 1061bf62fb76SShun Hao * Get the next meter from one meter's policy in hierarchy chain. 1062bf62fb76SShun Hao * Lock free, mutex should be acquired by caller. 1063bf62fb76SShun Hao * 1064bf62fb76SShun Hao * @param[in] priv 1065bf62fb76SShun Hao * Pointer to mlx5_priv. 1066bf62fb76SShun Hao * @param[in] policy 1067bf62fb76SShun Hao * Pointer to flow meter policy. 1068bf62fb76SShun Hao * @param[out] mtr_idx 1069bf62fb76SShun Hao * Pointer to Meter index. 1070bf62fb76SShun Hao * 1071bf62fb76SShun Hao * @return 1072bf62fb76SShun Hao * Pointer to the next meter, or NULL when fail. 1073bf62fb76SShun Hao */ 1074bf62fb76SShun Hao struct mlx5_flow_meter_info * 1075bf62fb76SShun Hao mlx5_flow_meter_hierarchy_next_meter(struct mlx5_priv *priv, 1076bf62fb76SShun Hao struct mlx5_flow_meter_policy *policy, 1077bf62fb76SShun Hao uint32_t *mtr_idx) 1078bf62fb76SShun Hao { 1079bf62fb76SShun Hao int i; 1080bf62fb76SShun Hao 1081bf62fb76SShun Hao for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) { 1082bf62fb76SShun Hao if (policy->act_cnt[i].fate_action == MLX5_FLOW_FATE_MTR) 1083bf62fb76SShun Hao return mlx5_flow_meter_find(priv, 1084bf62fb76SShun Hao policy->act_cnt[i].next_mtr_id, 1085bf62fb76SShun Hao mtr_idx); 1086bf62fb76SShun Hao } 1087bf62fb76SShun Hao return NULL; 1088bf62fb76SShun Hao } 1089bf62fb76SShun Hao 1090bf62fb76SShun Hao /** 109150cc92ddSShun Hao * Get the last meter's policy from one meter's policy in hierarchy. 109250cc92ddSShun Hao * 109350cc92ddSShun Hao * @param[in] dev 109450cc92ddSShun Hao * Pointer to Ethernet device. 109550cc92ddSShun Hao * @param[in] policy 109650cc92ddSShun Hao * Pointer to flow meter policy. 109750cc92ddSShun Hao * 109850cc92ddSShun Hao * @return 109950cc92ddSShun Hao * Pointer to the final meter's policy, or NULL when fail. 110050cc92ddSShun Hao */ 110150cc92ddSShun Hao struct mlx5_flow_meter_policy * 110250cc92ddSShun Hao mlx5_flow_meter_hierarchy_get_final_policy(struct rte_eth_dev *dev, 110350cc92ddSShun Hao struct mlx5_flow_meter_policy *policy) 110450cc92ddSShun Hao { 110550cc92ddSShun Hao struct mlx5_priv *priv = dev->data->dev_private; 110650cc92ddSShun Hao struct mlx5_flow_meter_info *next_fm; 110750cc92ddSShun Hao struct mlx5_flow_meter_policy *next_policy = policy; 110850cc92ddSShun Hao 110950cc92ddSShun Hao while (next_policy->is_hierarchy) { 1110bf62fb76SShun Hao rte_spinlock_lock(&next_policy->sl); 1111bf62fb76SShun Hao next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, next_policy, NULL); 1112bf62fb76SShun Hao rte_spinlock_unlock(&next_policy->sl); 111350cc92ddSShun Hao if (!next_fm || next_fm->def_policy) 111450cc92ddSShun Hao return NULL; 111550cc92ddSShun Hao next_policy = mlx5_flow_meter_policy_find(dev, 111650cc92ddSShun Hao next_fm->policy_id, NULL); 111750cc92ddSShun Hao MLX5_ASSERT(next_policy); 111850cc92ddSShun Hao } 111950cc92ddSShun Hao return next_policy; 112050cc92ddSShun Hao } 112150cc92ddSShun Hao 112250cc92ddSShun Hao /** 1123afb4aa4fSLi Zhang * Callback to check MTR policy action validate 1124afb4aa4fSLi Zhang * 1125afb4aa4fSLi Zhang * @param[in] dev 1126afb4aa4fSLi Zhang * Pointer to Ethernet device. 1127afb4aa4fSLi Zhang * @param[in] actions 1128afb4aa4fSLi Zhang * Pointer to meter policy action detail. 1129afb4aa4fSLi Zhang * @param[out] error 1130afb4aa4fSLi Zhang * Pointer to the error structure. 1131afb4aa4fSLi Zhang * 1132afb4aa4fSLi Zhang * @return 1133afb4aa4fSLi Zhang * 0 on success, a negative errno value otherwise and rte_errno is set. 1134afb4aa4fSLi Zhang */ 1135afb4aa4fSLi Zhang static int 1136afb4aa4fSLi Zhang mlx5_flow_meter_policy_validate(struct rte_eth_dev *dev, 1137afb4aa4fSLi Zhang struct rte_mtr_meter_policy_params *policy, 1138afb4aa4fSLi Zhang struct rte_mtr_error *error) 1139afb4aa4fSLi Zhang { 1140afb4aa4fSLi Zhang struct mlx5_priv *priv = dev->data->dev_private; 1141a13ec19cSMichael Baum struct rte_flow_attr attr = { .transfer = priv->sh->config.dv_esw_en ? 1142a13ec19cSMichael Baum 1 : 0 }; 1143afb4aa4fSLi Zhang bool is_rss = false; 11444b7bf3ffSBing Zhao uint8_t policy_mode; 1145afb4aa4fSLi Zhang uint8_t domain_bitmap; 1146afb4aa4fSLi Zhang int ret; 1147afb4aa4fSLi Zhang 1148afb4aa4fSLi Zhang if (!priv->mtr_en || !priv->sh->meter_aso_en) 1149afb4aa4fSLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 1150afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY, 1151afb4aa4fSLi Zhang NULL, "meter policy unsupported."); 1152afb4aa4fSLi Zhang ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr, 11534b7bf3ffSBing Zhao &is_rss, &domain_bitmap, &policy_mode, error); 1154afb4aa4fSLi Zhang if (ret) 1155afb4aa4fSLi Zhang return ret; 1156afb4aa4fSLi Zhang return 0; 1157afb4aa4fSLi Zhang } 1158afb4aa4fSLi Zhang 11597576c32eSGregory Etelson #if defined(HAVE_MLX5_HWS_SUPPORT) 116024865366SAlexander Kozyrev /** 116124865366SAlexander Kozyrev * Callback to check MTR policy action validate for HWS 116224865366SAlexander Kozyrev * 116324865366SAlexander Kozyrev * @param[in] dev 116424865366SAlexander Kozyrev * Pointer to Ethernet device. 116524865366SAlexander Kozyrev * @param[in] actions 116624865366SAlexander Kozyrev * Pointer to meter policy action detail. 116724865366SAlexander Kozyrev * @param[out] error 116824865366SAlexander Kozyrev * Pointer to the error structure. 116924865366SAlexander Kozyrev * 117024865366SAlexander Kozyrev * @return 117124865366SAlexander Kozyrev * 0 on success, a negative errno value otherwise and rte_errno is set. 117224865366SAlexander Kozyrev */ 117324865366SAlexander Kozyrev static int 117424865366SAlexander Kozyrev mlx5_flow_meter_policy_hws_validate(struct rte_eth_dev *dev, 117524865366SAlexander Kozyrev struct rte_mtr_meter_policy_params *policy, 117624865366SAlexander Kozyrev struct rte_mtr_error *error) 117724865366SAlexander Kozyrev { 117824865366SAlexander Kozyrev struct mlx5_priv *priv = dev->data->dev_private; 117924865366SAlexander Kozyrev const struct rte_flow_actions_template_attr attr = { 118024865366SAlexander Kozyrev .transfer = priv->sh->config.dv_esw_en ? 1 : 0 }; 118124865366SAlexander Kozyrev int ret; 118224865366SAlexander Kozyrev int i; 118324865366SAlexander Kozyrev 1184*61a81061SGregory Etelson if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL)) 1185*61a81061SGregory Etelson return -rte_mtr_error_set(error, EINVAL, 1186*61a81061SGregory Etelson RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 1187*61a81061SGregory Etelson "non-template flow engine was not configured"); 118824865366SAlexander Kozyrev if (!priv->mtr_en || !priv->sh->meter_aso_en) 118924865366SAlexander Kozyrev return -rte_mtr_error_set(error, ENOTSUP, 119024865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_POLICY, 119124865366SAlexander Kozyrev NULL, "meter policy unsupported."); 119224865366SAlexander Kozyrev for (i = 0; i < RTE_COLORS; i++) { 119324865366SAlexander Kozyrev ret = mlx5_flow_actions_validate(dev, &attr, policy->actions[i], 119424865366SAlexander Kozyrev policy->actions[i], NULL); 119524865366SAlexander Kozyrev if (ret) 119624865366SAlexander Kozyrev return ret; 119724865366SAlexander Kozyrev } 119824865366SAlexander Kozyrev return 0; 119924865366SAlexander Kozyrev } 12007576c32eSGregory Etelson #endif 120124865366SAlexander Kozyrev 1202afb4aa4fSLi Zhang static int 1203afb4aa4fSLi Zhang __mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev, 1204afb4aa4fSLi Zhang uint32_t policy_id, 1205afb4aa4fSLi Zhang struct mlx5_flow_meter_policy *mtr_policy, 1206035f4c23SLi Zhang struct rte_mtr_error *error, 1207035f4c23SLi Zhang bool clear_l3t) 1208afb4aa4fSLi Zhang { 1209afb4aa4fSLi Zhang struct mlx5_priv *priv = dev->data->dev_private; 1210afb4aa4fSLi Zhang struct mlx5_flow_meter_sub_policy *sub_policy; 1211afb4aa4fSLi Zhang uint32_t i, j; 1212afb4aa4fSLi Zhang uint16_t sub_policy_num; 1213afb4aa4fSLi Zhang 1214afb4aa4fSLi Zhang rte_spinlock_lock(&mtr_policy->sl); 1215afb4aa4fSLi Zhang if (mtr_policy->ref_cnt) { 1216afb4aa4fSLi Zhang rte_spinlock_unlock(&mtr_policy->sl); 1217afb4aa4fSLi Zhang return -rte_mtr_error_set(error, EBUSY, 1218afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 1219afb4aa4fSLi Zhang NULL, 1220afb4aa4fSLi Zhang "Meter policy object is being used."); 1221afb4aa4fSLi Zhang } 1222afb4aa4fSLi Zhang mlx5_flow_destroy_policy_rules(dev, mtr_policy); 1223afb4aa4fSLi Zhang mlx5_flow_destroy_mtr_acts(dev, mtr_policy); 1224afb4aa4fSLi Zhang for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) { 1225afb4aa4fSLi Zhang sub_policy_num = (mtr_policy->sub_policy_num >> 1226afb4aa4fSLi Zhang (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) & 1227afb4aa4fSLi Zhang MLX5_MTR_SUB_POLICY_NUM_MASK; 1228afb4aa4fSLi Zhang if (sub_policy_num) { 1229afb4aa4fSLi Zhang for (j = 0; j < sub_policy_num; j++) { 1230afb4aa4fSLi Zhang sub_policy = mtr_policy->sub_policys[i][j]; 1231afb4aa4fSLi Zhang if (sub_policy) 1232afb4aa4fSLi Zhang mlx5_ipool_free 1233afb4aa4fSLi Zhang (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY], 1234afb4aa4fSLi Zhang sub_policy->idx); 1235afb4aa4fSLi Zhang } 1236afb4aa4fSLi Zhang } 1237afb4aa4fSLi Zhang } 1238efcce4dcSShun Hao if (priv->policy_idx_tbl && clear_l3t) { 1239efcce4dcSShun Hao if (mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id)) { 1240afb4aa4fSLi Zhang rte_spinlock_unlock(&mtr_policy->sl); 1241afb4aa4fSLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 1242afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL, 1243afb4aa4fSLi Zhang "Fail to delete policy in index table."); 1244afb4aa4fSLi Zhang } 1245afb4aa4fSLi Zhang } 1246afb4aa4fSLi Zhang rte_spinlock_unlock(&mtr_policy->sl); 1247afb4aa4fSLi Zhang return 0; 1248afb4aa4fSLi Zhang } 1249afb4aa4fSLi Zhang 1250afb4aa4fSLi Zhang /** 1251afb4aa4fSLi Zhang * Callback to add MTR policy. 1252afb4aa4fSLi Zhang * 1253afb4aa4fSLi Zhang * @param[in] dev 1254afb4aa4fSLi Zhang * Pointer to Ethernet device. 1255afb4aa4fSLi Zhang * @param[out] policy_id 1256afb4aa4fSLi Zhang * Pointer to policy id 1257afb4aa4fSLi Zhang * @param[in] actions 1258afb4aa4fSLi Zhang * Pointer to meter policy action detail. 1259afb4aa4fSLi Zhang * @param[out] error 1260afb4aa4fSLi Zhang * Pointer to the error structure. 1261afb4aa4fSLi Zhang * 1262afb4aa4fSLi Zhang * @return 1263afb4aa4fSLi Zhang * 0 on success, a negative errno value otherwise and rte_errno is set. 1264afb4aa4fSLi Zhang */ 1265afb4aa4fSLi Zhang static int 1266afb4aa4fSLi Zhang mlx5_flow_meter_policy_add(struct rte_eth_dev *dev, 1267afb4aa4fSLi Zhang uint32_t policy_id, 1268afb4aa4fSLi Zhang struct rte_mtr_meter_policy_params *policy, 1269afb4aa4fSLi Zhang struct rte_mtr_error *error) 1270afb4aa4fSLi Zhang { 1271afb4aa4fSLi Zhang struct mlx5_priv *priv = dev->data->dev_private; 1272a13ec19cSMichael Baum struct rte_flow_attr attr = { .transfer = priv->sh->config.dv_esw_en ? 1273a13ec19cSMichael Baum 1 : 0 }; 1274afb4aa4fSLi Zhang uint32_t sub_policy_idx = 0; 1275afb4aa4fSLi Zhang uint32_t policy_idx = 0; 1276afb4aa4fSLi Zhang struct mlx5_flow_meter_policy *mtr_policy = NULL; 1277afb4aa4fSLi Zhang struct mlx5_flow_meter_sub_policy *sub_policy; 1278afb4aa4fSLi Zhang bool is_rss = false; 12794b7bf3ffSBing Zhao uint8_t policy_mode; 1280afb4aa4fSLi Zhang uint32_t i; 1281afb4aa4fSLi Zhang int ret; 1282afb4aa4fSLi Zhang uint32_t policy_size = sizeof(struct mlx5_flow_meter_policy); 1283afb4aa4fSLi Zhang uint16_t sub_policy_num; 1284afb4aa4fSLi Zhang uint8_t domain_bitmap = 0; 1285afb4aa4fSLi Zhang union mlx5_l3t_data data; 128650cc92ddSShun Hao bool skip_rule = false; 1287afb4aa4fSLi Zhang 1288afb4aa4fSLi Zhang if (!priv->mtr_en) 1289afb4aa4fSLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 1290afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY, 1291afb4aa4fSLi Zhang NULL, "meter policy unsupported. "); 1292afb4aa4fSLi Zhang if (policy_id == MLX5_INVALID_POLICY_ID) 1293afb4aa4fSLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 1294fa31a5edSBing Zhao RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 1295fa31a5edSBing Zhao NULL, "policy ID is invalid. "); 1296afb4aa4fSLi Zhang if (policy_id == priv->sh->mtrmng->def_policy_id) 1297afb4aa4fSLi Zhang return -rte_mtr_error_set(error, EEXIST, 1298fa31a5edSBing Zhao RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 1299fa31a5edSBing Zhao NULL, "default policy ID exists. "); 1300fa31a5edSBing Zhao mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx); 1301afb4aa4fSLi Zhang if (mtr_policy) 1302afb4aa4fSLi Zhang return -rte_mtr_error_set(error, EEXIST, 1303fa31a5edSBing Zhao RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 1304fa31a5edSBing Zhao NULL, "policy ID exists. "); 1305afb4aa4fSLi Zhang ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr, 13064b7bf3ffSBing Zhao &is_rss, &domain_bitmap, 13074b7bf3ffSBing Zhao &policy_mode, error); 1308afb4aa4fSLi Zhang if (ret) 1309afb4aa4fSLi Zhang return ret; 1310afb4aa4fSLi Zhang if (!domain_bitmap) 1311afb4aa4fSLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 1312afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY, 1313afb4aa4fSLi Zhang NULL, "fail to find policy domain."); 13144b7bf3ffSBing Zhao if (policy_mode == MLX5_MTR_POLICY_MODE_DEF) { 1315afb4aa4fSLi Zhang if (priv->sh->mtrmng->def_policy_id != MLX5_INVALID_POLICY_ID) 1316afb4aa4fSLi Zhang return -rte_mtr_error_set(error, EEXIST, 1317afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 1318afb4aa4fSLi Zhang NULL, "a policy with similar actions " 1319afb4aa4fSLi Zhang "is already configured"); 1320afb4aa4fSLi Zhang if (mlx5_flow_create_def_policy(dev)) 1321afb4aa4fSLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 1322afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY, 1323afb4aa4fSLi Zhang NULL, 1324afb4aa4fSLi Zhang "fail to create non-terminated policy."); 1325afb4aa4fSLi Zhang priv->sh->mtrmng->def_policy_id = policy_id; 1326afb4aa4fSLi Zhang return 0; 1327afb4aa4fSLi Zhang } 1328afb4aa4fSLi Zhang if (!priv->sh->meter_aso_en) 1329afb4aa4fSLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 1330afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, 1331afb4aa4fSLi Zhang "no ASO capability to support the policy "); 1332afb4aa4fSLi Zhang for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) { 1333afb4aa4fSLi Zhang if (!(domain_bitmap & (1 << i))) 1334afb4aa4fSLi Zhang continue; 1335fa31a5edSBing Zhao /* 1336fa31a5edSBing Zhao * If RSS is found, it means that only the ingress domain can 1337fa31a5edSBing Zhao * be supported. It is invalid to support RSS for one color 1338fa31a5edSBing Zhao * and egress / transfer domain actions for another. Drop and 1339fa31a5edSBing Zhao * jump action should have no impact. 1340fa31a5edSBing Zhao */ 1341afb4aa4fSLi Zhang if (is_rss) { 1342afb4aa4fSLi Zhang policy_size += 1343afb4aa4fSLi Zhang sizeof(struct mlx5_flow_meter_sub_policy *) * 1344afb4aa4fSLi Zhang MLX5_MTR_RSS_MAX_SUB_POLICY; 1345afb4aa4fSLi Zhang break; 1346afb4aa4fSLi Zhang } 1347afb4aa4fSLi Zhang policy_size += sizeof(struct mlx5_flow_meter_sub_policy *); 1348afb4aa4fSLi Zhang } 1349afb4aa4fSLi Zhang mtr_policy = mlx5_malloc(MLX5_MEM_ZERO, policy_size, 1350afb4aa4fSLi Zhang RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 1351afb4aa4fSLi Zhang if (!mtr_policy) 1352afb4aa4fSLi Zhang return -rte_mtr_error_set(error, ENOMEM, 1353afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, 1354afb4aa4fSLi Zhang "Memory alloc failed for meter policy."); 13554d648fadSBing Zhao if (policy_mode == MLX5_MTR_POLICY_MODE_OG) 13564d648fadSBing Zhao mtr_policy->skip_y = 1; 13574d648fadSBing Zhao else if (policy_mode == MLX5_MTR_POLICY_MODE_OY) 13584d648fadSBing Zhao mtr_policy->skip_g = 1; 1359afb4aa4fSLi Zhang policy_size = sizeof(struct mlx5_flow_meter_policy); 1360afb4aa4fSLi Zhang for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) { 1361afb4aa4fSLi Zhang if (!(domain_bitmap & (1 << i))) 1362afb4aa4fSLi Zhang continue; 136344432018SLi Zhang if (i == MLX5_MTR_DOMAIN_INGRESS) 136444432018SLi Zhang mtr_policy->ingress = 1; 136544432018SLi Zhang if (i == MLX5_MTR_DOMAIN_EGRESS) 136644432018SLi Zhang mtr_policy->egress = 1; 136744432018SLi Zhang if (i == MLX5_MTR_DOMAIN_TRANSFER) 136844432018SLi Zhang mtr_policy->transfer = 1; 1369afb4aa4fSLi Zhang sub_policy = mlx5_ipool_zmalloc 1370afb4aa4fSLi Zhang (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY], 1371afb4aa4fSLi Zhang &sub_policy_idx); 1372fa31a5edSBing Zhao if (!sub_policy || 1373fa31a5edSBing Zhao sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM) 1374afb4aa4fSLi Zhang goto policy_add_err; 1375afb4aa4fSLi Zhang sub_policy->idx = sub_policy_idx; 1376afb4aa4fSLi Zhang sub_policy->main_policy = mtr_policy; 1377afb4aa4fSLi Zhang if (!policy_idx) { 1378afb4aa4fSLi Zhang policy_idx = sub_policy_idx; 1379afb4aa4fSLi Zhang sub_policy->main_policy_id = 1; 1380afb4aa4fSLi Zhang } 1381afb4aa4fSLi Zhang mtr_policy->sub_policys[i] = 1382afb4aa4fSLi Zhang (struct mlx5_flow_meter_sub_policy **) 1383afb4aa4fSLi Zhang ((uint8_t *)mtr_policy + policy_size); 1384afb4aa4fSLi Zhang mtr_policy->sub_policys[i][0] = sub_policy; 1385afb4aa4fSLi Zhang sub_policy_num = (mtr_policy->sub_policy_num >> 1386afb4aa4fSLi Zhang (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) & 1387afb4aa4fSLi Zhang MLX5_MTR_SUB_POLICY_NUM_MASK; 1388afb4aa4fSLi Zhang sub_policy_num++; 1389afb4aa4fSLi Zhang mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK << 1390afb4aa4fSLi Zhang (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)); 1391afb4aa4fSLi Zhang mtr_policy->sub_policy_num |= 1392afb4aa4fSLi Zhang (sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) << 1393afb4aa4fSLi Zhang (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i); 1394fa31a5edSBing Zhao /* 1395fa31a5edSBing Zhao * If RSS is found, it means that only the ingress domain can 1396fa31a5edSBing Zhao * be supported. It is invalid to support RSS for one color 1397fa31a5edSBing Zhao * and egress / transfer domain actions for another. Drop and 1398fa31a5edSBing Zhao * jump action should have no impact. 1399fa31a5edSBing Zhao */ 1400afb4aa4fSLi Zhang if (is_rss) { 1401afb4aa4fSLi Zhang mtr_policy->is_rss = 1; 1402afb4aa4fSLi Zhang break; 1403afb4aa4fSLi Zhang } 1404afb4aa4fSLi Zhang policy_size += sizeof(struct mlx5_flow_meter_sub_policy *); 1405afb4aa4fSLi Zhang } 1406afb4aa4fSLi Zhang rte_spinlock_init(&mtr_policy->sl); 1407afb4aa4fSLi Zhang ret = mlx5_flow_create_mtr_acts(dev, mtr_policy, 14086431068dSSean Zhang policy->actions, &attr, error); 1409afb4aa4fSLi Zhang if (ret) 1410afb4aa4fSLi Zhang goto policy_add_err; 141150cc92ddSShun Hao if (mtr_policy->is_hierarchy) { 141250cc92ddSShun Hao struct mlx5_flow_meter_policy *final_policy; 141350cc92ddSShun Hao 141450cc92ddSShun Hao final_policy = 141550cc92ddSShun Hao mlx5_flow_meter_hierarchy_get_final_policy(dev, mtr_policy); 141650cc92ddSShun Hao if (!final_policy) 141750cc92ddSShun Hao goto policy_add_err; 141850cc92ddSShun Hao skip_rule = (final_policy->is_rss || final_policy->is_queue); 141950cc92ddSShun Hao } 1420fa31a5edSBing Zhao /* 1421fa31a5edSBing Zhao * If either Green or Yellow has queue / RSS action, all the policy 1422fa31a5edSBing Zhao * rules will be created later in the flow splitting stage. 1423fa31a5edSBing Zhao */ 142450cc92ddSShun Hao if (!is_rss && !mtr_policy->is_queue && !skip_rule) { 1425afb4aa4fSLi Zhang /* Create policy rules in HW. */ 1426afb4aa4fSLi Zhang ret = mlx5_flow_create_policy_rules(dev, mtr_policy); 1427afb4aa4fSLi Zhang if (ret) 1428afb4aa4fSLi Zhang goto policy_add_err; 1429afb4aa4fSLi Zhang } 1430afb4aa4fSLi Zhang data.dword = policy_idx; 1431efcce4dcSShun Hao if (!priv->policy_idx_tbl) { 1432efcce4dcSShun Hao priv->policy_idx_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_DWORD); 1433efcce4dcSShun Hao if (!priv->policy_idx_tbl) 1434afb4aa4fSLi Zhang goto policy_add_err; 1435afb4aa4fSLi Zhang } 1436efcce4dcSShun Hao if (mlx5_l3t_set_entry(priv->policy_idx_tbl, policy_id, &data)) 1437afb4aa4fSLi Zhang goto policy_add_err; 1438afb4aa4fSLi Zhang return 0; 1439afb4aa4fSLi Zhang policy_add_err: 1440afb4aa4fSLi Zhang if (mtr_policy) { 1441afb4aa4fSLi Zhang ret = __mlx5_flow_meter_policy_delete(dev, policy_id, 1442035f4c23SLi Zhang mtr_policy, error, false); 1443afb4aa4fSLi Zhang mlx5_free(mtr_policy); 1444afb4aa4fSLi Zhang if (ret) 1445afb4aa4fSLi Zhang return ret; 1446afb4aa4fSLi Zhang } 1447afb4aa4fSLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 1448afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_UNSPECIFIED, 1449afb4aa4fSLi Zhang NULL, "Failed to create devx policy."); 1450afb4aa4fSLi Zhang } 1451afb4aa4fSLi Zhang 1452afb4aa4fSLi Zhang /** 1453afb4aa4fSLi Zhang * Callback to delete MTR policy. 1454afb4aa4fSLi Zhang * 1455afb4aa4fSLi Zhang * @param[in] dev 1456afb4aa4fSLi Zhang * Pointer to Ethernet device. 1457afb4aa4fSLi Zhang * @param[in] policy_id 1458afb4aa4fSLi Zhang * Meter policy id. 1459afb4aa4fSLi Zhang * @param[out] error 1460afb4aa4fSLi Zhang * Pointer to the error structure. 1461afb4aa4fSLi Zhang * 1462afb4aa4fSLi Zhang * @return 1463afb4aa4fSLi Zhang * 0 on success, a negative errno value otherwise and rte_errno is set. 1464afb4aa4fSLi Zhang */ 1465afb4aa4fSLi Zhang static int 1466afb4aa4fSLi Zhang mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev, 1467afb4aa4fSLi Zhang uint32_t policy_id, 1468afb4aa4fSLi Zhang struct rte_mtr_error *error) 1469afb4aa4fSLi Zhang { 1470afb4aa4fSLi Zhang struct mlx5_priv *priv = dev->data->dev_private; 1471afb4aa4fSLi Zhang struct mlx5_flow_meter_policy *mtr_policy; 1472afb4aa4fSLi Zhang uint32_t policy_idx; 1473afb4aa4fSLi Zhang int ret; 1474afb4aa4fSLi Zhang 1475afb4aa4fSLi Zhang if (policy_id == priv->sh->mtrmng->def_policy_id) { 1476afb4aa4fSLi Zhang if (priv->sh->mtrmng->def_policy_ref_cnt > 0) 1477afb4aa4fSLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 1478afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL, 1479afb4aa4fSLi Zhang "Meter policy object is being used."); 1480afb4aa4fSLi Zhang priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID; 1481afb4aa4fSLi Zhang return 0; 1482afb4aa4fSLi Zhang } 1483afb4aa4fSLi Zhang mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx); 1484afb4aa4fSLi Zhang if (!mtr_policy) 1485afb4aa4fSLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 1486afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL, 1487afb4aa4fSLi Zhang "Meter policy id is invalid. "); 1488afb4aa4fSLi Zhang ret = __mlx5_flow_meter_policy_delete(dev, policy_id, mtr_policy, 1489035f4c23SLi Zhang error, true); 1490afb4aa4fSLi Zhang if (ret) 1491afb4aa4fSLi Zhang return ret; 1492afb4aa4fSLi Zhang mlx5_free(mtr_policy); 1493afb4aa4fSLi Zhang return 0; 1494afb4aa4fSLi Zhang } 1495afb4aa4fSLi Zhang 1496afb4aa4fSLi Zhang /** 149748fbb0e9SAlexander Kozyrev * Callback to get MTR policy. 149848fbb0e9SAlexander Kozyrev * 149948fbb0e9SAlexander Kozyrev * @param[in] dev 150048fbb0e9SAlexander Kozyrev * Pointer to Ethernet device. 150148fbb0e9SAlexander Kozyrev * @param[in] policy_id 150248fbb0e9SAlexander Kozyrev * Meter policy id. 150348fbb0e9SAlexander Kozyrev * @param[out] error 150448fbb0e9SAlexander Kozyrev * Pointer to the error structure. 150548fbb0e9SAlexander Kozyrev * 150648fbb0e9SAlexander Kozyrev * @return 150748fbb0e9SAlexander Kozyrev * A valid handle in case of success, NULL otherwise. 150848fbb0e9SAlexander Kozyrev */ 150948fbb0e9SAlexander Kozyrev static struct rte_flow_meter_policy * 151048fbb0e9SAlexander Kozyrev mlx5_flow_meter_policy_get(struct rte_eth_dev *dev, 151148fbb0e9SAlexander Kozyrev uint32_t policy_id, 151248fbb0e9SAlexander Kozyrev struct rte_mtr_error *error) 151348fbb0e9SAlexander Kozyrev { 151448fbb0e9SAlexander Kozyrev struct mlx5_priv *priv = dev->data->dev_private; 151548fbb0e9SAlexander Kozyrev uint32_t policy_idx; 151648fbb0e9SAlexander Kozyrev 1517*61a81061SGregory Etelson if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL)) { 1518*61a81061SGregory Etelson rte_mtr_error_set(error, EINVAL, 1519*61a81061SGregory Etelson RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 1520*61a81061SGregory Etelson "non-template flow engine was not configured"); 1521*61a81061SGregory Etelson return NULL; 1522*61a81061SGregory Etelson } 152348fbb0e9SAlexander Kozyrev if (!priv->mtr_en) { 152448fbb0e9SAlexander Kozyrev rte_mtr_error_set(error, ENOTSUP, 152548fbb0e9SAlexander Kozyrev RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 152648fbb0e9SAlexander Kozyrev "Meter is not supported"); 152748fbb0e9SAlexander Kozyrev return NULL; 152848fbb0e9SAlexander Kozyrev } 152948fbb0e9SAlexander Kozyrev return (void *)(uintptr_t)mlx5_flow_meter_policy_find(dev, policy_id, 153048fbb0e9SAlexander Kozyrev &policy_idx); 153148fbb0e9SAlexander Kozyrev } 153248fbb0e9SAlexander Kozyrev 15337576c32eSGregory Etelson #if defined(HAVE_MLX5_HWS_SUPPORT) 153448fbb0e9SAlexander Kozyrev /** 153524865366SAlexander Kozyrev * Callback to delete MTR policy for HWS. 153624865366SAlexander Kozyrev * 153724865366SAlexander Kozyrev * @param[in] dev 153824865366SAlexander Kozyrev * Pointer to Ethernet device. 153924865366SAlexander Kozyrev * @param[in] policy_id 154024865366SAlexander Kozyrev * Meter policy id. 154124865366SAlexander Kozyrev * @param[out] error 154224865366SAlexander Kozyrev * Pointer to the error structure. 154324865366SAlexander Kozyrev * 154424865366SAlexander Kozyrev * @return 154524865366SAlexander Kozyrev * 0 on success, a negative errno value otherwise and rte_errno is set. 154624865366SAlexander Kozyrev */ 154724865366SAlexander Kozyrev static int 154824865366SAlexander Kozyrev mlx5_flow_meter_policy_hws_delete(struct rte_eth_dev *dev, 154924865366SAlexander Kozyrev uint32_t policy_id, 155024865366SAlexander Kozyrev struct rte_mtr_error *error) 155124865366SAlexander Kozyrev { 155224865366SAlexander Kozyrev struct mlx5_priv *priv = dev->data->dev_private; 155324865366SAlexander Kozyrev struct mlx5_flow_meter_policy *mtr_policy; 155424865366SAlexander Kozyrev uint32_t i, j; 155524865366SAlexander Kozyrev uint32_t nb_flows = 0; 155624865366SAlexander Kozyrev int ret; 155724865366SAlexander Kozyrev struct rte_flow_op_attr op_attr = { .postpone = 1 }; 155824865366SAlexander Kozyrev struct rte_flow_op_result result[RTE_COLORS * MLX5_MTR_DOMAIN_MAX]; 155924865366SAlexander Kozyrev 156024865366SAlexander Kozyrev if (!priv->mtr_policy_arr) 1561077eb39fSAlexander Kozyrev return mlx5_flow_meter_policy_delete(dev, policy_id, error); 156224865366SAlexander Kozyrev /* Meter policy must exist. */ 156324865366SAlexander Kozyrev mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, NULL); 156424865366SAlexander Kozyrev if (!mtr_policy->initialized) 156524865366SAlexander Kozyrev return -rte_mtr_error_set(error, ENOENT, 156624865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL, 156724865366SAlexander Kozyrev "Meter policy does not exists."); 156824865366SAlexander Kozyrev /* Check policy is unused. */ 156924865366SAlexander Kozyrev if (mtr_policy->ref_cnt) 157024865366SAlexander Kozyrev return -rte_mtr_error_set(error, EBUSY, 157124865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 157224865366SAlexander Kozyrev NULL, "Meter policy is in use."); 157324865366SAlexander Kozyrev rte_spinlock_lock(&priv->hw_ctrl_lock); 157424865366SAlexander Kozyrev for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) { 157524865366SAlexander Kozyrev for (j = 0; j < RTE_COLORS; j++) { 157624865366SAlexander Kozyrev if (mtr_policy->hws_flow_rule[i][j]) { 157724865366SAlexander Kozyrev ret = rte_flow_async_destroy(dev->data->port_id, 157824865366SAlexander Kozyrev CTRL_QUEUE_ID(priv), &op_attr, 157924865366SAlexander Kozyrev mtr_policy->hws_flow_rule[i][j], 158024865366SAlexander Kozyrev NULL, NULL); 158124865366SAlexander Kozyrev if (ret < 0) 158224865366SAlexander Kozyrev continue; 158324865366SAlexander Kozyrev nb_flows++; 158424865366SAlexander Kozyrev } 158524865366SAlexander Kozyrev } 158624865366SAlexander Kozyrev } 158724865366SAlexander Kozyrev ret = rte_flow_push(dev->data->port_id, CTRL_QUEUE_ID(priv), NULL); 158824865366SAlexander Kozyrev while (nb_flows && (ret >= 0)) { 158924865366SAlexander Kozyrev ret = rte_flow_pull(dev->data->port_id, 159024865366SAlexander Kozyrev CTRL_QUEUE_ID(priv), result, 159124865366SAlexander Kozyrev nb_flows, NULL); 159224865366SAlexander Kozyrev nb_flows -= ret; 159324865366SAlexander Kozyrev } 159424865366SAlexander Kozyrev for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) { 159524865366SAlexander Kozyrev if (mtr_policy->hws_flow_table[i]) 159624865366SAlexander Kozyrev rte_flow_template_table_destroy(dev->data->port_id, 159724865366SAlexander Kozyrev mtr_policy->hws_flow_table[i], NULL); 159824865366SAlexander Kozyrev } 159924865366SAlexander Kozyrev for (i = 0; i < RTE_COLORS; i++) { 160024865366SAlexander Kozyrev if (mtr_policy->hws_act_templ[i]) 160124865366SAlexander Kozyrev rte_flow_actions_template_destroy(dev->data->port_id, 160224865366SAlexander Kozyrev mtr_policy->hws_act_templ[i], NULL); 160324865366SAlexander Kozyrev } 160424865366SAlexander Kozyrev if (mtr_policy->hws_item_templ) 160524865366SAlexander Kozyrev rte_flow_pattern_template_destroy(dev->data->port_id, 160624865366SAlexander Kozyrev mtr_policy->hws_item_templ, NULL); 160724865366SAlexander Kozyrev rte_spinlock_unlock(&priv->hw_ctrl_lock); 160824865366SAlexander Kozyrev memset(mtr_policy, 0, sizeof(struct mlx5_flow_meter_policy)); 160924865366SAlexander Kozyrev return 0; 161024865366SAlexander Kozyrev } 161124865366SAlexander Kozyrev 161224865366SAlexander Kozyrev /** 161324865366SAlexander Kozyrev * Callback to add MTR policy for HWS. 161424865366SAlexander Kozyrev * 161524865366SAlexander Kozyrev * @param[in] dev 161624865366SAlexander Kozyrev * Pointer to Ethernet device. 161724865366SAlexander Kozyrev * @param[out] policy_id 161824865366SAlexander Kozyrev * Pointer to policy id 161924865366SAlexander Kozyrev * @param[in] actions 162024865366SAlexander Kozyrev * Pointer to meter policy action detail. 162124865366SAlexander Kozyrev * @param[out] error 162224865366SAlexander Kozyrev * Pointer to the error structure. 162324865366SAlexander Kozyrev * 162424865366SAlexander Kozyrev * @return 162524865366SAlexander Kozyrev * 0 on success, a negative errno value otherwise and rte_errno is set. 162624865366SAlexander Kozyrev */ 162724865366SAlexander Kozyrev static int 162824865366SAlexander Kozyrev mlx5_flow_meter_policy_hws_add(struct rte_eth_dev *dev, 162924865366SAlexander Kozyrev uint32_t policy_id, 163024865366SAlexander Kozyrev struct rte_mtr_meter_policy_params *policy, 163124865366SAlexander Kozyrev struct rte_mtr_error *error) 163224865366SAlexander Kozyrev { 163324865366SAlexander Kozyrev struct mlx5_priv *priv = dev->data->dev_private; 163424865366SAlexander Kozyrev struct mlx5_flow_meter_policy *mtr_policy = NULL; 163524865366SAlexander Kozyrev const struct rte_flow_action *act; 163624865366SAlexander Kozyrev const struct rte_flow_action_meter *mtr; 163724865366SAlexander Kozyrev struct mlx5_flow_meter_info *fm; 163824865366SAlexander Kozyrev struct mlx5_flow_meter_policy *plc; 163924865366SAlexander Kozyrev uint8_t domain_color = MLX5_MTR_ALL_DOMAIN_BIT; 164024865366SAlexander Kozyrev bool is_rss = false; 164124865366SAlexander Kozyrev bool is_hierarchy = false; 164224865366SAlexander Kozyrev int i, j; 164324865366SAlexander Kozyrev uint32_t nb_colors = 0; 164424865366SAlexander Kozyrev uint32_t nb_flows = 0; 164524865366SAlexander Kozyrev int color; 164624865366SAlexander Kozyrev int ret; 164724865366SAlexander Kozyrev struct rte_flow_pattern_template_attr pta = {0}; 164824865366SAlexander Kozyrev struct rte_flow_actions_template_attr ata = {0}; 164924865366SAlexander Kozyrev struct rte_flow_template_table_attr ta = { {0}, 0 }; 165024865366SAlexander Kozyrev struct rte_flow_op_attr op_attr = { .postpone = 1 }; 165124865366SAlexander Kozyrev struct rte_flow_op_result result[RTE_COLORS * MLX5_MTR_DOMAIN_MAX]; 165224865366SAlexander Kozyrev const uint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1; 165324865366SAlexander Kozyrev int color_reg_c_idx = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 165424865366SAlexander Kozyrev 0, NULL); 165524865366SAlexander Kozyrev struct rte_flow_item_tag tag_spec = { 165624865366SAlexander Kozyrev .data = 0, 165724865366SAlexander Kozyrev .index = color_reg_c_idx 165824865366SAlexander Kozyrev }; 165924865366SAlexander Kozyrev struct rte_flow_item_tag tag_mask = { 166024865366SAlexander Kozyrev .data = color_mask, 166124865366SAlexander Kozyrev .index = 0xff}; 166224865366SAlexander Kozyrev struct rte_flow_item pattern[] = { 166324865366SAlexander Kozyrev [0] = { 166424865366SAlexander Kozyrev .type = (enum rte_flow_item_type) 166524865366SAlexander Kozyrev MLX5_RTE_FLOW_ITEM_TYPE_TAG, 166624865366SAlexander Kozyrev .spec = &tag_spec, 166724865366SAlexander Kozyrev .mask = &tag_mask, 166824865366SAlexander Kozyrev }, 166924865366SAlexander Kozyrev [1] = { .type = RTE_FLOW_ITEM_TYPE_END } 167024865366SAlexander Kozyrev }; 167124865366SAlexander Kozyrev 1672*61a81061SGregory Etelson if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL)) 1673*61a81061SGregory Etelson return -rte_mtr_error_set(error, EINVAL, 1674*61a81061SGregory Etelson RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 1675*61a81061SGregory Etelson "non-template flow engine was not configured"); 167624865366SAlexander Kozyrev if (!priv->mtr_policy_arr) 1677077eb39fSAlexander Kozyrev return mlx5_flow_meter_policy_add(dev, policy_id, policy, error); 167824865366SAlexander Kozyrev mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, NULL); 167924865366SAlexander Kozyrev if (mtr_policy->initialized) 168024865366SAlexander Kozyrev return -rte_mtr_error_set(error, EEXIST, 168124865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 168224865366SAlexander Kozyrev NULL, "Meter policy already exists."); 168324865366SAlexander Kozyrev if (!policy || 168448fbb0e9SAlexander Kozyrev (!policy->actions[RTE_COLOR_RED] && 168548fbb0e9SAlexander Kozyrev !policy->actions[RTE_COLOR_YELLOW] && 168648fbb0e9SAlexander Kozyrev !policy->actions[RTE_COLOR_GREEN])) 168724865366SAlexander Kozyrev return -rte_mtr_error_set(error, EINVAL, 168824865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_POLICY, 168924865366SAlexander Kozyrev NULL, "Meter policy actions are not valid."); 169024865366SAlexander Kozyrev if (policy->actions[RTE_COLOR_RED] == RTE_FLOW_ACTION_TYPE_END) 169124865366SAlexander Kozyrev mtr_policy->skip_r = 1; 169224865366SAlexander Kozyrev if (policy->actions[RTE_COLOR_YELLOW] == RTE_FLOW_ACTION_TYPE_END) 169324865366SAlexander Kozyrev mtr_policy->skip_y = 1; 169424865366SAlexander Kozyrev if (policy->actions[RTE_COLOR_GREEN] == RTE_FLOW_ACTION_TYPE_END) 169524865366SAlexander Kozyrev mtr_policy->skip_g = 1; 169624865366SAlexander Kozyrev if (mtr_policy->skip_r && mtr_policy->skip_y && mtr_policy->skip_g) 169724865366SAlexander Kozyrev return -rte_mtr_error_set(error, ENOTSUP, 169824865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 169924865366SAlexander Kozyrev NULL, "Meter policy actions are empty."); 170024865366SAlexander Kozyrev for (i = 0; i < RTE_COLORS; i++) { 170124865366SAlexander Kozyrev act = policy->actions[i]; 170224865366SAlexander Kozyrev while (act && act->type != RTE_FLOW_ACTION_TYPE_END) { 170324865366SAlexander Kozyrev switch (act->type) { 170424865366SAlexander Kozyrev case RTE_FLOW_ACTION_TYPE_PORT_ID: 170524865366SAlexander Kozyrev /* fall-through. */ 170624865366SAlexander Kozyrev case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: 170724865366SAlexander Kozyrev domain_color &= ~(MLX5_MTR_DOMAIN_INGRESS_BIT | 170824865366SAlexander Kozyrev MLX5_MTR_DOMAIN_EGRESS_BIT); 170924865366SAlexander Kozyrev break; 171024865366SAlexander Kozyrev case RTE_FLOW_ACTION_TYPE_RSS: 171124865366SAlexander Kozyrev is_rss = true; 171224865366SAlexander Kozyrev /* fall-through. */ 171324865366SAlexander Kozyrev case RTE_FLOW_ACTION_TYPE_QUEUE: 171424865366SAlexander Kozyrev domain_color &= ~(MLX5_MTR_DOMAIN_EGRESS_BIT | 171524865366SAlexander Kozyrev MLX5_MTR_DOMAIN_TRANSFER_BIT); 171624865366SAlexander Kozyrev break; 171724865366SAlexander Kozyrev case RTE_FLOW_ACTION_TYPE_METER: 171824865366SAlexander Kozyrev is_hierarchy = true; 171924865366SAlexander Kozyrev mtr = act->conf; 172024865366SAlexander Kozyrev fm = mlx5_flow_meter_find(priv, 172124865366SAlexander Kozyrev mtr->mtr_id, NULL); 172224865366SAlexander Kozyrev if (!fm) 172324865366SAlexander Kozyrev return -rte_mtr_error_set(error, EINVAL, 172424865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_MTR_ID, NULL, 172524865366SAlexander Kozyrev "Meter not found in meter hierarchy."); 172624865366SAlexander Kozyrev plc = mlx5_flow_meter_policy_find(dev, 172724865366SAlexander Kozyrev fm->policy_id, 172824865366SAlexander Kozyrev NULL); 172924865366SAlexander Kozyrev MLX5_ASSERT(plc); 173024865366SAlexander Kozyrev domain_color &= MLX5_MTR_ALL_DOMAIN_BIT & 173124865366SAlexander Kozyrev (plc->ingress << 173224865366SAlexander Kozyrev MLX5_MTR_DOMAIN_INGRESS); 173324865366SAlexander Kozyrev domain_color &= MLX5_MTR_ALL_DOMAIN_BIT & 173424865366SAlexander Kozyrev (plc->egress << 173524865366SAlexander Kozyrev MLX5_MTR_DOMAIN_EGRESS); 173624865366SAlexander Kozyrev domain_color &= MLX5_MTR_ALL_DOMAIN_BIT & 173724865366SAlexander Kozyrev (plc->transfer << 173824865366SAlexander Kozyrev MLX5_MTR_DOMAIN_TRANSFER); 173924865366SAlexander Kozyrev break; 174024865366SAlexander Kozyrev default: 174124865366SAlexander Kozyrev break; 174224865366SAlexander Kozyrev } 174324865366SAlexander Kozyrev act++; 174424865366SAlexander Kozyrev } 174524865366SAlexander Kozyrev } 174648fbb0e9SAlexander Kozyrev if (priv->sh->config.dv_esw_en) 174748fbb0e9SAlexander Kozyrev domain_color &= ~(MLX5_MTR_DOMAIN_EGRESS_BIT | 174848fbb0e9SAlexander Kozyrev MLX5_MTR_DOMAIN_TRANSFER_BIT); 174948fbb0e9SAlexander Kozyrev else 175048fbb0e9SAlexander Kozyrev domain_color &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT; 175124865366SAlexander Kozyrev if (!domain_color) 175224865366SAlexander Kozyrev return -rte_mtr_error_set(error, ENOTSUP, 175324865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 175424865366SAlexander Kozyrev NULL, "Meter policy domains are conflicting."); 175524865366SAlexander Kozyrev mtr_policy->is_rss = is_rss; 175624865366SAlexander Kozyrev mtr_policy->ingress = !!(domain_color & MLX5_MTR_DOMAIN_INGRESS_BIT); 175724865366SAlexander Kozyrev pta.ingress = mtr_policy->ingress; 175824865366SAlexander Kozyrev mtr_policy->egress = !!(domain_color & MLX5_MTR_DOMAIN_EGRESS_BIT); 175924865366SAlexander Kozyrev pta.egress = mtr_policy->egress; 176024865366SAlexander Kozyrev mtr_policy->transfer = !!(domain_color & MLX5_MTR_DOMAIN_TRANSFER_BIT); 176124865366SAlexander Kozyrev pta.transfer = mtr_policy->transfer; 176224865366SAlexander Kozyrev mtr_policy->group = MLX5_FLOW_TABLE_HWS_POLICY - policy_id; 176324865366SAlexander Kozyrev mtr_policy->is_hierarchy = is_hierarchy; 176424865366SAlexander Kozyrev mtr_policy->initialized = 1; 176524865366SAlexander Kozyrev rte_spinlock_lock(&priv->hw_ctrl_lock); 176624865366SAlexander Kozyrev mtr_policy->hws_item_templ = 176724865366SAlexander Kozyrev rte_flow_pattern_template_create(dev->data->port_id, 176824865366SAlexander Kozyrev &pta, pattern, NULL); 176924865366SAlexander Kozyrev if (!mtr_policy->hws_item_templ) 177024865366SAlexander Kozyrev goto policy_add_err; 177124865366SAlexander Kozyrev for (i = 0; i < RTE_COLORS; i++) { 177224865366SAlexander Kozyrev if (mtr_policy->skip_g && i == RTE_COLOR_GREEN) 177324865366SAlexander Kozyrev continue; 177424865366SAlexander Kozyrev if (mtr_policy->skip_y && i == RTE_COLOR_YELLOW) 177524865366SAlexander Kozyrev continue; 177624865366SAlexander Kozyrev if (mtr_policy->skip_r && i == RTE_COLOR_RED) 177724865366SAlexander Kozyrev continue; 177824865366SAlexander Kozyrev mtr_policy->hws_act_templ[nb_colors] = 177924865366SAlexander Kozyrev rte_flow_actions_template_create(dev->data->port_id, 178024865366SAlexander Kozyrev &ata, policy->actions[i], 178124865366SAlexander Kozyrev policy->actions[i], NULL); 178224865366SAlexander Kozyrev if (!mtr_policy->hws_act_templ[nb_colors]) 178324865366SAlexander Kozyrev goto policy_add_err; 178424865366SAlexander Kozyrev nb_colors++; 178524865366SAlexander Kozyrev } 178624865366SAlexander Kozyrev for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) { 178724865366SAlexander Kozyrev memset(&ta, 0, sizeof(ta)); 178824865366SAlexander Kozyrev ta.nb_flows = RTE_COLORS; 178924865366SAlexander Kozyrev ta.flow_attr.group = mtr_policy->group; 179024865366SAlexander Kozyrev if (i == MLX5_MTR_DOMAIN_INGRESS) { 179124865366SAlexander Kozyrev if (!mtr_policy->ingress) 179224865366SAlexander Kozyrev continue; 179324865366SAlexander Kozyrev ta.flow_attr.ingress = 1; 179424865366SAlexander Kozyrev } else if (i == MLX5_MTR_DOMAIN_EGRESS) { 179524865366SAlexander Kozyrev if (!mtr_policy->egress) 179624865366SAlexander Kozyrev continue; 179724865366SAlexander Kozyrev ta.flow_attr.egress = 1; 179824865366SAlexander Kozyrev } else if (i == MLX5_MTR_DOMAIN_TRANSFER) { 179924865366SAlexander Kozyrev if (!mtr_policy->transfer) 180024865366SAlexander Kozyrev continue; 180124865366SAlexander Kozyrev ta.flow_attr.transfer = 1; 180224865366SAlexander Kozyrev } 180324865366SAlexander Kozyrev mtr_policy->hws_flow_table[i] = 180424865366SAlexander Kozyrev rte_flow_template_table_create(dev->data->port_id, 180524865366SAlexander Kozyrev &ta, &mtr_policy->hws_item_templ, 1, 180624865366SAlexander Kozyrev mtr_policy->hws_act_templ, nb_colors, 180724865366SAlexander Kozyrev NULL); 180824865366SAlexander Kozyrev if (!mtr_policy->hws_flow_table[i]) 180924865366SAlexander Kozyrev goto policy_add_err; 181024865366SAlexander Kozyrev nb_colors = 0; 181124865366SAlexander Kozyrev for (j = 0; j < RTE_COLORS; j++) { 181224865366SAlexander Kozyrev if (mtr_policy->skip_g && j == RTE_COLOR_GREEN) 181324865366SAlexander Kozyrev continue; 181424865366SAlexander Kozyrev if (mtr_policy->skip_y && j == RTE_COLOR_YELLOW) 181524865366SAlexander Kozyrev continue; 181624865366SAlexander Kozyrev if (mtr_policy->skip_r && j == RTE_COLOR_RED) 181724865366SAlexander Kozyrev continue; 181824865366SAlexander Kozyrev color = rte_col_2_mlx5_col((enum rte_color)j); 181924865366SAlexander Kozyrev tag_spec.data = color; 182024865366SAlexander Kozyrev mtr_policy->hws_flow_rule[i][j] = 182124865366SAlexander Kozyrev rte_flow_async_create(dev->data->port_id, 182224865366SAlexander Kozyrev CTRL_QUEUE_ID(priv), &op_attr, 182324865366SAlexander Kozyrev mtr_policy->hws_flow_table[i], 182424865366SAlexander Kozyrev pattern, 0, policy->actions[j], 182524865366SAlexander Kozyrev nb_colors, NULL, NULL); 182624865366SAlexander Kozyrev if (!mtr_policy->hws_flow_rule[i][j]) 182724865366SAlexander Kozyrev goto policy_add_err; 182824865366SAlexander Kozyrev nb_colors++; 182924865366SAlexander Kozyrev nb_flows++; 183024865366SAlexander Kozyrev } 183124865366SAlexander Kozyrev ret = rte_flow_push(dev->data->port_id, 183224865366SAlexander Kozyrev CTRL_QUEUE_ID(priv), NULL); 183324865366SAlexander Kozyrev if (ret < 0) 183424865366SAlexander Kozyrev goto policy_add_err; 183524865366SAlexander Kozyrev while (nb_flows) { 183624865366SAlexander Kozyrev ret = rte_flow_pull(dev->data->port_id, 183724865366SAlexander Kozyrev CTRL_QUEUE_ID(priv), result, 183824865366SAlexander Kozyrev nb_flows, NULL); 183924865366SAlexander Kozyrev if (ret < 0) 184024865366SAlexander Kozyrev goto policy_add_err; 184124865366SAlexander Kozyrev for (j = 0; j < ret; j++) { 184224865366SAlexander Kozyrev if (result[j].status == RTE_FLOW_OP_ERROR) 184324865366SAlexander Kozyrev goto policy_add_err; 184424865366SAlexander Kozyrev } 184524865366SAlexander Kozyrev nb_flows -= ret; 184624865366SAlexander Kozyrev } 184724865366SAlexander Kozyrev } 184824865366SAlexander Kozyrev rte_spinlock_unlock(&priv->hw_ctrl_lock); 184924865366SAlexander Kozyrev return 0; 185024865366SAlexander Kozyrev policy_add_err: 185124865366SAlexander Kozyrev rte_spinlock_unlock(&priv->hw_ctrl_lock); 185224865366SAlexander Kozyrev ret = mlx5_flow_meter_policy_hws_delete(dev, policy_id, error); 185324865366SAlexander Kozyrev memset(mtr_policy, 0, sizeof(struct mlx5_flow_meter_policy)); 185424865366SAlexander Kozyrev if (ret) 185524865366SAlexander Kozyrev return ret; 185624865366SAlexander Kozyrev return -rte_mtr_error_set(error, ENOTSUP, 185724865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_UNSPECIFIED, 185824865366SAlexander Kozyrev NULL, "Failed to create meter policy."); 185924865366SAlexander Kozyrev } 18607576c32eSGregory Etelson #endif 186124865366SAlexander Kozyrev /** 186244432018SLi Zhang * Check meter validation. 186344432018SLi Zhang * 186444432018SLi Zhang * @param[in] priv 186544432018SLi Zhang * Pointer to mlx5 private data structure. 186644432018SLi Zhang * @param[in] meter_id 186744432018SLi Zhang * Meter id. 186844432018SLi Zhang * @param[in] params 186944432018SLi Zhang * Pointer to rte meter parameters. 187044432018SLi Zhang * @param[out] error 187144432018SLi Zhang * Pointer to rte meter error structure. 187244432018SLi Zhang * 187344432018SLi Zhang * @return 187444432018SLi Zhang * 0 on success, a negative errno value otherwise and rte_errno is set. 187544432018SLi Zhang */ 187644432018SLi Zhang static int 187744432018SLi Zhang mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id, 187844432018SLi Zhang struct rte_mtr_params *params, 187944432018SLi Zhang struct rte_mtr_error *error) 188044432018SLi Zhang { 188144432018SLi Zhang /* Meter must use global drop action. */ 188244432018SLi Zhang if (!priv->sh->dr_drop_action) 188344432018SLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 188444432018SLi Zhang RTE_MTR_ERROR_TYPE_MTR_PARAMS, 188544432018SLi Zhang NULL, 188644432018SLi Zhang "No drop action ready for meter."); 188744432018SLi Zhang /* Meter params must not be NULL. */ 188844432018SLi Zhang if (params == NULL) 188944432018SLi Zhang return -rte_mtr_error_set(error, EINVAL, 189044432018SLi Zhang RTE_MTR_ERROR_TYPE_MTR_PARAMS, 189144432018SLi Zhang NULL, "Meter object params null."); 189244432018SLi Zhang /* Previous meter color is not supported. */ 18936b838de3SShun Hao if (params->use_prev_mtr_color && !priv->sh->meter_aso_en) 189444432018SLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 189544432018SLi Zhang RTE_MTR_ERROR_TYPE_MTR_PARAMS, 189644432018SLi Zhang NULL, 189744432018SLi Zhang "Previous meter color " 189844432018SLi Zhang "not supported."); 189944432018SLi Zhang if (params->meter_policy_id == MLX5_INVALID_POLICY_ID) 190044432018SLi Zhang return -rte_mtr_error_set(error, ENOENT, 190144432018SLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 190244432018SLi Zhang NULL, "Meter policy id not valid."); 190344432018SLi Zhang /* Validate meter id. */ 190444432018SLi Zhang if (mlx5_flow_meter_find(priv, meter_id, NULL)) 190544432018SLi Zhang return -rte_mtr_error_set(error, EEXIST, 190644432018SLi Zhang RTE_MTR_ERROR_TYPE_MTR_ID, NULL, 190744432018SLi Zhang "Meter object already exists."); 190844432018SLi Zhang return 0; 190944432018SLi Zhang } 191044432018SLi Zhang 191144432018SLi Zhang /** 191233e01809SSuanming Mou * Modify the flow meter action. 191333e01809SSuanming Mou * 191433e01809SSuanming Mou * @param[in] priv 191533e01809SSuanming Mou * Pointer to mlx5 private data structure. 191633e01809SSuanming Mou * @param[in] fm 191733e01809SSuanming Mou * Pointer to flow meter to be modified. 191833e01809SSuanming Mou * @param[in] srtcm 191933e01809SSuanming Mou * Pointer to meter srtcm description parameter. 192033e01809SSuanming Mou * @param[in] modify_bits 192133e01809SSuanming Mou * The bit in srtcm to be updated. 192233e01809SSuanming Mou * @param[in] active_state 192333e01809SSuanming Mou * The state to be updated. 192433e01809SSuanming Mou * @return 192533e01809SSuanming Mou * 0 on success, o negative value otherwise. 192633e01809SSuanming Mou */ 192733e01809SSuanming Mou static int 192833e01809SSuanming Mou mlx5_flow_meter_action_modify(struct mlx5_priv *priv, 1929e6100c7bSLi Zhang struct mlx5_flow_meter_info *fm, 193033e01809SSuanming Mou const struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm, 1931e93c58daSLi Zhang uint64_t modify_bits, uint32_t active_state, uint32_t is_enable) 193233e01809SSuanming Mou { 193333e01809SSuanming Mou #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER 193404e740e6SGregory Etelson struct mlx5_dev_ctx_shared *sh = priv->sh; 193533e01809SSuanming Mou uint32_t in[MLX5_ST_SZ_DW(flow_meter_parameters)] = { 0 }; 193633e01809SSuanming Mou uint32_t *attr; 193733e01809SSuanming Mou struct mlx5dv_dr_flow_meter_attr mod_attr = { 0 }; 193833e01809SSuanming Mou int ret; 1939e93c58daSLi Zhang struct mlx5_aso_mtr *aso_mtr = NULL; 1940e6100c7bSLi Zhang uint32_t cbs_cir, ebs_eir, val; 194133e01809SSuanming Mou 194204e740e6SGregory Etelson if (sh->meter_aso_en) { 1943e93c58daSLi Zhang fm->is_enable = !!is_enable; 1944e93c58daSLi Zhang aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm); 19450c37d8f7SGregory Etelson aso_mtr->state = ASO_METER_WAIT; 19464359d9d1SGregory Etelson ret = mlx5_aso_meter_update_by_wqe(priv, MLX5_HW_INV_QUEUE, 194704e740e6SGregory Etelson aso_mtr, &priv->mtr_bulk, 194804e740e6SGregory Etelson NULL, true); 1949e93c58daSLi Zhang if (ret) 1950e93c58daSLi Zhang return ret; 19514359d9d1SGregory Etelson ret = mlx5_aso_mtr_wait(priv, aso_mtr, false); 1952e93c58daSLi Zhang if (ret) 1953e93c58daSLi Zhang return ret; 1954e93c58daSLi Zhang } else { 195533e01809SSuanming Mou /* Fill command parameters. */ 19565e9f9a28SGregory Etelson mod_attr.reg_c_index = sh->registers.aso_reg - REG_C_0; 195733e01809SSuanming Mou mod_attr.flow_meter_parameter = in; 1958e6100c7bSLi Zhang mod_attr.flow_meter_parameter_sz = 1959e6100c7bSLi Zhang MLX5_ST_SZ_BYTES(flow_meter_parameters); 196033e01809SSuanming Mou if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE) 196133e01809SSuanming Mou mod_attr.active = !!active_state; 196233e01809SSuanming Mou else 196333e01809SSuanming Mou mod_attr.active = 0; 196433e01809SSuanming Mou attr = in; 1965e6100c7bSLi Zhang cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir); 1966e6100c7bSLi Zhang ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir); 196733e01809SSuanming Mou if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS) { 1968e93c58daSLi Zhang val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) & 1969e93c58daSLi Zhang ASO_DSEG_EXP_MASK; 1970e93c58daSLi Zhang MLX5_SET(flow_meter_parameters, attr, 1971e93c58daSLi Zhang cbs_exponent, val); 1972e93c58daSLi Zhang val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) & 1973e93c58daSLi Zhang ASO_DSEG_MAN_MASK; 1974e93c58daSLi Zhang MLX5_SET(flow_meter_parameters, attr, 1975e93c58daSLi Zhang cbs_mantissa, val); 197633e01809SSuanming Mou } 197733e01809SSuanming Mou if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR) { 197833a7493cSBing Zhao val = (cbs_cir >> ASO_DSEG_XIR_EXP_OFFSET) & 1979e93c58daSLi Zhang ASO_DSEG_EXP_MASK; 1980e93c58daSLi Zhang MLX5_SET(flow_meter_parameters, attr, 1981e93c58daSLi Zhang cir_exponent, val); 1982e6100c7bSLi Zhang val = cbs_cir & ASO_DSEG_MAN_MASK; 1983e93c58daSLi Zhang MLX5_SET(flow_meter_parameters, attr, 1984e93c58daSLi Zhang cir_mantissa, val); 198533e01809SSuanming Mou } 198633e01809SSuanming Mou if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_EBS) { 1987e93c58daSLi Zhang val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) & 1988e93c58daSLi Zhang ASO_DSEG_EXP_MASK; 1989e93c58daSLi Zhang MLX5_SET(flow_meter_parameters, attr, 1990e93c58daSLi Zhang ebs_exponent, val); 1991e93c58daSLi Zhang val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) & 1992e93c58daSLi Zhang ASO_DSEG_MAN_MASK; 1993e93c58daSLi Zhang MLX5_SET(flow_meter_parameters, attr, 1994e93c58daSLi Zhang ebs_mantissa, val); 199533e01809SSuanming Mou } 199633e01809SSuanming Mou /* Apply modifications to meter only if it was created. */ 1997bf62fb76SShun Hao if (fm->meter_action_g) { 199833e01809SSuanming Mou ret = mlx5_glue->dv_modify_flow_action_meter 1999bf62fb76SShun Hao (fm->meter_action_g, &mod_attr, 200033e01809SSuanming Mou rte_cpu_to_be_64(modify_bits)); 200133e01809SSuanming Mou if (ret) 200233e01809SSuanming Mou return ret; 200333e01809SSuanming Mou } 20047be78d02SJosh Soref /* Update succeeded modify meter parameters. */ 200533e01809SSuanming Mou if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE) 200633e01809SSuanming Mou fm->active_state = !!active_state; 2007e93c58daSLi Zhang } 200833e01809SSuanming Mou return 0; 200933e01809SSuanming Mou #else 201033e01809SSuanming Mou (void)priv; 201133e01809SSuanming Mou (void)fm; 201233e01809SSuanming Mou (void)srtcm; 201333e01809SSuanming Mou (void)modify_bits; 201433e01809SSuanming Mou (void)active_state; 2015c99b4f8bSLi Zhang (void)is_enable; 201633e01809SSuanming Mou return -ENOTSUP; 201733e01809SSuanming Mou #endif 201833e01809SSuanming Mou } 201933e01809SSuanming Mou 202044432018SLi Zhang static int 202144432018SLi Zhang mlx5_flow_meter_stats_enable_update(struct rte_eth_dev *dev, 202244432018SLi Zhang struct mlx5_flow_meter_info *fm, 20235df35867SLi Zhang uint64_t stats_mask) 20245df35867SLi Zhang { 20255df35867SLi Zhang fm->bytes_dropped = 20265df35867SLi Zhang (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0; 20275df35867SLi Zhang fm->pkts_dropped = (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0; 202844432018SLi Zhang if (fm->bytes_dropped || fm->pkts_dropped) { 202944432018SLi Zhang if (!fm->drop_cnt) { 203044432018SLi Zhang /* Alloc policer counters. */ 203144432018SLi Zhang fm->drop_cnt = mlx5_counter_alloc(dev); 203244432018SLi Zhang if (!fm->drop_cnt) 203344432018SLi Zhang return -1; 203444432018SLi Zhang } 203544432018SLi Zhang } else { 203644432018SLi Zhang if (fm->drop_cnt) { 203744432018SLi Zhang mlx5_counter_free(dev, fm->drop_cnt); 203844432018SLi Zhang fm->drop_cnt = 0; 203944432018SLi Zhang } 204044432018SLi Zhang } 204144432018SLi Zhang return 0; 204244432018SLi Zhang } 204344432018SLi Zhang 204444432018SLi Zhang /** 204544432018SLi Zhang * Create meter rules. 204644432018SLi Zhang * 204744432018SLi Zhang * @param[in] dev 204844432018SLi Zhang * Pointer to Ethernet device. 204944432018SLi Zhang * @param[in] meter_id 205044432018SLi Zhang * Meter id. 205144432018SLi Zhang * @param[in] params 205244432018SLi Zhang * Pointer to rte meter parameters. 205344432018SLi Zhang * @param[in] shared 205444432018SLi Zhang * Meter shared with other flow or not. 205544432018SLi Zhang * @param[out] error 205644432018SLi Zhang * Pointer to rte meter error structure. 205744432018SLi Zhang * 205844432018SLi Zhang * @return 205944432018SLi Zhang * 0 on success, a negative errno value otherwise and rte_errno is set. 206044432018SLi Zhang */ 206144432018SLi Zhang static int 206244432018SLi Zhang mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id, 206344432018SLi Zhang struct rte_mtr_params *params, int shared, 206444432018SLi Zhang struct rte_mtr_error *error) 206544432018SLi Zhang { 206644432018SLi Zhang struct mlx5_priv *priv = dev->data->dev_private; 206744432018SLi Zhang struct mlx5_legacy_flow_meters *fms = &priv->flow_meters; 206844432018SLi Zhang struct mlx5_flow_meter_profile *fmp; 206944432018SLi Zhang struct mlx5_flow_meter_info *fm; 2070be8cda49SDmitry Kozlyuk /* GCC fails to infer legacy_fm is set when !priv->sh->meter_aso_en. */ 2071be8cda49SDmitry Kozlyuk struct mlx5_legacy_flow_meter *legacy_fm = NULL; 207244432018SLi Zhang struct mlx5_flow_meter_policy *mtr_policy = NULL; 207344432018SLi Zhang struct mlx5_indexed_pool_config flow_ipool_cfg = { 207444432018SLi Zhang .size = 0, 207544432018SLi Zhang .trunk_size = 64, 207644432018SLi Zhang .need_lock = 1, 207744432018SLi Zhang .type = "mlx5_flow_mtr_flow_id_pool", 207844432018SLi Zhang }; 207944432018SLi Zhang struct mlx5_aso_mtr *aso_mtr; 208044432018SLi Zhang uint32_t mtr_idx, policy_idx; 208144432018SLi Zhang union mlx5_l3t_data data; 208244432018SLi Zhang int ret; 208344432018SLi Zhang uint8_t domain_bitmap; 208444432018SLi Zhang uint8_t mtr_id_bits; 208544432018SLi Zhang uint8_t mtr_reg_bits = priv->mtr_reg_share ? 208644432018SLi Zhang MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS; 208744432018SLi Zhang 208844432018SLi Zhang if (!priv->mtr_en) 208944432018SLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 209044432018SLi Zhang RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 209144432018SLi Zhang "Meter is not supported"); 209244432018SLi Zhang /* Validate the parameters. */ 209344432018SLi Zhang ret = mlx5_flow_meter_validate(priv, meter_id, params, error); 209444432018SLi Zhang if (ret) 209544432018SLi Zhang return ret; 209644432018SLi Zhang /* Meter profile must exist. */ 209744432018SLi Zhang fmp = mlx5_flow_meter_profile_find(priv, params->meter_profile_id); 209844432018SLi Zhang if (fmp == NULL) 209944432018SLi Zhang return -rte_mtr_error_set(error, ENOENT, 210044432018SLi Zhang RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 210144432018SLi Zhang NULL, "Meter profile id not valid."); 210244432018SLi Zhang /* Meter policy must exist. */ 210344432018SLi Zhang if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) { 2104e12a0166STyler Retzlaff rte_atomic_fetch_add_explicit 210544432018SLi Zhang (&priv->sh->mtrmng->def_policy_ref_cnt, 2106e12a0166STyler Retzlaff 1, rte_memory_order_relaxed); 210744432018SLi Zhang domain_bitmap = MLX5_MTR_ALL_DOMAIN_BIT; 2108a13ec19cSMichael Baum if (!priv->sh->config.dv_esw_en) 210944432018SLi Zhang domain_bitmap &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT; 211044432018SLi Zhang } else { 211144432018SLi Zhang if (!priv->sh->meter_aso_en) 211244432018SLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 211344432018SLi Zhang RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 211444432018SLi Zhang "Part of the policies cannot be " 211544432018SLi Zhang "supported without ASO "); 21164d648fadSBing Zhao mtr_policy = mlx5_flow_meter_policy_find(dev, 21174d648fadSBing Zhao params->meter_policy_id, &policy_idx); 211844432018SLi Zhang if (!mtr_policy) 211944432018SLi Zhang return -rte_mtr_error_set(error, ENOENT, 212044432018SLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 212144432018SLi Zhang NULL, "Meter policy id not valid."); 212244432018SLi Zhang domain_bitmap = (mtr_policy->ingress ? 212344432018SLi Zhang MLX5_MTR_DOMAIN_INGRESS_BIT : 0) | 212444432018SLi Zhang (mtr_policy->egress ? 212544432018SLi Zhang MLX5_MTR_DOMAIN_EGRESS_BIT : 0) | 212644432018SLi Zhang (mtr_policy->transfer ? 212744432018SLi Zhang MLX5_MTR_DOMAIN_TRANSFER_BIT : 0); 21284d648fadSBing Zhao if (fmp->g_support && mtr_policy->skip_g) 21294d648fadSBing Zhao return -rte_mtr_error_set(error, ENOTSUP, 21304d648fadSBing Zhao RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 21314d648fadSBing Zhao NULL, "Meter green policy is empty."); 21324d648fadSBing Zhao if (fmp->y_support && mtr_policy->skip_y) 21334d648fadSBing Zhao return -rte_mtr_error_set(error, ENOTSUP, 21344d648fadSBing Zhao RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 21354d648fadSBing Zhao NULL, "Meter yellow policy is empty."); 213644432018SLi Zhang } 213744432018SLi Zhang /* Allocate the flow meter memory. */ 213844432018SLi Zhang if (priv->sh->meter_aso_en) { 213944432018SLi Zhang mtr_idx = mlx5_flow_mtr_alloc(dev); 214044432018SLi Zhang if (!mtr_idx) 214144432018SLi Zhang return -rte_mtr_error_set(error, ENOMEM, 214244432018SLi Zhang RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 214344432018SLi Zhang "Memory alloc failed for meter."); 214444432018SLi Zhang aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx); 214544432018SLi Zhang fm = &aso_mtr->fm; 214644432018SLi Zhang } else { 21478a0fca11SBing Zhao if (fmp->y_support) 21488a0fca11SBing Zhao return -rte_mtr_error_set(error, ENOMEM, 21498a0fca11SBing Zhao RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 21508a0fca11SBing Zhao "Unsupported profile with yellow."); 215144432018SLi Zhang legacy_fm = mlx5_ipool_zmalloc 215244432018SLi Zhang (priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx); 215344432018SLi Zhang if (legacy_fm == NULL) 215444432018SLi Zhang return -rte_mtr_error_set(error, ENOMEM, 215544432018SLi Zhang RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 215644432018SLi Zhang "Memory alloc failed for meter."); 215744432018SLi Zhang legacy_fm->idx = mtr_idx; 215844432018SLi Zhang fm = &legacy_fm->fm; 215944432018SLi Zhang } 21603d4e27fdSDavid Marchand mtr_id_bits = MLX5_REG_BITS - rte_clz32(mtr_idx); 216144432018SLi Zhang if ((mtr_id_bits + priv->sh->mtrmng->max_mtr_flow_bits) > 216244432018SLi Zhang mtr_reg_bits) { 216344432018SLi Zhang DRV_LOG(ERR, "Meter number exceeds max limit."); 216444432018SLi Zhang goto error; 216544432018SLi Zhang } 216644432018SLi Zhang if (mtr_id_bits > priv->sh->mtrmng->max_mtr_bits) 216744432018SLi Zhang priv->sh->mtrmng->max_mtr_bits = mtr_id_bits; 216844432018SLi Zhang /* Fill the flow meter parameters. */ 216944432018SLi Zhang fm->meter_id = meter_id; 217044432018SLi Zhang fm->policy_id = params->meter_policy_id; 217144432018SLi Zhang fm->profile = fmp; 217244432018SLi Zhang if (mlx5_flow_meter_stats_enable_update(dev, fm, params->stats_mask)) 217344432018SLi Zhang goto error; 217444432018SLi Zhang if (mlx5_flow_create_mtr_tbls(dev, fm, mtr_idx, domain_bitmap)) 217544432018SLi Zhang goto error; 217644432018SLi Zhang /* Add to the flow meter list. */ 2177be8cda49SDmitry Kozlyuk if (!priv->sh->meter_aso_en) { 2178be8cda49SDmitry Kozlyuk MLX5_ASSERT(legacy_fm != NULL); 217944432018SLi Zhang TAILQ_INSERT_TAIL(fms, legacy_fm, next); 2180be8cda49SDmitry Kozlyuk } 218144432018SLi Zhang /* Add to the flow meter list. */ 218244432018SLi Zhang fm->active_state = 1; /* Config meter starts as active. */ 2183c3130c78SRongwei Liu fm->is_enable = params->meter_enable; 218444432018SLi Zhang fm->shared = !!shared; 21856b838de3SShun Hao fm->color_aware = !!params->use_prev_mtr_color; 2186e12a0166STyler Retzlaff rte_atomic_fetch_add_explicit(&fm->profile->ref_cnt, 1, rte_memory_order_relaxed); 218744432018SLi Zhang if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) { 218844432018SLi Zhang fm->def_policy = 1; 218944432018SLi Zhang fm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg); 219044432018SLi Zhang if (!fm->flow_ipool) 219144432018SLi Zhang goto error; 219244432018SLi Zhang } 219344432018SLi Zhang rte_spinlock_init(&fm->sl); 219444432018SLi Zhang /* If ASO meter supported, update ASO flow meter by wqe. */ 219544432018SLi Zhang if (priv->sh->meter_aso_en) { 219644432018SLi Zhang aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm); 21970c37d8f7SGregory Etelson aso_mtr->state = ASO_METER_WAIT; 21984359d9d1SGregory Etelson ret = mlx5_aso_meter_update_by_wqe(priv, MLX5_HW_INV_QUEUE, 2199478ba4bbSSuanming Mou aso_mtr, &priv->mtr_bulk, NULL, true); 220044432018SLi Zhang if (ret) 220144432018SLi Zhang goto error; 220244432018SLi Zhang if (!priv->mtr_idx_tbl) { 220344432018SLi Zhang priv->mtr_idx_tbl = 220444432018SLi Zhang mlx5_l3t_create(MLX5_L3T_TYPE_DWORD); 220544432018SLi Zhang if (!priv->mtr_idx_tbl) 220644432018SLi Zhang goto error; 220744432018SLi Zhang } 220844432018SLi Zhang data.dword = mtr_idx; 220944432018SLi Zhang if (mlx5_l3t_set_entry(priv->mtr_idx_tbl, meter_id, &data)) 221044432018SLi Zhang goto error; 2211c3130c78SRongwei Liu } else if (!params->meter_enable && mlx5_flow_meter_disable(dev, meter_id, error)) { 2212c3130c78SRongwei Liu goto error; 221344432018SLi Zhang } 2214c3130c78SRongwei Liu fm->active_state = params->meter_enable; 221544432018SLi Zhang if (mtr_policy) 2216e12a0166STyler Retzlaff rte_atomic_fetch_add_explicit(&mtr_policy->ref_cnt, 1, rte_memory_order_relaxed); 221744432018SLi Zhang return 0; 221844432018SLi Zhang error: 221944432018SLi Zhang mlx5_flow_destroy_mtr_tbls(dev, fm); 222044432018SLi Zhang /* Free policer counters. */ 222144432018SLi Zhang if (fm->drop_cnt) 222244432018SLi Zhang mlx5_counter_free(dev, fm->drop_cnt); 222344432018SLi Zhang if (priv->sh->meter_aso_en) 222444432018SLi Zhang mlx5_flow_mtr_free(dev, mtr_idx); 222544432018SLi Zhang else 222644432018SLi Zhang mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], mtr_idx); 222744432018SLi Zhang return -rte_mtr_error_set(error, ENOTSUP, 222844432018SLi Zhang RTE_MTR_ERROR_TYPE_UNSPECIFIED, 222944432018SLi Zhang NULL, "Failed to create devx meter."); 22305df35867SLi Zhang } 22315df35867SLi Zhang 22327576c32eSGregory Etelson #if defined(HAVE_MLX5_HWS_SUPPORT) 223324865366SAlexander Kozyrev /** 223424865366SAlexander Kozyrev * Create meter rules. 223524865366SAlexander Kozyrev * 223624865366SAlexander Kozyrev * @param[in] dev 223724865366SAlexander Kozyrev * Pointer to Ethernet device. 223824865366SAlexander Kozyrev * @param[in] meter_id 223924865366SAlexander Kozyrev * Meter id. 224024865366SAlexander Kozyrev * @param[in] params 224124865366SAlexander Kozyrev * Pointer to rte meter parameters. 224224865366SAlexander Kozyrev * @param[in] shared 224324865366SAlexander Kozyrev * Meter shared with other flow or not. 224424865366SAlexander Kozyrev * @param[out] error 224524865366SAlexander Kozyrev * Pointer to rte meter error structure. 224624865366SAlexander Kozyrev * 224724865366SAlexander Kozyrev * @return 224824865366SAlexander Kozyrev * 0 on success, a negative errno value otherwise and rte_errno is set. 224924865366SAlexander Kozyrev */ 225024865366SAlexander Kozyrev static int 225124865366SAlexander Kozyrev mlx5_flow_meter_hws_create(struct rte_eth_dev *dev, uint32_t meter_id, 225224865366SAlexander Kozyrev struct rte_mtr_params *params, int shared, 225324865366SAlexander Kozyrev struct rte_mtr_error *error) 225424865366SAlexander Kozyrev { 225524865366SAlexander Kozyrev struct mlx5_priv *priv = dev->data->dev_private; 225624865366SAlexander Kozyrev struct mlx5_flow_meter_profile *profile; 225724865366SAlexander Kozyrev struct mlx5_flow_meter_info *fm; 225824865366SAlexander Kozyrev struct mlx5_flow_meter_policy *policy = NULL; 225924865366SAlexander Kozyrev struct mlx5_aso_mtr *aso_mtr; 22604359d9d1SGregory Etelson struct mlx5_hw_q_job *job; 226124865366SAlexander Kozyrev int ret; 226224865366SAlexander Kozyrev 2263*61a81061SGregory Etelson if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL)) 2264*61a81061SGregory Etelson return -rte_mtr_error_set(error, EINVAL, 2265*61a81061SGregory Etelson RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 2266*61a81061SGregory Etelson "non-template flow engine was not configured"); 226724865366SAlexander Kozyrev if (!priv->mtr_profile_arr || 226824865366SAlexander Kozyrev !priv->mtr_policy_arr || 226924865366SAlexander Kozyrev !priv->mtr_bulk.aso) 227024865366SAlexander Kozyrev return -rte_mtr_error_set(error, ENOTSUP, 227124865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 227224865366SAlexander Kozyrev "Meter bulk array is not allocated."); 227324865366SAlexander Kozyrev /* Meter profile must exist. */ 227424865366SAlexander Kozyrev profile = mlx5_flow_meter_profile_find(priv, params->meter_profile_id); 227524865366SAlexander Kozyrev if (!profile->initialized) 227624865366SAlexander Kozyrev return -rte_mtr_error_set(error, ENOENT, 227724865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 227824865366SAlexander Kozyrev NULL, "Meter profile id not valid."); 227924865366SAlexander Kozyrev /* Meter policy must exist. */ 228024865366SAlexander Kozyrev policy = mlx5_flow_meter_policy_find(dev, 228124865366SAlexander Kozyrev params->meter_policy_id, NULL); 228224865366SAlexander Kozyrev if (!policy->initialized) 228324865366SAlexander Kozyrev return -rte_mtr_error_set(error, ENOENT, 228424865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 228524865366SAlexander Kozyrev NULL, "Meter policy id not valid."); 228624865366SAlexander Kozyrev /* Meter ID must be valid. */ 228724865366SAlexander Kozyrev if (meter_id >= priv->mtr_config.nb_meters) 228824865366SAlexander Kozyrev return -rte_mtr_error_set(error, EINVAL, 228924865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_MTR_ID, 229024865366SAlexander Kozyrev NULL, "Meter id not valid."); 229124865366SAlexander Kozyrev /* Find ASO object. */ 229224865366SAlexander Kozyrev aso_mtr = mlx5_aso_meter_by_idx(priv, meter_id); 229324865366SAlexander Kozyrev fm = &aso_mtr->fm; 229424865366SAlexander Kozyrev if (fm->initialized) 229524865366SAlexander Kozyrev return -rte_mtr_error_set(error, ENOENT, 229624865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_MTR_ID, 229724865366SAlexander Kozyrev NULL, "Meter object already exists."); 229824865366SAlexander Kozyrev /* Fill the flow meter parameters. */ 229924865366SAlexander Kozyrev fm->meter_id = meter_id; 230024865366SAlexander Kozyrev fm->policy_id = params->meter_policy_id; 230124865366SAlexander Kozyrev fm->profile = profile; 230224865366SAlexander Kozyrev fm->meter_offset = meter_id; 230324865366SAlexander Kozyrev fm->group = policy->group; 230424865366SAlexander Kozyrev /* Add to the flow meter list. */ 230524865366SAlexander Kozyrev fm->active_state = 1; /* Config meter starts as active. */ 230624865366SAlexander Kozyrev fm->is_enable = params->meter_enable; 230724865366SAlexander Kozyrev fm->shared = !!shared; 230824865366SAlexander Kozyrev fm->initialized = 1; 230924865366SAlexander Kozyrev /* Update ASO flow meter by wqe. */ 23104359d9d1SGregory Etelson job = mlx5_flow_action_job_init(priv, MLX5_HW_INV_QUEUE, NULL, NULL, 23114359d9d1SGregory Etelson NULL, MLX5_HW_Q_JOB_TYPE_CREATE, NULL); 23124359d9d1SGregory Etelson if (!job) 23134359d9d1SGregory Etelson return -rte_mtr_error_set(error, ENOMEM, 23144359d9d1SGregory Etelson RTE_MTR_ERROR_TYPE_MTR_ID, 23154359d9d1SGregory Etelson NULL, "No job context."); 23164359d9d1SGregory Etelson ret = mlx5_aso_meter_update_by_wqe(priv, MLX5_HW_INV_QUEUE, aso_mtr, 23174359d9d1SGregory Etelson &priv->mtr_bulk, job, true); 23184359d9d1SGregory Etelson if (ret) { 2319dc7faa13SGregory Etelson flow_hw_job_put(priv, job, CTRL_QUEUE_ID(priv)); 232024865366SAlexander Kozyrev return -rte_mtr_error_set(error, ENOTSUP, 232124865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_UNSPECIFIED, 232224865366SAlexander Kozyrev NULL, "Failed to create devx meter."); 23234359d9d1SGregory Etelson } 232424865366SAlexander Kozyrev fm->active_state = params->meter_enable; 2325e12a0166STyler Retzlaff rte_atomic_fetch_add_explicit(&fm->profile->ref_cnt, 1, rte_memory_order_relaxed); 2326e12a0166STyler Retzlaff rte_atomic_fetch_add_explicit(&policy->ref_cnt, 1, rte_memory_order_relaxed); 232724865366SAlexander Kozyrev return 0; 232824865366SAlexander Kozyrev } 23297576c32eSGregory Etelson #endif 233024865366SAlexander Kozyrev 2331e6100c7bSLi Zhang static int 2332e6100c7bSLi Zhang mlx5_flow_meter_params_flush(struct rte_eth_dev *dev, 2333e6100c7bSLi Zhang struct mlx5_flow_meter_info *fm, 2334e6100c7bSLi Zhang uint32_t mtr_idx) 2335e6100c7bSLi Zhang { 2336e6100c7bSLi Zhang struct mlx5_priv *priv = dev->data->dev_private; 2337e6100c7bSLi Zhang struct mlx5_legacy_flow_meters *fms = &priv->flow_meters; 2338e6100c7bSLi Zhang struct mlx5_flow_meter_profile *fmp; 2339e6100c7bSLi Zhang struct mlx5_legacy_flow_meter *legacy_fm = NULL; 234044432018SLi Zhang struct mlx5_flow_meter_policy *mtr_policy; 2341e6100c7bSLi Zhang 2342e6100c7bSLi Zhang /* Meter object must not have any owner. */ 2343e6100c7bSLi Zhang MLX5_ASSERT(!fm->ref_cnt); 2344e6100c7bSLi Zhang /* Get meter profile. */ 2345e6100c7bSLi Zhang fmp = fm->profile; 2346e6100c7bSLi Zhang if (fmp == NULL) 2347e6100c7bSLi Zhang return -1; 2348e6100c7bSLi Zhang /* Update dependencies. */ 2349e12a0166STyler Retzlaff rte_atomic_fetch_sub_explicit(&fmp->ref_cnt, 1, rte_memory_order_relaxed); 235044432018SLi Zhang fm->profile = NULL; 2351e6100c7bSLi Zhang /* Remove from list. */ 2352e6100c7bSLi Zhang if (!priv->sh->meter_aso_en) { 235344432018SLi Zhang legacy_fm = container_of(fm, 235444432018SLi Zhang struct mlx5_legacy_flow_meter, fm); 2355e6100c7bSLi Zhang TAILQ_REMOVE(fms, legacy_fm, next); 2356e6100c7bSLi Zhang } 23575f0d54f3SLi Zhang /* Free drop counters. */ 23585f0d54f3SLi Zhang if (fm->drop_cnt) 23595f0d54f3SLi Zhang mlx5_counter_free(dev, fm->drop_cnt); 2360e6100c7bSLi Zhang /* Free meter flow table. */ 236144432018SLi Zhang if (fm->flow_ipool) { 2362e6100c7bSLi Zhang mlx5_ipool_destroy(fm->flow_ipool); 236344432018SLi Zhang fm->flow_ipool = 0; 236444432018SLi Zhang } 236544432018SLi Zhang mlx5_flow_destroy_mtr_tbls(dev, fm); 236644432018SLi Zhang if (fm->def_policy) 2367e12a0166STyler Retzlaff rte_atomic_fetch_sub_explicit(&priv->sh->mtrmng->def_policy_ref_cnt, 2368e12a0166STyler Retzlaff 1, rte_memory_order_relaxed); 236944432018SLi Zhang if (priv->sh->meter_aso_en) { 237044432018SLi Zhang if (!fm->def_policy) { 237144432018SLi Zhang mtr_policy = mlx5_flow_meter_policy_find(dev, 237244432018SLi Zhang fm->policy_id, NULL); 237344432018SLi Zhang if (mtr_policy) 2374e12a0166STyler Retzlaff rte_atomic_fetch_sub_explicit(&mtr_policy->ref_cnt, 2375e12a0166STyler Retzlaff 1, rte_memory_order_relaxed); 237644432018SLi Zhang fm->policy_id = 0; 237744432018SLi Zhang } 237844432018SLi Zhang fm->def_policy = 0; 237944432018SLi Zhang if (mlx5_l3t_clear_entry(priv->mtr_idx_tbl, fm->meter_id)) 238044432018SLi Zhang return -1; 2381e6100c7bSLi Zhang mlx5_flow_mtr_free(dev, mtr_idx); 238244432018SLi Zhang } else { 2383e6100c7bSLi Zhang mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], 2384e6100c7bSLi Zhang legacy_fm->idx); 238544432018SLi Zhang } 2386e6100c7bSLi Zhang return 0; 2387e6100c7bSLi Zhang } 2388e6100c7bSLi Zhang 23893f373f35SSuanming Mou /** 23903f373f35SSuanming Mou * Destroy meter rules. 23913f373f35SSuanming Mou * 23923f373f35SSuanming Mou * @param[in] dev 23933f373f35SSuanming Mou * Pointer to Ethernet device. 23943f373f35SSuanming Mou * @param[in] meter_id 23953f373f35SSuanming Mou * Meter id. 23963f373f35SSuanming Mou * @param[out] error 23973f373f35SSuanming Mou * Pointer to rte meter error structure. 23983f373f35SSuanming Mou * 23993f373f35SSuanming Mou * @return 24003f373f35SSuanming Mou * 0 on success, a negative errno value otherwise and rte_errno is set. 24013f373f35SSuanming Mou */ 24023f373f35SSuanming Mou static int 24033f373f35SSuanming Mou mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id, 24043f373f35SSuanming Mou struct rte_mtr_error *error) 24053f373f35SSuanming Mou { 24063f373f35SSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 2407e6100c7bSLi Zhang struct mlx5_flow_meter_info *fm; 2408e6100c7bSLi Zhang uint32_t mtr_idx = 0; 24093f373f35SSuanming Mou 24103f373f35SSuanming Mou if (!priv->mtr_en) 24113f373f35SSuanming Mou return -rte_mtr_error_set(error, ENOTSUP, 241244432018SLi Zhang RTE_MTR_ERROR_TYPE_UNSPECIFIED, 241344432018SLi Zhang NULL, 24143efac808SAli Alnubani "Meter is not supported"); 24153f373f35SSuanming Mou /* Meter object must exist. */ 2416e6100c7bSLi Zhang fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx); 24173f373f35SSuanming Mou if (fm == NULL) 24183f373f35SSuanming Mou return -rte_mtr_error_set(error, ENOENT, 24193f373f35SSuanming Mou RTE_MTR_ERROR_TYPE_MTR_ID, 242044432018SLi Zhang NULL, 242144432018SLi Zhang "Meter object id not valid."); 24223f373f35SSuanming Mou /* Meter object must not have any owner. */ 24233f373f35SSuanming Mou if (fm->ref_cnt > 0) 24243f373f35SSuanming Mou return -rte_mtr_error_set(error, EBUSY, 24253f373f35SSuanming Mou RTE_MTR_ERROR_TYPE_UNSPECIFIED, 242644432018SLi Zhang NULL, 242744432018SLi Zhang "Meter object is being used."); 2428e6100c7bSLi Zhang /* Destroy the meter profile. */ 24295f0d54f3SLi Zhang if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx)) 2430e6100c7bSLi Zhang return -rte_mtr_error_set(error, EINVAL, 2431e6100c7bSLi Zhang RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 243244432018SLi Zhang NULL, 243344432018SLi Zhang "MTR object meter profile invalid."); 24343f373f35SSuanming Mou return 0; 24353f373f35SSuanming Mou } 24363f373f35SSuanming Mou 243733e01809SSuanming Mou /** 243824865366SAlexander Kozyrev * Destroy meter rules. 243924865366SAlexander Kozyrev * 244024865366SAlexander Kozyrev * @param[in] dev 244124865366SAlexander Kozyrev * Pointer to Ethernet device. 244224865366SAlexander Kozyrev * @param[in] meter_id 244324865366SAlexander Kozyrev * Meter id. 244424865366SAlexander Kozyrev * @param[out] error 244524865366SAlexander Kozyrev * Pointer to rte meter error structure. 244624865366SAlexander Kozyrev * 244724865366SAlexander Kozyrev * @return 244824865366SAlexander Kozyrev * 0 on success, a negative errno value otherwise and rte_errno is set. 244924865366SAlexander Kozyrev */ 245024865366SAlexander Kozyrev static int 245124865366SAlexander Kozyrev mlx5_flow_meter_hws_destroy(struct rte_eth_dev *dev, uint32_t meter_id, 245224865366SAlexander Kozyrev struct rte_mtr_error *error) 245324865366SAlexander Kozyrev { 245424865366SAlexander Kozyrev struct mlx5_priv *priv = dev->data->dev_private; 245524865366SAlexander Kozyrev struct mlx5_aso_mtr *aso_mtr; 245624865366SAlexander Kozyrev struct mlx5_flow_meter_info *fm; 245724865366SAlexander Kozyrev struct mlx5_flow_meter_policy *policy; 245824865366SAlexander Kozyrev 245924865366SAlexander Kozyrev if (!priv->mtr_profile_arr || 246024865366SAlexander Kozyrev !priv->mtr_policy_arr || 246124865366SAlexander Kozyrev !priv->mtr_bulk.aso) 246224865366SAlexander Kozyrev return -rte_mtr_error_set(error, ENOTSUP, 246324865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, 246424865366SAlexander Kozyrev "Meter bulk array is not allocated."); 246524865366SAlexander Kozyrev /* Find ASO object. */ 246624865366SAlexander Kozyrev aso_mtr = mlx5_aso_meter_by_idx(priv, meter_id); 246724865366SAlexander Kozyrev fm = &aso_mtr->fm; 246824865366SAlexander Kozyrev if (!fm->initialized) 246924865366SAlexander Kozyrev return -rte_mtr_error_set(error, ENOENT, 247024865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_MTR_ID, 247124865366SAlexander Kozyrev NULL, "Meter object id not valid."); 247224865366SAlexander Kozyrev /* Meter object must not have any owner. */ 247324865366SAlexander Kozyrev if (fm->ref_cnt > 0) 247424865366SAlexander Kozyrev return -rte_mtr_error_set(error, EBUSY, 247524865366SAlexander Kozyrev RTE_MTR_ERROR_TYPE_UNSPECIFIED, 247624865366SAlexander Kozyrev NULL, "Meter object is being used."); 247724865366SAlexander Kozyrev /* Destroy the meter profile. */ 2478e12a0166STyler Retzlaff rte_atomic_fetch_sub_explicit(&fm->profile->ref_cnt, 2479e12a0166STyler Retzlaff 1, rte_memory_order_relaxed); 248024865366SAlexander Kozyrev /* Destroy the meter policy. */ 248124865366SAlexander Kozyrev policy = mlx5_flow_meter_policy_find(dev, 248224865366SAlexander Kozyrev fm->policy_id, NULL); 2483e12a0166STyler Retzlaff rte_atomic_fetch_sub_explicit(&policy->ref_cnt, 2484e12a0166STyler Retzlaff 1, rte_memory_order_relaxed); 248524865366SAlexander Kozyrev memset(fm, 0, sizeof(struct mlx5_flow_meter_info)); 248624865366SAlexander Kozyrev return 0; 248724865366SAlexander Kozyrev } 248824865366SAlexander Kozyrev 248924865366SAlexander Kozyrev /** 249033e01809SSuanming Mou * Modify meter state. 249133e01809SSuanming Mou * 249233e01809SSuanming Mou * @param[in] priv 249333e01809SSuanming Mou * Pointer to mlx5 private data structure. 249433e01809SSuanming Mou * @param[in] fm 249533e01809SSuanming Mou * Pointer to flow meter. 249633e01809SSuanming Mou * @param[in] new_state 249733e01809SSuanming Mou * New state to update. 249833e01809SSuanming Mou * @param[out] error 249933e01809SSuanming Mou * Pointer to rte meter error structure. 250033e01809SSuanming Mou * 250133e01809SSuanming Mou * @return 250233e01809SSuanming Mou * 0 on success, a negative errno value otherwise and rte_errno is set. 250333e01809SSuanming Mou */ 250433e01809SSuanming Mou static int 250533e01809SSuanming Mou mlx5_flow_meter_modify_state(struct mlx5_priv *priv, 2506e6100c7bSLi Zhang struct mlx5_flow_meter_info *fm, 250733e01809SSuanming Mou uint32_t new_state, 250833e01809SSuanming Mou struct rte_mtr_error *error) 250933e01809SSuanming Mou { 251033e01809SSuanming Mou static const struct mlx5_flow_meter_srtcm_rfc2697_prm srtcm = { 2511e6100c7bSLi Zhang .cbs_cir = RTE_BE32(MLX5_IFC_FLOW_METER_DISABLE_CBS_CIR_VAL), 2512e6100c7bSLi Zhang .ebs_eir = 0, 251333e01809SSuanming Mou }; 251433e01809SSuanming Mou uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS | 251533e01809SSuanming Mou MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR; 251633e01809SSuanming Mou int ret; 251733e01809SSuanming Mou 251833e01809SSuanming Mou if (new_state == MLX5_FLOW_METER_DISABLE) 2519e93c58daSLi Zhang ret = mlx5_flow_meter_action_modify(priv, fm, 2520e93c58daSLi Zhang &srtcm, modify_bits, 0, 0); 252133e01809SSuanming Mou else 252233e01809SSuanming Mou ret = mlx5_flow_meter_action_modify(priv, fm, 252333e01809SSuanming Mou &fm->profile->srtcm_prm, 2524e93c58daSLi Zhang modify_bits, 0, 1); 252533e01809SSuanming Mou if (ret) 252633e01809SSuanming Mou return -rte_mtr_error_set(error, -ret, 252733e01809SSuanming Mou RTE_MTR_ERROR_TYPE_MTR_PARAMS, 252833e01809SSuanming Mou NULL, 252933e01809SSuanming Mou new_state ? 253033e01809SSuanming Mou "Failed to enable meter." : 253133e01809SSuanming Mou "Failed to disable meter."); 253233e01809SSuanming Mou return 0; 253333e01809SSuanming Mou } 253433e01809SSuanming Mou 253533e01809SSuanming Mou /** 253633e01809SSuanming Mou * Callback to enable flow meter. 253733e01809SSuanming Mou * 253833e01809SSuanming Mou * @param[in] dev 253933e01809SSuanming Mou * Pointer to Ethernet device. 254033e01809SSuanming Mou * @param[in] meter_id 254133e01809SSuanming Mou * Meter id. 254233e01809SSuanming Mou * @param[out] error 254333e01809SSuanming Mou * Pointer to rte meter error structure. 254433e01809SSuanming Mou * 254533e01809SSuanming Mou * @return 254633e01809SSuanming Mou * 0 on success, a negative errno value otherwise and rte_errno is set. 254733e01809SSuanming Mou */ 254833e01809SSuanming Mou static int 254933e01809SSuanming Mou mlx5_flow_meter_enable(struct rte_eth_dev *dev, 255033e01809SSuanming Mou uint32_t meter_id, 255133e01809SSuanming Mou struct rte_mtr_error *error) 255233e01809SSuanming Mou { 255333e01809SSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 2554e6100c7bSLi Zhang struct mlx5_flow_meter_info *fm; 255533e01809SSuanming Mou int ret; 255633e01809SSuanming Mou 2557*61a81061SGregory Etelson if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL)) 2558*61a81061SGregory Etelson return -rte_mtr_error_set(error, EINVAL, 2559*61a81061SGregory Etelson RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 2560*61a81061SGregory Etelson "non-template flow engine was not configured"); 256133e01809SSuanming Mou if (!priv->mtr_en) 256233e01809SSuanming Mou return -rte_mtr_error_set(error, ENOTSUP, 256333e01809SSuanming Mou RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 25643efac808SAli Alnubani "Meter is not supported"); 256533e01809SSuanming Mou /* Meter object must exist. */ 2566e6100c7bSLi Zhang fm = mlx5_flow_meter_find(priv, meter_id, NULL); 256733e01809SSuanming Mou if (fm == NULL) 256833e01809SSuanming Mou return -rte_mtr_error_set(error, ENOENT, 256933e01809SSuanming Mou RTE_MTR_ERROR_TYPE_MTR_ID, 257033e01809SSuanming Mou NULL, "Meter not found."); 257133e01809SSuanming Mou if (fm->active_state == MLX5_FLOW_METER_ENABLE) 257233e01809SSuanming Mou return 0; 257333e01809SSuanming Mou ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_ENABLE, 257433e01809SSuanming Mou error); 257533e01809SSuanming Mou if (!ret) 257633e01809SSuanming Mou fm->active_state = MLX5_FLOW_METER_ENABLE; 257733e01809SSuanming Mou return ret; 257833e01809SSuanming Mou } 257933e01809SSuanming Mou 258033e01809SSuanming Mou /** 258133e01809SSuanming Mou * Callback to disable flow meter. 258233e01809SSuanming Mou * 258333e01809SSuanming Mou * @param[in] dev 258433e01809SSuanming Mou * Pointer to Ethernet device. 258533e01809SSuanming Mou * @param[in] meter_id 258633e01809SSuanming Mou * Meter id. 258733e01809SSuanming Mou * @param[out] error 258833e01809SSuanming Mou * Pointer to rte meter error structure. 258933e01809SSuanming Mou * 259033e01809SSuanming Mou * @return 259133e01809SSuanming Mou * 0 on success, a negative errno value otherwise and rte_errno is set. 259233e01809SSuanming Mou */ 259333e01809SSuanming Mou static int 259433e01809SSuanming Mou mlx5_flow_meter_disable(struct rte_eth_dev *dev, 259533e01809SSuanming Mou uint32_t meter_id, 259633e01809SSuanming Mou struct rte_mtr_error *error) 259733e01809SSuanming Mou { 259833e01809SSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 2599e6100c7bSLi Zhang struct mlx5_flow_meter_info *fm; 260033e01809SSuanming Mou int ret; 260133e01809SSuanming Mou 260233e01809SSuanming Mou if (!priv->mtr_en) 260333e01809SSuanming Mou return -rte_mtr_error_set(error, ENOTSUP, 260433e01809SSuanming Mou RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 26053efac808SAli Alnubani "Meter is not supported"); 260633e01809SSuanming Mou /* Meter object must exist. */ 2607e6100c7bSLi Zhang fm = mlx5_flow_meter_find(priv, meter_id, NULL); 260833e01809SSuanming Mou if (fm == NULL) 260933e01809SSuanming Mou return -rte_mtr_error_set(error, ENOENT, 261033e01809SSuanming Mou RTE_MTR_ERROR_TYPE_MTR_ID, 261133e01809SSuanming Mou NULL, "Meter not found."); 261233e01809SSuanming Mou if (fm->active_state == MLX5_FLOW_METER_DISABLE) 261333e01809SSuanming Mou return 0; 261433e01809SSuanming Mou ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_DISABLE, 261533e01809SSuanming Mou error); 261633e01809SSuanming Mou if (!ret) 261733e01809SSuanming Mou fm->active_state = MLX5_FLOW_METER_DISABLE; 261833e01809SSuanming Mou return ret; 261933e01809SSuanming Mou } 262033e01809SSuanming Mou 262163ffeb2fSSuanming Mou /** 262263ffeb2fSSuanming Mou * Callback to update meter profile. 262363ffeb2fSSuanming Mou * 262463ffeb2fSSuanming Mou * @param[in] dev 262563ffeb2fSSuanming Mou * Pointer to Ethernet device. 262663ffeb2fSSuanming Mou * @param[in] meter_id 262763ffeb2fSSuanming Mou * Meter id. 262863ffeb2fSSuanming Mou * @param[in] meter_profile_id 262963ffeb2fSSuanming Mou * To be updated meter profile id. 263063ffeb2fSSuanming Mou * @param[out] error 263163ffeb2fSSuanming Mou * Pointer to rte meter error structure. 263263ffeb2fSSuanming Mou * 263363ffeb2fSSuanming Mou * @return 263463ffeb2fSSuanming Mou * 0 on success, a negative errno value otherwise and rte_errno is set. 263563ffeb2fSSuanming Mou */ 263663ffeb2fSSuanming Mou static int 263763ffeb2fSSuanming Mou mlx5_flow_meter_profile_update(struct rte_eth_dev *dev, 263863ffeb2fSSuanming Mou uint32_t meter_id, 263963ffeb2fSSuanming Mou uint32_t meter_profile_id, 264063ffeb2fSSuanming Mou struct rte_mtr_error *error) 264163ffeb2fSSuanming Mou { 264263ffeb2fSSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 264363ffeb2fSSuanming Mou struct mlx5_flow_meter_profile *fmp; 264463ffeb2fSSuanming Mou struct mlx5_flow_meter_profile *old_fmp; 2645e6100c7bSLi Zhang struct mlx5_flow_meter_info *fm; 264663ffeb2fSSuanming Mou uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS | 264763ffeb2fSSuanming Mou MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR; 264863ffeb2fSSuanming Mou int ret; 264963ffeb2fSSuanming Mou 2650*61a81061SGregory Etelson if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL)) 2651*61a81061SGregory Etelson return -rte_mtr_error_set(error, EINVAL, 2652*61a81061SGregory Etelson RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 2653*61a81061SGregory Etelson "non-template flow engine was not configured"); 265463ffeb2fSSuanming Mou if (!priv->mtr_en) 265563ffeb2fSSuanming Mou return -rte_mtr_error_set(error, ENOTSUP, 265663ffeb2fSSuanming Mou RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 26573efac808SAli Alnubani "Meter is not supported"); 265863ffeb2fSSuanming Mou /* Meter profile must exist. */ 265963ffeb2fSSuanming Mou fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id); 266063ffeb2fSSuanming Mou if (fmp == NULL) 266163ffeb2fSSuanming Mou return -rte_mtr_error_set(error, ENOENT, 266263ffeb2fSSuanming Mou RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 266363ffeb2fSSuanming Mou NULL, "Meter profile not found."); 266463ffeb2fSSuanming Mou /* Meter object must exist. */ 2665e6100c7bSLi Zhang fm = mlx5_flow_meter_find(priv, meter_id, NULL); 266663ffeb2fSSuanming Mou if (fm == NULL) 266763ffeb2fSSuanming Mou return -rte_mtr_error_set(error, ENOENT, 266863ffeb2fSSuanming Mou RTE_MTR_ERROR_TYPE_MTR_ID, 266963ffeb2fSSuanming Mou NULL, "Meter not found."); 267063ffeb2fSSuanming Mou /* MTR object already set to meter profile id. */ 267163ffeb2fSSuanming Mou old_fmp = fm->profile; 267263ffeb2fSSuanming Mou if (fmp == old_fmp) 267363ffeb2fSSuanming Mou return 0; 267463ffeb2fSSuanming Mou /* Update the profile. */ 267563ffeb2fSSuanming Mou fm->profile = fmp; 267663ffeb2fSSuanming Mou /* Update meter params in HW (if not disabled). */ 267763ffeb2fSSuanming Mou if (fm->active_state == MLX5_FLOW_METER_DISABLE) 26789b7fcf39SShun Hao goto dec_ref_cnt; 267963ffeb2fSSuanming Mou ret = mlx5_flow_meter_action_modify(priv, fm, &fm->profile->srtcm_prm, 2680e93c58daSLi Zhang modify_bits, fm->active_state, 1); 268163ffeb2fSSuanming Mou if (ret) { 268263ffeb2fSSuanming Mou fm->profile = old_fmp; 268363ffeb2fSSuanming Mou return -rte_mtr_error_set(error, -ret, 268463ffeb2fSSuanming Mou RTE_MTR_ERROR_TYPE_MTR_PARAMS, 268563ffeb2fSSuanming Mou NULL, "Failed to update meter" 26867be78d02SJosh Soref " parameters in hardware."); 268763ffeb2fSSuanming Mou } 26889b7fcf39SShun Hao dec_ref_cnt: 268963ffeb2fSSuanming Mou old_fmp->ref_cnt--; 269063ffeb2fSSuanming Mou fmp->ref_cnt++; 269163ffeb2fSSuanming Mou return 0; 269263ffeb2fSSuanming Mou } 269363ffeb2fSSuanming Mou 2694fab7f7d4SSuanming Mou /** 2695fab7f7d4SSuanming Mou * Callback to update meter stats mask. 2696fab7f7d4SSuanming Mou * 2697fab7f7d4SSuanming Mou * @param[in] dev 2698fab7f7d4SSuanming Mou * Pointer to Ethernet device. 2699fab7f7d4SSuanming Mou * @param[in] meter_id 2700fab7f7d4SSuanming Mou * Meter id. 2701fab7f7d4SSuanming Mou * @param[in] stats_mask 2702fab7f7d4SSuanming Mou * To be updated stats_mask. 2703fab7f7d4SSuanming Mou * @param[out] error 2704fab7f7d4SSuanming Mou * Pointer to rte meter error structure. 2705fab7f7d4SSuanming Mou * 2706fab7f7d4SSuanming Mou * @return 2707fab7f7d4SSuanming Mou * 0 on success, a negative errno value otherwise and rte_errno is set. 2708fab7f7d4SSuanming Mou */ 2709fab7f7d4SSuanming Mou static int 2710fab7f7d4SSuanming Mou mlx5_flow_meter_stats_update(struct rte_eth_dev *dev, 2711fab7f7d4SSuanming Mou uint32_t meter_id, 2712fab7f7d4SSuanming Mou uint64_t stats_mask, 2713fab7f7d4SSuanming Mou struct rte_mtr_error *error) 2714fab7f7d4SSuanming Mou { 2715fab7f7d4SSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 2716e6100c7bSLi Zhang struct mlx5_flow_meter_info *fm; 2717fab7f7d4SSuanming Mou 2718fab7f7d4SSuanming Mou if (!priv->mtr_en) 2719fab7f7d4SSuanming Mou return -rte_mtr_error_set(error, ENOTSUP, 2720fab7f7d4SSuanming Mou RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 27213efac808SAli Alnubani "Meter is not supported"); 2722fab7f7d4SSuanming Mou /* Meter object must exist. */ 2723e6100c7bSLi Zhang fm = mlx5_flow_meter_find(priv, meter_id, NULL); 2724fab7f7d4SSuanming Mou if (fm == NULL) 2725fab7f7d4SSuanming Mou return -rte_mtr_error_set(error, ENOENT, 2726fab7f7d4SSuanming Mou RTE_MTR_ERROR_TYPE_MTR_ID, 2727fab7f7d4SSuanming Mou NULL, "Meter object id not valid."); 272844432018SLi Zhang if (mlx5_flow_meter_stats_enable_update(dev, fm, stats_mask)) 272944432018SLi Zhang return -rte_mtr_error_set(error, ENOENT, 273044432018SLi Zhang RTE_MTR_ERROR_TYPE_MTR_ID, 273144432018SLi Zhang NULL, "Fail to allocate " 273244432018SLi Zhang "counter for meter."); 2733fab7f7d4SSuanming Mou return 0; 2734fab7f7d4SSuanming Mou } 2735fab7f7d4SSuanming Mou 2736fab7f7d4SSuanming Mou /** 2737fab7f7d4SSuanming Mou * Callback to read meter statistics. 2738fab7f7d4SSuanming Mou * 2739fab7f7d4SSuanming Mou * @param[in] dev 2740fab7f7d4SSuanming Mou * Pointer to Ethernet device. 2741fab7f7d4SSuanming Mou * @param[in] meter_id 2742fab7f7d4SSuanming Mou * Meter id. 2743fab7f7d4SSuanming Mou * @param[out] stats 2744fab7f7d4SSuanming Mou * Pointer to store the statistics. 2745fab7f7d4SSuanming Mou * @param[out] stats_mask 2746fab7f7d4SSuanming Mou * Pointer to store the stats_mask. 2747fab7f7d4SSuanming Mou * @param[in] clear 2748fab7f7d4SSuanming Mou * Statistic to be cleared after read or not. 2749fab7f7d4SSuanming Mou * @param[out] error 2750fab7f7d4SSuanming Mou * Pointer to rte meter error structure. 2751fab7f7d4SSuanming Mou * 2752fab7f7d4SSuanming Mou * @return 2753fab7f7d4SSuanming Mou * 0 on success, a negative errno value otherwise and rte_errno is set. 2754fab7f7d4SSuanming Mou */ 2755fab7f7d4SSuanming Mou static int 2756fab7f7d4SSuanming Mou mlx5_flow_meter_stats_read(struct rte_eth_dev *dev, 2757fab7f7d4SSuanming Mou uint32_t meter_id, 2758fab7f7d4SSuanming Mou struct rte_mtr_stats *stats, 2759fab7f7d4SSuanming Mou uint64_t *stats_mask, 2760fab7f7d4SSuanming Mou int clear, 2761fab7f7d4SSuanming Mou struct rte_mtr_error *error) 2762fab7f7d4SSuanming Mou { 2763fab7f7d4SSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 2764e6100c7bSLi Zhang struct mlx5_flow_meter_info *fm; 2765fab7f7d4SSuanming Mou uint64_t pkts; 2766fab7f7d4SSuanming Mou uint64_t bytes; 2767fab7f7d4SSuanming Mou int ret = 0; 2768fab7f7d4SSuanming Mou 2769fab7f7d4SSuanming Mou if (!priv->mtr_en) 2770fab7f7d4SSuanming Mou return -rte_mtr_error_set(error, ENOTSUP, 2771fab7f7d4SSuanming Mou RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 27723efac808SAli Alnubani "Meter is not supported"); 2773fab7f7d4SSuanming Mou /* Meter object must exist. */ 2774e6100c7bSLi Zhang fm = mlx5_flow_meter_find(priv, meter_id, NULL); 2775fab7f7d4SSuanming Mou if (fm == NULL) 2776fab7f7d4SSuanming Mou return -rte_mtr_error_set(error, ENOENT, 2777fab7f7d4SSuanming Mou RTE_MTR_ERROR_TYPE_MTR_ID, 2778fab7f7d4SSuanming Mou NULL, "Meter object id not valid."); 27795df35867SLi Zhang *stats_mask = 0; 27805df35867SLi Zhang if (fm->bytes_dropped) 27815df35867SLi Zhang *stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED; 27825df35867SLi Zhang if (fm->pkts_dropped) 27835df35867SLi Zhang *stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED; 27845df35867SLi Zhang memset(stats, 0, sizeof(*stats)); 27855f0d54f3SLi Zhang if (fm->drop_cnt) { 27865f0d54f3SLi Zhang ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts, 27879b57df55SHaifei Luo &bytes, NULL); 2788fab7f7d4SSuanming Mou if (ret) 2789fab7f7d4SSuanming Mou goto error; 2790fab7f7d4SSuanming Mou /* If need to read the packets, set it. */ 27915df35867SLi Zhang if (fm->pkts_dropped) 2792fab7f7d4SSuanming Mou stats->n_pkts_dropped = pkts; 2793fab7f7d4SSuanming Mou /* If need to read the bytes, set it. */ 27945df35867SLi Zhang if (fm->bytes_dropped) 2795fab7f7d4SSuanming Mou stats->n_bytes_dropped = bytes; 2796fab7f7d4SSuanming Mou } 2797fab7f7d4SSuanming Mou return 0; 2798fab7f7d4SSuanming Mou error: 2799fab7f7d4SSuanming Mou return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL, 28005f0d54f3SLi Zhang "Failed to read meter drop counters."); 2801fab7f7d4SSuanming Mou } 2802fab7f7d4SSuanming Mou 2803d740eb50SSuanming Mou static const struct rte_mtr_ops mlx5_flow_mtr_ops = { 28046bc327b9SSuanming Mou .capabilities_get = mlx5_flow_mtr_cap_get, 28053bd26b23SSuanming Mou .meter_profile_add = mlx5_flow_meter_profile_add, 28063bd26b23SSuanming Mou .meter_profile_delete = mlx5_flow_meter_profile_delete, 280748fbb0e9SAlexander Kozyrev .meter_profile_get = mlx5_flow_meter_profile_get, 2808afb4aa4fSLi Zhang .meter_policy_validate = mlx5_flow_meter_policy_validate, 2809afb4aa4fSLi Zhang .meter_policy_add = mlx5_flow_meter_policy_add, 2810afb4aa4fSLi Zhang .meter_policy_delete = mlx5_flow_meter_policy_delete, 281148fbb0e9SAlexander Kozyrev .meter_policy_get = mlx5_flow_meter_policy_get, 281244432018SLi Zhang .create = mlx5_flow_meter_create, 28133f373f35SSuanming Mou .destroy = mlx5_flow_meter_destroy, 281433e01809SSuanming Mou .meter_enable = mlx5_flow_meter_enable, 281533e01809SSuanming Mou .meter_disable = mlx5_flow_meter_disable, 281663ffeb2fSSuanming Mou .meter_profile_update = mlx5_flow_meter_profile_update, 2817d740eb50SSuanming Mou .meter_dscp_table_update = NULL, 2818fab7f7d4SSuanming Mou .stats_update = mlx5_flow_meter_stats_update, 2819fab7f7d4SSuanming Mou .stats_read = mlx5_flow_meter_stats_read, 2820d740eb50SSuanming Mou }; 2821d740eb50SSuanming Mou 28227576c32eSGregory Etelson #if defined(HAVE_MLX5_HWS_SUPPORT) 282324865366SAlexander Kozyrev static const struct rte_mtr_ops mlx5_flow_mtr_hws_ops = { 282424865366SAlexander Kozyrev .capabilities_get = mlx5_flow_mtr_cap_get, 282524865366SAlexander Kozyrev .meter_profile_add = mlx5_flow_meter_profile_hws_add, 282624865366SAlexander Kozyrev .meter_profile_delete = mlx5_flow_meter_profile_hws_delete, 282748fbb0e9SAlexander Kozyrev .meter_profile_get = mlx5_flow_meter_profile_get, 282824865366SAlexander Kozyrev .meter_policy_validate = mlx5_flow_meter_policy_hws_validate, 282924865366SAlexander Kozyrev .meter_policy_add = mlx5_flow_meter_policy_hws_add, 283024865366SAlexander Kozyrev .meter_policy_delete = mlx5_flow_meter_policy_hws_delete, 283148fbb0e9SAlexander Kozyrev .meter_policy_get = mlx5_flow_meter_policy_get, 283224865366SAlexander Kozyrev .create = mlx5_flow_meter_hws_create, 283324865366SAlexander Kozyrev .destroy = mlx5_flow_meter_hws_destroy, 283424865366SAlexander Kozyrev .meter_enable = mlx5_flow_meter_enable, 283524865366SAlexander Kozyrev .meter_disable = mlx5_flow_meter_disable, 283624865366SAlexander Kozyrev .meter_profile_update = mlx5_flow_meter_profile_update, 283724865366SAlexander Kozyrev .meter_dscp_table_update = NULL, 283824865366SAlexander Kozyrev .stats_update = NULL, 283924865366SAlexander Kozyrev .stats_read = NULL, 284024865366SAlexander Kozyrev }; 28417576c32eSGregory Etelson #endif 284224865366SAlexander Kozyrev 2843d740eb50SSuanming Mou /** 2844d740eb50SSuanming Mou * Get meter operations. 2845d740eb50SSuanming Mou * 2846d740eb50SSuanming Mou * @param dev 2847d740eb50SSuanming Mou * Pointer to Ethernet device structure. 2848d740eb50SSuanming Mou * @param arg 2849d740eb50SSuanming Mou * Pointer to set the mtr operations. 2850d740eb50SSuanming Mou * 2851d740eb50SSuanming Mou * @return 2852d740eb50SSuanming Mou * Always 0. 2853d740eb50SSuanming Mou */ 2854d740eb50SSuanming Mou int 2855d740eb50SSuanming Mou mlx5_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg) 2856d740eb50SSuanming Mou { 28577576c32eSGregory Etelson #if defined(HAVE_MLX5_HWS_SUPPORT) 285824865366SAlexander Kozyrev struct mlx5_priv *priv = dev->data->dev_private; 285924865366SAlexander Kozyrev 286024865366SAlexander Kozyrev if (priv->sh->config.dv_flow_en == 2) 286124865366SAlexander Kozyrev *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_hws_ops; 286224865366SAlexander Kozyrev else 2863d740eb50SSuanming Mou *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_ops; 28647576c32eSGregory Etelson #else 28657576c32eSGregory Etelson *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_ops; 28667576c32eSGregory Etelson #endif 2867d740eb50SSuanming Mou return 0; 2868d740eb50SSuanming Mou } 28693f373f35SSuanming Mou 28703f373f35SSuanming Mou /** 28713f373f35SSuanming Mou * Find meter by id. 28723f373f35SSuanming Mou * 28733f373f35SSuanming Mou * @param priv 28743f373f35SSuanming Mou * Pointer to mlx5_priv. 28753f373f35SSuanming Mou * @param meter_id 28763f373f35SSuanming Mou * Meter id. 2877e93c58daSLi Zhang * @param mtr_idx 2878e93c58daSLi Zhang * Pointer to Meter index. 28793f373f35SSuanming Mou * 28803f373f35SSuanming Mou * @return 288144432018SLi Zhang * Pointer to the meter info found on success, NULL otherwise. 28823f373f35SSuanming Mou */ 2883e6100c7bSLi Zhang struct mlx5_flow_meter_info * 2884e6100c7bSLi Zhang mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id, 2885e6100c7bSLi Zhang uint32_t *mtr_idx) 28863f373f35SSuanming Mou { 2887e6100c7bSLi Zhang struct mlx5_legacy_flow_meter *legacy_fm; 2888e6100c7bSLi Zhang struct mlx5_legacy_flow_meters *fms = &priv->flow_meters; 2889e6100c7bSLi Zhang struct mlx5_aso_mtr *aso_mtr; 2890afb4aa4fSLi Zhang struct mlx5_aso_mtr_pools_mng *pools_mng = 2891afb4aa4fSLi Zhang &priv->sh->mtrmng->pools_mng; 2892e6100c7bSLi Zhang union mlx5_l3t_data data; 28937797b0feSJiawei Wang uint16_t n_valid; 28943f373f35SSuanming Mou 289524865366SAlexander Kozyrev if (priv->mtr_bulk.aso) { 289624865366SAlexander Kozyrev if (mtr_idx) 289724865366SAlexander Kozyrev *mtr_idx = meter_id; 289824865366SAlexander Kozyrev aso_mtr = priv->mtr_bulk.aso + meter_id; 289924865366SAlexander Kozyrev return &aso_mtr->fm; 290024865366SAlexander Kozyrev } 2901e6100c7bSLi Zhang if (priv->sh->meter_aso_en) { 29027797b0feSJiawei Wang rte_rwlock_read_lock(&pools_mng->resize_mtrwl); 29037797b0feSJiawei Wang n_valid = pools_mng->n_valid; 29047797b0feSJiawei Wang rte_rwlock_read_unlock(&pools_mng->resize_mtrwl); 29057797b0feSJiawei Wang if (!n_valid || !priv->mtr_idx_tbl || 29067797b0feSJiawei Wang (mlx5_l3t_get_entry(priv->mtr_idx_tbl, meter_id, &data) || 29077797b0feSJiawei Wang !data.dword)) 290844432018SLi Zhang return NULL; 2909e6100c7bSLi Zhang if (mtr_idx) 2910e6100c7bSLi Zhang *mtr_idx = data.dword; 2911e6100c7bSLi Zhang aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword); 2912e93c58daSLi Zhang /* Remove reference taken by the mlx5_l3t_get_entry. */ 291329efa63aSLi Zhang mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id); 2914afb4aa4fSLi Zhang if (!aso_mtr || aso_mtr->state == ASO_METER_FREE) 2915afb4aa4fSLi Zhang return NULL; 2916e6100c7bSLi Zhang return &aso_mtr->fm; 2917e6100c7bSLi Zhang } 2918e6100c7bSLi Zhang TAILQ_FOREACH(legacy_fm, fms, next) 291944432018SLi Zhang if (meter_id == legacy_fm->fm.meter_id) { 2920e93c58daSLi Zhang if (mtr_idx) 2921e93c58daSLi Zhang *mtr_idx = legacy_fm->idx; 2922e6100c7bSLi Zhang return &legacy_fm->fm; 2923e6100c7bSLi Zhang } 2924e6100c7bSLi Zhang return NULL; 2925e6100c7bSLi Zhang } 2926e6100c7bSLi Zhang 2927e6100c7bSLi Zhang /** 2928e6100c7bSLi Zhang * Find meter by index. 2929e6100c7bSLi Zhang * 2930e6100c7bSLi Zhang * @param priv 2931e6100c7bSLi Zhang * Pointer to mlx5_priv. 2932e6100c7bSLi Zhang * @param idx 2933e6100c7bSLi Zhang * Meter index. 2934e6100c7bSLi Zhang * 2935e6100c7bSLi Zhang * @return 293644432018SLi Zhang * Pointer to the meter info found on success, NULL otherwise. 2937e6100c7bSLi Zhang */ 2938e6100c7bSLi Zhang struct mlx5_flow_meter_info * 2939e6100c7bSLi Zhang flow_dv_meter_find_by_idx(struct mlx5_priv *priv, uint32_t idx) 2940e6100c7bSLi Zhang { 2941e6100c7bSLi Zhang struct mlx5_aso_mtr *aso_mtr; 2942e6100c7bSLi Zhang 2943e6100c7bSLi Zhang if (priv->sh->meter_aso_en) { 2944e6100c7bSLi Zhang aso_mtr = mlx5_aso_meter_by_idx(priv, idx); 294544432018SLi Zhang if (!aso_mtr) 294644432018SLi Zhang return NULL; 2947e6100c7bSLi Zhang return &aso_mtr->fm; 2948e6100c7bSLi Zhang } else { 2949e6100c7bSLi Zhang return mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], idx); 2950e6100c7bSLi Zhang } 2951e6100c7bSLi Zhang } 2952266e9f3dSSuanming Mou 2953266e9f3dSSuanming Mou /** 2954266e9f3dSSuanming Mou * Attach meter to flow. 2955266e9f3dSSuanming Mou * Unidirectional Meter creation can only be done 2956266e9f3dSSuanming Mou * when flow direction is known, i.e. when calling meter_attach. 2957266e9f3dSSuanming Mou * 2958266e9f3dSSuanming Mou * @param [in] priv 2959266e9f3dSSuanming Mou * Pointer to mlx5 private data. 296083306d6cSShun Hao * @param[in] fm 296183306d6cSShun Hao * Pointer to flow meter. 2962266e9f3dSSuanming Mou * @param [in] attr 2963266e9f3dSSuanming Mou * Pointer to flow attributes. 2964266e9f3dSSuanming Mou * @param [out] error 2965266e9f3dSSuanming Mou * Pointer to error structure. 2966266e9f3dSSuanming Mou * 296783306d6cSShun Hao * @return 296883306d6cSShun Hao * 0 on success, a negative errno value otherwise and rte_errno is set. 2969266e9f3dSSuanming Mou */ 297083306d6cSShun Hao int 297183306d6cSShun Hao mlx5_flow_meter_attach(struct mlx5_priv *priv, 2972e6100c7bSLi Zhang struct mlx5_flow_meter_info *fm, 2973266e9f3dSSuanming Mou const struct rte_flow_attr *attr, 2974266e9f3dSSuanming Mou struct rte_flow_error *error) 2975266e9f3dSSuanming Mou { 297689a8e3c4SSuanming Mou int ret = 0; 2977266e9f3dSSuanming Mou 2978c99b4f8bSLi Zhang if (priv->sh->meter_aso_en) { 2979c99b4f8bSLi Zhang struct mlx5_aso_mtr *aso_mtr; 2980c99b4f8bSLi Zhang 2981c99b4f8bSLi Zhang aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm); 29824359d9d1SGregory Etelson if (mlx5_aso_mtr_wait(priv, aso_mtr, false)) { 2983c99b4f8bSLi Zhang return rte_flow_error_set(error, ENOENT, 2984c99b4f8bSLi Zhang RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 2985c99b4f8bSLi Zhang NULL, 2986c99b4f8bSLi Zhang "Timeout in meter configuration"); 2987c99b4f8bSLi Zhang } 298889a8e3c4SSuanming Mou rte_spinlock_lock(&fm->sl); 2989c99b4f8bSLi Zhang if (fm->shared || !fm->ref_cnt) { 2990c99b4f8bSLi Zhang fm->ref_cnt++; 2991c99b4f8bSLi Zhang } else { 2992c99b4f8bSLi Zhang rte_flow_error_set(error, EINVAL, 2993c99b4f8bSLi Zhang RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 2994c99b4f8bSLi Zhang "Meter cannot be shared"); 2995c99b4f8bSLi Zhang ret = -1; 2996c99b4f8bSLi Zhang } 2997c99b4f8bSLi Zhang rte_spinlock_unlock(&fm->sl); 2998c99b4f8bSLi Zhang } else { 2999c99b4f8bSLi Zhang rte_spinlock_lock(&fm->sl); 3000bf62fb76SShun Hao if (fm->meter_action_g) { 300189a8e3c4SSuanming Mou if (fm->shared && 300289a8e3c4SSuanming Mou attr->transfer == fm->transfer && 300389a8e3c4SSuanming Mou attr->ingress == fm->ingress && 3004c99b4f8bSLi Zhang attr->egress == fm->egress) { 300589a8e3c4SSuanming Mou fm->ref_cnt++; 3006c99b4f8bSLi Zhang } else { 3007c99b4f8bSLi Zhang rte_flow_error_set(error, EINVAL, 3008c99b4f8bSLi Zhang RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 3009c99b4f8bSLi Zhang fm->shared ? 3010c99b4f8bSLi Zhang "Meter attr not match." : 3011c99b4f8bSLi Zhang "Meter cannot be shared."); 301289a8e3c4SSuanming Mou ret = -1; 3013c99b4f8bSLi Zhang } 301489a8e3c4SSuanming Mou } else { 301578466e08SWentao Cui fm->ingress = attr->ingress; 301678466e08SWentao Cui fm->egress = attr->egress; 301778466e08SWentao Cui fm->transfer = attr->transfer; 301889a8e3c4SSuanming Mou fm->ref_cnt = 1; 3019266e9f3dSSuanming Mou /* This also creates the meter object. */ 3020bf62fb76SShun Hao fm->meter_action_g = mlx5_flow_meter_action_create(priv, 3021266e9f3dSSuanming Mou fm); 3022bf62fb76SShun Hao if (!fm->meter_action_g) { 302389a8e3c4SSuanming Mou fm->ref_cnt = 0; 302489a8e3c4SSuanming Mou fm->ingress = 0; 302589a8e3c4SSuanming Mou fm->egress = 0; 302689a8e3c4SSuanming Mou fm->transfer = 0; 3027c99b4f8bSLi Zhang rte_flow_error_set(error, EINVAL, 3028c99b4f8bSLi Zhang RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 3029c99b4f8bSLi Zhang "Meter action create failed."); 303089a8e3c4SSuanming Mou ret = -1; 3031266e9f3dSSuanming Mou } 3032266e9f3dSSuanming Mou } 303389a8e3c4SSuanming Mou rte_spinlock_unlock(&fm->sl); 3034c99b4f8bSLi Zhang } 303583306d6cSShun Hao return ret ? -rte_errno : 0; 3036266e9f3dSSuanming Mou } 3037266e9f3dSSuanming Mou 3038266e9f3dSSuanming Mou /** 3039266e9f3dSSuanming Mou * Detach meter from flow. 3040266e9f3dSSuanming Mou * 3041c99b4f8bSLi Zhang * @param [in] priv 3042c99b4f8bSLi Zhang * Pointer to mlx5 private data. 3043266e9f3dSSuanming Mou * @param [in] fm 3044266e9f3dSSuanming Mou * Pointer to flow meter. 3045266e9f3dSSuanming Mou */ 3046266e9f3dSSuanming Mou void 3047c99b4f8bSLi Zhang mlx5_flow_meter_detach(struct mlx5_priv *priv, 3048c99b4f8bSLi Zhang struct mlx5_flow_meter_info *fm) 3049266e9f3dSSuanming Mou { 30501e577c9eSOphir Munk #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER 305189a8e3c4SSuanming Mou rte_spinlock_lock(&fm->sl); 30528e46d4e1SAlexander Kozyrev MLX5_ASSERT(fm->ref_cnt); 3053c99b4f8bSLi Zhang if (--fm->ref_cnt == 0 && !priv->sh->meter_aso_en) { 3054bf62fb76SShun Hao mlx5_glue->destroy_flow_action(fm->meter_action_g); 3055bf62fb76SShun Hao fm->meter_action_g = NULL; 305678466e08SWentao Cui fm->ingress = 0; 305778466e08SWentao Cui fm->egress = 0; 305878466e08SWentao Cui fm->transfer = 0; 305989a8e3c4SSuanming Mou } 306089a8e3c4SSuanming Mou rte_spinlock_unlock(&fm->sl); 30611e577c9eSOphir Munk #else 3062c99b4f8bSLi Zhang (void)priv; 30631e577c9eSOphir Munk (void)fm; 30641e577c9eSOphir Munk #endif 3065266e9f3dSSuanming Mou } 306602e76468SSuanming Mou 306702e76468SSuanming Mou /** 3068ec962badSLi Zhang * Flush meter with Rx queue configuration. 3069ec962badSLi Zhang * 3070ec962badSLi Zhang * @param[in] dev 3071ec962badSLi Zhang * Pointer to Ethernet device. 3072ec962badSLi Zhang */ 3073ec962badSLi Zhang void 3074ec962badSLi Zhang mlx5_flow_meter_rxq_flush(struct rte_eth_dev *dev) 3075ec962badSLi Zhang { 3076ec962badSLi Zhang struct mlx5_priv *priv = dev->data->dev_private; 3077ec962badSLi Zhang struct mlx5_flow_meter_sub_policy *sub_policy; 3078ec962badSLi Zhang struct mlx5_flow_meter_policy *mtr_policy; 3079ec962badSLi Zhang void *entry; 3080ec962badSLi Zhang uint32_t i, policy_idx; 3081ec962badSLi Zhang 3082ec962badSLi Zhang if (!priv->mtr_en) 3083ec962badSLi Zhang return; 3084efcce4dcSShun Hao if (priv->policy_idx_tbl) { 3085efcce4dcSShun Hao MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) { 3086ec962badSLi Zhang policy_idx = *(uint32_t *)entry; 3087ec962badSLi Zhang sub_policy = mlx5_ipool_get 3088ec962badSLi Zhang (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY], 3089ec962badSLi Zhang policy_idx); 3090ec962badSLi Zhang if (!sub_policy || !sub_policy->main_policy) 3091ec962badSLi Zhang continue; 3092ec962badSLi Zhang mtr_policy = sub_policy->main_policy; 3093ec962badSLi Zhang if (mtr_policy->is_queue || mtr_policy->is_rss) 3094ec962badSLi Zhang mlx5_flow_destroy_sub_policy_with_rxq(dev, 3095ec962badSLi Zhang mtr_policy); 3096ec962badSLi Zhang } 3097ec962badSLi Zhang } 3098ec962badSLi Zhang } 3099ec962badSLi Zhang 3100ec962badSLi Zhang /** 3101f890b030SShun Hao * Iterate a meter hierarchy and flush all meters and policies if possible. 3102f890b030SShun Hao * 3103f890b030SShun Hao * @param[in] dev 3104f890b030SShun Hao * Pointer to Ethernet device. 3105f890b030SShun Hao * @param[in] fm 3106f890b030SShun Hao * Pointer to flow meter. 3107f890b030SShun Hao * @param[in] mtr_idx 3108f890b030SShun Hao * .Meter's index 3109f890b030SShun Hao * @param[out] error 3110f890b030SShun Hao * Pointer to rte meter error structure. 3111f890b030SShun Hao * 3112f890b030SShun Hao * @return 3113f890b030SShun Hao * 0 on success, a negative errno value otherwise and rte_errno is set. 3114f890b030SShun Hao */ 3115f890b030SShun Hao static int 3116f890b030SShun Hao mlx5_flow_meter_flush_hierarchy(struct rte_eth_dev *dev, 3117f890b030SShun Hao struct mlx5_flow_meter_info *fm, 3118f890b030SShun Hao uint32_t mtr_idx, 3119f890b030SShun Hao struct rte_mtr_error *error) 3120f890b030SShun Hao { 3121f890b030SShun Hao struct mlx5_priv *priv = dev->data->dev_private; 3122f890b030SShun Hao struct mlx5_flow_meter_policy *policy; 3123f890b030SShun Hao uint32_t policy_id; 3124f890b030SShun Hao struct mlx5_flow_meter_info *next_fm; 3125f890b030SShun Hao uint32_t next_mtr_idx; 3126f890b030SShun Hao struct mlx5_flow_meter_policy *next_policy = NULL; 3127f890b030SShun Hao 3128f890b030SShun Hao policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL); 3129f890b030SShun Hao MLX5_ASSERT(policy); 3130f890b030SShun Hao while (!fm->ref_cnt && policy->is_hierarchy) { 3131f890b030SShun Hao policy_id = fm->policy_id; 3132bf62fb76SShun Hao next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, policy, &next_mtr_idx); 3133f890b030SShun Hao if (next_fm) { 3134f890b030SShun Hao next_policy = mlx5_flow_meter_policy_find(dev, 3135f890b030SShun Hao next_fm->policy_id, 3136f890b030SShun Hao NULL); 3137f890b030SShun Hao MLX5_ASSERT(next_policy); 3138f890b030SShun Hao } 3139f890b030SShun Hao if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx)) 3140f890b030SShun Hao return -rte_mtr_error_set(error, ENOTSUP, 3141f890b030SShun Hao RTE_MTR_ERROR_TYPE_MTR_ID, 3142f890b030SShun Hao NULL, 3143f890b030SShun Hao "Failed to flush meter."); 3144f890b030SShun Hao if (policy->ref_cnt) 3145f890b030SShun Hao break; 3146f890b030SShun Hao if (__mlx5_flow_meter_policy_delete(dev, policy_id, 3147f890b030SShun Hao policy, error, true)) 3148f890b030SShun Hao return -rte_errno; 3149f890b030SShun Hao mlx5_free(policy); 3150f890b030SShun Hao if (!next_fm || !next_policy) 3151f890b030SShun Hao break; 3152f890b030SShun Hao fm = next_fm; 3153f890b030SShun Hao mtr_idx = next_mtr_idx; 3154f890b030SShun Hao policy = next_policy; 3155f890b030SShun Hao } 3156f890b030SShun Hao return 0; 3157f890b030SShun Hao } 3158f890b030SShun Hao 3159f890b030SShun Hao /** 3160f890b030SShun Hao * Flush all the hierarchy meters and their policies. 3161f890b030SShun Hao * 3162f890b030SShun Hao * @param[in] dev 3163f890b030SShun Hao * Pointer to Ethernet device. 3164f890b030SShun Hao * @param[out] error 3165f890b030SShun Hao * Pointer to rte meter error structure. 3166f890b030SShun Hao * 3167f890b030SShun Hao * @return 3168f890b030SShun Hao * 0 on success, a negative errno value otherwise and rte_errno is set. 3169f890b030SShun Hao */ 3170f890b030SShun Hao static int 3171f890b030SShun Hao mlx5_flow_meter_flush_all_hierarchies(struct rte_eth_dev *dev, 3172f890b030SShun Hao struct rte_mtr_error *error) 3173f890b030SShun Hao { 3174f890b030SShun Hao struct mlx5_priv *priv = dev->data->dev_private; 3175f890b030SShun Hao struct mlx5_flow_meter_info *fm; 3176f890b030SShun Hao struct mlx5_flow_meter_policy *policy; 3177f890b030SShun Hao struct mlx5_flow_meter_sub_policy *sub_policy; 3178f890b030SShun Hao struct mlx5_flow_meter_info *next_fm; 3179f890b030SShun Hao struct mlx5_aso_mtr *aso_mtr; 3180f890b030SShun Hao uint32_t mtr_idx = 0; 3181f890b030SShun Hao uint32_t i, policy_idx; 3182f890b030SShun Hao void *entry; 3183f890b030SShun Hao 3184f890b030SShun Hao if (!priv->mtr_idx_tbl || !priv->policy_idx_tbl) 3185f890b030SShun Hao return 0; 3186f890b030SShun Hao MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) { 3187f890b030SShun Hao mtr_idx = *(uint32_t *)entry; 3188f890b030SShun Hao if (!mtr_idx) 3189f890b030SShun Hao continue; 3190f890b030SShun Hao aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx); 3191f890b030SShun Hao fm = &aso_mtr->fm; 3192f890b030SShun Hao if (fm->ref_cnt || fm->def_policy) 3193f890b030SShun Hao continue; 3194f890b030SShun Hao if (mlx5_flow_meter_flush_hierarchy(dev, fm, mtr_idx, error)) 3195f890b030SShun Hao return -rte_errno; 3196f890b030SShun Hao } 3197f890b030SShun Hao MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) { 3198f890b030SShun Hao policy_idx = *(uint32_t *)entry; 3199f890b030SShun Hao sub_policy = mlx5_ipool_get 3200f890b030SShun Hao (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY], 3201f890b030SShun Hao policy_idx); 3202f890b030SShun Hao if (!sub_policy) 3203f890b030SShun Hao return -rte_mtr_error_set(error, 3204f890b030SShun Hao EINVAL, 3205f890b030SShun Hao RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 3206f890b030SShun Hao NULL, "Meter policy invalid."); 3207f890b030SShun Hao policy = sub_policy->main_policy; 3208f890b030SShun Hao if (!policy || !policy->is_hierarchy || policy->ref_cnt) 3209f890b030SShun Hao continue; 3210bf62fb76SShun Hao next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, policy, &mtr_idx); 3211f890b030SShun Hao if (__mlx5_flow_meter_policy_delete(dev, i, policy, 3212f890b030SShun Hao error, true)) 3213f890b030SShun Hao return -rte_mtr_error_set(error, 3214f890b030SShun Hao EINVAL, 3215f890b030SShun Hao RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 3216f890b030SShun Hao NULL, "Meter policy invalid."); 3217f890b030SShun Hao mlx5_free(policy); 3218f890b030SShun Hao if (!next_fm || next_fm->ref_cnt || next_fm->def_policy) 3219f890b030SShun Hao continue; 3220f890b030SShun Hao if (mlx5_flow_meter_flush_hierarchy(dev, next_fm, 3221f890b030SShun Hao mtr_idx, error)) 3222f890b030SShun Hao return -rte_errno; 3223f890b030SShun Hao } 3224f890b030SShun Hao return 0; 3225f890b030SShun Hao } 3226f890b030SShun Hao /** 322702e76468SSuanming Mou * Flush meter configuration. 322802e76468SSuanming Mou * 322902e76468SSuanming Mou * @param[in] dev 323002e76468SSuanming Mou * Pointer to Ethernet device. 323102e76468SSuanming Mou * @param[out] error 323202e76468SSuanming Mou * Pointer to rte meter error structure. 323302e76468SSuanming Mou * 323402e76468SSuanming Mou * @return 323502e76468SSuanming Mou * 0 on success, a negative errno value otherwise and rte_errno is set. 323602e76468SSuanming Mou */ 323702e76468SSuanming Mou int 323802e76468SSuanming Mou mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error) 323902e76468SSuanming Mou { 324002e76468SSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 3241e6100c7bSLi Zhang struct mlx5_legacy_flow_meters *fms = &priv->flow_meters; 324202e76468SSuanming Mou struct mlx5_flow_meter_profile *fmp; 3243e6100c7bSLi Zhang struct mlx5_legacy_flow_meter *legacy_fm; 3244e6100c7bSLi Zhang struct mlx5_flow_meter_info *fm; 3245afb4aa4fSLi Zhang struct mlx5_flow_meter_sub_policy *sub_policy; 324602e76468SSuanming Mou void *tmp; 324744432018SLi Zhang uint32_t i, mtr_idx, policy_idx; 3248afb4aa4fSLi Zhang void *entry; 324944432018SLi Zhang struct mlx5_aso_mtr *aso_mtr; 325002e76468SSuanming Mou 3251afb4aa4fSLi Zhang if (!priv->mtr_en) 3252afb4aa4fSLi Zhang return 0; 3253e6100c7bSLi Zhang if (priv->sh->meter_aso_en) { 3254f890b030SShun Hao if (mlx5_flow_meter_flush_all_hierarchies(dev, error)) 3255f890b030SShun Hao return -rte_errno; 325644432018SLi Zhang if (priv->mtr_idx_tbl) { 325744432018SLi Zhang MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) { 325844432018SLi Zhang mtr_idx = *(uint32_t *)entry; 325944432018SLi Zhang if (mtr_idx) { 326044432018SLi Zhang aso_mtr = 326144432018SLi Zhang mlx5_aso_meter_by_idx(priv, mtr_idx); 326244432018SLi Zhang fm = &aso_mtr->fm; 3263afb4aa4fSLi Zhang (void)mlx5_flow_meter_params_flush(dev, 3264afb4aa4fSLi Zhang fm, mtr_idx); 3265e6100c7bSLi Zhang } 3266e6100c7bSLi Zhang } 326744432018SLi Zhang mlx5_l3t_destroy(priv->mtr_idx_tbl); 326844432018SLi Zhang priv->mtr_idx_tbl = NULL; 326944432018SLi Zhang } 3270e6100c7bSLi Zhang } else { 3271f1f6ebc0SWilliam Tu RTE_TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) { 3272e6100c7bSLi Zhang fm = &legacy_fm->fm; 32735f0d54f3SLi Zhang if (mlx5_flow_meter_params_flush(dev, fm, 0)) 327402e76468SSuanming Mou return -rte_mtr_error_set(error, EINVAL, 327502e76468SSuanming Mou RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 327602e76468SSuanming Mou NULL, "MTR object meter profile invalid."); 3277e6100c7bSLi Zhang } 327802e76468SSuanming Mou } 327924865366SAlexander Kozyrev if (priv->mtr_bulk.aso) { 328048fbb0e9SAlexander Kozyrev for (i = 0; i < priv->mtr_config.nb_meters; i++) { 328124865366SAlexander Kozyrev aso_mtr = mlx5_aso_meter_by_idx(priv, i); 328224865366SAlexander Kozyrev fm = &aso_mtr->fm; 328324865366SAlexander Kozyrev if (fm->initialized) 328424865366SAlexander Kozyrev mlx5_flow_meter_hws_destroy(dev, i, error); 328524865366SAlexander Kozyrev } 328624865366SAlexander Kozyrev } 3287efcce4dcSShun Hao if (priv->policy_idx_tbl) { 3288efcce4dcSShun Hao MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) { 3289afb4aa4fSLi Zhang policy_idx = *(uint32_t *)entry; 3290afb4aa4fSLi Zhang sub_policy = mlx5_ipool_get 3291afb4aa4fSLi Zhang (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY], 3292afb4aa4fSLi Zhang policy_idx); 3293afb4aa4fSLi Zhang if (!sub_policy) 3294afb4aa4fSLi Zhang return -rte_mtr_error_set(error, 3295afb4aa4fSLi Zhang EINVAL, 3296afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 3297afb4aa4fSLi Zhang NULL, "MTR object " 3298afb4aa4fSLi Zhang "meter policy invalid."); 3299afb4aa4fSLi Zhang if (__mlx5_flow_meter_policy_delete(dev, i, 3300afb4aa4fSLi Zhang sub_policy->main_policy, 3301035f4c23SLi Zhang error, true)) 3302afb4aa4fSLi Zhang return -rte_mtr_error_set(error, 3303afb4aa4fSLi Zhang EINVAL, 3304afb4aa4fSLi Zhang RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 3305afb4aa4fSLi Zhang NULL, "MTR object " 3306afb4aa4fSLi Zhang "meter policy invalid."); 3307afb4aa4fSLi Zhang mlx5_free(sub_policy->main_policy); 3308afb4aa4fSLi Zhang } 3309efcce4dcSShun Hao mlx5_l3t_destroy(priv->policy_idx_tbl); 3310efcce4dcSShun Hao priv->policy_idx_tbl = NULL; 3311afb4aa4fSLi Zhang } 33127576c32eSGregory Etelson #if defined(HAVE_MLX5_HWS_SUPPORT) 331324865366SAlexander Kozyrev if (priv->mtr_policy_arr) { 33147576c32eSGregory Etelson struct mlx5_flow_meter_policy *policy; 33157576c32eSGregory Etelson 331624865366SAlexander Kozyrev for (i = 0; i < priv->mtr_config.nb_meter_policies; i++) { 331724865366SAlexander Kozyrev policy = mlx5_flow_meter_policy_find(dev, i, 331824865366SAlexander Kozyrev &policy_idx); 33197576c32eSGregory Etelson if (policy->initialized) { 332024865366SAlexander Kozyrev mlx5_flow_meter_policy_hws_delete(dev, i, 332124865366SAlexander Kozyrev error); 332224865366SAlexander Kozyrev } 332324865366SAlexander Kozyrev } 33247576c32eSGregory Etelson } 33257576c32eSGregory Etelson #endif 3326a295c69aSShun Hao if (priv->mtr_profile_tbl) { 3327a295c69aSShun Hao MLX5_L3T_FOREACH(priv->mtr_profile_tbl, i, entry) { 3328a295c69aSShun Hao fmp = entry; 3329a295c69aSShun Hao if (mlx5_flow_meter_profile_delete(dev, fmp->id, 3330a295c69aSShun Hao error)) 3331a295c69aSShun Hao return -rte_mtr_error_set(error, EINVAL, 3332a295c69aSShun Hao RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 3333a295c69aSShun Hao NULL, "Fail to destroy " 3334a295c69aSShun Hao "meter profile."); 3335a295c69aSShun Hao } 3336a295c69aSShun Hao mlx5_l3t_destroy(priv->mtr_profile_tbl); 3337a295c69aSShun Hao priv->mtr_profile_tbl = NULL; 333802e76468SSuanming Mou } 33397576c32eSGregory Etelson #if defined(HAVE_MLX5_HWS_SUPPORT) 334024865366SAlexander Kozyrev if (priv->mtr_profile_arr) { 334124865366SAlexander Kozyrev for (i = 0; i < priv->mtr_config.nb_meter_profiles; i++) { 334224865366SAlexander Kozyrev fmp = mlx5_flow_meter_profile_find(priv, i); 33437576c32eSGregory Etelson if (fmp->initialized) { 334424865366SAlexander Kozyrev mlx5_flow_meter_profile_hws_delete(dev, i, 334524865366SAlexander Kozyrev error); 334624865366SAlexander Kozyrev } 334724865366SAlexander Kozyrev } 33487576c32eSGregory Etelson } 33497576c32eSGregory Etelson #endif 3350afb4aa4fSLi Zhang /* Delete default policy table. */ 3351afb4aa4fSLi Zhang mlx5_flow_destroy_def_policy(dev); 335244432018SLi Zhang if (priv->sh->refcnt == 1) 3353afb4aa4fSLi Zhang mlx5_flow_destroy_mtr_drop_tbls(dev); 335424865366SAlexander Kozyrev #ifdef HAVE_MLX5_HWS_SUPPORT 335524865366SAlexander Kozyrev /* Destroy HWS configuration. */ 335624865366SAlexander Kozyrev mlx5_flow_meter_uninit(dev); 335724865366SAlexander Kozyrev #endif 335802e76468SSuanming Mou return 0; 335902e76468SSuanming Mou } 3360