From patchwork Sun Oct 7 14:25:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dekel Peled X-Patchwork-Id: 46214 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 3C7DF4C80; Sun, 7 Oct 2018 16:27:14 +0200 (CEST) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by dpdk.org (Postfix) with ESMTP id 4DA683977 for ; Sun, 7 Oct 2018 16:27:12 +0200 (CEST) Received: from Internal Mail-Server by MTLPINE1 (envelope-from dekelp@mellanox.com) with ESMTPS (AES256-SHA encrypted); 7 Oct 2018 16:31:57 +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 w97ER1DJ031642; Sun, 7 Oct 2018 17:27:11 +0300 From: Dekel Peled To: yskoh@mellanox.com, shahafs@mellanox.com Cc: dev@dpdk.org, orika@mellanox.com Date: Sun, 7 Oct 2018 17:25:07 +0300 Message-Id: <1538922308-9516-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 v2 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow 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 | 226 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 222 insertions(+), 4 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index 80e7b24..221c76a 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -84,6 +84,167 @@ } /** + * 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 +flow_dv_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_FLOW_ACTION_DROP) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "can't drop and encap in same flow"); + if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP | + MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3)) + return rte_flow_error_set(error, EINVAL, + 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 +flow_dv_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_FLOW_ACTION_DROP) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "can't drop and encap in same flow"); + if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP | + MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3)) + return rte_flow_error_set(error, EINVAL, + 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] dev + * Pointer to rte_eth_dev structure. + * @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 * +flow_dv_create_encap(const struct rte_flow_action *action, + struct rte_eth_dev *dev, + struct rte_flow_error *error) +{ + struct ibv_flow_action *encap_verb = NULL; + const struct rte_flow_action_tunnel_encap *encap_data; + struct priv *priv = dev->data->dev_private; + + encap_data = (const struct rte_flow_action_tunnel_encap *)action->conf; + encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat + (priv->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] dev + * Pointer to rte_eth_dev structure. + * @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 * +flow_dv_create_encap_l3(const struct rte_flow_action *action, + struct rte_eth_dev *dev, + struct rte_flow_error *error) +{ + struct ibv_flow_action *encap_l3_verb = NULL; + const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data; + struct priv *priv = dev->data->dev_private; + + encap_l3_data = + (const struct rte_flow_action_tunnel_encap_l3 *)action->conf; + encap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat + (priv->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. * @@ -330,6 +491,20 @@ action_flags |= MLX5_FLOW_ACTION_COUNT; ++actions_n; break; + case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP: + ret = flow_dv_validate_action_tunnel_encap + (action_flags, actions, attr, error); + if (ret < 0) + return ret; + action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP; + break; + case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3: + ret = flow_dv_validate_action_tunnel_encap_l3 + (action_flags, actions, attr, error); + if (ret < 0) + return ret; + action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3; + break; default: return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, @@ -1042,10 +1217,19 @@ * Flow action to translate. * @param[in, out] dev_flow * Pointer to the mlx5_flow. + * @param[in] dev + * Pointer to rte_eth_dev structure. + * @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 rte_eth_dev *dev, + struct rte_flow_error *error) { const struct rte_flow_action_queue *queue; const struct rte_flow_action_rss *rss; @@ -1092,10 +1276,35 @@ /* Added to array only in apply since we need the QP */ flow->actions |= MLX5_FLOW_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 = + flow_dv_create_encap(action, dev, 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_FLOW_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 = + flow_dv_create_encap_l3(action, dev, 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_FLOW_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 }; @@ -1259,8 +1468,10 @@ 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); + for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { + if (flow_dv_create_action(actions, dev_flow, dev, error)) + return -rte_errno; + } return 0; } @@ -1444,6 +1655,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); } }