From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by dpdk.org (Postfix) with ESMTP id 646A22BAB for ; Wed, 31 Oct 2018 09:00:25 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from dekelp@mellanox.com) with ESMTPS (AES256-SHA encrypted); 31 Oct 2018 09:17:15 +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 w9V7Bn3i020147; Wed, 31 Oct 2018 09:11:59 +0200 From: Dekel Peled To: yskoh@mellanox.com, shahafs@mellanox.com Cc: dev@dpdk.org, orika@mellanox.com Date: Wed, 31 Oct 2018 09:10:46 +0200 Message-Id: <1540969847-48919-7-git-send-email-dekelp@mellanox.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1540498108-18358-1-git-send-email-dekelp@mellanox.com> References: <1540498108-18358-1-git-send-email-dekelp@mellanox.com> Subject: [dpdk-dev] [PATCH v7 6/7] net/mlx5: add raw data encap decap to Direct Verbs 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: , X-List-Received-Date: Wed, 31 Oct 2018 08:00:26 -0000 This patch implements the encap and decap actions, using raw data, in DV flow for MLX5 PMD. Signed-off-by: Dekel Peled --- drivers/net/mlx5/mlx5_flow.h | 12 +- drivers/net/mlx5/mlx5_flow_dv.c | 246 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 241 insertions(+), 17 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index 104a1e6..908123f 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -96,15 +96,19 @@ #define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23) #define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24) #define MLX5_FLOW_ACTION_NVGRE_DECAP (1u << 25) +#define MLX5_FLOW_ACTION_RAW_ENCAP (1u << 26) +#define MLX5_FLOW_ACTION_RAW_DECAP (1u << 27) #define MLX5_FLOW_FATE_ACTIONS \ (MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS) -#define MLX5_FLOW_ENCAP_ACTIONS \ - (MLX5_FLOW_ACTION_VXLAN_ENCAP | MLX5_FLOW_ACTION_NVGRE_ENCAP) +#define MLX5_FLOW_ENCAP_ACTIONS (MLX5_FLOW_ACTION_VXLAN_ENCAP | \ + MLX5_FLOW_ACTION_NVGRE_ENCAP | \ + MLX5_FLOW_ACTION_RAW_ENCAP) -#define MLX5_FLOW_DECAP_ACTIONS \ - (MLX5_FLOW_ACTION_VXLAN_DECAP | MLX5_FLOW_ACTION_NVGRE_DECAP) +#define MLX5_FLOW_DECAP_ACTIONS (MLX5_FLOW_ACTION_VXLAN_DECAP | \ + MLX5_FLOW_ACTION_NVGRE_DECAP | \ + MLX5_FLOW_ACTION_RAW_DECAP) #ifndef IPPROTO_MPLS #define IPPROTO_MPLS 137 diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index b3ee237..d1c811f 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -177,6 +177,101 @@ } /** + * Validate the raw 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_errno is set. + */ +static int +flow_dv_validate_action_raw_encap(uint64_t action_flags, + const struct rte_flow_action *action, + const struct rte_flow_attr *attr, + struct rte_flow_error *error) +{ + if (!(action->conf)) + 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_ENCAP_ACTIONS) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "can only have a single encap" + " action in a flow"); + /* encap without preceding decap is not supported for ingress */ + if (attr->ingress && !(action_flags & MLX5_FLOW_ACTION_RAW_DECAP)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, + NULL, + "encap action not supported for " + "ingress"); + return 0; +} + +/** + * Validate the raw decap 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_errno is set. + */ +static int +flow_dv_validate_action_raw_decap(uint64_t action_flags, + const struct rte_flow_action *action, + 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 decap in same flow"); + if (action_flags & MLX5_FLOW_ENCAP_ACTIONS) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "can't have encap action before" + " decap action"); + if (action_flags & MLX5_FLOW_DECAP_ACTIONS) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "can only have a single decap" + " action in a flow"); + /* decap action is valid on egress only if it is followed by encap */ + if (attr->egress) { + for (; action->type != RTE_FLOW_ACTION_TYPE_END && + action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP; + action++) { + } + if (action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) + return rte_flow_error_set + (error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, + NULL, "decap action not supported" + " for egress"); + } + return 0; +} + +/** * Get the size of specific rte_flow_item_type * * @param[in] item_type @@ -423,23 +518,34 @@ { struct ibv_flow_action *verbs_action = NULL; const struct rte_flow_item *encap_data; + const struct rte_flow_action_raw_encap *raw_encap_data; struct priv *priv = dev->data->dev_private; uint8_t buf[MLX5_ENCAP_MAX_LEN]; + uint8_t *buf_ptr = buf; size_t size = 0; int convert_result = 0; - if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) - encap_data = ((const struct rte_flow_action_vxlan_encap *) + if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) { + raw_encap_data = + (const struct rte_flow_action_raw_encap *)action->conf; + buf_ptr = raw_encap_data->data; + size = raw_encap_data->size; + } else { + if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) + encap_data = + ((const struct rte_flow_action_vxlan_encap *) action->conf)->definition; - else - encap_data = ((const struct rte_flow_action_nvgre_encap *) + else + encap_data = + ((const struct rte_flow_action_nvgre_encap *) action->conf)->definition; - convert_result = flow_dv_convert_encap_data(encap_data, buf, - &size, error); - if (convert_result) - return NULL; + convert_result = flow_dv_convert_encap_data(encap_data, buf, + &size, error); + if (convert_result) + return NULL; + } verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat - (priv->ctx, size, buf, + (priv->ctx, size, buf_ptr, MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL, MLX5DV_FLOW_TABLE_TYPE_NIC_TX); if (!verbs_action) @@ -477,6 +583,50 @@ } /** + * Convert raw decap/encap (L3 tunnel) action to DV specification. + * + * @param[in] dev + * Pointer to rte_eth_dev structure. + * @param[in] action + * Pointer to action structure. + * @param[in] attr + * Pointer to the flow attributes. + * @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_action_raw_encap(struct rte_eth_dev *dev, + const struct rte_flow_action *action, + const struct rte_flow_attr *attr, + struct rte_flow_error *error) +{ + struct ibv_flow_action *verbs_action = NULL; + const struct rte_flow_action_raw_encap *encap_data; + struct priv *priv = dev->data->dev_private; + enum mlx5dv_flow_action_packet_reformat_type reformat_type; + enum mlx5dv_flow_table_type ft_type; + + encap_data = (const struct rte_flow_action_raw_encap *)action->conf; + reformat_type = attr->egress ? + MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL : + MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2; + ft_type = attr->egress ? + MLX5DV_FLOW_TABLE_TYPE_NIC_TX : + MLX5DV_FLOW_TABLE_TYPE_NIC_RX; + verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat + (priv->ctx, encap_data->size, + (encap_data->size ? encap_data->data : NULL), + reformat_type, ft_type); + if (!verbs_action) + rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, + NULL, "cannot create encap action"); + return verbs_action; +} + +/** * Verify the @p attributes will be correctly understood by the NIC and store * them in the @p flow if everything is correct. * @@ -731,7 +881,6 @@ RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ? MLX5_FLOW_ACTION_VXLAN_ENCAP : MLX5_FLOW_ACTION_NVGRE_ENCAP; - ++actions_n; break; case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: @@ -744,7 +893,24 @@ RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ? MLX5_FLOW_ACTION_VXLAN_DECAP : MLX5_FLOW_ACTION_NVGRE_DECAP; - + ++actions_n; + break; + case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: + ret = flow_dv_validate_action_raw_encap(action_flags, + actions, attr, + error); + if (ret < 0) + return ret; + action_flags |= MLX5_FLOW_ACTION_RAW_ENCAP; + ++actions_n; + break; + case RTE_FLOW_ACTION_TYPE_RAW_DECAP: + ret = flow_dv_validate_action_raw_decap(action_flags, + actions, attr, + error); + if (ret < 0) + return ret; + action_flags |= MLX5_FLOW_ACTION_RAW_DECAP; ++actions_n; break; default: @@ -1459,6 +1625,8 @@ * Flow action to translate. * @param[in, out] dev_flow * Pointer to the mlx5_flow. + * @param[in] attr + * Pointer to the flow attributes. * @param[out] error * Pointer to the error structure. * @@ -1469,12 +1637,14 @@ flow_dv_create_action(struct rte_eth_dev *dev, const struct rte_flow_action *action, struct mlx5_flow *dev_flow, + const struct rte_flow_attr *attr, struct rte_flow_error *error) { const struct rte_flow_action_queue *queue; const struct rte_flow_action_rss *rss; int actions_n = dev_flow->dv.actions_n; struct rte_flow *flow = dev_flow->flow; + const struct rte_flow_action *action_ptr = action; switch (action->type) { case RTE_FLOW_ACTION_TYPE_VOID: @@ -1550,6 +1720,56 @@ MLX5_FLOW_ACTION_NVGRE_DECAP; actions_n++; break; + case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: + /* Handle encap action with preceding decap */ + if (flow->actions & MLX5_FLOW_ACTION_RAW_DECAP) { + dev_flow->dv.actions[actions_n].type = + MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION; + dev_flow->dv.actions[actions_n].action = + flow_dv_create_action_raw_encap + (dev, action, + attr, error); + if (!(dev_flow->dv.actions[actions_n].action)) + return -rte_errno; + dev_flow->dv.encap_decap_verbs_action = + dev_flow->dv.actions[actions_n].action; + } else { + /* Handle encap action without preceding decap */ + dev_flow->dv.actions[actions_n].type = + MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION; + dev_flow->dv.actions[actions_n].action = + flow_dv_create_action_l2_encap + (dev, action, error); + if (!(dev_flow->dv.actions[actions_n].action)) + return -rte_errno; + dev_flow->dv.encap_decap_verbs_action = + dev_flow->dv.actions[actions_n].action; + } + flow->actions |= MLX5_FLOW_ACTION_RAW_ENCAP; + actions_n++; + break; + case RTE_FLOW_ACTION_TYPE_RAW_DECAP: + /* Check if this decap action is followed by encap. */ + for (; action_ptr->type != RTE_FLOW_ACTION_TYPE_END && + action_ptr->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP; + action_ptr++) { + } + /* Handle decap action only if it isn't followed by encap */ + if (action_ptr->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) { + dev_flow->dv.actions[actions_n].type = + MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION; + dev_flow->dv.actions[actions_n].action = + flow_dv_create_action_l2_decap(dev, + error); + if (!(dev_flow->dv.actions[actions_n].action)) + return -rte_errno; + dev_flow->dv.encap_decap_verbs_action = + dev_flow->dv.actions[actions_n].action; + actions_n++; + } + /* If decap is followed by encap, handle it at encap case. */ + flow->actions |= MLX5_FLOW_ACTION_RAW_DECAP; + break; default: break; } @@ -1692,7 +1912,7 @@ struct mlx5_flow *dev_flow, const struct rte_flow_attr *attr, const struct rte_flow_item items[], - const struct rte_flow_action actions[] __rte_unused, + const struct rte_flow_action actions[], struct rte_flow_error *error) { struct priv *priv = dev->data->dev_private; @@ -1722,7 +1942,7 @@ if (flow_dv_matcher_register(dev, &matcher, dev_flow, error)) return -rte_errno; for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) - if (flow_dv_create_action(dev, actions, dev_flow, error)) + if (flow_dv_create_action(dev, actions, dev_flow, attr, error)) return -rte_errno; return 0; } -- 1.8.3.1