case MLX5_METADATA_TX:
return REG_A;
case MLX5_METADATA_FDB:
- return REG_C_0;
+ switch (config->dv_xmeta_en) {
+ case MLX5_XMETA_MODE_LEGACY:
+ return REG_NONE;
+ case MLX5_XMETA_MODE_META16:
+ return REG_C_0;
+ case MLX5_XMETA_MODE_META32:
+ return REG_C_1;
+ }
+ break;
case MLX5_FLOW_MARK:
switch (config->dv_xmeta_en) {
case MLX5_XMETA_MODE_LEGACY:
RTE_FLOW_ERROR_TYPE_ACTION_CONF,
NULL, "No queues configured");
for (i = 0; i != rss->queue_num; ++i) {
+ if (rss->queue[i] >= priv->rxqs_n)
+ return rte_flow_error_set
+ (error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+ &rss->queue[i], "queue index out of range");
if (!(*priv->rxqs)[rss->queue[i]])
return rte_flow_error_set
(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_CONF,
const rte_be32_t *mask = item->mask;
int ret = 0;
rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
- const struct rte_flow_item_gre *gre_spec = gre_item->spec;
- const struct rte_flow_item_gre *gre_mask = gre_item->mask;
+ const struct rte_flow_item_gre *gre_spec;
+ const struct rte_flow_item_gre *gre_mask;
if (item_flags & MLX5_FLOW_LAYER_GRE_KEY)
return rte_flow_error_set(error, ENOTSUP,
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ITEM, item,
"GRE key following a wrong item");
+ gre_mask = gre_item->mask;
if (!gre_mask)
gre_mask = &rte_flow_item_gre_mask;
+ gre_spec = gre_item->spec;
if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x2000)) &&
!(gre_spec->c_rsvd0_ver & RTE_BE16(0x2000)))
return rte_flow_error_set(error, EINVAL,
flow_qrss_free_id(dev, dev_flow->qrss_id);
}
-/**
- * Release meter prefix suffix flow match id.
- *
- * @param dev
- * Pointer to Ethernet device.
- * @param flow
- * Flow to release id's from.
- */
-static void
-flow_meter_split_id_release(struct rte_eth_dev *dev,
- struct rte_flow *flow)
-{
- struct mlx5_flow *dev_flow;
- struct mlx5_priv *priv = dev->data->dev_private;
-
- LIST_FOREACH(dev_flow, &flow->dev_flows, next)
- if (dev_flow->qrss_id)
- mlx5_flow_id_release(priv->sh->flow_id_pool,
- dev_flow->mtr_flow_id);
-}
-
static int
flow_null_validate(struct rte_eth_dev *dev __rte_unused,
const struct rte_flow_attr *attr __rte_unused,
enum mlx5_flow_drv_type type = flow->drv_type;
flow_mreg_split_qrss_release(dev, flow);
- flow_meter_split_id_release(dev, flow);
assert(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);
fops = flow_get_drv_ops(type);
fops->destroy(dev, flow);
switch (actions->type) {
case RTE_FLOW_ACTION_TYPE_QUEUE:
queue = actions->conf;
+ if (queue == NULL)
+ return 0;
if (mlx5_rxq_get_type(dev, queue->index) !=
MLX5_RXQ_TYPE_HAIRPIN)
return 0;
break;
case RTE_FLOW_ACTION_TYPE_RSS:
rss = actions->conf;
+ if (rss == NULL || rss->queue_num == 0)
+ return 0;
if (mlx5_rxq_get_type(dev, rss->queue[0]) !=
MLX5_RXQ_TYPE_HAIRPIN)
return 0;
mcp_res = (void *)mlx5_hlist_lookup(priv->mreg_cp_tbl, mark_id);
if (mcp_res) {
/* For non-default rule. */
- if (mark_id)
+ if (mark_id != MLX5_DEFAULT_COPY_ID)
mcp_res->refcnt++;
- assert(mark_id || mcp_res->refcnt == 1);
+ assert(mark_id != MLX5_DEFAULT_COPY_ID || mcp_res->refcnt == 1);
return mcp_res;
}
/* Provide the full width of FLAG specific value. */
if (mark_id == (priv->sh->dv_regc0_mask & MLX5_FLOW_MARK_DEFAULT))
tag_spec.data = MLX5_FLOW_MARK_DEFAULT;
/* Build a new flow. */
- if (mark_id) {
+ if (mark_id != MLX5_DEFAULT_COPY_ID) {
items[0] = (struct rte_flow_item){
.type = MLX5_RTE_FLOW_ITEM_TYPE_TAG,
.spec = &tag_spec,
}
/*
* We do not check availability of metadata registers here,
- * because copy resources are allocated in this case.
+ * because copy resources are not allocated in this case.
*/
if (--mcp_res->refcnt)
return;
/* Check if default flow is registered. */
if (!priv->mreg_cp_tbl)
return;
- mcp_res = (void *)mlx5_hlist_lookup(priv->mreg_cp_tbl, 0ULL);
+ mcp_res = (void *)mlx5_hlist_lookup(priv->mreg_cp_tbl,
+ MLX5_DEFAULT_COPY_ID);
if (!mcp_res)
return;
assert(mcp_res->flow);
!mlx5_flow_ext_mreg_supported(dev) ||
!priv->sh->dv_regc0_mask)
return 0;
- mcp_res = flow_mreg_add_copy_action(dev, 0, error);
+ mcp_res = flow_mreg_add_copy_action(dev, MLX5_DEFAULT_COPY_ID, error);
if (!mcp_res)
return -rte_errno;
return 0;
struct rte_flow_action actions_sfx[],
struct rte_flow_action actions_pre[])
{
- struct mlx5_priv *priv = dev->data->dev_private;
struct rte_flow_action *tag_action;
struct mlx5_rte_flow_action_set_tag *set_tag;
struct rte_flow_error error;
/* Set the tag. */
set_tag = (void *)actions_pre;
set_tag->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0, &error);
- mlx5_flow_id_get(priv->sh->flow_id_pool, &tag_id);
+ /*
+ * Get the id from the qrss_pool to make qrss share the id with meter.
+ */
+ tag_id = flow_qrss_get_id(dev);
set_tag->data = rte_cpu_to_be_32(tag_id);
tag_action->conf = set_tag;
return tag_id;
struct mlx5_rte_flow_action_set_tag *set_tag;
struct rte_flow_action_jump *jump;
const int qrss_idx = qrss - actions;
- uint32_t flow_id;
+ uint32_t flow_id = 0;
int ret = 0;
/*
* As a result, there will be one more action.
*/
++actions_n;
+ memcpy(split_actions, actions, sizeof(*split_actions) * actions_n);
+ set_tag = (void *)(split_actions + actions_n);
/*
- * Allocate the new subflow ID. This one is unique within
- * device and not shared with representors. Otherwise,
- * we would have to resolve multi-thread access synch
- * issue. Each flow on the shared device is appended
- * with source vport identifier, so the resulting
- * flows will be unique in the shared (by master and
- * representors) domain even if they have coinciding
- * IDs.
+ * If tag action is not set to void(it means we are not the meter
+ * suffix flow), add the tag action. Since meter suffix flow already
+ * has the tag added.
*/
- flow_id = flow_qrss_get_id(dev);
- if (!flow_id)
- return rte_flow_error_set(error, ENOMEM,
- RTE_FLOW_ERROR_TYPE_ACTION,
- NULL, "can't allocate id "
- "for split Q/RSS subflow");
- /* Internal SET_TAG action to set flow ID. */
- set_tag = (void *)(split_actions + actions_n);
- *set_tag = (struct mlx5_rte_flow_action_set_tag){
- .data = flow_id,
- };
- ret = mlx5_flow_get_reg_id(dev, MLX5_COPY_MARK, 0, error);
- if (ret < 0)
- return ret;
- set_tag->id = ret;
+ if (split_actions[qrss_idx].type != RTE_FLOW_ACTION_TYPE_VOID) {
+ /*
+ * Allocate the new subflow ID. This one is unique within
+ * device and not shared with representors. Otherwise,
+ * we would have to resolve multi-thread access synch
+ * issue. Each flow on the shared device is appended
+ * with source vport identifier, so the resulting
+ * flows will be unique in the shared (by master and
+ * representors) domain even if they have coinciding
+ * IDs.
+ */
+ flow_id = flow_qrss_get_id(dev);
+ if (!flow_id)
+ return rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL, "can't allocate id "
+ "for split Q/RSS subflow");
+ /* Internal SET_TAG action to set flow ID. */
+ *set_tag = (struct mlx5_rte_flow_action_set_tag){
+ .data = flow_id,
+ };
+ ret = mlx5_flow_get_reg_id(dev, MLX5_COPY_MARK, 0, error);
+ if (ret < 0)
+ return ret;
+ set_tag->id = ret;
+ /* Construct new actions array. */
+ /* Replace QUEUE/RSS action. */
+ split_actions[qrss_idx] = (struct rte_flow_action){
+ .type = MLX5_RTE_FLOW_ACTION_TYPE_TAG,
+ .conf = set_tag,
+ };
+ }
/* JUMP action to jump to mreg copy table (CP_TBL). */
jump = (void *)(set_tag + 1);
*jump = (struct rte_flow_action_jump){
.group = MLX5_FLOW_MREG_CP_TABLE_GROUP,
};
- /* Construct new actions array. */
- memcpy(split_actions, actions, sizeof(*split_actions) * actions_n);
- /* Replace QUEUE/RSS action. */
- split_actions[qrss_idx] = (struct rte_flow_action){
- .type = MLX5_RTE_FLOW_ACTION_TYPE_TAG,
- .conf = set_tag,
- };
split_actions[actions_n - 2] = (struct rte_flow_action){
.type = RTE_FLOW_ACTION_TYPE_JUMP,
.conf = jump,
struct rte_flow_action *ext_actions = NULL;
struct mlx5_flow *dev_flow = NULL;
uint32_t qrss_id = 0;
+ int mtr_sfx = 0;
size_t act_size;
int actions_n;
int ret;
}
}
if (qrss) {
+ /* Check if it is in meter suffix table. */
+ mtr_sfx = attr->group == (attr->transfer ?
+ (MLX5_FLOW_TABLE_LEVEL_SUFFIX - 1) :
+ MLX5_FLOW_TABLE_LEVEL_SUFFIX);
/*
* Q/RSS action on NIC Rx should be split in order to pass by
* the mreg copy table (RX_CP_TBL) and then it jumps to the
RTE_FLOW_ERROR_TYPE_ACTION,
NULL, "no memory to split "
"metadata flow");
+ /*
+ * If we are the suffix flow of meter, tag already exist.
+ * Set the tag action to void.
+ */
+ if (mtr_sfx)
+ ext_actions[qrss - actions].type =
+ RTE_FLOW_ACTION_TYPE_VOID;
+ else
+ ext_actions[qrss - actions].type =
+ MLX5_RTE_FLOW_ACTION_TYPE_TAG;
/*
* Create the new actions list with removed Q/RSS action
* and appended set tag and jump to register copy table
*/
qrss_id = flow_mreg_split_qrss_prep(dev, ext_actions, actions,
qrss, actions_n, error);
- if (!qrss_id) {
+ if (!mtr_sfx && !qrss_id) {
ret = -rte_errno;
goto exit;
}
if (ret < 0)
goto exit;
assert(dev_flow);
- if (qrss_id) {
+ if (qrss) {
const struct rte_flow_attr q_attr = {
.group = MLX5_FLOW_MREG_ACT_TABLE_GROUP,
.ingress = 1,
},
};
uint64_t hash_fields = dev_flow->hash_fields;
+
/*
- * Put unique id in prefix flow due to it is destroyed after
- * prefix flow and id will be freed after there is no actual
- * flows with this id and identifier reallocation becomes
- * possible (for example, for other flows in other threads).
+ * Configure the tag item only if there is no meter subflow.
+ * Since tag is already marked in the meter suffix subflow
+ * we can just use the meter suffix items as is.
*/
- dev_flow->qrss_id = qrss_id;
- qrss_id = 0;
+ if (qrss_id) {
+ /* Not meter subflow. */
+ assert(!mtr_sfx);
+ /*
+ * Put unique id in prefix flow due to it is destroyed
+ * after suffix flow and id will be freed after there
+ * is no actual flows with this id and identifier
+ * reallocation becomes possible (for example, for
+ * other flows in other threads).
+ */
+ dev_flow->qrss_id = qrss_id;
+ qrss_id = 0;
+ ret = mlx5_flow_get_reg_id(dev, MLX5_COPY_MARK, 0,
+ error);
+ if (ret < 0)
+ goto exit;
+ q_tag_spec.id = ret;
+ }
dev_flow = NULL;
- ret = mlx5_flow_get_reg_id(dev, MLX5_COPY_MARK, 0, error);
- if (ret < 0)
- goto exit;
- q_tag_spec.id = ret;
/* Add suffix subflow to execute Q/RSS. */
ret = flow_create_split_inner(dev, flow, &dev_flow,
- &q_attr, q_items, q_actions,
+ &q_attr, mtr_sfx ? items :
+ q_items, q_actions,
external, error);
if (ret < 0)
goto exit;