From patchwork Thu Sep 27 14:50:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dekel Peled X-Patchwork-Id: 45534 X-Patchwork-Delegate: shahafs@mellanox.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 9C2F01B4D1; Thu, 27 Sep 2018 16:52:17 +0200 (CEST) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by dpdk.org (Postfix) with ESMTP id 6EC501B4D1 for ; Thu, 27 Sep 2018 16:52:15 +0200 (CEST) Received: from Internal Mail-Server by MTLPINE1 (envelope-from dekelp@mellanox.com) with ESMTPS (AES256-SHA encrypted); 27 Sep 2018 16:56:44 +0200 Received: from mtl-vdi-280.wap.labs.mlnx. (mtl-vdi-280.wap.labs.mlnx [10.128.130.87]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id w8REq7gL013802; Thu, 27 Sep 2018 17:52:10 +0300 From: Dekel Peled To: dev@dpdk.org, shahafs@mellanox.com, yskoh@mellanox.com Cc: orika@mellanox.com Date: Thu, 27 Sep 2018 17:50:44 +0300 Message-Id: <1538059845-35896-4-git-send-email-dekelp@mellanox.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1538059845-35896-1-git-send-email-dekelp@mellanox.com> References: <1538059845-35896-1-git-send-email-dekelp@mellanox.com> Subject: [dpdk-dev] [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 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" This patch adds support for Direct Verbs encap operations, L2 and L3. Signed-off-by: Dekel Peled --- drivers/net/mlx5/mlx5_flow_dv.c | 249 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 244 insertions(+), 5 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index 1f3fcb8..50925ac 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -85,6 +85,178 @@ } /** + * Validate the tunnel encap action. + * + * @param[in] action_flags + * holds the actions detected until now. + * @param[in] action + * Pointer to the encap action. + * @param[in] attr + * Pointer to flow attributes + * @param[out] error + * Pointer to error structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_ernno is set. + */ +static int +mlx5_flow_validate_action_tunnel_encap(uint64_t action_flags, + const struct rte_flow_action *action, + const struct rte_flow_attr *attr, + struct rte_flow_error *error) +{ + const struct rte_flow_action_tunnel_encap *tunnel_encap = action->conf; + + if (!tunnel_encap || !(tunnel_encap->buf)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + action, + "configuration cannot be null"); + if (action_flags & MLX5_ACTION_DROP) + return rte_flow_error_set(error, + ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, + NULL, + "can't drop and encap in same flow"); + if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP | + MLX5_ACTION_TUNNEL_ENCAP_L3)) + return rte_flow_error_set(error, + ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, + NULL, + "can't have 2 encap actions in same" + " flow"); + if (attr->ingress) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, + NULL, + "encap action not supported for " + "ingress"); + return 0; +} + +/** + * Validate the tunnel encap L3 action + * + * @param[in] action_flags + * holds the actions detected until now. + * @param[in] action + * Pointer to the encap action. + * @param[in] attr + * Pointer to flow attributes + * @param[out] error + * Pointer to error structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_ernno is set. + */ +static int +mlx5_flow_validate_action_tunnel_encap_l3(uint64_t action_flags, + const struct rte_flow_action *action, + const struct rte_flow_attr *attr, + struct rte_flow_error *error) +{ + const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 = + action->conf; + + if (!tunnel_encap_l3 || !(tunnel_encap_l3->buf)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + action, + "configuration cannot be null"); + if (action_flags & MLX5_ACTION_DROP) + return rte_flow_error_set(error, + ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, + NULL, + "can't drop and encap in same flow"); + if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP | + MLX5_ACTION_TUNNEL_ENCAP_L3)) + return rte_flow_error_set(error, + ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, + NULL, + "can't have 2 encap actions in same" + " flow"); + if (attr->ingress) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, + NULL, + "encap action not supported for " + "ingress"); + return 0; +} + +/** + * Convert encap action to DV specification. + * + * @param[in] action + * Pointer to action structure. + * @param[in] ctx + * Verbs context. + * @param[out] error + * Pointer to the error structure. + * + * @return + * Pointer to action on success, NULL otherwise and rte_errno is set. + */ +static struct ibv_flow_action * +mlx5_flow_dv_create_encap(const struct rte_flow_action *action, + struct ibv_context *ctx, + struct rte_flow_error *error) +{ + struct ibv_flow_action *encap_verb = NULL; + const struct rte_flow_action_tunnel_encap *encap_data; + + encap_data = (const struct rte_flow_action_tunnel_encap *)action->conf; + encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat(ctx, + encap_data->size, + encap_data->size ? encap_data->buf : + NULL, + MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL, + MLX5DV_FLOW_TABLE_TYPE_NIC_TX); + if (!encap_verb) + rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, + NULL, "cannot create encap action"); + return encap_verb; +} + +/** + * Convert encap L3 action to DV specification. + * + * @param[in] action + * Pointer to action structure. + * @param[in] ctx + * Verbs context. + * @param[out] error + * Pointer to the error structure. + * + * @return + * Pointer to action on success, NULL otherwise and rte_errno is set. + */ +static struct ibv_flow_action * +mlx5_flow_dv_create_encap_l3(const struct rte_flow_action *action, + struct ibv_context *ctx, + struct rte_flow_error *error) +{ + struct ibv_flow_action *encap_l3_verb = NULL; + const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data; + + encap_l3_data = + (const struct rte_flow_action_tunnel_encap_l3 *)action->conf; + encap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat(ctx, + encap_l3_data->size, + encap_l3_data->size ? encap_l3_data->buf : + NULL, + MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL, + MLX5DV_FLOW_TABLE_TYPE_NIC_TX); + if (!encap_l3_verb) + rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, + NULL, "cannot create encap L3 action"); + return encap_l3_verb; +} + +/** * Verify the @p attributes will be correctly understood by the NIC and store * them in the @p flow if everything is correct. * @@ -337,6 +509,26 @@ action_flags |= MLX5_ACTION_COUNT; ++actions_n; break; + case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP: + ret = mlx5_flow_validate_action_tunnel_encap + (action_flags, + actions, + attr, + error); + if (ret < 0) + return ret; + action_flags |= MLX5_ACTION_TUNNEL_ENCAP; + break; + case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3: + ret = mlx5_flow_validate_action_tunnel_encap_l3 + (action_flags, + actions, + attr, + error); + if (ret < 0) + return ret; + action_flags |= MLX5_ACTION_TUNNEL_ENCAP_L3; + break; default: return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, @@ -1047,10 +1239,19 @@ * Flow action to translate. * @param[in, out] dev_flow * Pointer to the mlx5_flow. + * @param[in] ctx + * Verbs context. + * @param[out] error + * Pointer to the error structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_ernno is set. */ -static void +static int flow_dv_create_action(const struct rte_flow_action *action, - struct mlx5_flow *dev_flow) + struct mlx5_flow *dev_flow, + struct ibv_context *ctx, + struct rte_flow_error *error) { const struct rte_flow_action_queue *queue; const struct rte_flow_action_rss *rss; @@ -1095,10 +1296,35 @@ /* Added to array only in apply since we need the QP */ flow->actions |= MLX5_ACTION_RSS; break; + case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP: + dev_flow->dv.actions[actions_n].type = + MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION; + dev_flow->dv.actions[actions_n].action = + mlx5_flow_dv_create_encap(action, ctx, error); + if (!(dev_flow->dv.actions[actions_n].action)) + return -rte_errno; + dev_flow->dv.encap_verb = + dev_flow->dv.actions[actions_n].action; + flow->actions |= MLX5_ACTION_TUNNEL_ENCAP; + actions_n++; + break; + case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3: + dev_flow->dv.actions[actions_n].type = + MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION; + dev_flow->dv.actions[actions_n].action = + mlx5_flow_dv_create_encap_l3(action, ctx, error); + if (!(dev_flow->dv.actions[actions_n].action)) + return -rte_errno; + dev_flow->dv.encap_verb = + dev_flow->dv.actions[actions_n].action; + flow->actions |= MLX5_ACTION_TUNNEL_ENCAP_L3; + actions_n++; + break; default: break; } dev_flow->dv.actions_n = actions_n; + return 0; } static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 }; @@ -1247,6 +1473,7 @@ }; void *match_value = dev_flow->dv.value.buf; uint8_t inner = 0; + int retval = 0; if (priority == MLX5_FLOW_PRIO_RSVD) priority = priv->config.flow_prio - 1; @@ -1262,9 +1489,14 @@ matcher.egress = attr->egress; if (flow_dv_matcher_register(dev, &matcher, dev_flow, error)) return -rte_errno; - for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) - flow_dv_create_action(actions, dev_flow); - return 0; + for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { + retval = + flow_dv_create_action(actions, dev_flow, priv->ctx, error); + if (retval) + break; + } + + return retval; } /** @@ -1447,6 +1679,13 @@ LIST_REMOVE(dev_flow, next); if (dev_flow->dv.matcher) flow_dv_matcher_release(dev, dev_flow->dv.matcher); + + if (dev_flow->dv.encap_verb) { + claim_zero(mlx5_glue->destroy_flow_action + (dev_flow->dv.encap_verb)); + dev_flow->dv.encap_verb = NULL; + } + rte_free(dev_flow); } }