break;
case RTE_FLOW_FIELD_TCP_FLAGS:
info[idx] = (struct field_modify_info){1, 0,
- MLX5_MODI_IN_TCP_FLAGS};
+ MLX5_MODI_OUT_TCP_FLAGS};
if (mask) {
mask[idx] = 0x0000003f;
if (width < 6)
"isn't supported");
if (reg != REG_A)
nic_mask.data = priv->sh->dv_meta_mask;
- } else if (attr->transfer) {
- return rte_flow_error_set(error, ENOTSUP,
+ } else {
+ if (attr->transfer)
+ return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ITEM, item,
"extended metadata feature "
"should be enabled when "
"meta item is requested "
"with e-switch mode ");
+ if (attr->ingress)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "match on metadata for ingress "
+ "is not supported in legacy "
+ "metadata mode");
}
if (!mask)
mask = &rte_flow_item_meta_mask;
*
* @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;
}
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"invalid shared action to update");
+ if (priv->obj_ops.ind_table_modify == NULL)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "cannot modify indirection table");
queue = mlx5_malloc(MLX5_MEM_ZERO,
RTE_ALIGN_CEIL(queue_size, sizeof(void *)),
0, SOCKET_ID_ANY);
RTE_SET_USED(conf);
switch (action->type) {
case RTE_FLOW_ACTION_TYPE_RSS:
+ /*
+ * priv->obj_ops is set according to driver capabilities.
+ * When DevX capabilities are
+ * sufficient, it is set to devx_obj_ops.
+ * Otherwise, it is set to ibv_obj_ops.
+ * ibv_obj_ops doesn't support ind_table_modify operation.
+ * In this case the shared RSS action can't be used.
+ */
+ if (priv->obj_ops.ind_table_modify == NULL)
+ return rte_flow_error_set
+ (err, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "shared RSS action not supported");
return mlx5_validate_action_rss(dev, action, err);
case RTE_FLOW_ACTION_TYPE_AGE:
if (!priv->sh->aso_age_mng)