net/mlx5: support meter policy operations
MLX5 PMD checks the validation of actions in policy while add a new meter policy, if pass the validation, allocates the new policy object from the meter policy indexed memory pool. It is common to use the same policy for multiple meters. MLX5 PMD supports two types of policy: termination policy and no-termination policy. Implement the next policy operations: validate: The driver doesn't support to configure actions in the flow after the meter action except one case when the meter policy is configured to do nothing in GREEN\YELLOW and only DROP action in RED, this special policy is called non-terminated policy and is handed as a singleton object internally. For all the terminated policies, the next actions are supported: GREEN - QUEUE, RSS, PORT_ID, JUMP, DROP, MARK and SET_TAG. YELLOW - not supported at all -> must be empty. RED - must include DROP action. Hence, in ingress case, for example, QUEUE\RSS\JUMP must be configured as last action for GREEN color. All the above limitations will be validated. create: Validate the policy configuration. Prepare the related tables and actions. destroy: Release the created policy resources. Signed-off-by: Li Zhang <lizh@nvidia.com> Acked-by: Matan Azrad <matan@nvidia.com>
This commit is contained in:
parent
c02bbaa96b
commit
afb4aa4f12
@ -1301,7 +1301,7 @@ err_secondary:
|
||||
log_obj_size <=
|
||||
config->hca_attr.qos.log_meter_aso_max_alloc) {
|
||||
sh->meter_aso_en = 1;
|
||||
err = mlx5_aso_flow_mtrs_mng_init(priv);
|
||||
err = mlx5_aso_flow_mtrs_mng_init(priv->sh);
|
||||
if (err) {
|
||||
err = -err;
|
||||
goto error;
|
||||
|
@ -352,6 +352,20 @@ static const struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = {
|
||||
.free = mlx5_free,
|
||||
.type = "mlx5_shared_action_rss",
|
||||
},
|
||||
[MLX5_IPOOL_MTR_POLICY] = {
|
||||
/**
|
||||
* The ipool index should grow continually from small to big,
|
||||
* for policy idx, so not set grow_trunk to avoid policy index
|
||||
* not jump continually.
|
||||
*/
|
||||
.size = sizeof(struct mlx5_flow_meter_sub_policy),
|
||||
.trunk_size = 64,
|
||||
.need_lock = 1,
|
||||
.release_mem_en = 1,
|
||||
.malloc = mlx5_malloc,
|
||||
.free = mlx5_free,
|
||||
.type = "mlx5_meter_policy_ipool",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -571,27 +585,25 @@ mlx5_flow_counters_mng_close(struct mlx5_dev_ctx_shared *sh)
|
||||
* Pointer to mlx5_dev_ctx_shared object to free
|
||||
*/
|
||||
int
|
||||
mlx5_aso_flow_mtrs_mng_init(struct mlx5_priv *priv)
|
||||
mlx5_aso_flow_mtrs_mng_init(struct mlx5_dev_ctx_shared *sh)
|
||||
{
|
||||
if (!priv->mtr_idx_tbl) {
|
||||
priv->mtr_idx_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
|
||||
if (!priv->mtr_idx_tbl) {
|
||||
DRV_LOG(ERR, "fail to create meter lookup table.");
|
||||
rte_errno = ENOMEM;
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
if (!priv->sh->mtrmng) {
|
||||
priv->sh->mtrmng = mlx5_malloc(MLX5_MEM_ZERO,
|
||||
sizeof(*priv->sh->mtrmng),
|
||||
if (!sh->mtrmng) {
|
||||
sh->mtrmng = mlx5_malloc(MLX5_MEM_ZERO,
|
||||
sizeof(*sh->mtrmng),
|
||||
RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
|
||||
if (!priv->sh->mtrmng) {
|
||||
DRV_LOG(ERR, "mlx5_aso_mtr_pools_mng allocation was failed.");
|
||||
if (!sh->mtrmng) {
|
||||
DRV_LOG(ERR,
|
||||
"meter management allocation was failed.");
|
||||
rte_errno = ENOMEM;
|
||||
return -ENOMEM;
|
||||
}
|
||||
rte_spinlock_init(&priv->sh->mtrmng->mtrsl);
|
||||
LIST_INIT(&priv->sh->mtrmng->meters);
|
||||
if (sh->meter_aso_en) {
|
||||
rte_spinlock_init(&sh->mtrmng->pools_mng.mtrsl);
|
||||
LIST_INIT(&sh->mtrmng->pools_mng.meters);
|
||||
sh->mtrmng->policy_idx_tbl =
|
||||
mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
|
||||
}
|
||||
sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -607,31 +619,34 @@ static void
|
||||
mlx5_aso_flow_mtrs_mng_close(struct mlx5_dev_ctx_shared *sh)
|
||||
{
|
||||
struct mlx5_aso_mtr_pool *mtr_pool;
|
||||
struct mlx5_aso_mtr_pools_mng *mtrmng = sh->mtrmng;
|
||||
struct mlx5_flow_mtr_mng *mtrmng = sh->mtrmng;
|
||||
uint32_t idx;
|
||||
#ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
|
||||
struct mlx5_aso_mtr *aso_mtr;
|
||||
int i;
|
||||
#endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO */
|
||||
|
||||
mlx5_aso_queue_uninit(sh, ASO_OPC_MOD_POLICER);
|
||||
idx = mtrmng->n_valid;
|
||||
while (idx--) {
|
||||
mtr_pool = mtrmng->pools[idx];
|
||||
if (sh->meter_aso_en) {
|
||||
mlx5_aso_queue_uninit(sh, ASO_OPC_MOD_POLICER);
|
||||
idx = mtrmng->pools_mng.n_valid;
|
||||
while (idx--) {
|
||||
mtr_pool = mtrmng->pools_mng.pools[idx];
|
||||
#ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
|
||||
for (i = 0; i < MLX5_ASO_MTRS_PER_POOL; i++) {
|
||||
aso_mtr = &mtr_pool->mtrs[i];
|
||||
if (aso_mtr->fm.meter_action)
|
||||
claim_zero(mlx5_glue->destroy_flow_action
|
||||
(aso_mtr->fm.meter_action));
|
||||
}
|
||||
for (i = 0; i < MLX5_ASO_MTRS_PER_POOL; i++) {
|
||||
aso_mtr = &mtr_pool->mtrs[i];
|
||||
if (aso_mtr->fm.meter_action)
|
||||
claim_zero
|
||||
(mlx5_glue->destroy_flow_action
|
||||
(aso_mtr->fm.meter_action));
|
||||
}
|
||||
#endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO */
|
||||
claim_zero(mlx5_devx_cmd_destroy
|
||||
claim_zero(mlx5_devx_cmd_destroy
|
||||
(mtr_pool->devx_obj));
|
||||
mtrmng->n_valid--;
|
||||
mlx5_free(mtr_pool);
|
||||
mtrmng->pools_mng.n_valid--;
|
||||
mlx5_free(mtr_pool);
|
||||
}
|
||||
mlx5_free(sh->mtrmng->pools_mng.pools);
|
||||
}
|
||||
mlx5_free(sh->mtrmng->pools);
|
||||
mlx5_free(sh->mtrmng);
|
||||
sh->mtrmng = NULL;
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ enum mlx5_ipool_index {
|
||||
MLX5_IPOOL_RTE_FLOW, /* Pool for rte_flow. */
|
||||
MLX5_IPOOL_RSS_EXPANTION_FLOW_ID, /* Pool for Queue/RSS flow ID. */
|
||||
MLX5_IPOOL_RSS_SHARED_ACTIONS, /* Pool for RSS shared actions. */
|
||||
MLX5_IPOOL_MTR_POLICY, /* Pool for meter policy resource. */
|
||||
MLX5_IPOOL_MAX,
|
||||
};
|
||||
|
||||
@ -589,9 +590,126 @@ struct mlx5_dev_shared_port {
|
||||
/* Aging information for per port. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Max number of actions per DV flow.
|
||||
* See CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED
|
||||
* in rdma-core file providers/mlx5/verbs.c.
|
||||
*/
|
||||
#define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8
|
||||
|
||||
/*ASO flow meter structures*/
|
||||
/* Modify this value if enum rte_mtr_color changes. */
|
||||
#define RTE_MTR_DROPPED RTE_COLORS
|
||||
/* Yellow is not supported. */
|
||||
#define MLX5_MTR_RTE_COLORS (RTE_COLOR_GREEN + 1)
|
||||
/* table_id 22 bits in mlx5_flow_tbl_key so limit policy number. */
|
||||
#define MLX5_MAX_SUB_POLICY_TBL_NUM 0x3FFFFF
|
||||
#define MLX5_INVALID_POLICY_ID UINT32_MAX
|
||||
/* Suffix table_id on MLX5_FLOW_TABLE_LEVEL_METER. */
|
||||
#define MLX5_MTR_TABLE_ID_SUFFIX 1
|
||||
/* Drop table_id on MLX5_FLOW_TABLE_LEVEL_METER. */
|
||||
#define MLX5_MTR_TABLE_ID_DROP 2
|
||||
|
||||
enum mlx5_meter_domain {
|
||||
MLX5_MTR_DOMAIN_INGRESS,
|
||||
MLX5_MTR_DOMAIN_EGRESS,
|
||||
MLX5_MTR_DOMAIN_TRANSFER,
|
||||
MLX5_MTR_DOMAIN_MAX,
|
||||
};
|
||||
#define MLX5_MTR_DOMAIN_INGRESS_BIT (1 << MLX5_MTR_DOMAIN_INGRESS)
|
||||
#define MLX5_MTR_DOMAIN_EGRESS_BIT (1 << MLX5_MTR_DOMAIN_EGRESS)
|
||||
#define MLX5_MTR_DOMAIN_TRANSFER_BIT (1 << MLX5_MTR_DOMAIN_TRANSFER)
|
||||
#define MLX5_MTR_ALL_DOMAIN_BIT (MLX5_MTR_DOMAIN_INGRESS_BIT | \
|
||||
MLX5_MTR_DOMAIN_EGRESS_BIT | \
|
||||
MLX5_MTR_DOMAIN_TRANSFER_BIT)
|
||||
|
||||
/*
|
||||
* Meter sub-policy structure.
|
||||
* Each RSS TIR in meter policy need its own sub-policy resource.
|
||||
*/
|
||||
struct mlx5_flow_meter_sub_policy {
|
||||
uint32_t main_policy_id:1;
|
||||
/* Main policy id is same as this sub_policy id. */
|
||||
uint32_t idx:31;
|
||||
/* Index to sub_policy ipool entity. */
|
||||
void *main_policy;
|
||||
/* Point to struct mlx5_flow_meter_policy. */
|
||||
struct mlx5_flow_tbl_resource *tbl_rsc;
|
||||
/* The sub-policy table resource. */
|
||||
uint32_t rix_hrxq[MLX5_MTR_RTE_COLORS];
|
||||
/* Index to TIR resource. */
|
||||
struct mlx5_flow_tbl_resource *jump_tbl[MLX5_MTR_RTE_COLORS];
|
||||
/* Meter jump/drop table. */
|
||||
struct mlx5_flow_dv_matcher *color_matcher[RTE_COLORS];
|
||||
/* Matcher for Color. */
|
||||
void *color_rule[RTE_COLORS];
|
||||
/* Meter green/yellow/drop rule. */
|
||||
};
|
||||
|
||||
struct mlx5_meter_policy_acts {
|
||||
uint8_t actions_n;
|
||||
/* Number of actions. */
|
||||
void *dv_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
|
||||
/* Action list. */
|
||||
};
|
||||
|
||||
struct mlx5_meter_policy_action_container {
|
||||
uint32_t rix_mark;
|
||||
/* Index to the mark action. */
|
||||
struct mlx5_flow_dv_modify_hdr_resource *modify_hdr;
|
||||
/* Pointer to modify header resource in cache. */
|
||||
uint8_t fate_action;
|
||||
/* Fate action type. */
|
||||
union {
|
||||
struct rte_flow_action *rss;
|
||||
/* Rss action configuration. */
|
||||
uint32_t rix_port_id_action;
|
||||
/* Index to port ID action resource. */
|
||||
void *dr_jump_action[MLX5_MTR_DOMAIN_MAX];
|
||||
/* Jump/drop action per color. */
|
||||
};
|
||||
};
|
||||
|
||||
/* Flow meter policy parameter structure. */
|
||||
struct mlx5_flow_meter_policy {
|
||||
uint32_t is_rss:1;
|
||||
/* Is RSS policy table. */
|
||||
uint32_t ingress:1;
|
||||
/* Rule applies to ingress domain. */
|
||||
uint32_t egress:1;
|
||||
/* Rule applies to egress domain. */
|
||||
uint32_t transfer:1;
|
||||
/* Rule applies to transfer domain. */
|
||||
rte_spinlock_t sl;
|
||||
uint32_t ref_cnt;
|
||||
/* Use count. */
|
||||
struct mlx5_meter_policy_action_container act_cnt[MLX5_MTR_RTE_COLORS];
|
||||
/* Policy actions container. */
|
||||
void *dr_drop_action[MLX5_MTR_DOMAIN_MAX];
|
||||
/* drop action for red color. */
|
||||
uint16_t sub_policy_num;
|
||||
/* Count sub policy tables, 3 bits per domain. */
|
||||
struct mlx5_flow_meter_sub_policy **sub_policys[MLX5_MTR_DOMAIN_MAX];
|
||||
/* Sub policy table array must be the end of struct. */
|
||||
};
|
||||
|
||||
/* The maximum sub policy is relate to struct mlx5_rss_hash_fields[]. */
|
||||
#define MLX5_MTR_RSS_MAX_SUB_POLICY 7
|
||||
#define MLX5_MTR_SUB_POLICY_NUM_SHIFT 3
|
||||
#define MLX5_MTR_SUB_POLICY_NUM_MASK 0x7
|
||||
#define MLX5_MTRS_DEFAULT_RULE_PRIORITY 0xFFFF
|
||||
|
||||
/* Flow meter default policy parameter structure.
|
||||
* Policy index 0 is reserved by default policy table.
|
||||
* Action per color as below:
|
||||
* green - do nothing, yellow - do nothing, red - drop
|
||||
*/
|
||||
struct mlx5_flow_meter_def_policy {
|
||||
struct mlx5_flow_meter_sub_policy sub_policy;
|
||||
/* Policy rules jump to other tables. */
|
||||
void *dr_jump_action[RTE_COLORS];
|
||||
/* Jump action per color. */
|
||||
};
|
||||
|
||||
/* Meter table structure. */
|
||||
struct mlx5_meter_domain_info {
|
||||
@ -755,6 +873,28 @@ struct mlx5_aso_mtr_pools_mng {
|
||||
struct mlx5_aso_mtr_pool **pools; /* ASO flow meter pool array. */
|
||||
};
|
||||
|
||||
/* Meter management structure for global flow meter resource. */
|
||||
struct mlx5_flow_mtr_mng {
|
||||
struct mlx5_aso_mtr_pools_mng pools_mng;
|
||||
/* Pools management structure for ASO flow meter pools. */
|
||||
struct mlx5_flow_meter_def_policy *def_policy[MLX5_MTR_DOMAIN_MAX];
|
||||
/* Default policy table. */
|
||||
uint32_t def_policy_id;
|
||||
/* Default policy id. */
|
||||
uint32_t def_policy_ref_cnt;
|
||||
/** def_policy meter use count. */
|
||||
struct mlx5_l3t_tbl *policy_idx_tbl;
|
||||
/* Policy index lookup table. */
|
||||
struct mlx5_flow_tbl_resource *drop_tbl[MLX5_MTR_DOMAIN_MAX];
|
||||
/* Meter drop table. */
|
||||
struct mlx5_flow_dv_matcher *drop_matcher[MLX5_MTR_DOMAIN_MAX];
|
||||
/* Matcher meter in drop table. */
|
||||
struct mlx5_flow_dv_matcher *def_matcher[MLX5_MTR_DOMAIN_MAX];
|
||||
/* Default matcher in drop table. */
|
||||
void *def_rule[MLX5_MTR_DOMAIN_MAX];
|
||||
/* Default rule in drop table. */
|
||||
};
|
||||
|
||||
/* Table key of the hash organization. */
|
||||
union mlx5_flow_tbl_key {
|
||||
struct {
|
||||
@ -781,9 +921,9 @@ struct mlx5_flow_tbl_resource {
|
||||
#define MLX5_FLOW_MREG_ACT_TABLE_GROUP (MLX5_MAX_TABLES - 1)
|
||||
#define MLX5_FLOW_MREG_CP_TABLE_GROUP (MLX5_MAX_TABLES - 2)
|
||||
/* Tables for metering splits should be added here. */
|
||||
#define MLX5_FLOW_TABLE_LEVEL_SUFFIX (MLX5_MAX_TABLES - 3)
|
||||
#define MLX5_FLOW_TABLE_LEVEL_METER (MLX5_MAX_TABLES - 4)
|
||||
#define MLX5_MAX_TABLES_EXTERNAL MLX5_FLOW_TABLE_LEVEL_METER
|
||||
#define MLX5_FLOW_TABLE_LEVEL_METER (MLX5_MAX_TABLES - 3)
|
||||
#define MLX5_FLOW_TABLE_LEVEL_POLICY (MLX5_MAX_TABLES - 4)
|
||||
#define MLX5_MAX_TABLES_EXTERNAL MLX5_FLOW_TABLE_LEVEL_POLICY
|
||||
#define MLX5_MAX_TABLES_FDB UINT16_MAX
|
||||
#define MLX5_FLOW_TABLE_FACTOR 10
|
||||
|
||||
@ -944,8 +1084,8 @@ struct mlx5_dev_ctx_shared {
|
||||
struct mlx5_geneve_tlv_option_resource *geneve_tlv_option_resource;
|
||||
/* Management structure for geneve tlv option */
|
||||
rte_spinlock_t geneve_tlv_opt_sl; /* Lock for geneve tlv resource */
|
||||
struct mlx5_aso_mtr_pools_mng *mtrmng;
|
||||
/* Meter pools management structure. */
|
||||
struct mlx5_flow_mtr_mng *mtrmng;
|
||||
/* Meter management structure. */
|
||||
struct mlx5_dev_shared_port port[]; /* per device port data array. */
|
||||
};
|
||||
|
||||
@ -1246,7 +1386,7 @@ int mlx5_hairpin_cap_get(struct rte_eth_dev *dev,
|
||||
bool mlx5_flex_parser_ecpri_exist(struct rte_eth_dev *dev);
|
||||
int mlx5_flex_parser_ecpri_alloc(struct rte_eth_dev *dev);
|
||||
int mlx5_flow_aso_age_mng_init(struct mlx5_dev_ctx_shared *sh);
|
||||
int mlx5_aso_flow_mtrs_mng_init(struct mlx5_priv *priv);
|
||||
int mlx5_aso_flow_mtrs_mng_init(struct mlx5_dev_ctx_shared *sh);
|
||||
|
||||
/* mlx5_ethdev.c */
|
||||
|
||||
@ -1472,6 +1612,12 @@ int mlx5_flow_meter_attach(struct mlx5_priv *priv,
|
||||
struct rte_flow_error *error);
|
||||
void mlx5_flow_meter_detach(struct mlx5_priv *priv,
|
||||
struct mlx5_flow_meter_info *fm);
|
||||
struct mlx5_flow_meter_policy *mlx5_flow_meter_policy_find
|
||||
(struct rte_eth_dev *dev,
|
||||
uint32_t policy_id,
|
||||
uint32_t *policy_idx);
|
||||
int mlx5_flow_meter_flush(struct rte_eth_dev *dev,
|
||||
struct rte_mtr_error *error);
|
||||
|
||||
/* mlx5_os.c */
|
||||
struct rte_pci_driver;
|
||||
|
@ -1028,7 +1028,7 @@ flow_rxq_tunnel_ptype_update(struct mlx5_rxq_ctrl *rxq_ctrl)
|
||||
* @param[in] dev_handle
|
||||
* Pointer to device flow handle structure.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
flow_drv_rxq_flags_set(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_handle *dev_handle)
|
||||
{
|
||||
@ -4479,8 +4479,8 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
|
||||
actions_pre++;
|
||||
jump_data = (struct rte_flow_action_jump *)actions_pre;
|
||||
jump_data->group = attr->transfer ?
|
||||
(MLX5_FLOW_TABLE_LEVEL_METER - 1) :
|
||||
MLX5_FLOW_TABLE_LEVEL_METER;
|
||||
(MLX5_FLOW_TABLE_LEVEL_POLICY - 1) :
|
||||
MLX5_FLOW_TABLE_LEVEL_POLICY;
|
||||
hw_mtr_action->conf = jump_data;
|
||||
actions_pre = (struct rte_flow_action *)(jump_data + 1);
|
||||
} else {
|
||||
@ -5087,8 +5087,8 @@ flow_create_split_metadata(struct rte_eth_dev *dev,
|
||||
if (qrss) {
|
||||
/* Check if it is in meter suffix table. */
|
||||
mtr_sfx = attr->group == (attr->transfer ?
|
||||
(MLX5_FLOW_TABLE_LEVEL_SUFFIX - 1) :
|
||||
MLX5_FLOW_TABLE_LEVEL_SUFFIX);
|
||||
(MLX5_FLOW_TABLE_LEVEL_METER - 1) :
|
||||
MLX5_FLOW_TABLE_LEVEL_METER);
|
||||
/*
|
||||
* Q/RSS action on NIC Rx should be split in order to pass by
|
||||
* the mreg copy table (RX_CP_TBL) and then it jumps to the
|
||||
@ -5352,8 +5352,8 @@ flow_create_split_meter(struct rte_eth_dev *dev,
|
||||
dev_flow->handle->is_meter_flow_id = 1;
|
||||
/* Setting the sfx group atrr. */
|
||||
sfx_attr.group = sfx_attr.transfer ?
|
||||
(MLX5_FLOW_TABLE_LEVEL_SUFFIX - 1) :
|
||||
MLX5_FLOW_TABLE_LEVEL_SUFFIX;
|
||||
(MLX5_FLOW_TABLE_LEVEL_METER - 1) :
|
||||
MLX5_FLOW_TABLE_LEVEL_METER;
|
||||
flow_split_info->prefix_layers =
|
||||
flow_get_prefix_layer_flags(dev_flow);
|
||||
flow_split_info->prefix_mark = dev_flow->handle->mark;
|
||||
@ -6616,6 +6616,169 @@ mlx5_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate meter policy actions.
|
||||
* Dispatcher for action type specific validation.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to the Ethernet device structure.
|
||||
* @param[in] action
|
||||
* The meter policy action object to validate.
|
||||
* @param[in] attr
|
||||
* Attributes of flow to determine steering domain.
|
||||
* @param[out] is_rss
|
||||
* Is RSS or not.
|
||||
* @param[out] domain_bitmap
|
||||
* Domain bitmap.
|
||||
* @param[out] is_def_policy
|
||||
* Is default policy or not.
|
||||
* @param[out] error
|
||||
* Perform verbose error reporting if not NULL. Initialized in case of
|
||||
* error only.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, otherwise negative errno value.
|
||||
*/
|
||||
int
|
||||
mlx5_flow_validate_mtr_acts(struct rte_eth_dev *dev,
|
||||
const struct rte_flow_action *actions[RTE_COLORS],
|
||||
struct rte_flow_attr *attr,
|
||||
bool *is_rss,
|
||||
uint8_t *domain_bitmap,
|
||||
bool *is_def_policy,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
const struct mlx5_flow_driver_ops *fops;
|
||||
|
||||
fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
|
||||
return fops->validate_mtr_acts(dev, actions, attr,
|
||||
is_rss, domain_bitmap, is_def_policy, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the meter table set.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
* @param[in] mtr_policy
|
||||
* Meter policy struct.
|
||||
*/
|
||||
void
|
||||
mlx5_flow_destroy_mtr_acts(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_policy *mtr_policy)
|
||||
{
|
||||
const struct mlx5_flow_driver_ops *fops;
|
||||
|
||||
fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
|
||||
fops->destroy_mtr_acts(dev, mtr_policy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create policy action, lock free,
|
||||
* (mutex should be acquired by caller).
|
||||
* Dispatcher for action type specific call.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to the Ethernet device structure.
|
||||
* @param[in] mtr_policy
|
||||
* Meter policy struct.
|
||||
* @param[in] action
|
||||
* Action specification used to create meter actions.
|
||||
* @param[out] error
|
||||
* Perform verbose error reporting if not NULL. Initialized in case of
|
||||
* error only.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, otherwise negative errno value.
|
||||
*/
|
||||
int
|
||||
mlx5_flow_create_mtr_acts(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_policy *mtr_policy,
|
||||
const struct rte_flow_action *actions[RTE_COLORS],
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
const struct mlx5_flow_driver_ops *fops;
|
||||
|
||||
fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
|
||||
return fops->create_mtr_acts(dev, mtr_policy, actions, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create policy rules, lock free,
|
||||
* (mutex should be acquired by caller).
|
||||
* Dispatcher for action type specific call.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to the Ethernet device structure.
|
||||
* @param[in] mtr_policy
|
||||
* Meter policy struct.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, -1 otherwise.
|
||||
*/
|
||||
int
|
||||
mlx5_flow_create_policy_rules(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_policy *mtr_policy)
|
||||
{
|
||||
const struct mlx5_flow_driver_ops *fops;
|
||||
|
||||
fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
|
||||
return fops->create_policy_rules(dev, mtr_policy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy policy rules, lock free,
|
||||
* (mutex should be acquired by caller).
|
||||
* Dispatcher for action type specific call.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to the Ethernet device structure.
|
||||
* @param[in] mtr_policy
|
||||
* Meter policy struct.
|
||||
*/
|
||||
void
|
||||
mlx5_flow_destroy_policy_rules(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_policy *mtr_policy)
|
||||
{
|
||||
const struct mlx5_flow_driver_ops *fops;
|
||||
|
||||
fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
|
||||
fops->destroy_policy_rules(dev, mtr_policy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the default policy table set.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
*/
|
||||
void
|
||||
mlx5_flow_destroy_def_policy(struct rte_eth_dev *dev)
|
||||
{
|
||||
const struct mlx5_flow_driver_ops *fops;
|
||||
|
||||
fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
|
||||
fops->destroy_def_policy(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the default policy table set.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, -1 otherwise.
|
||||
*/
|
||||
int
|
||||
mlx5_flow_create_def_policy(struct rte_eth_dev *dev)
|
||||
{
|
||||
const struct mlx5_flow_driver_ops *fops;
|
||||
|
||||
fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
|
||||
return fops->create_def_policy(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the needed meter and suffix tables.
|
||||
*
|
||||
@ -6655,6 +6818,21 @@ mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
|
||||
return fops->destroy_mtr_tbls(dev, tbls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the global meter drop table.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
*/
|
||||
void
|
||||
mlx5_flow_destroy_mtr_drop_tbls(struct rte_eth_dev *dev)
|
||||
{
|
||||
const struct mlx5_flow_driver_ops *fops;
|
||||
|
||||
fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
|
||||
fops->destroy_mtr_drop_tbls(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate the needed aso flow meter id.
|
||||
*
|
||||
|
@ -690,13 +690,6 @@ struct mlx5_flow_handle {
|
||||
#define MLX5_FLOW_HANDLE_VERBS_SIZE (sizeof(struct mlx5_flow_handle))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Max number of actions per DV flow.
|
||||
* See CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED
|
||||
* in rdma-core file providers/mlx5/verbs.c.
|
||||
*/
|
||||
#define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8
|
||||
|
||||
/** Device flow structure only for DV flow creation. */
|
||||
struct mlx5_flow_dv_workspace {
|
||||
uint32_t group; /**< The group index. */
|
||||
@ -1098,6 +1091,7 @@ typedef struct mlx5_meter_domains_infos *(*mlx5_flow_create_mtr_tbls_t)
|
||||
(struct rte_eth_dev *dev);
|
||||
typedef int (*mlx5_flow_destroy_mtr_tbls_t)(struct rte_eth_dev *dev,
|
||||
struct mlx5_meter_domains_infos *tbls);
|
||||
typedef void (*mlx5_flow_destroy_mtr_drop_tbls_t)(struct rte_eth_dev *dev);
|
||||
typedef uint32_t (*mlx5_flow_mtr_alloc_t)
|
||||
(struct rte_eth_dev *dev);
|
||||
typedef void (*mlx5_flow_mtr_free_t)(struct rte_eth_dev *dev,
|
||||
@ -1143,6 +1137,32 @@ typedef int (*mlx5_flow_sync_domain_t)
|
||||
(struct rte_eth_dev *dev,
|
||||
uint32_t domains,
|
||||
uint32_t flags);
|
||||
typedef int (*mlx5_flow_validate_mtr_acts_t)
|
||||
(struct rte_eth_dev *dev,
|
||||
const struct rte_flow_action *actions[RTE_COLORS],
|
||||
struct rte_flow_attr *attr,
|
||||
bool *is_rss,
|
||||
uint8_t *domain_bitmap,
|
||||
bool *is_def_policy,
|
||||
struct rte_mtr_error *error);
|
||||
typedef int (*mlx5_flow_create_mtr_acts_t)
|
||||
(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_policy *mtr_policy,
|
||||
const struct rte_flow_action *actions[RTE_COLORS],
|
||||
struct rte_mtr_error *error);
|
||||
typedef void (*mlx5_flow_destroy_mtr_acts_t)
|
||||
(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_policy *mtr_policy);
|
||||
typedef int (*mlx5_flow_create_policy_rules_t)
|
||||
(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_policy *mtr_policy);
|
||||
typedef void (*mlx5_flow_destroy_policy_rules_t)
|
||||
(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_policy *mtr_policy);
|
||||
typedef int (*mlx5_flow_create_def_policy_t)
|
||||
(struct rte_eth_dev *dev);
|
||||
typedef void (*mlx5_flow_destroy_def_policy_t)
|
||||
(struct rte_eth_dev *dev);
|
||||
|
||||
struct mlx5_flow_driver_ops {
|
||||
mlx5_flow_validate_t validate;
|
||||
@ -1154,8 +1174,16 @@ struct mlx5_flow_driver_ops {
|
||||
mlx5_flow_query_t query;
|
||||
mlx5_flow_create_mtr_tbls_t create_mtr_tbls;
|
||||
mlx5_flow_destroy_mtr_tbls_t destroy_mtr_tbls;
|
||||
mlx5_flow_destroy_mtr_drop_tbls_t destroy_mtr_drop_tbls;
|
||||
mlx5_flow_mtr_alloc_t create_meter;
|
||||
mlx5_flow_mtr_free_t free_meter;
|
||||
mlx5_flow_validate_mtr_acts_t validate_mtr_acts;
|
||||
mlx5_flow_create_mtr_acts_t create_mtr_acts;
|
||||
mlx5_flow_destroy_mtr_acts_t destroy_mtr_acts;
|
||||
mlx5_flow_create_policy_rules_t create_policy_rules;
|
||||
mlx5_flow_destroy_policy_rules_t destroy_policy_rules;
|
||||
mlx5_flow_create_def_policy_t create_def_policy;
|
||||
mlx5_flow_destroy_def_policy_t destroy_def_policy;
|
||||
mlx5_flow_counter_alloc_t counter_alloc;
|
||||
mlx5_flow_counter_free_t counter_free;
|
||||
mlx5_flow_counter_query_t counter_query;
|
||||
@ -1232,12 +1260,13 @@ static inline struct mlx5_aso_mtr *
|
||||
mlx5_aso_meter_by_idx(struct mlx5_priv *priv, uint32_t idx)
|
||||
{
|
||||
struct mlx5_aso_mtr_pool *pool;
|
||||
struct mlx5_aso_mtr_pools_mng *mtrmng = priv->sh->mtrmng;
|
||||
struct mlx5_aso_mtr_pools_mng *pools_mng =
|
||||
&priv->sh->mtrmng->pools_mng;
|
||||
|
||||
/* Decrease to original index. */
|
||||
idx--;
|
||||
MLX5_ASSERT(idx / MLX5_ASO_MTRS_PER_POOL < mtrmng->n);
|
||||
pool = mtrmng->pools[idx / MLX5_ASO_MTRS_PER_POOL];
|
||||
MLX5_ASSERT(idx / MLX5_ASO_MTRS_PER_POOL < pools_mng->n);
|
||||
pool = pools_mng->pools[idx / MLX5_ASO_MTRS_PER_POOL];
|
||||
return &pool->mtrs[idx % MLX5_ASO_MTRS_PER_POOL];
|
||||
}
|
||||
|
||||
@ -1383,8 +1412,7 @@ struct mlx5_meter_domains_infos *mlx5_flow_create_mtr_tbls
|
||||
(struct rte_eth_dev *dev);
|
||||
int mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
|
||||
struct mlx5_meter_domains_infos *tbl);
|
||||
int mlx5_flow_meter_flush(struct rte_eth_dev *dev,
|
||||
struct rte_mtr_error *error);
|
||||
void mlx5_flow_destroy_mtr_drop_tbls(struct rte_eth_dev *dev);
|
||||
int mlx5_flow_dv_discover_counter_offset_support(struct rte_eth_dev *dev);
|
||||
int mlx5_action_handle_flush(struct rte_eth_dev *dev);
|
||||
void mlx5_release_tunnel_hub(struct mlx5_dev_ctx_shared *sh, uint16_t port_id);
|
||||
@ -1485,4 +1513,25 @@ int mlx5_flow_os_set_specific_workspace(struct mlx5_flow_workspace *data);
|
||||
void mlx5_flow_os_release_workspace(void);
|
||||
uint32_t mlx5_flow_mtr_alloc(struct rte_eth_dev *dev);
|
||||
void mlx5_flow_mtr_free(struct rte_eth_dev *dev, uint32_t mtr_idx);
|
||||
int mlx5_flow_validate_mtr_acts(struct rte_eth_dev *dev,
|
||||
const struct rte_flow_action *actions[RTE_COLORS],
|
||||
struct rte_flow_attr *attr,
|
||||
bool *is_rss,
|
||||
uint8_t *domain_bitmap,
|
||||
bool *is_def_policy,
|
||||
struct rte_mtr_error *error);
|
||||
void mlx5_flow_destroy_mtr_acts(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_policy *mtr_policy);
|
||||
int mlx5_flow_create_mtr_acts(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_policy *mtr_policy,
|
||||
const struct rte_flow_action *actions[RTE_COLORS],
|
||||
struct rte_mtr_error *error);
|
||||
int mlx5_flow_create_policy_rules(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_policy *mtr_policy);
|
||||
void mlx5_flow_destroy_policy_rules(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_policy *mtr_policy);
|
||||
int mlx5_flow_create_def_policy(struct rte_eth_dev *dev);
|
||||
void mlx5_flow_destroy_def_policy(struct rte_eth_dev *dev);
|
||||
void flow_drv_rxq_flags_set(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_handle *dev_handle);
|
||||
#endif /* RTE_PMD_MLX5_FLOW_H_ */
|
||||
|
@ -311,11 +311,11 @@ mlx5_aso_queue_init(struct mlx5_dev_ctx_shared *sh,
|
||||
mlx5_aso_age_init_sq(&sh->aso_age_mng->aso_sq);
|
||||
break;
|
||||
case ASO_OPC_MOD_POLICER:
|
||||
if (mlx5_aso_sq_create(sh->ctx, &sh->mtrmng->sq, 0,
|
||||
if (mlx5_aso_sq_create(sh->ctx, &sh->mtrmng->pools_mng.sq, 0,
|
||||
sh->tx_uar, sh->pdn, MLX5_ASO_QUEUE_LOG_DESC,
|
||||
sh->sq_ts_format))
|
||||
return -1;
|
||||
mlx5_aso_mtr_init_sq(&sh->mtrmng->sq);
|
||||
mlx5_aso_mtr_init_sq(&sh->mtrmng->pools_mng.sq);
|
||||
break;
|
||||
default:
|
||||
DRV_LOG(ERR, "Unknown ASO operation mode");
|
||||
@ -342,7 +342,7 @@ mlx5_aso_queue_uninit(struct mlx5_dev_ctx_shared *sh,
|
||||
sq = &sh->aso_age_mng->aso_sq;
|
||||
break;
|
||||
case ASO_OPC_MOD_POLICER:
|
||||
sq = &sh->mtrmng->sq;
|
||||
sq = &sh->mtrmng->pools_mng.sq;
|
||||
break;
|
||||
default:
|
||||
DRV_LOG(ERR, "Unknown ASO operation mode");
|
||||
@ -798,7 +798,7 @@ int
|
||||
mlx5_aso_meter_update_by_wqe(struct mlx5_dev_ctx_shared *sh,
|
||||
struct mlx5_aso_mtr *mtr)
|
||||
{
|
||||
struct mlx5_aso_sq *sq = &sh->mtrmng->sq;
|
||||
struct mlx5_aso_sq *sq = &sh->mtrmng->pools_mng.sq;
|
||||
uint32_t poll_wqe_times = MLX5_MTR_POLL_WQE_CQE_TIMES;
|
||||
|
||||
do {
|
||||
@ -830,7 +830,7 @@ int
|
||||
mlx5_aso_mtr_wait(struct mlx5_dev_ctx_shared *sh,
|
||||
struct mlx5_aso_mtr *mtr)
|
||||
{
|
||||
struct mlx5_aso_sq *sq = &sh->mtrmng->sq;
|
||||
struct mlx5_aso_sq *sq = &sh->mtrmng->pools_mng.sq;
|
||||
uint32_t poll_cqe_times = MLX5_MTR_POLL_WQE_CQE_TIMES;
|
||||
|
||||
if (__atomic_load_n(&mtr->state, __ATOMIC_RELAXED) ==
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -38,6 +38,12 @@ mlx5_flow_meter_action_create(struct mlx5_priv *priv,
|
||||
uint32_t cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir);
|
||||
uint32_t ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir);
|
||||
uint32_t val;
|
||||
enum mlx5_meter_domain domain =
|
||||
fm->transfer ? MLX5_MTR_DOMAIN_TRANSFER :
|
||||
fm->egress ? MLX5_MTR_DOMAIN_EGRESS :
|
||||
MLX5_MTR_DOMAIN_INGRESS;
|
||||
struct mlx5_flow_meter_def_policy *def_policy =
|
||||
priv->sh->mtrmng->def_policy[domain];
|
||||
|
||||
memset(fmp, 0, MLX5_ST_SZ_BYTES(flow_meter_parameters));
|
||||
MLX5_SET(flow_meter_parameters, fmp, valid, 1);
|
||||
@ -57,10 +63,7 @@ mlx5_flow_meter_action_create(struct mlx5_priv *priv,
|
||||
MLX5_SET(flow_meter_parameters, fmp, ebs_exponent, val);
|
||||
val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) & ASO_DSEG_MAN_MASK;
|
||||
MLX5_SET(flow_meter_parameters, fmp, ebs_mantissa, val);
|
||||
mtr_init.next_table =
|
||||
fm->transfer ? fm->mfts->transfer.tbl->obj :
|
||||
fm->egress ? fm->mfts->egress.tbl->obj :
|
||||
fm->mfts->ingress.tbl->obj;
|
||||
mtr_init.next_table = def_policy->sub_policy.tbl_rsc->obj;
|
||||
mtr_init.reg_c_index = priv->mtr_color_reg - REG_C_0;
|
||||
mtr_init.flow_meter_parameter = fmp;
|
||||
mtr_init.flow_meter_parameter_sz =
|
||||
@ -317,7 +320,7 @@ mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
|
||||
"Meter is not supported");
|
||||
memset(cap, 0, sizeof(*cap));
|
||||
if (priv->sh->meter_aso_en)
|
||||
/* 2 meters per one ASO cache line. */
|
||||
/* 2 meters per one ASO cache line. */
|
||||
cap->n_max = 1 << (qattr->log_max_num_meter_aso + 1);
|
||||
else
|
||||
cap->n_max = 1 << qattr->log_max_flow_meter;
|
||||
@ -435,6 +438,347 @@ mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find policy by id.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
* @param policy_id
|
||||
* Policy id.
|
||||
*
|
||||
* @return
|
||||
* Pointer to the policy found on success, NULL otherwise.
|
||||
*/
|
||||
struct mlx5_flow_meter_policy *
|
||||
mlx5_flow_meter_policy_find(struct rte_eth_dev *dev,
|
||||
uint32_t policy_id,
|
||||
uint32_t *policy_idx)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
|
||||
union mlx5_l3t_data data;
|
||||
|
||||
if (policy_id > MLX5_MAX_SUB_POLICY_TBL_NUM ||
|
||||
!priv->sh->mtrmng->policy_idx_tbl)
|
||||
return NULL;
|
||||
if (mlx5_l3t_get_entry(priv->sh->mtrmng->policy_idx_tbl,
|
||||
policy_id, &data) ||
|
||||
!data.dword)
|
||||
return NULL;
|
||||
if (policy_idx)
|
||||
*policy_idx = data.dword;
|
||||
sub_policy = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
|
||||
data.dword);
|
||||
/* Remove reference taken by the mlx5_l3t_get_entry. */
|
||||
mlx5_l3t_clear_entry(priv->sh->mtrmng->policy_idx_tbl,
|
||||
policy_id);
|
||||
if (sub_policy)
|
||||
if (sub_policy->main_policy_id)
|
||||
return sub_policy->main_policy;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to check MTR policy action validate
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
* @param[in] actions
|
||||
* Pointer to meter policy action detail.
|
||||
* @param[out] error
|
||||
* Pointer to the error structure.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, a negative errno value otherwise and rte_errno is set.
|
||||
*/
|
||||
static int
|
||||
mlx5_flow_meter_policy_validate(struct rte_eth_dev *dev,
|
||||
struct rte_mtr_meter_policy_params *policy,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct rte_flow_attr attr = { .transfer =
|
||||
priv->config.dv_esw_en ? 1 : 0};
|
||||
bool is_rss = false;
|
||||
bool is_def_policy = false;
|
||||
uint8_t domain_bitmap;
|
||||
int ret;
|
||||
|
||||
if (!priv->mtr_en || !priv->sh->meter_aso_en)
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY,
|
||||
NULL, "meter policy unsupported.");
|
||||
ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
|
||||
&is_rss, &domain_bitmap, &is_def_policy, error);
|
||||
if (ret)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
__mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
|
||||
uint32_t policy_id,
|
||||
struct mlx5_flow_meter_policy *mtr_policy,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_flow_meter_sub_policy *sub_policy;
|
||||
uint32_t i, j;
|
||||
uint16_t sub_policy_num;
|
||||
|
||||
rte_spinlock_lock(&mtr_policy->sl);
|
||||
if (mtr_policy->ref_cnt) {
|
||||
rte_spinlock_unlock(&mtr_policy->sl);
|
||||
return -rte_mtr_error_set(error, EBUSY,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
|
||||
NULL,
|
||||
"Meter policy object is being used.");
|
||||
}
|
||||
mlx5_flow_destroy_policy_rules(dev, mtr_policy);
|
||||
mlx5_flow_destroy_mtr_acts(dev, mtr_policy);
|
||||
for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
|
||||
sub_policy_num = (mtr_policy->sub_policy_num >>
|
||||
(MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
|
||||
MLX5_MTR_SUB_POLICY_NUM_MASK;
|
||||
if (sub_policy_num) {
|
||||
for (j = 0; j < sub_policy_num; j++) {
|
||||
sub_policy = mtr_policy->sub_policys[i][j];
|
||||
if (sub_policy)
|
||||
mlx5_ipool_free
|
||||
(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
|
||||
sub_policy->idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (priv->sh->mtrmng->policy_idx_tbl) {
|
||||
if (mlx5_l3t_clear_entry(priv->sh->mtrmng->policy_idx_tbl,
|
||||
policy_id)) {
|
||||
rte_spinlock_unlock(&mtr_policy->sl);
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
|
||||
"Fail to delete policy in index table.");
|
||||
}
|
||||
}
|
||||
rte_spinlock_unlock(&mtr_policy->sl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to add MTR policy.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
* @param[out] policy_id
|
||||
* Pointer to policy id
|
||||
* @param[in] actions
|
||||
* Pointer to meter policy action detail.
|
||||
* @param[out] error
|
||||
* Pointer to the error structure.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, a negative errno value otherwise and rte_errno is set.
|
||||
*/
|
||||
static int
|
||||
mlx5_flow_meter_policy_add(struct rte_eth_dev *dev,
|
||||
uint32_t policy_id,
|
||||
struct rte_mtr_meter_policy_params *policy,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct rte_flow_attr attr = { .transfer =
|
||||
priv->config.dv_esw_en ? 1 : 0};
|
||||
uint32_t sub_policy_idx = 0;
|
||||
uint32_t policy_idx = 0;
|
||||
struct mlx5_flow_meter_policy *mtr_policy = NULL;
|
||||
struct mlx5_flow_meter_sub_policy *sub_policy;
|
||||
bool is_rss = false;
|
||||
bool is_def_policy = false;
|
||||
uint32_t i;
|
||||
int ret;
|
||||
uint32_t policy_size = sizeof(struct mlx5_flow_meter_policy);
|
||||
uint16_t sub_policy_num;
|
||||
uint8_t domain_bitmap = 0;
|
||||
union mlx5_l3t_data data;
|
||||
|
||||
if (!priv->mtr_en)
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY,
|
||||
NULL, "meter policy unsupported.");
|
||||
if (policy_id == MLX5_INVALID_POLICY_ID)
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
|
||||
"policy ID is invalid. ");
|
||||
if (policy_id == priv->sh->mtrmng->def_policy_id)
|
||||
return -rte_mtr_error_set(error, EEXIST,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
|
||||
"policy ID exists. ");
|
||||
mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id,
|
||||
&policy_idx);
|
||||
if (mtr_policy)
|
||||
return -rte_mtr_error_set(error, EEXIST,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
|
||||
"policy ID exists. ");
|
||||
ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
|
||||
&is_rss, &domain_bitmap, &is_def_policy, error);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!domain_bitmap)
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY,
|
||||
NULL, "fail to find policy domain.");
|
||||
if (is_def_policy) {
|
||||
if (priv->sh->mtrmng->def_policy_id != MLX5_INVALID_POLICY_ID)
|
||||
return -rte_mtr_error_set(error, EEXIST,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
|
||||
NULL, "a policy with similar actions "
|
||||
"is already configured");
|
||||
if (mlx5_flow_create_def_policy(dev))
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY,
|
||||
NULL,
|
||||
"fail to create non-terminated policy.");
|
||||
priv->sh->mtrmng->def_policy_id = policy_id;
|
||||
return 0;
|
||||
}
|
||||
if (!priv->sh->meter_aso_en)
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
|
||||
"no ASO capability to support the policy ");
|
||||
for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
|
||||
if (!(domain_bitmap & (1 << i)))
|
||||
continue;
|
||||
if (is_rss) {
|
||||
policy_size +=
|
||||
sizeof(struct mlx5_flow_meter_sub_policy *) *
|
||||
MLX5_MTR_RSS_MAX_SUB_POLICY;
|
||||
break;
|
||||
}
|
||||
policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
|
||||
}
|
||||
mtr_policy = mlx5_malloc(MLX5_MEM_ZERO, policy_size,
|
||||
RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
|
||||
if (!mtr_policy)
|
||||
return -rte_mtr_error_set(error, ENOMEM,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
|
||||
"Memory alloc failed for meter policy.");
|
||||
policy_size = sizeof(struct mlx5_flow_meter_policy);
|
||||
for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
|
||||
if (!(domain_bitmap & (1 << i)))
|
||||
continue;
|
||||
mtr_policy->ingress = (i == MLX5_MTR_DOMAIN_INGRESS) ? 1 : 0;
|
||||
mtr_policy->egress = (i == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
|
||||
mtr_policy->transfer = (i == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
|
||||
sub_policy = mlx5_ipool_zmalloc
|
||||
(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
|
||||
&sub_policy_idx);
|
||||
if (!sub_policy)
|
||||
goto policy_add_err;
|
||||
if (sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM)
|
||||
goto policy_add_err;
|
||||
sub_policy->idx = sub_policy_idx;
|
||||
sub_policy->main_policy = mtr_policy;
|
||||
if (!policy_idx) {
|
||||
policy_idx = sub_policy_idx;
|
||||
sub_policy->main_policy_id = 1;
|
||||
}
|
||||
mtr_policy->sub_policys[i] =
|
||||
(struct mlx5_flow_meter_sub_policy **)
|
||||
((uint8_t *)mtr_policy + policy_size);
|
||||
mtr_policy->sub_policys[i][0] = sub_policy;
|
||||
sub_policy_num = (mtr_policy->sub_policy_num >>
|
||||
(MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
|
||||
MLX5_MTR_SUB_POLICY_NUM_MASK;
|
||||
sub_policy_num++;
|
||||
mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
|
||||
(MLX5_MTR_SUB_POLICY_NUM_SHIFT * i));
|
||||
mtr_policy->sub_policy_num |=
|
||||
(sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
|
||||
(MLX5_MTR_SUB_POLICY_NUM_SHIFT * i);
|
||||
if (is_rss) {
|
||||
mtr_policy->is_rss = 1;
|
||||
break;
|
||||
}
|
||||
policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
|
||||
}
|
||||
rte_spinlock_init(&mtr_policy->sl);
|
||||
ret = mlx5_flow_create_mtr_acts(dev, mtr_policy,
|
||||
policy->actions, error);
|
||||
if (ret)
|
||||
goto policy_add_err;
|
||||
if (!is_rss) {
|
||||
/* Create policy rules in HW. */
|
||||
ret = mlx5_flow_create_policy_rules(dev, mtr_policy);
|
||||
if (ret)
|
||||
goto policy_add_err;
|
||||
}
|
||||
data.dword = policy_idx;
|
||||
if (!priv->sh->mtrmng->policy_idx_tbl) {
|
||||
priv->sh->mtrmng->policy_idx_tbl =
|
||||
mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
|
||||
if (!priv->sh->mtrmng->policy_idx_tbl)
|
||||
goto policy_add_err;
|
||||
}
|
||||
if (mlx5_l3t_set_entry(priv->sh->mtrmng->policy_idx_tbl,
|
||||
policy_id, &data))
|
||||
goto policy_add_err;
|
||||
return 0;
|
||||
policy_add_err:
|
||||
if (mtr_policy) {
|
||||
ret = __mlx5_flow_meter_policy_delete(dev, policy_id,
|
||||
mtr_policy, error);
|
||||
mlx5_free(mtr_policy);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_UNSPECIFIED,
|
||||
NULL, "Failed to create devx policy.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to delete MTR policy.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
* @param[in] policy_id
|
||||
* Meter policy id.
|
||||
* @param[out] error
|
||||
* Pointer to the error structure.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, a negative errno value otherwise and rte_errno is set.
|
||||
*/
|
||||
static int
|
||||
mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
|
||||
uint32_t policy_id,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_flow_meter_policy *mtr_policy;
|
||||
uint32_t policy_idx;
|
||||
int ret;
|
||||
|
||||
if (policy_id == priv->sh->mtrmng->def_policy_id) {
|
||||
if (priv->sh->mtrmng->def_policy_ref_cnt > 0)
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
|
||||
"Meter policy object is being used.");
|
||||
priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
|
||||
return 0;
|
||||
}
|
||||
mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
|
||||
if (!mtr_policy)
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
|
||||
"Meter policy id is invalid. ");
|
||||
ret = __mlx5_flow_meter_policy_delete(dev, policy_id, mtr_policy,
|
||||
error);
|
||||
if (ret)
|
||||
return ret;
|
||||
mlx5_free(mtr_policy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the flow meter action.
|
||||
*
|
||||
@ -942,6 +1286,9 @@ static const struct rte_mtr_ops mlx5_flow_mtr_ops = {
|
||||
.capabilities_get = mlx5_flow_mtr_cap_get,
|
||||
.meter_profile_add = mlx5_flow_meter_profile_add,
|
||||
.meter_profile_delete = mlx5_flow_meter_profile_delete,
|
||||
.meter_policy_validate = mlx5_flow_meter_policy_validate,
|
||||
.meter_policy_add = mlx5_flow_meter_policy_add,
|
||||
.meter_policy_delete = mlx5_flow_meter_policy_delete,
|
||||
.destroy = mlx5_flow_meter_destroy,
|
||||
.meter_enable = mlx5_flow_meter_enable,
|
||||
.meter_disable = mlx5_flow_meter_disable,
|
||||
@ -989,22 +1336,32 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
|
||||
struct mlx5_legacy_flow_meter *legacy_fm;
|
||||
struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
|
||||
struct mlx5_aso_mtr *aso_mtr;
|
||||
struct mlx5_aso_mtr_pools_mng *mtrmng = priv->sh->mtrmng;
|
||||
struct mlx5_aso_mtr_pools_mng *pools_mng =
|
||||
&priv->sh->mtrmng->pools_mng;
|
||||
union mlx5_l3t_data data;
|
||||
|
||||
if (priv->sh->meter_aso_en) {
|
||||
rte_spinlock_lock(&mtrmng->mtrsl);
|
||||
if (mlx5_l3t_get_entry(priv->mtr_idx_tbl, meter_id, &data) ||
|
||||
!data.dword) {
|
||||
rte_spinlock_unlock(&mtrmng->mtrsl);
|
||||
return NULL;
|
||||
rte_spinlock_lock(&pools_mng->mtrsl);
|
||||
if (priv->mtr_idx_tbl) {
|
||||
if (mlx5_l3t_get_entry(priv->mtr_idx_tbl,
|
||||
meter_id, &data) ||
|
||||
!data.dword) {
|
||||
rte_spinlock_unlock(&pools_mng->mtrsl);
|
||||
return NULL;
|
||||
}
|
||||
if (mtr_idx)
|
||||
*mtr_idx = data.dword;
|
||||
aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
|
||||
/* Remove reference taken by the mlx5_l3t_get_entry. */
|
||||
mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
|
||||
} else {
|
||||
if (mtr_idx)
|
||||
*mtr_idx = meter_id;
|
||||
aso_mtr = mlx5_aso_meter_by_idx(priv, meter_id);
|
||||
}
|
||||
if (mtr_idx)
|
||||
*mtr_idx = data.dword;
|
||||
aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
|
||||
/* Remove reference taken by the mlx5_l3t_get_entry. */
|
||||
mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
|
||||
rte_spinlock_unlock(&mtrmng->mtrsl);
|
||||
rte_spinlock_unlock(&pools_mng->mtrsl);
|
||||
if (!aso_mtr || aso_mtr->state == ASO_METER_FREE)
|
||||
return NULL;
|
||||
return &aso_mtr->fm;
|
||||
}
|
||||
TAILQ_FOREACH(legacy_fm, fms, next)
|
||||
@ -1169,30 +1526,31 @@ int
|
||||
mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_aso_mtr_pools_mng *mtrmng = priv->sh->mtrmng;
|
||||
struct mlx5_aso_mtr_pools_mng *pools_mng =
|
||||
&priv->sh->mtrmng->pools_mng;
|
||||
struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
|
||||
struct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles;
|
||||
struct mlx5_flow_meter_profile *fmp;
|
||||
struct mlx5_legacy_flow_meter *legacy_fm;
|
||||
struct mlx5_flow_meter_info *fm;
|
||||
struct mlx5_aso_mtr_pool *mtr_pool;
|
||||
struct mlx5_flow_meter_sub_policy *sub_policy;
|
||||
void *tmp;
|
||||
uint32_t i, offset, mtr_idx;
|
||||
uint32_t i, offset, mtr_idx, policy_idx;
|
||||
void *entry;
|
||||
|
||||
if (!priv->mtr_en)
|
||||
return 0;
|
||||
if (priv->sh->meter_aso_en) {
|
||||
i = mtrmng->n_valid;
|
||||
i = pools_mng->n_valid;
|
||||
while (i--) {
|
||||
mtr_pool = mtrmng->pools[i];
|
||||
mtr_pool = pools_mng->pools[i];
|
||||
for (offset = 0; offset < MLX5_ASO_MTRS_PER_POOL;
|
||||
offset++) {
|
||||
fm = &mtr_pool->mtrs[offset].fm;
|
||||
mtr_idx = MLX5_MAKE_MTR_IDX(i, offset);
|
||||
if (mlx5_flow_meter_params_flush(dev,
|
||||
fm, mtr_idx))
|
||||
return -rte_mtr_error_set
|
||||
(error, EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
|
||||
NULL, "MTR object meter profile invalid.");
|
||||
(void)mlx5_flow_meter_params_flush(dev,
|
||||
fm, mtr_idx);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1200,10 +1558,36 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
|
||||
fm = &legacy_fm->fm;
|
||||
if (mlx5_flow_meter_params_flush(dev, fm, 0))
|
||||
return -rte_mtr_error_set(error, EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
|
||||
NULL, "MTR object meter profile invalid.");
|
||||
RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
|
||||
NULL, "MTR object meter profile invalid.");
|
||||
}
|
||||
}
|
||||
if (priv->sh->mtrmng->policy_idx_tbl) {
|
||||
MLX5_L3T_FOREACH(priv->sh->mtrmng->policy_idx_tbl,
|
||||
i, entry) {
|
||||
policy_idx = *(uint32_t *)entry;
|
||||
sub_policy = mlx5_ipool_get
|
||||
(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
|
||||
policy_idx);
|
||||
if (!sub_policy)
|
||||
return -rte_mtr_error_set(error,
|
||||
EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
|
||||
NULL, "MTR object "
|
||||
"meter policy invalid.");
|
||||
if (__mlx5_flow_meter_policy_delete(dev, i,
|
||||
sub_policy->main_policy,
|
||||
error))
|
||||
return -rte_mtr_error_set(error,
|
||||
EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
|
||||
NULL, "MTR object "
|
||||
"meter policy invalid.");
|
||||
mlx5_free(sub_policy->main_policy);
|
||||
}
|
||||
mlx5_l3t_destroy(priv->sh->mtrmng->policy_idx_tbl);
|
||||
priv->sh->mtrmng->policy_idx_tbl = NULL;
|
||||
}
|
||||
TAILQ_FOREACH_SAFE(fmp, fmps, next, tmp) {
|
||||
/* Check unused. */
|
||||
MLX5_ASSERT(!fmp->ref_cnt);
|
||||
@ -1211,5 +1595,8 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
|
||||
TAILQ_REMOVE(&priv->flow_meter_profiles, fmp, next);
|
||||
mlx5_free(fmp);
|
||||
}
|
||||
/* Delete default policy table. */
|
||||
mlx5_flow_destroy_def_policy(dev);
|
||||
mlx5_flow_destroy_mtr_drop_tbls(dev);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1180,6 +1180,7 @@ mlx5_dev_stop(struct rte_eth_dev *dev)
|
||||
mlx5_traffic_disable(dev);
|
||||
/* All RX queue flags will be cleared in the flush interface. */
|
||||
mlx5_flow_list_flush(dev, &priv->flows, true);
|
||||
mlx5_flow_meter_flush(dev, NULL);
|
||||
mlx5_rx_intr_vec_disable(dev);
|
||||
priv->sh->port[priv->dev_port - 1].ih_port_id = RTE_MAX_ETHPORTS;
|
||||
priv->sh->port[priv->dev_port - 1].devx_ih_port_id = RTE_MAX_ETHPORTS;
|
||||
|
Loading…
x
Reference in New Issue
Block a user