@@ -3174,16 +3174,28 @@ struct mlx5_flow_tunnel_info {
static const struct rte_flow_action_rss*
flow_get_rss_action(const struct rte_flow_action actions[])
{
+ const struct rte_flow_action_rss *rss = NULL;
+
for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
switch (actions->type) {
case RTE_FLOW_ACTION_TYPE_RSS:
- return (const struct rte_flow_action_rss *)
- actions->conf;
+ rss = actions->conf;
+ break;
+ case RTE_FLOW_ACTION_TYPE_SAMPLE:
+ {
+ const struct rte_flow_action_sample *sample =
+ actions->conf;
+ const struct rte_flow_action *act = sample->actions;
+ for (; act->type != RTE_FLOW_ACTION_TYPE_END; act++)
+ if (act->type == RTE_FLOW_ACTION_TYPE_RSS)
+ rss = act->conf;
+ break;
+ }
default:
break;
}
}
- return NULL;
+ return rss;
}
/**
@@ -5278,7 +5290,7 @@ struct mlx5_hlist_entry *
struct mlx5_priv *priv = dev->data->dev_private;
struct rte_flow *flow = NULL;
struct mlx5_flow *dev_flow;
- const struct rte_flow_action_rss *rss;
+ const struct rte_flow_action_rss *rss = NULL;
struct mlx5_translated_shared_action
shared_actions[MLX5_MAX_SHARED_ACTIONS];
int shared_actions_n = MLX5_MAX_SHARED_ACTIONS;
@@ -5356,7 +5368,9 @@ struct mlx5_hlist_entry *
MLX5_ASSERT(flow->drv_type > MLX5_FLOW_TYPE_MIN &&
flow->drv_type < MLX5_FLOW_TYPE_MAX);
memset(rss_desc, 0, offsetof(struct mlx5_flow_rss_desc, queue));
- rss = flow_get_rss_action(p_actions_rx);
+ /* RSS Action only works on NIC RX domain */
+ if (attr->ingress && !attr->transfer)
+ rss = flow_get_rss_action(p_actions_rx);
if (rss) {
if (flow_rss_workspace_adjust(wks, rss_desc, rss->queue_num))
return 0;
@@ -4344,6 +4344,10 @@ struct mlx5_hlist_entry *
* 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.
*
@@ -4355,7 +4359,9 @@ struct mlx5_hlist_entry *
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;
@@ -4415,6 +4421,28 @@ struct mlx5_hlist_entry *
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,
@@ -4463,7 +4491,8 @@ struct mlx5_hlist_entry *
}
}
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,
@@ -4490,6 +4519,11 @@ struct mlx5_hlist_entry *
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,
@@ -5240,7 +5274,8 @@ struct mlx5_hlist_entry *
const struct rte_flow_item *gre_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,
@@ -5709,6 +5744,14 @@ struct mlx5_hlist_entry *
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;
@@ -6027,6 +6070,7 @@ struct mlx5_hlist_entry *
ret = flow_dv_validate_action_sample(action_flags,
actions, dev,
attr, item_flags,
+ rss, &sample_rss,
error);
if (ret < 0)
return ret;
@@ -9053,7 +9097,7 @@ struct mlx5_cache_entry *
* @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
@@ -9072,7 +9116,7 @@ struct mlx5_cache_entry *
*/
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,
@@ -9081,9 +9125,7 @@ struct mlx5_cache_entry *
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();
@@ -9094,9 +9136,8 @@ struct mlx5_cache_entry *
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;
@@ -9104,6 +9145,7 @@ struct mlx5_cache_entry *
switch (type) {
case RTE_FLOW_ACTION_TYPE_QUEUE:
{
+ const struct rte_flow_action_queue *queue;
struct mlx5_hrxq *hrxq;
uint32_t hrxq_idx;
@@ -9130,6 +9172,45 @@ struct mlx5_cache_entry *
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
@@ -9694,6 +9775,7 @@ struct mlx5_cache_entry *
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;
@@ -10235,15 +10317,8 @@ struct mlx5_cache_entry *
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 */
@@ -10279,30 +10354,6 @@ struct mlx5_cache_entry *
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;
}
@@ -10310,33 +10361,6 @@ struct mlx5_cache_entry *
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;
@@ -10588,6 +10612,68 @@ struct mlx5_cache_entry *
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) {
+ 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;
/* Register matcher. */
matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
matcher.mask.size);