Skip to content

Commit

Permalink
net/mlx5: fix E-Switch mirror flow rule validation
Browse files Browse the repository at this point in the history
[ upstream commit a8697f50f50f35b2078c78b2d9ea84f78a0f325e ]

The port action and jump to flow table action are not supported
in the mirror flows (RTE_FLOW_ACTION_TYPE_SAMPLE with sample ratio=1)
in E-Switch domain (transfer attribute set) without presented encap
action.

The encap action is supported for uplink port only. So, if flow with
mirroring contains  encap action application should provide encap
and uplink port actions in the mirror action list and PMD validates
this condition (to make sure we cover the hardware limitation).

This patch adds the validation for E-Switch mirror flow rule checking
and rejects as invalid.

Fixes: 6a95156 ("net/mlx5: support E-Switch mirroring and jump in one flow")

Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
  • Loading branch information
jiaweiwsz authored and kevintraynor committed Nov 16, 2023
1 parent 9f2c545 commit 986d9d2
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 24 deletions.
8 changes: 6 additions & 2 deletions doc/guides/nics/mlx5.rst
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,12 @@ Limitations
encapsulation actions.
- For NIC Rx flow, supports ``MARK``, ``COUNT``, ``QUEUE``, ``RSS`` in the
sample actions list.
- For E-Switch mirroring flow, supports ``RAW ENCAP``, ``Port ID``,
``VXLAN ENCAP``, ``NVGRE ENCAP`` in the sample actions list.
- For E-Switch mirroring flow, supports ``RAW_ENCAP``, ``PORT_ID``,
``VXLAN_ENCAP``, ``NVGRE_ENCAP`` in the sample actions list.
- For E-Switch mirroring flow with sample ratio = 1, the ``ENCAP`` action
supports uplink port only.
- For E-Switch mirroring flow with sample ratio = 1, the ``PORT`` and ``JUMP`` actions
are not supported without presented ``ENCAP`` action in the sample actions list.
- For ConnectX-5 trusted device, the application metadata with SET_TAG index 0
is not supported before ``RTE_FLOW_ACTION_TYPE_SAMPLE`` action.

