net/mlx5: expose flow counters management

Expose the flow counter management mechanism for other components to
use.

Signed-off-by: Suanming Mou <suanmingm@mellanox.com>
Acked-by: Matan Azrad <matan@mellanox.com>
This commit is contained in:
Suanming Mou 2019-11-08 05:49:18 +02:00 committed by Ferruh Yigit
parent 63ffeb2ff2
commit e189f55cd2
4 changed files with 166 additions and 0 deletions

View File

@ -959,6 +959,10 @@ void mlx5_flow_async_pool_query_handle(struct mlx5_ibv_shared *sh,
uint64_t async_id, int status);
void mlx5_set_query_alarm(struct mlx5_ibv_shared *sh);
void mlx5_flow_query_alarm(void *arg);
struct mlx5_flow_counter *mlx5_counter_alloc(struct rte_eth_dev *dev);
void mlx5_counter_free(struct rte_eth_dev *dev, struct mlx5_flow_counter *cnt);
int mlx5_counter_query(struct rte_eth_dev *dev, struct mlx5_flow_counter *cnt,
bool clear, uint64_t *pkts, uint64_t *bytes);
/* mlx5_mp.c */
void mlx5_mp_req_start_rxtx(struct rte_eth_dev *dev);

View File

@ -4996,6 +4996,89 @@ mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,
return fops->destroy_policer_rules(dev, fm, attr);
}
/**
* Allocate a counter.
*
* @param[in] dev
* Pointer to Ethernet device structure.
*
* @return
* Pointer to allocated counter on success, NULL otherwise.
*/
struct mlx5_flow_counter *
mlx5_counter_alloc(struct rte_eth_dev *dev)
{
const struct mlx5_flow_driver_ops *fops;
struct rte_flow_attr attr = { .transfer = 0 };
if (flow_get_drv_type(dev, &attr) == MLX5_FLOW_TYPE_DV) {
fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
return fops->counter_alloc(dev);
}
DRV_LOG(ERR,
"port %u counter allocate is not supported.",
dev->data->port_id);
return NULL;
}
/**
* Free a counter.
*
* @param[in] dev
* Pointer to Ethernet device structure.
* @param[in] cnt
* Pointer to counter to be free.
*/
void
mlx5_counter_free(struct rte_eth_dev *dev, struct mlx5_flow_counter *cnt)
{
const struct mlx5_flow_driver_ops *fops;
struct rte_flow_attr attr = { .transfer = 0 };
if (flow_get_drv_type(dev, &attr) == MLX5_FLOW_TYPE_DV) {
fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
fops->counter_free(dev, cnt);
return;
}
DRV_LOG(ERR,
"port %u counter free is not supported.",
dev->data->port_id);
}
/**
* Query counter statistics.
*
* @param[in] dev
* Pointer to Ethernet device structure.
* @param[in] cnt
* Pointer to counter to query.
* @param[in] clear
* Set to clear counter statistics.
* @param[out] pkts
* The counter hits packets number to save.
* @param[out] bytes
* The counter hits bytes number to save.
*
* @return
* 0 on success, a negative errno value otherwise.
*/
int
mlx5_counter_query(struct rte_eth_dev *dev, struct mlx5_flow_counter *cnt,
bool clear, uint64_t *pkts, uint64_t *bytes)
{
const struct mlx5_flow_driver_ops *fops;
struct rte_flow_attr attr = { .transfer = 0 };
if (flow_get_drv_type(dev, &attr) == MLX5_FLOW_TYPE_DV) {
fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
return fops->counter_query(dev, cnt, clear, pkts, bytes);
}
DRV_LOG(ERR,
"port %u counter query is not supported.",
dev->data->port_id);
return -ENOTSUP;
}
#define MLX5_POOL_QUERY_FREQ_US 1000000
/**

View File

@ -664,6 +664,14 @@ typedef int (*mlx5_flow_destroy_policer_rules_t)
(struct rte_eth_dev *dev,
const struct mlx5_flow_meter *fm,
const struct rte_flow_attr *attr);
typedef struct mlx5_flow_counter * (*mlx5_flow_counter_alloc_t)
(struct rte_eth_dev *dev);
typedef void (*mlx5_flow_counter_free_t)(struct rte_eth_dev *dev,
struct mlx5_flow_counter *cnt);
typedef int (*mlx5_flow_counter_query_t)(struct rte_eth_dev *dev,
struct mlx5_flow_counter *cnt,
bool clear, uint64_t *pkts,
uint64_t *bytes);
struct mlx5_flow_driver_ops {
mlx5_flow_validate_t validate;
mlx5_flow_prepare_t prepare;
@ -676,6 +684,9 @@ struct mlx5_flow_driver_ops {
mlx5_flow_destroy_mtr_tbls_t destroy_mtr_tbls;
mlx5_flow_create_policer_rules_t create_policer_rules;
mlx5_flow_destroy_policer_rules_t destroy_policer_rules;
mlx5_flow_counter_alloc_t counter_alloc;
mlx5_flow_counter_free_t counter_free;
mlx5_flow_counter_query_t counter_query;
};

View File

@ -8005,6 +8005,46 @@ error:
return -1;
}
/**
* Query a devx counter.
*
* @param[in] dev
* Pointer to the Ethernet device structure.
* @param[in] cnt
* Pointer to the flow counter.
* @param[in] clear
* Set to clear the counter statistics.
* @param[out] pkts
* The statistics value of packets.
* @param[out] bytes
* The statistics value of bytes.
*
* @return
* 0 on success, otherwise return -1.
*/
static int
flow_dv_counter_query(struct rte_eth_dev *dev,
struct mlx5_flow_counter *cnt, bool clear,
uint64_t *pkts, uint64_t *bytes)
{
struct mlx5_priv *priv = dev->data->dev_private;
uint64_t inn_pkts, inn_bytes;
int ret;
if (!priv->config.devx)
return -1;
ret = _flow_dv_query_count(dev, cnt, &inn_pkts, &inn_bytes);
if (ret)
return -1;
*pkts = inn_pkts - cnt->hits;
*bytes = inn_bytes - cnt->bytes;
if (clear) {
cnt->hits = inn_pkts;
cnt->bytes = inn_bytes;
}
return 0;
}
/*
* Mutex-protected thunk to lock-free __flow_dv_translate().
*/
@ -8062,6 +8102,31 @@ flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
flow_dv_shared_unlock(dev);
}
/*
* Mutex-protected thunk to lock-free flow_dv_counter_alloc().
*/
static struct mlx5_flow_counter *
flow_dv_counter_allocate(struct rte_eth_dev *dev)
{
struct mlx5_flow_counter *cnt;
flow_dv_shared_lock(dev);
cnt = flow_dv_counter_alloc(dev, 0, 0, 1);
flow_dv_shared_unlock(dev);
return cnt;
}
/*
* Mutex-protected thunk to lock-free flow_dv_counter_release().
*/
static void
flow_dv_counter_free(struct rte_eth_dev *dev, struct mlx5_flow_counter *cnt)
{
flow_dv_shared_lock(dev);
flow_dv_counter_release(dev, cnt);
flow_dv_shared_unlock(dev);
}
const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {
.validate = flow_dv_validate,
.prepare = flow_dv_prepare,
@ -8074,6 +8139,9 @@ const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {
.destroy_mtr_tbls = flow_dv_destroy_mtr_tbl,
.create_policer_rules = flow_dv_create_policer_rules,
.destroy_policer_rules = flow_dv_destroy_policer_rules,
.counter_alloc = flow_dv_counter_allocate,
.counter_free = flow_dv_counter_free,
.counter_query = flow_dv_counter_query,
};
#endif /* HAVE_IBV_FLOW_DV_SUPPORT */