From patchwork Sun Feb 20 03:43:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kozyrev X-Patchwork-Id: 107858 X-Patchwork-Delegate: ferruh.yigit@amd.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 6141DA00C2; Sun, 20 Feb 2022 04:44:44 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 098A54114E; Sun, 20 Feb 2022 04:44:40 +0100 (CET) Received: from NAM10-BN7-obe.outbound.protection.outlook.com (mail-bn7nam10on2048.outbound.protection.outlook.com [40.107.92.48]) by mails.dpdk.org (Postfix) with ESMTP id 7B7D14114E for ; Sun, 20 Feb 2022 04:44:38 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=hTnR+LygHT0Ohu0ZFHkWWT7cGvjvwKbpm7WqS/sYbuDA9ZImo54ifN+DaFhmIWanLnZpfhTFHqTk7BRuPaTBd1KjSdetQzq1kcbcM4QpctaQt4RudnuUeJaKkGkcalyLd+6Cv1gZhwWPq66A3Jna8bgyNrbnrmgfnCdYD1CzOOwCLQqF0fuewy4aZB5Yndj4tSanqnr8KeVgbqhuZ6dC6R4/sheEbwtqUpHja2BhwgEYgYPA3Sg4QHNaXaNRukY+F49P4Oqh9nAxS+cnLFcpaLw7iLjX1bayDNgGTGoxpkoPemzDUptfSP+25tzDQtJ/5H1lJ6r95QXAXr88SyvgMQ== 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=UAPbBBk9Vf59LbcnsDPBz9S05kMkMGCCKymhJzi4j8I=; b=XWQ+yPI2ddbVbmkvxw4DaVKr3c1/ts1E0WDN3Id1peKc0Y/Ms529Db2l6OTVQ/uNNdsCVQnByDYJMODehpVusJPT4vW3cEHdh1e/JN48/B6heLViJ6fZbNW8OSI/GpGRlYW3ccDIxuzUgHpl4g4tglpNHZYm3B0yb67WS7OXyF7s6wgjjdK8pE/Cug8Mn9tus7wEdCUB3JERbdj47mlh8EshrvZexIGHcNGXg47GNPofEBrMyFy7dKz6CsWjaIScN+OnkT15j5NKCdB9NXYnGSTNX0TZyRlG0hhAm3oOQQZuMHxt8LyQPVl8MUUNTy2UBu9t3ed08Fgy4+UVSdKIDA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 12.22.5.235) smtp.rcpttodomain=intel.com 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 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=UAPbBBk9Vf59LbcnsDPBz9S05kMkMGCCKymhJzi4j8I=; b=sOQE9smUmFfbCMqL6Dnp6sKMASREqTmu50mL+Nnv+/eA4GFHstOFhxPlQoZCknlz951fUZ8DX1Al3eMQvjrEA7gvs3GrnWGXwGAKD+wwklnrG2WsaXAlizejWDw4Fa76XdzhZEMldFHtXEOE0VHU8Ki87krbikR+ENkBmNWqOS07J+BJBycuHiASFzpIDyV8nNHWkJqD+b3KnLBIb2Cn81DgVyDiz+hHICq+R8yPzIdgr/859gmNiSqd5DsRnlFTxqa/DBt9fvsKz4yWQKrwqyksSS6kLFK7ThdT22Vhk+SZOm4Q1e/52pwSgZLpBQlypzej20d5QkMGA3QKhnn/Yg== Received: from MW5PR12MB5682.namprd12.prod.outlook.com (2603:10b6:303:19f::20) by DM5PR12MB2405.namprd12.prod.outlook.com (2603:10b6:4:b2::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.16; Sun, 20 Feb 2022 03:44:36 +0000 Received: from DM6PR03CA0087.namprd03.prod.outlook.com (2603:10b6:5:333::20) by MW5PR12MB5682.namprd12.prod.outlook.com (2603:10b6:303:19f::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.24; Sun, 20 Feb 2022 03:44:34 +0000 Received: from DM6NAM11FT006.eop-nam11.prod.protection.outlook.com (2603:10b6:5:333:cafe::dc) by DM6PR03CA0087.outlook.office365.com (2603:10b6:5:333::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.17 via Frontend Transport; Sun, 20 Feb 2022 03:44:34 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 12.22.5.235) 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 12.22.5.235 as permitted sender) receiver=protection.outlook.com; client-ip=12.22.5.235; helo=mail.nvidia.com; Received: from mail.nvidia.com (12.22.5.235) by DM6NAM11FT006.mail.protection.outlook.com (10.13.173.104) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4995.15 via Frontend Transport; Sun, 20 Feb 2022 03:44:33 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by DRHQMAIL107.nvidia.com (10.27.9.16) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Sun, 20 Feb 2022 03:44:33 +0000 Received: from pegasus01.mtr.labs.mlnx (10.126.230.35) 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.9; Sat, 19 Feb 2022 19:44:29 -0800 From: Alexander Kozyrev To: CC: , , , , , , , , , Subject: [PATCH v8 01/11] ethdev: introduce flow engine configuration Date: Sun, 20 Feb 2022 05:43:59 +0200 Message-ID: <20220220034409.2226860-2-akozyrev@nvidia.com> X-Mailer: git-send-email 2.18.2 In-Reply-To: <20220220034409.2226860-1-akozyrev@nvidia.com> References: <20220219041144.2145380-1-akozyrev@nvidia.com> <20220220034409.2226860-1-akozyrev@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.126.230.35] X-ClientProxiedBy: rnnvmail202.nvidia.com (10.129.68.7) To rnnvmail201.nvidia.com (10.129.68.8) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 5d640029-7a6c-4c1a-0e3e-08d9f4234f4c X-MS-TrafficTypeDiagnostic: MW5PR12MB5682:EE_|DM5PR12MB2405:EE_ X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr,ExtAddr X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 9Rgg5pnfZgltPztQ2XkBAdMGRYdTvghAjTlah8cjkgz69g8Vvwywx/cb39isjj300K0AEBOZIuKTNqehZF+i2MKEwRyQhyPmON8eCDwmo6m3RsL1reMgbWbnDkAWUoo0GF90qNzakhVVEPuYhDID7KGSwrcdsSrCyseEBT9eRJ83GRadg0vqO/gMbvGNYaAjzEjLp/AKTku9Vk2BwMcAYAVNrzOWBlpY+y9ppUOrLduchqzeQplhiM30TK0T33C0IqWn5ZhzXMS9ZlTJ43IGNIAWUCgL5nhknTDmdd2WMIFAJ7BWSjwAZ+PDw90AQ27w/Gj4fXnTGgJzzLkRNeosnWiOQz1uMwBkSWONF1b19W+ACUsRkLY86fjGGoSMd8v2xaEBxlx0P9PdsLuKYfOLd3xig9MOvLHbeNIYYIkjTqJjRHO2NCXXHOnY8H2Uc1FNthBXKu3EbhwKVW55hpmg+UykVeCeu0zjubzeNWvQ8THR3zr5dBnHLICgzo8wMaj3SY7TPkfy8rMo/G+TmQJGbnDOvAPMBbnEMUw2n59zJsLHOC7Qn3z0bN5dp9lU/xBeXIiGNVvcca8FMHXoqpDT6Wuxq2aNB0XUA7UBQeYgLtd0IAOwZRAH0xLMqRZRcdLYsMxq+ejHN0acmYFFLr+hNX/ZI8LDyLS6FjRwqq4YZQOvYo/y4dB0PISIv0Rp32ZLLQV52+mxocWW4DS2zUVtEg== X-Forefront-Antispam-Report: CIP:12.22.5.235; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:mail.nvidia.com; PTR:InfoNoRecords; CAT:NONE; SFS:(13230001)(4636009)(40470700004)(36840700001)(46966006)(36860700001)(83380400001)(356005)(81166007)(47076005)(4326008)(82310400004)(316002)(6916009)(86362001)(54906003)(5660300002)(70206006)(70586007)(26005)(30864003)(8676002)(40460700003)(8936002)(2906002)(336012)(186003)(6666004)(1076003)(2616005)(7416002)(16526019)(36756003)(426003)(508600001)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Feb 2022 03:44:33.9490 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 5d640029-7a6c-4c1a-0e3e-08d9f4234f4c X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[12.22.5.235]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-CrossTenant-AuthSource: DM6NAM11FT006.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR12MB2405 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 The flow rules creation/destruction at a large scale incurs a performance penalty and may negatively impact the packet processing when used as part of the datapath logic. This is mainly because software/hardware resources are allocated and prepared during the flow rule creation. In order to optimize the insertion rate, PMD may use some hints provided by the application at the initialization phase. The rte_flow_configure() function allows to pre-allocate all the needed resources beforehand. These resources can be used at a later stage without costly allocations. Every PMD may use only the subset of hints and ignore unused ones or fail in case the requested configuration is not supported. The rte_flow_info_get() is available to retrieve the information about supported pre-configurable resources. Both these functions must be called before any other usage of the flow API engine. Signed-off-by: Alexander Kozyrev Acked-by: Ori Kam --- doc/guides/prog_guide/rte_flow.rst | 36 ++++++++ doc/guides/rel_notes/release_22_03.rst | 6 ++ lib/ethdev/ethdev_driver.h | 7 +- lib/ethdev/rte_flow.c | 69 +++++++++++++++ lib/ethdev/rte_flow.h | 111 +++++++++++++++++++++++++ lib/ethdev/rte_flow_driver.h | 10 +++ lib/ethdev/version.map | 2 + 7 files changed, 240 insertions(+), 1 deletion(-) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 0e475019a6..c89161faef 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -3606,6 +3606,42 @@ Return values: - 0 on success, a negative errno value otherwise and ``rte_errno`` is set. +Flow engine configuration +------------------------- + +Configure flow API management. + +An application may provide some parameters at the initialization phase about +rules engine configuration and/or expected flow rules characteristics. +These parameters may be used by PMD to preallocate resources and configure NIC. + +Configuration +~~~~~~~~~~~~~ + +This function performs the flow API engine configuration and allocates +requested resources beforehand to avoid costly allocations later. +Expected number of resources in an application allows PMD to prepare +and optimize NIC hardware configuration and memory layout in advance. +``rte_flow_configure()`` must be called before any flow rule is created, +but after an Ethernet device is configured. + +.. code-block:: c + + int + rte_flow_configure(uint16_t port_id, + const struct rte_flow_port_attr *port_attr, + struct rte_flow_error *error); + +Information about the number of available resources can be retrieved via +``rte_flow_info_get()`` API. + +.. code-block:: c + + int + rte_flow_info_get(uint16_t port_id, + struct rte_flow_port_info *port_info, + struct rte_flow_error *error); + .. _flow_isolated_mode: Flow isolated mode diff --git a/doc/guides/rel_notes/release_22_03.rst b/doc/guides/rel_notes/release_22_03.rst index ff3095d742..eceab07576 100644 --- a/doc/guides/rel_notes/release_22_03.rst +++ b/doc/guides/rel_notes/release_22_03.rst @@ -99,6 +99,12 @@ New Features The information of these properties is important for debug. As the information is private, a dump function is introduced. +* ** Added functions to configure Flow API engine + + * ethdev: Added ``rte_flow_configure`` API to configure Flow Management + engine, allowing to pre-allocate some resources for better performance. + Added ``rte_flow_info_get`` API to retrieve available resources. + * **Updated AF_XDP PMD** * Added support for libxdp >=v1.2.2. diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h index 6d697a879a..06f0896e1e 100644 --- a/lib/ethdev/ethdev_driver.h +++ b/lib/ethdev/ethdev_driver.h @@ -138,7 +138,12 @@ struct rte_eth_dev_data { * Indicates whether the device is configured: * CONFIGURED(1) / NOT CONFIGURED(0) */ - dev_configured : 1; + dev_configured:1, + /** + * Indicates whether the flow engine is configured: + * CONFIGURED(1) / NOT CONFIGURED(0) + */ + flow_configured:1; /** Queues state: HAIRPIN(2) / STARTED(1) / STOPPED(0) */ uint8_t rx_queue_state[RTE_MAX_QUEUES_PER_PORT]; diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 7f93900bc8..ffd48e40d5 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -1392,3 +1392,72 @@ rte_flow_flex_item_release(uint16_t port_id, ret = ops->flex_item_release(dev, handle, error); return flow_err(port_id, ret, error); } + +int +rte_flow_info_get(uint16_t port_id, + struct rte_flow_port_info *port_info, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + + if (port_info == NULL) { + RTE_FLOW_LOG(ERR, "Port %"PRIu16" info is NULL.\n", port_id); + return -EINVAL; + } + if (dev->data->dev_configured == 0) { + RTE_FLOW_LOG(INFO, + "Device with port_id=%"PRIu16" is not configured.\n", + port_id); + return -EINVAL; + } + if (unlikely(!ops)) + return -rte_errno; + if (likely(!!ops->info_get)) { + return flow_err(port_id, + ops->info_get(dev, port_info, error), + error); + } + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); +} + +int +rte_flow_configure(uint16_t port_id, + const struct rte_flow_port_attr *port_attr, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + int ret; + + dev->data->flow_configured = 0; + if (port_attr == NULL) { + RTE_FLOW_LOG(ERR, "Port %"PRIu16" info is NULL.\n", port_id); + return -EINVAL; + } + if (dev->data->dev_configured == 0) { + RTE_FLOW_LOG(INFO, + "Device with port_id=%"PRIu16" is not configured.\n", + port_id); + return -EINVAL; + } + if (dev->data->dev_started != 0) { + RTE_FLOW_LOG(INFO, + "Device with port_id=%"PRIu16" already started.\n", + port_id); + return -EINVAL; + } + if (unlikely(!ops)) + return -rte_errno; + if (likely(!!ops->configure)) { + ret = ops->configure(dev, port_attr, error); + if (ret == 0) + dev->data->flow_configured = 1; + return flow_err(port_id, ret, error); + } + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); +} diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index 765beb3e52..cdb7b2be68 100644 --- a/lib/ethdev/rte_flow.h +++ b/lib/ethdev/rte_flow.h @@ -43,6 +43,9 @@ extern "C" { #endif +#define RTE_FLOW_LOG(level, ...) \ + rte_log(RTE_LOG_ ## level, rte_eth_dev_logtype, "" __VA_ARGS__) + /** * Flow rule attributes. * @@ -4872,6 +4875,114 @@ rte_flow_flex_item_release(uint16_t port_id, const struct rte_flow_item_flex_handle *handle, struct rte_flow_error *error); +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Information about flow engine resources. + * The zero value means a resource is not supported. + * + */ +struct rte_flow_port_info { + /** + * Maximum number of counters. + * @see RTE_FLOW_ACTION_TYPE_COUNT + */ + uint32_t max_nb_counters; + /** + * Maximum number of aging objects. + * @see RTE_FLOW_ACTION_TYPE_AGE + */ + uint32_t max_nb_aging_objects; + /** + * Maximum number traffic meters. + * @see RTE_FLOW_ACTION_TYPE_METER + */ + uint32_t max_nb_meters; +}; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Get information about flow engine resources. + * + * @param port_id + * Port identifier of Ethernet device. + * @param[out] port_info + * A pointer to a structure of type *rte_flow_port_info* + * to be filled with the resources information of the port. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +__rte_experimental +int +rte_flow_info_get(uint16_t port_id, + struct rte_flow_port_info *port_info, + struct rte_flow_error *error); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Flow engine resources settings. + * The zero value means on demand resource allocations only. + * + */ +struct rte_flow_port_attr { + /** + * Number of counters to configure. + * @see RTE_FLOW_ACTION_TYPE_COUNT + */ + uint32_t nb_counters; + /** + * Number of aging objects to configure. + * @see RTE_FLOW_ACTION_TYPE_AGE + */ + uint32_t nb_aging_objects; + /** + * Number of traffic meters to configure. + * @see RTE_FLOW_ACTION_TYPE_METER + */ + uint32_t nb_meters; +}; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Configure the port's flow API engine. + * + * This API can only be invoked before the application + * starts using the rest of the flow library functions. + * + * The API can be invoked multiple times to change the + * settings. The port, however, may reject the changes. + * + * Parameters in configuration attributes must not exceed + * numbers of resources returned by the rte_flow_info_get API. + * + * @param port_id + * Port identifier of Ethernet device. + * @param[in] port_attr + * Port configuration attributes. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +__rte_experimental +int +rte_flow_configure(uint16_t port_id, + const struct rte_flow_port_attr *port_attr, + struct rte_flow_error *error); + #ifdef __cplusplus } #endif diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h index f691b04af4..7c29930d0f 100644 --- a/lib/ethdev/rte_flow_driver.h +++ b/lib/ethdev/rte_flow_driver.h @@ -152,6 +152,16 @@ struct rte_flow_ops { (struct rte_eth_dev *dev, const struct rte_flow_item_flex_handle *handle, struct rte_flow_error *error); + /** See rte_flow_info_get() */ + int (*info_get) + (struct rte_eth_dev *dev, + struct rte_flow_port_info *port_info, + struct rte_flow_error *err); + /** See rte_flow_configure() */ + int (*configure) + (struct rte_eth_dev *dev, + const struct rte_flow_port_attr *port_attr, + struct rte_flow_error *err); }; /** diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map index d5cc56a560..0d849c153f 100644 --- a/lib/ethdev/version.map +++ b/lib/ethdev/version.map @@ -264,6 +264,8 @@ EXPERIMENTAL { rte_eth_ip_reassembly_capability_get; rte_eth_ip_reassembly_conf_get; rte_eth_ip_reassembly_conf_set; + rte_flow_info_get; + rte_flow_configure; }; INTERNAL { From patchwork Sun Feb 20 03:44:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kozyrev X-Patchwork-Id: 107860 X-Patchwork-Delegate: ferruh.yigit@amd.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 B9723A00C2; Sun, 20 Feb 2022 04:44:58 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 783384115A; Sun, 20 Feb 2022 04:44:51 +0100 (CET) Received: from NAM12-DM6-obe.outbound.protection.outlook.com (mail-dm6nam12on2087.outbound.protection.outlook.com [40.107.243.87]) by mails.dpdk.org (Postfix) with ESMTP id 9667640395 for ; Sun, 20 Feb 2022 04:44:47 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=KL1eUrWdaQtiggY1y9H6ppA58SATt65mX9okMfUA56lgD8poDHTWPSHnmzYO4G2vxidYntLXkOhvPxYXAaI04bualypz6REj+WiUzT318qveXKzmvI5DvVJoiWlz9wZj6rzf1gxhgL3wC12YRUWttXnOLtQFUVq2xwlqHY4hs2B9O0JuTZ71p87v9OpuG4MMFG8SM/bdFIImD1htrXxnhC9t0KNVma1JTj1Pu6qfUYkD4iWjZDX94JIsx3GMEzHiRirakW9gIgZ/e/SKHZnP5+NbChXW+TkY3bteQhZKKo3jJYAT9DxNv/MoakJLpiSQPT4epeROcuRa232e/BdPHQ== 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=SQJ0GTC0hhunoR9sIH4YtqHXPqPKcRpFNtgUuX6zDX4=; b=Pr0e/lGiWj0jgFBs3Ds7/CbmaZj1wf3gtFC+ZSfaieQHvyNkFyfNUPVxWRxjDHUY0YSZFqTBp3evBqLvI6kX2Bg9c0JcHlBszTMb/iq3j3ab9C9aiezIpdEeiMeT/IbbdfSzVAeOw1gXkGBTEIz50TiTpP8lqJqs7+gvzvSxx/xeNDOBa+d/FSaoUihPPbjV/atm1Sxcfy7pnbg8EaLSjrnm0DgHynC6ennOvmOn9a0kYQj1YyUGyO8vse70zWYJSb5vKqZHw53eavtBxXT+Oit3J9UFFskLT+rSX1n/WSrmzcI12k/4NXsvkuCUJWFf+2eG2EQphqAXJmdomR1l0g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 12.22.5.236) smtp.rcpttodomain=intel.com 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 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=SQJ0GTC0hhunoR9sIH4YtqHXPqPKcRpFNtgUuX6zDX4=; b=K5xHO8ZdZJqExL5C09s5FtnJ0qdGmQeCfZqeksN76ZhuCV4+oPu2jM4x2QRDqDwEQf8EvYtYByNrPbSGti7cyMr1jp1HKp5G7u96DPxa8qBjM93wsO1yVCaMbKHLLuzlFdwCHJ+AoqF+oo+feL1YIkAEcZd/mZdXKSbqKFCaEn8BFkvOJDNIFasyvLfE5+Eqn5hlMTMJ8WeASul8+MP3o6rCcjiEagIacZeIq3ClFnJp3zPW7keoSULXyVyLJgwJyL7hWMx4txIc5jlLVD+DzaKbdpRJ3J+qnONvrUDisnBdyHNCUkNMbHkcu55W1rewFOStIVrphvO22h5dB0J2BQ== Received: from MN2PR12MB4607.namprd12.prod.outlook.com (2603:10b6:208:a1::18) by MN2PR12MB4304.namprd12.prod.outlook.com (2603:10b6:208:1d0::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.16; Sun, 20 Feb 2022 03:44:43 +0000 Received: from DM6PR13CA0059.namprd13.prod.outlook.com (2603:10b6:5:134::36) by MN2PR12MB4607.namprd12.prod.outlook.com (2603:10b6:208:a1::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.16; Sun, 20 Feb 2022 03:44:37 +0000 Received: from DM6NAM11FT014.eop-nam11.prod.protection.outlook.com (2603:10b6:5:134:cafe::44) by DM6PR13CA0059.outlook.office365.com (2603:10b6:5:134::36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5017.19 via Frontend Transport; Sun, 20 Feb 2022 03:44:37 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 12.22.5.236) 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 12.22.5.236 as permitted sender) receiver=protection.outlook.com; client-ip=12.22.5.236; helo=mail.nvidia.com; Received: from mail.nvidia.com (12.22.5.236) by DM6NAM11FT014.mail.protection.outlook.com (10.13.173.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4995.15 via Frontend Transport; Sun, 20 Feb 2022 03:44:37 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by DRHQMAIL109.nvidia.com (10.27.9.19) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Sun, 20 Feb 2022 03:44:36 +0000 Received: from pegasus01.mtr.labs.mlnx (10.126.230.35) 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.9; Sat, 19 Feb 2022 19:44:33 -0800 From: Alexander Kozyrev To: CC: , , , , , , , , , Subject: [PATCH v8 02/11] ethdev: add flow item/action templates Date: Sun, 20 Feb 2022 05:44:00 +0200 Message-ID: <20220220034409.2226860-3-akozyrev@nvidia.com> X-Mailer: git-send-email 2.18.2 In-Reply-To: <20220220034409.2226860-1-akozyrev@nvidia.com> References: <20220219041144.2145380-1-akozyrev@nvidia.com> <20220220034409.2226860-1-akozyrev@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.126.230.35] X-ClientProxiedBy: rnnvmail202.nvidia.com (10.129.68.7) To rnnvmail201.nvidia.com (10.129.68.8) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 606cba3d-5487-4ef4-0a0c-08d9f423513a X-MS-TrafficTypeDiagnostic: MN2PR12MB4607:EE_|MN2PR12MB4304:EE_ X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr,ExtAddr X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: f46mDhJoxZ+NFWNAwQMCPQovLSRGnto8lJEip315cS2sS/fgK4jaQemiXPN7uP+b9NYzsLsvfinHA4wjQ2lroE+xTdNTiz6ZjumDIgSWioWLdZ+/PcisOuCuan7jW4uA+dDTJpyUb+l9Lylo9c3rCDOXVQv2CCFhQ3FJP5bkVzpISVXZNcdHnhZLyx6wcmqjbwLvbZzb95x64kjSuRZClHnG22ixKSnjX4Q8VFB5GNQ6SUpHAt0w+miFN35skd0vAPiQo6ED24VBs4MIi/d6W6RXzauiC8/3A+xt9IoZAcqtkmT3JSiCKhe9H65rcvwp8EZj+VY9NKjlrSeByMWhI9ZYtkFOvcnRs39OXD1qbl/J9rwZmuqBu0TEIVwM2JWn1+ST2sKp2vjBC4IJotkBzdw7I08XvcSDFMyb6spsIK9sMwTma+vLbQSDauShjavaGh8WdjaAr+kdE3zlqbvG7//1rt+LiBzuUu5T87V+4Lvgxu686HgIArch/rBLPua0MUQrjdzVZEknqsr0A/PD1hEM5CXRKZ6K5AV98NuYadTLavmE1DwfMUVFi1idf6nPz3FrTBlYQRHtzoZwK7MHz+NPgqieM/OmsL3/ynj2s0S7PlA2t+VsovhrupECH3YisL+c+MXflW2LZ4VyBSgF0cwuhJSNCuCjK8y4ZhBI/D3ZQHH0hkuDndTF+nHMSQ5M8xq9m2WO9lttPtRXFFaPQA== X-Forefront-Antispam-Report: CIP:12.22.5.236; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:mail.nvidia.com; PTR:InfoNoRecords; CAT:NONE; SFS:(13230001)(4636009)(40470700004)(46966006)(36840700001)(1076003)(336012)(426003)(36756003)(6916009)(316002)(16526019)(2616005)(40460700003)(508600001)(186003)(47076005)(26005)(36860700001)(8676002)(4326008)(70586007)(70206006)(8936002)(82310400004)(6666004)(30864003)(5660300002)(7416002)(54906003)(86362001)(356005)(81166007)(2906002)(83380400001)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Feb 2022 03:44:37.2176 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 606cba3d-5487-4ef4-0a0c-08d9f423513a X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[12.22.5.236]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-CrossTenant-AuthSource: DM6NAM11FT014.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4304 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 Treating every single flow rule as a completely independent and separate entity negatively impacts the flow rules insertion rate. Oftentimes in an application, many flow rules share a common structure (the same item mask and/or action list) so they can be grouped and classified together. This knowledge may be used as a source of optimization by a PMD/HW. The pattern template defines common matching fields (the item mask) without values. The actions template holds a list of action types that will be used together in the same rule. The specific values for items and actions will be given only during the rule creation. A table combines pattern and actions templates along with shared flow rule attributes (group ID, priority and traffic direction). This way a PMD/HW can prepare all the resources needed for efficient flow rules creation in the datapath. To avoid any hiccups due to memory reallocation, the maximum number of flow rules is defined at the table creation time. The flow rule creation is done by selecting a table, a pattern template and an actions template (which are bound to the table), and setting unique values for the items and actions. Signed-off-by: Alexander Kozyrev Acked-by: Ori Kam --- doc/guides/prog_guide/rte_flow.rst | 135 ++++++++++++ doc/guides/rel_notes/release_22_03.rst | 8 + lib/ethdev/rte_flow.c | 252 +++++++++++++++++++++++ lib/ethdev/rte_flow.h | 274 +++++++++++++++++++++++++ lib/ethdev/rte_flow_driver.h | 37 ++++ lib/ethdev/version.map | 6 + 6 files changed, 712 insertions(+) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index c89161faef..6cdfea09be 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -3642,6 +3642,141 @@ Information about the number of available resources can be retrieved via struct rte_flow_port_info *port_info, struct rte_flow_error *error); +Flow templates +~~~~~~~~~~~~~~ + +Oftentimes in an application, many flow rules share a common structure +(the same pattern and/or action list) so they can be grouped and classified +together. This knowledge may be used as a source of optimization by a PMD/HW. +The flow rule creation is done by selecting a table, a pattern template +and an actions template (which are bound to the table), and setting unique +values for the items and actions. This API is not thread-safe. + +Pattern templates +^^^^^^^^^^^^^^^^^ + +The pattern template defines a common pattern (the item mask) without values. +The mask value is used to select a field to match on, spec/last are ignored. +The pattern template may be used by multiple tables and must not be destroyed +until all these tables are destroyed first. + +.. code-block:: c + + struct rte_flow_pattern_template * + rte_flow_pattern_template_create(uint16_t port_id, + const struct rte_flow_pattern_template_attr *template_attr, + const struct rte_flow_item pattern[], + struct rte_flow_error *error); + +For example, to create a pattern template to match on the destination MAC: + +.. code-block:: c + + const struct rte_flow_pattern_template_attr attr = {.ingress = 1}; + struct rte_flow_item_eth eth_m = { + .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff"; + }; + struct rte_flow_item pattern[] = { + [0] = {.type = RTE_FLOW_ITEM_TYPE_ETH, + .mask = ð_m}, + [1] = {.type = RTE_FLOW_ITEM_TYPE_END,}, + }; + struct rte_flow_error err; + + struct rte_flow_pattern_template *pattern_template = + rte_flow_pattern_template_create(port, &attr, &pattern, &err); + +The concrete value to match on will be provided at the rule creation. + +Actions templates +^^^^^^^^^^^^^^^^^ + +The actions template holds a list of action types to be used in flow rules. +The mask parameter allows specifying a shared constant value for every rule. +The actions template may be used by multiple tables and must not be destroyed +until all these tables are destroyed first. + +.. code-block:: c + + struct rte_flow_actions_template * + rte_flow_actions_template_create(uint16_t port_id, + const struct rte_flow_actions_template_attr *template_attr, + const struct rte_flow_action actions[], + const struct rte_flow_action masks[], + struct rte_flow_error *error); + +For example, to create an actions template with the same Mark ID +but different Queue Index for every rule: + +.. code-block:: c + + rte_flow_actions_template_attr attr = {.ingress = 1}; + struct rte_flow_action act[] = { + /* Mark ID is 4 for every rule, Queue Index is unique */ + [0] = {.type = RTE_FLOW_ACTION_TYPE_MARK, + .conf = &(struct rte_flow_action_mark){.id = 4}}, + [1] = {.type = RTE_FLOW_ACTION_TYPE_QUEUE}, + [2] = {.type = RTE_FLOW_ACTION_TYPE_END,}, + }; + struct rte_flow_action msk[] = { + /* Assign to MARK mask any non-zero value to make it constant */ + [0] = {.type = RTE_FLOW_ACTION_TYPE_MARK, + .conf = &(struct rte_flow_action_mark){.id = 1}}, + [1] = {.type = RTE_FLOW_ACTION_TYPE_QUEUE}, + [2] = {.type = RTE_FLOW_ACTION_TYPE_END,}, + }; + struct rte_flow_error err; + + struct rte_flow_actions_template *actions_template = + rte_flow_actions_template_create(port, &attr, &act, &msk, &err); + +The concrete value for Queue Index will be provided at the rule creation. + +Template table +^^^^^^^^^^^^^^ + +A template table combines a number of pattern and actions templates along with +shared flow rule attributes (group ID, priority and traffic direction). +This way a PMD/HW can prepare all the resources needed for efficient flow rules +creation in the datapath. To avoid any hiccups due to memory reallocation, +the maximum number of flow rules is defined at table creation time. +Any flow rule creation beyond the maximum table size is rejected. +Application may create another table to accommodate more rules in this case. + +.. code-block:: c + + struct rte_flow_template_table * + rte_flow_template_table_create(uint16_t port_id, + const struct rte_flow_template_table_attr *table_attr, + struct rte_flow_pattern_template *pattern_templates[], + uint8_t nb_pattern_templates, + struct rte_flow_actions_template *actions_templates[], + uint8_t nb_actions_templates, + struct rte_flow_error *error); + +A table can be created only after the Flow Rules management is configured +and pattern and actions templates are created. + +.. code-block:: c + + rte_flow_template_table_attr table_attr = { + .flow_attr.ingress = 1, + .nb_flows = 10000; + }; + uint8_t nb_pattern_templ = 1; + struct rte_flow_pattern_template *pattern_templates[nb_pattern_templ]; + pattern_templates[0] = pattern_template; + uint8_t nb_actions_templ = 1; + struct rte_flow_actions_template *actions_templates[nb_actions_templ]; + actions_templates[0] = actions_template; + struct rte_flow_error error; + + struct rte_flow_template_table *table = + rte_flow_template_table_create(port, &table_attr, + &pattern_templates, nb_pattern_templ, + &actions_templates, nb_actions_templ, + &error); + .. _flow_isolated_mode: Flow isolated mode diff --git a/doc/guides/rel_notes/release_22_03.rst b/doc/guides/rel_notes/release_22_03.rst index eceab07576..7150d06c87 100644 --- a/doc/guides/rel_notes/release_22_03.rst +++ b/doc/guides/rel_notes/release_22_03.rst @@ -105,6 +105,14 @@ New Features engine, allowing to pre-allocate some resources for better performance. Added ``rte_flow_info_get`` API to retrieve available resources. + * ethdev: Added ``rte_flow_template_table_create`` API to group flow rules + with the same flow attributes and common matching patterns and actions + defined by ``rte_flow_pattern_template_create`` and + ``rte_flow_actions_template_create`` respectively. + Corresponding functions to destroy these entities are: + ``rte_flow_template_table_destroy``, ``rte_flow_pattern_template_destroy`` + and ``rte_flow_actions_template_destroy``. + * **Updated AF_XDP PMD** * Added support for libxdp >=v1.2.2. diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index ffd48e40d5..e9f684eedb 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -1461,3 +1461,255 @@ rte_flow_configure(uint16_t port_id, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, rte_strerror(ENOTSUP)); } + +struct rte_flow_pattern_template * +rte_flow_pattern_template_create(uint16_t port_id, + const struct rte_flow_pattern_template_attr *template_attr, + const struct rte_flow_item pattern[], + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + struct rte_flow_pattern_template *template; + + if (template_attr == NULL) { + RTE_FLOW_LOG(ERR, + "Port %"PRIu16" template attr is NULL.\n", + port_id); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ATTR, + NULL, rte_strerror(EINVAL)); + return NULL; + } + if (pattern == NULL) { + RTE_FLOW_LOG(ERR, + "Port %"PRIu16" pattern is NULL.\n", + port_id); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ATTR, + NULL, rte_strerror(EINVAL)); + return NULL; + } + if (dev->data->flow_configured == 0) { + RTE_FLOW_LOG(INFO, + "Flow engine on port_id=%"PRIu16" is not configured.\n", + port_id); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_STATE, + NULL, rte_strerror(EINVAL)); + return NULL; + } + if (unlikely(!ops)) + return NULL; + if (likely(!!ops->pattern_template_create)) { + template = ops->pattern_template_create(dev, template_attr, + pattern, error); + if (template == NULL) + flow_err(port_id, -rte_errno, error); + return template; + } + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + return NULL; +} + +int +rte_flow_pattern_template_destroy(uint16_t port_id, + struct rte_flow_pattern_template *pattern_template, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + + if (unlikely(pattern_template == NULL)) + return 0; + if (unlikely(!ops)) + return -rte_errno; + if (likely(!!ops->pattern_template_destroy)) { + return flow_err(port_id, + ops->pattern_template_destroy(dev, + pattern_template, + error), + error); + } + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); +} + +struct rte_flow_actions_template * +rte_flow_actions_template_create(uint16_t port_id, + const struct rte_flow_actions_template_attr *template_attr, + const struct rte_flow_action actions[], + const struct rte_flow_action masks[], + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + struct rte_flow_actions_template *template; + + if (template_attr == NULL) { + RTE_FLOW_LOG(ERR, + "Port %"PRIu16" template attr is NULL.\n", + port_id); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ATTR, + NULL, rte_strerror(EINVAL)); + return NULL; + } + if (actions == NULL) { + RTE_FLOW_LOG(ERR, + "Port %"PRIu16" actions is NULL.\n", + port_id); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ATTR, + NULL, rte_strerror(EINVAL)); + return NULL; + } + if (masks == NULL) { + RTE_FLOW_LOG(ERR, + "Port %"PRIu16" masks is NULL.\n", + port_id); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ATTR, + NULL, rte_strerror(EINVAL)); + + } + if (dev->data->flow_configured == 0) { + RTE_FLOW_LOG(INFO, + "Flow engine on port_id=%"PRIu16" is not configured.\n", + port_id); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_STATE, + NULL, rte_strerror(EINVAL)); + return NULL; + } + if (unlikely(!ops)) + return NULL; + if (likely(!!ops->actions_template_create)) { + template = ops->actions_template_create(dev, template_attr, + actions, masks, error); + if (template == NULL) + flow_err(port_id, -rte_errno, error); + return template; + } + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + return NULL; +} + +int +rte_flow_actions_template_destroy(uint16_t port_id, + struct rte_flow_actions_template *actions_template, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + + if (unlikely(actions_template == NULL)) + return 0; + if (unlikely(!ops)) + return -rte_errno; + if (likely(!!ops->actions_template_destroy)) { + return flow_err(port_id, + ops->actions_template_destroy(dev, + actions_template, + error), + error); + } + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); +} + +struct rte_flow_template_table * +rte_flow_template_table_create(uint16_t port_id, + const struct rte_flow_template_table_attr *table_attr, + struct rte_flow_pattern_template *pattern_templates[], + uint8_t nb_pattern_templates, + struct rte_flow_actions_template *actions_templates[], + uint8_t nb_actions_templates, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + struct rte_flow_template_table *table; + + if (table_attr == NULL) { + RTE_FLOW_LOG(ERR, + "Port %"PRIu16" table attr is NULL.\n", + port_id); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ATTR, + NULL, rte_strerror(EINVAL)); + return NULL; + } + if (pattern_templates == NULL) { + RTE_FLOW_LOG(ERR, + "Port %"PRIu16" pattern templates is NULL.\n", + port_id); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ATTR, + NULL, rte_strerror(EINVAL)); + return NULL; + } + if (actions_templates == NULL) { + RTE_FLOW_LOG(ERR, + "Port %"PRIu16" actions templates is NULL.\n", + port_id); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ATTR, + NULL, rte_strerror(EINVAL)); + return NULL; + } + if (dev->data->flow_configured == 0) { + RTE_FLOW_LOG(INFO, + "Flow engine on port_id=%"PRIu16" is not configured.\n", + port_id); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_STATE, + NULL, rte_strerror(EINVAL)); + return NULL; + } + if (unlikely(!ops)) + return NULL; + if (likely(!!ops->template_table_create)) { + table = ops->template_table_create(dev, table_attr, + pattern_templates, nb_pattern_templates, + actions_templates, nb_actions_templates, + error); + if (table == NULL) + flow_err(port_id, -rte_errno, error); + return table; + } + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + return NULL; +} + +int +rte_flow_template_table_destroy(uint16_t port_id, + struct rte_flow_template_table *template_table, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + + if (unlikely(template_table == NULL)) + return 0; + if (unlikely(!ops)) + return -rte_errno; + if (likely(!!ops->template_table_destroy)) { + return flow_err(port_id, + ops->template_table_destroy(dev, + template_table, + error), + error); + } + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); +} diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index cdb7b2be68..776e8ccc11 100644 --- a/lib/ethdev/rte_flow.h +++ b/lib/ethdev/rte_flow.h @@ -4983,6 +4983,280 @@ rte_flow_configure(uint16_t port_id, const struct rte_flow_port_attr *port_attr, struct rte_flow_error *error); +/** + * Opaque type returned after successful creation of pattern template. + * This handle can be used to manage the created pattern template. + */ +struct rte_flow_pattern_template; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Flow pattern template attributes. + */ +__extension__ +struct rte_flow_pattern_template_attr { + /** + * Relaxed matching policy. + * - PMD may match only on items with mask member set and skip + * matching on protocol layers specified without any masks. + * - If not set, PMD will match on protocol layers + * specified without any masks as well. + * - Packet data must be stacked in the same order as the + * protocol layers to match inside packets, starting from the lowest. + */ + uint32_t relaxed_matching:1; + /** Pattern valid for rules applied to ingress traffic. */ + uint32_t ingress:1; + /** Pattern valid for rules applied to egress traffic. */ + uint32_t egress:1; + /** Pattern valid for rules applied to transfer traffic. */ + uint32_t transfer:1; +}; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Create flow pattern template. + * + * The pattern template defines common matching fields without values. + * For example, matching on 5 tuple TCP flow, the template will be + * eth(null) + IPv4(source + dest) + TCP(s_port + d_port), + * while values for each rule will be set during the flow rule creation. + * The number and order of items in the template must be the same + * at the rule creation. + * + * @param port_id + * Port identifier of Ethernet device. + * @param[in] template_attr + * Pattern template attributes. + * @param[in] pattern + * Pattern specification (list terminated by the END pattern item). + * The spec member of an item is not used unless the end member is used. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * Handle on success, NULL otherwise and rte_errno is set. + */ +__rte_experimental +struct rte_flow_pattern_template * +rte_flow_pattern_template_create(uint16_t port_id, + const struct rte_flow_pattern_template_attr *template_attr, + const struct rte_flow_item pattern[], + struct rte_flow_error *error); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Destroy flow pattern template. + * + * This function may be called only when + * there are no more tables referencing this template. + * + * @param port_id + * Port identifier of Ethernet device. + * @param[in] pattern_template + * Handle of the template to be destroyed. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +__rte_experimental +int +rte_flow_pattern_template_destroy(uint16_t port_id, + struct rte_flow_pattern_template *pattern_template, + struct rte_flow_error *error); + +/** + * Opaque type returned after successful creation of actions template. + * This handle can be used to manage the created actions template. + */ +struct rte_flow_actions_template; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Flow actions template attributes. + */ +__extension__ +struct rte_flow_actions_template_attr { + /** Action valid for rules applied to ingress traffic. */ + uint32_t ingress:1; + /** Action valid for rules applied to egress traffic. */ + uint32_t egress:1; + /** Action valid for rules applied to transfer traffic. */ + uint32_t transfer:1; +}; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Create flow actions template. + * + * The actions template holds a list of action types without values. + * For example, the template to change TCP ports is TCP(s_port + d_port), + * while values for each rule will be set during the flow rule creation. + * The number and order of actions in the template must be the same + * at the rule creation. + * + * @param port_id + * Port identifier of Ethernet device. + * @param[in] template_attr + * Template attributes. + * @param[in] actions + * Associated actions (list terminated by the END action). + * The spec member is only used if @p masks spec is non-zero. + * @param[in] masks + * List of actions that marks which of the action's member is constant. + * A mask has the same format as the corresponding action. + * If the action field in @p masks is not 0, + * the corresponding value in an action from @p actions will be the part + * of the template and used in all flow rules. + * The order of actions in @p masks is the same as in @p actions. + * In case of indirect actions present in @p actions, + * the actual action type should be present in @p mask. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * Handle on success, NULL otherwise and rte_errno is set. + */ +__rte_experimental +struct rte_flow_actions_template * +rte_flow_actions_template_create(uint16_t port_id, + const struct rte_flow_actions_template_attr *template_attr, + const struct rte_flow_action actions[], + const struct rte_flow_action masks[], + struct rte_flow_error *error); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Destroy flow actions template. + * + * This function may be called only when + * there are no more tables referencing this template. + * + * @param port_id + * Port identifier of Ethernet device. + * @param[in] actions_template + * Handle to the template to be destroyed. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +__rte_experimental +int +rte_flow_actions_template_destroy(uint16_t port_id, + struct rte_flow_actions_template *actions_template, + struct rte_flow_error *error); + +/** + * Opaque type returned after successful creation of a template table. + * This handle can be used to manage the created template table. + */ +struct rte_flow_template_table; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Table attributes. + */ +struct rte_flow_template_table_attr { + /** + * Flow attributes to be used in each rule generated from this table. + */ + struct rte_flow_attr flow_attr; + /** + * Maximum number of flow rules that this table holds. + */ + uint32_t nb_flows; +}; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Create flow template table. + * + * A template table consists of multiple pattern templates and actions + * templates associated with a single set of rule attributes (group ID, + * priority and traffic direction). + * + * Each rule is free to use any combination of pattern and actions templates + * and specify particular values for items and actions it would like to change. + * + * @param port_id + * Port identifier of Ethernet device. + * @param[in] table_attr + * Template table attributes. + * @param[in] pattern_templates + * Array of pattern templates to be used in this table. + * @param[in] nb_pattern_templates + * The number of pattern templates in the pattern_templates array. + * @param[in] actions_templates + * Array of actions templates to be used in this table. + * @param[in] nb_actions_templates + * The number of actions templates in the actions_templates array. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * Handle on success, NULL otherwise and rte_errno is set. + */ +__rte_experimental +struct rte_flow_template_table * +rte_flow_template_table_create(uint16_t port_id, + const struct rte_flow_template_table_attr *table_attr, + struct rte_flow_pattern_template *pattern_templates[], + uint8_t nb_pattern_templates, + struct rte_flow_actions_template *actions_templates[], + uint8_t nb_actions_templates, + struct rte_flow_error *error); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Destroy flow template table. + * + * This function may be called only when + * there are no more flow rules referencing this table. + * + * @param port_id + * Port identifier of Ethernet device. + * @param[in] template_table + * Handle to the table to be destroyed. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +__rte_experimental +int +rte_flow_template_table_destroy(uint16_t port_id, + struct rte_flow_template_table *template_table, + struct rte_flow_error *error); + #ifdef __cplusplus } #endif diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h index 7c29930d0f..2d96db1dc7 100644 --- a/lib/ethdev/rte_flow_driver.h +++ b/lib/ethdev/rte_flow_driver.h @@ -162,6 +162,43 @@ struct rte_flow_ops { (struct rte_eth_dev *dev, const struct rte_flow_port_attr *port_attr, struct rte_flow_error *err); + /** See rte_flow_pattern_template_create() */ + struct rte_flow_pattern_template *(*pattern_template_create) + (struct rte_eth_dev *dev, + const struct rte_flow_pattern_template_attr *template_attr, + const struct rte_flow_item pattern[], + struct rte_flow_error *err); + /** See rte_flow_pattern_template_destroy() */ + int (*pattern_template_destroy) + (struct rte_eth_dev *dev, + struct rte_flow_pattern_template *pattern_template, + struct rte_flow_error *err); + /** See rte_flow_actions_template_create() */ + struct rte_flow_actions_template *(*actions_template_create) + (struct rte_eth_dev *dev, + const struct rte_flow_actions_template_attr *template_attr, + const struct rte_flow_action actions[], + const struct rte_flow_action masks[], + struct rte_flow_error *err); + /** See rte_flow_actions_template_destroy() */ + int (*actions_template_destroy) + (struct rte_eth_dev *dev, + struct rte_flow_actions_template *actions_template, + struct rte_flow_error *err); + /** See rte_flow_template_table_create() */ + struct rte_flow_template_table *(*template_table_create) + (struct rte_eth_dev *dev, + const struct rte_flow_template_table_attr *table_attr, + struct rte_flow_pattern_template *pattern_templates[], + uint8_t nb_pattern_templates, + struct rte_flow_actions_template *actions_templates[], + uint8_t nb_actions_templates, + struct rte_flow_error *err); + /** See rte_flow_template_table_destroy() */ + int (*template_table_destroy) + (struct rte_eth_dev *dev, + struct rte_flow_template_table *template_table, + struct rte_flow_error *err); }; /** diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map index 0d849c153f..62ff791261 100644 --- a/lib/ethdev/version.map +++ b/lib/ethdev/version.map @@ -266,6 +266,12 @@ EXPERIMENTAL { rte_eth_ip_reassembly_conf_set; rte_flow_info_get; rte_flow_configure; + rte_flow_pattern_template_create; + rte_flow_pattern_template_destroy; + rte_flow_actions_template_create; + rte_flow_actions_template_destroy; + rte_flow_template_table_create; + rte_flow_template_table_destroy; }; INTERNAL { From patchwork Sun Feb 20 03:44:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kozyrev X-Patchwork-Id: 107859 X-Patchwork-Delegate: ferruh.yigit@amd.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 0C56AA00C2; Sun, 20 Feb 2022 04:44:50 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 04CE341147; Sun, 20 Feb 2022 04:44:48 +0100 (CET) Received: from NAM02-BN1-obe.outbound.protection.outlook.com (mail-bn1nam07on2085.outbound.protection.outlook.com [40.107.212.85]) by mails.dpdk.org (Postfix) with ESMTP id 525DE40395 for ; Sun, 20 Feb 2022 04:44:46 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=UvqYnhz7DBWquLgrQYXH+71yIbghTrbowKBOmwILv1N/jRCdMzkdFiB/87ORMHFajszaxQWyFQnRs9zI87uXSPrakG66xTJvRgB1eUzhvHyssYF47LftvYiR78LC354IRSsgwVkxVccHb6YKa+oUz1NDCdvzsEkFIoNIyY/cVHzEUUZm+T/mgKaEv4ilsObF1plGFYlIsIFAObWxZ5F9kXIbtzOMNIAfh9i2OPOGDqQtVyaoCD8QL6PzfH6wtiCQVzQPa9FPuGwVTwSn9iVtcIQ5nffKEYzpSAJYQLVgdxr7pdlxuNk4B8vY9hj4NVmO/vAbxVgRJsCZs34VfvapPQ== 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=IkEkmU8YA6Dg09C0qWhd2ow3+bonFmhApDcJ1yTyYyk=; b=exsVlRYoCcWcZAwEYoQuap6c/F/SJiOGO5WbVN536cxcoSaT+4SQo6ULXstCOKqhywRHSd0fe/+U9Z6uP0za5uKM20JlTWp6ja2QDQFLVHcxdvolIRN6UU+Jf/+tb8mrOwXl/8mdE3Jl6q1tCpSqKhcCogJ6EtS9KTlhH7K4b1rFqMJfUHiLbNmXYanc3m9trxwarDPQBQIWZh55/xNtBlitpGIGgvDSvTSKliIE54KGzUuGSdF2JH/vSdm/7O5DqDaqF0iEt/PdO0Fx3X11Fa9VaJrfA/BIJ2MS0bHXaXwSFdKqCB+5Qw+I8c7YVTVS5KyHTtLC9Lfj8jOWQgmUBg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 12.22.5.238) smtp.rcpttodomain=intel.com 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 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=IkEkmU8YA6Dg09C0qWhd2ow3+bonFmhApDcJ1yTyYyk=; b=Ob549CPLzLmpZfUQyCzw7Rc+9WHMrQ6vCBvjAUTdHybCosS7ckqKEO862lKbbtW5ARlVR7YIrXRz24cHkTYaNSC0c+RQgzMS8avmwLIyCSRXm4NZiBTld0tdONK0X33rDIYrSiTHItqySMcjNc97efP51MSaQmwC1/0p8s7J8Yoso7PC1hEqTeUITnmvSzPK6bZtGVPqpsweLXfedc+c1Z7ThXvwBjbRSqSwbZQHgi5c3Kap3LwBfpBhT8URI3gkwg7HQQT78dE+VgHBWS7y0r3kyCv+6FvF+UuoVrKMS6VIVz91BupTgA2Jt/rBYQeLYzD76PxazbrJy4Vez411wA== Received: from DM6PR12MB2714.namprd12.prod.outlook.com (2603:10b6:5:42::18) by BL1PR12MB5286.namprd12.prod.outlook.com (2603:10b6:208:31d::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.17; Sun, 20 Feb 2022 03:44:43 +0000 Received: from BN9PR03CA0986.namprd03.prod.outlook.com (2603:10b6:408:109::31) by DM6PR12MB2714.namprd12.prod.outlook.com (2603:10b6:5:42::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.22; Sun, 20 Feb 2022 03:44:40 +0000 Received: from BN8NAM11FT005.eop-nam11.prod.protection.outlook.com (2603:10b6:408:109:cafe::6e) by BN9PR03CA0986.outlook.office365.com (2603:10b6:408:109::31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.14 via Frontend Transport; Sun, 20 Feb 2022 03:44:41 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 12.22.5.238) 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 12.22.5.238 as permitted sender) receiver=protection.outlook.com; client-ip=12.22.5.238; helo=mail.nvidia.com; Received: from mail.nvidia.com (12.22.5.238) by BN8NAM11FT005.mail.protection.outlook.com (10.13.176.69) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4995.15 via Frontend Transport; Sun, 20 Feb 2022 03:44:40 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by DRHQMAIL105.nvidia.com (10.27.9.14) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Sun, 20 Feb 2022 03:44:39 +0000 Received: from pegasus01.mtr.labs.mlnx (10.126.230.35) 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.9; Sat, 19 Feb 2022 19:44:36 -0800 From: Alexander Kozyrev To: CC: , , , , , , , , , Subject: [PATCH v8 03/11] ethdev: bring in async queue-based flow rules operations Date: Sun, 20 Feb 2022 05:44:01 +0200 Message-ID: <20220220034409.2226860-4-akozyrev@nvidia.com> X-Mailer: git-send-email 2.18.2 In-Reply-To: <20220220034409.2226860-1-akozyrev@nvidia.com> References: <20220219041144.2145380-1-akozyrev@nvidia.com> <20220220034409.2226860-1-akozyrev@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.126.230.35] X-ClientProxiedBy: rnnvmail202.nvidia.com (10.129.68.7) To rnnvmail201.nvidia.com (10.129.68.8) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 769d28a3-dbac-42d7-349e-08d9f4235364 X-MS-TrafficTypeDiagnostic: DM6PR12MB2714:EE_|BL1PR12MB5286:EE_ X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr,ExtAddr X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: K4ib6Ik2yNuSEPwCSgqXSeOaDFn0BNgM4kQWYUEq2HPGYaNm/8rRWTgEzL+hSm9hEr8Wn5z5rcf4G6Bdvcq8PejxL/pYDvJM0oM3VyFOi6Pv+KYkVDw7yUgwBUiesjt5ZMAn49Cb6TzW3b6yBfMZCf5D26C/dBnoiQD/th5IC0zu8uKkcUTQmcoOMwuGxwuPnOo2yBi7+sFB38j71az9kDFnI3mxdRrgmjYeZi2SHNt+rSoKAJ6vtTsx5F06wZJNSqsrkIEXFkTyRwqVEmG0f1AR3p/lxv+dIxCtzaQCp7R1PUEyJjFGYDbOZ79H99Zj8QqEGTlbCGxs0cf1xXLXq+VB6NSUr1LjKVMpBdwYMjQGAfh6bRpAoOw3a5y/6SV+hBkrf/Mj9yjGqh5axBsR+Ih6dKbZCUJxdVaGbWKaC+G/o3YsPv4sgsA9t5UIWWOIeEdne4JeIJEWqw82kwV1x2F5UQDNs3uTO95OhOUJMfJpxgP4/dr0GbLJ8Cr6EOydq/6jP1tT6hTpjTYbd2i+xMzduUCiqtB+5yA8QD1jUjGeOSaNJd+/8lyBvE+om52QAtxxRUi0VNaERnKFA9G13Zz6D4rJ6yymmFjKr36HCg1lBxHq9KKL2f7M03sUQNFIud2yZ/VQorR1sYQOMKBeDwtDprJCFqVkoR8EZhPQ0ZQk+kJ62n7U9jUbTNYOZPb8XEb7DsFP0SXKH8e9iohr7T7FHSCL+ZhvxQwzkmI8DGXqpD9b/xO+P20wSBUscL8BlYTtJHV2epoQGB/oRaso3nZnqMrzrBPHgFRt4qTtY3A4YjvKpxx3vdkjTP+DrE+3YBpEaeOnwN48gQtDGL+/WavNZ/PAgnVrUmxr9VDnPgk= X-Forefront-Antispam-Report: CIP:12.22.5.238; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:mail.nvidia.com; PTR:InfoNoRecords; CAT:NONE; SFS:(13230001)(4636009)(36840700001)(46966006)(40470700004)(186003)(26005)(16526019)(426003)(336012)(47076005)(40460700003)(1076003)(2616005)(356005)(81166007)(36756003)(2906002)(5660300002)(19273905006)(8936002)(7416002)(30864003)(508600001)(70586007)(70206006)(4326008)(82310400004)(6666004)(8676002)(83380400001)(36860700001)(86362001)(316002)(6916009)(54906003)(36900700001)(579004)(563064011); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Feb 2022 03:44:40.7244 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 769d28a3-dbac-42d7-349e-08d9f4235364 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[12.22.5.238]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-CrossTenant-AuthSource: BN8NAM11FT005.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL1PR12MB5286 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 A new, faster, queue-based flow rules management mechanism is needed for applications offloading rules inside the datapath. This asynchronous and lockless mechanism frees the CPU for further packet processing and reduces the performance impact of the flow rules creation/destruction on the datapath. Note that queues are not thread-safe and the queue should be accessed from the same thread for all queue operations. It is the responsibility of the app to sync the queue functions in case of multi-threaded access to the same queue. The rte_flow_async_create() function enqueues a flow creation to the requested queue. It benefits from already configured resources and sets unique values on top of item and action templates. A flow rule is enqueued on the specified flow queue and offloaded asynchronously to the hardware. The function returns immediately to spare CPU for further packet processing. The application must invoke the rte_flow_pull() function to complete the flow rule operation offloading, to clear the queue, and to receive the operation status. The rte_flow_async_destroy() function enqueues a flow destruction to the requested queue. Signed-off-by: Alexander Kozyrev Acked-by: Ori Kam --- .../prog_guide/img/rte_flow_async_init.svg | 205 ++++++++++ .../prog_guide/img/rte_flow_async_usage.svg | 354 ++++++++++++++++++ doc/guides/prog_guide/rte_flow.rst | 124 ++++++ doc/guides/rel_notes/release_22_03.rst | 7 + lib/ethdev/rte_flow.c | 110 +++++- lib/ethdev/rte_flow.h | 251 +++++++++++++ lib/ethdev/rte_flow_driver.h | 35 ++ lib/ethdev/version.map | 4 + 8 files changed, 1087 insertions(+), 3 deletions(-) create mode 100644 doc/guides/prog_guide/img/rte_flow_async_init.svg create mode 100644 doc/guides/prog_guide/img/rte_flow_async_usage.svg diff --git a/doc/guides/prog_guide/img/rte_flow_async_init.svg b/doc/guides/prog_guide/img/rte_flow_async_init.svg new file mode 100644 index 0000000000..f66e9c73d7 --- /dev/null +++ b/doc/guides/prog_guide/img/rte_flow_async_init.svg @@ -0,0 +1,205 @@ + + + + + + + + + + + + + + + + + rte_eth_dev_configure + () + + + rte_flow_configure() + + + rte_flow_pattern_template_create() + + rte_flow_actions_template_create() + + rte_eal_init() + + + + + rte_flow_template_table_create() + + + + rte_eth_dev_start() + + + diff --git a/doc/guides/prog_guide/img/rte_flow_async_usage.svg b/doc/guides/prog_guide/img/rte_flow_async_usage.svg new file mode 100644 index 0000000000..bb978bca1e --- /dev/null +++ b/doc/guides/prog_guide/img/rte_flow_async_usage.svg @@ -0,0 +1,354 @@ + + + + + + + + + + + + + + + + rte_eth_rx_burst() + + analyze packet + + rte_flow_async_create() + + more packets? + + + + + + + add new rule? + + + yes + + no + + + destroy the rule? + + + rte_flow_async_destroy() + + + + + rte_flow_pull() + + rte_flow_push() + + + no + + yes + + no + + yes + + diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 6cdfea09be..436845717f 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -3624,12 +3624,16 @@ Expected number of resources in an application allows PMD to prepare and optimize NIC hardware configuration and memory layout in advance. ``rte_flow_configure()`` must be called before any flow rule is created, but after an Ethernet device is configured. +It also creates flow queues for asynchronous flow rules operations via +queue-based API, see `Asynchronous operations`_ section. .. code-block:: c int rte_flow_configure(uint16_t port_id, const struct rte_flow_port_attr *port_attr, + uint16_t nb_queue, + const struct rte_flow_queue_attr *queue_attr[], struct rte_flow_error *error); Information about the number of available resources can be retrieved via @@ -3640,6 +3644,7 @@ Information about the number of available resources can be retrieved via int rte_flow_info_get(uint16_t port_id, struct rte_flow_port_info *port_info, + struct rte_flow_queue_info *queue_info, struct rte_flow_error *error); Flow templates @@ -3777,6 +3782,125 @@ and pattern and actions templates are created. &actions_templates, nb_actions_templ, &error); +Asynchronous operations +----------------------- + +Flow rules management can be done via special lockless flow management queues. +- Queue operations are asynchronous and not thread-safe. + +- Operations can thus be invoked by the app's datapath, + packet processing can continue while queue operations are processed by NIC. + +- Number of flow queues is configured at initialization stage. + +- Available operation types: rule creation, rule destruction, + indirect rule creation, indirect rule destruction, indirect rule update. + +- Operations may be reordered within a queue. + +- Operations can be postponed and pushed to NIC in batches. + +- Results pulling must be done on time to avoid queue overflows. + +- User data is returned as part of the result to identify an operation. + +- Flow handle is valid once the creation operation is enqueued and must be + destroyed even if the operation is not successful and the rule is not inserted. + +- Application must wait for the creation operation result before enqueueing + the deletion operation to make sure the creation is processed by NIC. + +The asynchronous flow rule insertion logic can be broken into two phases. + +1. Initialization stage as shown here: + +.. _figure_rte_flow_async_init: + +.. figure:: img/rte_flow_async_init.* + +2. Main loop as presented on a datapath application example: + +.. _figure_rte_flow_async_usage: + +.. figure:: img/rte_flow_async_usage.* + +Enqueue creation operation +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enqueueing a flow rule creation operation is similar to simple creation. + +.. code-block:: c + + struct rte_flow * + rte_flow_async_create(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow_template_table *template_table, + const struct rte_flow_item pattern[], + uint8_t pattern_template_index, + const struct rte_flow_action actions[], + uint8_t actions_template_index, + void *user_data, + struct rte_flow_error *error); + +A valid handle in case of success is returned. It must be destroyed later +by calling ``rte_flow_async_destroy()`` even if the rule is rejected by HW. + +Enqueue destruction operation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enqueueing a flow rule destruction operation is similar to simple destruction. + +.. code-block:: c + + int + rte_flow_async_destroy(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow *flow, + void *user_data, + struct rte_flow_error *error); + +Push enqueued operations +~~~~~~~~~~~~~~~~~~~~~~~~ + +Pushing all internally stored rules from a queue to the NIC. + +.. code-block:: c + + int + rte_flow_push(uint16_t port_id, + uint32_t queue_id, + struct rte_flow_error *error); + +There is the postpone attribute in the queue operation attributes. +When it is set, multiple operations can be bulked together and not sent to HW +right away to save SW/HW interactions and prioritize throughput over latency. +The application must invoke this function to actually push all outstanding +operations to HW in this case. + +Pull enqueued operations +~~~~~~~~~~~~~~~~~~~~~~~~ + +Pulling asynchronous operations results. + +The application must invoke this function in order to complete asynchronous +flow rule operations and to receive flow rule operations statuses. + +.. code-block:: c + + int + rte_flow_pull(uint16_t port_id, + uint32_t queue_id, + struct rte_flow_q_op_res res[], + uint16_t n_res, + struct rte_flow_error *error); + +Multiple outstanding operation results can be pulled simultaneously. +User data may be provided during a flow creation/destruction in order +to distinguish between multiple operations. User data is returned as part +of the result to provide a method to detect which operation is completed. + .. _flow_isolated_mode: Flow isolated mode diff --git a/doc/guides/rel_notes/release_22_03.rst b/doc/guides/rel_notes/release_22_03.rst index 7150d06c87..cd495ef40c 100644 --- a/doc/guides/rel_notes/release_22_03.rst +++ b/doc/guides/rel_notes/release_22_03.rst @@ -113,6 +113,13 @@ New Features ``rte_flow_template_table_destroy``, ``rte_flow_pattern_template_destroy`` and ``rte_flow_actions_template_destroy``. +* ** Added functions for asynchronous flow rules creation/destruction + + * ethdev: Added ``rte_flow_async_create`` and ``rte_flow_async_destroy`` API + to enqueue flow creaion/destruction operations asynchronously as well as + ``rte_flow_pull`` to poll and retrieve results of these operations and + ``rte_flow_push`` to push all the in-flight operations to the NIC. + * **Updated AF_XDP PMD** * Added support for libxdp >=v1.2.2. diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index e9f684eedb..4e7b202522 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -1396,6 +1396,7 @@ rte_flow_flex_item_release(uint16_t port_id, int rte_flow_info_get(uint16_t port_id, struct rte_flow_port_info *port_info, + struct rte_flow_queue_info *queue_info, struct rte_flow_error *error) { struct rte_eth_dev *dev = &rte_eth_devices[port_id]; @@ -1415,7 +1416,7 @@ rte_flow_info_get(uint16_t port_id, return -rte_errno; if (likely(!!ops->info_get)) { return flow_err(port_id, - ops->info_get(dev, port_info, error), + ops->info_get(dev, port_info, queue_info, error), error); } return rte_flow_error_set(error, ENOTSUP, @@ -1426,6 +1427,8 @@ rte_flow_info_get(uint16_t port_id, int rte_flow_configure(uint16_t port_id, const struct rte_flow_port_attr *port_attr, + uint16_t nb_queue, + const struct rte_flow_queue_attr *queue_attr[], struct rte_flow_error *error) { struct rte_eth_dev *dev = &rte_eth_devices[port_id]; @@ -1433,7 +1436,7 @@ rte_flow_configure(uint16_t port_id, int ret; dev->data->flow_configured = 0; - if (port_attr == NULL) { + if (port_attr == NULL || queue_attr == NULL) { RTE_FLOW_LOG(ERR, "Port %"PRIu16" info is NULL.\n", port_id); return -EINVAL; } @@ -1452,7 +1455,7 @@ rte_flow_configure(uint16_t port_id, if (unlikely(!ops)) return -rte_errno; if (likely(!!ops->configure)) { - ret = ops->configure(dev, port_attr, error); + ret = ops->configure(dev, port_attr, nb_queue, queue_attr, error); if (ret == 0) dev->data->flow_configured = 1; return flow_err(port_id, ret, error); @@ -1713,3 +1716,104 @@ rte_flow_template_table_destroy(uint16_t port_id, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, rte_strerror(ENOTSUP)); } + +struct rte_flow * +rte_flow_async_create(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow_template_table *template_table, + const struct rte_flow_item pattern[], + uint8_t pattern_template_index, + const struct rte_flow_action actions[], + uint8_t actions_template_index, + void *user_data, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + struct rte_flow *flow; + + if (unlikely(!ops)) + return NULL; + if (likely(!!ops->async_create)) { + flow = ops->async_create(dev, queue_id, + q_ops_attr, template_table, + pattern, pattern_template_index, + actions, actions_template_index, + user_data, error); + if (flow == NULL) + flow_err(port_id, -rte_errno, error); + return flow; + } + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + return NULL; +} + +int +rte_flow_async_destroy(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow *flow, + void *user_data, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + + if (unlikely(!ops)) + return -rte_errno; + if (likely(!!ops->async_destroy)) { + return flow_err(port_id, + ops->async_destroy(dev, queue_id, + q_ops_attr, flow, + user_data, error), + error); + } + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); +} + +int +rte_flow_push(uint16_t port_id, + uint32_t queue_id, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + + if (unlikely(!ops)) + return -rte_errno; + if (likely(!!ops->push)) { + return flow_err(port_id, + ops->push(dev, queue_id, error), + error); + } + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); +} + +int +rte_flow_pull(uint16_t port_id, + uint32_t queue_id, + struct rte_flow_q_op_res res[], + uint16_t n_res, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + int ret; + + if (unlikely(!ops)) + return -rte_errno; + if (likely(!!ops->pull)) { + ret = ops->pull(dev, queue_id, res, n_res, error); + return ret ? ret : flow_err(port_id, ret, error); + } + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); +} diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index 776e8ccc11..9e71a576f6 100644 --- a/lib/ethdev/rte_flow.h +++ b/lib/ethdev/rte_flow.h @@ -4884,6 +4884,10 @@ rte_flow_flex_item_release(uint16_t port_id, * */ struct rte_flow_port_info { + /** + * Maximum umber of queues for asynchronous operations. + */ + uint32_t max_nb_queues; /** * Maximum number of counters. * @see RTE_FLOW_ACTION_TYPE_COUNT @@ -4901,6 +4905,21 @@ struct rte_flow_port_info { uint32_t max_nb_meters; }; +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Information about flow engine asynchronous queues. + * The value only valid if @p port_attr.max_nb_queues is not zero. + * + */ +struct rte_flow_queue_info { + /** + * Maximum number of operations a queue can hold. + */ + uint32_t max_size; +}; + /** * @warning * @b EXPERIMENTAL: this API may change without prior notice. @@ -4912,6 +4931,9 @@ struct rte_flow_port_info { * @param[out] port_info * A pointer to a structure of type *rte_flow_port_info* * to be filled with the resources information of the port. + * @param[out] queue_info + * A pointer to a structure of type *rte_flow_queue_info* + * to be filled with the asynchronous queues information. * @param[out] error * Perform verbose error reporting if not NULL. * PMDs initialize this structure in case of error only. @@ -4923,6 +4945,7 @@ __rte_experimental int rte_flow_info_get(uint16_t port_id, struct rte_flow_port_info *port_info, + struct rte_flow_queue_info *queue_info, struct rte_flow_error *error); /** @@ -4951,6 +4974,21 @@ struct rte_flow_port_attr { uint32_t nb_meters; }; +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Flow engine asynchronous queues settings. + * The value means default value picked by PMD. + * + */ +struct rte_flow_queue_attr { + /** + * Number of flow rule operations a queue can hold. + */ + uint32_t size; +}; + /** * @warning * @b EXPERIMENTAL: this API may change without prior notice. @@ -4970,6 +5008,11 @@ struct rte_flow_port_attr { * Port identifier of Ethernet device. * @param[in] port_attr * Port configuration attributes. + * @param[in] nb_queue + * Number of flow queues to be configured. + * @param[in] queue_attr + * Array that holds attributes for each flow queue. + * Number of elements is set in @p port_attr.nb_queues. * @param[out] error * Perform verbose error reporting if not NULL. * PMDs initialize this structure in case of error only. @@ -4981,6 +5024,8 @@ __rte_experimental int rte_flow_configure(uint16_t port_id, const struct rte_flow_port_attr *port_attr, + uint16_t nb_queue, + const struct rte_flow_queue_attr *queue_attr[], struct rte_flow_error *error); /** @@ -5257,6 +5302,212 @@ rte_flow_template_table_destroy(uint16_t port_id, struct rte_flow_template_table *template_table, struct rte_flow_error *error); +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Queue operation attributes. + */ +__extension__ +struct rte_flow_q_ops_attr { + /** + * When set, the requested action will not be sent to the HW immediately. + * The application must call the rte_flow_queue_push to actually send it. + */ + uint32_t postpone:1; +}; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Enqueue rule creation operation. + * + * @param port_id + * Port identifier of Ethernet device. + * @param queue_id + * Flow queue used to insert the rule. + * @param[in] q_ops_attr + * Rule creation operation attributes. + * @param[in] template_table + * Template table to select templates from. + * @param[in] pattern + * List of pattern items to be used. + * The list order should match the order in the pattern template. + * The spec is the only relevant member of the item that is being used. + * @param[in] pattern_template_index + * Pattern template index in the table. + * @param[in] actions + * List of actions to be used. + * The list order should match the order in the actions template. + * @param[in] actions_template_index + * Actions template index in the table. + * @param[in] user_data + * The user data that will be returned on the completion events. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * Handle on success, NULL otherwise and rte_errno is set. + * The rule handle doesn't mean that the rule has been populated. + * Only completion result indicates that if there was success or failure. + */ +__rte_experimental +struct rte_flow * +rte_flow_async_create(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow_template_table *template_table, + const struct rte_flow_item pattern[], + uint8_t pattern_template_index, + const struct rte_flow_action actions[], + uint8_t actions_template_index, + void *user_data, + struct rte_flow_error *error); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Enqueue rule destruction operation. + * + * This function enqueues a destruction operation on the queue. + * Application should assume that after calling this function + * the rule handle is not valid anymore. + * Completion indicates the full removal of the rule from the HW. + * + * @param port_id + * Port identifier of Ethernet device. + * @param queue_id + * Flow queue which is used to destroy the rule. + * This must match the queue on which the rule was created. + * @param[in] q_ops_attr + * Rule destroy operation attributes. + * @param[in] flow + * Flow handle to be destroyed. + * @param[in] user_data + * The user data that will be returned on the completion events. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +__rte_experimental +int +rte_flow_async_destroy(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow *flow, + void *user_data, + struct rte_flow_error *error); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Push all internally stored rules to the HW. + * Postponed rules are rules that were inserted with the postpone flag set. + * Can be used to notify the HW about batch of rules prepared by the SW to + * reduce the number of communications between the HW and SW. + * + * @param port_id + * Port identifier of Ethernet device. + * @param queue_id + * Flow queue to be pushed. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set + * to one of the error codes defined: + * - (ENODEV) if *port_id* invalid. + * - (ENOSYS) if underlying device does not support this functionality. + * - (EIO) if underlying device is removed. + * - (EINVAL) if *queue_id* invalid. + */ +__rte_experimental +int +rte_flow_push(uint16_t port_id, + uint32_t queue_id, + struct rte_flow_error *error); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Queue operation status. + */ +enum rte_flow_q_op_status { + /** + * The operation was completed successfully. + */ + RTE_FLOW_Q_OP_SUCCESS, + /** + * The operation was not completed successfully. + */ + RTE_FLOW_Q_OP_ERROR, +}; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Queue operation results. + */ +__extension__ +struct rte_flow_q_op_res { + /** + * Returns the status of the operation that this completion signals. + */ + enum rte_flow_q_op_status status; + /** + * The user data that will be returned on the completion events. + */ + void *user_data; +}; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Pull a rte flow operation. + * The application must invoke this function in order to complete + * the flow rule offloading and to retrieve the flow rule operation status. + * + * @param port_id + * Port identifier of Ethernet device. + * @param queue_id + * Flow queue which is used to pull the operation. + * @param[out] res + * Array of results that will be set. + * @param[in] n_res + * Maximum number of results that can be returned. + * This value is equal to the size of the res array. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * Number of results that were pulled, + * a negative errno value otherwise and rte_errno is set + * to one of the error codes defined: + * - (ENODEV) if *port_id* invalid. + * - (ENOSYS) if underlying device does not support this functionality. + * - (EIO) if underlying device is removed. + * - (EINVAL) if *queue_id* invalid. + */ +__rte_experimental +int +rte_flow_pull(uint16_t port_id, + uint32_t queue_id, + struct rte_flow_q_op_res res[], + uint16_t n_res, + struct rte_flow_error *error); + #ifdef __cplusplus } #endif diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h index 2d96db1dc7..332783cf78 100644 --- a/lib/ethdev/rte_flow_driver.h +++ b/lib/ethdev/rte_flow_driver.h @@ -156,11 +156,14 @@ struct rte_flow_ops { int (*info_get) (struct rte_eth_dev *dev, struct rte_flow_port_info *port_info, + struct rte_flow_queue_info *queue_info, struct rte_flow_error *err); /** See rte_flow_configure() */ int (*configure) (struct rte_eth_dev *dev, const struct rte_flow_port_attr *port_attr, + uint16_t nb_queue, + const struct rte_flow_queue_attr *queue_attr[], struct rte_flow_error *err); /** See rte_flow_pattern_template_create() */ struct rte_flow_pattern_template *(*pattern_template_create) @@ -199,6 +202,38 @@ struct rte_flow_ops { (struct rte_eth_dev *dev, struct rte_flow_template_table *template_table, struct rte_flow_error *err); + /** See rte_flow_async_create() */ + struct rte_flow *(*async_create) + (struct rte_eth_dev *dev, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow_template_table *template_table, + const struct rte_flow_item pattern[], + uint8_t pattern_template_index, + const struct rte_flow_action actions[], + uint8_t actions_template_index, + void *user_data, + struct rte_flow_error *err); + /** See rte_flow_async_destroy() */ + int (*async_destroy) + (struct rte_eth_dev *dev, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow *flow, + void *user_data, + struct rte_flow_error *err); + /** See rte_flow_push() */ + int (*push) + (struct rte_eth_dev *dev, + uint32_t queue_id, + struct rte_flow_error *err); + /** See rte_flow_pull() */ + int (*pull) + (struct rte_eth_dev *dev, + uint32_t queue_id, + struct rte_flow_q_op_res res[], + uint16_t n_res, + struct rte_flow_error *error); }; /** diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map index 62ff791261..13c1a22118 100644 --- a/lib/ethdev/version.map +++ b/lib/ethdev/version.map @@ -272,6 +272,10 @@ EXPERIMENTAL { rte_flow_actions_template_destroy; rte_flow_template_table_create; rte_flow_template_table_destroy; + rte_flow_async_create; + rte_flow_async_destroy; + rte_flow_push; + rte_flow_pull; }; INTERNAL { From patchwork Sun Feb 20 03:44:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kozyrev X-Patchwork-Id: 107861 X-Patchwork-Delegate: ferruh.yigit@amd.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 59FE2A00C2; Sun, 20 Feb 2022 04:45:04 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 690F84115F; Sun, 20 Feb 2022 04:44:52 +0100 (CET) Received: from NAM10-DM6-obe.outbound.protection.outlook.com (mail-dm6nam10on2055.outbound.protection.outlook.com [40.107.93.55]) by mails.dpdk.org (Postfix) with ESMTP id 6CFB841153 for ; Sun, 20 Feb 2022 04:44:49 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ANhL6zmITmSmPnXokIqaYzgG4DVdy/6cL79RAZ8Zw9yrIY/xSRr+hJz4Oh9mVDB4R/obYRe0iJvs5lPYdqkyLH3mzEXOg/ZFSxmybPtZ/GSX5FxNd9oO6qKWUU41ZGTmpayza6CSMUaN7dDJ5zp/AF1iU4tvXCwe78i7znddKMZqu3Kz3TIUe9t6UhLuErlgedochnaHMOlzUVIMxs4y8z4/Hks0BhTDRVcHgZLJSUf846b/OYJRs0XnecxbEIXX77g1VR41Sgyn3F4XINRbZOiWQm60AufVb/RgoqR4+rqxEZNxHdyFavYrlFZHBvhexh9NzT1UnpiRJmHiefsdJQ== 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=7kgKwXoyFLxACtf1oq5zs3WkRxfN6fOA9O8IRumulwA=; b=TFHNTxu8fGtq2fkgGS6CWecBpmEzdK1k0Lq+okpQYYoFJoG3x0VRFL1bWIKyLzZGVYIszMdh8grBMej5sPWxfMWQSh2gMPC/8nJgC/7mEYe9vd6FhndTDM4Gk6D+zW4M5woeF6PocnJPM4MVWzLng+AEKymc/NhvBLyZPk5Y25vWI0psUw/5rkfBIFAmrcoyaVYKy3Ino8tdHtE99X3Pm3JKO3zznsEzih4ptV88AoEa7E/VLbcuiNpOJhF3fJ5tYgJRYFvaUdvNsIlfOM5B+NjXWxz2z7algcCcnLAALxW2cqsHAZJOCwLgd9/Wtwn4Bxp2L9+9eeu6IjwY5maz4w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 12.22.5.234) smtp.rcpttodomain=intel.com 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 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=7kgKwXoyFLxACtf1oq5zs3WkRxfN6fOA9O8IRumulwA=; b=V5V1H516l9KcNgmtINm0iYP0OMYsfA05irHe+S2fucbTt1QaZs0QhvyKbANoVe67lwXPXNAOOHmhIoq/bDLQaIrHZpxFla12ceWOn5AX0htgSCtx7W8ytLnt3LWmhunh7w5xv8CwW3LwUCZiV9tzbAQcaAQWbVfCBPLhq2qM+l6mGPHe9svVy/TzBplrApTkSrfbbQxk+LAc9GudEzQLGuUQvy5r0h291HIMWUFgHHGn/mH9k9r2faQJzTSGI/xTABGmeUIy9TC8/4dOrzohx+R+k/NncYBh3p3UlXQMcKsj2KMuAWPc0tH8a6iDGIGtt4MCkYL9xjBfFbYuds1o3Q== Received: from MN2PR12MB3613.namprd12.prod.outlook.com (2603:10b6:208:c1::17) by DM6PR12MB2714.namprd12.prod.outlook.com (2603:10b6:5:42::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.22; Sun, 20 Feb 2022 03:44:46 +0000 Received: from BN9P222CA0023.NAMP222.PROD.OUTLOOK.COM (2603:10b6:408:10c::28) by MN2PR12MB3613.namprd12.prod.outlook.com (2603:10b6:208:c1::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.24; Sun, 20 Feb 2022 03:44:46 +0000 Received: from BN8NAM11FT038.eop-nam11.prod.protection.outlook.com (2603:10b6:408:10c:cafe::94) by BN9P222CA0023.outlook.office365.com (2603:10b6:408:10c::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.15 via Frontend Transport; Sun, 20 Feb 2022 03:44:46 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 12.22.5.234) 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 12.22.5.234 as permitted sender) receiver=protection.outlook.com; client-ip=12.22.5.234; helo=mail.nvidia.com; Received: from mail.nvidia.com (12.22.5.234) by BN8NAM11FT038.mail.protection.outlook.com (10.13.176.246) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4995.15 via Frontend Transport; Sun, 20 Feb 2022 03:44:45 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by DRHQMAIL101.nvidia.com (10.27.9.10) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Sun, 20 Feb 2022 03:44:43 +0000 Received: from pegasus01.mtr.labs.mlnx (10.126.230.35) 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.9; Sat, 19 Feb 2022 19:44:39 -0800 From: Alexander Kozyrev To: CC: , , , , , , , , , Subject: [PATCH v8 04/11] ethdev: bring in async indirect actions operations Date: Sun, 20 Feb 2022 05:44:02 +0200 Message-ID: <20220220034409.2226860-5-akozyrev@nvidia.com> X-Mailer: git-send-email 2.18.2 In-Reply-To: <20220220034409.2226860-1-akozyrev@nvidia.com> References: <20220219041144.2145380-1-akozyrev@nvidia.com> <20220220034409.2226860-1-akozyrev@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.126.230.35] X-ClientProxiedBy: rnnvmail202.nvidia.com (10.129.68.7) To rnnvmail201.nvidia.com (10.129.68.8) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: f42200da-d6a9-4dce-83bf-08d9f4235670 X-MS-TrafficTypeDiagnostic: MN2PR12MB3613:EE_|DM6PR12MB2714:EE_ X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr,ExtAddr X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: heZvhX3NbyMXJYeCOOAV+PAW34Ev28TqA2Ez18xOe4rqrlDHJolRgL+qYfFZ6sF9+wB3XKm+wA+Y0kW1C7nSc3tP++s2XX2ZkgFeGkRz2BnQX927Kkr1+jyAGZTDnhIUTZvt/bqwQdEgfiX9HHY21xzeChwEecG3GvPayUeRowao2RclWuYPJawRcYkZ0GfCAyiVkd6rmNN8AB7q0oO5/RSpbK/RVcMutn3AMiKJJ0L3+xz0tGc0i8UwjDLtwF4qO7M5rAGrBcwA8hKDKo32YCxVNOpkqCG/Iswgd+EUo1tcWoZd0KFDmuwCCS25pQz6r394NGHY7Qfndb14OtnLW7iJCeF6myyc3NOES4rWhicwM3I3DKWhcnBU0LV1R4BFftf/dbYOxTVvQcdYjsXSU9hApkJ4n5UXMH8w5ScIftNACiGhAkgv5zwpwHbRhXcZXcZXyHzRTH3bJRS+Z+8B76G0tty76j2Fm1UHdqKHqKrms+bdqptxQ8+N8mwQROubMrIG9Zgoo1sOo4cyfK0Nm42GPJM5jtCj3QQ8+SLLF3E1bd9kR0RRuTHb+JVHcHjY8K07zoSdkYwa8Q82G/EL92CpVT3+nJPGBrjCJYXAzU2l3uIKYw0+puzKqWQePyZfj5K+K8uIOtsTJgRoGIkX50pC4HDjcZR5M6YhTYPHrPVWFZWodmyEOwLoTFSoB9XSH7vxPs+F5ePj6jPLyQJaxw== X-Forefront-Antispam-Report: CIP:12.22.5.234; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:mail.nvidia.com; PTR:InfoNoRecords; CAT:NONE; SFS:(13230001)(4636009)(46966006)(40470700004)(36840700001)(70206006)(70586007)(36860700001)(356005)(83380400001)(81166007)(4326008)(8676002)(7416002)(508600001)(82310400004)(2906002)(5660300002)(6666004)(30864003)(1076003)(26005)(8936002)(6916009)(54906003)(186003)(86362001)(40460700003)(36756003)(16526019)(316002)(426003)(336012)(2616005)(47076005)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Feb 2022 03:44:45.9318 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: f42200da-d6a9-4dce-83bf-08d9f4235670 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[12.22.5.234]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-CrossTenant-AuthSource: BN8NAM11FT038.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR12MB2714 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 Queue-based flow rules management mechanism is suitable not only for flow rules creation/destruction, but also for speeding up other types of Flow API management. Indirect action object operations may be executed asynchronously as well. Provide async versions for all indirect action operations, namely: rte_flow_async_action_handle_create, rte_flow_async_action_handle_destroy and rte_flow_async_action_handle_update. Signed-off-by: Alexander Kozyrev Acked-by: Ori Kam --- doc/guides/prog_guide/rte_flow.rst | 50 ++++++++++ doc/guides/rel_notes/release_22_03.rst | 5 + lib/ethdev/rte_flow.c | 75 ++++++++++++++ lib/ethdev/rte_flow.h | 130 +++++++++++++++++++++++++ lib/ethdev/rte_flow_driver.h | 26 +++++ lib/ethdev/version.map | 3 + 6 files changed, 289 insertions(+) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 436845717f..ac5e2046e4 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -3861,6 +3861,56 @@ Enqueueing a flow rule destruction operation is similar to simple destruction. void *user_data, struct rte_flow_error *error); +Enqueue indirect action creation operation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Asynchronous version of indirect action creation API. + +.. code-block:: c + + struct rte_flow_action_handle * + rte_flow_async_action_handle_create(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + const struct rte_flow_indir_action_conf *indir_action_conf, + const struct rte_flow_action *action, + void *user_data, + struct rte_flow_error *error); + +A valid handle in case of success is returned. It must be destroyed later by +``rte_flow_async_action_handle_destroy()`` even if the rule was rejected. + +Enqueue indirect action destruction operation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Asynchronous version of indirect action destruction API. + +.. code-block:: c + + int + rte_flow_async_action_handle_destroy(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow_action_handle *action_handle, + void *user_data, + struct rte_flow_error *error); + +Enqueue indirect action update operation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Asynchronous version of indirect action update API. + +.. code-block:: c + + int + rte_flow_async_action_handle_update(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow_action_handle *action_handle, + const void *update, + void *user_data, + struct rte_flow_error *error); + Push enqueued operations ~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/guides/rel_notes/release_22_03.rst b/doc/guides/rel_notes/release_22_03.rst index cd495ef40c..c9c9078cab 100644 --- a/doc/guides/rel_notes/release_22_03.rst +++ b/doc/guides/rel_notes/release_22_03.rst @@ -120,6 +120,11 @@ New Features ``rte_flow_pull`` to poll and retrieve results of these operations and ``rte_flow_push`` to push all the in-flight operations to the NIC. + * ethdev: Added asynchronous API for indirect actions management: + ``rte_flow_async_action_handle_create``, + ``rte_flow_async_action_handle_destroy`` and + ``rte_flow_async_action_handle_update``. + * **Updated AF_XDP PMD** * Added support for libxdp >=v1.2.2. diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 4e7b202522..38886edb0b 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -1817,3 +1817,78 @@ rte_flow_pull(uint16_t port_id, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, rte_strerror(ENOTSUP)); } + +struct rte_flow_action_handle * +rte_flow_async_action_handle_create(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + const struct rte_flow_indir_action_conf *indir_action_conf, + const struct rte_flow_action *action, + void *user_data, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + struct rte_flow_action_handle *handle; + + if (unlikely(!ops)) + return NULL; + if (unlikely(!ops->async_action_handle_create)) { + rte_flow_error_set(error, ENOSYS, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + rte_strerror(ENOSYS)); + return NULL; + } + handle = ops->async_action_handle_create(dev, queue_id, q_ops_attr, + indir_action_conf, action, user_data, error); + if (handle == NULL) + flow_err(port_id, -rte_errno, error); + return handle; +} + +int +rte_flow_async_action_handle_destroy(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow_action_handle *action_handle, + void *user_data, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + int ret; + + if (unlikely(!ops)) + return -rte_errno; + if (unlikely(!ops->async_action_handle_destroy)) + return rte_flow_error_set(error, ENOSYS, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOSYS)); + ret = ops->async_action_handle_destroy(dev, queue_id, q_ops_attr, + action_handle, user_data, error); + return flow_err(port_id, ret, error); +} + +int +rte_flow_async_action_handle_update(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow_action_handle *action_handle, + const void *update, + void *user_data, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + int ret; + + if (unlikely(!ops)) + return -rte_errno; + if (unlikely(!ops->async_action_handle_update)) + return rte_flow_error_set(error, ENOSYS, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOSYS)); + ret = ops->async_action_handle_update(dev, queue_id, q_ops_attr, + action_handle, update, user_data, error); + return flow_err(port_id, ret, error); +} diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index 9e71a576f6..f85f20abe6 100644 --- a/lib/ethdev/rte_flow.h +++ b/lib/ethdev/rte_flow.h @@ -5508,6 +5508,136 @@ rte_flow_pull(uint16_t port_id, uint16_t n_res, struct rte_flow_error *error); +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Enqueue indirect action creation operation. + * @see rte_flow_action_handle_create + * + * @param[in] port_id + * Port identifier of Ethernet device. + * @param[in] queue_id + * Flow queue which is used to create the rule. + * @param[in] q_ops_attr + * Queue operation attributes. + * @param[in] indir_action_conf + * Action configuration for the indirect action object creation. + * @param[in] action + * Specific configuration of the indirect action object. + * @param[in] user_data + * The user data that will be returned on the completion events. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * A valid handle in case of success, NULL otherwise and rte_errno is set + * to one of the error codes defined: + * - (ENODEV) if *port_id* invalid. + * - (ENOSYS) if underlying device does not support this functionality. + * - (EIO) if underlying device is removed. + * - (EINVAL) if *action* invalid. + * - (ENOTSUP) if *action* valid but unsupported. + * - (EAGAIN) if *queue* is full + */ +__rte_experimental +struct rte_flow_action_handle * +rte_flow_async_action_handle_create(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + const struct rte_flow_indir_action_conf *indir_action_conf, + const struct rte_flow_action *action, + void *user_data, + struct rte_flow_error *error); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Enqueue indirect action destruction operation. + * The destroy queue must be the same + * as the queue on which the action was created. + * + * @param[in] port_id + * Port identifier of Ethernet device. + * @param[in] queue_id + * Flow queue which is used to destroy the rule. + * @param[in] q_ops_attr + * Queue operation attributes. + * @param[in] action_handle + * Handle for the indirect action object to be destroyed. + * @param[in] user_data + * The user data that will be returned on the completion events. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * - (0) if success. + * - (-ENODEV) if *port_id* invalid. + * - (-ENOSYS) if underlying device does not support this functionality. + * - (-EIO) if underlying device is removed. + * - (-ENOENT) if action pointed by *action* handle was not found. + * - (-EBUSY) if action pointed by *action* handle still used by some rules + * rte_errno is also set. + * - (EAGAIN) if *queue* is full + */ +__rte_experimental +int +rte_flow_async_action_handle_destroy(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow_action_handle *action_handle, + void *user_data, + struct rte_flow_error *error); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Enqueue indirect action update operation. + * @see rte_flow_action_handle_create + * + * @param[in] port_id + * Port identifier of Ethernet device. + * @param[in] queue_id + * Flow queue which is used to update the rule. + * @param[in] q_ops_attr + * Queue operation attributes. + * @param[in] action_handle + * Handle for the indirect action object to be updated. + * @param[in] update + * Update profile specification used to modify the action pointed by handle. + * *update* could be with the same type of the immediate action corresponding + * to the *handle* argument when creating, or a wrapper structure includes + * action configuration to be updated and bit fields to indicate the member + * of fields inside the action to update. + * @param[in] user_data + * The user data that will be returned on the completion events. + * @param[out] error + * Perform verbose error reporting if not NULL. + * PMDs initialize this structure in case of error only. + * + * @return + * - (0) if success. + * - (-ENODEV) if *port_id* invalid. + * - (-ENOSYS) if underlying device does not support this functionality. + * - (-EIO) if underlying device is removed. + * - (-ENOENT) if action pointed by *action* handle was not found. + * - (-EBUSY) if action pointed by *action* handle still used by some rules + * rte_errno is also set. + * - (EAGAIN) if *queue* is full + */ +__rte_experimental +int +rte_flow_async_action_handle_update(uint16_t port_id, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow_action_handle *action_handle, + const void *update, + void *user_data, + struct rte_flow_error *error); #ifdef __cplusplus } #endif diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h index 332783cf78..d660e29c6a 100644 --- a/lib/ethdev/rte_flow_driver.h +++ b/lib/ethdev/rte_flow_driver.h @@ -234,6 +234,32 @@ struct rte_flow_ops { struct rte_flow_q_op_res res[], uint16_t n_res, struct rte_flow_error *error); + /** See rte_flow_async_action_handle_create() */ + struct rte_flow_action_handle *(*async_action_handle_create) + (struct rte_eth_dev *dev, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + const struct rte_flow_indir_action_conf *indir_action_conf, + const struct rte_flow_action *action, + void *user_data, + struct rte_flow_error *err); + /** See rte_flow_async_action_handle_destroy() */ + int (*async_action_handle_destroy) + (struct rte_eth_dev *dev, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow_action_handle *action_handle, + void *user_data, + struct rte_flow_error *error); + /** See rte_flow_async_action_handle_update() */ + int (*async_action_handle_update) + (struct rte_eth_dev *dev, + uint32_t queue_id, + const struct rte_flow_q_ops_attr *q_ops_attr, + struct rte_flow_action_handle *action_handle, + const void *update, + void *user_data, + struct rte_flow_error *error); }; /** diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map index 13c1a22118..20391ab29e 100644 --- a/lib/ethdev/version.map +++ b/lib/ethdev/version.map @@ -276,6 +276,9 @@ EXPERIMENTAL { rte_flow_async_destroy; rte_flow_push; rte_flow_pull; + rte_flow_async_action_handle_create; + rte_flow_async_action_handle_destroy; + rte_flow_async_action_handle_update; }; INTERNAL { From patchwork Sun Feb 20 03:44:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kozyrev X-Patchwork-Id: 107862 X-Patchwork-Delegate: ferruh.yigit@amd.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 85E88A00C2; Sun, 20 Feb 2022 04:45:12 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id BF0B141171; Sun, 20 Feb 2022 04:44:54 +0100 (CET) Received: from NAM10-DM6-obe.outbound.protection.outlook.com (mail-dm6nam10on2080.outbound.protection.outlook.com [40.107.93.80]) by mails.dpdk.org (Postfix) with ESMTP id A3E884116D for ; Sun, 20 Feb 2022 04:44:53 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Dy1azZ4uE/6h7zwq1S364DVMbpTBiHcFRi2Ks/e7+M9VVhMCr2dLn8LQJEkhMJLBhT//GJ4w3tGU+jfbTj+LOUIntT8iFQU7sLxOfxTXifa50i8N6dHitW8A+4l6szomOHlorNvFZhwCmsVnKq+XXQ58LG21an+7zVnfF2a9WZDzAuksmefycUoUnR2JNbGWlxNSqvywBzw1R4BxzNm9sYDscOcpi8JtiODxOk7N4uC6iq+5FV0y1k6+T1aCnhKlBxmJQcd6tyrtwSUzKsa7p9QgZ3q5kGjgGvHZKOUlXknQpOqCxz9zO0t5MTNsSjoiufhqKleN6pRlOPy65mvd1g== 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=1njSzhhZT0vrwKozTCDbOEoSzHstT8+Ug0QtkO/8b/s=; b=kBHTBweUXPL8faiZaxhwwwzoUSOy07pQXLMehxgTtvNgCGljwwtML1UR80gZYT7UtQOp/0UkvaE12lYkgJlv1+L5Lo0dYEyqo6ZHCid+Hvc+bgdtw8rOCh24+f6hC4KeBsF75rIvITH3kDkFDdO8ZHLn1HeTfa/dJXbTRImYp+WTZKootClEuq7tpLzQOy8lRN9HsZ4JXsHL0RWf3XVVuRRViCxHypGtds8QvDT7RKkZnwT8DZm2K/hwVj6mPoxW7XfbpyIZ2UxiATeEuwSGMUUWCtAq/5VXwHfcUzFVu/QNbzo19yq5pjvFTRHZL+bF2qxsTl5vWZwEkxfg96M3Jg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 12.22.5.235) smtp.rcpttodomain=intel.com 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 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=1njSzhhZT0vrwKozTCDbOEoSzHstT8+Ug0QtkO/8b/s=; b=X8JUdSChL/7WQ6Bnu61j/hnMjHKB84jgJBQK3RVhD5ZFc/6RHXk7LoB22l1/xJyyH+rqLd0GrO4vBXebmMuAGW0sTFFnZ8rA1yHoYBkC6wtzOPGsJovDWEbVDeU4zTSLI0EAJdG4pAA3zhR3a6erpJVtnwwHT5ROna6Q/MwhLKEh61QVReLbu4PgTbMYjWP4CJ+JhjeJ2c4+rcZdMUXFcKh5SU+NRoM8FqjfuIhf1s4xIQyHQcEN+bWVSKYOSAUmy9UPDhgiGb8yOo8O3Gmo6GhIMbzc8IcHXbb0r5P/NFaULtLq3n8HltptGBK8etgTV2Nfnz6B8bGg5IUoc/rg4w== Received: from DM6PR12MB3401.namprd12.prod.outlook.com (2603:10b6:5:39::32) by SN1PR12MB2349.namprd12.prod.outlook.com (2603:10b6:802:2a::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.24; Sun, 20 Feb 2022 03:44:51 +0000 Received: from DM5PR2201CA0007.namprd22.prod.outlook.com (2603:10b6:4:14::17) by DM6PR12MB3401.namprd12.prod.outlook.com (2603:10b6:5:39::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.15; Sun, 20 Feb 2022 03:44:47 +0000 Received: from DM6NAM11FT008.eop-nam11.prod.protection.outlook.com (2603:10b6:4:14:cafe::47) by DM5PR2201CA0007.outlook.office365.com (2603:10b6:4:14::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.25 via Frontend Transport; Sun, 20 Feb 2022 03:44:47 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 12.22.5.235) 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 12.22.5.235 as permitted sender) receiver=protection.outlook.com; client-ip=12.22.5.235; helo=mail.nvidia.com; Received: from mail.nvidia.com (12.22.5.235) by DM6NAM11FT008.mail.protection.outlook.com (10.13.172.85) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4995.20 via Frontend Transport; Sun, 20 Feb 2022 03:44:46 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by DRHQMAIL107.nvidia.com (10.27.9.16) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Sun, 20 Feb 2022 03:44:46 +0000 Received: from pegasus01.mtr.labs.mlnx (10.126.230.35) 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.9; Sat, 19 Feb 2022 19:44:42 -0800 From: Alexander Kozyrev To: CC: , , , , , , , , , Subject: [PATCH v8 05/11] app/testpmd: add flow engine configuration Date: Sun, 20 Feb 2022 05:44:03 +0200 Message-ID: <20220220034409.2226860-6-akozyrev@nvidia.com> X-Mailer: git-send-email 2.18.2 In-Reply-To: <20220220034409.2226860-1-akozyrev@nvidia.com> References: <20220219041144.2145380-1-akozyrev@nvidia.com> <20220220034409.2226860-1-akozyrev@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.126.230.35] X-ClientProxiedBy: rnnvmail202.nvidia.com (10.129.68.7) To rnnvmail201.nvidia.com (10.129.68.8) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 46e42957-6c9d-4da0-3df7-08d9f423570d X-MS-TrafficTypeDiagnostic: DM6PR12MB3401:EE_|SN1PR12MB2349:EE_ X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr,ExtAddr X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 7X1H8iIi7eYZ/1WX72wDqWPx0rJavq1jASr2Xqff3KxVvUPff8LPd+2iuJw7SoYlrdNuQSjLJnVFH+dcGyka2P0FMb16BCn1TlbMY30sge3n/hQMDxNh7oHmLXnC9LCHZ2IkvnOEhIZH8aJwDRjn8Z94eDWTO1zWq3TVa03ws/eDmTZu2CkNOEM37WsVS+EOI0SxMz0Plp7TAmdGdcaHLQCtfwwYlrN2xPrivaierrGzURDp7Ix6ahLx+OFcz4ErGC0A2ST8UvDL5x7Jpg+JhLFhF/VI96deYiy4NxVSQ8paDB6jiMMYyzCOpwvxz+EsS78tH2OtOSeovFaOtd/j/m0jODBhCOhs8qJ/QIqncG5XpVJzwokyJGFckd+3mz7YqnyPI8Iu/zxJlskI9pjKhrK0trWOdcB0zVRbSjtfQpY9rp/oZeMM907GsNvKibT5Gnmik7aOR8+c+8AcqcPDaX/9TH9Lm+8DLl0m1MiKyDy2EPBZu8O784MChdn9UBwX+hjW1UzkLVrA+stBC5g/Z7lqEm3vmYeRVxYBUs+2SD0HP10xFyrZ2o8aAFyaL8xMoWJKXVu/2dj2Qle6K9Lf+X2LyfRgfhJiO4245lctJzAwJFmyGG8rvvo0CwHWfLOVpbNFL/GHs+khoBJqt+p5PuMVjBGOgviDg0TyC8I/+BiKn/cRsCZgMlIaBcTe3RwqZyDOx+P1wsf633xIlNoqzg== X-Forefront-Antispam-Report: CIP:12.22.5.235; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:mail.nvidia.com; PTR:InfoNoRecords; CAT:NONE; SFS:(13230001)(4636009)(46966006)(36840700001)(40470700004)(316002)(2906002)(86362001)(82310400004)(54906003)(336012)(426003)(6916009)(6666004)(2616005)(47076005)(5660300002)(7416002)(40460700003)(8936002)(36860700001)(16526019)(186003)(26005)(4326008)(8676002)(356005)(81166007)(1076003)(30864003)(83380400001)(36756003)(70206006)(70586007)(508600001)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Feb 2022 03:44:46.9435 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 46e42957-6c9d-4da0-3df7-08d9f423570d X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[12.22.5.235]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-CrossTenant-AuthSource: DM6NAM11FT008.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1PR12MB2349 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 testpmd support for the rte_flow_configure API. Provide the command line interface for the Flow management. Usage example: flow configure 0 queues_number 8 queues_size 256 Implement rte_flow_info_get API to get available resources: Usage example: flow info 0 Signed-off-by: Alexander Kozyrev Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 126 +++++++++++++++++++- app/test-pmd/config.c | 61 ++++++++++ app/test-pmd/testpmd.h | 7 ++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 61 +++++++++- 4 files changed, 252 insertions(+), 3 deletions(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index c0644d678c..0533a33ca2 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -72,6 +72,8 @@ enum index { /* Top-level command. */ FLOW, /* Sub-level commands. */ + INFO, + CONFIGURE, INDIRECT_ACTION, VALIDATE, CREATE, @@ -122,6 +124,13 @@ enum index { DUMP_ALL, DUMP_ONE, + /* Configure arguments */ + CONFIG_QUEUES_NUMBER, + CONFIG_QUEUES_SIZE, + CONFIG_COUNTERS_NUMBER, + CONFIG_AGING_OBJECTS_NUMBER, + CONFIG_METERS_NUMBER, + /* Indirect action arguments */ INDIRECT_ACTION_CREATE, INDIRECT_ACTION_UPDATE, @@ -868,6 +877,11 @@ struct buffer { enum index command; /**< Flow command. */ portid_t port; /**< Affected port ID. */ union { + struct { + struct rte_flow_port_attr port_attr; + uint32_t nb_queue; + struct rte_flow_queue_attr queue_attr; + } configure; /**< Configuration arguments. */ struct { uint32_t *action_id; uint32_t action_id_n; @@ -949,6 +963,16 @@ static const enum index next_flex_item[] = { ZERO, }; +static const enum index next_config_attr[] = { + CONFIG_QUEUES_NUMBER, + CONFIG_QUEUES_SIZE, + CONFIG_COUNTERS_NUMBER, + CONFIG_AGING_OBJECTS_NUMBER, + CONFIG_METERS_NUMBER, + END, + ZERO, +}; + static const enum index next_ia_create_attr[] = { INDIRECT_ACTION_CREATE_ID, INDIRECT_ACTION_INGRESS, @@ -2045,6 +2069,9 @@ static int parse_aged(struct context *, const struct token *, static int parse_isolate(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_configure(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_tunnel(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -2270,7 +2297,9 @@ static const struct token token_list[] = { .type = "{command} {port_id} [{arg} [...]]", .help = "manage ingress/egress flow rules", .next = NEXT(NEXT_ENTRY - (INDIRECT_ACTION, + (INFO, + CONFIGURE, + INDIRECT_ACTION, VALIDATE, CREATE, DESTROY, @@ -2285,6 +2314,65 @@ static const struct token token_list[] = { .call = parse_init, }, /* Top-level command. */ + [INFO] = { + .name = "info", + .help = "get information about flow engine", + .next = NEXT(NEXT_ENTRY(END), + NEXT_ENTRY(COMMON_PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_configure, + }, + /* Top-level command. */ + [CONFIGURE] = { + .name = "configure", + .help = "configure flow engine", + .next = NEXT(next_config_attr, + NEXT_ENTRY(COMMON_PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_configure, + }, + /* Configure arguments. */ + [CONFIG_QUEUES_NUMBER] = { + .name = "queues_number", + .help = "number of queues", + .next = NEXT(next_config_attr, + NEXT_ENTRY(COMMON_UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.configure.nb_queue)), + }, + [CONFIG_QUEUES_SIZE] = { + .name = "queues_size", + .help = "number of elements in queues", + .next = NEXT(next_config_attr, + NEXT_ENTRY(COMMON_UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.configure.queue_attr.size)), + }, + [CONFIG_COUNTERS_NUMBER] = { + .name = "counters_number", + .help = "number of counters", + .next = NEXT(next_config_attr, + NEXT_ENTRY(COMMON_UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.configure.port_attr.nb_counters)), + }, + [CONFIG_AGING_OBJECTS_NUMBER] = { + .name = "aging_counters_number", + .help = "number of aging objects", + .next = NEXT(next_config_attr, + NEXT_ENTRY(COMMON_UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.configure.port_attr.nb_aging_objects)), + }, + [CONFIG_METERS_NUMBER] = { + .name = "meters_number", + .help = "number of meters", + .next = NEXT(next_config_attr, + NEXT_ENTRY(COMMON_UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.configure.port_attr.nb_meters)), + }, + /* Top-level command. */ [INDIRECT_ACTION] = { .name = "indirect_action", .type = "{command} {port_id} [{arg} [...]]", @@ -7736,6 +7824,33 @@ parse_isolate(struct context *ctx, const struct token *token, return len; } +/** Parse tokens for info/configure command. */ +static int +parse_configure(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command) { + if (ctx->curr != INFO && ctx->curr != CONFIGURE) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + } + return len; +} + static int parse_flex(struct context *ctx, const struct token *token, const char *str, unsigned int len, @@ -8964,6 +9079,15 @@ static void cmd_flow_parsed(const struct buffer *in) { switch (in->command) { + case INFO: + port_flow_get_info(in->port); + break; + case CONFIGURE: + port_flow_configure(in->port, + &in->args.configure.port_attr, + in->args.configure.nb_queue, + &in->args.configure.queue_attr); + break; case INDIRECT_ACTION_CREATE: port_action_handle_create( in->port, in->args.vc.attr.group, diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index de1ec14bc7..33a85cd7ca 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -1610,6 +1610,67 @@ action_alloc(portid_t port_id, uint32_t id, return 0; } +/** Get info about flow management resources. */ +int +port_flow_get_info(portid_t port_id) +{ + struct rte_flow_port_info port_info; + struct rte_flow_queue_info queue_info; + struct rte_flow_error error; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x99, sizeof(error)); + memset(&port_info, 0, sizeof(port_info)); + memset(&queue_info, 0, sizeof(queue_info)); + if (rte_flow_info_get(port_id, &port_info, &queue_info, &error)) + return port_flow_complain(&error); + printf("Flow engine resources on port %u:\n" + "Number of queues: %d\n" + "Size of queues: %d\n" + "Number of counters: %d\n" + "Number of aging objects: %d\n" + "Number of meter actions: %d\n", + port_id, port_info.max_nb_queues, + queue_info.max_size, + port_info.max_nb_counters, + port_info.max_nb_aging_objects, + port_info.max_nb_meters); + return 0; +} + +/** Configure flow management resources. */ +int +port_flow_configure(portid_t port_id, + const struct rte_flow_port_attr *port_attr, + uint16_t nb_queue, + const struct rte_flow_queue_attr *queue_attr) +{ + struct rte_port *port; + struct rte_flow_error error; + const struct rte_flow_queue_attr *attr_list[nb_queue]; + int std_queue; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + port->queue_nb = nb_queue; + port->queue_sz = queue_attr->size; + for (std_queue = 0; std_queue < nb_queue; std_queue++) + attr_list[std_queue] = queue_attr; + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x66, sizeof(error)); + if (rte_flow_configure(port_id, port_attr, nb_queue, attr_list, &error)) + return port_flow_complain(&error); + printf("Configure flows on port %u: " + "number of queues %d with %d elements\n", + port_id, nb_queue, queue_attr->size); + return 0; +} + /** Create indirect action */ int port_action_handle_create(portid_t port_id, uint32_t id, diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 9967825044..096b6825eb 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -243,6 +243,8 @@ struct rte_port { struct rte_eth_txconf tx_conf[RTE_MAX_QUEUES_PER_PORT+1]; /**< per queue tx configuration */ struct rte_ether_addr *mc_addr_pool; /**< pool of multicast addrs */ uint32_t mc_addr_nb; /**< nb. of addr. in mc_addr_pool */ + queueid_t queue_nb; /**< nb. of queues for flow rules */ + uint32_t queue_sz; /**< size of a queue for flow rules */ uint8_t slave_flag; /**< bonding slave port */ struct port_flow *flow_list; /**< Associated flows. */ struct port_indirect_action *actions_list; @@ -885,6 +887,11 @@ struct rte_flow_action_handle *port_action_handle_get_by_id(portid_t port_id, uint32_t id); int port_action_handle_update(portid_t port_id, uint32_t id, const struct rte_flow_action *action); +int port_flow_get_info(portid_t port_id); +int port_flow_configure(portid_t port_id, + const struct rte_flow_port_attr *port_attr, + uint16_t nb_queue, + const struct rte_flow_queue_attr *queue_attr); int port_flow_validate(portid_t port_id, const struct rte_flow_attr *attr, const struct rte_flow_item *pattern, diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 9cc248084f..c8f048aeef 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -3308,8 +3308,8 @@ Flow rules management --------------------- Control of the generic flow API (*rte_flow*) is fully exposed through the -``flow`` command (validation, creation, destruction, queries and operation -modes). +``flow`` command (configuration, validation, creation, destruction, queries +and operation modes). Considering *rte_flow* overlaps with all `Filter Functions`_, using both features simultaneously may cause undefined side-effects and is therefore @@ -3332,6 +3332,18 @@ The first parameter stands for the operation mode. Possible operations and their general syntax are described below. They are covered in detail in the following sections. +- Get info about flow engine:: + + flow info {port_id} + +- Configure flow engine:: + + flow configure {port_id} + [queues_number {number}] [queues_size {size}] + [counters_number {number}] + [aging_counters_number {number}] + [meters_number {number}] + - Check whether a flow rule can be created:: flow validate {port_id} @@ -3391,6 +3403,51 @@ following sections. flow tunnel list {port_id} +Retrieving info about flow management engine +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow info`` retrieves info on pre-configurable resources in the underlying +device to give a hint of possible values for flow engine configuration. + +``rte_flow_info_get()``:: + + flow info {port_id} + +If successful, it will show:: + + Flow engine resources on port #[...]: + Number of queues: #[...] + Size of queues: #[...] + Number of counters: #[...] + Number of aging objects: #[...] + Number of meters: #[...] + +Otherwise it will show an error message of the form:: + + Caught error type [...] ([...]): [...] + +Configuring flow management engine +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow configure`` pre-allocates all the needed resources in the underlying +device to be used later at the flow creation. Flow queues are allocated as well +for asynchronous flow creation/destruction operations. It is bound to +``rte_flow_configure()``:: + + flow configure {port_id} + [queues_number {number}] [queues_size {size}] + [counters_number {number}] + [aging_counters_number {number}] + [meters_number {number}] + +If successful, it will show:: + + Configure flows on port #[...]: number of queues #[...] with #[...] elements + +Otherwise it will show an error message of the form:: + + Caught error type [...] ([...]): [...] + Creating a tunnel stub for offload ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From patchwork Sun Feb 20 03:44:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kozyrev X-Patchwork-Id: 107865 X-Patchwork-Delegate: ferruh.yigit@amd.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 74F50A00C2; Sun, 20 Feb 2022 04:45:32 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id EA40341180; Sun, 20 Feb 2022 04:45:04 +0100 (CET) Received: from NAM11-CO1-obe.outbound.protection.outlook.com (mail-co1nam11on2058.outbound.protection.outlook.com [40.107.220.58]) by mails.dpdk.org (Postfix) with ESMTP id E312741152 for ; Sun, 20 Feb 2022 04:45:02 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=mfVQHndruo6GNglJDFwQVtdf8NVszSNCc4QQqkA3ociPYgqrr9/K12tvUFWQNTXXfn2jPXHb4GDAKzYD9XWQD/NIM3EHohX/FbHG/PLDJKyi5cjiTVoqFUgYHw6BCpn3A2fH8oRkY2WCV/uKKqfQZcAjCvqCRu3Qx3UCz9/F6Ds1CTtU4f4oOQYw6feIdUILshrS9Iv/BPQ3it4G9HzYpLIyreh62LaNuuBanmTdvrQjTLm3w0iCZKD1vNaqEMeyXgJifwV9SWMbfgKrOetJ7wC4D6yBqA9ntnUzY2wQKN/85dlGH41GHD5nbRYsSMT6HfZKOfCGMNOryyfHFSpKUA== 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=AAZYeW/g5iouyFM+w5iZkrXPtvw+WaxaoxTrSjljtZg=; b=HnG7F6IylOr/pGnA9mhz3SgapZ5iNCL+u/4O0IAWr1oSm10MwKnTAHhw+hC3eT+8k5ewMyRQeNelDx0kHbwNB1lFSbZ5Ox8y1bJU3t3q0YUo08oOh824JNvP6tlpfvTXMjT9LRSkrNxW88d5UX2lbN1kLOqdIxP49qIrTk++MS2pRzmTXVcoMtd2nVzyWb0fXgF3Id+qOQpndVdzXZD9XqEgN17bGx9+yMFaq2EEBXS9lc9a3lkENg452YKiWO/mgjo2EypTCPHrahNEFTvbNpFT/mVjP6J1mj1M7wndKIh562tTBuI0+DWBwJdISoo3A715RMV/0yKNpeGY7xjt/g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 12.22.5.238) smtp.rcpttodomain=intel.com 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 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=AAZYeW/g5iouyFM+w5iZkrXPtvw+WaxaoxTrSjljtZg=; b=jdnLMV1ICRDsW+eHglWWgkBE0cYQURmE9wEwKLDwa7PMt92QPWsLDEt9HC32EYCRxyVLQ5sKRXXZHhVt0u5Y/BjSIHufpw4k3ANObOf2kgGGMJKJtQLCGBwRT64zzihQHfEPN5r1FDfjRYhPn9hzkqyrUVIEQLfeOHrVuhn/Ay8/62nitRw+Hg6hSTjTOAFQcmvjsiStsUyEk6P/q4Sl6fgXE8E0jv1k6Rxw/2YqK8jMCdY1uqYGdLYRkm2EMbaoHWsdLr8WfPvqxiIliW1P2ieaxE64Gb6Ml4Jm//JI05aNdN/EzlZF1qxf8MXtJxmQVrH+qbPOozZKObAcxGsiQQ== Received: from DS7PR12MB6007.namprd12.prod.outlook.com (2603:10b6:8:7e::13) by DM6PR12MB3963.namprd12.prod.outlook.com (2603:10b6:5:1cd::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.16; Sun, 20 Feb 2022 03:44:54 +0000 Received: from BN6PR11CA0004.namprd11.prod.outlook.com (2603:10b6:405:2::14) by DS7PR12MB6007.namprd12.prod.outlook.com (2603:10b6:8:7e::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.24; Sun, 20 Feb 2022 03:44:52 +0000 Received: from BN8NAM11FT036.eop-nam11.prod.protection.outlook.com (2603:10b6:405:2:cafe::8f) by BN6PR11CA0004.outlook.office365.com (2603:10b6:405:2::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.14 via Frontend Transport; Sun, 20 Feb 2022 03:44:52 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 12.22.5.238) 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 12.22.5.238 as permitted sender) receiver=protection.outlook.com; client-ip=12.22.5.238; helo=mail.nvidia.com; Received: from mail.nvidia.com (12.22.5.238) by BN8NAM11FT036.mail.protection.outlook.com (10.13.177.168) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4995.15 via Frontend Transport; Sun, 20 Feb 2022 03:44:52 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by DRHQMAIL105.nvidia.com (10.27.9.14) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Sun, 20 Feb 2022 03:44:49 +0000 Received: from pegasus01.mtr.labs.mlnx (10.126.230.35) 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.9; Sat, 19 Feb 2022 19:44:45 -0800 From: Alexander Kozyrev To: CC: , , , , , , , , , Subject: [PATCH v8 06/11] app/testpmd: add flow template management Date: Sun, 20 Feb 2022 05:44:04 +0200 Message-ID: <20220220034409.2226860-7-akozyrev@nvidia.com> X-Mailer: git-send-email 2.18.2 In-Reply-To: <20220220034409.2226860-1-akozyrev@nvidia.com> References: <20220219041144.2145380-1-akozyrev@nvidia.com> <20220220034409.2226860-1-akozyrev@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.126.230.35] X-ClientProxiedBy: rnnvmail202.nvidia.com (10.129.68.7) To rnnvmail201.nvidia.com (10.129.68.8) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 4d15b009-6fda-4c4f-4752-08d9f4235a3b X-MS-TrafficTypeDiagnostic: DS7PR12MB6007:EE_|DM6PR12MB3963:EE_ X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr,ExtAddr X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: eXTvguJGNA7++Z7khPbpxXqSTNMnB0QaPKPCeBPg06L4lBwrZPcGPaBZeCtAOks99slDY8fE8Lfbm6MRLptvBpySlAjb9GNWj0QDw7k7DqQ/EkA2Hkkn5aDBhmEwiFe+TK6MYZ4gBR22fKBN2zQB3gSZZHFxiAKVZBu0n7T+q/ledzsbQ5e2z+UyeYf7QrF1hs4EDsj3VQpjICHOaUTnhLIT0z96qjDR7yUP4MSHC6HASYu+A1k7FFpCEdrAvkt9eRyQf7d5Cw1/eo2TYPvUZlps6ihaO4X75lFLIrsp1aLOZdgJ4SumJuTEq4267KRbhNQQNTQaaxixHC4Xibg3JJ0L9pbTiBN+VZ7oUkZMDDnQPROnyW0eftkVnbjhGa52IqecNIO80sCUfe9xDT8stEaHeUpVK9ACVbsuNhDKDYrMFJ9ehng6W8cKLTdItwI+K3LJN82FXI89OUroGvO/aZXdbavDtBq4FzTZIQfy+fKYuSMAgAxuciWZjqmjwicZvVH+8ubOcY+3XvV+jYlYzyw/QsMFn1nL7ojkUOVTDM8SXhQ8ZfGT3/eYR/Dhr6bzwo02t6Bp3VEXntBNDRhaLQhJdYfzbafHZu0eDsAlG7+Jic1l4Vb7gYD8MZGXLaz0JAdTyWqeVEr/wG6wxP+N5tXo1+2rUJBgIca3Nv1fePKmLht5z1Ffjv2SJXhnk0NDrSJBBbOWCLIaFHMQ5xap/w== X-Forefront-Antispam-Report: CIP:12.22.5.238; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:mail.nvidia.com; PTR:InfoNoRecords; CAT:NONE; SFS:(13230001)(4636009)(36840700001)(40470700004)(46966006)(70206006)(86362001)(70586007)(6916009)(54906003)(4326008)(47076005)(356005)(8676002)(83380400001)(36756003)(316002)(8936002)(508600001)(7416002)(5660300002)(30864003)(6666004)(16526019)(2906002)(82310400004)(40460700003)(81166007)(2616005)(1076003)(426003)(336012)(186003)(26005)(36860700001)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Feb 2022 03:44:52.2003 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 4d15b009-6fda-4c4f-4752-08d9f4235a3b X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[12.22.5.238]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-CrossTenant-AuthSource: BN8NAM11FT036.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR12MB3963 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 testpmd support for the rte_flow_pattern_template and rte_flow_actions_template APIs. Provide the command line interface for the template creation/destruction. Usage example: testpmd> flow pattern_template 0 create pattern_template_id 2 template eth dst is 00:16:3e:31:15:c3 / end testpmd> flow actions_template 0 create actions_template_id 4 template drop / end mask drop / end testpmd> flow actions_template 0 destroy actions_template 4 testpmd> flow pattern_template 0 destroy pattern_template 2 Signed-off-by: Alexander Kozyrev Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 456 +++++++++++++++++++- app/test-pmd/config.c | 203 +++++++++ app/test-pmd/testpmd.h | 24 ++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 101 +++++ 4 files changed, 782 insertions(+), 2 deletions(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 0533a33ca2..1aa32ea217 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -56,6 +56,8 @@ enum index { COMMON_POLICY_ID, COMMON_FLEX_HANDLE, COMMON_FLEX_TOKEN, + COMMON_PATTERN_TEMPLATE_ID, + COMMON_ACTIONS_TEMPLATE_ID, /* TOP-level command. */ ADD, @@ -74,6 +76,8 @@ enum index { /* Sub-level commands. */ INFO, CONFIGURE, + PATTERN_TEMPLATE, + ACTIONS_TEMPLATE, INDIRECT_ACTION, VALIDATE, CREATE, @@ -92,6 +96,28 @@ enum index { FLEX_ITEM_CREATE, FLEX_ITEM_DESTROY, + /* Pattern template arguments. */ + PATTERN_TEMPLATE_CREATE, + PATTERN_TEMPLATE_DESTROY, + PATTERN_TEMPLATE_CREATE_ID, + PATTERN_TEMPLATE_DESTROY_ID, + PATTERN_TEMPLATE_RELAXED_MATCHING, + PATTERN_TEMPLATE_INGRESS, + PATTERN_TEMPLATE_EGRESS, + PATTERN_TEMPLATE_TRANSFER, + PATTERN_TEMPLATE_SPEC, + + /* Actions template arguments. */ + ACTIONS_TEMPLATE_CREATE, + ACTIONS_TEMPLATE_DESTROY, + ACTIONS_TEMPLATE_CREATE_ID, + ACTIONS_TEMPLATE_DESTROY_ID, + ACTIONS_TEMPLATE_INGRESS, + ACTIONS_TEMPLATE_EGRESS, + ACTIONS_TEMPLATE_TRANSFER, + ACTIONS_TEMPLATE_SPEC, + ACTIONS_TEMPLATE_MASK, + /* Tunnel arguments. */ TUNNEL_CREATE, TUNNEL_CREATE_TYPE, @@ -882,6 +908,10 @@ struct buffer { uint32_t nb_queue; struct rte_flow_queue_attr queue_attr; } configure; /**< Configuration arguments. */ + struct { + uint32_t *template_id; + uint32_t template_id_n; + } templ_destroy; /**< Template destroy arguments. */ struct { uint32_t *action_id; uint32_t action_id_n; @@ -890,10 +920,13 @@ struct buffer { uint32_t action_id; } ia; /* Indirect action query arguments */ struct { + uint32_t pat_templ_id; + uint32_t act_templ_id; struct rte_flow_attr attr; struct tunnel_ops tunnel_ops; struct rte_flow_item *pattern; struct rte_flow_action *actions; + struct rte_flow_action *masks; uint32_t pattern_n; uint32_t actions_n; uint8_t *data; @@ -973,6 +1006,49 @@ static const enum index next_config_attr[] = { ZERO, }; +static const enum index next_pt_subcmd[] = { + PATTERN_TEMPLATE_CREATE, + PATTERN_TEMPLATE_DESTROY, + ZERO, +}; + +static const enum index next_pt_attr[] = { + PATTERN_TEMPLATE_CREATE_ID, + PATTERN_TEMPLATE_RELAXED_MATCHING, + PATTERN_TEMPLATE_INGRESS, + PATTERN_TEMPLATE_EGRESS, + PATTERN_TEMPLATE_TRANSFER, + PATTERN_TEMPLATE_SPEC, + ZERO, +}; + +static const enum index next_pt_destroy_attr[] = { + PATTERN_TEMPLATE_DESTROY_ID, + END, + ZERO, +}; + +static const enum index next_at_subcmd[] = { + ACTIONS_TEMPLATE_CREATE, + ACTIONS_TEMPLATE_DESTROY, + ZERO, +}; + +static const enum index next_at_attr[] = { + ACTIONS_TEMPLATE_CREATE_ID, + ACTIONS_TEMPLATE_INGRESS, + ACTIONS_TEMPLATE_EGRESS, + ACTIONS_TEMPLATE_TRANSFER, + ACTIONS_TEMPLATE_SPEC, + ZERO, +}; + +static const enum index next_at_destroy_attr[] = { + ACTIONS_TEMPLATE_DESTROY_ID, + END, + ZERO, +}; + static const enum index next_ia_create_attr[] = { INDIRECT_ACTION_CREATE_ID, INDIRECT_ACTION_INGRESS, @@ -2072,6 +2148,12 @@ static int parse_isolate(struct context *, const struct token *, static int parse_configure(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_template(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); +static int parse_template_destroy(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_tunnel(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -2141,6 +2223,10 @@ static int comp_set_modify_field_op(struct context *, const struct token *, unsigned int, char *, unsigned int); static int comp_set_modify_field_id(struct context *, const struct token *, unsigned int, char *, unsigned int); +static int comp_pattern_template_id(struct context *, const struct token *, + unsigned int, char *, unsigned int); +static int comp_actions_template_id(struct context *, const struct token *, + unsigned int, char *, unsigned int); /** Token definitions. */ static const struct token token_list[] = { @@ -2291,6 +2377,20 @@ static const struct token token_list[] = { .call = parse_flex_handle, .comp = comp_none, }, + [COMMON_PATTERN_TEMPLATE_ID] = { + .name = "{pattern_template_id}", + .type = "PATTERN_TEMPLATE_ID", + .help = "pattern template id", + .call = parse_int, + .comp = comp_pattern_template_id, + }, + [COMMON_ACTIONS_TEMPLATE_ID] = { + .name = "{actions_template_id}", + .type = "ACTIONS_TEMPLATE_ID", + .help = "actions template id", + .call = parse_int, + .comp = comp_actions_template_id, + }, /* Top-level command. */ [FLOW] = { .name = "flow", @@ -2299,6 +2399,8 @@ static const struct token token_list[] = { .next = NEXT(NEXT_ENTRY (INFO, CONFIGURE, + PATTERN_TEMPLATE, + ACTIONS_TEMPLATE, INDIRECT_ACTION, VALIDATE, CREATE, @@ -2373,6 +2475,148 @@ static const struct token token_list[] = { args.configure.port_attr.nb_meters)), }, /* Top-level command. */ + [PATTERN_TEMPLATE] = { + .name = "pattern_template", + .type = "{command} {port_id} [{arg} [...]]", + .help = "manage pattern templates", + .next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_template, + }, + /* Sub-level commands. */ + [PATTERN_TEMPLATE_CREATE] = { + .name = "create", + .help = "create pattern template", + .next = NEXT(next_pt_attr), + .call = parse_template, + }, + [PATTERN_TEMPLATE_DESTROY] = { + .name = "destroy", + .help = "destroy pattern template", + .next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_template_destroy, + }, + /* Pattern template arguments. */ + [PATTERN_TEMPLATE_CREATE_ID] = { + .name = "pattern_template_id", + .help = "specify a pattern template id to create", + .next = NEXT(next_pt_attr, + NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)), + }, + [PATTERN_TEMPLATE_DESTROY_ID] = { + .name = "pattern_template", + .help = "specify a pattern template id to destroy", + .next = NEXT(next_pt_destroy_attr, + NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)), + .args = ARGS(ARGS_ENTRY_PTR(struct buffer, + args.templ_destroy.template_id)), + .call = parse_template_destroy, + }, + [PATTERN_TEMPLATE_RELAXED_MATCHING] = { + .name = "relaxed", + .help = "is matching relaxed", + .next = NEXT(next_pt_attr, + NEXT_ENTRY(COMMON_BOOLEAN)), + .args = ARGS(ARGS_ENTRY_BF(struct buffer, + args.vc.attr.reserved, 1)), + }, + [PATTERN_TEMPLATE_INGRESS] = { + .name = "ingress", + .help = "attribute pattern to ingress", + .next = NEXT(next_pt_attr), + .call = parse_template, + }, + [PATTERN_TEMPLATE_EGRESS] = { + .name = "egress", + .help = "attribute pattern to egress", + .next = NEXT(next_pt_attr), + .call = parse_template, + }, + [PATTERN_TEMPLATE_TRANSFER] = { + .name = "transfer", + .help = "attribute pattern to transfer", + .next = NEXT(next_pt_attr), + .call = parse_template, + }, + [PATTERN_TEMPLATE_SPEC] = { + .name = "template", + .help = "specify item to create pattern template", + .next = NEXT(next_item), + }, + /* Top-level command. */ + [ACTIONS_TEMPLATE] = { + .name = "actions_template", + .type = "{command} {port_id} [{arg} [...]]", + .help = "manage actions templates", + .next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_template, + }, + /* Sub-level commands. */ + [ACTIONS_TEMPLATE_CREATE] = { + .name = "create", + .help = "create actions template", + .next = NEXT(next_at_attr), + .call = parse_template, + }, + [ACTIONS_TEMPLATE_DESTROY] = { + .name = "destroy", + .help = "destroy actions template", + .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_template_destroy, + }, + /* Actions template arguments. */ + [ACTIONS_TEMPLATE_CREATE_ID] = { + .name = "actions_template_id", + .help = "specify an actions template id to create", + .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK), + NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC), + NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)), + }, + [ACTIONS_TEMPLATE_DESTROY_ID] = { + .name = "actions_template", + .help = "specify an actions template id to destroy", + .next = NEXT(next_at_destroy_attr, + NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)), + .args = ARGS(ARGS_ENTRY_PTR(struct buffer, + args.templ_destroy.template_id)), + .call = parse_template_destroy, + }, + [ACTIONS_TEMPLATE_INGRESS] = { + .name = "ingress", + .help = "attribute actions to ingress", + .next = NEXT(next_at_attr), + .call = parse_template, + }, + [ACTIONS_TEMPLATE_EGRESS] = { + .name = "egress", + .help = "attribute actions to egress", + .next = NEXT(next_at_attr), + .call = parse_template, + }, + [ACTIONS_TEMPLATE_TRANSFER] = { + .name = "transfer", + .help = "attribute actions to transfer", + .next = NEXT(next_at_attr), + .call = parse_template, + }, + [ACTIONS_TEMPLATE_SPEC] = { + .name = "template", + .help = "specify action to create actions template", + .next = NEXT(next_action), + .call = parse_template, + }, + [ACTIONS_TEMPLATE_MASK] = { + .name = "mask", + .help = "specify action mask to create actions template", + .next = NEXT(next_action), + .call = parse_template, + }, + /* Top-level command. */ [INDIRECT_ACTION] = { .name = "indirect_action", .type = "{command} {port_id} [{arg} [...]]", @@ -2695,7 +2939,7 @@ static const struct token token_list[] = { .name = "end", .help = "end list of pattern items", .priv = PRIV_ITEM(END, 0), - .next = NEXT(NEXT_ENTRY(ACTIONS)), + .next = NEXT(NEXT_ENTRY(ACTIONS, END)), .call = parse_vc, }, [ITEM_VOID] = { @@ -5975,7 +6219,9 @@ parse_vc(struct context *ctx, const struct token *token, if (!out) return len; if (!out->command) { - if (ctx->curr != VALIDATE && ctx->curr != CREATE) + if (ctx->curr != VALIDATE && ctx->curr != CREATE && + ctx->curr != PATTERN_TEMPLATE_CREATE && + ctx->curr != ACTIONS_TEMPLATE_CREATE) return -1; if (sizeof(*out) > size) return -1; @@ -7851,6 +8097,132 @@ parse_configure(struct context *ctx, const struct token *token, return len; } +/** Parse tokens for template create command. */ +static int +parse_template(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command) { + if (ctx->curr != PATTERN_TEMPLATE && + ctx->curr != ACTIONS_TEMPLATE) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + out->args.vc.data = (uint8_t *)out + size; + return len; + } + switch (ctx->curr) { + case PATTERN_TEMPLATE_CREATE: + out->args.vc.pattern = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + out->args.vc.pat_templ_id = UINT32_MAX; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + return len; + case PATTERN_TEMPLATE_EGRESS: + out->args.vc.attr.egress = 1; + return len; + case PATTERN_TEMPLATE_INGRESS: + out->args.vc.attr.ingress = 1; + return len; + case PATTERN_TEMPLATE_TRANSFER: + out->args.vc.attr.transfer = 1; + return len; + case ACTIONS_TEMPLATE_CREATE: + out->args.vc.act_templ_id = UINT32_MAX; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + return len; + case ACTIONS_TEMPLATE_SPEC: + out->args.vc.actions = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + ctx->object = out->args.vc.actions; + ctx->objmask = NULL; + return len; + case ACTIONS_TEMPLATE_MASK: + out->args.vc.masks = + (void *)RTE_ALIGN_CEIL((uintptr_t) + (out->args.vc.actions + + out->args.vc.actions_n), + sizeof(double)); + ctx->object = out->args.vc.masks; + ctx->objmask = NULL; + return len; + case ACTIONS_TEMPLATE_EGRESS: + out->args.vc.attr.egress = 1; + return len; + case ACTIONS_TEMPLATE_INGRESS: + out->args.vc.attr.ingress = 1; + return len; + case ACTIONS_TEMPLATE_TRANSFER: + out->args.vc.attr.transfer = 1; + return len; + default: + return -1; + } +} + +/** Parse tokens for template destroy command. */ +static int +parse_template_destroy(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + uint32_t *template_id; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command || + out->command == PATTERN_TEMPLATE || + out->command == ACTIONS_TEMPLATE) { + if (ctx->curr != PATTERN_TEMPLATE_DESTROY && + ctx->curr != ACTIONS_TEMPLATE_DESTROY) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + out->args.templ_destroy.template_id = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + return len; + } + template_id = out->args.templ_destroy.template_id + + out->args.templ_destroy.template_id_n++; + if ((uint8_t *)template_id > (uint8_t *)out + size) + return -1; + ctx->objdata = 0; + ctx->object = template_id; + ctx->objmask = NULL; + return len; +} + static int parse_flex(struct context *ctx, const struct token *token, const char *str, unsigned int len, @@ -8820,6 +9192,54 @@ comp_set_modify_field_id(struct context *ctx, const struct token *token, return -1; } +/** Complete available pattern template IDs. */ +static int +comp_pattern_template_id(struct context *ctx, const struct token *token, + unsigned int ent, char *buf, unsigned int size) +{ + unsigned int i = 0; + struct rte_port *port; + struct port_template *pt; + + (void)token; + if (port_id_is_invalid(ctx->port, DISABLED_WARN) || + ctx->port == (portid_t)RTE_PORT_ALL) + return -1; + port = &ports[ctx->port]; + for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) { + if (buf && i == ent) + return snprintf(buf, size, "%u", pt->id); + ++i; + } + if (buf) + return -1; + return i; +} + +/** Complete available actions template IDs. */ +static int +comp_actions_template_id(struct context *ctx, const struct token *token, + unsigned int ent, char *buf, unsigned int size) +{ + unsigned int i = 0; + struct rte_port *port; + struct port_template *pt; + + (void)token; + if (port_id_is_invalid(ctx->port, DISABLED_WARN) || + ctx->port == (portid_t)RTE_PORT_ALL) + return -1; + port = &ports[ctx->port]; + for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) { + if (buf && i == ent) + return snprintf(buf, size, "%u", pt->id); + ++i; + } + if (buf) + return -1; + return i; +} + /** Internal context. */ static struct context cmd_flow_context; @@ -9088,6 +9508,38 @@ cmd_flow_parsed(const struct buffer *in) in->args.configure.nb_queue, &in->args.configure.queue_attr); break; + case PATTERN_TEMPLATE_CREATE: + port_flow_pattern_template_create(in->port, + in->args.vc.pat_templ_id, + &((const struct rte_flow_pattern_template_attr) { + .relaxed_matching = in->args.vc.attr.reserved, + .ingress = in->args.vc.attr.ingress, + .egress = in->args.vc.attr.egress, + .transfer = in->args.vc.attr.transfer, + }), + in->args.vc.pattern); + break; + case PATTERN_TEMPLATE_DESTROY: + port_flow_pattern_template_destroy(in->port, + in->args.templ_destroy.template_id_n, + in->args.templ_destroy.template_id); + break; + case ACTIONS_TEMPLATE_CREATE: + port_flow_actions_template_create(in->port, + in->args.vc.act_templ_id, + &((const struct rte_flow_actions_template_attr) { + .ingress = in->args.vc.attr.ingress, + .egress = in->args.vc.attr.egress, + .transfer = in->args.vc.attr.transfer, + }), + in->args.vc.actions, + in->args.vc.masks); + break; + case ACTIONS_TEMPLATE_DESTROY: + port_flow_actions_template_destroy(in->port, + in->args.templ_destroy.template_id_n, + in->args.templ_destroy.template_id); + break; case INDIRECT_ACTION_CREATE: port_action_handle_create( in->port, in->args.vc.attr.group, diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index 33a85cd7ca..ecaf4ca03c 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -1610,6 +1610,49 @@ action_alloc(portid_t port_id, uint32_t id, return 0; } +static int +template_alloc(uint32_t id, struct port_template **template, + struct port_template **list) +{ + struct port_template *lst = *list; + struct port_template **ppt; + struct port_template *pt = NULL; + + *template = NULL; + if (id == UINT32_MAX) { + /* taking first available ID */ + if (lst) { + if (lst->id == UINT32_MAX - 1) { + printf("Highest template ID is already" + " assigned, delete it first\n"); + return -ENOMEM; + } + id = lst->id + 1; + } else { + id = 0; + } + } + pt = calloc(1, sizeof(*pt)); + if (!pt) { + printf("Allocation of port template failed\n"); + return -ENOMEM; + } + ppt = list; + while (*ppt && (*ppt)->id > id) + ppt = &(*ppt)->next; + if (*ppt && (*ppt)->id == id) { + printf("Template #%u is already assigned," + " delete it first\n", id); + free(pt); + return -EINVAL; + } + pt->next = *ppt; + pt->id = id; + *ppt = pt; + *template = pt; + return 0; +} + /** Get info about flow management resources. */ int port_flow_get_info(portid_t port_id) @@ -2086,6 +2129,166 @@ age_action_get(const struct rte_flow_action *actions) return NULL; } +/** Create pattern template */ +int +port_flow_pattern_template_create(portid_t port_id, uint32_t id, + const struct rte_flow_pattern_template_attr *attr, + const struct rte_flow_item *pattern) +{ + struct rte_port *port; + struct port_template *pit; + int ret; + struct rte_flow_error error; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + ret = template_alloc(id, &pit, &port->pattern_templ_list); + if (ret) + return ret; + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x22, sizeof(error)); + pit->template.pattern_template = rte_flow_pattern_template_create(port_id, + attr, pattern, &error); + if (!pit->template.pattern_template) { + uint32_t destroy_id = pit->id; + port_flow_pattern_template_destroy(port_id, 1, &destroy_id); + return port_flow_complain(&error); + } + printf("Pattern template #%u created\n", pit->id); + return 0; +} + +/** Destroy pattern template */ +int +port_flow_pattern_template_destroy(portid_t port_id, uint32_t n, + const uint32_t *template) +{ + struct rte_port *port; + struct port_template **tmp; + uint32_t c = 0; + int ret = 0; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + tmp = &port->pattern_templ_list; + while (*tmp) { + uint32_t i; + + for (i = 0; i != n; ++i) { + struct rte_flow_error error; + struct port_template *pit = *tmp; + + if (template[i] != pit->id) + continue; + /* + * Poisoning to make sure PMDs update it in case + * of error. + */ + memset(&error, 0x33, sizeof(error)); + + if (pit->template.pattern_template && + rte_flow_pattern_template_destroy(port_id, + pit->template.pattern_template, + &error)) { + ret = port_flow_complain(&error); + continue; + } + *tmp = pit->next; + printf("Pattern template #%u destroyed\n", pit->id); + free(pit); + break; + } + if (i == n) + tmp = &(*tmp)->next; + ++c; + } + return ret; +} + +/** Create actions template */ +int +port_flow_actions_template_create(portid_t port_id, uint32_t id, + const struct rte_flow_actions_template_attr *attr, + const struct rte_flow_action *actions, + const struct rte_flow_action *masks) +{ + struct rte_port *port; + struct port_template *pat; + int ret; + struct rte_flow_error error; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + ret = template_alloc(id, &pat, &port->actions_templ_list); + if (ret) + return ret; + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x22, sizeof(error)); + pat->template.actions_template = rte_flow_actions_template_create(port_id, + attr, actions, masks, &error); + if (!pat->template.actions_template) { + uint32_t destroy_id = pat->id; + port_flow_actions_template_destroy(port_id, 1, &destroy_id); + return port_flow_complain(&error); + } + printf("Actions template #%u created\n", pat->id); + return 0; +} + +/** Destroy actions template */ +int +port_flow_actions_template_destroy(portid_t port_id, uint32_t n, + const uint32_t *template) +{ + struct rte_port *port; + struct port_template **tmp; + uint32_t c = 0; + int ret = 0; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + tmp = &port->actions_templ_list; + while (*tmp) { + uint32_t i; + + for (i = 0; i != n; ++i) { + struct rte_flow_error error; + struct port_template *pat = *tmp; + + if (template[i] != pat->id) + continue; + /* + * Poisoning to make sure PMDs update it in case + * of error. + */ + memset(&error, 0x33, sizeof(error)); + + if (pat->template.actions_template && + rte_flow_actions_template_destroy(port_id, + pat->template.actions_template, &error)) { + ret = port_flow_complain(&error); + continue; + } + *tmp = pat->next; + printf("Actions template #%u destroyed\n", pat->id); + free(pat); + break; + } + if (i == n) + tmp = &(*tmp)->next; + ++c; + } + return ret; +} + /** Create flow rule. */ int port_flow_create(portid_t port_id, diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 096b6825eb..ce46d754a1 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -166,6 +166,17 @@ enum age_action_context_type { ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION, }; +/** Descriptor for a template. */ +struct port_template { + struct port_template *next; /**< Next template in list. */ + struct port_template *tmp; /**< Temporary linking. */ + uint32_t id; /**< Template ID. */ + union { + struct rte_flow_pattern_template *pattern_template; + struct rte_flow_actions_template *actions_template; + } template; /**< PMD opaque template object */ +}; + /** Descriptor for a single flow. */ struct port_flow { struct port_flow *next; /**< Next flow in list. */ @@ -246,6 +257,8 @@ struct rte_port { queueid_t queue_nb; /**< nb. of queues for flow rules */ uint32_t queue_sz; /**< size of a queue for flow rules */ uint8_t slave_flag; /**< bonding slave port */ + struct port_template *pattern_templ_list; /**< Pattern templates. */ + struct port_template *actions_templ_list; /**< Actions templates. */ struct port_flow *flow_list; /**< Associated flows. */ struct port_indirect_action *actions_list; /**< Associated indirect actions. */ @@ -892,6 +905,17 @@ int port_flow_configure(portid_t port_id, const struct rte_flow_port_attr *port_attr, uint16_t nb_queue, const struct rte_flow_queue_attr *queue_attr); +int port_flow_pattern_template_create(portid_t port_id, uint32_t id, + const struct rte_flow_pattern_template_attr *attr, + const struct rte_flow_item *pattern); +int port_flow_pattern_template_destroy(portid_t port_id, uint32_t n, + const uint32_t *template); +int port_flow_actions_template_create(portid_t port_id, uint32_t id, + const struct rte_flow_actions_template_attr *attr, + const struct rte_flow_action *actions, + const struct rte_flow_action *masks); +int port_flow_actions_template_destroy(portid_t port_id, uint32_t n, + const uint32_t *template); int port_flow_validate(portid_t port_id, const struct rte_flow_attr *attr, const struct rte_flow_item *pattern, diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index c8f048aeef..2e6a23b12a 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -3344,6 +3344,26 @@ following sections. [aging_counters_number {number}] [meters_number {number}] +- Create a pattern template:: + flow pattern_template {port_id} create [pattern_template_id {id}] + [relaxed {boolean}] [ingress] [egress] [transfer] + template {item} [/ {item} [...]] / end + +- Destroy a pattern template:: + + flow pattern_template {port_id} destroy pattern_template {id} [...] + +- Create an actions template:: + + flow actions_template {port_id} create [actions_template_id {id}] + [ingress] [egress] [transfer] + template {action} [/ {action} [...]] / end + mask {action} [/ {action} [...]] / end + +- Destroy an actions template:: + + flow actions_template {port_id} destroy actions_template {id} [...] + - Check whether a flow rule can be created:: flow validate {port_id} @@ -3448,6 +3468,87 @@ Otherwise it will show an error message of the form:: Caught error type [...] ([...]): [...] +Creating pattern templates +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow pattern_template create`` creates the specified pattern template. +It is bound to ``rte_flow_pattern_template_create()``:: + + flow pattern_template {port_id} create [pattern_template_id {id}] + [relaxed {boolean}] [ingress] [egress] [transfer] + template {item} [/ {item} [...]] / end + +If successful, it will show:: + + Pattern template #[...] created + +Otherwise it will show an error message of the form:: + + Caught error type [...] ([...]): [...] + +This command uses the same pattern items as ``flow create``, +their format is described in `Creating flow rules`_. + +Destroying pattern templates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow pattern_template destroy`` destroys one or more pattern templates +from their template ID (as returned by ``flow pattern_template create``), +this command calls ``rte_flow_pattern_template_destroy()`` as many +times as necessary:: + + flow pattern_template {port_id} destroy pattern_template {id} [...] + +If successful, it will show:: + + Pattern template #[...] destroyed + +It does not report anything for pattern template IDs that do not exist. +The usual error message is shown when a pattern template cannot be destroyed:: + + Caught error type [...] ([...]): [...] + +Creating actions templates +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow actions_template create`` creates the specified actions template. +It is bound to ``rte_flow_actions_template_create()``:: + + flow actions_template {port_id} create [actions_template_id {id}] + [ingress] [egress] [transfer] + template {action} [/ {action} [...]] / end + mask {action} [/ {action} [...]] / end + +If successful, it will show:: + + Actions template #[...] created + +Otherwise it will show an error message of the form:: + + Caught error type [...] ([...]): [...] + +This command uses the same actions as ``flow create``, +their format is described in `Creating flow rules`_. + +Destroying actions templates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow actions_template destroy`` destroys one or more actions templates +from their template ID (as returned by ``flow actions_template create``), +this command calls ``rte_flow_actions_template_destroy()`` as many +times as necessary:: + + flow actions_template {port_id} destroy actions_template {id} [...] + +If successful, it will show:: + + Actions template #[...] destroyed + +It does not report anything for actions template IDs that do not exist. +The usual error message is shown when an actions template cannot be destroyed:: + + Caught error type [...] ([...]): [...] + Creating a tunnel stub for offload ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From patchwork Sun Feb 20 03:44:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kozyrev X-Patchwork-Id: 107863 X-Patchwork-Delegate: ferruh.yigit@amd.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 362BCA00C2; Sun, 20 Feb 2022 04:45:20 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0550141154; Sun, 20 Feb 2022 04:45:01 +0100 (CET) Received: from NAM02-SN1-obe.outbound.protection.outlook.com (mail-sn1anam02on2075.outbound.protection.outlook.com [40.107.96.75]) by mails.dpdk.org (Postfix) with ESMTP id 465BF41150 for ; Sun, 20 Feb 2022 04:44:59 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ULkZOPGa/iFcf+woxeaUrXs6xb6VDbbAdhadKaw59SVw9kdTLTqRn8EmuksEEnf1XYKaZN3+PgFAi5mK7eJll8p8Q45HeDb+M+RWBxmrsT6gVp0gEUNr9qcRB2XV2Fsjz+W98ccgDaKpA4zhXfhJUHmG5azRNHapm9364DUouOGC2mWRdDKilkoUO9hoGUern6t6YwUz0Ancw8mZOgaqAEJRvivNEuBmzMSIR2KYYavVAD51P2TMHy43tLd4HbY6rXWdcpdF12vvwpodGh6QZparzCGVW20sbRafes1tBEcBBkRnusa9FeO4pQcR/tKioufVS12B5zRWOerVxHTqHQ== 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=zW3wex6mxImQf5L4fQm+N3DnWBnNS1kocEVO8gZ1Weo=; b=axEdRn2EfPNX8q5z3AsncL9R22MjFwM37lD3Ob2JhnBSftFwzd7lnPngAAgePVGJfnR5noG0UVLDiBUfcmx4zPni6TOxOZc5jEIbKupRd5rPjMZthd34zxBdzODi/PKilE0C5j+y1Nc/AUv9V/GtURO/+cknhAg8d6HKCaEyPg5kt+UUMAGf2zorw3ZNiwsw8CxWDQFrLZOwh8k/lwZaMW/EqGPO77ukFs/FyKXgtbX5/Pwmt/D6djRT7wgKAltGVGNrpwVsFHNttD7Z1wsH7mDmHHxq6Sn0hYw7htDjOCihUk4bryye/RL8m/XOjfZJDu80D6qbOd4U+wnm9LNNrw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 12.22.5.234) smtp.rcpttodomain=intel.com 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 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=zW3wex6mxImQf5L4fQm+N3DnWBnNS1kocEVO8gZ1Weo=; b=AkVoNhw5fTwkIvyr8/nqX7n30OShygU9RwFDfalrKxF84NajeLr787AO4tXDEc0UOCZA2oOuUBi7dObuOIthlFBskR0JXGt9yUQoRadp6zu0GNlP6qhrd/6UPDN5H4x88CXAWA2qzWu7sYbcNBQLLzMEob0zZPKcnD3zpjm1MGZVgRC6/5tMMdFU/DoQ7Ts3LoPxPSuBM2Z6hLCd4h2x9r/rpeFwNqRDDMgC5gP0jIceDlYkMHc0e6qwgq9x8IvH3P47PzpcoZ4eDR44p9sN79n5mwLWL0jq30RyoSjxjz1EsvVDBaidWWIaXkrGFw459kp11RosrHG/fGzpY3RZ4Q== Received: from CY4PR12MB1192.namprd12.prod.outlook.com (2603:10b6:903:40::11) by SJ0PR12MB5421.namprd12.prod.outlook.com (2603:10b6:a03:3bb::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.14; Sun, 20 Feb 2022 03:44:56 +0000 Received: from BN9PR03CA0544.namprd03.prod.outlook.com (2603:10b6:408:138::9) by CY4PR12MB1192.namprd12.prod.outlook.com (2603:10b6:903:40::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.16; Sun, 20 Feb 2022 03:44:54 +0000 Received: from BN8NAM11FT004.eop-nam11.prod.protection.outlook.com (2603:10b6:408:138:cafe::87) by BN9PR03CA0544.outlook.office365.com (2603:10b6:408:138::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.14 via Frontend Transport; Sun, 20 Feb 2022 03:44:54 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 12.22.5.234) 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 12.22.5.234 as permitted sender) receiver=protection.outlook.com; client-ip=12.22.5.234; helo=mail.nvidia.com; Received: from mail.nvidia.com (12.22.5.234) by BN8NAM11FT004.mail.protection.outlook.com (10.13.176.164) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4995.15 via Frontend Transport; Sun, 20 Feb 2022 03:44:53 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by DRHQMAIL101.nvidia.com (10.27.9.10) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Sun, 20 Feb 2022 03:44:52 +0000 Received: from pegasus01.mtr.labs.mlnx (10.126.230.35) 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.9; Sat, 19 Feb 2022 19:44:49 -0800 From: Alexander Kozyrev To: CC: , , , , , , , , , Subject: [PATCH v8 07/11] app/testpmd: add flow table management Date: Sun, 20 Feb 2022 05:44:05 +0200 Message-ID: <20220220034409.2226860-8-akozyrev@nvidia.com> X-Mailer: git-send-email 2.18.2 In-Reply-To: <20220220034409.2226860-1-akozyrev@nvidia.com> References: <20220219041144.2145380-1-akozyrev@nvidia.com> <20220220034409.2226860-1-akozyrev@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.126.230.35] X-ClientProxiedBy: rnnvmail202.nvidia.com (10.129.68.7) To rnnvmail201.nvidia.com (10.129.68.8) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 0c3aff7a-4b01-4b62-561b-08d9f4235b15 X-MS-TrafficTypeDiagnostic: CY4PR12MB1192:EE_|SJ0PR12MB5421:EE_ X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr,ExtAddr X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 4+hJAV8DkaHkxk75QlaFpWM8Ry7UTfyNkpwB+XwukxqpkL9P9/3c2j3FXiApnkwKtqYXP4OqIhq/WY8f6CXoLpvdaWDxoq+9Cxd/JEvjgUJrDqeLUumbvnfX+HHnkYUl6hfgFWmTdOQsgFDH733aOgw2jpJok4kU1Zwiu8crsgIhOqmxudiHoXTbkYcheFDbMWGk1+BEcMFKAfXBiq8z51GBk/UMnqqVtr91Xh6k7ZrWzI0c/p1lBAkXpz/lAwTo/6FB14iDqpKqB21vlb8v2EBXwyvP6jolneoDNt1HHS/HOG254wdBsIxSnbl7IdFL2R26FhfuZyLtsgFtNkBGsJecJiG8SNsqS1lJnyt4wKxw5PmmlyyK0ECDx9+IBn537eKnxGX9BXcURulwPT9GOFpIXGdePcxJy5et/AebhyzAWtk/nJK0jHTmIk1MYsJMSJ7aT03IwzwU1OQL7H9Kyn2VoFNj/SpM1rDhaXziIbpbVFPKMt1PGhUXE5Qz8XHU9VBaen+XmxqSwUMvAye2Xv3Obt3fk87IQBVAiJTL8YS/EwcY1sLYf06U10BJ204cwur1TmWToYO31xUMTvT4ftT6GYOtutFHYTSWDzsz18IK9e96c8xJ/n6xGZeTiATbV8qMWMJ71/zZEQHgVUPJBOc+IM1OLUSsTQxdznR4hIrGu0HjHocIvhOiuMsnkBey58Bx5rvtRFfWk6Pl0cPSbQ== X-Forefront-Antispam-Report: CIP:12.22.5.234; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:mail.nvidia.com; PTR:InfoNoRecords; CAT:NONE; SFS:(13230001)(4636009)(36840700001)(46966006)(40470700004)(6666004)(8676002)(4326008)(70586007)(70206006)(82310400004)(508600001)(316002)(86362001)(6916009)(54906003)(83380400001)(36860700001)(2906002)(40460700003)(47076005)(2616005)(356005)(1076003)(81166007)(426003)(336012)(16526019)(186003)(26005)(5660300002)(8936002)(36756003)(30864003)(7416002)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Feb 2022 03:44:53.6449 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 0c3aff7a-4b01-4b62-561b-08d9f4235b15 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[12.22.5.234]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-CrossTenant-AuthSource: BN8NAM11FT004.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR12MB5421 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 testpmd support for the rte_flow_table API. Provide the command line interface for the flow table creation/destruction. Usage example: testpmd> flow template_table 0 create table_id 6 group 9 priority 4 ingress mode 1 rules_number 64 pattern_template 2 actions_template 4 testpmd> flow template_table 0 destroy table 6 Signed-off-by: Alexander Kozyrev Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 315 ++++++++++++++++++++ app/test-pmd/config.c | 171 +++++++++++ app/test-pmd/testpmd.h | 17 ++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 53 ++++ 4 files changed, 556 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 1aa32ea217..5715899c95 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -58,6 +58,7 @@ enum index { COMMON_FLEX_TOKEN, COMMON_PATTERN_TEMPLATE_ID, COMMON_ACTIONS_TEMPLATE_ID, + COMMON_TABLE_ID, /* TOP-level command. */ ADD, @@ -78,6 +79,7 @@ enum index { CONFIGURE, PATTERN_TEMPLATE, ACTIONS_TEMPLATE, + TABLE, INDIRECT_ACTION, VALIDATE, CREATE, @@ -118,6 +120,20 @@ enum index { ACTIONS_TEMPLATE_SPEC, ACTIONS_TEMPLATE_MASK, + /* Table arguments. */ + TABLE_CREATE, + TABLE_DESTROY, + TABLE_CREATE_ID, + TABLE_DESTROY_ID, + TABLE_GROUP, + TABLE_PRIORITY, + TABLE_INGRESS, + TABLE_EGRESS, + TABLE_TRANSFER, + TABLE_RULES_NUMBER, + TABLE_PATTERN_TEMPLATE, + TABLE_ACTIONS_TEMPLATE, + /* Tunnel arguments. */ TUNNEL_CREATE, TUNNEL_CREATE_TYPE, @@ -912,6 +928,18 @@ struct buffer { uint32_t *template_id; uint32_t template_id_n; } templ_destroy; /**< Template destroy arguments. */ + struct { + uint32_t id; + struct rte_flow_template_table_attr attr; + uint32_t *pat_templ_id; + uint32_t pat_templ_id_n; + uint32_t *act_templ_id; + uint32_t act_templ_id_n; + } table; /**< Table arguments. */ + struct { + uint32_t *table_id; + uint32_t table_id_n; + } table_destroy; /**< Template destroy arguments. */ struct { uint32_t *action_id; uint32_t action_id_n; @@ -1049,6 +1077,32 @@ static const enum index next_at_destroy_attr[] = { ZERO, }; +static const enum index next_table_subcmd[] = { + TABLE_CREATE, + TABLE_DESTROY, + ZERO, +}; + +static const enum index next_table_attr[] = { + TABLE_CREATE_ID, + TABLE_GROUP, + TABLE_PRIORITY, + TABLE_INGRESS, + TABLE_EGRESS, + TABLE_TRANSFER, + TABLE_RULES_NUMBER, + TABLE_PATTERN_TEMPLATE, + TABLE_ACTIONS_TEMPLATE, + END, + ZERO, +}; + +static const enum index next_table_destroy_attr[] = { + TABLE_DESTROY_ID, + END, + ZERO, +}; + static const enum index next_ia_create_attr[] = { INDIRECT_ACTION_CREATE_ID, INDIRECT_ACTION_INGRESS, @@ -2154,6 +2208,11 @@ static int parse_template(struct context *, const struct token *, static int parse_template_destroy(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_table(struct context *, const struct token *, + const char *, unsigned int, void *, unsigned int); +static int parse_table_destroy(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_tunnel(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -2227,6 +2286,8 @@ static int comp_pattern_template_id(struct context *, const struct token *, unsigned int, char *, unsigned int); static int comp_actions_template_id(struct context *, const struct token *, unsigned int, char *, unsigned int); +static int comp_table_id(struct context *, const struct token *, + unsigned int, char *, unsigned int); /** Token definitions. */ static const struct token token_list[] = { @@ -2391,6 +2452,13 @@ static const struct token token_list[] = { .call = parse_int, .comp = comp_actions_template_id, }, + [COMMON_TABLE_ID] = { + .name = "{table_id}", + .type = "TABLE_ID", + .help = "table id", + .call = parse_int, + .comp = comp_table_id, + }, /* Top-level command. */ [FLOW] = { .name = "flow", @@ -2401,6 +2469,7 @@ static const struct token token_list[] = { CONFIGURE, PATTERN_TEMPLATE, ACTIONS_TEMPLATE, + TABLE, INDIRECT_ACTION, VALIDATE, CREATE, @@ -2617,6 +2686,104 @@ static const struct token token_list[] = { .call = parse_template, }, /* Top-level command. */ + [TABLE] = { + .name = "template_table", + .type = "{command} {port_id} [{arg} [...]]", + .help = "manage template tables", + .next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_table, + }, + /* Sub-level commands. */ + [TABLE_CREATE] = { + .name = "create", + .help = "create template table", + .next = NEXT(next_table_attr), + .call = parse_table, + }, + [TABLE_DESTROY] = { + .name = "destroy", + .help = "destroy template table", + .next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_table_destroy, + }, + /* Table arguments. */ + [TABLE_CREATE_ID] = { + .name = "table_id", + .help = "specify table id to create", + .next = NEXT(next_table_attr, + NEXT_ENTRY(COMMON_TABLE_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)), + }, + [TABLE_DESTROY_ID] = { + .name = "table", + .help = "specify table id to destroy", + .next = NEXT(next_table_destroy_attr, + NEXT_ENTRY(COMMON_TABLE_ID)), + .args = ARGS(ARGS_ENTRY_PTR(struct buffer, + args.table_destroy.table_id)), + .call = parse_table_destroy, + }, + [TABLE_GROUP] = { + .name = "group", + .help = "specify a group", + .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.table.attr.flow_attr.group)), + }, + [TABLE_PRIORITY] = { + .name = "priority", + .help = "specify a priority level", + .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.table.attr.flow_attr.priority)), + }, + [TABLE_EGRESS] = { + .name = "egress", + .help = "affect rule to egress", + .next = NEXT(next_table_attr), + .call = parse_table, + }, + [TABLE_INGRESS] = { + .name = "ingress", + .help = "affect rule to ingress", + .next = NEXT(next_table_attr), + .call = parse_table, + }, + [TABLE_TRANSFER] = { + .name = "transfer", + .help = "affect rule to transfer", + .next = NEXT(next_table_attr), + .call = parse_table, + }, + [TABLE_RULES_NUMBER] = { + .name = "rules_number", + .help = "number of rules in table", + .next = NEXT(next_table_attr, + NEXT_ENTRY(COMMON_UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.table.attr.nb_flows)), + }, + [TABLE_PATTERN_TEMPLATE] = { + .name = "pattern_template", + .help = "specify pattern template id", + .next = NEXT(next_table_attr, + NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)), + .args = ARGS(ARGS_ENTRY_PTR(struct buffer, + args.table.pat_templ_id)), + .call = parse_table, + }, + [TABLE_ACTIONS_TEMPLATE] = { + .name = "actions_template", + .help = "specify actions template id", + .next = NEXT(next_table_attr, + NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)), + .args = ARGS(ARGS_ENTRY_PTR(struct buffer, + args.table.act_templ_id)), + .call = parse_table, + }, + /* Top-level command. */ [INDIRECT_ACTION] = { .name = "indirect_action", .type = "{command} {port_id} [{arg} [...]]", @@ -8223,6 +8390,119 @@ parse_template_destroy(struct context *ctx, const struct token *token, return len; } +/** Parse tokens for table create command. */ +static int +parse_table(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + uint32_t *template_id; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command) { + if (ctx->curr != TABLE) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + return len; + } + switch (ctx->curr) { + case TABLE_CREATE: + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + out->args.table.id = UINT32_MAX; + return len; + case TABLE_PATTERN_TEMPLATE: + out->args.table.pat_templ_id = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + template_id = out->args.table.pat_templ_id + + out->args.table.pat_templ_id_n++; + if ((uint8_t *)template_id > (uint8_t *)out + size) + return -1; + ctx->objdata = 0; + ctx->object = template_id; + ctx->objmask = NULL; + return len; + case TABLE_ACTIONS_TEMPLATE: + out->args.table.act_templ_id = + (void *)RTE_ALIGN_CEIL((uintptr_t) + (out->args.table.pat_templ_id + + out->args.table.pat_templ_id_n), + sizeof(double)); + template_id = out->args.table.act_templ_id + + out->args.table.act_templ_id_n++; + if ((uint8_t *)template_id > (uint8_t *)out + size) + return -1; + ctx->objdata = 0; + ctx->object = template_id; + ctx->objmask = NULL; + return len; + case TABLE_INGRESS: + out->args.table.attr.flow_attr.ingress = 1; + return len; + case TABLE_EGRESS: + out->args.table.attr.flow_attr.egress = 1; + return len; + case TABLE_TRANSFER: + out->args.table.attr.flow_attr.transfer = 1; + return len; + default: + return -1; + } +} + +/** Parse tokens for table destroy command. */ +static int +parse_table_destroy(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + uint32_t *table_id; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command || out->command == TABLE) { + if (ctx->curr != TABLE_DESTROY) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + out->args.table_destroy.table_id = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + return len; + } + table_id = out->args.table_destroy.table_id + + out->args.table_destroy.table_id_n++; + if ((uint8_t *)table_id > (uint8_t *)out + size) + return -1; + ctx->objdata = 0; + ctx->object = table_id; + ctx->objmask = NULL; + return len; +} + static int parse_flex(struct context *ctx, const struct token *token, const char *str, unsigned int len, @@ -9240,6 +9520,30 @@ comp_actions_template_id(struct context *ctx, const struct token *token, return i; } +/** Complete available table IDs. */ +static int +comp_table_id(struct context *ctx, const struct token *token, + unsigned int ent, char *buf, unsigned int size) +{ + unsigned int i = 0; + struct rte_port *port; + struct port_table *pt; + + (void)token; + if (port_id_is_invalid(ctx->port, DISABLED_WARN) || + ctx->port == (portid_t)RTE_PORT_ALL) + return -1; + port = &ports[ctx->port]; + for (pt = port->table_list; pt != NULL; pt = pt->next) { + if (buf && i == ent) + return snprintf(buf, size, "%u", pt->id); + ++i; + } + if (buf) + return -1; + return i; +} + /** Internal context. */ static struct context cmd_flow_context; @@ -9540,6 +9844,17 @@ cmd_flow_parsed(const struct buffer *in) in->args.templ_destroy.template_id_n, in->args.templ_destroy.template_id); break; + case TABLE_CREATE: + port_flow_template_table_create(in->port, in->args.table.id, + &in->args.table.attr, in->args.table.pat_templ_id_n, + in->args.table.pat_templ_id, in->args.table.act_templ_id_n, + in->args.table.act_templ_id); + break; + case TABLE_DESTROY: + port_flow_template_table_destroy(in->port, + in->args.table_destroy.table_id_n, + in->args.table_destroy.table_id); + break; case INDIRECT_ACTION_CREATE: port_action_handle_create( in->port, in->args.vc.attr.group, diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index ecaf4ca03c..cefbc64c0c 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -1653,6 +1653,49 @@ template_alloc(uint32_t id, struct port_template **template, return 0; } +static int +table_alloc(uint32_t id, struct port_table **table, + struct port_table **list) +{ + struct port_table *lst = *list; + struct port_table **ppt; + struct port_table *pt = NULL; + + *table = NULL; + if (id == UINT32_MAX) { + /* taking first available ID */ + if (lst) { + if (lst->id == UINT32_MAX - 1) { + printf("Highest table ID is already" + " assigned, delete it first\n"); + return -ENOMEM; + } + id = lst->id + 1; + } else { + id = 0; + } + } + pt = calloc(1, sizeof(*pt)); + if (!pt) { + printf("Allocation of table failed\n"); + return -ENOMEM; + } + ppt = list; + while (*ppt && (*ppt)->id > id) + ppt = &(*ppt)->next; + if (*ppt && (*ppt)->id == id) { + printf("Table #%u is already assigned," + " delete it first\n", id); + free(pt); + return -EINVAL; + } + pt->next = *ppt; + pt->id = id; + *ppt = pt; + *table = pt; + return 0; +} + /** Get info about flow management resources. */ int port_flow_get_info(portid_t port_id) @@ -2289,6 +2332,134 @@ port_flow_actions_template_destroy(portid_t port_id, uint32_t n, return ret; } +/** Create table */ +int +port_flow_template_table_create(portid_t port_id, uint32_t id, + const struct rte_flow_template_table_attr *table_attr, + uint32_t nb_pattern_templates, uint32_t *pattern_templates, + uint32_t nb_actions_templates, uint32_t *actions_templates) +{ + struct rte_port *port; + struct port_table *pt; + struct port_template *temp = NULL; + int ret; + uint32_t i; + struct rte_flow_error error; + struct rte_flow_pattern_template + *flow_pattern_templates[nb_pattern_templates]; + struct rte_flow_actions_template + *flow_actions_templates[nb_actions_templates]; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + for (i = 0; i < nb_pattern_templates; ++i) { + bool found = false; + temp = port->pattern_templ_list; + while (temp) { + if (pattern_templates[i] == temp->id) { + flow_pattern_templates[i] = + temp->template.pattern_template; + found = true; + break; + } + temp = temp->next; + } + if (!found) { + printf("Pattern template #%u is invalid\n", + pattern_templates[i]); + return -EINVAL; + } + } + for (i = 0; i < nb_actions_templates; ++i) { + bool found = false; + temp = port->actions_templ_list; + while (temp) { + if (actions_templates[i] == temp->id) { + flow_actions_templates[i] = + temp->template.actions_template; + found = true; + break; + } + temp = temp->next; + } + if (!found) { + printf("Actions template #%u is invalid\n", + actions_templates[i]); + return -EINVAL; + } + } + ret = table_alloc(id, &pt, &port->table_list); + if (ret) + return ret; + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x22, sizeof(error)); + pt->table = rte_flow_template_table_create(port_id, table_attr, + flow_pattern_templates, nb_pattern_templates, + flow_actions_templates, nb_actions_templates, + &error); + + if (!pt->table) { + uint32_t destroy_id = pt->id; + port_flow_template_table_destroy(port_id, 1, &destroy_id); + return port_flow_complain(&error); + } + pt->nb_pattern_templates = nb_pattern_templates; + pt->nb_actions_templates = nb_actions_templates; + printf("Template table #%u created\n", pt->id); + return 0; +} + +/** Destroy table */ +int +port_flow_template_table_destroy(portid_t port_id, + uint32_t n, const uint32_t *table) +{ + struct rte_port *port; + struct port_table **tmp; + uint32_t c = 0; + int ret = 0; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + tmp = &port->table_list; + while (*tmp) { + uint32_t i; + + for (i = 0; i != n; ++i) { + struct rte_flow_error error; + struct port_table *pt = *tmp; + + if (table[i] != pt->id) + continue; + /* + * Poisoning to make sure PMDs update it in case + * of error. + */ + memset(&error, 0x33, sizeof(error)); + + if (pt->table && + rte_flow_template_table_destroy(port_id, + pt->table, + &error)) { + ret = port_flow_complain(&error); + continue; + } + *tmp = pt->next; + printf("Template table #%u destroyed\n", pt->id); + free(pt); + break; + } + if (i == n) + tmp = &(*tmp)->next; + ++c; + } + return ret; +} + /** Create flow rule. */ int port_flow_create(portid_t port_id, diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index ce46d754a1..fd02498faf 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -177,6 +177,16 @@ struct port_template { } template; /**< PMD opaque template object */ }; +/** Descriptor for a flow table. */ +struct port_table { + struct port_table *next; /**< Next table in list. */ + struct port_table *tmp; /**< Temporary linking. */ + uint32_t id; /**< Table ID. */ + uint32_t nb_pattern_templates; /**< Number of pattern templates. */ + uint32_t nb_actions_templates; /**< Number of actions templates. */ + struct rte_flow_template_table *table; /**< PMD opaque template object */ +}; + /** Descriptor for a single flow. */ struct port_flow { struct port_flow *next; /**< Next flow in list. */ @@ -259,6 +269,7 @@ struct rte_port { uint8_t slave_flag; /**< bonding slave port */ struct port_template *pattern_templ_list; /**< Pattern templates. */ struct port_template *actions_templ_list; /**< Actions templates. */ + struct port_table *table_list; /**< Flow tables. */ struct port_flow *flow_list; /**< Associated flows. */ struct port_indirect_action *actions_list; /**< Associated indirect actions. */ @@ -916,6 +927,12 @@ int port_flow_actions_template_create(portid_t port_id, uint32_t id, const struct rte_flow_action *masks); int port_flow_actions_template_destroy(portid_t port_id, uint32_t n, const uint32_t *template); +int port_flow_template_table_create(portid_t port_id, uint32_t id, + const struct rte_flow_template_table_attr *table_attr, + uint32_t nb_pattern_templates, uint32_t *pattern_templates, + uint32_t nb_actions_templates, uint32_t *actions_templates); +int port_flow_template_table_destroy(portid_t port_id, + uint32_t n, const uint32_t *table); int port_flow_validate(portid_t port_id, const struct rte_flow_attr *attr, const struct rte_flow_item *pattern, diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 2e6a23b12a..f63eb76a3a 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -3364,6 +3364,19 @@ following sections. flow actions_template {port_id} destroy actions_template {id} [...] +- Create a table:: + + flow table {port_id} create + [table_id {id}] + [group {group_id}] [priority {level}] [ingress] [egress] [transfer] + rules_number {number} + pattern_template {pattern_template_id} + actions_template {actions_template_id} + +- Destroy a table:: + + flow table {port_id} destroy table {id} [...] + - Check whether a flow rule can be created:: flow validate {port_id} @@ -3549,6 +3562,46 @@ The usual error message is shown when an actions template cannot be destroyed:: Caught error type [...] ([...]): [...] +Creating template table +~~~~~~~~~~~~~~~~~~~~~~~ + +``flow template_table create`` creates the specified template table. +It is bound to ``rte_flow_template_table_create()``:: + + flow template_table {port_id} create + [table_id {id}] [group {group_id}] + [priority {level}] [ingress] [egress] [transfer] + rules_number {number} + pattern_template {pattern_template_id} + actions_template {actions_template_id} + +If successful, it will show:: + + Template table #[...] created + +Otherwise it will show an error message of the form:: + + Caught error type [...] ([...]): [...] + +Destroying flow table +~~~~~~~~~~~~~~~~~~~~~ + +``flow template_table destroy`` destroys one or more template tables +from their table ID (as returned by ``flow template_table create``), +this command calls ``rte_flow_template_table_destroy()`` as many +times as necessary:: + + flow template_table {port_id} destroy table {id} [...] + +If successful, it will show:: + + Template table #[...] destroyed + +It does not report anything for table IDs that do not exist. +The usual error message is shown when a table cannot be destroyed:: + + Caught error type [...] ([...]): [...] + Creating a tunnel stub for offload ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From patchwork Sun Feb 20 03:44:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kozyrev X-Patchwork-Id: 107864 X-Patchwork-Delegate: ferruh.yigit@amd.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 42ABCA00C2; Sun, 20 Feb 2022 04:45:26 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0243441158; Sun, 20 Feb 2022 04:45:04 +0100 (CET) Received: from NAM10-MW2-obe.outbound.protection.outlook.com (mail-mw2nam10on2081.outbound.protection.outlook.com [40.107.94.81]) by mails.dpdk.org (Postfix) with ESMTP id 11B4741161 for ; Sun, 20 Feb 2022 04:45:02 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=JTu6/zYhEA0IHWnIDwZ1wyrcoua28ADWlsD0HJ72LIkomIHrervXhSBdW+usl4OWctSh7MPV/+K6odw+o4Oi3hS44LAVGkR/boef61vNgNc43xHWg/4wSFvlIQZvkh5kQvimL5cQ3O7E0H41ys9Xi3gMDs/YTwCDjOaKgY8ahaAqxCOpnE1j8eRtxDpIPOH0CyAfqwovBRO54nSIStmsG57mWiUc/deLaiuvbBW0mzagPAZeeFx7bLFySMQgEVrITGS2IbFLrQOWnNtn4mucTfcNnnPN8f/kRxKDGenxqjdmJEGygza4KqkvObfRcPeUG1qclDH/6P1dJZrpw5vSVw== 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=9aa5Luq+u3Ah4Cc+9pSnbs7iiMDdqLu2VW91VSWAgoY=; b=elFUcWwYn7x5ZrAwJtarha/ZVypPoJgfaQYD+B8e36Li8JihtvFWly6PbtuUhNpGbnlKnq/loSF8NNol+CW4/Yeq9ks/syu6tX9OoBTEpRZbejiw+VXgfOHUxmakd5HBGUnHIpurLTH6ShkumAUOzzd/n7SwFneHhydhFFfbI5m/vwXL+K6zlNEx0wVJUiFlnvNfKVZdrNxFVcANTd/NaT3bVqzzUTTMtwwSgtY6Z1DHQoV0VZeSMroWb5qW/IV6qt/ihTEZKmUg5gJBkI+vh990k+ucLxAc1xRbFN+c8zKPh/k4QGN/jWCEDMcBSYhe8HZ3wYMM6XPMuH5BhOzZWQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 12.22.5.236) smtp.rcpttodomain=intel.com 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 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=9aa5Luq+u3Ah4Cc+9pSnbs7iiMDdqLu2VW91VSWAgoY=; b=WULZwxdxcRVfkhOLODcY07C28GET/KQc8K/P+dgHygJdl/65OAsM4OrOq/Smy2aWO8ADHoFcoVq5GUY7uNzDaN/DgNE92jyY0Yp82w7JDZxeUobq5hRowS/zvhr31qF8Vhv3Y2ugMTIp0UpUcYx7oifFIGCZzKNl53ztjRZoQT11Uue2DADRwF5VIkcTs9pfd1nnEJ3/c+7vBWfbKLNx7WVaMkt3/zvtiW6o2UDdL02RpaysFi+OYXVDH+j6izH+3GmYPcoNTyqtrO20+BHon9pRydAnwx+2Rd5WiFwIX4hs8EKqPnUOO6ke3H7R4XxTI9TAN2NGfh3CJ9O1tHfsUg== Received: from BN7PR12MB2707.namprd12.prod.outlook.com (2603:10b6:408:2f::29) by CH2PR12MB3959.namprd12.prod.outlook.com (2603:10b6:610:28::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.24; Sun, 20 Feb 2022 03:45:00 +0000 Received: from DM5PR07CA0066.namprd07.prod.outlook.com (2603:10b6:4:ad::31) by BN7PR12MB2707.namprd12.prod.outlook.com (2603:10b6:408:2f::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.14; Sun, 20 Feb 2022 03:44:56 +0000 Received: from DM6NAM11FT004.eop-nam11.prod.protection.outlook.com (2603:10b6:4:ad:cafe::e8) by DM5PR07CA0066.outlook.office365.com (2603:10b6:4:ad::31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.15 via Frontend Transport; Sun, 20 Feb 2022 03:44:56 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 12.22.5.236) 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 12.22.5.236 as permitted sender) receiver=protection.outlook.com; client-ip=12.22.5.236; helo=mail.nvidia.com; Received: from mail.nvidia.com (12.22.5.236) by DM6NAM11FT004.mail.protection.outlook.com (10.13.172.217) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4995.15 via Frontend Transport; Sun, 20 Feb 2022 03:44:56 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by DRHQMAIL109.nvidia.com (10.27.9.19) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Sun, 20 Feb 2022 03:44:55 +0000 Received: from pegasus01.mtr.labs.mlnx (10.126.230.35) 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.9; Sat, 19 Feb 2022 19:44:52 -0800 From: Alexander Kozyrev To: CC: , , , , , , , , , Subject: [PATCH v8 08/11] app/testpmd: add async flow create/destroy operations Date: Sun, 20 Feb 2022 05:44:06 +0200 Message-ID: <20220220034409.2226860-9-akozyrev@nvidia.com> X-Mailer: git-send-email 2.18.2 In-Reply-To: <20220220034409.2226860-1-akozyrev@nvidia.com> References: <20220219041144.2145380-1-akozyrev@nvidia.com> <20220220034409.2226860-1-akozyrev@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.126.230.35] X-ClientProxiedBy: rnnvmail202.nvidia.com (10.129.68.7) To rnnvmail201.nvidia.com (10.129.68.8) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: dfe08a16-23ee-4f87-7b60-08d9f4235cd0 X-MS-TrafficTypeDiagnostic: BN7PR12MB2707:EE_|CH2PR12MB3959:EE_ X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr,ExtAddr X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: WXeHTsltGbgdJOK5dFMitCZJhIzyG6TWG3QtLO9rjCwaJVg+sPxnZRV3ykQlCsp/pIjYc5ucsRSUFjU6SXWiwB/5xIo25695gJYzZTdIfqDjbdo0SmmOFh1aR8CEfKudMsszBFgv4pONCM2ttY1jS1JTx6zpNO+F80RI0db5M22m2B+CxR3cgkpUYItGYcSXio2/EZIvygLWhNy5S2a9TpxphJCiC6DNNx/4UXpzVEEROcw/tUt/FZHxHiht1TKWQg5QjmQ9JFjY+0SuhQxmZUwrWOeJhdf5yo9WNlmsN8Tk3NyTlKI8YSSecSydax6FvLt2QX/OYu54omsvVGIea5dP4J2sn7ctGRVMr9wmVAru1qweILXmB4p+F5qXbvyOgBaLl2O3ozcZCLZoG/Ll0bkSwoa/HEJGWtp4NwXzamJDanFJLICoMwkK1IFTGNvs7ZC2C+UM8zKznBlHUskGgso+qYV8T6t4J8XK6BbgVmNrhK14DUxhuoLU+CeNVDO2HZMbXRzijCxAucFzKLbmLaN6LM/d5AKYq4SpHGjIJlXy1gmWfwKicxaS9eJqVyV/RcUmZxbr7aLdvOBetWcgBcIQcnzhQ9nlb6GGoUmZ/O0bb9/SPOaaHe009NEtlim6lpkosNUlw/nN6loLnAuuhvwNEktAXM/oBqSYGqBGzvvmOfEVc6A7/TT1Zm64s2lmOcvbJyVYmep2EAJNSyegCg== X-Forefront-Antispam-Report: CIP:12.22.5.236; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:mail.nvidia.com; PTR:InfoNoRecords; CAT:NONE; SFS:(13230001)(4636009)(36840700001)(46966006)(40470700004)(36860700001)(86362001)(356005)(81166007)(40460700003)(8676002)(4326008)(70586007)(70206006)(316002)(54906003)(8936002)(6916009)(2906002)(5660300002)(30864003)(7416002)(336012)(426003)(1076003)(16526019)(186003)(26005)(47076005)(83380400001)(2616005)(508600001)(6666004)(82310400004)(36756003)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Feb 2022 03:44:56.5960 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: dfe08a16-23ee-4f87-7b60-08d9f4235cd0 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[12.22.5.236]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-CrossTenant-AuthSource: DM6NAM11FT004.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH2PR12MB3959 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 testpmd support for the rte_flow_q_create/rte_flow_q_destroy API. Provide the command line interface for enqueueing flow creation/destruction operations. Usage example: testpmd> flow queue 0 create 0 postpone no template_table 6 pattern_template 0 actions_template 0 pattern eth dst is 00:16:3e:31:15:c3 / end actions drop / end testpmd> flow queue 0 destroy 0 postpone yes rule 0 Signed-off-by: Alexander Kozyrev Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 267 +++++++++++++++++++- app/test-pmd/config.c | 166 ++++++++++++ app/test-pmd/testpmd.h | 7 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 57 +++++ 4 files changed, 496 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 5715899c95..d359127df9 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -59,6 +59,7 @@ enum index { COMMON_PATTERN_TEMPLATE_ID, COMMON_ACTIONS_TEMPLATE_ID, COMMON_TABLE_ID, + COMMON_QUEUE_ID, /* TOP-level command. */ ADD, @@ -92,6 +93,7 @@ enum index { ISOLATE, TUNNEL, FLEX, + QUEUE, /* Flex arguments */ FLEX_ITEM_INIT, @@ -120,6 +122,22 @@ enum index { ACTIONS_TEMPLATE_SPEC, ACTIONS_TEMPLATE_MASK, + /* Queue arguments. */ + QUEUE_CREATE, + QUEUE_DESTROY, + + /* Queue create arguments. */ + QUEUE_CREATE_ID, + QUEUE_CREATE_POSTPONE, + QUEUE_TEMPLATE_TABLE, + QUEUE_PATTERN_TEMPLATE, + QUEUE_ACTIONS_TEMPLATE, + QUEUE_SPEC, + + /* Queue destroy arguments. */ + QUEUE_DESTROY_ID, + QUEUE_DESTROY_POSTPONE, + /* Table arguments. */ TABLE_CREATE, TABLE_DESTROY, @@ -918,6 +936,8 @@ struct token { struct buffer { enum index command; /**< Flow command. */ portid_t port; /**< Affected port ID. */ + queueid_t queue; /** Async queue ID. */ + bool postpone; /** Postpone async operation */ union { struct { struct rte_flow_port_attr port_attr; @@ -948,6 +968,7 @@ struct buffer { uint32_t action_id; } ia; /* Indirect action query arguments */ struct { + uint32_t table_id; uint32_t pat_templ_id; uint32_t act_templ_id; struct rte_flow_attr attr; @@ -1103,6 +1124,18 @@ static const enum index next_table_destroy_attr[] = { ZERO, }; +static const enum index next_queue_subcmd[] = { + QUEUE_CREATE, + QUEUE_DESTROY, + ZERO, +}; + +static const enum index next_queue_destroy_attr[] = { + QUEUE_DESTROY_ID, + END, + ZERO, +}; + static const enum index next_ia_create_attr[] = { INDIRECT_ACTION_CREATE_ID, INDIRECT_ACTION_INGRESS, @@ -2213,6 +2246,12 @@ static int parse_table(struct context *, const struct token *, static int parse_table_destroy(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_qo(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); +static int parse_qo_destroy(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_tunnel(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -2288,6 +2327,8 @@ static int comp_actions_template_id(struct context *, const struct token *, unsigned int, char *, unsigned int); static int comp_table_id(struct context *, const struct token *, unsigned int, char *, unsigned int); +static int comp_queue_id(struct context *, const struct token *, + unsigned int, char *, unsigned int); /** Token definitions. */ static const struct token token_list[] = { @@ -2459,6 +2500,13 @@ static const struct token token_list[] = { .call = parse_int, .comp = comp_table_id, }, + [COMMON_QUEUE_ID] = { + .name = "{queue_id}", + .type = "QUEUE_ID", + .help = "queue id", + .call = parse_int, + .comp = comp_queue_id, + }, /* Top-level command. */ [FLOW] = { .name = "flow", @@ -2481,7 +2529,8 @@ static const struct token token_list[] = { QUERY, ISOLATE, TUNNEL, - FLEX)), + FLEX, + QUEUE)), .call = parse_init, }, /* Top-level command. */ @@ -2784,6 +2833,84 @@ static const struct token token_list[] = { .call = parse_table, }, /* Top-level command. */ + [QUEUE] = { + .name = "queue", + .help = "queue a flow rule operation", + .next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_qo, + }, + /* Sub-level commands. */ + [QUEUE_CREATE] = { + .name = "create", + .help = "create a flow rule", + .next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE), + NEXT_ENTRY(COMMON_QUEUE_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, queue)), + .call = parse_qo, + }, + [QUEUE_DESTROY] = { + .name = "destroy", + .help = "destroy a flow rule", + .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID), + NEXT_ENTRY(COMMON_QUEUE_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, queue)), + .call = parse_qo_destroy, + }, + /* Queue arguments. */ + [QUEUE_TEMPLATE_TABLE] = { + .name = "template table", + .help = "specify table id", + .next = NEXT(NEXT_ENTRY(QUEUE_PATTERN_TEMPLATE), + NEXT_ENTRY(COMMON_TABLE_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.vc.table_id)), + .call = parse_qo, + }, + [QUEUE_PATTERN_TEMPLATE] = { + .name = "pattern_template", + .help = "specify pattern template index", + .next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE), + NEXT_ENTRY(COMMON_UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.vc.pat_templ_id)), + .call = parse_qo, + }, + [QUEUE_ACTIONS_TEMPLATE] = { + .name = "actions_template", + .help = "specify actions template index", + .next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE), + NEXT_ENTRY(COMMON_UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.vc.act_templ_id)), + .call = parse_qo, + }, + [QUEUE_CREATE_POSTPONE] = { + .name = "postpone", + .help = "postpone create operation", + .next = NEXT(NEXT_ENTRY(ITEM_PATTERN), + NEXT_ENTRY(COMMON_BOOLEAN)), + .args = ARGS(ARGS_ENTRY(struct buffer, postpone)), + .call = parse_qo, + }, + [QUEUE_DESTROY_POSTPONE] = { + .name = "postpone", + .help = "postpone destroy operation", + .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID), + NEXT_ENTRY(COMMON_BOOLEAN)), + .args = ARGS(ARGS_ENTRY(struct buffer, postpone)), + .call = parse_qo_destroy, + }, + [QUEUE_DESTROY_ID] = { + .name = "rule", + .help = "specify rule id to destroy", + .next = NEXT(next_queue_destroy_attr, + NEXT_ENTRY(COMMON_UNSIGNED)), + .args = ARGS(ARGS_ENTRY_PTR(struct buffer, + args.destroy.rule)), + .call = parse_qo_destroy, + }, + /* Top-level command. */ [INDIRECT_ACTION] = { .name = "indirect_action", .type = "{command} {port_id} [{arg} [...]]", @@ -8503,6 +8630,111 @@ parse_table_destroy(struct context *ctx, const struct token *token, return len; } +/** Parse tokens for queue create commands. */ +static int +parse_qo(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command) { + if (ctx->curr != QUEUE) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + out->args.vc.data = (uint8_t *)out + size; + return len; + } + switch (ctx->curr) { + case QUEUE_CREATE: + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + return len; + case QUEUE_TEMPLATE_TABLE: + case QUEUE_PATTERN_TEMPLATE: + case QUEUE_ACTIONS_TEMPLATE: + case QUEUE_CREATE_POSTPONE: + return len; + case ITEM_PATTERN: + out->args.vc.pattern = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + ctx->object = out->args.vc.pattern; + ctx->objmask = NULL; + return len; + case ACTIONS: + out->args.vc.actions = + (void *)RTE_ALIGN_CEIL((uintptr_t) + (out->args.vc.pattern + + out->args.vc.pattern_n), + sizeof(double)); + ctx->object = out->args.vc.actions; + ctx->objmask = NULL; + return len; + default: + return -1; + } +} + +/** Parse tokens for queue destroy command. */ +static int +parse_qo_destroy(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + uint32_t *flow_id; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command || out->command == QUEUE) { + if (ctx->curr != QUEUE_DESTROY) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + out->args.destroy.rule = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + return len; + } + switch (ctx->curr) { + case QUEUE_DESTROY_ID: + flow_id = out->args.destroy.rule + + out->args.destroy.rule_n++; + if ((uint8_t *)flow_id > (uint8_t *)out + size) + return -1; + ctx->objdata = 0; + ctx->object = flow_id; + ctx->objmask = NULL; + return len; + case QUEUE_DESTROY_POSTPONE: + return len; + default: + return -1; + } +} + static int parse_flex(struct context *ctx, const struct token *token, const char *str, unsigned int len, @@ -9544,6 +9776,28 @@ comp_table_id(struct context *ctx, const struct token *token, return i; } +/** Complete available queue IDs. */ +static int +comp_queue_id(struct context *ctx, const struct token *token, + unsigned int ent, char *buf, unsigned int size) +{ + unsigned int i = 0; + struct rte_port *port; + + (void)token; + if (port_id_is_invalid(ctx->port, DISABLED_WARN) || + ctx->port == (portid_t)RTE_PORT_ALL) + return -1; + port = &ports[ctx->port]; + for (i = 0; i < port->queue_nb; i++) { + if (buf && i == ent) + return snprintf(buf, size, "%u", i); + } + if (buf) + return -1; + return i; +} + /** Internal context. */ static struct context cmd_flow_context; @@ -9855,6 +10109,17 @@ cmd_flow_parsed(const struct buffer *in) in->args.table_destroy.table_id_n, in->args.table_destroy.table_id); break; + case QUEUE_CREATE: + port_queue_flow_create(in->port, in->queue, in->postpone, + in->args.vc.table_id, in->args.vc.pat_templ_id, + in->args.vc.act_templ_id, in->args.vc.pattern, + in->args.vc.actions); + break; + case QUEUE_DESTROY: + port_queue_flow_destroy(in->port, in->queue, in->postpone, + in->args.destroy.rule_n, + in->args.destroy.rule); + break; case INDIRECT_ACTION_CREATE: port_action_handle_create( in->port, in->args.vc.attr.group, diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index cefbc64c0c..d3b3e6ca5a 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -2460,6 +2460,172 @@ port_flow_template_table_destroy(portid_t port_id, return ret; } +/** Enqueue create flow rule operation. */ +int +port_queue_flow_create(portid_t port_id, queueid_t queue_id, + bool postpone, uint32_t table_id, + uint32_t pattern_idx, uint32_t actions_idx, + const struct rte_flow_item *pattern, + const struct rte_flow_action *actions) +{ + struct rte_flow_q_ops_attr ops_attr = { .postpone = postpone }; + struct rte_flow_q_op_res comp = { 0 }; + struct rte_flow *flow; + struct rte_port *port; + struct port_flow *pf; + struct port_table *pt; + uint32_t id = 0; + bool found; + int ret = 0; + struct rte_flow_error error = { RTE_FLOW_ERROR_TYPE_NONE, NULL, NULL }; + struct rte_flow_action_age *age = age_action_get(actions); + + port = &ports[port_id]; + if (port->flow_list) { + if (port->flow_list->id == UINT32_MAX) { + printf("Highest rule ID is already assigned," + " delete it first"); + return -ENOMEM; + } + id = port->flow_list->id + 1; + } + + if (queue_id >= port->queue_nb) { + printf("Queue #%u is invalid\n", queue_id); + return -EINVAL; + } + + found = false; + pt = port->table_list; + while (pt) { + if (table_id == pt->id) { + found = true; + break; + } + pt = pt->next; + } + if (!found) { + printf("Table #%u is invalid\n", table_id); + return -EINVAL; + } + + if (pattern_idx >= pt->nb_pattern_templates) { + printf("Pattern template index #%u is invalid," + " %u templates present in the table\n", + pattern_idx, pt->nb_pattern_templates); + return -EINVAL; + } + if (actions_idx >= pt->nb_actions_templates) { + printf("Actions template index #%u is invalid," + " %u templates present in the table\n", + actions_idx, pt->nb_actions_templates); + return -EINVAL; + } + + pf = port_flow_new(NULL, pattern, actions, &error); + if (!pf) + return port_flow_complain(&error); + if (age) { + pf->age_type = ACTION_AGE_CONTEXT_TYPE_FLOW; + age->context = &pf->age_type; + } + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x11, sizeof(error)); + flow = rte_flow_async_create(port_id, queue_id, &ops_attr, pt->table, + pattern, pattern_idx, actions, actions_idx, NULL, &error); + if (!flow) { + uint32_t flow_id = pf->id; + port_queue_flow_destroy(port_id, queue_id, true, 1, &flow_id); + return port_flow_complain(&error); + } + + while (ret == 0) { + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x22, sizeof(error)); + ret = rte_flow_pull(port_id, queue_id, &comp, 1, &error); + if (ret < 0) { + printf("Failed to pull queue\n"); + return -EINVAL; + } + } + + pf->next = port->flow_list; + pf->id = id; + pf->flow = flow; + port->flow_list = pf; + printf("Flow rule #%u creation enqueued\n", pf->id); + return 0; +} + +/** Enqueue number of destroy flow rules operations. */ +int +port_queue_flow_destroy(portid_t port_id, queueid_t queue_id, + bool postpone, uint32_t n, const uint32_t *rule) +{ + struct rte_flow_q_ops_attr op_attr = { .postpone = postpone }; + struct rte_flow_q_op_res comp = { 0 }; + struct rte_port *port; + struct port_flow **tmp; + uint32_t c = 0; + int ret = 0; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + + if (queue_id >= port->queue_nb) { + printf("Queue #%u is invalid\n", queue_id); + return -EINVAL; + } + + tmp = &port->flow_list; + while (*tmp) { + uint32_t i; + + for (i = 0; i != n; ++i) { + struct rte_flow_error error; + struct port_flow *pf = *tmp; + + if (rule[i] != pf->id) + continue; + /* + * Poisoning to make sure PMD + * update it in case of error. + */ + memset(&error, 0x33, sizeof(error)); + if (rte_flow_async_destroy(port_id, queue_id, &op_attr, + pf->flow, NULL, &error)) { + ret = port_flow_complain(&error); + continue; + } + + while (ret == 0) { + /* + * Poisoning to make sure PMD + * update it in case of error. + */ + memset(&error, 0x44, sizeof(error)); + ret = rte_flow_pull(port_id, queue_id, + &comp, 1, &error); + if (ret < 0) { + printf("Failed to pull queue\n"); + return -EINVAL; + } + } + + printf("Flow rule #%u destruction enqueued\n", pf->id); + *tmp = pf->next; + free(pf); + break; + } + if (i == n) + tmp = &(*tmp)->next; + ++c; + } + return ret; +} + /** Create flow rule. */ int port_flow_create(portid_t port_id, diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index fd02498faf..62e874eaaf 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -933,6 +933,13 @@ int port_flow_template_table_create(portid_t port_id, uint32_t id, uint32_t nb_actions_templates, uint32_t *actions_templates); int port_flow_template_table_destroy(portid_t port_id, uint32_t n, const uint32_t *table); +int port_queue_flow_create(portid_t port_id, queueid_t queue_id, + bool postpone, uint32_t table_id, + uint32_t pattern_idx, uint32_t actions_idx, + const struct rte_flow_item *pattern, + const struct rte_flow_action *actions); +int port_queue_flow_destroy(portid_t port_id, queueid_t queue_id, + bool postpone, uint32_t n, const uint32_t *rule); int port_flow_validate(portid_t port_id, const struct rte_flow_attr *attr, const struct rte_flow_item *pattern, diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index f63eb76a3a..194b350932 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -3384,6 +3384,20 @@ following sections. pattern {item} [/ {item} [...]] / end actions {action} [/ {action} [...]] / end +- Enqueue creation of a flow rule:: + + flow queue {port_id} create {queue_id} + [postpone {boolean}] template_table {table_id} + pattern_template {pattern_template_index} + actions_template {actions_template_index} + pattern {item} [/ {item} [...]] / end + actions {action} [/ {action} [...]] / end + +- Enqueue destruction of specific flow rules:: + + flow queue {port_id} destroy {queue_id} + [postpone {boolean}] rule {rule_id} [...] + - Create a flow rule:: flow create {port_id} @@ -3708,6 +3722,30 @@ one. **All unspecified object values are automatically initialized to 0.** +Enqueueing creation of flow rules +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow queue create`` adds creation operation of a flow rule to a queue. +It is bound to ``rte_flow_async_create()``:: + + flow queue {port_id} create {queue_id} + [postpone {boolean}] template_table {table_id} + pattern_template {pattern_template_index} + actions_template {actions_template_index} + pattern {item} [/ {item} [...]] / end + actions {action} [/ {action} [...]] / end + +If successful, it will return a flow rule ID usable with other commands:: + + Flow rule #[...] creaion enqueued + +Otherwise it will show an error message of the form:: + + Caught error type [...] ([...]): [...] + +This command uses the same pattern items and actions as ``flow create``, +their format is described in `Creating flow rules`_. + Attributes ^^^^^^^^^^ @@ -4430,6 +4468,25 @@ Non-existent rule IDs are ignored:: Flow rule #0 destroyed testpmd> +Enqueueing destruction of flow rules +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow queue destroy`` adds destruction operations to destroy one or more rules +from their rule ID (as returned by ``flow queue create``) to a queue, +this command calls ``rte_flow_async_destroy()`` as many times as necessary:: + + flow queue {port_id} destroy {queue_id} + [postpone {boolean}] rule {rule_id} [...] + +If successful, it will show:: + + Flow rule #[...] destruction enqueued + +It does not report anything for rule IDs that do not exist. The usual error +message is shown when a rule cannot be destroyed:: + + Caught error type [...] ([...]): [...] + Querying flow rules ~~~~~~~~~~~~~~~~~~~ From patchwork Sun Feb 20 03:44:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kozyrev X-Patchwork-Id: 107866 X-Patchwork-Delegate: ferruh.yigit@amd.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 89AC2A00C2; Sun, 20 Feb 2022 04:45:41 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 79DBF411B2; Sun, 20 Feb 2022 04:45:07 +0100 (CET) Received: from NAM11-BN8-obe.outbound.protection.outlook.com (mail-bn8nam11on2048.outbound.protection.outlook.com [40.107.236.48]) by mails.dpdk.org (Postfix) with ESMTP id 18ECD4116E for ; Sun, 20 Feb 2022 04:45:05 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=I5Bcng+DZSg+wkoIVIo6gyZk8NV8vP72j0ir2NiLcMUAnIhBtG3q/5EDdfvoPtqEcHmrY32MUChNCBVWEMBNpIqSOaosiAAVtpW/ijoFyPIH1vAqfAURTarwjBa/ApDJUpvtPBeXYAwJuGlHXuEV9tVq5K0cBnh4RWjtoLimJvfvmZvVsKNVWH1DIqWTL9waYfsQKo1CsYJ3O2gPpxUn0F45MmItE17SN0okK60riHNH8LZ48gRH8c5HEUWF74vE2724YrpiJwLi93ocdVfvjFa4/Y4vSYPK67KNf9uVRZ4HBYzhhsDzTpM+Vb+6e3Z1fdNq4DjFCP0AHDT3EAyPeg== 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=hYgvzeOWEQFoDap0ZaNPkkZPMIySpNz2qIjFzhzWwic=; b=Z+dYPTCXinF2Sq6s6MXeUwKowT2hAKJF6gyyD9CowQX00fdvH2iDoWPMwCrdzq6catVvwI54frRupR0i2t+9fCMqlNFyvJfddDxkIteH/wkFAl1nJPD6ftHNcQ1j5v677g9XHz/OlgjwQMzFPZH/p2eYD7HxBFFLyHY4cu8fRVHbu+eDul5L5ksGHYCEiCt86PZLHqS6f01nSqL5ag0wGM6FxnesAPPZBNaSubFoEMYBaX65TbzRbvtS0LWmIpqgevIQhWvlrTRXHoi9ev6x0Ijbuj1n/GRosKdqtiWatDzccWZMDGeEyWlsrjWZYarUlb7F5K4GcdAAERm6jZb7rQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=temperror (sender ip is 12.22.5.238) smtp.rcpttodomain=intel.com smtp.mailfrom=nvidia.com; dmarc=temperror action=none header.from=nvidia.com; dkim=none (message not signed); arc=none 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=hYgvzeOWEQFoDap0ZaNPkkZPMIySpNz2qIjFzhzWwic=; b=Ryk6gFWVG0vo6daOiVvSw55e/m7bS/XuHgn1tsGuMdX1SjGArR0StT1lUYnxcIakATITEGTdGBdFycqtAC6qCJ98HrZivLrXjEdQyTu5i8nOLwkNFex+ugANbdKdw8CALlKnS1x4qi2uq0v848V971mW8AuAJxXzzz485xN/lAnnoTi2W4+emxh8vYoE2xs61hidPXAgJGS2YhUOfpYx16L2Lry0ws/5mhMl1ipBgJbN1Dy1Mr5gDeyYkYwZ9pU7VaAXge359pevih1yAv8SjmW7JiXKgIp7SFX8kgxBRI2I69/5W0bEMDhuD1YzeS1Db/C88ZBoda7X+3D5Zg8slQ== Received: from CH0PR12MB5387.namprd12.prod.outlook.com (2603:10b6:610:d6::17) by BY5PR12MB3953.namprd12.prod.outlook.com (2603:10b6:a03:194::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.24; Sun, 20 Feb 2022 03:45:02 +0000 Received: from BN8PR07CA0006.namprd07.prod.outlook.com (2603:10b6:408:ac::19) by CH0PR12MB5387.namprd12.prod.outlook.com (2603:10b6:610:d6::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.24; Sun, 20 Feb 2022 03:45:01 +0000 Received: from BN8NAM11FT030.eop-nam11.prod.protection.outlook.com (2603:10b6:408:ac:cafe::1f) by BN8PR07CA0006.outlook.office365.com (2603:10b6:408:ac::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.14 via Frontend Transport; Sun, 20 Feb 2022 03:45:01 +0000 X-MS-Exchange-Authentication-Results: spf=temperror (sender IP is 12.22.5.238) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=temperror action=none header.from=nvidia.com; Received-SPF: TempError (protection.outlook.com: error in processing during lookup of nvidia.com: DNS Timeout) Received: from mail.nvidia.com (12.22.5.238) by BN8NAM11FT030.mail.protection.outlook.com (10.13.177.146) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4995.15 via Frontend Transport; Sun, 20 Feb 2022 03:45:00 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by DRHQMAIL105.nvidia.com (10.27.9.14) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Sun, 20 Feb 2022 03:44:59 +0000 Received: from pegasus01.mtr.labs.mlnx (10.126.230.35) 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.9; Sat, 19 Feb 2022 19:44:55 -0800 From: Alexander Kozyrev To: CC: , , , , , , , , , Subject: [PATCH v8 09/11] app/testpmd: add flow queue push operation Date: Sun, 20 Feb 2022 05:44:07 +0200 Message-ID: <20220220034409.2226860-10-akozyrev@nvidia.com> X-Mailer: git-send-email 2.18.2 In-Reply-To: <20220220034409.2226860-1-akozyrev@nvidia.com> References: <20220219041144.2145380-1-akozyrev@nvidia.com> <20220220034409.2226860-1-akozyrev@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.126.230.35] X-ClientProxiedBy: rnnvmail202.nvidia.com (10.129.68.7) To rnnvmail201.nvidia.com (10.129.68.8) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 0613f6ee-71a5-4ef4-1e2b-08d9f4235edf X-MS-TrafficTypeDiagnostic: CH0PR12MB5387:EE_|BY5PR12MB3953:EE_ X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr,ExtAddr X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: SWLpoYMOv6Ha9pJnJM+B2m1nb6zywhZkCQsmQpHMDWubN6lxgHPBaSgL8OUE/5xMQE/uF1j+7Ofou0QI7cjoTgCUiFJw9BQTG6JhmyeSQnNjPlsHoZeUf4q8K6/ONUwdE83ZUdJD4KW2HEtPYRr3JI9e7NqpldTKACwqyWXEav316HnpPW0BzXwChInjPQWYaCgnLkgJHS05pqDiq40jsezGuSq6aA8Cj2yec8a7OCyEcvuwvnnSeksr6tbckrpkoYrFEbzJJbB8Auvz4+E9olFAK/pbNPIOgGAvq4UahXB1Mc7hT2bqVcOT3+lNIUo4ZNgdDT1WBCCgNRG1HBM+DHx7o5jRaPLCetri+20Iv5+1L1J0CQ2uw+yTMIjF+IykuIgQcpf9hVYRsEkNb0QaqQU1Dx0uPXQBA2BtES2gb4M8Rxi/s5VfSL1D/+LlugXUpdJYKQnkPoc0J4rIIPJ8lHu18uN0nF8GvkHalZUlkoGdSPpRtrhruUQvB+OpF4K7hMZ37WaEAUTvFu7qDGqHsdYN3crDUzSjFmnPHpci5/c2rcJBcLGO6nMqQFvcNXP3rfAICUK7JdF8TIRjViqesNp5XtM2r5CMPiuIodH2CDwasVOltPR0GGBBIt2Gf0sXUl0AS7rXq3z6B0SX3Nhx2JElE1+IB4tBvR5p6QKUPY1ypfFZjDlukEiVjR6mY3Vv8r02GpWSkZHE+7UAdmYttA== X-Forefront-Antispam-Report: CIP:12.22.5.238; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:mail.nvidia.com; PTR:InfoNoRecords; CAT:NONE; SFS:(13230001)(4636009)(36840700001)(46966006)(40470700004)(8676002)(70586007)(6666004)(4326008)(82310400004)(70206006)(508600001)(316002)(86362001)(6916009)(54906003)(63370400001)(83380400001)(63350400001)(36860700001)(40460700003)(47076005)(356005)(2616005)(81166007)(1076003)(186003)(16526019)(336012)(426003)(26005)(5660300002)(8936002)(36756003)(2906002)(7416002)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Feb 2022 03:45:00.0474 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 0613f6ee-71a5-4ef4-1e2b-08d9f4235edf X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[12.22.5.238]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-CrossTenant-AuthSource: BN8NAM11FT030.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY5PR12MB3953 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 testpmd support for the rte_flow_push API. Provide the command line interface for pushing operations. Usage example: flow queue 0 push 0 Signed-off-by: Alexander Kozyrev Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 56 ++++++++++++++++++++- app/test-pmd/config.c | 28 +++++++++++ app/test-pmd/testpmd.h | 1 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 21 ++++++++ 4 files changed, 105 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index d359127df9..af36975cdf 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -94,6 +94,7 @@ enum index { TUNNEL, FLEX, QUEUE, + PUSH, /* Flex arguments */ FLEX_ITEM_INIT, @@ -138,6 +139,9 @@ enum index { QUEUE_DESTROY_ID, QUEUE_DESTROY_POSTPONE, + /* Push arguments. */ + PUSH_QUEUE, + /* Table arguments. */ TABLE_CREATE, TABLE_DESTROY, @@ -2252,6 +2256,9 @@ static int parse_qo(struct context *, const struct token *, static int parse_qo_destroy(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_push(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_tunnel(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -2530,7 +2537,8 @@ static const struct token token_list[] = { ISOLATE, TUNNEL, FLEX, - QUEUE)), + QUEUE, + PUSH)), .call = parse_init, }, /* Top-level command. */ @@ -2911,6 +2919,21 @@ static const struct token token_list[] = { .call = parse_qo_destroy, }, /* Top-level command. */ + [PUSH] = { + .name = "push", + .help = "push enqueued operations", + .next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_push, + }, + /* Sub-level commands. */ + [PUSH_QUEUE] = { + .name = "queue", + .help = "specify queue id", + .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, queue)), + }, + /* Top-level command. */ [INDIRECT_ACTION] = { .name = "indirect_action", .type = "{command} {port_id} [{arg} [...]]", @@ -8735,6 +8758,34 @@ parse_qo_destroy(struct context *ctx, const struct token *token, } } +/** Parse tokens for push queue command. */ +static int +parse_push(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command) { + if (ctx->curr != PUSH) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + out->args.vc.data = (uint8_t *)out + size; + } + return len; +} + static int parse_flex(struct context *ctx, const struct token *token, const char *str, unsigned int len, @@ -10120,6 +10171,9 @@ cmd_flow_parsed(const struct buffer *in) in->args.destroy.rule_n, in->args.destroy.rule); break; + case PUSH: + port_queue_flow_push(in->port, in->queue); + break; case INDIRECT_ACTION_CREATE: port_action_handle_create( in->port, in->args.vc.attr.group, diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index d3b3e6ca5a..e3b5e348ab 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -2626,6 +2626,34 @@ port_queue_flow_destroy(portid_t port_id, queueid_t queue_id, return ret; } +/** Push all the queue operations in the queue to the NIC. */ +int +port_queue_flow_push(portid_t port_id, queueid_t queue_id) +{ + struct rte_port *port; + struct rte_flow_error error; + int ret = 0; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + + if (queue_id >= port->queue_nb) { + printf("Queue #%u is invalid\n", queue_id); + return -EINVAL; + } + + memset(&error, 0x55, sizeof(error)); + ret = rte_flow_push(port_id, queue_id, &error); + if (ret < 0) { + printf("Failed to push operations in the queue\n"); + return -EINVAL; + } + printf("Queue #%u operations pushed\n", queue_id); + return ret; +} + /** Create flow rule. */ int port_flow_create(portid_t port_id, diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 62e874eaaf..24a43fd82c 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -940,6 +940,7 @@ int port_queue_flow_create(portid_t port_id, queueid_t queue_id, const struct rte_flow_action *actions); int port_queue_flow_destroy(portid_t port_id, queueid_t queue_id, bool postpone, uint32_t n, const uint32_t *rule); +int port_queue_flow_push(portid_t port_id, queueid_t queue_id); int port_flow_validate(portid_t port_id, const struct rte_flow_attr *attr, const struct rte_flow_item *pattern, diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 194b350932..4f1f908d4a 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -3398,6 +3398,10 @@ following sections. flow queue {port_id} destroy {queue_id} [postpone {boolean}] rule {rule_id} [...] +- Push enqueued operations:: + + flow push {port_id} queue {queue_id} + - Create a flow rule:: flow create {port_id} @@ -3616,6 +3620,23 @@ The usual error message is shown when a table cannot be destroyed:: Caught error type [...] ([...]): [...] +Pushing enqueued operations +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow push`` pushes all the outstanding enqueued operations +to the underlying device immediately. +It is bound to ``rte_flow_push()``:: + + flow push {port_id} queue {queue_id} + +If successful, it will show:: + + Queue #[...] operations pushed + +The usual error message is shown when operations cannot be pushed:: + + Caught error type [...] ([...]): [...] + Creating a tunnel stub for offload ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From patchwork Sun Feb 20 03:44:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kozyrev X-Patchwork-Id: 107867 X-Patchwork-Delegate: ferruh.yigit@amd.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 C0D7DA00C2; Sun, 20 Feb 2022 04:45:46 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 62B234114A; Sun, 20 Feb 2022 04:45:13 +0100 (CET) Received: from NAM12-MW2-obe.outbound.protection.outlook.com (mail-mw2nam12on2040.outbound.protection.outlook.com [40.107.244.40]) by mails.dpdk.org (Postfix) with ESMTP id EA03F410E7 for ; Sun, 20 Feb 2022 04:45:10 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Ot/ZOzqwDJIBXpeTuCnqpG9j6eb1z7eAacU/p9uI6dKl+nDj5XXYRpdZHe3kiF/84Ko9ZRtaPzUNXHKpcn2sw3biKS1FefkF8N0TyxficRpRRFHdR7HmMG4nX3P6HjEW14lMo/MDkb9Mgz3WsTLk5eAiWTK+jhZDu3uOgPgr/LPOv4E3rakMiBt1JwFvYtxRTr3uZ0aExP/oIJvMhwRPhbkAHdcP/UrKzlhS02l62b+hx3Q/Sq2IEllbnLWeAjSBt1VP7HBtLQOdr5IEVH4H8xlcmKMr1lCs9Ou+VUoCn10SxKM7I/ETuIOa7fkWy6m4ecBszDfEfBMlzH2z3f4YlA== 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=k8pmHHUUjzX73O9IbnGxTSt292xJageuxx2A7uDEV5c=; b=NmAn8HPxlRP/oEujdSz+00/N7hvL6WBUTR1xm1WB8Ez739u8iHfaeiAqazkM8qcANoB6UyzmqjFFlmYbSMCiM7PMp4xW00fhZGerk1YiOWkPe+ibstJ6H18NavyXa9tWB5kU2sOaHpZv6Q5PsmSyimUhfJIXCmTGgq/QVvNGN1NSsyoE33xo+AgHi78H7f1lalHHTnW/8nftQptXDm+PWj+8HdqpBN4GQGnp3K+DExEgtdkO6fx2pE7FZsBhF6ZL6cHMBcZh/+7qVs/Cnm4McozAVxDzR9/e/9ejrDkYCAPjQl3AaXkC2VkAj5KTXeKKys2DHa+WH8v3BGlDC2Hsow== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 12.22.5.234) smtp.rcpttodomain=intel.com 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 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=k8pmHHUUjzX73O9IbnGxTSt292xJageuxx2A7uDEV5c=; b=NCAoimPt3vDdCpepQZeaALxfHGbkpP7XDTrfhuQkxKCx0BoZ33ywNYEqJbGUaNRYCA2xtHNOcf3jLWR4gi2EcPgkZfGNOIpsKHlKM2M3Bg5H5JapBoF4AG9sPEEeFHIggh36/hZi/KosZPrNqiXeNTPYs3kdEOJYHXrj32IpBSZU4kCt3eTq40AgesVR6RNObyK0XdO0hGh1kr2HzYH+O+4mXxIRlF6Qy5+VGDwrOldJhxln7GKDlZzC29w+jVJ68IS54QXyo0k5WuVy8n3eoPNgzvbX3OQWyyGazAzbRWfPRJNT+MzDj9h1IOD+r0S0QtdCdOdBluwENK10C43vAA== Received: from DM6PR12MB4060.namprd12.prod.outlook.com (2603:10b6:5:216::15) by MN2PR12MB3118.namprd12.prod.outlook.com (2603:10b6:208:c6::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.17; Sun, 20 Feb 2022 03:45:07 +0000 Received: from BN9PR03CA0672.namprd03.prod.outlook.com (2603:10b6:408:10e::17) by DM6PR12MB4060.namprd12.prod.outlook.com (2603:10b6:5:216::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.16; Sun, 20 Feb 2022 03:45:04 +0000 Received: from BN8NAM11FT055.eop-nam11.prod.protection.outlook.com (2603:10b6:408:10e:cafe::da) by BN9PR03CA0672.outlook.office365.com (2603:10b6:408:10e::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.14 via Frontend Transport; Sun, 20 Feb 2022 03:45:04 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 12.22.5.234) 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 12.22.5.234 as permitted sender) receiver=protection.outlook.com; client-ip=12.22.5.234; helo=mail.nvidia.com; Received: from mail.nvidia.com (12.22.5.234) by BN8NAM11FT055.mail.protection.outlook.com (10.13.177.62) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4995.15 via Frontend Transport; Sun, 20 Feb 2022 03:45:04 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by DRHQMAIL101.nvidia.com (10.27.9.10) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Sun, 20 Feb 2022 03:45:02 +0000 Received: from pegasus01.mtr.labs.mlnx (10.126.230.35) 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.9; Sat, 19 Feb 2022 19:44:58 -0800 From: Alexander Kozyrev To: CC: , , , , , , , , , Subject: [PATCH v8 10/11] app/testpmd: add flow queue pull operation Date: Sun, 20 Feb 2022 05:44:08 +0200 Message-ID: <20220220034409.2226860-11-akozyrev@nvidia.com> X-Mailer: git-send-email 2.18.2 In-Reply-To: <20220220034409.2226860-1-akozyrev@nvidia.com> References: <20220219041144.2145380-1-akozyrev@nvidia.com> <20220220034409.2226860-1-akozyrev@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.126.230.35] X-ClientProxiedBy: rnnvmail202.nvidia.com (10.129.68.7) To rnnvmail201.nvidia.com (10.129.68.8) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 64f2ec08-6199-4b46-5f30-08d9f4236157 X-MS-TrafficTypeDiagnostic: DM6PR12MB4060:EE_|MN2PR12MB3118:EE_ X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr,ExtAddr X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: BFWpqOCeVV2gjVm39zAQRnrIaqLIFUcFP/LaYIPd+IjBv0oSkKtEjYlFBkv/ZVZwfOa9aO+9cZdb4PPNxOnPJ4UY7F3+RB7W8NTXk5GkUSmfgQYed0mklWIvsanUmv/XSIAOOg/7cXCTQ1KBXo1XWLr6xe1vb7mdRs+69SXWfqQm70S5eGk7l70VS7+tk3pkXk8IYSQ997RiDL6Kg85+1q9dXj0SuKMfM2XrLYm/vZWyWP0Miu7wsC6yiKsA4IB3X6WyCrANzvHR+ZgXMaiF9nQs0QQN5/WJiVEoMfI6topAAqtHfVmF+aajjbe6qxKWGzqR70YCcOFPzLZ/Suwq8EvOM8e2qFneacVHyQ4Gdg1Z4E3WKGJo3iPwSaYS+WMKyd/E5gdjg1MpDHASwwSOirQSIk83vZzPCMTEHKgy0TmoTIInbT54R36iabEtFO94GhEbcuTyelGKSXi34hcuJqB/uNoj2DNFyKIQeSkuSoQR35w8uZ/5zmETbBIjsMo1dp/6tuOyD9Gs0+OZHClEoyeD/8Z+/wfcJWKqubn75AVv/rPYTNEzFsG82KrApYixoGubGJUICdNGj6r2QrTLGOZkLHoOnzoU8cZFfJZI+IDx0UG1BA+u6/LVs5740M87l9h+QzJM16oQ4lQO7t3oOvxpHV1ZK2iyZZYeNRvglbQGMNwIYm70TYLURYfnRtx8q7JZv3OUV2kPs3w2fEuLVA== X-Forefront-Antispam-Report: CIP:12.22.5.234; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:mail.nvidia.com; PTR:InfoNoRecords; CAT:NONE; SFS:(13230001)(4636009)(36840700001)(40470700004)(46966006)(186003)(16526019)(26005)(1076003)(8936002)(47076005)(2906002)(36860700001)(83380400001)(36756003)(70586007)(82310400004)(54906003)(316002)(70206006)(2616005)(426003)(4326008)(336012)(8676002)(81166007)(6666004)(7416002)(5660300002)(356005)(40460700003)(508600001)(6916009)(86362001)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Feb 2022 03:45:04.2222 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 64f2ec08-6199-4b46-5f30-08d9f4236157 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[12.22.5.234]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-CrossTenant-AuthSource: BN8NAM11FT055.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB3118 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 testpmd support for the rte_flow_pull API. Provide the command line interface for pulling operations results. Usage example: flow pull 0 queue 0 Signed-off-by: Alexander Kozyrev Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 56 +++++++++++++++- app/test-pmd/config.c | 74 +++++++++++++-------- app/test-pmd/testpmd.h | 1 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 25 +++++++ 4 files changed, 127 insertions(+), 29 deletions(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index af36975cdf..d4b72724e6 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -95,6 +95,7 @@ enum index { FLEX, QUEUE, PUSH, + PULL, /* Flex arguments */ FLEX_ITEM_INIT, @@ -142,6 +143,9 @@ enum index { /* Push arguments. */ PUSH_QUEUE, + /* Pull arguments. */ + PULL_QUEUE, + /* Table arguments. */ TABLE_CREATE, TABLE_DESTROY, @@ -2259,6 +2263,9 @@ static int parse_qo_destroy(struct context *, const struct token *, static int parse_push(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_pull(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_tunnel(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -2538,7 +2545,8 @@ static const struct token token_list[] = { TUNNEL, FLEX, QUEUE, - PUSH)), + PUSH, + PULL)), .call = parse_init, }, /* Top-level command. */ @@ -2934,6 +2942,21 @@ static const struct token token_list[] = { .args = ARGS(ARGS_ENTRY(struct buffer, queue)), }, /* Top-level command. */ + [PULL] = { + .name = "pull", + .help = "pull flow operations results", + .next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_pull, + }, + /* Sub-level commands. */ + [PULL_QUEUE] = { + .name = "queue", + .help = "specify queue id", + .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, queue)), + }, + /* Top-level command. */ [INDIRECT_ACTION] = { .name = "indirect_action", .type = "{command} {port_id} [{arg} [...]]", @@ -8786,6 +8809,34 @@ parse_push(struct context *ctx, const struct token *token, return len; } +/** Parse tokens for pull command. */ +static int +parse_pull(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command) { + if (ctx->curr != PULL) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + out->args.vc.data = (uint8_t *)out + size; + } + return len; +} + static int parse_flex(struct context *ctx, const struct token *token, const char *str, unsigned int len, @@ -10174,6 +10225,9 @@ cmd_flow_parsed(const struct buffer *in) case PUSH: port_queue_flow_push(in->port, in->queue); break; + case PULL: + port_queue_flow_pull(in->port, in->queue); + break; case INDIRECT_ACTION_CREATE: port_action_handle_create( in->port, in->args.vc.attr.group, diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index e3b5e348ab..2bd4359bfe 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -2469,14 +2469,12 @@ port_queue_flow_create(portid_t port_id, queueid_t queue_id, const struct rte_flow_action *actions) { struct rte_flow_q_ops_attr ops_attr = { .postpone = postpone }; - struct rte_flow_q_op_res comp = { 0 }; struct rte_flow *flow; struct rte_port *port; struct port_flow *pf; struct port_table *pt; uint32_t id = 0; bool found; - int ret = 0; struct rte_flow_error error = { RTE_FLOW_ERROR_TYPE_NONE, NULL, NULL }; struct rte_flow_action_age *age = age_action_get(actions); @@ -2539,16 +2537,6 @@ port_queue_flow_create(portid_t port_id, queueid_t queue_id, return port_flow_complain(&error); } - while (ret == 0) { - /* Poisoning to make sure PMDs update it in case of error. */ - memset(&error, 0x22, sizeof(error)); - ret = rte_flow_pull(port_id, queue_id, &comp, 1, &error); - if (ret < 0) { - printf("Failed to pull queue\n"); - return -EINVAL; - } - } - pf->next = port->flow_list; pf->id = id; pf->flow = flow; @@ -2563,7 +2551,6 @@ port_queue_flow_destroy(portid_t port_id, queueid_t queue_id, bool postpone, uint32_t n, const uint32_t *rule) { struct rte_flow_q_ops_attr op_attr = { .postpone = postpone }; - struct rte_flow_q_op_res comp = { 0 }; struct rte_port *port; struct port_flow **tmp; uint32_t c = 0; @@ -2599,21 +2586,6 @@ port_queue_flow_destroy(portid_t port_id, queueid_t queue_id, ret = port_flow_complain(&error); continue; } - - while (ret == 0) { - /* - * Poisoning to make sure PMD - * update it in case of error. - */ - memset(&error, 0x44, sizeof(error)); - ret = rte_flow_pull(port_id, queue_id, - &comp, 1, &error); - if (ret < 0) { - printf("Failed to pull queue\n"); - return -EINVAL; - } - } - printf("Flow rule #%u destruction enqueued\n", pf->id); *tmp = pf->next; free(pf); @@ -2654,6 +2626,52 @@ port_queue_flow_push(portid_t port_id, queueid_t queue_id) return ret; } +/** Pull queue operation results from the queue. */ +int +port_queue_flow_pull(portid_t port_id, queueid_t queue_id) +{ + struct rte_port *port; + struct rte_flow_q_op_res *res; + struct rte_flow_error error; + int ret = 0; + int success = 0; + int i; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + + if (queue_id >= port->queue_nb) { + printf("Queue #%u is invalid\n", queue_id); + return -EINVAL; + } + + res = calloc(port->queue_sz, sizeof(struct rte_flow_q_op_res)); + if (!res) { + printf("Failed to allocate memory for pulled results\n"); + return -ENOMEM; + } + + memset(&error, 0x66, sizeof(error)); + ret = rte_flow_pull(port_id, queue_id, res, + port->queue_sz, &error); + if (ret < 0) { + printf("Failed to pull a operation results\n"); + free(res); + return -EINVAL; + } + + for (i = 0; i < ret; i++) { + if (res[i].status == RTE_FLOW_Q_OP_SUCCESS) + success++; + } + printf("Queue #%u pulled %u operations (%u failed, %u succeeded)\n", + queue_id, ret, ret - success, success); + free(res); + return ret; +} + /** Create flow rule. */ int port_flow_create(portid_t port_id, diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 24a43fd82c..5ea2408a0b 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -941,6 +941,7 @@ int port_queue_flow_create(portid_t port_id, queueid_t queue_id, int port_queue_flow_destroy(portid_t port_id, queueid_t queue_id, bool postpone, uint32_t n, const uint32_t *rule); int port_queue_flow_push(portid_t port_id, queueid_t queue_id); +int port_queue_flow_pull(portid_t port_id, queueid_t queue_id); int port_flow_validate(portid_t port_id, const struct rte_flow_attr *attr, const struct rte_flow_item *pattern, diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 4f1f908d4a..5080ddb256 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -3402,6 +3402,10 @@ following sections. flow push {port_id} queue {queue_id} +- Pull all operations results from a queue:: + + flow pull {port_id} queue {queue_id} + - Create a flow rule:: flow create {port_id} @@ -3637,6 +3641,23 @@ The usual error message is shown when operations cannot be pushed:: Caught error type [...] ([...]): [...] +Pulling flow operations results +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow pull`` asks the underlying device about flow queue operations +results and return all the processed (successfully or not) operations. +It is bound to ``rte_flow_pull()``:: + + flow pull {port_id} queue {queue_id} + +If successful, it will show:: + + Queue #[...] pulled #[...] operations (#[...] failed, #[...] succeeded) + +The usual error message is shown when operations results cannot be pulled:: + + Caught error type [...] ([...]): [...] + Creating a tunnel stub for offload ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -3767,6 +3788,8 @@ Otherwise it will show an error message of the form:: This command uses the same pattern items and actions as ``flow create``, their format is described in `Creating flow rules`_. +``flow queue pull`` must be called to retrieve the operation status. + Attributes ^^^^^^^^^^ @@ -4508,6 +4531,8 @@ message is shown when a rule cannot be destroyed:: Caught error type [...] ([...]): [...] +``flow queue pull`` must be called to retrieve the operation status. + Querying flow rules ~~~~~~~~~~~~~~~~~~~ From patchwork Sun Feb 20 03:44:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kozyrev X-Patchwork-Id: 107868 X-Patchwork-Delegate: ferruh.yigit@amd.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 AE377A00C2; Sun, 20 Feb 2022 04:45:53 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B0391411C9; Sun, 20 Feb 2022 04:45:15 +0100 (CET) Received: from NAM11-CO1-obe.outbound.protection.outlook.com (mail-co1nam11on2064.outbound.protection.outlook.com [40.107.220.64]) by mails.dpdk.org (Postfix) with ESMTP id 73A0941104 for ; Sun, 20 Feb 2022 04:45:12 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=U5rLm1SBfC4KKD9GNDWnhSqbNnCRE7oCH+D1J5O2MdUoODf1Uwz7MTUm6OSyqifDohF0639IQx/D2ALHgxqegLE5+Alxh0tQSTuKENvZHojDDEbvfVr1UDG9sJS9KEZLjHP3hnsBMYLA1vz6EBAmsJuSHxl8IUE+c7HDTpN8rKV3JAtqZYoQvqVisdjv0KkoRXUApPxFyHYF+sjxX6T3P948afPl2tefjejvnXhQ1Rc6LxytEJSbsFL5vMNyHgjeKENOCo+/hpcxXJP95egYwmtDbc4Zp+u/5nFl2FKiDc9rThMvQgkXhollqVGyEMPvSPu4l/obuBO+mUIOYbRLAg== 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=s0HaPYtblCpJMwxV0PdM4eDnOsejw1owXt5LqVDBqgo=; b=ZP+wdfrCQGA6EDWX9si6jBOPFS5P6a4S98HToMrWMc60UWU1DCqPNsc0xNuXCN4bImxSqkLzwEtUmrUjKXfJfEkdjEsSh51mykYuJGzVloGS5Fdjww6TRA4v63T+rtynQ78jzrzaeOnF9ML8CXehAsYgV5GPfw5pTxMEcQGbfXbRK8RDmbVD2Mocv/4FeN17I1VgbwLvEWcwmLCj/0PigLZH+5A8o0gU2GY5WKJA6YFZKNtKadoJgTbXHNeJK8AnnnL0BN5CRexKjRwuTVu6egSPiD0F8/UCfdFR3vc6kJDMoBIOws9N+1JyCrrrrTMNsEulj2JsUCmXV4fn9e5FoA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 12.22.5.235) smtp.rcpttodomain=intel.com 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 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=s0HaPYtblCpJMwxV0PdM4eDnOsejw1owXt5LqVDBqgo=; b=boO60oKzbH0geTkXbmOxguw0Cxash7q7epHP2qV5KNPF3LpgRjwuS9KUKsi0j3ULB1wPkIHVlSA2EiGF4vZOT6/kw9MjUtADaBAqZ0vQ6pe5csVTf5lolHgYhfdnEhUHNJsOFmPk37NI6NpGm0Bpl5QW9NLkjIRkRMqGClMbbng4pwLiB/Q4tPbgrtOk9aL8ykESPX4rHbw9tn85hor0dPlYtygjqhc4pGFrvpCuOiro4Y4BX7J00jthymwgGexsDpwLiRBgb9r3zTmV7bOOAxODlR1SrjabiAHm3roZGBYO/puLR0arBFfJ23kawq9EtQE/wHILQifYcZg+KdSlfw== Received: from DM6PR12MB4234.namprd12.prod.outlook.com (2603:10b6:5:213::18) by BY5PR12MB4067.namprd12.prod.outlook.com (2603:10b6:a03:212::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.14; Sun, 20 Feb 2022 03:45:10 +0000 Received: from DM3PR12CA0079.namprd12.prod.outlook.com (2603:10b6:0:57::23) by DM6PR12MB4234.namprd12.prod.outlook.com (2603:10b6:5:213::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.17; Sun, 20 Feb 2022 03:45:08 +0000 Received: from DM6NAM11FT037.eop-nam11.prod.protection.outlook.com (2603:10b6:0:57:cafe::da) by DM3PR12CA0079.outlook.office365.com (2603:10b6:0:57::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4995.16 via Frontend Transport; Sun, 20 Feb 2022 03:45:08 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 12.22.5.235) 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 12.22.5.235 as permitted sender) receiver=protection.outlook.com; client-ip=12.22.5.235; helo=mail.nvidia.com; Received: from mail.nvidia.com (12.22.5.235) by DM6NAM11FT037.mail.protection.outlook.com (10.13.172.122) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4995.15 via Frontend Transport; Sun, 20 Feb 2022 03:45:08 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by DRHQMAIL107.nvidia.com (10.27.9.16) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Sun, 20 Feb 2022 03:45:05 +0000 Received: from pegasus01.mtr.labs.mlnx (10.126.230.35) 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.9; Sat, 19 Feb 2022 19:45:02 -0800 From: Alexander Kozyrev To: CC: , , , , , , , , , Subject: [PATCH v8 11/11] app/testpmd: add async indirect actions operations Date: Sun, 20 Feb 2022 05:44:09 +0200 Message-ID: <20220220034409.2226860-12-akozyrev@nvidia.com> X-Mailer: git-send-email 2.18.2 In-Reply-To: <20220220034409.2226860-1-akozyrev@nvidia.com> References: <20220219041144.2145380-1-akozyrev@nvidia.com> <20220220034409.2226860-1-akozyrev@nvidia.com> MIME-Version: 1.0 X-Originating-IP: [10.126.230.35] X-ClientProxiedBy: rnnvmail202.nvidia.com (10.129.68.7) To rnnvmail201.nvidia.com (10.129.68.8) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 423f5593-7d2e-43f3-aea1-08d9f42363da X-MS-TrafficTypeDiagnostic: DM6PR12MB4234:EE_|BY5PR12MB4067:EE_ X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr,ExtAddr X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: CK4Qq2Yq7/fxAVkIkkPFn5JYOlFoPCVQtGANqv7gnV3oS36MCfCcxSsxSLR4vFIE6EKUirAf2URxt4F9guXxH6sjNvr03omodarVxl4opC4tV4UXK/BHX6IN0dWDW/prREKdK2PpNpmjHnCk3pY2SEtE80ogcXUse+VC/unILLYsGbVZdEyA46d1rXQPMfO+98Dn5a8ILY6ov5WscfmPOngnK3llgIX+wjez09ih/v8/16Q/MobpdcIiYSMJtFVMSJlffJVYVmEqlDOZ8uJqbjkgXqxnQasu9MIYOVUeoMlM42ejjHWTtaOUFpS+qOt9BqkjgOw0MG23Caw7mePpF4KUYWlIKtKnumBbSfvaCfpKqRaig157b5EntolT0igZExI7KsRCM6e50DQrN12aiCQr1Zbe1lObGDnALCc8BDtWXB1KFMaw7+1flTHExTzpGzuNMXtywpNmNZKjkNmWLQIbabPWHwE4nrXRTOsxvRZ89ZZ9R35Xfn5WCLu/gWfr0ij9T8J2JoSroYSYanqRpQ8HlqcE1l1kZrIgwaNdGi5zPcvBnwCyJTtpndNIi06MjOHf6YYmnUGSBeco9yquhBpUawgL9YhF+n3+v8G3B4jkH2D9P7iogosXh14mnjjiLm90g8aJNj1TfLzcXpdOf0rE8crBD4/fzcpj5JAkZKz6oEVIQSaa33JN6MJ+ZMIaI+SrKNw5HMzE+gzwSgLuPA== X-Forefront-Antispam-Report: CIP:12.22.5.235; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:mail.nvidia.com; PTR:InfoNoRecords; CAT:NONE; SFS:(13230001)(4636009)(36840700001)(46966006)(40470700004)(186003)(26005)(16526019)(426003)(336012)(47076005)(40460700003)(1076003)(2616005)(356005)(81166007)(36756003)(2906002)(5660300002)(8936002)(7416002)(30864003)(508600001)(70586007)(70206006)(4326008)(82310400004)(8676002)(83380400001)(36860700001)(86362001)(316002)(6916009)(54906003)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Feb 2022 03:45:08.4538 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 423f5593-7d2e-43f3-aea1-08d9f42363da X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[12.22.5.235]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-CrossTenant-AuthSource: DM6NAM11FT037.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY5PR12MB4067 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 testpmd support for the rte_flow_async_action_handle API. Provide the command line interface for operations dequeue. Usage example: flow queue 0 indirect_action 0 create action_id 9 ingress postpone yes action rss / end flow queue 0 indirect_action 0 update action_id 9 action queue index 0 / end flow queue 0 indirect_action 0 destroy action_id 9 Signed-off-by: Alexander Kozyrev Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 276 ++++++++++++++++++++ app/test-pmd/config.c | 131 ++++++++++ app/test-pmd/testpmd.h | 10 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 65 +++++ 4 files changed, 482 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index d4b72724e6..b5f1191e55 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -127,6 +127,7 @@ enum index { /* Queue arguments. */ QUEUE_CREATE, QUEUE_DESTROY, + QUEUE_INDIRECT_ACTION, /* Queue create arguments. */ QUEUE_CREATE_ID, @@ -140,6 +141,26 @@ enum index { QUEUE_DESTROY_ID, QUEUE_DESTROY_POSTPONE, + /* Queue indirect action arguments */ + QUEUE_INDIRECT_ACTION_CREATE, + QUEUE_INDIRECT_ACTION_UPDATE, + QUEUE_INDIRECT_ACTION_DESTROY, + + /* Queue indirect action create arguments */ + QUEUE_INDIRECT_ACTION_CREATE_ID, + QUEUE_INDIRECT_ACTION_INGRESS, + QUEUE_INDIRECT_ACTION_EGRESS, + QUEUE_INDIRECT_ACTION_TRANSFER, + QUEUE_INDIRECT_ACTION_CREATE_POSTPONE, + QUEUE_INDIRECT_ACTION_SPEC, + + /* Queue indirect action update arguments */ + QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE, + + /* Queue indirect action destroy arguments */ + QUEUE_INDIRECT_ACTION_DESTROY_ID, + QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE, + /* Push arguments. */ PUSH_QUEUE, @@ -1135,6 +1156,7 @@ static const enum index next_table_destroy_attr[] = { static const enum index next_queue_subcmd[] = { QUEUE_CREATE, QUEUE_DESTROY, + QUEUE_INDIRECT_ACTION, ZERO, }; @@ -1144,6 +1166,36 @@ static const enum index next_queue_destroy_attr[] = { ZERO, }; +static const enum index next_qia_subcmd[] = { + QUEUE_INDIRECT_ACTION_CREATE, + QUEUE_INDIRECT_ACTION_UPDATE, + QUEUE_INDIRECT_ACTION_DESTROY, + ZERO, +}; + +static const enum index next_qia_create_attr[] = { + QUEUE_INDIRECT_ACTION_CREATE_ID, + QUEUE_INDIRECT_ACTION_INGRESS, + QUEUE_INDIRECT_ACTION_EGRESS, + QUEUE_INDIRECT_ACTION_TRANSFER, + QUEUE_INDIRECT_ACTION_CREATE_POSTPONE, + QUEUE_INDIRECT_ACTION_SPEC, + ZERO, +}; + +static const enum index next_qia_update_attr[] = { + QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE, + QUEUE_INDIRECT_ACTION_SPEC, + ZERO, +}; + +static const enum index next_qia_destroy_attr[] = { + QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE, + QUEUE_INDIRECT_ACTION_DESTROY_ID, + END, + ZERO, +}; + static const enum index next_ia_create_attr[] = { INDIRECT_ACTION_CREATE_ID, INDIRECT_ACTION_INGRESS, @@ -2260,6 +2312,12 @@ static int parse_qo(struct context *, const struct token *, static int parse_qo_destroy(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_qia(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); +static int parse_qia_destroy(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_push(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -2873,6 +2931,13 @@ static const struct token token_list[] = { .args = ARGS(ARGS_ENTRY(struct buffer, queue)), .call = parse_qo_destroy, }, + [QUEUE_INDIRECT_ACTION] = { + .name = "indirect_action", + .help = "queue indirect actions", + .next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, queue)), + .call = parse_qia, + }, /* Queue arguments. */ [QUEUE_TEMPLATE_TABLE] = { .name = "template table", @@ -2926,6 +2991,90 @@ static const struct token token_list[] = { args.destroy.rule)), .call = parse_qo_destroy, }, + /* Queue indirect action arguments */ + [QUEUE_INDIRECT_ACTION_CREATE] = { + .name = "create", + .help = "create indirect action", + .next = NEXT(next_qia_create_attr), + .call = parse_qia, + }, + [QUEUE_INDIRECT_ACTION_UPDATE] = { + .name = "update", + .help = "update indirect action", + .next = NEXT(next_qia_update_attr, + NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)), + .call = parse_qia, + }, + [QUEUE_INDIRECT_ACTION_DESTROY] = { + .name = "destroy", + .help = "destroy indirect action", + .next = NEXT(next_qia_destroy_attr), + .call = parse_qia_destroy, + }, + /* Indirect action destroy arguments. */ + [QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = { + .name = "postpone", + .help = "postpone destroy operation", + .next = NEXT(next_qia_destroy_attr, + NEXT_ENTRY(COMMON_BOOLEAN)), + .args = ARGS(ARGS_ENTRY(struct buffer, postpone)), + }, + [QUEUE_INDIRECT_ACTION_DESTROY_ID] = { + .name = "action_id", + .help = "specify a indirect action id to destroy", + .next = NEXT(next_qia_destroy_attr, + NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), + .args = ARGS(ARGS_ENTRY_PTR(struct buffer, + args.ia_destroy.action_id)), + .call = parse_qia_destroy, + }, + /* Indirect action update arguments. */ + [QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = { + .name = "postpone", + .help = "postpone update operation", + .next = NEXT(next_qia_update_attr, + NEXT_ENTRY(COMMON_BOOLEAN)), + .args = ARGS(ARGS_ENTRY(struct buffer, postpone)), + }, + /* Indirect action create arguments. */ + [QUEUE_INDIRECT_ACTION_CREATE_ID] = { + .name = "action_id", + .help = "specify a indirect action id to create", + .next = NEXT(next_qia_create_attr, + NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)), + }, + [QUEUE_INDIRECT_ACTION_INGRESS] = { + .name = "ingress", + .help = "affect rule to ingress", + .next = NEXT(next_qia_create_attr), + .call = parse_qia, + }, + [QUEUE_INDIRECT_ACTION_EGRESS] = { + .name = "egress", + .help = "affect rule to egress", + .next = NEXT(next_qia_create_attr), + .call = parse_qia, + }, + [QUEUE_INDIRECT_ACTION_TRANSFER] = { + .name = "transfer", + .help = "affect rule to transfer", + .next = NEXT(next_qia_create_attr), + .call = parse_qia, + }, + [QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = { + .name = "postpone", + .help = "postpone create operation", + .next = NEXT(next_qia_create_attr, + NEXT_ENTRY(COMMON_BOOLEAN)), + .args = ARGS(ARGS_ENTRY(struct buffer, postpone)), + }, + [QUEUE_INDIRECT_ACTION_SPEC] = { + .name = "action", + .help = "specify action to create indirect handle", + .next = NEXT(next_action), + }, /* Top-level command. */ [PUSH] = { .name = "push", @@ -6501,6 +6650,110 @@ parse_ia_destroy(struct context *ctx, const struct token *token, return len; } +/** Parse tokens for indirect action commands. */ +static int +parse_qia(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command) { + if (ctx->curr != QUEUE) + return -1; + if (sizeof(*out) > size) + return -1; + out->args.vc.data = (uint8_t *)out + size; + return len; + } + switch (ctx->curr) { + case QUEUE_INDIRECT_ACTION: + return len; + case QUEUE_INDIRECT_ACTION_CREATE: + case QUEUE_INDIRECT_ACTION_UPDATE: + out->args.vc.actions = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + out->args.vc.attr.group = UINT32_MAX; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + return len; + case QUEUE_INDIRECT_ACTION_EGRESS: + out->args.vc.attr.egress = 1; + return len; + case QUEUE_INDIRECT_ACTION_INGRESS: + out->args.vc.attr.ingress = 1; + return len; + case QUEUE_INDIRECT_ACTION_TRANSFER: + out->args.vc.attr.transfer = 1; + return len; + case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE: + return len; + default: + return -1; + } +} + +/** Parse tokens for indirect action destroy command. */ +static int +parse_qia_destroy(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + uint32_t *action_id; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command || out->command == QUEUE) { + if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + out->args.ia_destroy.action_id = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + return len; + } + switch (ctx->curr) { + case QUEUE_INDIRECT_ACTION: + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + return len; + case QUEUE_INDIRECT_ACTION_DESTROY_ID: + action_id = out->args.ia_destroy.action_id + + out->args.ia_destroy.action_id_n++; + if ((uint8_t *)action_id > (uint8_t *)out + size) + return -1; + ctx->objdata = 0; + ctx->object = action_id; + ctx->objmask = NULL; + return len; + case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE: + return len; + default: + return -1; + } +} + /** Parse tokens for meter policy action commands. */ static int parse_mp(struct context *ctx, const struct token *token, @@ -10228,6 +10481,29 @@ cmd_flow_parsed(const struct buffer *in) case PULL: port_queue_flow_pull(in->port, in->queue); break; + case QUEUE_INDIRECT_ACTION_CREATE: + port_queue_action_handle_create( + in->port, in->queue, in->postpone, + in->args.vc.attr.group, + &((const struct rte_flow_indir_action_conf) { + .ingress = in->args.vc.attr.ingress, + .egress = in->args.vc.attr.egress, + .transfer = in->args.vc.attr.transfer, + }), + in->args.vc.actions); + break; + case QUEUE_INDIRECT_ACTION_DESTROY: + port_queue_action_handle_destroy(in->port, + in->queue, in->postpone, + in->args.ia_destroy.action_id_n, + in->args.ia_destroy.action_id); + break; + case QUEUE_INDIRECT_ACTION_UPDATE: + port_queue_action_handle_update(in->port, + in->queue, in->postpone, + in->args.vc.attr.group, + in->args.vc.actions); + break; case INDIRECT_ACTION_CREATE: port_action_handle_create( in->port, in->args.vc.attr.group, diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index 2bd4359bfe..53a848cf84 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -2598,6 +2598,137 @@ port_queue_flow_destroy(portid_t port_id, queueid_t queue_id, return ret; } +/** Enqueue indirect action create operation. */ +int +port_queue_action_handle_create(portid_t port_id, uint32_t queue_id, + bool postpone, uint32_t id, + const struct rte_flow_indir_action_conf *conf, + const struct rte_flow_action *action) +{ + const struct rte_flow_q_ops_attr attr = { .postpone = postpone}; + struct rte_port *port; + struct port_indirect_action *pia; + int ret; + struct rte_flow_error error; + + ret = action_alloc(port_id, id, &pia); + if (ret) + return ret; + + port = &ports[port_id]; + if (queue_id >= port->queue_nb) { + printf("Queue #%u is invalid\n", queue_id); + return -EINVAL; + } + + if (action->type == RTE_FLOW_ACTION_TYPE_AGE) { + struct rte_flow_action_age *age = + (struct rte_flow_action_age *)(uintptr_t)(action->conf); + + pia->age_type = ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION; + age->context = &pia->age_type; + } + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x88, sizeof(error)); + pia->handle = rte_flow_async_action_handle_create(port_id, queue_id, + &attr, conf, action, NULL, &error); + if (!pia->handle) { + uint32_t destroy_id = pia->id; + port_queue_action_handle_destroy(port_id, queue_id, + postpone, 1, &destroy_id); + return port_flow_complain(&error); + } + pia->type = action->type; + printf("Indirect action #%u creation queued\n", pia->id); + return 0; +} + +/** Enqueue indirect action destroy operation. */ +int +port_queue_action_handle_destroy(portid_t port_id, + uint32_t queue_id, bool postpone, + uint32_t n, const uint32_t *actions) +{ + const struct rte_flow_q_ops_attr attr = { .postpone = postpone}; + struct rte_port *port; + struct port_indirect_action **tmp; + uint32_t c = 0; + int ret = 0; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + + if (queue_id >= port->queue_nb) { + printf("Queue #%u is invalid\n", queue_id); + return -EINVAL; + } + + tmp = &port->actions_list; + while (*tmp) { + uint32_t i; + + for (i = 0; i != n; ++i) { + struct rte_flow_error error; + struct port_indirect_action *pia = *tmp; + + if (actions[i] != pia->id) + continue; + /* + * Poisoning to make sure PMDs update it in case + * of error. + */ + memset(&error, 0x99, sizeof(error)); + + if (pia->handle && + rte_flow_async_action_handle_destroy(port_id, + queue_id, &attr, pia->handle, NULL, &error)) { + ret = port_flow_complain(&error); + continue; + } + *tmp = pia->next; + printf("Indirect action #%u destruction queued\n", + pia->id); + free(pia); + break; + } + if (i == n) + tmp = &(*tmp)->next; + ++c; + } + return ret; +} + +/** Enqueue indirect action update operation. */ +int +port_queue_action_handle_update(portid_t port_id, + uint32_t queue_id, bool postpone, uint32_t id, + const struct rte_flow_action *action) +{ + const struct rte_flow_q_ops_attr attr = { .postpone = postpone}; + struct rte_port *port; + struct rte_flow_error error; + struct rte_flow_action_handle *action_handle; + + action_handle = port_action_handle_get_by_id(port_id, id); + if (!action_handle) + return -EINVAL; + + port = &ports[port_id]; + if (queue_id >= port->queue_nb) { + printf("Queue #%u is invalid\n", queue_id); + return -EINVAL; + } + + if (rte_flow_async_action_handle_update(port_id, queue_id, &attr, + action_handle, action, NULL, &error)) { + return port_flow_complain(&error); + } + printf("Indirect action #%u update queued\n", id); + return 0; +} + /** Push all the queue operations in the queue to the NIC. */ int port_queue_flow_push(portid_t port_id, queueid_t queue_id) diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 5ea2408a0b..31f766c965 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -940,6 +940,16 @@ int port_queue_flow_create(portid_t port_id, queueid_t queue_id, const struct rte_flow_action *actions); int port_queue_flow_destroy(portid_t port_id, queueid_t queue_id, bool postpone, uint32_t n, const uint32_t *rule); +int port_queue_action_handle_create(portid_t port_id, uint32_t queue_id, + bool postpone, uint32_t id, + const struct rte_flow_indir_action_conf *conf, + const struct rte_flow_action *action); +int port_queue_action_handle_destroy(portid_t port_id, + uint32_t queue_id, bool postpone, + uint32_t n, const uint32_t *action); +int port_queue_action_handle_update(portid_t port_id, uint32_t queue_id, + bool postpone, uint32_t id, + const struct rte_flow_action *action); int port_queue_flow_push(portid_t port_id, queueid_t queue_id); int port_queue_flow_pull(portid_t port_id, queueid_t queue_id); int port_flow_validate(portid_t port_id, diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 5080ddb256..1083c6d538 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -4792,6 +4792,31 @@ port 0:: testpmd> flow indirect_action 0 create action_id \ ingress action rss queues 0 1 end / end +Enqueueing creation of indirect actions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow queue indirect_action create`` adds creation operation of an indirect +action to a queue. It is bound to ``rte_flow_async_action_handle_create()``:: + + flow queue {port_id} create {queue_id} [postpone {boolean}] + table {table_id} item_template {item_template_id} + action_template {action_template_id} + pattern {item} [/ {item} [...]] / end + actions {action} [/ {action} [...]] / end + +If successful, it will show:: + + Indirect action #[...] creation queued + +Otherwise it will show an error message of the form:: + + Caught error type [...] ([...]): [...] + +This command uses the same parameters as ``flow indirect_action create``, +described in `Creating indirect actions`_. + +``flow queue pull`` must be called to retrieve the operation status. + Updating indirect actions ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -4821,6 +4846,25 @@ Update indirect rss action having id 100 on port 0 with rss to queues 0 and 3 testpmd> flow indirect_action 0 update 100 action rss queues 0 3 end / end +Enqueueing update of indirect actions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow queue indirect_action update`` adds update operation for an indirect +action to a queue. It is bound to ``rte_flow_async_action_handle_update()``:: + + flow queue {port_id} indirect_action {queue_id} update + {indirect_action_id} [postpone {boolean}] action {action} / end + +If successful, it will show:: + + Indirect action #[...] update queued + +Otherwise it will show an error message of the form:: + + Caught error type [...] ([...]): [...] + +``flow queue pull`` must be called to retrieve the operation status. + Destroying indirect actions ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -4844,6 +4888,27 @@ Destroy indirect actions having id 100 & 101:: testpmd> flow indirect_action 0 destroy action_id 100 action_id 101 +Enqueueing destruction of indirect actions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow queue indirect_action destroy`` adds destruction operation to destroy +one or more indirect actions from their indirect action IDs (as returned by +``flow queue {port_id} indirect_action {queue_id} create``) to a queue. +It is bound to ``rte_flow_async_action_handle_destroy()``:: + + flow queue {port_id} indirect_action {queue_id} destroy + [postpone {boolean}] action_id {indirect_action_id} [...] + +If successful, it will show:: + + Indirect action #[...] destruction queued + +Otherwise it will show an error message of the form:: + + Caught error type [...] ([...]): [...] + +``flow queue pull`` must be called to retrieve the operation status. + Query indirect actions ~~~~~~~~~~~~~~~~~~~~~~