X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_flow.c;h=008716367c05356abc47cc7fa12de97edc3b452e;hb=c8a1a172ae2b4535b57bcf194a731334246a5a35;hp=da3e47ac76a33bcb9ac80043d3b5f3cfa928275e;hpb=9ea9b049a960f67f42a5eb9b73976a48cb45e9d9;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index da3e47ac76..008716367c 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -364,7 +364,15 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev, 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: @@ -1151,6 +1159,11 @@ mlx5_flow_validate_action_rss(const struct rte_flow_action *action, 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, @@ -1985,8 +1998,8 @@ mlx5_flow_validate_item_gre_key(const struct rte_flow_item *item, 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, @@ -2000,8 +2013,10 @@ mlx5_flow_validate_item_gre_key(const struct rte_flow_item *item, 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, @@ -2328,27 +2343,6 @@ flow_mreg_split_qrss_release(struct rte_eth_dev *dev, 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, @@ -2639,7 +2633,6 @@ flow_drv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow) 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); @@ -2831,6 +2824,8 @@ flow_check_hairpin_split(struct rte_eth_dev *dev, 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; @@ -2839,6 +2834,8 @@ flow_check_hairpin_split(struct rte_eth_dev *dev, 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; @@ -2950,16 +2947,16 @@ flow_mreg_add_copy_action(struct rte_eth_dev *dev, uint32_t mark_id, 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, @@ -3057,7 +3054,7 @@ flow_mreg_del_copy_action(struct rte_eth_dev *dev, } /* * 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; @@ -3136,7 +3133,8 @@ flow_mreg_del_default_copy_action(struct rte_eth_dev *dev) /* 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); @@ -3169,7 +3167,7 @@ flow_mreg_add_default_copy_action(struct rte_eth_dev *dev, !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; @@ -3473,7 +3471,6 @@ flow_meter_split_prep(struct rte_eth_dev *dev, 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; @@ -3538,7 +3535,10 @@ flow_meter_split_prep(struct rte_eth_dev *dev, /* 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; @@ -3595,7 +3595,7 @@ flow_mreg_split_qrss_prep(struct rte_eth_dev *dev, 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; /* @@ -3605,43 +3605,50 @@ flow_mreg_split_qrss_prep(struct rte_eth_dev *dev, * 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, @@ -3742,6 +3749,7 @@ flow_create_split_metadata(struct rte_eth_dev *dev, 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; @@ -3772,6 +3780,10 @@ flow_create_split_metadata(struct rte_eth_dev *dev, } } 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 @@ -3786,6 +3798,16 @@ flow_create_split_metadata(struct rte_eth_dev *dev, 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 @@ -3794,7 +3816,7 @@ flow_create_split_metadata(struct rte_eth_dev *dev, */ 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; } @@ -3824,7 +3846,7 @@ flow_create_split_metadata(struct rte_eth_dev *dev, 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, @@ -3855,22 +3877,35 @@ flow_create_split_metadata(struct rte_eth_dev *dev, }, }; 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;