@@ -1545,7 +1545,8 @@ static rte_be32_t vlan_hdr_to_be32(const struct rte_flow_action *actions)
static __rte_always_inline struct mlx5_aso_mtr *
flow_hw_meter_mark_alloc(struct rte_eth_dev *dev, uint32_t queue,
const struct rte_flow_action *action,
- void *user_data, bool push)
+ void *user_data, bool push,
+ struct rte_flow_error *error)
{
struct mlx5_priv *priv = dev->data->dev_private;
struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
@@ -1554,6 +1555,11 @@ flow_hw_meter_mark_alloc(struct rte_eth_dev *dev, uint32_t queue,
struct mlx5_flow_meter_info *fm;
uint32_t mtr_id;
+ if (priv->shared_host) {
+ rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Meter mark actions can only be created on the host port");
+ return NULL;
+ }
if (meter_mark->profile == NULL)
return NULL;
aso_mtr = mlx5_ipool_malloc(priv->hws_mpool->idx_pool, &mtr_id);
@@ -1592,13 +1598,14 @@ flow_hw_meter_mark_compile(struct rte_eth_dev *dev,
const struct rte_flow_action *action,
struct mlx5dr_rule_action *acts,
uint32_t *index,
- uint32_t queue)
+ uint32_t queue,
+ struct rte_flow_error *error)
{
struct mlx5_priv *priv = dev->data->dev_private;
struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
struct mlx5_aso_mtr *aso_mtr;
- aso_mtr = flow_hw_meter_mark_alloc(dev, queue, action, NULL, true);
+ aso_mtr = flow_hw_meter_mark_alloc(dev, queue, action, NULL, true, error);
if (!aso_mtr)
return -1;
@@ -2474,7 +2481,8 @@ __flow_hw_actions_translate(struct rte_eth_dev *dev,
dr_pos, actions,
acts->rule_acts,
&acts->mtr_id,
- MLX5_HW_INV_QUEUE);
+ MLX5_HW_INV_QUEUE,
+ error);
if (err)
goto err;
} else if (__flow_hw_act_data_general_append(priv, acts,
@@ -3197,7 +3205,8 @@ flow_hw_actions_construct(struct rte_eth_dev *dev,
*/
ret = flow_hw_meter_mark_compile(dev,
act_data->action_dst, action,
- rule_acts, &job->flow->mtr_id, MLX5_HW_INV_QUEUE);
+ rule_acts, &job->flow->mtr_id,
+ MLX5_HW_INV_QUEUE, error);
if (ret != 0)
return ret;
break;
@@ -5322,6 +5331,8 @@ flow_hw_validate_action_count(struct rte_eth_dev *dev,
* Pointer to rte_eth_dev structure.
* @param[in] action
* Pointer to the indirect action.
+ * @param[in] indirect
+ * If true, then provided action was passed using an indirect action.
* @param[out] error
* Pointer to error structure.
*
@@ -5331,6 +5342,7 @@ flow_hw_validate_action_count(struct rte_eth_dev *dev,
static int
flow_hw_validate_action_meter_mark(struct rte_eth_dev *dev,
const struct rte_flow_action *action,
+ bool indirect,
struct rte_flow_error *error)
{
struct mlx5_priv *priv = dev->data->dev_private;
@@ -5341,6 +5353,9 @@ flow_hw_validate_action_meter_mark(struct rte_eth_dev *dev,
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"meter_mark action not supported");
+ if (!indirect && priv->shared_host)
+ return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, action,
+ "meter_mark action can only be used on host port");
if (!priv->hws_mpool)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -5384,7 +5399,7 @@ flow_hw_validate_action_indirect(struct rte_eth_dev *dev,
type = mask->type;
switch (type) {
case RTE_FLOW_ACTION_TYPE_METER_MARK:
- ret = flow_hw_validate_action_meter_mark(dev, mask, error);
+ ret = flow_hw_validate_action_meter_mark(dev, mask, true, error);
if (ret < 0)
return ret;
*action_flags |= MLX5_FLOW_ACTION_METER;
@@ -5841,8 +5856,7 @@ mlx5_flow_hw_actions_validate(struct rte_eth_dev *dev,
action_flags |= MLX5_FLOW_ACTION_METER;
break;
case RTE_FLOW_ACTION_TYPE_METER_MARK:
- ret = flow_hw_validate_action_meter_mark(dev, action,
- error);
+ ret = flow_hw_validate_action_meter_mark(dev, action, false, error);
if (ret < 0)
return ret;
action_flags |= MLX5_FLOW_ACTION_METER;
@@ -10138,7 +10152,7 @@ flow_hw_action_handle_validate(struct rte_eth_dev *dev, uint32_t queue,
"CT pool not initialized");
return mlx5_validate_action_ct(dev, action->conf, error);
case RTE_FLOW_ACTION_TYPE_METER_MARK:
- return flow_hw_validate_action_meter_mark(dev, action, error);
+ return flow_hw_validate_action_meter_mark(dev, action, true, error);
case RTE_FLOW_ACTION_TYPE_RSS:
return flow_dv_action_validate(dev, conf, action, error);
case RTE_FLOW_ACTION_TYPE_QUOTA:
@@ -10297,7 +10311,7 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
break;
case RTE_FLOW_ACTION_TYPE_METER_MARK:
aso = true;
- aso_mtr = flow_hw_meter_mark_alloc(dev, queue, action, job, push);
+ aso_mtr = flow_hw_meter_mark_alloc(dev, queue, action, job, push, error);
if (!aso_mtr)
break;
mtr_id = (MLX5_INDIRECT_ACTION_TYPE_METER_MARK <<
@@ -17,11 +17,32 @@
#ifdef HAVE_MLX5_HWS_SUPPORT
+static void
+mlx5_flow_meter_uninit_guest(struct rte_eth_dev *dev)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+
+ if (priv->hws_mpool) {
+ if (priv->hws_mpool->action) {
+ claim_zero(mlx5dr_action_destroy(priv->hws_mpool->action));
+ priv->hws_mpool->action = NULL;
+ }
+ priv->hws_mpool->devx_obj = NULL;
+ priv->hws_mpool->idx_pool = NULL;
+ mlx5_free(priv->hws_mpool);
+ priv->hws_mpool = NULL;
+ }
+}
+
void
mlx5_flow_meter_uninit(struct rte_eth_dev *dev)
{
struct mlx5_priv *priv = dev->data->dev_private;
+ if (priv->shared_host) {
+ mlx5_flow_meter_uninit_guest(dev);
+ return;
+ }
if (priv->mtr_policy_arr) {
mlx5_free(priv->mtr_policy_arr);
priv->mtr_policy_arr = NULL;
@@ -52,6 +73,54 @@ mlx5_flow_meter_uninit(struct rte_eth_dev *dev)
}
}
+static int
+mlx5_flow_meter_init_guest(struct rte_eth_dev *dev)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct rte_eth_dev *host_dev = priv->shared_host;
+ struct mlx5_priv *host_priv = host_dev->data->dev_private;
+ int reg_id = 0;
+ uint32_t flags;
+ int ret = 0;
+
+ MLX5_ASSERT(priv->shared_host);
+ reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
+ if (reg_id < 0) {
+ rte_errno = ENOMEM;
+ ret = -rte_errno;
+ DRV_LOG(ERR, "Meter register is not available.");
+ goto err;
+ }
+ priv->hws_mpool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_aso_mtr_pool),
+ RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
+ if (!priv->hws_mpool) {
+ rte_errno = ENOMEM;
+ ret = -rte_errno;
+ DRV_LOG(ERR, "Meter ipool allocation failed.");
+ goto err;
+ }
+ MLX5_ASSERT(host_priv->hws_mpool->idx_pool);
+ MLX5_ASSERT(host_priv->hws_mpool->devx_obj);
+ priv->hws_mpool->idx_pool = host_priv->hws_mpool->idx_pool;
+ priv->hws_mpool->devx_obj = host_priv->hws_mpool->devx_obj;
+ flags = MLX5DR_ACTION_FLAG_HWS_RX | MLX5DR_ACTION_FLAG_HWS_TX;
+ if (priv->sh->config.dv_esw_en && priv->master)
+ flags |= MLX5DR_ACTION_FLAG_HWS_FDB;
+ priv->hws_mpool->action = mlx5dr_action_create_aso_meter
+ (priv->dr_ctx, (struct mlx5dr_devx_obj *)priv->hws_mpool->devx_obj,
+ reg_id - REG_C_0, flags);
+ if (!priv->hws_mpool->action) {
+ rte_errno = ENOMEM;
+ ret = -rte_errno;
+ DRV_LOG(ERR, "Meter action creation failed.");
+ goto err;
+ }
+ return 0;
+err:
+ mlx5_flow_meter_uninit(dev);
+ return ret;
+}
+
int
mlx5_flow_meter_init(struct rte_eth_dev *dev,
uint32_t nb_meters,
@@ -81,6 +150,8 @@ mlx5_flow_meter_init(struct rte_eth_dev *dev,
.type = "mlx5_hw_mtr_mark_action",
};
+ if (priv->shared_host)
+ return mlx5_flow_meter_init_guest(dev);
if (!nb_meters) {
ret = ENOTSUP;
rte_flow_error_set(&error, ENOMEM,
@@ -850,6 +921,9 @@ mlx5_flow_meter_profile_hws_add(struct rte_eth_dev *dev,
struct mlx5_flow_meter_profile *fmp;
int ret;
+ if (priv->shared_host)
+ return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Meter profiles cannot be created on guest port");
if (!priv->mtr_profile_arr)
return mlx5_flow_meter_profile_add(dev, meter_profile_id, profile, error);
/* Check input params. */
@@ -887,6 +961,9 @@ mlx5_flow_meter_profile_hws_delete(struct rte_eth_dev *dev,
struct mlx5_priv *priv = dev->data->dev_private;
struct mlx5_flow_meter_profile *fmp;
+ if (priv->shared_host)
+ return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Meter profiles cannot be destroyed through guest port");
if (!priv->mtr_profile_arr)
return mlx5_flow_meter_profile_delete(dev, meter_profile_id, error);
/* Meter profile must exist. */