From patchwork Sun Dec 3 11:25:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Baum X-Patchwork-Id: 134769 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 152B64365F; Sun, 3 Dec 2023 12:29:02 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0BEEB410F6; Sun, 3 Dec 2023 12:27:06 +0100 (CET) Received: from NAM12-MW2-obe.outbound.protection.outlook.com (mail-mw2nam12on2046.outbound.protection.outlook.com [40.107.244.46]) by mails.dpdk.org (Postfix) with ESMTP id D575D410D3 for ; Sun, 3 Dec 2023 12:27:04 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=SUGSsat8mSENkDXm6DObmf3hxPBDxWfRRRo9l1ufcrKcPGRVSbUG/3w81p/rAdJRx/WRUEmhRn0507bW7gSl4DmY1RUaxAu5r8c33nFqBnWBZvOk5itxpzEHki4Br/l+mmmrHsXwEqyjSAAYMJdeq3DFsA7ggEZwWz0U7b3Up19QrtTX+TvcXrDBXXMeHoQDrAQKItmcIwTadEP44T1fp0co7WdfmLSbcse+0bPyqruDLqxh7BB8SfCalEBm5XU7KTbNNxi56nz1DPZjYOSdBbxxpiq74Ela/F4MBIDWs+4T9NcPwVOohp3rZSQ74TUwlDXW6qYSCYxZTW+gJDqPQA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=vHb8vwA5hxnDpVrorNzrufO+TMJxDfIj0X5VV+YogdM=; b=TUE9Rc/TeT8OrSBesm4ph4fE0Q7XeVoSFpT36FMLxjQ2+9rOxlatMyDrXoOMEGLUhBevJwdVsagvGt6245HuniJherdxrWtbn7f5WMUVJCIhmlJaLNvWCudQVt4vp7upewY856DnpVs8Nrz8z645ezlIS9NMo9+Q0UedZBU2SpIFib6JTJeN42mWk0KaN16Aj1/EDtHCAekyV4y2pERORlI6AUblQIZLVahbGY44ppPItKBM8P6saE2kMMMolgoYFvn7yYoBA+MJzQWjGR4JiUYeeUoLVhmQsTj2FbLMj+hrwh75bXcE+jlbMB7IqbAyjL8hIsLWPigCCfVh74a19Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.117.160) smtp.rcpttodomain=dpdk.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=vHb8vwA5hxnDpVrorNzrufO+TMJxDfIj0X5VV+YogdM=; b=ZYf0UaIZZVESeqn2juOGVO6dm8t9vRny8EI2THsh+XAQht+lQ2nVf5cqLkwAkiokIxl94HQiyiJMe/0Ir/wL/XoFdkjOnD9Qsk5uz6HwD9ynH1swf2iwG1KGquk7OydMl02uKUNbjYpitvxX/2FEwXAAmQ7ts2ylAs86deHxuFFpsXRBsGNYkBLdLleX4ZEjwuuiQuxvpTFCr8+DPXLe5n8/ajkQ7woNH6GGvAKHu/goPSqUvq1KQOKlIsydcvgdmHBXife2lm/C8UXQPA1qoeJCSayU/3JOMaBTDTpJZWvtdc7e/7rm+yjLMMlHfuHYT5SFvpyafbUppAD8R8/Ihg== Received: from MW4PR04CA0181.namprd04.prod.outlook.com (2603:10b6:303:86::6) by PH0PR12MB7958.namprd12.prod.outlook.com (2603:10b6:510:285::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7046.32; Sun, 3 Dec 2023 11:27:02 +0000 Received: from CO1PEPF000042AB.namprd03.prod.outlook.com (2603:10b6:303:86:cafe::a0) by MW4PR04CA0181.outlook.office365.com (2603:10b6:303:86::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7046.33 via Frontend Transport; Sun, 3 Dec 2023 11:27:01 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.117.160) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.117.160 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.117.160; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.117.160) by CO1PEPF000042AB.mail.protection.outlook.com (10.167.243.40) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7068.20 via Frontend Transport; Sun, 3 Dec 2023 11:27:01 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by mail.nvidia.com (10.129.200.66) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.41; Sun, 3 Dec 2023 03:26:46 -0800 Received: from rnnvmail205.nvidia.com (10.129.68.10) by rnnvmail201.nvidia.com (10.129.68.8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.41; Sun, 3 Dec 2023 03:26:45 -0800 Received: from nvidia.com (10.127.8.13) by mail.nvidia.com (10.129.68.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.41 via Frontend Transport; Sun, 3 Dec 2023 03:26:44 -0800 From: Michael Baum To: CC: Matan Azrad , Raslan Darawsheh , Viacheslav Ovsiienko , Ori Kam , Suanming Mou Subject: [PATCH v1 23/23] net/mlx5: add support for modify GENEVE option header Date: Sun, 3 Dec 2023 13:25:43 +0200 Message-ID: <20231203112543.844014-24-michaelba@nvidia.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231203112543.844014-1-michaelba@nvidia.com> References: <20231203112543.844014-1-michaelba@nvidia.com> MIME-Version: 1.0 X-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PEPF000042AB:EE_|PH0PR12MB7958:EE_ X-MS-Office365-Filtering-Correlation-Id: 41c79ece-988e-4620-4dfc-08dbf3f2c537 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 9cVtvPmPgIzbTnSFTSZ79XVRLsLbVxnB44dUDGWMl76kzSAycP6xgWZKfkXaE7mc8cEPCSWmKmhyXLKUYgTrJRvctqJA3846gItOHvfOWQiVvU0qnp4gzf1MS64BLXfaUkMs0f+tMKMx5ORif+oP3GCiW9HJCwOHlsqktY7agRu1CsIzi3zILnnE3ZxFdnNqmSr+U3k1ghyqkWpU0nLG4rRRB4AiY25TQvS9NZo9hzCAPldkxXd9AEXQJ1NTkkatvnY9d7OROL1QdfaO0g7rVkMGLqBi3nHJDnj16F8Pt7uFTic2H0vqNoYzWg+BDV3C/hXIFYWsQoUWgLQ7W4s1pbp24fTyzXhysaROEFP7AESBmpL35ul+7qKavkROutVOL4YRH+QLxImNFg7KOdR+dh9/0YkMsEYTK6ZN786ioij+etMg4sL/U0Oe+HFellvy0A5HgD2R6XRjQtTQMzwzW+rVsJ/wDHmg5KdRHW0eZar+LJxx0D5LADeyCT5RQOlbtouAdeNSAP8NbntjQIb65WPPpKSiJr+t9pKw+IuCtu5fYs8hsInvd+dgE2ExfdNztCB2NT6sCSngGPay74rJd/fB2mieqKwdogqylzzKQX/CK3z66sFGqJSPdqWP/p994J54wPhFokaFXyyl7ncs4LsC1dzOwdeMYJ3t3taoAyRjuCMp9jBLiG7ZIEcrbsd/F/FEVT++o2HRry89Q5A1CagMrD2ca0M14vhIuzxfgQq2tn/SsojL8MPa08DPsV2F X-Forefront-Antispam-Report: CIP:216.228.117.160; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:mail.nvidia.com; PTR:dc6edge1.nvidia.com; CAT:NONE; SFS:(13230031)(4636009)(39860400002)(396003)(376002)(346002)(136003)(230922051799003)(1800799012)(64100799003)(451199024)(82310400011)(186009)(46966006)(40470700004)(36840700001)(70586007)(70206006)(356005)(2616005)(55016003)(336012)(6286002)(26005)(7636003)(40480700001)(4326008)(478600001)(316002)(54906003)(36860700001)(6916009)(7696005)(82740400003)(1076003)(426003)(83380400001)(47076005)(107886003)(8936002)(8676002)(86362001)(5660300002)(40460700003)(36756003)(41300700001)(2906002)(30864003); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 03 Dec 2023 11:27:01.7865 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 41c79ece-988e-4620-4dfc-08dbf3f2c537 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[216.228.117.160]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: CO1PEPF000042AB.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR12MB7958 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 Add support for GENEVE option fields modification. Only fields configured in parser creation can be modified. Signed-off-by: Michael Baum --- doc/guides/nics/mlx5.rst | 4 + doc/guides/rel_notes/release_24_03.rst | 3 + drivers/net/mlx5/mlx5_flow.h | 21 +++++ drivers/net/mlx5/mlx5_flow_dv.c | 78 ++++++++++++++++- drivers/net/mlx5/mlx5_flow_geneve.c | 117 +++++++++++++++++++++++++ drivers/net/mlx5/mlx5_flow_hw.c | 71 ++++++++++----- 6 files changed, 268 insertions(+), 26 deletions(-) diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index fceb5bd58b..85820d7931 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -582,6 +582,10 @@ Limitations - Modification of GENEVE Network ID's is not supported when configured ``FLEX_PARSER_PROFILE_ENABLE`` supports Geneve TLV options. See :ref:`mlx5_firmware_config` for more flex parser information. + - Modification of GENEVE TLV option fields is supported only for HW steering. + Only DWs configured in :ref:`parser creation ` can be modified, + 'type' and 'class' fields can be modified when ``match_on_class_mode=2``. + - Modification of GENEVE TLV option data supports one DW per action. - Encapsulation levels are not supported, can modify outermost header fields only. - Offsets cannot skip past the boundary of a field. - If the field type is ``RTE_FLOW_FIELD_MAC_TYPE`` diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst index 8a99d6bfa4..f8d87c8a3c 100644 --- a/doc/guides/rel_notes/release_24_03.rst +++ b/doc/guides/rel_notes/release_24_03.rst @@ -60,6 +60,9 @@ New Features * Added HW steering support for ``RTE_FLOW_ITEM_TYPE_GENEVE`` flow item. * Added HW steering support for ``RTE_FLOW_ITEM_TYPE_GENEVE_OPT`` flow item. * Added HW steering support for modify field ``RTE_FLOW_FIELD_GENEVE_VNI`` flow action. + * Added HW steering support for modify field ``RTE_FLOW_FIELD_GENEVE_OPT_TYPE`` flow action. + * Added HW steering support for modify field ``RTE_FLOW_FIELD_GENEVE_OPT_CLASS`` flow action. + * Added HW steering support for modify field ``RTE_FLOW_FIELD_GENEVE_OPT_DATA`` flow action. Removed Items diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index 808f364c6c..65fe5be2fd 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -1805,6 +1805,25 @@ mlx5_get_geneve_hl_data(const void *dr_ctx, uint8_t type, uint16_t class, struct mlx5_hl_data ** const hl_dws, bool *ok_bit_on_class); +/** + * Get modify field ID for single DW inside configured GENEVE TLV option. + * + * @param[in] dr_ctx + * Pointer to HW steering DR context. + * @param[in] type + * GENEVE TLV option type. + * @param[in] class + * GENEVE TLV option class. + * @param[in] dw_offset + * Offset of DW inside the option. + * + * @return + * Modify field ID on success, negative errno otherwise and rte_errno is set. + */ +int +mlx5_get_geneve_option_modify_field_id(const void *dr_ctx, uint8_t type, + uint16_t class, uint8_t dw_offset); + void * mlx5_geneve_tlv_parser_create(uint16_t port_id, const struct rte_pmd_mlx5_geneve_tlv tlv_list[], @@ -1813,6 +1832,8 @@ int mlx5_geneve_tlv_parser_destroy(void *handle); int mlx5_flow_geneve_tlv_option_validate(struct mlx5_priv *priv, const struct rte_flow_item *geneve_opt, struct rte_flow_error *error); +int mlx5_geneve_opt_modi_field_get(struct mlx5_priv *priv, + const struct rte_flow_action_modify_data *data); struct mlx5_geneve_tlv_options_mng; int mlx5_geneve_tlv_option_register(struct mlx5_priv *priv, diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index bb3d7ddc3c..2a7ee4e91f 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -1446,6 +1446,21 @@ mlx5_mpls_modi_field_get(const struct rte_flow_action_modify_data *data) return MLX5_MODI_IN_MPLS_LABEL_0 + data->tag_index; } +static __rte_always_inline int +flow_geneve_opt_modi_field_get(struct mlx5_priv *priv, + const struct rte_flow_action_modify_data *data) +{ +#ifdef HAVE_MLX5_HWS_SUPPORT + return mlx5_geneve_opt_modi_field_get(priv, data); +#else + (void)priv; + (void)data; + DRV_LOG(ERR, "GENEVE option modification is not supported."); + rte_errno = ENOTSUP; + return -rte_errno; +#endif +} + static void mlx5_modify_flex_item(const struct rte_eth_dev *dev, const struct mlx5_flex_item *flex, @@ -1579,9 +1594,11 @@ mlx5_flow_field_id_to_modify_info const struct rte_flow_attr *attr, struct rte_flow_error *error) { struct mlx5_priv *priv = dev->data->dev_private; + enum mlx5_modification_field modi_id; uint32_t idx = 0; uint32_t off_be = 0; uint32_t length = 0; + switch ((int)data->field) { case RTE_FLOW_FIELD_START: /* not supported yet */ @@ -1892,6 +1909,48 @@ mlx5_flow_field_id_to_modify_info else info[idx].offset = off_be; break; + case RTE_FLOW_FIELD_GENEVE_OPT_TYPE: + MLX5_ASSERT(data->offset + width <= 8); + modi_id = flow_geneve_opt_modi_field_get(priv, data); + if (modi_id < 0) + return; + /* Type is on bits 16-8 of GENEVE option header (DW0). */ + off_be = 32 - (16 + data->offset + width); + info[idx] = (struct field_modify_info){4, 0, modi_id}; + if (mask) + mask[idx] = flow_modify_info_mask_32(width, off_be); + else + info[idx].offset = off_be; + break; + case RTE_FLOW_FIELD_GENEVE_OPT_CLASS: + MLX5_ASSERT(data->offset + width <= 16); + modi_id = flow_geneve_opt_modi_field_get(priv, data); + if (modi_id < 0) + return; + /* Class is on bits 31-16 of GENEVE option header (DW0). */ + off_be = 32 - (data->offset + width); + info[idx] = (struct field_modify_info){4, 0, modi_id}; + if (mask) + mask[idx] = flow_modify_info_mask_32(width, off_be); + else + info[idx].offset = off_be; + break; + case RTE_FLOW_FIELD_GENEVE_OPT_DATA: + if ((data->offset % 32) + width > 32) { + DRV_LOG(ERR, "Geneve TLV option data is per DW."); + return; + } + modi_id = flow_geneve_opt_modi_field_get(priv, data); + if (modi_id < 0) + return; + /* Use offset inside DW. */ + off_be = 32 - ((data->offset % 32) + width); + info[idx] = (struct field_modify_info){4, 0, modi_id}; + if (mask) + mask[idx] = flow_modify_info_mask_32(width, off_be); + else + info[idx].offset = off_be; + break; case RTE_FLOW_FIELD_GTP_TEID: MLX5_ASSERT(data->offset + width <= 32); off_be = 32 - (data->offset + width); @@ -1905,8 +1964,8 @@ mlx5_flow_field_id_to_modify_info case RTE_FLOW_FIELD_MPLS: MLX5_ASSERT(data->offset + width <= 32); off_be = 32 - (data->offset + width); - info[idx] = (struct field_modify_info){4, 0, - mlx5_mpls_modi_field_get(data)}; + modi_id = mlx5_mpls_modi_field_get(data); + info[idx] = (struct field_modify_info){4, 0, modi_id}; if (mask) mask[idx] = flow_modify_info_mask_32(width, off_be); else @@ -5388,6 +5447,21 @@ flow_dv_validate_action_modify_field(struct rte_eth_dev *dev, RTE_FLOW_ERROR_TYPE_ACTION, action, "modifications of the GENEVE Network" " Identifier is not supported"); + if (dst_data->field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE || + src_data->field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "modifications of the GENEVE option type is not supported"); + if (dst_data->field == RTE_FLOW_FIELD_GENEVE_OPT_CLASS || + src_data->field == RTE_FLOW_FIELD_GENEVE_OPT_CLASS) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "modifications of the GENEVE option class is not supported"); + if (dst_data->field == RTE_FLOW_FIELD_GENEVE_OPT_DATA || + src_data->field == RTE_FLOW_FIELD_GENEVE_OPT_DATA) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "modifications of the GENEVE option data is not supported"); if (dst_data->field == RTE_FLOW_FIELD_MPLS || src_data->field == RTE_FLOW_FIELD_MPLS) return rte_flow_error_set(error, ENOTSUP, diff --git a/drivers/net/mlx5/mlx5_flow_geneve.c b/drivers/net/mlx5/mlx5_flow_geneve.c index f3ee414d02..d5847a60e9 100644 --- a/drivers/net/mlx5/mlx5_flow_geneve.c +++ b/drivers/net/mlx5/mlx5_flow_geneve.c @@ -254,6 +254,123 @@ mlx5_geneve_tlv_options_unregister(struct mlx5_priv *priv, mng->nb_options = 0; } +/** + * Get single DW resource from given option. + * + * @param option + * Pointer to single GENEVE TLV option. + * @param offset + * Offset of DW related to option start. + * + * @return + * DW resource on success, NULL otherwise and rte_errno is set. + */ +static struct mlx5_geneve_tlv_resource * +mlx5_geneve_tlv_option_get_resource_by_offset(struct mlx5_geneve_tlv_option *option, + uint8_t offset) +{ + uint8_t i; + + for (i = 0; option->resources[i].obj != NULL; ++i) { + if (option->resources[i].offset < offset) + continue; + if (option->resources[i].offset == offset) + return &option->resources[i]; + break; + } + DRV_LOG(ERR, "The DW in offset %u wasn't configured.", offset); + rte_errno = EINVAL; + return NULL; +} + +int +mlx5_get_geneve_option_modify_field_id(const void *dr_ctx, uint8_t type, + uint16_t class, uint8_t dw_offset) +{ + uint16_t port_id; + + MLX5_ETH_FOREACH_DEV(port_id, NULL) { + struct mlx5_priv *priv; + struct mlx5_geneve_tlv_option *option; + struct mlx5_geneve_tlv_resource *resource; + + priv = rte_eth_devices[port_id].data->dev_private; + if (priv->dr_ctx != dr_ctx) + continue; + /* Find specific option inside list. */ + option = mlx5_geneve_tlv_option_get(priv, type, class); + if (option == NULL) + return -rte_errno; + /* Find specific FW object inside option resources. */ + resource = mlx5_geneve_tlv_option_get_resource_by_offset(option, + dw_offset); + if (resource == NULL) + return -rte_errno; + return resource->modify_field; + } + DRV_LOG(ERR, "DR CTX %p doesn't belong to any DPDK port.", dr_ctx); + rte_errno = EINVAL; + return -rte_errno; +} + +/** + * Get modify field ID for single DW inside configured GENEVE TLV option. + * + * @param[in] priv + * Pointer to port's private data. + * @param[in] data + * Pointer to modify field data structure. + * + * @return + * Modify field ID on success, negative errno otherwise and rte_errno is set. + */ +int +mlx5_geneve_opt_modi_field_get(struct mlx5_priv *priv, + const struct rte_flow_action_modify_data *data) +{ + uint16_t class = data->class_id; + uint8_t type = data->type; + struct mlx5_geneve_tlv_option *option; + struct mlx5_geneve_tlv_resource *resource; + uint8_t offset; + + option = mlx5_geneve_tlv_option_get(priv, type, class); + if (option == NULL) + return -rte_errno; + switch (data->field) { + case RTE_FLOW_FIELD_GENEVE_OPT_TYPE: + case RTE_FLOW_FIELD_GENEVE_OPT_CLASS: + if (!option->match_data[0].dw_mask) { + DRV_LOG(ERR, "DW0 isn't configured"); + rte_errno = EINVAL; + return -rte_errno; + } + resource = &option->resources[0]; + MLX5_ASSERT(resource->offset == 0); + break; + case RTE_FLOW_FIELD_GENEVE_OPT_DATA: + /* + * Convert offset twice: + * - First conversion from bit offset to DW offset. + * - Second conversion is to be related to data start instead + * of option start. + */ + offset = (data->offset >> 5) + 1; + resource = mlx5_geneve_tlv_option_get_resource_by_offset(option, + offset); + break; + default: + DRV_LOG(ERR, + "Field ID %u doesn't describe GENEVE option header.", + data->field); + rte_errno = EINVAL; + return -rte_errno; + } + if (resource == NULL) + return -rte_errno; + return resource->modify_field; +} + /** * Create single GENEVE TLV option sample. * diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c index 22ac4e0a7c..692bbe063e 100644 --- a/drivers/net/mlx5/mlx5_flow_hw.c +++ b/drivers/net/mlx5/mlx5_flow_hw.c @@ -1254,10 +1254,12 @@ flow_hw_modify_field_compile(struct rte_eth_dev *dev, else value = rte_cpu_to_be_32(value); item.spec = &value; - } else if (conf->dst.field == RTE_FLOW_FIELD_GTP_PSC_QFI) { + } else if (conf->dst.field == RTE_FLOW_FIELD_GTP_PSC_QFI || + conf->dst.field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE) { /* - * QFI is passed as an uint8_t integer, but it is accessed through - * a 2nd least significant byte of a 32-bit field in modify header command. + * Both QFI and Geneve option type are passed as an uint8_t integer, + * but it is accessed through a 2nd least significant byte of a 32-bit + * field in modify header command. */ value = *(const uint8_t *)item.spec; value = rte_cpu_to_be_32(value << 8); @@ -2825,12 +2827,14 @@ flow_hw_modify_field_construct(struct mlx5_hw_q_job *job, *value_p = rte_cpu_to_be_32(*value_p << 16); else *value_p = rte_cpu_to_be_32(*value_p); - } else if (mhdr_action->dst.field == RTE_FLOW_FIELD_GTP_PSC_QFI) { + } else if (mhdr_action->dst.field == RTE_FLOW_FIELD_GTP_PSC_QFI || + mhdr_action->dst.field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE) { uint32_t tmp; /* - * QFI is passed as an uint8_t integer, but it is accessed through - * a 2nd least significant byte of a 32-bit field in modify header command. + * Both QFI and Geneve option type are passed as an uint8_t integer, + * but it is accessed through a 2nd least significant byte of a 32-bit + * field in modify header command. */ tmp = values[0]; value_p = (unaligned_uint32_t *)values; @@ -4944,6 +4948,14 @@ flow_hw_modify_field_is_used(const struct rte_flow_action_modify_field *action, return action->src.field == field || action->dst.field == field; } +static bool +flow_hw_modify_field_is_geneve_opt(enum rte_flow_field_id field) +{ + return field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE || + field == RTE_FLOW_FIELD_GENEVE_OPT_CLASS || + field == RTE_FLOW_FIELD_GENEVE_OPT_DATA; +} + static int flow_hw_validate_action_modify_field(struct rte_eth_dev *dev, const struct rte_flow_action *action, @@ -4977,15 +4989,17 @@ flow_hw_validate_action_modify_field(struct rte_eth_dev *dev, ret = flow_validate_modify_field_level(&action_conf->dst, error); if (ret) return ret; - if (action_conf->dst.tag_index && - !flow_modify_field_support_tag_array(action_conf->dst.field)) - return rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, action, - "destination tag index is not supported"); - if (action_conf->dst.class_id) - return rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, action, - "destination class id is not supported"); + if (!flow_hw_modify_field_is_geneve_opt(action_conf->dst.field)) { + if (action_conf->dst.tag_index && + !flow_modify_field_support_tag_array(action_conf->dst.field)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "destination tag index is not supported"); + if (action_conf->dst.class_id) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "destination class id is not supported"); + } if (mask_conf->dst.level != UINT8_MAX) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, action, @@ -5000,15 +5014,17 @@ flow_hw_validate_action_modify_field(struct rte_eth_dev *dev, "destination field mask and template are not equal"); if (action_conf->src.field != RTE_FLOW_FIELD_POINTER && action_conf->src.field != RTE_FLOW_FIELD_VALUE) { - if (action_conf->src.tag_index && - !flow_modify_field_support_tag_array(action_conf->src.field)) - return rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, action, - "source tag index is not supported"); - if (action_conf->src.class_id) - return rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, action, - "source class id is not supported"); + if (!flow_hw_modify_field_is_geneve_opt(action_conf->src.field)) { + if (action_conf->src.tag_index && + !flow_modify_field_support_tag_array(action_conf->src.field)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "source tag index is not supported"); + if (action_conf->src.class_id) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "source class id is not supported"); + } if (mask_conf->src.level != UINT8_MAX) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, action, @@ -5059,6 +5075,13 @@ flow_hw_validate_action_modify_field(struct rte_eth_dev *dev, return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, action, "modifying Geneve VNI is not supported when GENEVE opt is supported"); + if (priv->tlv_options == NULL && + (flow_hw_modify_field_is_used(action_conf, RTE_FLOW_FIELD_GENEVE_OPT_TYPE) || + flow_hw_modify_field_is_used(action_conf, RTE_FLOW_FIELD_GENEVE_OPT_CLASS) || + flow_hw_modify_field_is_used(action_conf, RTE_FLOW_FIELD_GENEVE_OPT_DATA))) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "modifying Geneve TLV option is supported only after parser configuration"); /* Due to HW bug, tunnel MPLS header is read only. */ if (action_conf->dst.field == RTE_FLOW_FIELD_MPLS) return rte_flow_error_set(error, EINVAL,