static int
mlx5_flow_item_field_width(struct mlx5_priv *priv,
- enum rte_flow_field_id field)
+ enum rte_flow_field_id field, int inherit)
{
switch (field) {
case RTE_FLOW_FIELD_START:
return __builtin_popcount(priv->sh->dv_meta_mask);
case RTE_FLOW_FIELD_POINTER:
case RTE_FLOW_FIELD_VALUE:
- return 64;
+ return inherit < 0 ? 0 : inherit;
default:
MLX5_ASSERT(false);
}
static void
mlx5_flow_field_id_to_modify_info
(const struct rte_flow_action_modify_data *data,
- struct field_modify_info *info,
- uint32_t *mask, uint32_t *value,
- uint32_t width, uint32_t dst_width,
- uint32_t *shift, struct rte_eth_dev *dev,
- const struct rte_flow_attr *attr,
- struct rte_flow_error *error)
+ struct field_modify_info *info, uint32_t *mask,
+ uint32_t width, uint32_t *shift, struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr, struct rte_flow_error *error)
{
struct mlx5_priv *priv = dev->data->dev_private;
uint32_t idx = 0;
uint32_t off = 0;
- uint64_t val = 0;
+
switch (data->field) {
case RTE_FLOW_FIELD_START:
/* not supported yet */
off = data->offset > 16 ? data->offset - 16 : 0;
if (mask) {
if (data->offset < 16) {
- info[idx] = (struct field_modify_info){2, 0,
+ info[idx] = (struct field_modify_info){2, 4,
MLX5_MODI_OUT_DMAC_15_0};
if (width < 16) {
mask[idx] = rte_cpu_to_be_16(0xffff >>
break;
++idx;
}
- info[idx] = (struct field_modify_info){4, 4 * idx,
+ info[idx] = (struct field_modify_info){4, 0,
MLX5_MODI_OUT_DMAC_47_16};
mask[idx] = rte_cpu_to_be_32((0xffffffff >>
(32 - width)) << off);
} else {
if (data->offset < 16)
- info[idx++] = (struct field_modify_info){2, 0,
+ info[idx++] = (struct field_modify_info){2, 4,
MLX5_MODI_OUT_DMAC_15_0};
- info[idx] = (struct field_modify_info){4, off,
+ info[idx] = (struct field_modify_info){4, 0,
MLX5_MODI_OUT_DMAC_47_16};
}
break;
off = data->offset > 16 ? data->offset - 16 : 0;
if (mask) {
if (data->offset < 16) {
- info[idx] = (struct field_modify_info){2, 0,
+ info[idx] = (struct field_modify_info){2, 4,
MLX5_MODI_OUT_SMAC_15_0};
if (width < 16) {
mask[idx] = rte_cpu_to_be_16(0xffff >>
break;
++idx;
}
- info[idx] = (struct field_modify_info){4, 4 * idx,
+ info[idx] = (struct field_modify_info){4, 0,
MLX5_MODI_OUT_SMAC_47_16};
mask[idx] = rte_cpu_to_be_32((0xffffffff >>
(32 - width)) << off);
} else {
if (data->offset < 16)
- info[idx++] = (struct field_modify_info){2, 0,
+ info[idx++] = (struct field_modify_info){2, 4,
MLX5_MODI_OUT_SMAC_15_0};
- info[idx] = (struct field_modify_info){4, off,
+ info[idx] = (struct field_modify_info){4, 0,
MLX5_MODI_OUT_SMAC_47_16};
}
break;
case RTE_FLOW_FIELD_IPV6_SRC:
if (mask) {
if (data->offset < 32) {
- info[idx] = (struct field_modify_info){4,
- 4 * idx,
+ info[idx] = (struct field_modify_info){4, 12,
MLX5_MODI_OUT_SIPV6_31_0};
if (width < 32) {
mask[idx] =
++idx;
}
if (data->offset < 64) {
- info[idx] = (struct field_modify_info){4,
- 4 * idx,
+ info[idx] = (struct field_modify_info){4, 8,
MLX5_MODI_OUT_SIPV6_63_32};
if (width < 32) {
mask[idx] =
++idx;
}
if (data->offset < 96) {
- info[idx] = (struct field_modify_info){4,
- 4 * idx,
+ info[idx] = (struct field_modify_info){4, 4,
MLX5_MODI_OUT_SIPV6_95_64};
if (width < 32) {
mask[idx] =
break;
++idx;
}
- info[idx] = (struct field_modify_info){4, 4 * idx,
+ info[idx] = (struct field_modify_info){4, 0,
MLX5_MODI_OUT_SIPV6_127_96};
mask[idx] = rte_cpu_to_be_32(0xffffffff >>
(32 - width));
} else {
if (data->offset < 32)
- info[idx++] = (struct field_modify_info){4, 0,
+ info[idx++] = (struct field_modify_info){4, 12,
MLX5_MODI_OUT_SIPV6_31_0};
if (data->offset < 64)
- info[idx++] = (struct field_modify_info){4, 0,
+ info[idx++] = (struct field_modify_info){4, 8,
MLX5_MODI_OUT_SIPV6_63_32};
if (data->offset < 96)
- info[idx++] = (struct field_modify_info){4, 0,
+ info[idx++] = (struct field_modify_info){4, 4,
MLX5_MODI_OUT_SIPV6_95_64};
if (data->offset < 128)
info[idx++] = (struct field_modify_info){4, 0,
case RTE_FLOW_FIELD_IPV6_DST:
if (mask) {
if (data->offset < 32) {
- info[idx] = (struct field_modify_info){4,
- 4 * idx,
+ info[idx] = (struct field_modify_info){4, 12,
MLX5_MODI_OUT_DIPV6_31_0};
if (width < 32) {
mask[idx] =
++idx;
}
if (data->offset < 64) {
- info[idx] = (struct field_modify_info){4,
- 4 * idx,
+ info[idx] = (struct field_modify_info){4, 8,
MLX5_MODI_OUT_DIPV6_63_32};
if (width < 32) {
mask[idx] =
++idx;
}
if (data->offset < 96) {
- info[idx] = (struct field_modify_info){4,
- 4 * idx,
+ info[idx] = (struct field_modify_info){4, 4,
MLX5_MODI_OUT_DIPV6_95_64};
if (width < 32) {
mask[idx] =
break;
++idx;
}
- info[idx] = (struct field_modify_info){4, 4 * idx,
+ info[idx] = (struct field_modify_info){4, 0,
MLX5_MODI_OUT_DIPV6_127_96};
mask[idx] = rte_cpu_to_be_32(0xffffffff >>
(32 - width));
} else {
if (data->offset < 32)
- info[idx++] = (struct field_modify_info){4, 0,
+ info[idx++] = (struct field_modify_info){4, 12,
MLX5_MODI_OUT_DIPV6_31_0};
if (data->offset < 64)
- info[idx++] = (struct field_modify_info){4, 0,
+ info[idx++] = (struct field_modify_info){4, 8,
MLX5_MODI_OUT_DIPV6_63_32};
if (data->offset < 96)
- info[idx++] = (struct field_modify_info){4, 0,
+ info[idx++] = (struct field_modify_info){4, 4,
MLX5_MODI_OUT_DIPV6_95_64};
if (data->offset < 128)
info[idx++] = (struct field_modify_info){4, 0,
break;
case RTE_FLOW_FIELD_POINTER:
case RTE_FLOW_FIELD_VALUE:
- if (data->field == RTE_FLOW_FIELD_POINTER)
- memcpy(&val, (void *)(uintptr_t)data->value,
- sizeof(uint64_t));
- else
- val = data->value;
- for (idx = 0; idx < MLX5_ACT_MAX_MOD_FIELDS; idx++) {
- if (mask[idx]) {
- if (dst_width == 48) {
- /*special case for MAC addresses */
- value[idx] = rte_cpu_to_be_16(val);
- val >>= 16;
- dst_width -= 16;
- } else if (dst_width > 16) {
- value[idx] = rte_cpu_to_be_32(val);
- val >>= 32;
- } else if (dst_width > 8) {
- value[idx] = rte_cpu_to_be_16(val);
- val >>= 16;
- } else {
- value[idx] = (uint8_t)val;
- val >>= 8;
- }
- if (*shift)
- value[idx] <<= *shift;
- if (!val)
- break;
- }
- }
- break;
default:
MLX5_ASSERT(false);
break;
const struct rte_flow_attr *attr,
struct rte_flow_error *error)
{
- struct mlx5_priv *priv = dev->data->dev_private;
const struct rte_flow_action_modify_field *conf =
(const struct rte_flow_action_modify_field *)(action->conf);
- struct rte_flow_item item;
+ struct rte_flow_item item = {
+ .spec = NULL,
+ .mask = NULL
+ };
struct field_modify_info field[MLX5_ACT_MAX_MOD_FIELDS] = {
{0, 0, 0} };
struct field_modify_info dcopy[MLX5_ACT_MAX_MOD_FIELDS] = {
{0, 0, 0} };
uint32_t mask[MLX5_ACT_MAX_MOD_FIELDS] = {0, 0, 0, 0, 0};
- uint32_t value[MLX5_ACT_MAX_MOD_FIELDS] = {0, 0, 0, 0, 0};
uint32_t type;
uint32_t shift = 0;
- uint32_t dst_width = mlx5_flow_item_field_width(priv, conf->dst.field);
if (conf->src.field == RTE_FLOW_FIELD_POINTER ||
- conf->src.field == RTE_FLOW_FIELD_VALUE) {
+ conf->src.field == RTE_FLOW_FIELD_VALUE) {
type = MLX5_MODIFICATION_TYPE_SET;
/** For SET fill the destination field (field) first. */
mlx5_flow_field_id_to_modify_info(&conf->dst, field, mask,
- value, conf->width, dst_width,
- &shift, dev, attr, error);
- /** Then copy immediate value from source as per mask. */
- mlx5_flow_field_id_to_modify_info(&conf->src, dcopy, mask,
- value, conf->width, dst_width,
- &shift, dev, attr, error);
- item.spec = &value;
+ conf->width, &shift, dev,
+ attr, error);
+ item.spec = conf->src.field == RTE_FLOW_FIELD_POINTER ?
+ (void *)(uintptr_t)conf->src.pvalue :
+ (void *)(uintptr_t)&conf->src.value;
} else {
type = MLX5_MODIFICATION_TYPE_COPY;
/** For COPY fill the destination field (dcopy) without mask. */
mlx5_flow_field_id_to_modify_info(&conf->dst, dcopy, NULL,
- value, conf->width, dst_width,
- &shift, dev, attr, error);
+ conf->width, &shift, dev,
+ attr, error);
/** Then construct the source field (field) with mask. */
mlx5_flow_field_id_to_modify_info(&conf->src, field, mask,
- value, conf->width, dst_width,
- &shift, dev, attr, error);
+ conf->width, &shift,
+ dev, attr, error);
}
item.mask = &mask;
return flow_dv_convert_modify_action(&item,
{
const struct rte_flow_item_gtp *gtp_spec;
const struct rte_flow_item_gtp *gtp_mask;
- const struct rte_flow_item_gtp_psc *spec;
const struct rte_flow_item_gtp_psc *mask;
const struct rte_flow_item_gtp_psc nic_mask = {
- .pdu_type = 0xFF,
- .qfi = 0xFF,
+ .hdr.type = 0xF,
+ .hdr.qfi = 0x3F,
};
if (!gtp_item || !(last_item & MLX5_FLOW_LAYER_GTP))
/* GTP spec is here and E flag is requested to match zero. */
if (!item->spec)
return 0;
- spec = item->spec;
mask = item->mask ? item->mask : &rte_flow_item_gtp_psc_mask;
- if (spec->pdu_type > MLX5_GTP_EXT_MAX_PDU_TYPE)
- return rte_flow_error_set
- (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
- "PDU type should be smaller than 16");
return mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
(const uint8_t *)&nic_mask,
sizeof(struct rte_flow_item_gtp_psc),
return 0;
}
-/**
- * Check if action counter is shared by either old or new mechanism.
- *
- * @param[in] action
- * Pointer to the action structure.
- *
- * @return
- * True when counter is shared, false otherwise.
- */
-static inline bool
-is_shared_action_count(const struct rte_flow_action *action)
-{
- const struct rte_flow_action_count *count =
- (const struct rte_flow_action_count *)action->conf;
-
- if ((int)action->type == MLX5_RTE_FLOW_ACTION_TYPE_COUNT)
- return true;
- return !!(count && count->shared);
-}
-
/**
* Validate count action.
*
const struct rte_flow_action_modify_field *action_modify_field =
action->conf;
uint32_t dst_width = mlx5_flow_item_field_width(priv,
- action_modify_field->dst.field);
+ action_modify_field->dst.field, -1);
uint32_t src_width = mlx5_flow_item_field_width(priv,
- action_modify_field->src.field);
+ action_modify_field->src.field, dst_width);
ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
if (ret)
}
/*
- * Validate the port_id action.
+ * Validate action PORT_ID / REPRESENTED_PORT.
*
* @param[in] dev
* Pointer to rte_eth_dev structure.
* @param[in] action_flags
* Bit-fields that holds the actions detected until now.
* @param[in] action
- * Port_id RTE action structure.
+ * PORT_ID / REPRESENTED_PORT action structure.
* @param[in] attr
* Attributes of flow that includes this action.
* @param[out] error
struct rte_flow_error *error)
{
const struct rte_flow_action_port_id *port_id;
+ const struct rte_flow_action_ethdev *ethdev;
struct mlx5_priv *act_priv;
struct mlx5_priv *dev_priv;
uint16_t port;
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL,
- "port id action is valid in transfer"
+ "port action is valid in transfer"
" mode only");
if (!action || !action->conf)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION_CONF,
NULL,
- "port id action parameters must be"
+ "port action parameters must be"
" specified");
if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
MLX5_FLOW_FATE_ESWITCH_ACTIONS))
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL,
"failed to obtain E-Switch info");
- port_id = action->conf;
- port = port_id->original ? dev->data->port_id : port_id->id;
+ switch (action->type) {
+ case RTE_FLOW_ACTION_TYPE_PORT_ID:
+ port_id = action->conf;
+ port = port_id->original ? dev->data->port_id : port_id->id;
+ break;
+ case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
+ ethdev = action->conf;
+ port = ethdev->port_id;
+ break;
+ default:
+ MLX5_ASSERT(false);
+ return rte_flow_error_set
+ (error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, action,
+ "unknown E-Switch action");
+ }
act_priv = mlx5_port_to_eswitch_info(port, false);
if (!act_priv)
return rte_flow_error_set
(error, rte_errno,
- RTE_FLOW_ERROR_TYPE_ACTION_CONF, port_id,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF, action->conf,
"failed to obtain E-Switch port id for port");
if (act_priv->domain_id != dev_priv->domain_id)
return rte_flow_error_set
break;
case RTE_FLOW_ACTION_TYPE_COUNT:
ret = flow_dv_validate_action_count
- (dev, is_shared_action_count(act),
- *action_flags | sub_action_flags,
+ (dev, false, *action_flags | sub_action_flags,
error);
if (ret < 0)
return ret;
++actions_n;
break;
case RTE_FLOW_ACTION_TYPE_PORT_ID:
+ case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
ret = flow_dv_validate_action_port_id(dev,
sub_action_flags,
act,
return 0;
}
-/**
- * Allocate a shared flow counter.
- *
- * @param[in] ctx
- * Pointer to the shared counter configuration.
- * @param[in] data
- * Pointer to save the allocated counter index.
- *
- * @return
- * Index to flow counter on success, 0 otherwise and rte_errno is set.
- */
-
-static int32_t
-flow_dv_counter_alloc_shared_cb(void *ctx, union mlx5_l3t_data *data)
-{
- struct mlx5_shared_counter_conf *conf = ctx;
- struct rte_eth_dev *dev = conf->dev;
- struct mlx5_flow_counter *cnt;
-
- data->dword = flow_dv_counter_alloc(dev, 0);
- data->dword |= MLX5_CNT_SHARED_OFFSET;
- cnt = flow_dv_counter_get_by_idx(dev, data->dword, NULL);
- cnt->shared_info.id = conf->id;
- return 0;
-}
-
-/**
- * Get a shared flow counter.
- *
- * @param[in] dev
- * Pointer to the Ethernet device structure.
- * @param[in] id
- * Counter identifier.
- *
- * @return
- * Index to flow counter on success, 0 otherwise and rte_errno is set.
- */
-static uint32_t
-flow_dv_counter_get_shared(struct rte_eth_dev *dev, uint32_t id)
-{
- struct mlx5_priv *priv = dev->data->dev_private;
- struct mlx5_shared_counter_conf conf = {
- .dev = dev,
- .id = id,
- };
- union mlx5_l3t_data data = {
- .dword = 0,
- };
-
- mlx5_l3t_prepare_entry(priv->sh->cnt_id_tbl, id, &data,
- flow_dv_counter_alloc_shared_cb, &conf);
- return data.dword;
-}
-
/**
* Get age param from counter index.
*
if (pool->is_aged) {
flow_dv_counter_remove_from_age(dev, counter, cnt);
} else {
- /*
- * If the counter action is shared by ID, the l3t_clear_entry
- * function reduces its references counter. If after the
- * reduction the action is still referenced, the function
- * returns here and does not release it.
- */
- if (IS_LEGACY_SHARED_CNT(counter) &&
- mlx5_l3t_clear_entry(priv->sh->cnt_id_tbl,
- cnt->shared_info.id))
- return;
/*
* If the counter action is shared by indirect action API,
* the atomic function reduces its references counter.
* If after the reduction the action is still referenced, the
* function returns here and does not release it.
- * When the counter action is not shared neither by ID nor by
+ * When the counter action is not shared by
* indirect action API, shared info is 1 before the reduction,
* so this condition is failed and function doesn't return here.
*/
- if (!IS_LEGACY_SHARED_CNT(counter) &&
- __atomic_sub_fetch(&cnt->shared_info.refcnt, 1,
+ if (__atomic_sub_fetch(&cnt->shared_info.refcnt, 1,
__ATOMIC_RELAXED))
return;
}
case RTE_FLOW_ACTION_TYPE_VOID:
break;
case RTE_FLOW_ACTION_TYPE_PORT_ID:
+ case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
ret = flow_dv_validate_action_port_id(dev,
action_flags,
actions,
++actions_n;
break;
case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
+ shared_count = true;
+ /* fall-through. */
case RTE_FLOW_ACTION_TYPE_COUNT:
- shared_count = is_shared_action_count(actions);
ret = flow_dv_validate_action_count(dev, shared_count,
action_flags,
error);
if (!gtp_psc_m)
gtp_psc_m = &rte_flow_item_gtp_psc_mask;
dw_0.w32 = 0;
- dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_m->pdu_type);
- dw_0.qfi = gtp_psc_m->qfi;
+ dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_m->hdr.type);
+ dw_0.qfi = gtp_psc_m->hdr.qfi;
MLX5_SET(fte_match_set_misc3, misc3_m, gtpu_first_ext_dw_0,
rte_cpu_to_be_32(dw_0.w32));
dw_0.w32 = 0;
- dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_v->pdu_type &
- gtp_psc_m->pdu_type);
- dw_0.qfi = gtp_psc_v->qfi & gtp_psc_m->qfi;
+ dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_v->hdr.type &
+ gtp_psc_m->hdr.type);
+ dw_0.qfi = gtp_psc_v->hdr.qfi & gtp_psc_m->hdr.qfi;
MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_first_ext_dw_0,
rte_cpu_to_be_32(dw_0.w32));
}
}
/**
- * Translate port ID action to vport.
+ * Translate action PORT_ID / REPRESENTED_PORT to vport.
*
* @param[in] dev
* Pointer to rte_eth_dev structure.
* @param[in] action
- * Pointer to the port ID action.
+ * Pointer to action PORT_ID / REPRESENTED_PORT.
* @param[out] dst_port_id
* The target port ID.
* @param[out] error
{
uint32_t port;
struct mlx5_priv *priv;
- const struct rte_flow_action_port_id *conf =
- (const struct rte_flow_action_port_id *)action->conf;
- port = conf->original ? dev->data->port_id : conf->id;
+ switch (action->type) {
+ case RTE_FLOW_ACTION_TYPE_PORT_ID: {
+ const struct rte_flow_action_port_id *conf;
+
+ conf = (const struct rte_flow_action_port_id *)action->conf;
+ port = conf->original ? dev->data->port_id : conf->id;
+ break;
+ }
+ case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: {
+ const struct rte_flow_action_ethdev *ethdev;
+
+ ethdev = (const struct rte_flow_action_ethdev *)action->conf;
+ port = ethdev->port_id;
+ break;
+ }
+ default:
+ MLX5_ASSERT(false);
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, action,
+ "unknown E-Switch action");
+ }
+
priv = mlx5_port_to_eswitch_info(port, false);
if (!priv)
return rte_flow_error_set(error, -rte_errno,
static uint32_t
flow_dv_translate_create_counter(struct rte_eth_dev *dev,
struct mlx5_flow *dev_flow,
- const struct rte_flow_action_count *count,
+ const struct rte_flow_action_count *count
+ __rte_unused,
const struct rte_flow_action_age *age)
{
uint32_t counter;
struct mlx5_age_param *age_param;
- if (count && count->shared)
- counter = flow_dv_counter_get_shared(dev, count->id);
- else
- counter = flow_dv_counter_alloc(dev, !!age);
+ counter = flow_dv_counter_alloc(dev, !!age);
if (!counter || age == NULL)
return counter;
age_param = flow_dv_counter_idx_get_age(dev, counter);
break;
}
case RTE_FLOW_ACTION_TYPE_PORT_ID:
+ case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
{
struct mlx5_flow_dv_port_id_action_resource
port_id_resource;
}
static inline int
-flow_dv_aso_ct_release(struct rte_eth_dev *dev, uint32_t own_idx)
+flow_dv_aso_ct_release(struct rte_eth_dev *dev, uint32_t own_idx,
+ struct rte_flow_error *error)
{
uint16_t owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(own_idx);
uint32_t idx = MLX5_INDIRECT_ACT_CT_GET_IDX(own_idx);
struct rte_eth_dev *owndev = &rte_eth_devices[owner];
- RTE_SET_USED(dev);
+ int ret;
MLX5_ASSERT(owner < RTE_MAX_ETHPORTS);
if (dev->data->dev_started != 1)
- return -1;
- return flow_dv_aso_ct_dev_release(owndev, idx);
+ return rte_flow_error_set(error, EAGAIN,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "Indirect CT action cannot be destroyed when the port is stopped");
+ ret = flow_dv_aso_ct_dev_release(owndev, idx);
+ if (ret < 0)
+ return rte_flow_error_set(error, EAGAIN,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "Current state prevents indirect CT action from being destroyed");
+ return ret;
}
/*
case RTE_FLOW_ACTION_TYPE_VOID:
break;
case RTE_FLOW_ACTION_TYPE_PORT_ID:
+ case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
if (flow_dv_translate_action_port_id(dev, action,
&port_id, error))
return -rte_errno;
MLX5_FLOW_FATE_QUEUE;
break;
case MLX5_RTE_FLOW_ACTION_TYPE_AGE:
- flow->age = (uint32_t)(uintptr_t)(action->conf);
- age_act = flow_aso_age_get_by_idx(dev, flow->age);
- __atomic_fetch_add(&age_act->refcnt, 1,
- __ATOMIC_RELAXED);
+ owner_idx = (uint32_t)(uintptr_t)action->conf;
+ age_act = flow_aso_age_get_by_idx(dev, owner_idx);
+ if (flow->age == 0) {
+ flow->age = owner_idx;
+ __atomic_fetch_add(&age_act->refcnt, 1,
+ __ATOMIC_RELAXED);
+ }
age_act_pos = actions_n++;
action_flags |= MLX5_FLOW_ACTION_AGE;
break;
action_flags |= MLX5_FLOW_ACTION_AGE;
break;
case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
- cnt_act = flow_dv_counter_get_by_idx(dev,
- (uint32_t)(uintptr_t)action->conf,
- NULL);
+ owner_idx = (uint32_t)(uintptr_t)action->conf;
+ cnt_act = flow_dv_counter_get_by_idx(dev, owner_idx,
+ NULL);
MLX5_ASSERT(cnt_act != NULL);
/**
* When creating meter drop flow in drop table, the
dev_flow->dv.actions[actions_n++] =
cnt_act->action;
} else {
- flow->counter =
- (uint32_t)(uintptr_t)(action->conf);
- __atomic_fetch_add(&cnt_act->shared_info.refcnt,
- 1, __ATOMIC_RELAXED);
+ if (flow->counter == 0) {
+ flow->counter = owner_idx;
+ __atomic_fetch_add
+ (&cnt_act->shared_info.refcnt,
+ 1, __ATOMIC_RELAXED);
+ }
/* Save information first, will apply later. */
action_flags |= MLX5_FLOW_ACTION_COUNT;
}
else
dev_flow->dv.actions[actions_n] =
ct->dr_action_rply;
- flow->indirect_type = MLX5_INDIRECT_ACTION_TYPE_CT;
- flow->ct = owner_idx;
- __atomic_fetch_add(&ct->refcnt, 1, __ATOMIC_RELAXED);
+ if (flow->ct == 0) {
+ flow->indirect_type =
+ MLX5_INDIRECT_ACTION_TYPE_CT;
+ flow->ct = owner_idx;
+ __atomic_fetch_add(&ct->refcnt, 1,
+ __ATOMIC_RELAXED);
+ }
actions_n++;
action_flags |= MLX5_FLOW_ACTION_CT;
break;
* when they are not shared.
*/
if (action_flags & MLX5_FLOW_ACTION_AGE) {
- if ((non_shared_age &&
- count && !count->shared) ||
+ if ((non_shared_age && count) ||
!(priv->sh->flow_hit_aso_en &&
(attr->group || attr->transfer))) {
/* Creates age by counters. */
}
/* Keep the current age handling by default. */
if (flow->indirect_type == MLX5_INDIRECT_ACTION_TYPE_CT && flow->ct)
- flow_dv_aso_ct_release(dev, flow->ct);
+ flow_dv_aso_ct_release(dev, flow->ct, NULL);
else if (flow->age)
flow_dv_aso_age_release(dev, flow->age);
if (flow->geneve_tlv_option) {
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"invalid shared action");
- remaining = __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
- if (remaining)
- return rte_flow_error_set(error, EBUSY,
- RTE_FLOW_ERROR_TYPE_ACTION,
- NULL,
- "shared rss hrxq has references");
if (!__atomic_compare_exchange_n(&shared_rss->refcnt, &old_refcnt,
0, 0, __ATOMIC_ACQUIRE,
__ATOMIC_RELAXED))
RTE_FLOW_ERROR_TYPE_ACTION,
NULL,
"shared rss has references");
+ remaining = __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
+ if (remaining)
+ return rte_flow_error_set(error, EBUSY,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "shared rss hrxq has references");
queue = shared_rss->ind_tbl->queues;
remaining = mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl, true);
if (remaining)
" released with references %d.", idx, ret);
return 0;
case MLX5_INDIRECT_ACTION_TYPE_CT:
- ret = flow_dv_aso_ct_release(dev, idx);
+ ret = flow_dv_aso_ct_release(dev, idx, error);
if (ret < 0)
return ret;
if (ret > 0)
policy->act_cnt[i].fate_action == MLX5_FLOW_FATE_MTR)
next_fm = mlx5_flow_meter_find(priv,
policy->act_cnt[i].next_mtr_id, NULL);
- TAILQ_FOREACH_SAFE(color_rule, &sub_policy->color_rules[i],
+ RTE_TAILQ_FOREACH_SAFE(color_rule, &sub_policy->color_rules[i],
next_port, tmp) {
claim_zero(mlx5_flow_os_destroy_flow(color_rule->rule));
tbl = container_of(color_rule->matcher->tbl,
break;
}
case RTE_FLOW_ACTION_TYPE_PORT_ID:
+ case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
{
struct mlx5_flow_dv_port_id_action_resource
port_id_resource;
"Indirect age action not supported");
return flow_dv_validate_action_age(0, action, dev, err);
case RTE_FLOW_ACTION_TYPE_COUNT:
- /*
- * There are two mechanisms to share the action count.
- * The old mechanism uses the shared field to share, while the
- * new mechanism uses the indirect action API.
- * This validation comes to make sure that the two mechanisms
- * are not combined.
- */
- if (is_shared_action_count(action))
- return rte_flow_error_set(err, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ACTION,
- NULL,
- "Mix shared and indirect counter is not supported");
return flow_dv_validate_action_count(dev, true, 0, err);
case RTE_FLOW_ACTION_TYPE_CONNTRACK:
if (!priv->sh->ct_aso_en)
NULL, "too many actions");
switch (act->type) {
case RTE_FLOW_ACTION_TYPE_PORT_ID:
+ case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
if (!priv->config.dv_esw_en)
return -rte_mtr_error_set(error,
ENOTSUP,