*
* @param[in] dev
* Pointer to rte_eth_dev structure.
+ * @param[in] action
+ * Pointer to the action structure.
* @param[in] action_flags
* Holds the actions detected until now.
* @param[out] error
*/
static int
flow_dv_validate_action_count(struct rte_eth_dev *dev,
+ const struct rte_flow_action *action,
uint64_t action_flags,
struct rte_flow_error *error)
{
struct mlx5_priv *priv = dev->data->dev_private;
+ const struct rte_flow_action_count *count;
+ if (!priv->config.devx)
+ goto notsup_err;
if (action_flags & MLX5_FLOW_ACTION_COUNT)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"duplicate count actions set");
- if (!priv->config.devx)
- goto notsup_err;
+ count = (const struct rte_flow_action_count *)action->conf;
+ if (count && count->shared && (action_flags & MLX5_FLOW_ACTION_AGE) &&
+ !priv->sh->flow_hit_aso_en)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "old age and shared count combination is not supported");
#ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
return 0;
#endif
* Pointer to the RSS action.
* @param[out] sample_rss
* Pointer to the RSS action in sample action list.
+ * @param[out] count
+ * Pointer to the COUNT action in sample action list.
+ * @param[out] fdb_mirror_limit
+ * Pointer to the FDB mirror limitation flag.
* @param[out] error
* Pointer to error structure.
*
uint64_t item_flags,
const struct rte_flow_action_rss *rss,
const struct rte_flow_action_rss **sample_rss,
+ const struct rte_flow_action_count **count,
+ int *fdb_mirror_limit,
struct rte_flow_error *error)
{
struct mlx5_priv *priv = dev->data->dev_private;
++actions_n;
break;
case RTE_FLOW_ACTION_TYPE_COUNT:
- if (*action_flags & MLX5_FLOW_ACTION_COUNT)
- return rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION,
- action,
- "duplicate count action set");
- ret = flow_dv_validate_action_count(dev,
- sub_action_flags,
- error);
+ ret = flow_dv_validate_action_count
+ (dev, act,
+ *action_flags | sub_action_flags,
+ error);
if (ret < 0)
return ret;
+ *count = act->conf;
sub_action_flags |= MLX5_FLOW_ACTION_COUNT;
*action_flags |= MLX5_FLOW_ACTION_COUNT;
++actions_n;
NULL,
"E-Switch must has a dest "
"port for mirroring");
+ if (!priv->config.hca_attr.reg_c_preserve &&
+ priv->representor_id != -1)
+ *fdb_mirror_limit = 1;
}
/* Continue validation for Xcap actions.*/
if ((sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) &&
uint16_t ether_type = 0;
int actions_n = 0;
uint8_t item_ipv6_proto = 0;
+ int fdb_mirror_limit = 0;
+ int modify_after_mirror = 0;
const struct rte_flow_item *geneve_item = NULL;
const struct rte_flow_item *gre_item = NULL;
const struct rte_flow_item *gtp_item = NULL;
const struct rte_flow_action_raw_encap *encap;
const struct rte_flow_action_rss *rss = NULL;
const struct rte_flow_action_rss *sample_rss = NULL;
+ const struct rte_flow_action_count *count = NULL;
+ const struct rte_flow_action_count *sample_count = NULL;
const struct rte_flow_item_tcp nic_tcp_mask = {
.hdr = {
.tcp_flags = 0xFF,
++actions_n;
action_flags |= MLX5_FLOW_ACTION_FLAG |
MLX5_FLOW_ACTION_MARK_EXT;
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+ modify_after_mirror = 1;
+
} else {
action_flags |= MLX5_FLOW_ACTION_FLAG;
++actions_n;
++actions_n;
action_flags |= MLX5_FLOW_ACTION_MARK |
MLX5_FLOW_ACTION_MARK_EXT;
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+ modify_after_mirror = 1;
} else {
action_flags |= MLX5_FLOW_ACTION_MARK;
++actions_n;
/* Count all modify-header actions as one action. */
if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
++actions_n;
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+ modify_after_mirror = 1;
action_flags |= MLX5_FLOW_ACTION_SET_META;
rw_act_num += MLX5_ACT_NUM_SET_META;
break;
/* Count all modify-header actions as one action. */
if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
++actions_n;
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+ modify_after_mirror = 1;
action_flags |= MLX5_FLOW_ACTION_SET_TAG;
rw_act_num += MLX5_ACT_NUM_SET_TAG;
break;
++actions_n;
break;
case RTE_FLOW_ACTION_TYPE_COUNT:
- ret = flow_dv_validate_action_count(dev, action_flags,
+ ret = flow_dv_validate_action_count(dev, actions,
+ action_flags,
error);
if (ret < 0)
return ret;
+ count = actions->conf;
action_flags |= MLX5_FLOW_ACTION_COUNT;
++actions_n;
break;
RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ?
MLX5_FLOW_ACTION_SET_MAC_SRC :
MLX5_FLOW_ACTION_SET_MAC_DST;
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+ modify_after_mirror = 1;
/*
* Even if the source and destination MAC addresses have
* overlap in the header with 4B alignment, the convert
/* Count all modify-header actions as one action. */
if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
++actions_n;
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+ modify_after_mirror = 1;
action_flags |= actions->type ==
RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ?
MLX5_FLOW_ACTION_SET_IPV4_SRC :
/* Count all modify-header actions as one action. */
if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
++actions_n;
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+ modify_after_mirror = 1;
action_flags |= actions->type ==
RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ?
MLX5_FLOW_ACTION_SET_IPV6_SRC :
/* Count all modify-header actions as one action. */
if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
++actions_n;
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+ modify_after_mirror = 1;
action_flags |= actions->type ==
RTE_FLOW_ACTION_TYPE_SET_TP_SRC ?
MLX5_FLOW_ACTION_SET_TP_SRC :
/* Count all modify-header actions as one action. */
if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
++actions_n;
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+ modify_after_mirror = 1;
action_flags |= actions->type ==
RTE_FLOW_ACTION_TYPE_SET_TTL ?
MLX5_FLOW_ACTION_SET_TTL :
error);
if (ret)
return ret;
+ if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) &&
+ fdb_mirror_limit)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "sample and jump action combination is not supported");
++actions_n;
action_flags |= MLX5_FLOW_ACTION_JUMP;
break;
/* Count all modify-header actions as one action. */
if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
++actions_n;
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+ modify_after_mirror = 1;
action_flags |= actions->type ==
RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ ?
MLX5_FLOW_ACTION_INC_TCP_SEQ :
/* Count all modify-header actions as one action. */
if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
++actions_n;
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+ modify_after_mirror = 1;
action_flags |= actions->type ==
RTE_FLOW_ACTION_TYPE_INC_TCP_ACK ?
MLX5_FLOW_ACTION_INC_TCP_ACK :
error);
if (ret < 0)
return ret;
+ /*
+ * Validate the regular AGE action (using counter)
+ * mutual exclusion with share counter actions.
+ */
+ if (!priv->sh->flow_hit_aso_en) {
+ if (count && count->shared)
+ return rte_flow_error_set
+ (error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "old age and shared count combination is not supported");
+ if (sample_count)
+ return rte_flow_error_set
+ (error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "old age action and count must be in the same sub flow");
+ }
action_flags |= MLX5_FLOW_ACTION_AGE;
++actions_n;
break;
/* Count all modify-header actions as one action. */
if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
++actions_n;
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+ modify_after_mirror = 1;
action_flags |= MLX5_FLOW_ACTION_SET_IPV4_DSCP;
rw_act_num += MLX5_ACT_NUM_SET_DSCP;
break;
/* Count all modify-header actions as one action. */
if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
++actions_n;
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+ modify_after_mirror = 1;
action_flags |= MLX5_FLOW_ACTION_SET_IPV6_DSCP;
rw_act_num += MLX5_ACT_NUM_SET_DSCP;
break;
actions, dev,
attr, item_flags,
rss, &sample_rss,
+ &sample_count,
+ &fdb_mirror_limit,
error);
if (ret < 0)
return ret;
NULL, "too many header modify"
" actions to support");
}
+ /* Eswitch egress mirror and modify flow has limitation on CX5 */
+ if (fdb_mirror_limit && modify_after_mirror)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "sample before modify action is not supported");
return 0;
}
*/
static int
__flow_dv_action_rss_hrxqs_release(struct rte_eth_dev *dev,
- struct mlx5_shared_action_rss *action)
+ struct mlx5_shared_action_rss *shared_rss)
{
- return __flow_dv_hrxqs_release(dev, &action->hrxq) +
- __flow_dv_hrxqs_release(dev, &action->hrxq_tunnel);
+ return __flow_dv_hrxqs_release(dev, &shared_rss->hrxq) +
+ __flow_dv_hrxqs_release(dev, &shared_rss->hrxq_tunnel);
}
/**
static int
__flow_dv_action_rss_setup(struct rte_eth_dev *dev,
uint32_t action_idx,
- struct mlx5_shared_action_rss *action,
+ struct mlx5_shared_action_rss *shared_rss,
struct rte_flow_error *error)
{
struct mlx5_flow_rss_desc rss_desc = { 0 };
size_t i;
int err;
- if (mlx5_ind_table_obj_setup(dev, action->ind_tbl)) {
+ if (mlx5_ind_table_obj_setup(dev, shared_rss->ind_tbl)) {
return rte_flow_error_set(error, rte_errno,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
"cannot setup indirection table");
}
- memcpy(rss_desc.key, action->origin.key, MLX5_RSS_HASH_KEY_LEN);
+ memcpy(rss_desc.key, shared_rss->origin.key, MLX5_RSS_HASH_KEY_LEN);
rss_desc.key_len = MLX5_RSS_HASH_KEY_LEN;
- rss_desc.const_q = action->origin.queue;
- rss_desc.queue_num = action->origin.queue_num;
+ rss_desc.const_q = shared_rss->origin.queue;
+ rss_desc.queue_num = shared_rss->origin.queue_num;
/* Set non-zero value to indicate a shared RSS. */
rss_desc.shared_rss = action_idx;
- rss_desc.ind_tbl = action->ind_tbl;
+ rss_desc.ind_tbl = shared_rss->ind_tbl;
for (i = 0; i < MLX5_RSS_HASH_FIELDS_LEN; i++) {
uint32_t hrxq_idx;
uint64_t hash_fields = mlx5_rss_hash_fields[i];
goto error_hrxq_new;
}
err = __flow_dv_action_rss_hrxq_set
- (action, hash_fields, tunnel, hrxq_idx);
+ (shared_rss, hash_fields, tunnel, hrxq_idx);
MLX5_ASSERT(!err);
}
}
return 0;
error_hrxq_new:
err = rte_errno;
- __flow_dv_action_rss_hrxqs_release(dev, action);
- if (!mlx5_ind_table_obj_release(dev, action->ind_tbl, true))
- action->ind_tbl = NULL;
+ __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
+ if (!mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl, true))
+ shared_rss->ind_tbl = NULL;
rte_errno = err;
return -rte_errno;
}
struct rte_flow_error *error)
{
struct mlx5_priv *priv = dev->data->dev_private;
- struct mlx5_shared_action_rss *shared_action = NULL;
+ struct mlx5_shared_action_rss *shared_rss = NULL;
void *queue = NULL;
struct rte_flow_action_rss *origin;
const uint8_t *rss_key;
RTE_SET_USED(conf);
queue = mlx5_malloc(0, RTE_ALIGN_CEIL(queue_size, sizeof(void *)),
0, SOCKET_ID_ANY);
- shared_action = mlx5_ipool_zmalloc
+ shared_rss = mlx5_ipool_zmalloc
(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], &idx);
- if (!shared_action || !queue) {
+ if (!shared_rss || !queue) {
rte_flow_error_set(error, ENOMEM,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
"cannot allocate resource memory");
"rss action number out of range");
goto error_rss_init;
}
- shared_action->ind_tbl = mlx5_malloc(MLX5_MEM_ZERO,
- sizeof(*shared_action->ind_tbl),
- 0, SOCKET_ID_ANY);
- if (!shared_action->ind_tbl) {
+ shared_rss->ind_tbl = mlx5_malloc(MLX5_MEM_ZERO,
+ sizeof(*shared_rss->ind_tbl),
+ 0, SOCKET_ID_ANY);
+ if (!shared_rss->ind_tbl) {
rte_flow_error_set(error, ENOMEM,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
"cannot allocate resource memory");
goto error_rss_init;
}
memcpy(queue, rss->queue, queue_size);
- shared_action->ind_tbl->queues = queue;
- shared_action->ind_tbl->queues_n = rss->queue_num;
- origin = &shared_action->origin;
+ shared_rss->ind_tbl->queues = queue;
+ shared_rss->ind_tbl->queues_n = rss->queue_num;
+ origin = &shared_rss->origin;
origin->func = rss->func;
origin->level = rss->level;
/* RSS type 0 indicates default RSS type (ETH_RSS_IP). */
origin->types = !rss->types ? ETH_RSS_IP : rss->types;
/* NULL RSS key indicates default RSS key. */
rss_key = !rss->key ? rss_hash_default_key : rss->key;
- memcpy(shared_action->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
- origin->key = &shared_action->key[0];
+ memcpy(shared_rss->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
+ origin->key = &shared_rss->key[0];
origin->key_len = MLX5_RSS_HASH_KEY_LEN;
origin->queue = queue;
origin->queue_num = rss->queue_num;
- if (__flow_dv_action_rss_setup(dev, idx, shared_action, error))
+ if (__flow_dv_action_rss_setup(dev, idx, shared_rss, error))
goto error_rss_init;
- rte_spinlock_init(&shared_action->action_rss_sl);
- __atomic_add_fetch(&shared_action->refcnt, 1, __ATOMIC_RELAXED);
+ rte_spinlock_init(&shared_rss->action_rss_sl);
+ __atomic_add_fetch(&shared_rss->refcnt, 1, __ATOMIC_RELAXED);
rte_spinlock_lock(&priv->shared_act_sl);
ILIST_INSERT(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
- &priv->rss_shared_actions, idx, shared_action, next);
+ &priv->rss_shared_actions, idx, shared_rss, next);
rte_spinlock_unlock(&priv->shared_act_sl);
return idx;
error_rss_init:
- if (shared_action) {
- if (shared_action->ind_tbl)
- mlx5_free(shared_action->ind_tbl);
+ if (shared_rss) {
+ if (shared_rss->ind_tbl)
+ mlx5_free(shared_rss->ind_tbl);
mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
idx);
}
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))
+ return rte_flow_error_set(error, EBUSY,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "shared rss has references");
queue = shared_rss->ind_tbl->queues;
remaining = mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl, true);
if (remaining)
NULL,
"shared rss indirection table has"
" references");
- if (!__atomic_compare_exchange_n(&shared_rss->refcnt, &old_refcnt,
- 0, 0, __ATOMIC_ACQUIRE,
- __ATOMIC_RELAXED))
- return rte_flow_error_set(error, EBUSY,
- RTE_FLOW_ERROR_TYPE_ACTION,
- NULL,
- "shared rss has references");
mlx5_free(queue);
rte_spinlock_lock(&priv->shared_act_sl);
ILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],