X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_flow.c;h=47ba521a77bbb4763ee150172c70b045b9ef075a;hb=7b4f1e6bd367;hp=092f7b4c4f8c57c348cba22c1c03f491b4b3c4bd;hpb=8d72fa668964b1e4e1834ec0b9f19cb356a90a6e;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 092f7b4c4f..47ba521a77 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -27,11 +27,13 @@ #include #include -#include "mlx5.h" +#include +#include +#include + #include "mlx5_defs.h" +#include "mlx5.h" #include "mlx5_flow.h" -#include "mlx5_glue.h" -#include "mlx5_prm.h" #include "mlx5_rxtx.h" /* Dev ops structure defined in mlx5.c */ @@ -236,6 +238,7 @@ static const struct rte_flow_ops mlx5_flow_ops = { .flush = mlx5_flow_flush, .isolate = mlx5_flow_isolate, .query = mlx5_flow_query, + .dev_dump = mlx5_flow_dev_dump, }; /* Convert FDIR request to Generic flow. */ @@ -318,6 +321,10 @@ static struct mlx5_flow_tunnel_info tunnels_info[] = { .tunnel = MLX5_FLOW_LAYER_IPV6_ENCAP, .ptype = RTE_PTYPE_TUNNEL_IP, }, + { + .tunnel = MLX5_FLOW_LAYER_GTP, + .ptype = RTE_PTYPE_TUNNEL_GTPU, + }, }; /** @@ -336,7 +343,7 @@ static struct mlx5_flow_tunnel_info tunnels_info[] = { * The request register on success, a negative errno * value otherwise and rte_errno is set. */ -enum modify_reg +int mlx5_flow_get_reg_id(struct rte_eth_dev *dev, enum mlx5_feature_name feature, uint32_t id, @@ -345,6 +352,7 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev, struct mlx5_priv *priv = dev->data->dev_private; struct mlx5_dev_config *config = &priv->config; enum modify_reg start_reg; + bool skip_mtr_reg = false; switch (feature) { case MLX5_HAIRPIN_RX: @@ -364,7 +372,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: @@ -375,29 +391,36 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev, return REG_C_0; } break; - case MLX5_COPY_MARK: case MLX5_MTR_SFX: /* - * Metadata COPY_MARK register using is in meter suffix sub - * flow while with meter. It's safe to share the same register. + * If meter color and flow match share one register, flow match + * should use the meter color register for match. */ - return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : REG_C_3; + if (priv->mtr_reg_share) + return priv->mtr_color_reg; + else + return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : + REG_C_3; case MLX5_MTR_COLOR: RTE_ASSERT(priv->mtr_color_reg != REG_NONE); return priv->mtr_color_reg; + case MLX5_COPY_MARK: + /* + * Metadata COPY_MARK register using is in meter suffix sub + * flow while with meter. It's safe to share the same register. + */ + return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : REG_C_3; case MLX5_APP_TAG: /* - * If meter is enable, it will engage two registers for color + * If meter is enable, it will engage the register for color * match and flow match. If meter color match is not using the * REG_C_2, need to skip the REG_C_x be used by meter color * match. * If meter is disable, free to use all available registers. */ - if (priv->mtr_color_reg != REG_NONE) - start_reg = priv->mtr_color_reg != REG_C_2 ? REG_C_3 : - REG_C_4; - else - start_reg = REG_C_2; + start_reg = priv->mtr_color_reg != REG_C_2 ? REG_C_2 : + (priv->mtr_reg_share ? REG_C_3 : REG_C_4); + skip_mtr_reg = !!(priv->mtr_en && start_reg == REG_C_2); if (id > (REG_C_7 - start_reg)) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -412,12 +435,12 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev, * If the available index REG_C_y >= REG_C_x, skip the * color register. */ - if (start_reg == REG_C_3 && config->flow_mreg_c - [id + REG_C_3 - REG_C_0] >= priv->mtr_color_reg) { - if (config->flow_mreg_c[id + 1 + REG_C_3 - REG_C_0] != - REG_NONE) + if (skip_mtr_reg && config->flow_mreg_c + [id + start_reg - REG_C_0] >= priv->mtr_color_reg) { + if (config->flow_mreg_c + [id + 1 + start_reg - REG_C_0] != REG_NONE) return config->flow_mreg_c - [id + 1 + REG_C_3 - REG_C_0]; + [id + 1 + start_reg - REG_C_0]; return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, NULL, "unsupported tag id"); @@ -892,11 +915,6 @@ mlx5_flow_validate_action_flag(uint64_t action_flags, const struct rte_flow_attr *attr, struct rte_flow_error *error) { - - if (action_flags & MLX5_FLOW_ACTION_DROP) - return rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, NULL, - "can't drop and flag in same flow"); if (action_flags & MLX5_FLOW_ACTION_MARK) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, NULL, @@ -948,10 +966,6 @@ mlx5_flow_validate_action_mark(const struct rte_flow_action *action, &mark->id, "mark id must in 0 <= id < " RTE_STR(MLX5_FLOW_MARK_MAX)); - if (action_flags & MLX5_FLOW_ACTION_DROP) - return rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, NULL, - "can't drop and mark in same flow"); if (action_flags & MLX5_FLOW_ACTION_FLAG) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, NULL, @@ -983,24 +997,10 @@ mlx5_flow_validate_action_mark(const struct rte_flow_action *action, * 0 on success, a negative errno value otherwise and rte_errno is set. */ int -mlx5_flow_validate_action_drop(uint64_t action_flags, +mlx5_flow_validate_action_drop(uint64_t action_flags __rte_unused, const struct rte_flow_attr *attr, struct rte_flow_error *error) { - if (action_flags & MLX5_FLOW_ACTION_FLAG) - return rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, NULL, - "can't drop and flag in same flow"); - if (action_flags & MLX5_FLOW_ACTION_MARK) - return rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, NULL, - "can't drop and mark in same flow"); - if (action_flags & (MLX5_FLOW_FATE_ACTIONS | - MLX5_FLOW_FATE_ESWITCH_ACTIONS)) - return rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, NULL, - "can't have 2 fate actions in" - " same flow"); if (attr->egress) return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, @@ -1142,6 +1142,18 @@ mlx5_flow_validate_action_rss(const struct rte_flow_action *action, &rss->types, "some RSS protocols are not" " supported"); + if ((rss->types & (ETH_RSS_L3_SRC_ONLY | ETH_RSS_L3_DST_ONLY)) && + !(rss->types & ETH_RSS_IP)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, + "L3 partial RSS requested but L3 RSS" + " type not specified"); + if ((rss->types & (ETH_RSS_L4_SRC_ONLY | ETH_RSS_L4_DST_ONLY)) && + !(rss->types & (ETH_RSS_UDP | ETH_RSS_TCP))) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, + "L4 partial RSS requested but L4 RSS" + " type not specified"); if (!priv->rxqs_n) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_CONF, @@ -1151,6 +1163,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 +2002,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 +2017,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, @@ -2809,6 +2828,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; @@ -2817,6 +2838,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; @@ -2928,16 +2951,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, @@ -3035,7 +3058,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; @@ -3114,7 +3137,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); @@ -3147,7 +3171,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; @@ -3519,7 +3543,7 @@ flow_meter_split_prep(struct rte_eth_dev *dev, * 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); + set_tag->data = tag_id << MLX5_MTR_COLOR_BITS; tag_action->conf = set_tag; return tag_id; } @@ -3857,16 +3881,18 @@ flow_create_split_metadata(struct rte_eth_dev *dev, }, }; uint64_t hash_fields = dev_flow->hash_fields; - dev_flow = NULL; + /* - * Configure the tag action only if we are not the meter sub - * flow. Since tag is already marked in the meter suffix sub - * flow. + * 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. */ if (qrss_id) { + /* Not meter subflow. */ + assert(!mtr_sfx); /* * Put unique id in prefix flow due to it is destroyed - * after prefix flow and id will be freed after there + * 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). @@ -3879,6 +3905,7 @@ flow_create_split_metadata(struct rte_eth_dev *dev, goto exit; q_tag_spec.id = ret; } + dev_flow = NULL; /* Add suffix subflow to execute Q/RSS. */ ret = flow_create_split_inner(dev, flow, &dev_flow, &q_attr, mtr_sfx ? items : @@ -3954,13 +3981,14 @@ flow_create_split_meter(struct rte_eth_dev *dev, actions_n = flow_check_meter_action(actions, &mtr); if (mtr) { struct mlx5_rte_flow_item_tag *tag_spec; + struct mlx5_rte_flow_item_tag *tag_mask; /* The five prefix actions: meter, decap, encap, tag, end. */ act_size = sizeof(struct rte_flow_action) * (actions_n + 5) + sizeof(struct rte_flow_action_set_tag); /* tag, end. */ #define METER_SUFFIX_ITEM 3 item_size = sizeof(struct rte_flow_item) * METER_SUFFIX_ITEM + - sizeof(struct mlx5_rte_flow_item_tag); + sizeof(struct mlx5_rte_flow_item_tag) * 2; sfx_actions = rte_zmalloc(__func__, (act_size + item_size), 0); if (!sfx_actions) return rte_flow_error_set(error, ENOMEM, @@ -3987,13 +4015,15 @@ flow_create_split_meter(struct rte_eth_dev *dev, act_size); tag_spec = (struct mlx5_rte_flow_item_tag *)(sfx_items + METER_SUFFIX_ITEM); - tag_spec->data = rte_cpu_to_be_32(dev_flow->mtr_flow_id); + tag_spec->data = dev_flow->mtr_flow_id << MLX5_MTR_COLOR_BITS; tag_spec->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0, error); + tag_mask = tag_spec + 1; + tag_mask->data = 0xffffff00; sfx_items->type = MLX5_RTE_FLOW_ITEM_TYPE_TAG; sfx_items->spec = tag_spec; sfx_items->last = NULL; - sfx_items->mask = NULL; + sfx_items->mask = tag_mask; sfx_items++; sfx_port_id_item = find_port_id_item(items); if (sfx_port_id_item) { @@ -4002,7 +4032,7 @@ flow_create_split_meter(struct rte_eth_dev *dev, sfx_items++; } sfx_items->type = RTE_FLOW_ITEM_TYPE_END; - sfx_items -= METER_SUFFIX_ITEM; + sfx_items -= sfx_port_id_item ? 2 : 1; /* Setting the sfx group atrr. */ sfx_attr.group = sfx_attr.transfer ? (MLX5_FLOW_TABLE_LEVEL_SUFFIX - 1) : @@ -5644,3 +5674,28 @@ mlx5_flow_discover_mreg_c(struct rte_eth_dev *dev) config->flow_mreg_c[n] = REG_NONE; return 0; } + +/** + * Dump flow raw hw data to file + * + * @param[in] dev + * The pointer to Ethernet device. + * @param[in] file + * A pointer to a file for output. + * @param[out] error + * Perform verbose error reporting if not NULL. PMDs initialize this + * structure in case of error only. + * @return + * 0 on success, a nagative value otherwise. + */ +int +mlx5_flow_dev_dump(struct rte_eth_dev *dev, + FILE *file, + struct rte_flow_error *error __rte_unused) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_ibv_shared *sh = priv->sh; + + return mlx5_devx_cmd_flow_dump(sh->fdb_domain, sh->rx_domain, + sh->tx_domain, file); +}