From patchwork Tue Jan 12 10:29:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawei Wang X-Patchwork-Id: 86405 X-Patchwork-Delegate: rasland@nvidia.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 77B83A04B5; Tue, 12 Jan 2021 11:29:59 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 8E88D140E46; Tue, 12 Jan 2021 11:29:32 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 0372E140E28 for ; Tue, 12 Jan 2021 11:29:24 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from jiaweiw@nvidia.com) with SMTP; 12 Jan 2021 12:29:19 +0200 Received: from nvidia.com (gen-l-vrt-281.mtl.labs.mlnx [10.237.44.1]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 10CATJ6i003733; Tue, 12 Jan 2021 12:29:19 +0200 From: Jiawei Wang To: viacheslavo@nvidia.com, matan@nvidia.com, orika@nvidia.com Cc: dev@dpdk.org, rasland@nvidia.com Date: Tue, 12 Jan 2021 12:29:16 +0200 Message-Id: <1610447359-411658-3-git-send-email-jiaweiw@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1610447359-411658-1-git-send-email-jiaweiw@nvidia.com> References: <1610276814-455612-1-git-send-email-jiaweiw@nvidia.com> <1610447359-411658-1-git-send-email-jiaweiw@nvidia.com> Subject: [dpdk-dev] [PATCH v2 2/5] net/mlx5: support E-Switch mirroring and jump in one flow X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" mlx5 E-Switch mirroring is implemented as multiple destination array in one steering table. The array currently supports only port ID as destination actions. This patch adds the jump action support to the array as one of destination. The packets can be mirrored to the port and jump to the next table in the same destination array allowing to continue handling in the new table. For example: set sample_actions 0 port_id id 1 / end flow create 0 ingress transfer pattern eth / end actions sample ratio 1 index 0 / jump group 1 / end flow create 1 ingress transfer group 1 pattern eth / end actions set_mac_dst mac_addr 00:aa:bb:cc:dd:ee / port_id id 2 / end The flow results all the matched ingress packets are mirrored to port id 1 and go to group 1. In the group 1, packets are modified with the destination mac and sent to port id 2. Signed-off-by: Jiawei Wang Acked-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow.c | 36 ++++++++++-------- drivers/net/mlx5/mlx5_flow.h | 2 + drivers/net/mlx5/mlx5_flow_dv.c | 81 +++++++++++++++++++++++++++++------------ 3 files changed, 80 insertions(+), 39 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 2a4073c..217090a 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -4503,7 +4503,6 @@ struct mlx5_hlist_entry * { const struct rte_flow_action_sample *sample; int actions_n = 0; - int jump_flag = 0; uint32_t ratio = 0; int sub_type = 0; int flag = 0; @@ -4518,8 +4517,6 @@ struct mlx5_hlist_entry * if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE || actions->type == RTE_FLOW_ACTION_TYPE_RSS) *qrss_action_pos = actions_n; - if (actions->type == RTE_FLOW_ACTION_TYPE_JUMP) - jump_flag = 1; if (actions->type == RTE_FLOW_ACTION_TYPE_SAMPLE) { sample = actions->conf; ratio = sample->ratio; @@ -4530,10 +4527,10 @@ struct mlx5_hlist_entry * } if (flag && action == RTE_FLOW_ACTION_TYPE_SAMPLE && attr->transfer) { if (ratio == 1) { - /* JUMP Action not support for Mirroring; - * Mirroring support multi-destination; + /* FDB mirroring uses the destination array to implement + * instead of FLOW_SAMPLER object. */ - if (!jump_flag && sub_type != RTE_FLOW_ACTION_TYPE_END) + if (sub_type != RTE_FLOW_ACTION_TYPE_END) flag = 0; } } @@ -4554,8 +4551,8 @@ struct mlx5_hlist_entry * * * @param dev * Pointer to Ethernet device. - * @param[in] fdb_tx - * FDB egress flow flag. + * @param[in] add_tag + * Add extra tag action flag. * @param[out] sfx_items * Suffix flow match items (list terminated by the END pattern item). * @param[in] actions @@ -4579,7 +4576,7 @@ struct mlx5_hlist_entry * */ static int flow_sample_split_prep(struct rte_eth_dev *dev, - uint32_t fdb_tx, + int add_tag, struct rte_flow_item sfx_items[], const struct rte_flow_action actions[], struct rte_flow_action actions_sfx[], @@ -4602,7 +4599,11 @@ struct mlx5_hlist_entry * RTE_FLOW_ERROR_TYPE_ACTION, NULL, "invalid position of sample " "action in list"); - if (!fdb_tx) { + /* For CX5, add an extra tag action for NIC-RX and E-Switch ingress. + * For CX6DX and above, metadata registers Cx preserve their value, + * add an extra tag action for NIC-RX and E-Switch ingress and egress. + */ + if (add_tag) { /* Prepare the prefix tag action. */ set_tag = (void *)(actions_pre + actions_n + 1); ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, 0, error); @@ -4653,8 +4654,7 @@ struct mlx5_hlist_entry * memcpy(actions_pre, actions, sizeof(struct rte_flow_action) * index); } - /* Add the extra tag action for NIC-RX and E-Switch ingress. */ - if (!fdb_tx) { + if (add_tag) { actions_pre[index++] = (struct rte_flow_action){ .type = (enum rte_flow_action_type) @@ -5067,6 +5067,7 @@ struct mlx5_hlist_entry * int actions_n = 0; int sample_action_pos; int qrss_action_pos; + int add_tag = 0; int ret = 0; if (priv->sampler_en) @@ -5088,16 +5089,21 @@ struct mlx5_hlist_entry * "sample flow"); /* The representor_id is -1 for uplink. */ fdb_tx = (attr->transfer && priv->representor_id != -1); - if (!fdb_tx) + /* + * When reg_c_preserve is set, metadata registers Cx preserve + * their value even through packet duplication. + */ + add_tag = (!fdb_tx || priv->config.hca_attr.reg_c_preserve); + if (add_tag) sfx_items = (struct rte_flow_item *)((char *)sfx_actions + act_size); pre_actions = sfx_actions + actions_n; - tag_id = flow_sample_split_prep(dev, fdb_tx, sfx_items, + tag_id = flow_sample_split_prep(dev, add_tag, sfx_items, actions, sfx_actions, pre_actions, actions_n, sample_action_pos, qrss_action_pos, error); - if (tag_id < 0 || (!fdb_tx && !tag_id)) { + if (tag_id < 0 || (add_tag && !tag_id)) { ret = -rte_errno; goto exit; } diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index ee85c9d..18d5cfc 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -552,6 +552,7 @@ struct mlx5_flow_sub_actions_list { void *dr_cnt_action; void *dr_port_id_action; void *dr_encap_action; + void *dr_jump_action; }; /* Sample sub-actions resource list. */ @@ -561,6 +562,7 @@ struct mlx5_flow_sub_actions_idx { uint32_t cnt; uint32_t rix_port_id_action; /**< Index to port ID action resource. */ uint32_t rix_encap_decap; /**< Index to encap/decap resource. */ + uint32_t rix_jump; /**< Index to the jump action resource. */ }; /* Sample action resource structure. */ diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index e4736ee..d82d22e 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -76,7 +76,7 @@ static int flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev, - uint32_t encap_decap_idx); + uint32_t encap_decap_idx); static int flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev, @@ -84,6 +84,10 @@ static void flow_dv_shared_rss_action_release(struct rte_eth_dev *dev, uint32_t srss); +static int +flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev, + uint32_t rix_jump); + /** * Initialize flow attributes structure according to flow items' types. * @@ -3596,7 +3600,7 @@ struct mlx5_cache_entry * (dev, &res, dev_flow, error); } -static int fdb_mirror; +static int fdb_mirror_limit; /** * Validate the modify-header actions. @@ -3625,7 +3629,7 @@ struct mlx5_cache_entry * RTE_FLOW_ERROR_TYPE_ACTION, NULL, "can't have encap action before" " modify action"); - if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) && fdb_mirror) + if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) && fdb_mirror_limit) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, NULL, "can't support sample action before" @@ -3961,12 +3965,6 @@ struct mlx5_cache_entry * return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, NULL, "jump with meter not support"); - if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) && fdb_mirror) - return rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, NULL, - "E-Switch mirroring can't support" - " Sample action and jump action in" - " same flow now"); if (!action->conf) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_CONF, @@ -4366,8 +4364,8 @@ struct mlx5_hlist_entry * uint16_t queue_index = 0xFFFF; int actions_n = 0; int ret; - fdb_mirror = 0; + fdb_mirror_limit = 0; if (!sample) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, action, @@ -4484,7 +4482,7 @@ struct mlx5_hlist_entry * "E-Switch doesn't support " "any optional action " "for sampling"); - fdb_mirror = 1; + fdb_mirror_limit = 1; if (sub_action_flags & MLX5_FLOW_ACTION_QUEUE) return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, @@ -8706,6 +8704,10 @@ struct mlx5_hlist_entry * flow_dv_counter_free(dev, act_res->cnt); act_res->cnt = 0; } + if (act_res->rix_jump) { + flow_dv_jump_tbl_resource_release(dev, act_res->rix_jump); + act_res->rix_jump = 0; + } } int @@ -8918,6 +8920,7 @@ struct mlx5_cache_entry * struct mlx5dv_dr_domain *domain; uint32_t idx = 0, res_idx = 0; struct rte_flow_error *error = ctx->error; + uint64_t action_flags; int ret; /* Register new destination array resource. */ @@ -8951,19 +8954,31 @@ struct mlx5_cache_entry * } dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST; sample_act = &resource->sample_act[idx]; - if (sample_act->action_flags == MLX5_FLOW_ACTION_QUEUE) { + action_flags = sample_act->action_flags; + switch (action_flags) { + case MLX5_FLOW_ACTION_QUEUE: dest_attr[idx]->dest = sample_act->dr_queue_action; - } else if (sample_act->action_flags == - (MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_ENCAP)) { + break; + case (MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_ENCAP): dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST_REFORMAT; dest_attr[idx]->dest_reformat = &dest_reformat[idx]; dest_attr[idx]->dest_reformat->reformat = sample_act->dr_encap_action; dest_attr[idx]->dest_reformat->dest = sample_act->dr_port_id_action; - } else if (sample_act->action_flags == - MLX5_FLOW_ACTION_PORT_ID) { + break; + case MLX5_FLOW_ACTION_PORT_ID: dest_attr[idx]->dest = sample_act->dr_port_id_action; + break; + case MLX5_FLOW_ACTION_JUMP: + dest_attr[idx]->dest = sample_act->dr_jump_action; + break; + default: + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + NULL, + "unsupported actions type"); + goto error; } } /* create a dest array actioin */ @@ -9000,6 +9015,10 @@ struct mlx5_cache_entry * !flow_dv_port_id_action_resource_release(dev, act_res->rix_port_id_action)) act_res->rix_port_id_action = 0; + if (act_res->rix_jump && + !flow_dv_jump_tbl_resource_release(dev, + act_res->rix_jump)) + act_res->rix_jump = 0; if (dest_attr[idx]) mlx5_free(dest_attr[idx]); } @@ -9336,6 +9355,14 @@ struct mlx5_cache_entry * sample_act->dr_port_id_action = dev_flow->dv.port_id_action->action; } + if (sample_act->action_flags & MLX5_FLOW_ACTION_JUMP) { + normal_idx++; + mdest_res->sample_idx[dest_index].rix_jump = + dev_flow->handle->rix_jump; + sample_act->dr_jump_action = + dev_flow->dv.jump->action; + dev_flow->handle->rix_jump = 0; + } sample_act->actions_num = normal_idx; /* update sample action resource into first index of array */ mdest_res->ft_type = res->ft_type; @@ -10094,6 +10121,8 @@ struct mlx5_cache_entry * dev_flow->dv.jump->action; action_flags |= MLX5_FLOW_ACTION_JUMP; dev_flow->handle->fate_action = MLX5_FLOW_FATE_JUMP; + sample_act->action_flags |= MLX5_FLOW_ACTION_JUMP; + num_of_dest++; break; case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: case RTE_FLOW_ACTION_TYPE_SET_MAC_DST: @@ -10316,7 +10345,8 @@ struct mlx5_cache_entry * * So need remove the original these actions in the flow and only * use the sample action instead of. */ - if (num_of_dest > 1 && sample_act->dr_port_id_action) { + if (num_of_dest > 1 && + (sample_act->dr_port_id_action || sample_act->dr_jump_action)) { int i; void *temp_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0}; @@ -10326,6 +10356,9 @@ struct mlx5_cache_entry * dev_flow->dv.actions[i]) || (sample_act->dr_port_id_action && sample_act->dr_port_id_action == + dev_flow->dv.actions[i]) || + (sample_act->dr_jump_action && + sample_act->dr_jump_action == dev_flow->dv.actions[i])) continue; temp_actions[tmp_actions_n++] = dev_flow->dv.actions[i]; @@ -10924,21 +10957,21 @@ struct mlx5_cache_entry * * * @param dev * Pointer to Ethernet device. - * @param handle - * Pointer to mlx5_flow_handle. + * @param rix_jump + * Index to the jump action resource. * * @return * 1 while a reference on it exists, 0 when freed. */ static int flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev, - struct mlx5_flow_handle *handle) + uint32_t rix_jump) { struct mlx5_priv *priv = dev->data->dev_private; struct mlx5_flow_tbl_data_entry *tbl_data; tbl_data = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_JUMP], - handle->rix_jump); + rix_jump); if (!tbl_data) return 0; return flow_dv_tbl_resource_release(MLX5_SH(dev), &tbl_data->tbl); @@ -11092,7 +11125,7 @@ struct mlx5_cache_entry * mlx5_hrxq_release(dev, handle->rix_hrxq); break; case MLX5_FLOW_FATE_JUMP: - flow_dv_jump_tbl_resource_release(dev, handle); + flow_dv_jump_tbl_resource_release(dev, handle->rix_jump); break; case MLX5_FLOW_FATE_PORT_ID: flow_dv_port_id_action_resource_release(dev, @@ -11188,8 +11221,8 @@ struct mlx5_cache_entry * * * @param dev * Pointer to Ethernet device. - * @param handle - * Pointer to mlx5_flow_handle. + * @param port_id + * Index to port ID action resource. * * @return * 1 while a reference on it exists, 0 when freed.