{
const struct rte_flow_action_sample *sample;
int actions_n = 0;
- int jump_flag = 0;
uint32_t ratio = 0;
int sub_type = 0;
int flag = 0;
if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE ||
actions->type == RTE_FLOW_ACTION_TYPE_RSS)
*qrss_action_pos = actions_n;
- if (actions->type == RTE_FLOW_ACTION_TYPE_JUMP)
- jump_flag = 1;
if (actions->type == RTE_FLOW_ACTION_TYPE_SAMPLE) {
sample = actions->conf;
ratio = sample->ratio;
}
if (flag && action == RTE_FLOW_ACTION_TYPE_SAMPLE && attr->transfer) {
if (ratio == 1) {
- /* JUMP Action not support for Mirroring;
- * Mirroring support multi-destination;
+ /* FDB mirroring uses the destination array to implement
+ * instead of FLOW_SAMPLER object.
*/
- if (!jump_flag && sub_type != RTE_FLOW_ACTION_TYPE_END)
+ if (sub_type != RTE_FLOW_ACTION_TYPE_END)
flag = 0;
}
}
*
* @param dev
* Pointer to Ethernet device.
- * @param[in] fdb_tx
- * FDB egress flow flag.
+ * @param[in] add_tag
+ * Add extra tag action flag.
* @param[out] sfx_items
* Suffix flow match items (list terminated by the END pattern item).
* @param[in] actions
*/
static int
flow_sample_split_prep(struct rte_eth_dev *dev,
- uint32_t fdb_tx,
+ int add_tag,
struct rte_flow_item sfx_items[],
const struct rte_flow_action actions[],
struct rte_flow_action actions_sfx[],
RTE_FLOW_ERROR_TYPE_ACTION,
NULL, "invalid position of sample "
"action in list");
- if (!fdb_tx) {
+ /* For CX5, add an extra tag action for NIC-RX and E-Switch ingress.
+ * For CX6DX and above, metadata registers Cx preserve their value,
+ * add an extra tag action for NIC-RX and E-Switch ingress and egress.
+ */
+ if (add_tag) {
/* Prepare the prefix tag action. */
set_tag = (void *)(actions_pre + actions_n + 1);
ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, 0, error);
memcpy(actions_pre, actions,
sizeof(struct rte_flow_action) * index);
}
- /* Add the extra tag action for NIC-RX and E-Switch ingress. */
- if (!fdb_tx) {
+ if (add_tag) {
actions_pre[index++] =
(struct rte_flow_action){
.type = (enum rte_flow_action_type)
int actions_n = 0;
int sample_action_pos;
int qrss_action_pos;
+ int add_tag = 0;
int ret = 0;
if (priv->sampler_en)
"sample flow");
/* The representor_id is -1 for uplink. */
fdb_tx = (attr->transfer && priv->representor_id != -1);
- if (!fdb_tx)
+ /*
+ * When reg_c_preserve is set, metadata registers Cx preserve
+ * their value even through packet duplication.
+ */
+ add_tag = (!fdb_tx || priv->config.hca_attr.reg_c_preserve);
+ if (add_tag)
sfx_items = (struct rte_flow_item *)((char *)sfx_actions
+ act_size);
pre_actions = sfx_actions + actions_n;
- tag_id = flow_sample_split_prep(dev, fdb_tx, sfx_items,
+ tag_id = flow_sample_split_prep(dev, add_tag, sfx_items,
actions, sfx_actions,
pre_actions, actions_n,
sample_action_pos,
qrss_action_pos, error);
- if (tag_id < 0 || (!fdb_tx && !tag_id)) {
+ if (tag_id < 0 || (add_tag && !tag_id)) {
ret = -rte_errno;
goto exit;
}
static int
flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev,
- uint32_t encap_decap_idx);
+ uint32_t encap_decap_idx);
static int
flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev,
static void
flow_dv_shared_rss_action_release(struct rte_eth_dev *dev, uint32_t srss);
+static int
+flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev,
+ uint32_t rix_jump);
+
/**
* Initialize flow attributes structure according to flow items' types.
*
(dev, &res, dev_flow, error);
}
-static int fdb_mirror;
+static int fdb_mirror_limit;
/**
* Validate the modify-header actions.
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"can't have encap action before"
" modify action");
- if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) && fdb_mirror)
+ if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) && fdb_mirror_limit)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"can't support sample action before"
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"jump with meter not support");
- if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) && fdb_mirror)
- return rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, NULL,
- "E-Switch mirroring can't support"
- " Sample action and jump action in"
- " same flow now");
if (!action->conf)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION_CONF,
uint16_t queue_index = 0xFFFF;
int actions_n = 0;
int ret;
- fdb_mirror = 0;
+ fdb_mirror_limit = 0;
if (!sample)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"E-Switch doesn't support "
"any optional action "
"for sampling");
- fdb_mirror = 1;
+ fdb_mirror_limit = 1;
if (sub_action_flags & MLX5_FLOW_ACTION_QUEUE)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION,
flow_dv_counter_free(dev, act_res->cnt);
act_res->cnt = 0;
}
+ if (act_res->rix_jump) {
+ flow_dv_jump_tbl_resource_release(dev, act_res->rix_jump);
+ act_res->rix_jump = 0;
+ }
}
int
struct mlx5dv_dr_domain *domain;
uint32_t idx = 0, res_idx = 0;
struct rte_flow_error *error = ctx->error;
+ uint64_t action_flags;
int ret;
/* Register new destination array resource. */
}
dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST;
sample_act = &resource->sample_act[idx];
- if (sample_act->action_flags == MLX5_FLOW_ACTION_QUEUE) {
+ action_flags = sample_act->action_flags;
+ switch (action_flags) {
+ case MLX5_FLOW_ACTION_QUEUE:
dest_attr[idx]->dest = sample_act->dr_queue_action;
- } else if (sample_act->action_flags ==
- (MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_ENCAP)) {
+ break;
+ case (MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_ENCAP):
dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST_REFORMAT;
dest_attr[idx]->dest_reformat = &dest_reformat[idx];
dest_attr[idx]->dest_reformat->reformat =
sample_act->dr_encap_action;
dest_attr[idx]->dest_reformat->dest =
sample_act->dr_port_id_action;
- } else if (sample_act->action_flags ==
- MLX5_FLOW_ACTION_PORT_ID) {
+ break;
+ case MLX5_FLOW_ACTION_PORT_ID:
dest_attr[idx]->dest = sample_act->dr_port_id_action;
+ break;
+ case MLX5_FLOW_ACTION_JUMP:
+ dest_attr[idx]->dest = sample_act->dr_jump_action;
+ break;
+ default:
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "unsupported actions type");
+ goto error;
}
}
/* create a dest array actioin */
!flow_dv_port_id_action_resource_release(dev,
act_res->rix_port_id_action))
act_res->rix_port_id_action = 0;
+ if (act_res->rix_jump &&
+ !flow_dv_jump_tbl_resource_release(dev,
+ act_res->rix_jump))
+ act_res->rix_jump = 0;
if (dest_attr[idx])
mlx5_free(dest_attr[idx]);
}
sample_act->dr_port_id_action =
dev_flow->dv.port_id_action->action;
}
+ if (sample_act->action_flags & MLX5_FLOW_ACTION_JUMP) {
+ normal_idx++;
+ mdest_res->sample_idx[dest_index].rix_jump =
+ dev_flow->handle->rix_jump;
+ sample_act->dr_jump_action =
+ dev_flow->dv.jump->action;
+ dev_flow->handle->rix_jump = 0;
+ }
sample_act->actions_num = normal_idx;
/* update sample action resource into first index of array */
mdest_res->ft_type = res->ft_type;
dev_flow->dv.jump->action;
action_flags |= MLX5_FLOW_ACTION_JUMP;
dev_flow->handle->fate_action = MLX5_FLOW_FATE_JUMP;
+ sample_act->action_flags |= MLX5_FLOW_ACTION_JUMP;
+ num_of_dest++;
break;
case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
* So need remove the original these actions in the flow and only
* use the sample action instead of.
*/
- if (num_of_dest > 1 && sample_act->dr_port_id_action) {
+ if (num_of_dest > 1 &&
+ (sample_act->dr_port_id_action || sample_act->dr_jump_action)) {
int i;
void *temp_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
dev_flow->dv.actions[i]) ||
(sample_act->dr_port_id_action &&
sample_act->dr_port_id_action ==
+ dev_flow->dv.actions[i]) ||
+ (sample_act->dr_jump_action &&
+ sample_act->dr_jump_action ==
dev_flow->dv.actions[i]))
continue;
temp_actions[tmp_actions_n++] = dev_flow->dv.actions[i];
*
* @param dev
* Pointer to Ethernet device.
- * @param handle
- * Pointer to mlx5_flow_handle.
+ * @param port_id
+ * Index to port ID action resource.
*
* @return
* 1 while a reference on it exists, 0 when freed.
*
* @param dev
* Pointer to Ethernet device.
- * @param handle
- * Pointer to mlx5_flow_handle.
+ * @param rix_jump
+ * Index to the jump action resource.
*
* @return
* 1 while a reference on it exists, 0 when freed.
*/
static int
flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev,
- struct mlx5_flow_handle *handle)
+ uint32_t rix_jump)
{
struct mlx5_priv *priv = dev->data->dev_private;
struct mlx5_flow_tbl_data_entry *tbl_data;
tbl_data = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_JUMP],
- handle->rix_jump);
+ rix_jump);
if (!tbl_data)
return 0;
return flow_dv_tbl_resource_release(MLX5_SH(dev), &tbl_data->tbl);
mlx5_hrxq_release(dev, handle->rix_hrxq);
break;
case MLX5_FLOW_FATE_JUMP:
- flow_dv_jump_tbl_resource_release(dev, handle);
+ flow_dv_jump_tbl_resource_release(dev, handle->rix_jump);
break;
case MLX5_FLOW_FATE_PORT_ID:
flow_dv_port_id_action_resource_release(dev,