Expand Down
93 changes: 71 additions & 22 deletions drivers/net/mlx5/mlx5_flow_dv.c
Original file line number Diff line number Diff line change
Expand Up @@ -5553,6 +5553,7 @@ flow_dv_modify_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
*/
static int
flow_dv_validate_action_sample(uint64_t *action_flags,
uint64_t *sub_action_flags,
const struct rte_flow_action *action,
struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
Expand All @@ -5561,13 +5562,14 @@ flow_dv_validate_action_sample(uint64_t *action_flags,
const struct rte_flow_action_rss **sample_rss,
const struct rte_flow_action_count **count,
int *fdb_mirror,
uint16_t *sample_port_id,
struct rte_flow_error *error)
{
struct mlx5_priv *priv = dev->data->dev_private;
struct mlx5_dev_config *dev_conf = &priv->config;
const struct rte_flow_action_sample *sample = action->conf;
const struct rte_flow_action_port_id *port = NULL;
const struct rte_flow_action *act;
uint64_t sub_action_flags = 0;
uint16_t queue_index = 0xFFFF;
int actions_n = 0;
int ret;
Expand Down Expand Up @@ -5613,20 +5615,20 @@ flow_dv_validate_action_sample(uint64_t *action_flags,
switch (act->type) {
case RTE_FLOW_ACTION_TYPE_QUEUE:
ret = mlx5_flow_validate_action_queue(act,
sub_action_flags,
*sub_action_flags,
dev,
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;
*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,
*sub_action_flags,
dev, attr,
item_flags,
error);
Expand All @@ -5642,48 +5644,57 @@ flow_dv_validate_action_sample(uint64_t *action_flags,
"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;
*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,
*sub_action_flags,
attr, error);
if (ret < 0)
return ret;
if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY)
sub_action_flags |= MLX5_FLOW_ACTION_MARK |
*sub_action_flags |= MLX5_FLOW_ACTION_MARK |
MLX5_FLOW_ACTION_MARK_EXT;
else
sub_action_flags |= MLX5_FLOW_ACTION_MARK;
*sub_action_flags |= MLX5_FLOW_ACTION_MARK;
++actions_n;
break;
case RTE_FLOW_ACTION_TYPE_COUNT:
ret = flow_dv_validate_action_count
(dev, false, *action_flags | sub_action_flags,
(dev, false, *action_flags | *sub_action_flags,
attr, error);
if (ret < 0)
return ret;
*count = act->conf;
sub_action_flags |= MLX5_FLOW_ACTION_COUNT;
*sub_action_flags |= MLX5_FLOW_ACTION_COUNT;
*action_flags |= MLX5_FLOW_ACTION_COUNT;
++actions_n;
break;
case RTE_FLOW_ACTION_TYPE_PORT_ID:
case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
ret = flow_dv_validate_action_port_id(dev,
sub_action_flags,
*sub_action_flags,
act,
attr,
error);
if (ret)
return ret;
sub_action_flags |= MLX5_FLOW_ACTION_PORT_ID;
if (act->type == RTE_FLOW_ACTION_TYPE_PORT_ID) {
port = (const struct rte_flow_action_port_id *)
act->conf;
*sample_port_id = port->original ?
dev->data->port_id : port->id;
} else {
*sample_port_id = ((const struct rte_flow_action_ethdev *)
act->conf)->port_id;
}
*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,
(dev, NULL, act->conf, attr, sub_action_flags,
&actions_n, action, item_flags, error);
if (ret < 0)
return ret;
Expand All @@ -5692,12 +5703,12 @@ flow_dv_validate_action_sample(uint64_t *action_flags,
case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
ret = flow_dv_validate_action_l2_encap(dev,
sub_action_flags,
*sub_action_flags,
act, attr,
error);
if (ret < 0)
return ret;
sub_action_flags |= MLX5_FLOW_ACTION_ENCAP;
*sub_action_flags |= MLX5_FLOW_ACTION_ENCAP;
++actions_n;
break;
default:
Expand All @@ -5709,7 +5720,7 @@ flow_dv_validate_action_sample(uint64_t *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,
Expand All @@ -5731,17 +5742,17 @@ flow_dv_validate_action_sample(uint64_t *action_flags,
"E-Switch doesn't support "
"any optional action "
"for sampling");
if (sub_action_flags & MLX5_FLOW_ACTION_QUEUE)
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)
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))
if (!(*sub_action_flags & MLX5_FLOW_ACTION_PORT_ID))
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
NULL,
Expand All @@ -5750,17 +5761,17 @@ flow_dv_validate_action_sample(uint64_t *action_flags,
*fdb_mirror = 1;
}
/* Continue validation for Xcap actions.*/
if ((sub_action_flags & MLX5_FLOW_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) ==
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 &
if (!attr->transfer && attr->ingress && (*sub_action_flags &
MLX5_FLOW_ACTION_ENCAP))
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION,
Expand Down Expand Up @@ -6869,9 +6880,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
uint32_t tag_id = 0, tag_bitmap = 0;
const struct rte_flow_action_age *non_shared_age = NULL;
const struct rte_flow_action_count *count = NULL;
const struct rte_flow_action_port_id *port = NULL;
const struct mlx5_rte_flow_item_tag *mlx5_tag;
struct mlx5_priv *act_priv = NULL;
int aso_after_sample = 0;
struct mlx5_priv *port_priv = NULL;
uint64_t sub_action_flags = 0;
uint16_t sample_port_id = 0;
uint16_t port_id = 0;

if (items == NULL)
return -1;
Expand Down Expand Up @@ -7278,6 +7294,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
error);
if (ret)
return ret;
if (type == RTE_FLOW_ACTION_TYPE_PORT_ID) {
port = (const struct rte_flow_action_port_id *)
actions->conf;
port_id = port->original ? dev->data->port_id : port->id;
} else {
port_id = ((const struct rte_flow_action_ethdev *)
actions->conf)->port_id;
}
action_flags |= MLX5_FLOW_ACTION_PORT_ID;
++actions_n;
break;
Expand Down Expand Up @@ -7777,11 +7801,13 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
break;
case RTE_FLOW_ACTION_TYPE_SAMPLE:
ret = flow_dv_validate_action_sample(&action_flags,
&sub_action_flags,
actions, dev,
attr, item_flags,
rss, &sample_rss,
&sample_count,
&fdb_mirror,
&sample_port_id,
error);
if (ret < 0)
return ret;
Expand Down Expand Up @@ -8086,6 +8112,29 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"sample before ASO action is not supported");
if (sub_action_flags & MLX5_FLOW_ACTION_PORT_ID) {
port_priv = mlx5_port_to_eswitch_info(sample_port_id, false);
if (flow_source_vport_representor(priv, port_priv)) {
if (sub_action_flags & MLX5_FLOW_ACTION_ENCAP)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"mirror to rep port with encap is not supported");
} else {
if ((sub_action_flags & ~MLX5_FLOW_ACTION_ENCAP) &&
(action_flags & MLX5_FLOW_ACTION_JUMP))
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"mirror to wire port without encap is not supported");
}
}
if ((action_flags & MLX5_FLOW_ACTION_PORT_ID) &&
(action_flags & MLX5_FLOW_ACTION_ENCAP)) {
port_priv = mlx5_port_to_eswitch_info(port_id, false);
if (flow_source_vport_representor(priv, port_priv))
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"mirror to rep port with encap is not supported");
}
}
/*
* Validation the NIC Egress flow on representor, except implicit
Expand Down

0 comments on commit 986d9d2

Please sign in to comment.