#include <rte_common.h>
#include <rte_ether.h>
-#include <rte_ethdev_driver.h>
+#include <ethdev_driver.h>
#include <rte_flow.h>
#include <rte_flow_driver.h>
#include <rte_malloc.h>
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.
*
const struct rte_flow_action_mark *mark = action->conf;
int ret;
+ if (is_tunnel_offload_active(dev))
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "no mark action "
+ "if tunnel offload active");
/* Fall back if no extended metadata register support. */
if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY)
return mlx5_flow_validate_action_mark(action, action_flags,
(dev, &res, dev_flow, error);
}
-static int fdb_mirror;
-
/**
* 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)
- return rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, NULL,
- "can't support sample action before"
- " modify action for E-Switch"
- " mirroring");
return 0;
}
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,
* Attributes of flow that includes this action.
* @param[in] item_flags
* Holds the items detected.
+ * @param[in] rss
+ * Pointer to the RSS action.
+ * @param[out] sample_rss
+ * Pointer to the RSS action in sample action list.
* @param[out] error
* Pointer to error structure.
*
const struct rte_flow_action *action,
struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
- const uint64_t item_flags,
+ uint64_t item_flags,
+ const struct rte_flow_action_rss *rss,
+ const struct rte_flow_action_rss **sample_rss,
struct rte_flow_error *error)
{
struct mlx5_priv *priv = dev->data->dev_private;
uint16_t queue_index = 0xFFFF;
int actions_n = 0;
int ret;
- fdb_mirror = 0;
if (!sample)
return rte_flow_error_set(error, EINVAL,
sub_action_flags |= MLX5_FLOW_ACTION_QUEUE;
++actions_n;
break;
+ case RTE_FLOW_ACTION_TYPE_RSS:
+ *sample_rss = act->conf;
+ ret = mlx5_flow_validate_action_rss(act,
+ sub_action_flags,
+ dev, attr,
+ item_flags,
+ error);
+ if (ret < 0)
+ return ret;
+ if (rss && *sample_rss &&
+ ((*sample_rss)->level != rss->level ||
+ (*sample_rss)->types != rss->types))
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "Can't use the different RSS types "
+ "or level in the same flow");
+ if (*sample_rss != NULL && (*sample_rss)->queue_num)
+ queue_index = (*sample_rss)->queue[0];
+ sub_action_flags |= MLX5_FLOW_ACTION_RSS;
+ ++actions_n;
+ break;
case RTE_FLOW_ACTION_TYPE_MARK:
ret = flow_dv_validate_action_mark(dev, act,
sub_action_flags,
}
}
if (attr->ingress && !attr->transfer) {
- if (!(sub_action_flags & MLX5_FLOW_ACTION_QUEUE))
+ if (!(sub_action_flags & (MLX5_FLOW_ACTION_QUEUE |
+ MLX5_FLOW_ACTION_RSS)))
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
NULL,
"E-Switch doesn't support "
"any optional action "
"for sampling");
- fdb_mirror = 1;
if (sub_action_flags & MLX5_FLOW_ACTION_QUEUE)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION,
NULL,
"unsupported action QUEUE");
+ if (sub_action_flags & MLX5_FLOW_ACTION_RSS)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "unsupported action QUEUE");
if (!(sub_action_flags & MLX5_FLOW_ACTION_PORT_ID))
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
struct rte_flow_error *error)
{
struct mlx5_priv *priv = dev->data->dev_private;
- uint32_t priority_max = priv->config.flow_prio - 1;
+ uint32_t lowest_priority = mlx5_get_lowest_priority(dev, attributes);
int ret = 0;
#ifndef HAVE_MLX5DV_DR
if (!table)
ret = MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL;
#endif
- if (attributes->priority != MLX5_FLOW_PRIO_RSVD &&
- attributes->priority >= priority_max)
+ if (attributes->priority != MLX5_FLOW_LOWEST_PRIO_INDICATOR &&
+ attributes->priority > lowest_priority)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
NULL,
const struct rte_flow_item *gtp_item = NULL;
const struct rte_flow_action_raw_decap *decap;
const struct rte_flow_action_raw_encap *encap;
- const struct rte_flow_action_rss *rss;
+ const struct rte_flow_action_rss *rss = NULL;
+ const struct rte_flow_action_rss *sample_rss = NULL;
const struct rte_flow_item_tcp nic_tcp_mask = {
.hdr = {
.tcp_flags = 0xFF,
error);
if (ret < 0)
return ret;
+ if (rss && sample_rss &&
+ (sample_rss->level != rss->level ||
+ sample_rss->types != rss->types))
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "Can't use the different RSS types "
+ "or level in the same flow");
if (rss != NULL && rss->queue_num)
queue_index = rss->queue[0];
action_flags |= MLX5_FLOW_ACTION_RSS;
ret = flow_dv_validate_action_sample(action_flags,
actions, dev,
attr, item_flags,
+ rss, &sample_rss,
error);
if (ret < 0)
return ret;
* Validate the drop action mutual exclusion with other actions.
* Drop action is mutually-exclusive with any other action, except for
* Count action.
+ * Drop action compatibility with tunnel offload was already validated.
*/
- if ((action_flags & MLX5_FLOW_ACTION_DROP) &&
+ if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_MATCH |
+ MLX5_FLOW_ACTION_TUNNEL_MATCH));
+ else if ((action_flags & MLX5_FLOW_ACTION_DROP) &&
(action_flags & ~(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_COUNT)))
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
return ret;
}
+/**
+ * Add Geneve TLV option item to matcher.
+ *
+ * @param[in, out] dev
+ * Pointer to rte_eth_dev structure.
+ * @param[in, out] matcher
+ * Flow matcher.
+ * @param[in, out] key
+ * Flow matcher value.
+ * @param[in] item
+ * Flow pattern to translate.
+ * @param[out] error
+ * Pointer to error structure.
+ */
+static int
+flow_dv_translate_item_geneve_opt(struct rte_eth_dev *dev, void *matcher,
+ void *key, const struct rte_flow_item *item,
+ struct rte_flow_error *error)
+{
+ const struct rte_flow_item_geneve_opt *geneve_opt_m = item->mask;
+ const struct rte_flow_item_geneve_opt *geneve_opt_v = item->spec;
+ void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+ void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+ void *misc3_m = MLX5_ADDR_OF(fte_match_param, matcher,
+ misc_parameters_3);
+ void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
+ rte_be32_t opt_data_key = 0, opt_data_mask = 0;
+ int ret = 0;
+
+ if (!geneve_opt_v)
+ return -1;
+ if (!geneve_opt_m)
+ geneve_opt_m = &rte_flow_item_geneve_opt_mask;
+ ret = flow_dev_geneve_tlv_option_resource_register(dev, item,
+ error);
+ if (ret) {
+ DRV_LOG(ERR, "Failed to create geneve_tlv_obj");
+ return ret;
+ }
+ /*
+ * Set the option length in GENEVE header if not requested.
+ * The GENEVE TLV option length is expressed by the option length field
+ * in the GENEVE header.
+ * If the option length was not requested but the GENEVE TLV option item
+ * is present we set the option length field implicitly.
+ */
+ if (!MLX5_GET16(fte_match_set_misc, misc_m, geneve_opt_len)) {
+ MLX5_SET(fte_match_set_misc, misc_m, geneve_opt_len,
+ MLX5_GENEVE_OPTLEN_MASK);
+ MLX5_SET(fte_match_set_misc, misc_v, geneve_opt_len,
+ geneve_opt_v->option_len + 1);
+ }
+ /* Set the data. */
+ if (geneve_opt_v->data) {
+ memcpy(&opt_data_key, geneve_opt_v->data,
+ RTE_MIN((uint32_t)(geneve_opt_v->option_len * 4),
+ sizeof(opt_data_key)));
+ MLX5_ASSERT((uint32_t)(geneve_opt_v->option_len * 4) <=
+ sizeof(opt_data_key));
+ memcpy(&opt_data_mask, geneve_opt_m->data,
+ RTE_MIN((uint32_t)(geneve_opt_v->option_len * 4),
+ sizeof(opt_data_mask)));
+ MLX5_ASSERT((uint32_t)(geneve_opt_v->option_len * 4) <=
+ sizeof(opt_data_mask));
+ MLX5_SET(fte_match_set_misc3, misc3_m,
+ geneve_tlv_option_0_data,
+ rte_be_to_cpu_32(opt_data_mask));
+ MLX5_SET(fte_match_set_misc3, misc3_v,
+ geneve_tlv_option_0_data,
+ rte_be_to_cpu_32(opt_data_key & opt_data_mask));
+ }
+ return ret;
+}
+
/**
* Add MPLS item to matcher and to the value.
*
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
"for sample");
goto error;
}
- int ret;
-
cache_resource->normal_path_tbl = tbl;
if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {
- ret = mlx5_flow_os_create_flow_action_default_miss
- (&cache_resource->default_miss);
- if (!ret) {
+ if (!sh->default_miss_action) {
rte_flow_error_set(error, ENOMEM,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL,
- "cannot create default miss "
- "action");
+ "default miss action was not "
+ "created");
goto error;
}
sample_dv_actions[resource->sample_act.actions_num++] =
- cache_resource->default_miss;
+ sh->default_miss_action;
}
/* Create a DR sample action */
sampler_attr.sample_ratio = cache_resource->ratio;
cache_resource->dev = dev;
return &cache_resource->entry;
error:
- if (cache_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB &&
- cache_resource->default_miss)
- claim_zero(mlx5_flow_os_destroy_flow_action
- (cache_resource->default_miss));
- else
+ if (cache_resource->ft_type != MLX5DV_FLOW_TABLE_TYPE_FDB)
flow_dv_sample_sub_actions_release(dev,
&cache_resource->sample_idx);
if (cache_resource->normal_path_tbl)
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]);
}
* @param[in] dev
* Pointer to rte_eth_dev structure.
* @param[in] action
- * Pointer to action structure.
+ * Pointer to sample action structure.
* @param[in, out] dev_flow
* Pointer to the mlx5_flow.
* @param[in] attr
*/
static int
flow_dv_translate_action_sample(struct rte_eth_dev *dev,
- const struct rte_flow_action *action,
+ const struct rte_flow_action_sample *action,
struct mlx5_flow *dev_flow,
const struct rte_flow_attr *attr,
uint32_t *num_of_dest,
struct rte_flow_error *error)
{
struct mlx5_priv *priv = dev->data->dev_private;
- const struct rte_flow_action_sample *sample_action;
const struct rte_flow_action *sub_actions;
- const struct rte_flow_action_queue *queue;
struct mlx5_flow_sub_actions_list *sample_act;
struct mlx5_flow_sub_actions_idx *sample_idx;
struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
rss_desc = &wks->rss_desc;
sample_act = &res->sample_act;
sample_idx = &res->sample_idx;
- sample_action = (const struct rte_flow_action_sample *)action->conf;
- res->ratio = sample_action->ratio;
- sub_actions = sample_action->actions;
+ res->ratio = action->ratio;
+ sub_actions = action->actions;
for (; sub_actions->type != RTE_FLOW_ACTION_TYPE_END; sub_actions++) {
int type = sub_actions->type;
uint32_t pre_rix = 0;
switch (type) {
case RTE_FLOW_ACTION_TYPE_QUEUE:
{
+ const struct rte_flow_action_queue *queue;
struct mlx5_hrxq *hrxq;
uint32_t hrxq_idx;
MLX5_FLOW_FATE_QUEUE;
break;
}
+ case RTE_FLOW_ACTION_TYPE_RSS:
+ {
+ struct mlx5_hrxq *hrxq;
+ uint32_t hrxq_idx;
+ const struct rte_flow_action_rss *rss;
+ const uint8_t *rss_key;
+
+ rss = sub_actions->conf;
+ memcpy(rss_desc->queue, rss->queue,
+ rss->queue_num * sizeof(uint16_t));
+ rss_desc->queue_num = rss->queue_num;
+ /* NULL RSS key indicates default RSS key. */
+ rss_key = !rss->key ? rss_hash_default_key : rss->key;
+ memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
+ /*
+ * rss->level and rss.types should be set in advance
+ * when expanding items for RSS.
+ */
+ flow_dv_hashfields_set(dev_flow, rss_desc);
+ hrxq = flow_dv_hrxq_prepare(dev, dev_flow,
+ rss_desc, &hrxq_idx);
+ if (!hrxq)
+ return rte_flow_error_set
+ (error, rte_errno,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "cannot create fate queue");
+ sample_act->dr_queue_action = hrxq->action;
+ sample_idx->rix_hrxq = hrxq_idx;
+ sample_actions[sample_act->actions_num++] =
+ hrxq->action;
+ (*num_of_dest)++;
+ action_flags |= MLX5_FLOW_ACTION_RSS;
+ if (action_flags & MLX5_FLOW_ACTION_MARK)
+ dev_flow->handle->rix_hrxq = hrxq_idx;
+ dev_flow->handle->fate_action =
+ MLX5_FLOW_FATE_QUEUE;
+ break;
+ }
case RTE_FLOW_ACTION_TYPE_MARK:
{
uint32_t tag_be = mlx5_flow_mark_set
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;
uint64_t item_flags = 0;
uint64_t last_item = 0;
uint64_t action_flags = 0;
- uint64_t priority = attr->priority;
struct mlx5_flow_dv_matcher matcher = {
.mask = {
.size = sizeof(matcher.mask.buf) -
struct mlx5_flow_dv_dest_array_resource mdest_res;
struct mlx5_flow_dv_sample_resource sample_res;
void *sample_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
+ const struct rte_flow_action_sample *sample = NULL;
struct mlx5_flow_sub_actions_list *sample_act;
uint32_t sample_act_pos = UINT32_MAX;
uint32_t num_of_dest = 0;
.external = !!dev_flow->external,
.transfer = !!attr->transfer,
.fdb_def_rule = !!priv->fdb_def_rule,
- .skip_scale = !!dev_flow->skip_scale,
+ .skip_scale = dev_flow->skip_scale &
+ (1 << MLX5_SCALE_FLOW_GROUP_BIT),
};
if (!wks)
dev_flow->dv.group = table;
if (attr->transfer)
mhdr_res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
- if (priority == MLX5_FLOW_PRIO_RSVD)
- priority = dev_conf->flow_prio - 1;
/* number of actions must be set to 0 in case of dirty stack. */
mhdr_res->actions_num = 0;
if (is_flow_tunnel_match_rule(dev, attr, items, actions)) {
break;
case RTE_FLOW_ACTION_TYPE_AGE:
if (priv->sh->flow_hit_aso_en && attr->group) {
- flow->age = flow_dv_translate_create_aso_age
- (dev, action->conf, error);
- if (!flow->age)
- return rte_flow_error_set
+ /*
+ * Create one shared age action, to be used
+ * by all sub-flows.
+ */
+ if (!flow->age) {
+ flow->age =
+ flow_dv_translate_create_aso_age
+ (dev, action->conf,
+ error);
+ if (!flow->age)
+ return rte_flow_error_set
(error, rte_errno,
RTE_FLOW_ERROR_TYPE_ACTION,
NULL,
"can't create ASO age action");
+ }
dev_flow->dv.actions[actions_n++] =
(flow_aso_age_get_by_idx
(dev, flow->age))->dr_action;
jump_group = ((const struct rte_flow_action_jump *)
action->conf)->group;
grp_info.std_tbl_fix = 0;
- grp_info.skip_scale = 0;
+ if (dev_flow->skip_scale &
+ (1 << MLX5_SCALE_JUMP_FLOW_GROUP_BIT))
+ grp_info.skip_scale = 1;
+ else
+ grp_info.skip_scale = 0;
ret = mlx5_flow_group_to_table(dev, tunnel,
jump_group,
&table,
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:
break;
case RTE_FLOW_ACTION_TYPE_SAMPLE:
sample_act_pos = actions_n;
- ret = flow_dv_translate_action_sample(dev,
- actions,
- dev_flow, attr,
- &num_of_dest,
- sample_actions,
- &sample_res,
- error);
- if (ret < 0)
- return ret;
+ sample = (const struct rte_flow_action_sample *)
+ action->conf;
actions_n++;
action_flags |= MLX5_FLOW_ACTION_SAMPLE;
/* put encap action into group if work with port id */
handle->dvh.modify_hdr->action;
}
if (action_flags & MLX5_FLOW_ACTION_COUNT) {
- flow->counter =
- flow_dv_translate_create_counter(dev,
- dev_flow, count, age);
-
- if (!flow->counter)
- return rte_flow_error_set
+ /*
+ * Create one count action, to be used
+ * by all sub-flows.
+ */
+ if (!flow->counter) {
+ flow->counter =
+ flow_dv_translate_create_counter
+ (dev, dev_flow, count,
+ age);
+ if (!flow->counter)
+ return rte_flow_error_set
(error, rte_errno,
- RTE_FLOW_ERROR_TYPE_ACTION,
- NULL,
- "cannot create counter"
- " object.");
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL, "cannot create counter"
+ " object.");
+ }
dev_flow->dv.actions[actions_n] =
(flow_dv_counter_get_by_idx(dev,
flow->counter, NULL))->action;
actions_n++;
}
- if (action_flags & MLX5_FLOW_ACTION_SAMPLE) {
- ret = flow_dv_create_action_sample(dev,
- dev_flow,
- num_of_dest,
- &sample_res,
- &mdest_res,
- sample_actions,
- action_flags,
- error);
- if (ret < 0)
- return rte_flow_error_set
- (error, rte_errno,
- RTE_FLOW_ERROR_TYPE_ACTION,
- NULL,
- "cannot create sample action");
- if (num_of_dest > 1) {
- dev_flow->dv.actions[sample_act_pos] =
- dev_flow->dv.dest_array_res->action;
- } else {
- dev_flow->dv.actions[sample_act_pos] =
- dev_flow->dv.sample_res->verbs_action;
- }
- }
- break;
default:
break;
}
modify_action_position == UINT32_MAX)
modify_action_position = actions_n++;
}
- /*
- * For multiple destination (sample action with ratio=1), the encap
- * action and port id action will be combined into group action.
- * 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) {
- int i;
- void *temp_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
-
- for (i = 0; i < actions_n; i++) {
- if ((sample_act->dr_encap_action &&
- sample_act->dr_encap_action ==
- dev_flow->dv.actions[i]) ||
- (sample_act->dr_port_id_action &&
- sample_act->dr_port_id_action ==
- dev_flow->dv.actions[i]))
- continue;
- temp_actions[tmp_actions_n++] = dev_flow->dv.actions[i];
- }
- memcpy((void *)dev_flow->dv.actions,
- (void *)temp_actions,
- tmp_actions_n * sizeof(void *));
- actions_n = tmp_actions_n;
- }
- dev_flow->dv.actions_n = actions_n;
- dev_flow->act_flags = action_flags;
for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
int item_type = items->type;
matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
last_item = MLX5_FLOW_LAYER_GENEVE;
break;
+ case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
+ ret = flow_dv_translate_item_geneve_opt(dev, match_mask,
+ match_value,
+ items, error);
+ if (ret)
+ return rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+ "cannot create GENEVE TLV option");
+ flow->geneve_tlv_option = 1;
+ last_item = MLX5_FLOW_LAYER_GENEVE_OPT;
+ break;
case RTE_FLOW_ITEM_TYPE_MPLS:
flow_dv_translate_item_mpls(match_mask, match_value,
items, last_item, tunnel);
handle->layers |= item_flags;
if (action_flags & MLX5_FLOW_ACTION_RSS)
flow_dv_hashfields_set(dev_flow, rss_desc);
+ /* If has RSS action in the sample action, the Sample/Mirror resource
+ * should be registered after the hash filed be update.
+ */
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE) {
+ ret = flow_dv_translate_action_sample(dev,
+ sample,
+ dev_flow, attr,
+ &num_of_dest,
+ sample_actions,
+ &sample_res,
+ error);
+ if (ret < 0)
+ return ret;
+ ret = flow_dv_create_action_sample(dev,
+ dev_flow,
+ num_of_dest,
+ &sample_res,
+ &mdest_res,
+ sample_actions,
+ action_flags,
+ error);
+ if (ret < 0)
+ return rte_flow_error_set
+ (error, rte_errno,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "cannot create sample action");
+ if (num_of_dest > 1) {
+ dev_flow->dv.actions[sample_act_pos] =
+ dev_flow->dv.dest_array_res->action;
+ } else {
+ dev_flow->dv.actions[sample_act_pos] =
+ dev_flow->dv.sample_res->verbs_action;
+ }
+ }
+ /*
+ * For multiple destination (sample action with ratio=1), the encap
+ * action and port id action will be combined into group action.
+ * 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 || sample_act->dr_jump_action)) {
+ int i;
+ void *temp_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
+
+ for (i = 0; i < actions_n; i++) {
+ if ((sample_act->dr_encap_action &&
+ sample_act->dr_encap_action ==
+ 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];
+ }
+ memcpy((void *)dev_flow->dv.actions,
+ (void *)temp_actions,
+ tmp_actions_n * sizeof(void *));
+ actions_n = tmp_actions_n;
+ }
+ dev_flow->dv.actions_n = actions_n;
+ dev_flow->act_flags = action_flags;
/* Register matcher. */
matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
matcher.mask.size);
- matcher.priority = mlx5_os_flow_adjust_priority(dev,
- priority,
- matcher.priority);
+ matcher.priority = mlx5_get_matcher_priority(dev, attr,
+ matcher.priority);
/* reserved field no needs to be set to 0 here. */
tbl_key.domain = attr->transfer;
tbl_key.direction = attr->egress;
*
* @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,
if (cache_resource->verbs_action)
claim_zero(mlx5_flow_os_destroy_flow_action
(cache_resource->verbs_action));
- if (cache_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {
- if (cache_resource->default_miss)
- claim_zero(mlx5_flow_os_destroy_flow_action
- (cache_resource->default_miss));
- }
if (cache_resource->normal_path_tbl)
flow_dv_tbl_resource_release(MLX5_SH(dev),
cache_resource->normal_path_tbl);