@@ -5934,7 +5934,8 @@ flow_check_match_action(const struct rte_flow_action actions[],
ratio = sample->ratio;
sub_type = ((const struct rte_flow_action *)
(sample->actions))->type;
- if (ratio == 1 && attr->transfer)
+ if (ratio == 1 && attr->transfer &&
+ sub_type != RTE_FLOW_ACTION_TYPE_END)
fdb_mirror = 1;
break;
case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
@@ -6106,9 +6107,11 @@ flow_sample_split_prep(struct rte_eth_dev *dev,
break;
case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
- push_vlan_idx = action_idx;
- if (push_vlan_idx < sample_action_pos)
+ if (action_idx < sample_action_pos &&
+ push_vlan_idx == -1) {
set_tag_idx = action_idx;
+ push_vlan_idx = action_idx;
+ }
break;
default:
break;
@@ -6171,18 +6174,20 @@ flow_sample_split_prep(struct rte_eth_dev *dev,
.data = tag_id,
};
/* Prepare the suffix subflow items. */
+ tag_spec = (void *)(sfx_items + SAMPLE_SUFFIX_ITEM);
+ tag_spec->data = tag_id;
+ tag_spec->id = set_tag->id;
+ tag_mask = tag_spec + 1;
+ tag_mask->data = UINT32_MAX;
for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
if (items->type == RTE_FLOW_ITEM_TYPE_PORT_ID ||
- items->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR) {
+ items->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR ||
+ items->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT) {
memcpy(sfx_items, items, sizeof(*sfx_items));
sfx_items++;
+ break;
}
}
- tag_spec = (void *)(sfx_items + SAMPLE_SUFFIX_ITEM);
- tag_spec->data = tag_id;
- tag_spec->id = set_tag->id;
- tag_mask = tag_spec + 1;
- tag_mask->data = UINT32_MAX;
sfx_items[0] = (struct rte_flow_item){
.type = (enum rte_flow_item_type)
MLX5_RTE_FLOW_ITEM_TYPE_TAG,
@@ -6757,6 +6762,8 @@ flow_create_split_sample(struct rte_eth_dev *dev,
uint16_t jump_table = 0;
const uint32_t next_ft_step = 1;
int ret = 0;
+ struct mlx5_priv *item_port_priv = NULL;
+ const struct rte_flow_item *item;
if (priv->sampler_en)
actions_n = flow_check_match_action(actions, attr,
@@ -6776,8 +6783,36 @@ flow_create_split_sample(struct rte_eth_dev *dev,
RTE_FLOW_ERROR_TYPE_ACTION,
NULL, "no memory to split "
"sample flow");
+ for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+ if (item->type == RTE_FLOW_ITEM_TYPE_PORT_ID) {
+ const struct rte_flow_item_port_id *spec;
+
+ spec = (const struct rte_flow_item_port_id *)item->spec;
+ if (spec)
+ item_port_priv =
+ mlx5_port_to_eswitch_info(spec->id, true);
+ break;
+ } else if (item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT) {
+ const struct rte_flow_item_ethdev *spec;
+
+ spec = (const struct rte_flow_item_ethdev *)item->spec;
+ if (spec)
+ item_port_priv =
+ mlx5_port_to_eswitch_info(spec->port_id, true);
+ break;
+ } else if (item->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR) {
+ const struct rte_flow_item_ethdev *spec;
+
+ spec = (const struct rte_flow_item_ethdev *)item->spec;
+ if (spec)
+ item_port_priv =
+ mlx5_port_to_eswitch_info(spec->port_id, true);
+ break;
+ }
+ }
/* The representor_id is UINT16_MAX for uplink. */
- fdb_tx = (attr->transfer && priv->representor_id != UINT16_MAX);
+ fdb_tx = (attr->transfer &&
+ flow_source_vport_representor(priv, item_port_priv));
/*
* When reg_c_preserve is set, metadata registers Cx preserve
* their value even through packet duplication.
@@ -2118,6 +2118,25 @@ rte_col_2_mlx5_col(enum rte_color rcol)
return MLX5_FLOW_COLOR_UNDEFINED;
}
+/**
+ * Indicates whether flow source vport is representor port.
+ *
+ * @param[in] priv
+ * Pointer to device private context structure.
+ * @param[in] act_priv
+ * Pointer to actual device private context structure if have.
+ *
+ * @return
+ * True when the flow source vport is representor port, false otherwise.
+ */
+static inline bool
+flow_source_vport_representor(struct mlx5_priv *priv, struct mlx5_priv *act_priv)
+{
+ MLX5_ASSERT(priv);
+ return (!act_priv ? (priv->representor_id != UINT16_MAX) :
+ (act_priv->representor_id != UINT16_MAX));
+}
+
/* All types of Ethernet patterns used in control flow rules. */
enum mlx5_flow_ctrl_rx_eth_pattern_type {
MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_ALL = 0,
@@ -2208,6 +2208,7 @@ flow_dv_validate_item_port_id(struct rte_eth_dev *dev,
const struct rte_flow_item *item,
const struct rte_flow_attr *attr,
uint64_t item_flags,
+ struct mlx5_priv **act_priv,
struct rte_flow_error *error)
{
const struct rte_flow_item_port_id *spec = item->spec;
@@ -2266,6 +2267,7 @@ flow_dv_validate_item_port_id(struct rte_eth_dev *dev,
RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
"cannot match on a port from a"
" different E-Switch");
+ *act_priv = esw_priv;
return 0;
}
@@ -2291,6 +2293,7 @@ flow_dv_validate_item_represented_port(struct rte_eth_dev *dev,
const struct rte_flow_item *item,
const struct rte_flow_attr *attr,
uint64_t item_flags,
+ struct mlx5_priv **act_priv,
struct rte_flow_error *error)
{
const struct rte_flow_item_ethdev *spec = item->spec;
@@ -2340,6 +2343,7 @@ flow_dv_validate_item_represented_port(struct rte_eth_dev *dev,
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
"cannot match on a port from a different E-Switch");
+ *act_priv = esw_priv;
return 0;
}
@@ -2860,30 +2864,12 @@ flow_dv_validate_action_pop_vlan(struct rte_eth_dev *dev,
struct rte_flow_error *error)
{
const struct mlx5_priv *priv = dev->data->dev_private;
- struct mlx5_dev_ctx_shared *sh = priv->sh;
- bool direction_error = false;
if (!priv->sh->pop_vlan_action)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL,
"pop vlan action is not supported");
- /* Pop VLAN is not supported in egress except for CX6 FDB mode. */
- if (attr->transfer) {
- bool fdb_tx = priv->representor_id != UINT16_MAX;
- bool is_cx5 = sh->steering_format_version ==
- MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
-
- if (fdb_tx && is_cx5)
- direction_error = true;
- } else if (attr->egress) {
- direction_error = true;
- }
- if (direction_error)
- return rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
- NULL,
- "pop vlan action not supported for egress");
if (action_flags & MLX5_FLOW_VLAN_ACTIONS)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -5794,6 +5780,7 @@ flow_dv_validate_action_sample(uint64_t *action_flags,
const struct rte_flow_action_count **count,
int *fdb_mirror_limit,
bool root,
+ struct mlx5_priv *act_priv,
struct rte_flow_error *error)
{
struct mlx5_priv *priv = dev->data->dev_private;
@@ -5982,7 +5969,7 @@ flow_dv_validate_action_sample(uint64_t *action_flags,
"E-Switch must has a dest "
"port for mirroring");
if (!priv->sh->cdev->config.hca_attr.reg_c_preserve &&
- priv->representor_id != UINT16_MAX)
+ flow_source_vport_representor(priv, act_priv))
*fdb_mirror_limit = 1;
}
/* Continue validation for Xcap actions.*/
@@ -7134,6 +7121,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
uint32_t tag_id = 0;
const struct rte_flow_action_age *non_shared_age = NULL;
const struct rte_flow_action_count *count = NULL;
+ struct mlx5_priv *act_priv = NULL;
if (items == NULL)
return -1;
@@ -7183,7 +7171,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
break;
case RTE_FLOW_ITEM_TYPE_PORT_ID:
ret = flow_dv_validate_item_port_id
- (dev, items, attr, item_flags, error);
+ (dev, items, attr, item_flags, &act_priv, error);
if (ret < 0)
return ret;
last_item = MLX5_FLOW_ITEM_PORT_ID;
@@ -7192,7 +7180,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
ret = flow_dv_validate_item_represented_port
- (dev, items, attr, item_flags, error);
+ (dev, items, attr, item_flags, &act_priv, error);
if (ret < 0)
return ret;
last_item = MLX5_FLOW_ITEM_REPRESENTED_PORT;
@@ -8070,6 +8058,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
&sample_count,
&fdb_mirror_limit,
is_root,
+ act_priv,
error);
if (ret < 0)
return ret;
@@ -8246,7 +8235,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
bool direction_error = false;
if (attr->transfer) {
- bool fdb_tx = priv->representor_id != UINT16_MAX;
+ bool fdb_tx = flow_source_vport_representor(priv, act_priv);
bool is_cx5 = sh->steering_format_version ==
MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
@@ -8278,6 +8267,27 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
"multiple VLAN actions");
}
}
+ /* Pop VLAN is not supported in egress except for NICs newer than CX5. */
+ if (action_flags & MLX5_FLOW_ACTION_OF_POP_VLAN) {
+ struct mlx5_dev_ctx_shared *sh = priv->sh;
+ bool direction_error = false;
+
+ if (attr->transfer) {
+ bool fdb_tx = flow_source_vport_representor(priv, act_priv);
+ bool is_cx5 = sh->steering_format_version ==
+ MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
+
+ if (fdb_tx && is_cx5)
+ direction_error = true;
+ } else if (attr->egress) {
+ direction_error = true;
+ }
+ if (direction_error)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+ NULL,
+ "pop vlan action not supported for egress");
+ }
if (action_flags & MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY) {
if ((action_flags & (MLX5_FLOW_FATE_ACTIONS &
~MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)) &&
@@ -8396,6 +8406,7 @@ flow_dv_prepare(struct rte_eth_dev *dev,
wks->skip_matcher_reg = 0;
wks->policy = NULL;
wks->final_policy = NULL;
+ wks->vport_meta_tag = 0;
/* In case of corrupting the memory. */
if (wks->flow_idx >= MLX5_NUM_MAX_DEV_FLOWS) {
rte_flow_error_set(error, ENOSPC,
@@ -10081,10 +10092,12 @@ flow_dv_translate_item_port_id(struct rte_eth_dev *dev, void *key,
{
const struct rte_flow_item_port_id *pid_m = item ? item->mask : NULL;
const struct rte_flow_item_port_id *pid_v = item ? item->spec : NULL;
+ struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
struct mlx5_priv *priv;
uint16_t mask, id;
uint32_t vport_meta;
+ MLX5_ASSERT(wks);
if (pid_v && pid_v->id == MLX5_PORT_ESW_MGR) {
flow_dv_translate_item_source_vport(key,
key_type & MLX5_SET_MATCHER_V ?
@@ -10102,6 +10115,7 @@ flow_dv_translate_item_port_id(struct rte_eth_dev *dev, void *key,
} else {
id = priv->vport_id;
vport_meta = priv->vport_meta_tag;
+ wks->vport_meta_tag = vport_meta;
}
/*
* Translate to vport field or to metadata, depending on mode.
@@ -12273,6 +12287,9 @@ flow_dv_translate_action_sample(struct rte_eth_dev *dev,
uint32_t action_in[MLX5_ST_SZ_DW(set_action_in)];
uint64_t set_action;
} action_ctx = { .set_action = 0 };
+ uint32_t vport_meta_tag = wks->vport_meta_tag ?
+ wks->vport_meta_tag :
+ priv->vport_meta_tag;
res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
MLX5_SET(set_action_in, action_ctx.action_in, action_type,
@@ -12280,7 +12297,7 @@ flow_dv_translate_action_sample(struct rte_eth_dev *dev,
MLX5_SET(set_action_in, action_ctx.action_in, field,
MLX5_MODI_META_REG_C_0);
MLX5_SET(set_action_in, action_ctx.action_in, data,
- priv->vport_meta_tag);
+ vport_meta_tag);
res->set_action = action_ctx.set_action;
} else if (attr->ingress) {
res->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX;