*
* @param[in] actions
* Pointer to the list of actions.
+ * @param[in] attr
+ * Flow rule attributes.
* @param[in] action
* The action to be check if exist.
* @param[out] match_action_pos
*/
static int
flow_check_match_action(const struct rte_flow_action actions[],
+ const struct rte_flow_attr *attr,
enum rte_flow_action_type action,
int *match_action_pos, int *qrss_action_pos)
{
+ 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;
*match_action_pos = -1;
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;
+ sub_type = ((const struct rte_flow_action *)
+ (sample->actions))->type;
+ }
actions_n++;
}
+ if (flag && action == RTE_FLOW_ACTION_TYPE_SAMPLE && attr->transfer) {
+ if (ratio == 1) {
+ /* JUMP Action not support for Mirroring;
+ * Mirroring support multi-destination;
+ */
+ if (!jump_flag && sub_type != RTE_FLOW_ACTION_TYPE_END)
+ flag = 0;
+ }
+ }
/* Count RTE_FLOW_ACTION_TYPE_END. */
return flag ? actions_n + 1 : 0;
}
int ret = 0;
if (priv->sampler_en)
- actions_n = flow_check_match_action(actions,
+ actions_n = flow_check_match_action(actions, attr,
RTE_FLOW_ACTION_TYPE_SAMPLE,
&sample_action_pos, &qrss_action_pos);
if (actions_n) {
(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,
const struct rte_flow_action_sample *sample = action->conf;
const struct rte_flow_action *act;
uint64_t sub_action_flags = 0;
+ uint16_t queue_index = 0xFFFF;
int actions_n = 0;
int ret;
+ fdb_mirror = 0;
if (!sample)
return rte_flow_error_set(error, EINVAL,
attr, error);
if (ret < 0)
return ret;
+ queue_index = ((const struct rte_flow_action_queue *)
+ (act->conf))->index;
sub_action_flags |= MLX5_FLOW_ACTION_QUEUE;
++actions_n;
break;
sub_action_flags |= MLX5_FLOW_ACTION_COUNT;
++actions_n;
break;
+ case RTE_FLOW_ACTION_TYPE_PORT_ID:
+ ret = flow_dv_validate_action_port_id(dev,
+ sub_action_flags,
+ act,
+ attr,
+ error);
+ if (ret)
+ return ret;
+ sub_action_flags |= MLX5_FLOW_ACTION_PORT_ID;
+ ++actions_n;
+ break;
+ case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+ ret = flow_dv_validate_action_raw_encap_decap
+ (dev, NULL, act->conf, attr, &sub_action_flags,
+ &actions_n, error);
+ if (ret < 0)
+ return ret;
+ ++actions_n;
+ break;
default:
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION,
"or E-Switch");
} else if (sample->actions->type != RTE_FLOW_ACTION_TYPE_END) {
MLX5_ASSERT(attr->transfer);
- return rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ACTION, NULL,
- "E-Switch doesn't support any "
- "optional action for sampling");
+ if (sample->ratio > 1)
+ return rte_flow_error_set(error, ENOTSUP,
+ 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_PORT_ID))
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "E-Switch must has a dest "
+ "port for mirroring");
+ }
+ /* Continue validation for Xcap actions.*/
+ if ((sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) &&
+ (queue_index == 0xFFFF ||
+ mlx5_rxq_get_type(dev, queue_index) != MLX5_RXQ_TYPE_HAIRPIN)) {
+ if ((sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
+ MLX5_FLOW_XCAP_ACTIONS)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL, "encap and decap "
+ "combination aren't "
+ "supported");
+ if (!attr->transfer && attr->ingress && (sub_action_flags &
+ MLX5_FLOW_ACTION_ENCAP))
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL, "encap is not supported"
+ " for ingress traffic");
}
return 0;
}