From patchwork Thu Jan 25 13:30:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Baum X-Patchwork-Id: 136166 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 C487C439C1; Thu, 25 Jan 2024 14:34:12 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 044F042E4A; Thu, 25 Jan 2024 14:32:00 +0100 (CET) Received: from NAM11-BN8-obe.outbound.protection.outlook.com (mail-bn8nam11on2040.outbound.protection.outlook.com [40.107.236.40]) by mails.dpdk.org (Postfix) with ESMTP id 0832442E4A for ; Thu, 25 Jan 2024 14:31:59 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=KhFTRFo7jQ2TCQpcJEMu9dmLpnVFhtSOZZkFUHYPCzx0Glb/5eh5KCmPNhC7cL2KuMZtfN/78c/42x7Yv6M6Xg65kkALYoTZcUBwjY1AO9aOdQjHt8ZzksswR+ZmeqHrnZ1uZhTXyaM4IScD0fj5LwCzlhEI9Mchdy+ngryJCoHC+xSLUx8elxMi643VaECuFfk23ewZqUu2LIYFTuel544qxqT9oMhDzCrkPicczYhhQdNgATPSxzCTuxgRs5HAFSJiyj8YRiCKI/NiALAbtF0bve9mtO7GbH7A5qSiIZryweTEVa+jgVOyx8axc7xB7W1cuIrp08edPo91Yk+rrA== 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=RhlqdTxbtI1gxZMUuiregBsg3NkxVJBl+kGdk5S6qgs=; b=M/xje1cMbEmMHA0z5cPbQnuhet8tbXn6UhF2PmE3mogM68LzLmJJ+4LFMHnGTYrT/43ZlrfZXoYI/82a+j4vTsFpTS99W+F59IpQADpxc4dG9V4BCeuIHO2W47rt2vwvsW+/nFAxgLK8ijEcDl/XqC5rRLkRaTLAzFxXp/dm3SpaPwEaKnRKB8Yof0v6b4MDjr4viRAxn84wdX5/qRrRHH3w4pdt9Rt6GZiGaN+h7mfqB/4GgYF/M1yJw9XBV39J7rUfwxaxtQdASMPAFs7CuUKuryTVR7+9UpGw7ST5iOlBNbzoKqLOxKdjQvHW3ywXsSyhIkzTlTaIu2AFAa0dlQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.233) 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=RhlqdTxbtI1gxZMUuiregBsg3NkxVJBl+kGdk5S6qgs=; b=XbIZPsBxZ3GdYWbvYj9BZqBww5SLLdijJoYSuzhPpF/lN7O5/xXZbcaqEf2wwBf3l9Wd3+q0d3FIrl6O0ByYzDJYNu7nLhpbodZB4QJBcvNNadB8jqR3B4Dm6ndY2WZXiZNOOKrCFYHgMtTQ8vtMH1BNfdZ6m8qd8oCS1AkahuCrRTiAcv5icNxO6BkAqMYa9DnSi8OfJhcemvRmpH/YhGxYItxa0YNJk/xPKF6oHSXATysI+b0pmxKMS/LU/jmPX+BIRfpJGjB2OCC0DheJyQxxAtZfIFg4sPUrZl6ViaAhlgxxt4Rzi4q+C6zNcBysZD+c5iRsmhbOs3gxuEZRlw== Received: from DM5PR07CA0055.namprd07.prod.outlook.com (2603:10b6:4:ad::20) by SN7PR12MB7180.namprd12.prod.outlook.com (2603:10b6:806:2a8::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7202.31; Thu, 25 Jan 2024 13:31:55 +0000 Received: from CY4PEPF0000EDD2.namprd03.prod.outlook.com (2603:10b6:4:ad:cafe::b2) by DM5PR07CA0055.outlook.office365.com (2603:10b6:4:ad::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7228.27 via Frontend Transport; Thu, 25 Jan 2024 13:31:54 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.233) 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.118.233 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.233; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.233) by CY4PEPF0000EDD2.mail.protection.outlook.com (10.167.241.206) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7228.16 via Frontend Transport; Thu, 25 Jan 2024 13:31:54 +0000 Received: from drhqmail203.nvidia.com (10.126.190.182) by mail.nvidia.com (10.127.129.6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.41; Thu, 25 Jan 2024 05:31:46 -0800 Received: from drhqmail202.nvidia.com (10.126.190.181) by drhqmail203.nvidia.com (10.126.190.182) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.41; Thu, 25 Jan 2024 05:31:46 -0800 Received: from nvidia.com (10.127.8.13) by mail.nvidia.com (10.126.190.181) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.41 via Frontend Transport; Thu, 25 Jan 2024 05:31:44 -0800 From: Michael Baum To: CC: Matan Azrad , Raslan Darawsheh , Dariusz Sosnowski , Viacheslav Ovsiienko , Ori Kam , Suanming Mou Subject: [PATCH v2 23/23] net/mlx5: add support for modify GENEVE option header Date: Thu, 25 Jan 2024 15:30:43 +0200 Message-ID: <20240125133043.575860-24-michaelba@nvidia.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240125133043.575860-1-michaelba@nvidia.com> References: <20231203112543.844014-1-michaelba@nvidia.com> <20240125133043.575860-1-michaelba@nvidia.com> MIME-Version: 1.0 X-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CY4PEPF0000EDD2:EE_|SN7PR12MB7180:EE_ X-MS-Office365-Filtering-Correlation-Id: 147cd586-9ca0-45f2-d675-08dc1da9ff42 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: Sy1/RRbGNtuf7ENKxBCNYmzv4bHyerXhh1QkZcck9xHzvnEQP8mhkxIvsZ/3zahfEsmuAVquWNHrrwwAIi0uvKLu1eW3W8/WotNV/3+XBtvEMeg8h8SJqrHrbYz4kSR8grIzDZ7ra6g5qybUMzeYZefKGve85XRts1t/LVsPdP58U8wRN52GlTHrqJXemkKcyRfEDZkP64P//oOU0pgkRy2DjgGFAhRAEzOt0XJ3S5wLPX3eqVc3YHuZf/S58Z7M34QC5XPWfPDfJOwqClIL7EKeKF1xNJbjeFlOmoWDSjD9iZgL+lz7ClhTYqJmWsxT4fqPCjaO/qmTr5PHkbvy4wexi8XnG/IeBZLRsXEEXP6UZaJSAQYBm7ojT2pEip8cbOyLdXDgBu6Szm/esEPf0+2fQQJLebiy27ltnEc1l+9Y39H47SoQ0xJxEl0HeeFRY1sL23NBgck01bl0LCQhOhkjsm6FtuhDRRa27JWBfCb+pSeSeNJk5JfkIlJ2chhgkJ0Qv9ZQMHWmksmVHjdd5ksvVX5Q79gSr5Tq6auCqCO55P+fPYVWSyvCYD1MopbBPx/85ve7XoBlPGcyljXHLxZflgtP+xnRQG3BUJg3YjE9qL9Ia9e6vaqychB7hViOSyF/93y8T5ZuCh60bD1ANc7H7i2MwzMXxIZFJ+Mc6djvXodDyB5A93HmtdaZJj+WBlCvHI9eTer/osUEwcgAWTDVta18+wtEQFAEjEFi3toEvJykN7gWUOh7QvVHaPiM X-Forefront-Antispam-Report: CIP:216.228.118.233; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:mail.nvidia.com; PTR:dc7edge2.nvidia.com; CAT:NONE; SFS:(13230031)(4636009)(39860400002)(396003)(376002)(136003)(346002)(230922051799003)(186009)(82310400011)(1800799012)(64100799003)(451199024)(36840700001)(46966006)(40470700004)(40480700001)(55016003)(40460700003)(83380400001)(47076005)(1076003)(86362001)(356005)(41300700001)(30864003)(36756003)(478600001)(336012)(8676002)(26005)(54906003)(426003)(2616005)(6286002)(4326008)(82740400003)(107886003)(6916009)(36860700001)(70206006)(316002)(5660300002)(2906002)(7636003)(7696005)(70586007)(8936002); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Jan 2024 13:31:54.7922 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 147cd586-9ca0-45f2-d675-08dc1da9ff42 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[216.228.118.233]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: CY4PEPF0000EDD2.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7180 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 Acked-by: Suanming Mou --- 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 0e3d0bc099..6e1e2df79a 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -591,6 +591,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 8b14ab8986..73515aad1e 100644 --- a/doc/guides/rel_notes/release_24_03.rst +++ b/doc/guides/rel_notes/release_24_03.rst @@ -81,6 +81,9 @@ New Features * 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 655e4d3d86..c9cc942d80 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -1811,6 +1811,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[], @@ -1819,6 +1838,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 5d5e2cadf6..6998be107f 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -1465,6 +1465,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, @@ -1604,9 +1619,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 */ @@ -1968,6 +1985,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); @@ -1981,8 +2040,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 @@ -5488,6 +5547,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 687d809b1b..7510715189 100644 --- a/drivers/net/mlx5/mlx5_flow_hw.c +++ b/drivers/net/mlx5/mlx5_flow_hw.c @@ -1257,10 +1257,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); @@ -2829,12 +2831,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; @@ -4955,6 +4959,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 bool flow_hw_modify_field_is_add_dst_valid(const struct rte_flow_action_modify_field *conf) { @@ -5015,15 +5027,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, @@ -5038,15 +5052,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, @@ -5101,6 +5117,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,