get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/108207/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 108207,
    "url": "http://patches.dpdk.org/api/patches/108207/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20220224031029.14049-8-suanmingm@nvidia.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20220224031029.14049-8-suanmingm@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220224031029.14049-8-suanmingm@nvidia.com",
    "date": "2022-02-24T03:10:22",
    "name": "[v3,07/14] net/mlx5: add table management",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "c9ead13fcfe6654f3d488bc6602ee897e223c51c",
    "submitter": {
        "id": 1887,
        "url": "http://patches.dpdk.org/api/people/1887/?format=api",
        "name": "Suanming Mou",
        "email": "suanmingm@nvidia.com"
    },
    "delegate": {
        "id": 3268,
        "url": "http://patches.dpdk.org/api/users/3268/?format=api",
        "username": "rasland",
        "first_name": "Raslan",
        "last_name": "Darawsheh",
        "email": "rasland@nvidia.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20220224031029.14049-8-suanmingm@nvidia.com/mbox/",
    "series": [
        {
            "id": 21839,
            "url": "http://patches.dpdk.org/api/series/21839/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=21839",
            "date": "2022-02-24T03:10:16",
            "name": "net/mlx5: add hardware steering",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/21839/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/108207/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/108207/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "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])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 5928FA0353;\n\tThu, 24 Feb 2022 04:11:24 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 8695E41168;\n\tThu, 24 Feb 2022 04:11:06 +0100 (CET)",
            "from NAM11-CO1-obe.outbound.protection.outlook.com\n (mail-co1nam11on2072.outbound.protection.outlook.com [40.107.220.72])\n by mails.dpdk.org (Postfix) with ESMTP id F13854116E\n for <dev@dpdk.org>; Thu, 24 Feb 2022 04:11:02 +0100 (CET)",
            "from CO2PR04CA0183.namprd04.prod.outlook.com (2603:10b6:104:5::13)\n by BY5PR12MB4870.namprd12.prod.outlook.com (2603:10b6:a03:1de::9) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5017.21; Thu, 24 Feb\n 2022 03:11:00 +0000",
            "from CO1NAM11FT028.eop-nam11.prod.protection.outlook.com\n (2603:10b6:104:5:cafe::bd) by CO2PR04CA0183.outlook.office365.com\n (2603:10b6:104:5::13) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5017.21 via Frontend\n Transport; Thu, 24 Feb 2022 03:11:00 +0000",
            "from mail.nvidia.com (12.22.5.236) by\n CO1NAM11FT028.mail.protection.outlook.com (10.13.175.214) with Microsoft SMTP\n Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id\n 15.20.5017.22 via Frontend Transport; Thu, 24 Feb 2022 03:10:59 +0000",
            "from rnnvmail201.nvidia.com (10.129.68.8) by DRHQMAIL109.nvidia.com\n (10.27.9.19) with Microsoft SMTP Server (TLS) id 15.0.1497.18;\n Thu, 24 Feb 2022 03:10:58 +0000",
            "from nvidia.com (10.126.231.35) by rnnvmail201.nvidia.com\n (10.129.68.8) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.9; Wed, 23 Feb 2022\n 19:10:56 -0800"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=FJ6f9k8VT7Nht08jUSkBlF2oCw5Ol8mdwad83fPJijuhAnydnn5VzjunyCWzIQiUcdBqfnS2l4PZzbLH51WpABMQxJgGwKPssnfdiRuD12Zy0QJxnbY/E/zjsf0yXg8mBLa6mE3i5BgynH8Pps1K2TDKLBOpqG0XuN0S7vCRa1cIMsi67JmFjZJhdTtCYV9irRZcjrWeFoozYBfNx/Olv/d4CeGLhJs1IewFTveHulYQRjEq+9+B2GhUP96hYGQWBLcJgE0xMUKIP3ffSGPpvbKC95IYtvTWWatL/m6Ksxed3d+CJyUGDK02I+V+dWgD3l2qTGel/9AoFSLt/CyCRA==",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector9901;\n 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;\n bh=lYnaRw9AaGbOnMUoL1/FLO8u5KOTr99V5NHXUFj3dyI=;\n b=L4wegBTQZan5UWpJr4rfoerKjlhB+KhGLq+gQp0j59XlnOXI9FkdJuD7m9N8K8RORBe8wgds0hnbIZunNTlJiMLtj3ZltcheJ53mFSKLV01R0cxdQtXqxT4oyxGtw9BCr23yQ38t4IbiAII9v8qiHHc1+yZwx9x9XGQsD4tP0IO5bPSQpt9kl6ndbhIZhKe2A3ClZnls+QLJJfiI2fpMgfLpKcNp67I2VWuyDIDBJnALKS5wXH7G9324XuiyamFqJCplWVNyvzLT2jCKS80z21juAfGT/DpFrzv420hIoV3VMmHfSgbCbQ6ne5Xf9IN15SP5sGrlVZ5JjZbKx7hPJQ==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass (sender ip is\n 12.22.5.236) smtp.rcpttodomain=dpdk.org smtp.mailfrom=nvidia.com; dmarc=pass\n (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none\n (message not signed); arc=none",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com;\n s=selector2;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=lYnaRw9AaGbOnMUoL1/FLO8u5KOTr99V5NHXUFj3dyI=;\n b=crZdf7ebOuiOrRB1G0x6fu3VlRrR3kntNuKrN36C4e4gyq/zgN6j4E/xMOxdZ+qbpgskw8iSlyUUMMF3GP6IeTtdQT5d+h2rQWa8AVva7lCGdT8NC37+5w9DhwmymzPKqmhsUhyAR7xKLzhkkFjtf62cE4y0VfLxuIcrh0TB70U0iFAmK0ERnEX94B+xTIs6wson39SUNLyr+/wNknnO8ouh3S/oDbQUbhpjKd5qVNl3GeA5a2sMoNO4gpWsEL8KlW2/0l/Xu094E0WFYBj9WlPRW4CWjVO7aQHFsiNHnyzCmIeySU9p0YjUU/XyQzJvvTzGW09GeTuRas3/+fV0ZQ==",
        "X-MS-Exchange-Authentication-Results": "spf=pass (sender IP is 12.22.5.236)\n smtp.mailfrom=nvidia.com; dkim=none (message not signed)\n header.d=none;dmarc=pass action=none header.from=nvidia.com;",
        "Received-SPF": "Pass (protection.outlook.com: domain of nvidia.com designates\n 12.22.5.236 as permitted sender) receiver=protection.outlook.com;\n client-ip=12.22.5.236; helo=mail.nvidia.com;",
        "From": "Suanming Mou <suanmingm@nvidia.com>",
        "To": "<viacheslavo@nvidia.com>, <matan@nvidia.com>",
        "CC": "<rasland@nvidia.com>, <orika@nvidia.com>, <dev@dpdk.org>",
        "Subject": "[PATCH v3 07/14] net/mlx5: add table management",
        "Date": "Thu, 24 Feb 2022 05:10:22 +0200",
        "Message-ID": "<20220224031029.14049-8-suanmingm@nvidia.com>",
        "X-Mailer": "git-send-email 2.18.1",
        "In-Reply-To": "<20220224031029.14049-1-suanmingm@nvidia.com>",
        "References": "<20220210162926.20436-1-suanmingm@nvidia.com>\n <20220224031029.14049-1-suanmingm@nvidia.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[10.126.231.35]",
        "X-ClientProxiedBy": "rnnvmail201.nvidia.com (10.129.68.8) To\n rnnvmail201.nvidia.com (10.129.68.8)",
        "X-EOPAttributedMessage": "0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-Office365-Filtering-Correlation-Id": "5e3147cb-a01c-49e4-e24c-08d9f7434867",
        "X-MS-TrafficTypeDiagnostic": "BY5PR12MB4870:EE_",
        "X-Microsoft-Antispam-PRVS": "\n <BY5PR12MB4870A2A6421C497DDA6C254CC13D9@BY5PR12MB4870.namprd12.prod.outlook.com>",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n 6yinfh9d1HBjxcLF/b9Y2uW9Bh0Gn1uDgn7PPbATSlTxrypcN0sDLPXfTNldDAakocNz845Cb0xScAlHbHnW7t6i29Z/1OzWSCkcz69GASTDWv23Z1QUPUGhS5qwmFfPSQon4bzuYBWpEPrQJzBYq9Ahn6bjzWi9sfXNTiDXlPzsh0oVMiAsJadtHD7es/TaBDjk6NgzModnhfkxXBgEyOwTAh36dsKrn0j2fO4UDUDOXYiemvWqa7w1kVxqENXs/MPwDdsSGRoFEvo7P7rCmiOcnBvXg8/G7FIodLK9+9Dq555Y3MGCp4nRiZxtB41AfvS7VlxTi02fpbMNqrE+MK3xbD/l/19TfGq3zBZS+xuARI1hCfeIajn/ss8c2UzuPqBKKf8pAJpYd84NI4z50QzzY+I2WqcIOVIF5CYbVPHiAX84zByiMZb+FcC0SD9OIKP8fGd1JeA3ulzOqSeCLuEkNCCq3K0wdp3ktfJeErJMBaBnBbT7c+MBZ2F/+VvfDuUCKLIxEVjGo+6xjt37uY1m25PcMQ87gASIbLI+LvIwURZzl7bvb6X7oW21nzOQSX24FOkW2YYo4H6O5XKsVaA5X2/yssEn+P8orC/ev8OMcYShfGfRf1bxQLwS77PY4c67zOOB4S3SqBfvEfWszqk8lB/0gShEbhDc0eklkHtLzEaHXZsu46bqXpDP7WolG14J9AWtMF3SnB0H6/b8hzX/zzJQqfM8A0iVXe0IZAEZUiMX8Ki0pHyJWRKi8u7M",
        "X-Forefront-Antispam-Report": "CIP:12.22.5.236; CTRY:US; LANG:en; SCL:1; SRV:;\n IPV:CAL; SFV:NSPM; H:mail.nvidia.com; PTR:InfoNoRecords; CAT:NONE;\n SFS:(13230001)(4636009)(36840700001)(46966006)(40470700004)(5660300002)(30864003)(16526019)(186003)(336012)(1076003)(426003)(2616005)(6286002)(82310400004)(2906002)(40460700003)(86362001)(8936002)(508600001)(26005)(6666004)(7696005)(6636002)(36756003)(356005)(316002)(55016003)(36860700001)(4326008)(47076005)(83380400001)(54906003)(8676002)(70206006)(70586007)(81166007)(110136005)(36900700001)(309714004);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "Nvidia.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "24 Feb 2022 03:10:59.7866 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 5e3147cb-a01c-49e4-e24c-08d9f7434867",
        "X-MS-Exchange-CrossTenant-Id": "43083d15-7273-40c1-b7db-39efd9ccc17a",
        "X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp": "\n TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[12.22.5.236];\n Helo=[mail.nvidia.com]",
        "X-MS-Exchange-CrossTenant-AuthSource": "\n CO1NAM11FT028.eop-nam11.prod.protection.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "BY5PR12MB4870",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "Flow table is a group of flows with the same matching criteria\nand the same actions defined for them. The table defines rules\nthat have the same matching fields but with different matching\nvalues. For example, matching on 5 tuple, the table will be\n(IPv4 source + IPv4 dest + s_port + d_port + next_proto)\nwhile the values for each rule will be different.\n\nThe templates' relevant matching criteria and action instances\nwill be created in the table creation and saved in the table.\nAs table attributes indicate the supported flow number, the flow\nmemory will also be allocated at the same time.\n\nThis commit adds the table management functions.\n\nSigned-off-by: Suanming Mou <suanmingm@nvidia.com>\nAcked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>\n---\n drivers/net/mlx5/mlx5.c         |  45 ++-\n drivers/net/mlx5/mlx5.h         |  21 +-\n drivers/net/mlx5/mlx5_flow.c    |  93 ++++++\n drivers/net/mlx5/mlx5_flow.h    |  73 +++++\n drivers/net/mlx5/mlx5_flow_hw.c | 525 ++++++++++++++++++++++++++++++++\n 5 files changed, 751 insertions(+), 6 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex 0079aa83c1..7611fdd62b 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -1607,12 +1607,46 @@ void\n mlx5_free_table_hash_list(struct mlx5_priv *priv)\n {\n \tstruct mlx5_dev_ctx_shared *sh = priv->sh;\n-\n-\tif (!sh->flow_tbls)\n+\tstruct mlx5_hlist **tbls = (priv->sh->config.dv_flow_en == 2) ?\n+\t\t\t\t   &sh->groups : &sh->flow_tbls;\n+\tif (*tbls == NULL)\n \t\treturn;\n-\tmlx5_hlist_destroy(sh->flow_tbls);\n-\tsh->flow_tbls = NULL;\n+\tmlx5_hlist_destroy(*tbls);\n+\t*tbls = NULL;\n+}\n+\n+#if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)\n+/**\n+ * Allocate HW steering group hash list.\n+ *\n+ * @param[in] priv\n+ *   Pointer to the private device data structure.\n+ */\n+static int\n+mlx5_alloc_hw_group_hash_list(struct mlx5_priv *priv)\n+{\n+\tint err = 0;\n+\tstruct mlx5_dev_ctx_shared *sh = priv->sh;\n+\tchar s[MLX5_NAME_SIZE];\n+\n+\tMLX5_ASSERT(sh);\n+\tsnprintf(s, sizeof(s), \"%s_flow_groups\", priv->sh->ibdev_name);\n+\tsh->groups = mlx5_hlist_create\n+\t\t\t(s, MLX5_FLOW_TABLE_HLIST_ARRAY_SIZE,\n+\t\t\t false, true, sh,\n+\t\t\t flow_hw_grp_create_cb,\n+\t\t\t flow_hw_grp_match_cb,\n+\t\t\t flow_hw_grp_remove_cb,\n+\t\t\t flow_hw_grp_clone_cb,\n+\t\t\t flow_hw_grp_clone_free_cb);\n+\tif (!sh->groups) {\n+\t\tDRV_LOG(ERR, \"flow groups with hash creation failed.\");\n+\t\terr = ENOMEM;\n+\t}\n+\treturn err;\n }\n+#endif\n+\n \n /**\n  * Initialize flow table hash list and create the root tables entry\n@@ -1628,11 +1662,14 @@ int\n mlx5_alloc_table_hash_list(struct mlx5_priv *priv __rte_unused)\n {\n \tint err = 0;\n+\n \t/* Tables are only used in DV and DR modes. */\n #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)\n \tstruct mlx5_dev_ctx_shared *sh = priv->sh;\n \tchar s[MLX5_NAME_SIZE];\n \n+\tif (priv->sh->config.dv_flow_en == 2)\n+\t\treturn mlx5_alloc_hw_group_hash_list(priv);\n \tMLX5_ASSERT(sh);\n \tsnprintf(s, sizeof(s), \"%s_flow_table\", priv->sh->ibdev_name);\n \tsh->flow_tbls = mlx5_hlist_create(s, MLX5_FLOW_TABLE_HLIST_ARRAY_SIZE,\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 156b8613d8..f523173ad5 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -64,7 +64,9 @@ enum mlx5_ipool_index {\n \tMLX5_IPOOL_PUSH_VLAN, /* Pool for push vlan resource. */\n \tMLX5_IPOOL_TAG, /* Pool for tag resource. */\n \tMLX5_IPOOL_PORT_ID, /* Pool for port id resource. */\n-\tMLX5_IPOOL_JUMP, /* Pool for jump resource. */\n+\tMLX5_IPOOL_JUMP, /* Pool for SWS jump resource. */\n+\t/* Pool for HWS group. Jump action will be created internally. */\n+\tMLX5_IPOOL_HW_GRP = MLX5_IPOOL_JUMP,\n \tMLX5_IPOOL_SAMPLE, /* Pool for sample resource. */\n \tMLX5_IPOOL_DEST_ARRAY, /* Pool for destination array resource. */\n \tMLX5_IPOOL_TUNNEL_ID, /* Pool for tunnel offload context */\n@@ -108,6 +110,13 @@ enum mlx5_delay_drop_mode {\n \tMLX5_DELAY_DROP_HAIRPIN = RTE_BIT32(1), /* Hairpin queues enable. */\n };\n \n+/* The HWS action type root/non-root. */\n+enum mlx5_hw_action_flag_type {\n+\tMLX5_HW_ACTION_FLAG_ROOT, /* Root action. */\n+\tMLX5_HW_ACTION_FLAG_NONE_ROOT, /* Non-root ation. */\n+\tMLX5_HW_ACTION_FLAG_MAX, /* Maximum action flag. */\n+};\n+\n /* Hlist and list callback context. */\n struct mlx5_flow_cb_ctx {\n \tstruct rte_eth_dev *dev;\n@@ -1204,7 +1213,10 @@ struct mlx5_dev_ctx_shared {\n \trte_spinlock_t uar_lock[MLX5_UAR_PAGE_NUM_MAX];\n \t/* UAR same-page access control required in 32bit implementations. */\n #endif\n-\tstruct mlx5_hlist *flow_tbls;\n+\tunion {\n+\t\tstruct mlx5_hlist *flow_tbls; /* SWS flow table. */\n+\t\tstruct mlx5_hlist *groups; /* HWS flow group. */\n+\t};\n \tstruct mlx5_flow_tunnel_hub *tunnel_hub;\n \t/* Direct Rules tables for FDB, NIC TX+RX */\n \tvoid *dr_drop_action; /* Pointer to DR drop action, any domain. */\n@@ -1510,6 +1522,11 @@ struct mlx5_priv {\n \tuint32_t nb_queue; /* HW steering queue number. */\n \t/* HW steering queue polling mechanism job descriptor LIFO. */\n \tstruct mlx5_hw_q *hw_q;\n+\t/* HW steering rte flow table list header. */\n+\tLIST_HEAD(flow_hw_tbl, rte_flow_template_table) flow_hw_tbl;\n+\t/* HW steering global drop action. */\n+\tstruct mlx5dr_action *hw_drop[MLX5_HW_ACTION_FLAG_MAX]\n+\t\t\t\t     [MLX5DR_TABLE_TYPE_MAX];\n #endif\n };\n \ndiff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex 18c313c6f0..ee7fc35e1a 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -838,6 +838,19 @@ mlx5_flow_actions_template_destroy(struct rte_eth_dev *dev,\n \t\t\t\t   struct rte_flow_actions_template *template,\n \t\t\t\t   struct rte_flow_error *error);\n \n+static struct rte_flow_template_table *\n+mlx5_flow_table_create(struct rte_eth_dev *dev,\n+\t\t       const struct rte_flow_template_table_attr *attr,\n+\t\t       struct rte_flow_pattern_template *item_templates[],\n+\t\t       uint8_t nb_item_templates,\n+\t\t       struct rte_flow_actions_template *action_templates[],\n+\t\t       uint8_t nb_action_templates,\n+\t\t       struct rte_flow_error *error);\n+static int\n+mlx5_flow_table_destroy(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_flow_template_table *table,\n+\t\t\tstruct rte_flow_error *error);\n+\n static const struct rte_flow_ops mlx5_flow_ops = {\n \t.validate = mlx5_flow_validate,\n \t.create = mlx5_flow_create,\n@@ -864,6 +877,8 @@ static const struct rte_flow_ops mlx5_flow_ops = {\n \t.pattern_template_destroy = mlx5_flow_pattern_template_destroy,\n \t.actions_template_create = mlx5_flow_actions_template_create,\n \t.actions_template_destroy = mlx5_flow_actions_template_destroy,\n+\t.template_table_create = mlx5_flow_table_create,\n+\t.template_table_destroy = mlx5_flow_table_destroy,\n };\n \n /* Tunnel information. */\n@@ -8078,6 +8093,84 @@ mlx5_flow_actions_template_destroy(struct rte_eth_dev *dev,\n \treturn fops->actions_template_destroy(dev, template, error);\n }\n \n+/**\n+ * Create flow table.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the rte_eth_dev structure.\n+ * @param[in] attr\n+ *   Pointer to the table attributes.\n+ * @param[in] item_templates\n+ *   Item template array to be binded to the table.\n+ * @param[in] nb_item_templates\n+ *   Number of item template.\n+ * @param[in] action_templates\n+ *   Action template array to be binded to the table.\n+ * @param[in] nb_action_templates\n+ *   Number of action template.\n+ * @param[out] error\n+ *   Pointer to error structure.\n+ *\n+ * @return\n+ *    Table on success, NULL otherwise and rte_errno is set.\n+ */\n+static struct rte_flow_template_table *\n+mlx5_flow_table_create(struct rte_eth_dev *dev,\n+\t\t       const struct rte_flow_template_table_attr *attr,\n+\t\t       struct rte_flow_pattern_template *item_templates[],\n+\t\t       uint8_t nb_item_templates,\n+\t\t       struct rte_flow_actions_template *action_templates[],\n+\t\t       uint8_t nb_action_templates,\n+\t\t       struct rte_flow_error *error)\n+{\n+\tconst struct mlx5_flow_driver_ops *fops;\n+\n+\tif (flow_get_drv_type(dev, NULL) != MLX5_FLOW_TYPE_HW) {\n+\t\trte_flow_error_set(error, ENOTSUP,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\tNULL,\n+\t\t\t\t\"table create with incorrect steering mode\");\n+\t\treturn NULL;\n+\t}\n+\tfops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);\n+\treturn fops->template_table_create(dev,\n+\t\t\t\t\t   attr,\n+\t\t\t\t\t   item_templates,\n+\t\t\t\t\t   nb_item_templates,\n+\t\t\t\t\t   action_templates,\n+\t\t\t\t\t   nb_action_templates,\n+\t\t\t\t\t   error);\n+}\n+\n+/**\n+ * PMD destroy flow table.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the rte_eth_dev structure.\n+ * @param[in] table\n+ *   Pointer to the table to be destroyed.\n+ * @param[out] error\n+ *   Pointer to error structure.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+mlx5_flow_table_destroy(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_flow_template_table *table,\n+\t\t\tstruct rte_flow_error *error)\n+{\n+\tconst struct mlx5_flow_driver_ops *fops;\n+\n+\tif (flow_get_drv_type(dev, NULL) != MLX5_FLOW_TYPE_HW)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\tNULL,\n+\t\t\t\t\"table destroy with incorrect steering mode\");\n+\tfops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);\n+\treturn fops->template_table_destroy(dev, table, error);\n+}\n+\n /**\n  * Allocate a new memory for the counter values wrapped by all the needed\n  * management.\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex 9a643fe0a8..1579036f58 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -1036,6 +1036,55 @@ struct rte_flow_actions_template {\n \tuint32_t refcnt; /* Reference counter. */\n };\n \n+/* Jump action struct. */\n+struct mlx5_hw_jump_action {\n+\t/* Action jump from root. */\n+\tstruct mlx5dr_action *root_action;\n+\t/* HW steering jump action. */\n+\tstruct mlx5dr_action *hws_action;\n+};\n+\n+/* DR action set struct. */\n+struct mlx5_hw_actions {\n+\tstruct mlx5dr_action *drop; /* Drop action. */\n+};\n+\n+/* mlx5 action template struct. */\n+struct mlx5_hw_action_template {\n+\t/* Action template pointer. */\n+\tstruct rte_flow_actions_template *action_template;\n+\tstruct mlx5_hw_actions acts; /* Template actions. */\n+};\n+\n+/* mlx5 flow group struct. */\n+struct mlx5_flow_group {\n+\tstruct mlx5_list_entry entry;\n+\tstruct mlx5dr_table *tbl; /* HWS table object. */\n+\tstruct mlx5_hw_jump_action jump; /* Jump action. */\n+\tenum mlx5dr_table_type type; /* Table type. */\n+\tuint32_t group_id; /* Group id. */\n+\tuint32_t idx; /* Group memory index. */\n+};\n+\n+\n+#define MLX5_HW_TBL_MAX_ITEM_TEMPLATE 2\n+#define MLX5_HW_TBL_MAX_ACTION_TEMPLATE 32\n+\n+struct rte_flow_template_table {\n+\tLIST_ENTRY(rte_flow_template_table) next;\n+\tstruct mlx5_flow_group *grp; /* The group rte_flow_template_table uses. */\n+\tstruct mlx5dr_matcher *matcher; /* Template matcher. */\n+\t/* Item templates bind to the table. */\n+\tstruct rte_flow_pattern_template *its[MLX5_HW_TBL_MAX_ITEM_TEMPLATE];\n+\t/* Action templates bind to the table. */\n+\tstruct mlx5_hw_action_template ats[MLX5_HW_TBL_MAX_ACTION_TEMPLATE];\n+\tstruct mlx5_indexed_pool *flow; /* The table's flow ipool. */\n+\tuint32_t type; /* Flow table type RX/TX/FDB. */\n+\tuint8_t nb_item_templates; /* Item template number. */\n+\tuint8_t nb_action_templates; /* Action template number. */\n+\tuint32_t refcnt; /* Table reference counter. */\n+};\n+\n #endif\n \n /*\n@@ -1310,6 +1359,18 @@ typedef int (*mlx5_flow_actions_template_destroy_t)\n \t\t\t(struct rte_eth_dev *dev,\n \t\t\t struct rte_flow_actions_template *template,\n \t\t\t struct rte_flow_error *error);\n+typedef struct rte_flow_template_table *(*mlx5_flow_table_create_t)\n+\t\t(struct rte_eth_dev *dev,\n+\t\t const struct rte_flow_template_table_attr *attr,\n+\t\t struct rte_flow_pattern_template *item_templates[],\n+\t\t uint8_t nb_item_templates,\n+\t\t struct rte_flow_actions_template *action_templates[],\n+\t\t uint8_t nb_action_templates,\n+\t\t struct rte_flow_error *error);\n+typedef int (*mlx5_flow_table_destroy_t)\n+\t\t\t(struct rte_eth_dev *dev,\n+\t\t\t struct rte_flow_template_table *table,\n+\t\t\t struct rte_flow_error *error);\n \n struct mlx5_flow_driver_ops {\n \tmlx5_flow_validate_t validate;\n@@ -1354,6 +1415,8 @@ struct mlx5_flow_driver_ops {\n \tmlx5_flow_pattern_template_destroy_t pattern_template_destroy;\n \tmlx5_flow_actions_template_create_t actions_template_create;\n \tmlx5_flow_actions_template_destroy_t actions_template_destroy;\n+\tmlx5_flow_table_create_t template_table_create;\n+\tmlx5_flow_table_destroy_t template_table_destroy;\n };\n \n /* mlx5_flow.c */\n@@ -1784,6 +1847,16 @@ struct mlx5_list_entry *flow_dv_dest_array_clone_cb(void *tool_ctx,\n void flow_dv_dest_array_clone_free_cb(void *tool_ctx,\n \t\t\t\t      struct mlx5_list_entry *entry);\n \n+struct mlx5_list_entry *flow_hw_grp_create_cb(void *tool_ctx, void *cb_ctx);\n+void flow_hw_grp_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry);\n+int flow_hw_grp_match_cb(void *tool_ctx,\n+\t\t\t struct mlx5_list_entry *entry,\n+\t\t\t void *cb_ctx);\n+struct mlx5_list_entry *flow_hw_grp_clone_cb(void *tool_ctx,\n+\t\t\t\t\t     struct mlx5_list_entry *oentry,\n+\t\t\t\t\t     void *cb_ctx);\n+void flow_hw_grp_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry);\n+\n struct mlx5_aso_age_action *flow_aso_age_get_by_idx(struct rte_eth_dev *dev,\n \t\t\t\t\t\t    uint32_t age_idx);\n int flow_dev_geneve_tlv_option_resource_register(struct rte_eth_dev *dev,\ndiff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c\nindex 4214a63a73..8cb1ef842a 100644\n--- a/drivers/net/mlx5/mlx5_flow_hw.c\n+++ b/drivers/net/mlx5/mlx5_flow_hw.c\n@@ -12,6 +12,306 @@\n \n const struct mlx5_flow_driver_ops mlx5_flow_hw_drv_ops;\n \n+/* DR action flags with different table. */\n+static uint32_t mlx5_hw_act_flag[MLX5_HW_ACTION_FLAG_MAX]\n+\t\t\t\t[MLX5DR_TABLE_TYPE_MAX] = {\n+\t{\n+\t\tMLX5DR_ACTION_FLAG_ROOT_RX,\n+\t\tMLX5DR_ACTION_FLAG_ROOT_TX,\n+\t\tMLX5DR_ACTION_FLAG_ROOT_FDB,\n+\t},\n+\t{\n+\t\tMLX5DR_ACTION_FLAG_HWS_RX,\n+\t\tMLX5DR_ACTION_FLAG_HWS_TX,\n+\t\tMLX5DR_ACTION_FLAG_HWS_FDB,\n+\t},\n+};\n+\n+/**\n+ * Destroy DR actions created by action template.\n+ *\n+ * For DR actions created during table creation's action translate.\n+ * Need to destroy the DR action when destroying the table.\n+ *\n+ * @param[in] acts\n+ *   Pointer to the template HW steering DR actions.\n+ */\n+static void\n+__flow_hw_action_template_destroy(struct mlx5_hw_actions *acts __rte_unused)\n+{\n+}\n+\n+/**\n+ * Translate rte_flow actions to DR action.\n+ *\n+ * As the action template has already indicated the actions. Translate\n+ * the rte_flow actions to DR action if possbile. So in flow create\n+ * stage we will save cycles from handing the actions' organizing.\n+ * For the actions with limited information, need to add these to a\n+ * list.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the rte_eth_dev structure.\n+ * @param[in] table_attr\n+ *   Pointer to the table attributes.\n+ * @param[in] item_templates\n+ *   Item template array to be binded to the table.\n+ * @param[in/out] acts\n+ *   Pointer to the template HW steering DR actions.\n+ * @param[in] at\n+ *   Action template.\n+ * @param[out] error\n+ *   Pointer to error structure.\n+ *\n+ * @return\n+ *    Table on success, NULL otherwise and rte_errno is set.\n+ */\n+static int\n+flow_hw_actions_translate(struct rte_eth_dev *dev,\n+\t\t\t  const struct rte_flow_template_table_attr *table_attr,\n+\t\t\t  struct mlx5_hw_actions *acts,\n+\t\t\t  struct rte_flow_actions_template *at,\n+\t\t\t  struct rte_flow_error *error __rte_unused)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tconst struct rte_flow_attr *attr = &table_attr->flow_attr;\n+\tstruct rte_flow_action *actions = at->actions;\n+\tstruct rte_flow_action *masks = at->masks;\n+\tbool actions_end = false;\n+\tuint32_t type;\n+\n+\tif (attr->transfer)\n+\t\ttype = MLX5DR_TABLE_TYPE_FDB;\n+\telse if (attr->egress)\n+\t\ttype = MLX5DR_TABLE_TYPE_NIC_TX;\n+\telse\n+\t\ttype = MLX5DR_TABLE_TYPE_NIC_RX;\n+\tfor (; !actions_end; actions++, masks++) {\n+\t\tswitch (actions->type) {\n+\t\tcase RTE_FLOW_ACTION_TYPE_INDIRECT:\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_VOID:\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_DROP:\n+\t\t\tacts->drop = priv->hw_drop[!!attr->group][type];\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_END:\n+\t\t\tactions_end = true;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n+ * Create flow table.\n+ *\n+ * The input item and action templates will be binded to the table.\n+ * Flow memory will also be allocated. Matcher will be created based\n+ * on the item template. Action will be translated to the dedicated\n+ * DR action if possible.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the rte_eth_dev structure.\n+ * @param[in] attr\n+ *   Pointer to the table attributes.\n+ * @param[in] item_templates\n+ *   Item template array to be binded to the table.\n+ * @param[in] nb_item_templates\n+ *   Number of item template.\n+ * @param[in] action_templates\n+ *   Action template array to be binded to the table.\n+ * @param[in] nb_action_templates\n+ *   Number of action template.\n+ * @param[out] error\n+ *   Pointer to error structure.\n+ *\n+ * @return\n+ *    Table on success, NULL otherwise and rte_errno is set.\n+ */\n+static struct rte_flow_template_table *\n+flow_hw_table_create(struct rte_eth_dev *dev,\n+\t\t     const struct rte_flow_template_table_attr *attr,\n+\t\t     struct rte_flow_pattern_template *item_templates[],\n+\t\t     uint8_t nb_item_templates,\n+\t\t     struct rte_flow_actions_template *action_templates[],\n+\t\t     uint8_t nb_action_templates,\n+\t\t     struct rte_flow_error *error)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5dr_matcher_attr matcher_attr = {0};\n+\tstruct rte_flow_template_table *tbl = NULL;\n+\tstruct mlx5_flow_group *grp;\n+\tstruct mlx5dr_match_template *mt[MLX5_HW_TBL_MAX_ITEM_TEMPLATE];\n+\tstruct rte_flow_attr flow_attr = attr->flow_attr;\n+\tstruct mlx5_flow_cb_ctx ctx = {\n+\t\t.dev = dev,\n+\t\t.error = error,\n+\t\t.data = &flow_attr,\n+\t};\n+\tstruct mlx5_indexed_pool_config cfg = {\n+\t\t.size = sizeof(struct rte_flow),\n+\t\t.trunk_size = 1 << 12,\n+\t\t.per_core_cache = 1 << 13,\n+\t\t.need_lock = 1,\n+\t\t.release_mem_en = !!priv->sh->config.reclaim_mode,\n+\t\t.malloc = mlx5_malloc,\n+\t\t.free = mlx5_free,\n+\t\t.type = \"mlx5_hw_table_flow\",\n+\t};\n+\tstruct mlx5_list_entry *ge;\n+\tuint32_t i, max_tpl = MLX5_HW_TBL_MAX_ITEM_TEMPLATE;\n+\tuint32_t nb_flows = rte_align32pow2(attr->nb_flows);\n+\tint err;\n+\n+\t/* HWS layer accepts only 1 item template with root table. */\n+\tif (!attr->flow_attr.group)\n+\t\tmax_tpl = 1;\n+\tcfg.max_idx = nb_flows;\n+\t/* For table has limited flows, resize the cache and trunk size. */\n+\tif (nb_flows < cfg.trunk_size) {\n+\t\tcfg.per_core_cache = nb_flows >> 2;\n+\t\tcfg.trunk_size = nb_flows;\n+\t}\n+\t/* Check if we requires too many templates. */\n+\tif (nb_item_templates > max_tpl ||\n+\t    nb_action_templates > MLX5_HW_TBL_MAX_ACTION_TEMPLATE) {\n+\t\trte_errno = EINVAL;\n+\t\tgoto error;\n+\t}\n+\t/* Allocate the table memory. */\n+\ttbl = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*tbl), 0, rte_socket_id());\n+\tif (!tbl)\n+\t\tgoto error;\n+\t/* Allocate flow indexed pool. */\n+\ttbl->flow = mlx5_ipool_create(&cfg);\n+\tif (!tbl->flow)\n+\t\tgoto error;\n+\t/* Register the flow group. */\n+\tge = mlx5_hlist_register(priv->sh->groups, attr->flow_attr.group, &ctx);\n+\tif (!ge)\n+\t\tgoto error;\n+\tgrp = container_of(ge, struct mlx5_flow_group, entry);\n+\ttbl->grp = grp;\n+\t/* Prepare matcher information. */\n+\tmatcher_attr.priority = attr->flow_attr.priority;\n+\tmatcher_attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_RULE;\n+\tmatcher_attr.rule.num_log = rte_log2_u32(nb_flows);\n+\t/* Build the item template. */\n+\tfor (i = 0; i < nb_item_templates; i++) {\n+\t\tuint32_t ret;\n+\n+\t\tret = __atomic_add_fetch(&item_templates[i]->refcnt, 1,\n+\t\t\t\t\t __ATOMIC_RELAXED);\n+\t\tif (ret <= 1) {\n+\t\t\trte_errno = EINVAL;\n+\t\t\tgoto it_error;\n+\t\t}\n+\t\tmt[i] = item_templates[i]->mt;\n+\t\ttbl->its[i] = item_templates[i];\n+\t}\n+\ttbl->matcher = mlx5dr_matcher_create\n+\t\t(tbl->grp->tbl, mt, nb_item_templates, &matcher_attr);\n+\tif (!tbl->matcher)\n+\t\tgoto it_error;\n+\ttbl->nb_item_templates = nb_item_templates;\n+\t/* Build the action template. */\n+\tfor (i = 0; i < nb_action_templates; i++) {\n+\t\tuint32_t ret;\n+\n+\t\tret = __atomic_add_fetch(&action_templates[i]->refcnt, 1,\n+\t\t\t\t\t __ATOMIC_RELAXED);\n+\t\tif (ret <= 1) {\n+\t\t\trte_errno = EINVAL;\n+\t\t\tgoto at_error;\n+\t\t}\n+\t\terr = flow_hw_actions_translate(dev, attr,\n+\t\t\t\t\t\t&tbl->ats[i].acts,\n+\t\t\t\t\t\taction_templates[i], error);\n+\t\tif (err)\n+\t\t\tgoto at_error;\n+\t\ttbl->ats[i].action_template = action_templates[i];\n+\t}\n+\ttbl->nb_action_templates = nb_action_templates;\n+\ttbl->type = attr->flow_attr.transfer ? MLX5DR_TABLE_TYPE_FDB :\n+\t\t    (attr->flow_attr.egress ? MLX5DR_TABLE_TYPE_NIC_TX :\n+\t\t    MLX5DR_TABLE_TYPE_NIC_RX);\n+\tLIST_INSERT_HEAD(&priv->flow_hw_tbl, tbl, next);\n+\treturn tbl;\n+at_error:\n+\twhile (i--) {\n+\t\t__flow_hw_action_template_destroy(&tbl->ats[i].acts);\n+\t\t__atomic_sub_fetch(&action_templates[i]->refcnt,\n+\t\t\t\t   1, __ATOMIC_RELAXED);\n+\t}\n+\ti = nb_item_templates;\n+it_error:\n+\twhile (i--)\n+\t\t__atomic_sub_fetch(&item_templates[i]->refcnt,\n+\t\t\t\t   1, __ATOMIC_RELAXED);\n+\tmlx5dr_matcher_destroy(tbl->matcher);\n+error:\n+\terr = rte_errno;\n+\tif (tbl) {\n+\t\tif (tbl->grp)\n+\t\t\tmlx5_hlist_unregister(priv->sh->groups,\n+\t\t\t\t\t      &tbl->grp->entry);\n+\t\tif (tbl->flow)\n+\t\t\tmlx5_ipool_destroy(tbl->flow);\n+\t\tmlx5_free(tbl);\n+\t}\n+\trte_flow_error_set(error, err,\n+\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t  \"fail to create rte table\");\n+\treturn NULL;\n+}\n+\n+/**\n+ * Destroy flow table.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the rte_eth_dev structure.\n+ * @param[in] table\n+ *   Pointer to the table to be destroyed.\n+ * @param[out] error\n+ *   Pointer to error structure.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+flow_hw_table_destroy(struct rte_eth_dev *dev,\n+\t\t      struct rte_flow_template_table *table,\n+\t\t      struct rte_flow_error *error)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tint i;\n+\n+\tif (table->refcnt) {\n+\t\tDRV_LOG(WARNING, \"Table %p is still in using.\", (void *)table);\n+\t\treturn rte_flow_error_set(error, EBUSY,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t   NULL,\n+\t\t\t\t   \"table in using\");\n+\t}\n+\tLIST_REMOVE(table, next);\n+\tfor (i = 0; i < table->nb_item_templates; i++)\n+\t\t__atomic_sub_fetch(&table->its[i]->refcnt,\n+\t\t\t\t   1, __ATOMIC_RELAXED);\n+\tfor (i = 0; i < table->nb_action_templates; i++) {\n+\t\t__flow_hw_action_template_destroy(&table->ats[i].acts);\n+\t\t__atomic_sub_fetch(&table->ats[i].action_template->refcnt,\n+\t\t\t\t   1, __ATOMIC_RELAXED);\n+\t}\n+\tmlx5dr_matcher_destroy(table->matcher);\n+\tmlx5_hlist_unregister(priv->sh->groups, &table->grp->entry);\n+\tmlx5_ipool_destroy(table->flow);\n+\tmlx5_free(table);\n+\treturn 0;\n+}\n+\n /**\n  * Create flow action template.\n  *\n@@ -228,6 +528,199 @@ flow_hw_info_get(struct rte_eth_dev *dev __rte_unused,\n \treturn 0;\n }\n \n+/**\n+ * Create group callback.\n+ *\n+ * @param[in] tool_ctx\n+ *   Pointer to the hash list related context.\n+ * @param[in] cb_ctx\n+ *   Pointer to the group creation context.\n+ *\n+ * @return\n+ *   Group entry on success, NULL otherwise and rte_errno is set.\n+ */\n+struct mlx5_list_entry *\n+flow_hw_grp_create_cb(void *tool_ctx, void *cb_ctx)\n+{\n+\tstruct mlx5_dev_ctx_shared *sh = tool_ctx;\n+\tstruct mlx5_flow_cb_ctx *ctx = cb_ctx;\n+\tstruct rte_eth_dev *dev = ctx->dev;\n+\tstruct rte_flow_attr *attr = (struct rte_flow_attr *)ctx->data;\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5dr_table_attr dr_tbl_attr = {0};\n+\tstruct rte_flow_error *error = ctx->error;\n+\tstruct mlx5_flow_group *grp_data;\n+\tstruct mlx5dr_table *tbl = NULL;\n+\tstruct mlx5dr_action *jump;\n+\tuint32_t idx = 0;\n+\n+\tgrp_data = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_HW_GRP], &idx);\n+\tif (!grp_data) {\n+\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t   NULL,\n+\t\t\t\t   \"cannot allocate flow table data entry\");\n+\t\treturn NULL;\n+\t}\n+\tdr_tbl_attr.level = attr->group;\n+\tif (attr->transfer)\n+\t\tdr_tbl_attr.type = MLX5DR_TABLE_TYPE_FDB;\n+\telse if (attr->egress)\n+\t\tdr_tbl_attr.type = MLX5DR_TABLE_TYPE_NIC_TX;\n+\telse\n+\t\tdr_tbl_attr.type = MLX5DR_TABLE_TYPE_NIC_RX;\n+\ttbl = mlx5dr_table_create(priv->dr_ctx, &dr_tbl_attr);\n+\tif (!tbl)\n+\t\tgoto error;\n+\tgrp_data->tbl = tbl;\n+\tif (attr->group) {\n+\t\t/* Jump action be used by non-root table. */\n+\t\tjump = mlx5dr_action_create_dest_table\n+\t\t\t(priv->dr_ctx, tbl,\n+\t\t\t mlx5_hw_act_flag[!!attr->group][dr_tbl_attr.type]);\n+\t\tif (!jump)\n+\t\t\tgoto error;\n+\t\tgrp_data->jump.hws_action = jump;\n+\t\t/* Jump action be used by root table.  */\n+\t\tjump = mlx5dr_action_create_dest_table\n+\t\t\t(priv->dr_ctx, tbl,\n+\t\t\t mlx5_hw_act_flag[MLX5_HW_ACTION_FLAG_ROOT]\n+\t\t\t\t\t [dr_tbl_attr.type]);\n+\t\tif (!jump)\n+\t\t\tgoto error;\n+\t\tgrp_data->jump.root_action = jump;\n+\t}\n+\tgrp_data->idx = idx;\n+\tgrp_data->group_id = attr->group;\n+\tgrp_data->type = dr_tbl_attr.type;\n+\treturn &grp_data->entry;\n+error:\n+\tif (grp_data->jump.root_action)\n+\t\tmlx5dr_action_destroy(grp_data->jump.root_action);\n+\tif (grp_data->jump.hws_action)\n+\t\tmlx5dr_action_destroy(grp_data->jump.hws_action);\n+\tif (tbl)\n+\t\tmlx5dr_table_destroy(tbl);\n+\tif (idx)\n+\t\tmlx5_ipool_free(sh->ipool[MLX5_IPOOL_HW_GRP], idx);\n+\trte_flow_error_set(error, ENOMEM,\n+\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t   NULL,\n+\t\t\t   \"cannot allocate flow dr table\");\n+\treturn NULL;\n+}\n+\n+/**\n+ * Remove group callback.\n+ *\n+ * @param[in] tool_ctx\n+ *   Pointer to the hash list related context.\n+ * @param[in] entry\n+ *   Pointer to the entry to be removed.\n+ */\n+void\n+flow_hw_grp_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)\n+{\n+\tstruct mlx5_dev_ctx_shared *sh = tool_ctx;\n+\tstruct mlx5_flow_group *grp_data =\n+\t\t    container_of(entry, struct mlx5_flow_group, entry);\n+\n+\tMLX5_ASSERT(entry && sh);\n+\t/* To use the wrapper glue functions instead. */\n+\tif (grp_data->jump.hws_action)\n+\t\tmlx5dr_action_destroy(grp_data->jump.hws_action);\n+\tif (grp_data->jump.root_action)\n+\t\tmlx5dr_action_destroy(grp_data->jump.root_action);\n+\tmlx5dr_table_destroy(grp_data->tbl);\n+\tmlx5_ipool_free(sh->ipool[MLX5_IPOOL_HW_GRP], grp_data->idx);\n+}\n+\n+/**\n+ * Match group callback.\n+ *\n+ * @param[in] tool_ctx\n+ *   Pointer to the hash list related context.\n+ * @param[in] entry\n+ *   Pointer to the group to be matched.\n+ * @param[in] cb_ctx\n+ *   Pointer to the group matching context.\n+ *\n+ * @return\n+ *   0 on matched, 1 on miss matched.\n+ */\n+int\n+flow_hw_grp_match_cb(void *tool_ctx __rte_unused, struct mlx5_list_entry *entry,\n+\t\t     void *cb_ctx)\n+{\n+\tstruct mlx5_flow_cb_ctx *ctx = cb_ctx;\n+\tstruct mlx5_flow_group *grp_data =\n+\t\tcontainer_of(entry, struct mlx5_flow_group, entry);\n+\tstruct rte_flow_attr *attr =\n+\t\t\t(struct rte_flow_attr *)ctx->data;\n+\n+\treturn (grp_data->group_id != attr->group) ||\n+\t\t((grp_data->type != MLX5DR_TABLE_TYPE_FDB) &&\n+\t\tattr->transfer) ||\n+\t\t((grp_data->type != MLX5DR_TABLE_TYPE_NIC_TX) &&\n+\t\tattr->egress) ||\n+\t\t((grp_data->type != MLX5DR_TABLE_TYPE_NIC_RX) &&\n+\t\tattr->ingress);\n+}\n+\n+/**\n+ * Clone group entry callback.\n+ *\n+ * @param[in] tool_ctx\n+ *   Pointer to the hash list related context.\n+ * @param[in] entry\n+ *   Pointer to the group to be matched.\n+ * @param[in] cb_ctx\n+ *   Pointer to the group matching context.\n+ *\n+ * @return\n+ *   0 on matched, 1 on miss matched.\n+ */\n+struct mlx5_list_entry *\n+flow_hw_grp_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,\n+\t\t     void *cb_ctx)\n+{\n+\tstruct mlx5_dev_ctx_shared *sh = tool_ctx;\n+\tstruct mlx5_flow_cb_ctx *ctx = cb_ctx;\n+\tstruct mlx5_flow_group *grp_data;\n+\tstruct rte_flow_error *error = ctx->error;\n+\tuint32_t idx = 0;\n+\n+\tgrp_data = mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_HW_GRP], &idx);\n+\tif (!grp_data) {\n+\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t   NULL,\n+\t\t\t\t   \"cannot allocate flow table data entry\");\n+\t\treturn NULL;\n+\t}\n+\tmemcpy(grp_data, oentry, sizeof(*grp_data));\n+\tgrp_data->idx = idx;\n+\treturn &grp_data->entry;\n+}\n+\n+/**\n+ * Free cloned group entry callback.\n+ *\n+ * @param[in] tool_ctx\n+ *   Pointer to the hash list related context.\n+ * @param[in] entry\n+ *   Pointer to the group to be freed.\n+ */\n+void\n+flow_hw_grp_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)\n+{\n+\tstruct mlx5_dev_ctx_shared *sh = tool_ctx;\n+\tstruct mlx5_flow_group *grp_data =\n+\t\t    container_of(entry, struct mlx5_flow_group, entry);\n+\n+\tmlx5_ipool_free(sh->ipool[MLX5_IPOOL_HW_GRP], grp_data->idx);\n+}\n+\n /**\n  * Configure port HWS resources.\n  *\n@@ -245,6 +738,7 @@ flow_hw_info_get(struct rte_eth_dev *dev __rte_unused,\n  * @return\n  *   0 on success, a negative errno value otherwise and rte_errno is set.\n  */\n+\n static int\n flow_hw_configure(struct rte_eth_dev *dev,\n \t\t  const struct rte_flow_port_attr *port_attr,\n@@ -321,8 +815,24 @@ flow_hw_configure(struct rte_eth_dev *dev,\n \t\tgoto err;\n \tpriv->dr_ctx = dr_ctx;\n \tpriv->nb_queue = nb_queue;\n+\t/* Add global actions. */\n+\tfor (i = 0; i < MLX5_HW_ACTION_FLAG_MAX; i++) {\n+\t\tfor (j = 0; j < MLX5DR_TABLE_TYPE_MAX; j++) {\n+\t\t\tpriv->hw_drop[i][j] = mlx5dr_action_create_dest_drop\n+\t\t\t\t(priv->dr_ctx, mlx5_hw_act_flag[i][j]);\n+\t\t\tif (!priv->hw_drop[i][j])\n+\t\t\t\tgoto err;\n+\t\t}\n+\t}\n \treturn 0;\n err:\n+\tfor (i = 0; i < MLX5_HW_ACTION_FLAG_MAX; i++) {\n+\t\tfor (j = 0; j < MLX5DR_TABLE_TYPE_MAX; j++) {\n+\t\t\tif (!priv->hw_drop[i][j])\n+\t\t\t\tcontinue;\n+\t\t\tmlx5dr_action_destroy(priv->hw_drop[i][j]);\n+\t\t}\n+\t}\n \tif (dr_ctx)\n \t\tclaim_zero(mlx5dr_context_close(dr_ctx));\n \tmlx5_free(priv->hw_q);\n@@ -342,11 +852,17 @@ void\n flow_hw_resource_release(struct rte_eth_dev *dev)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct rte_flow_template_table *tbl;\n \tstruct rte_flow_pattern_template *it;\n \tstruct rte_flow_actions_template *at;\n+\tint i, j;\n \n \tif (!priv->dr_ctx)\n \t\treturn;\n+\twhile (!LIST_EMPTY(&priv->flow_hw_tbl)) {\n+\t\ttbl = LIST_FIRST(&priv->flow_hw_tbl);\n+\t\tflow_hw_table_destroy(dev, tbl, NULL);\n+\t}\n \twhile (!LIST_EMPTY(&priv->flow_hw_itt)) {\n \t\tit = LIST_FIRST(&priv->flow_hw_itt);\n \t\tflow_hw_pattern_template_destroy(dev, it, NULL);\n@@ -355,6 +871,13 @@ flow_hw_resource_release(struct rte_eth_dev *dev)\n \t\tat = LIST_FIRST(&priv->flow_hw_at);\n \t\tflow_hw_actions_template_destroy(dev, at, NULL);\n \t}\n+\tfor (i = 0; i < MLX5_HW_ACTION_FLAG_MAX; i++) {\n+\t\tfor (j = 0; j < MLX5DR_TABLE_TYPE_MAX; j++) {\n+\t\t\tif (!priv->hw_drop[i][j])\n+\t\t\t\tcontinue;\n+\t\t\tmlx5dr_action_destroy(priv->hw_drop[i][j]);\n+\t\t}\n+\t}\n \tmlx5_free(priv->hw_q);\n \tpriv->hw_q = NULL;\n \tclaim_zero(mlx5dr_context_close(priv->dr_ctx));\n@@ -369,6 +892,8 @@ const struct mlx5_flow_driver_ops mlx5_flow_hw_drv_ops = {\n \t.pattern_template_destroy = flow_hw_pattern_template_destroy,\n \t.actions_template_create = flow_hw_actions_template_create,\n \t.actions_template_destroy = flow_hw_actions_template_destroy,\n+\t.template_table_create = flow_hw_table_create,\n+\t.template_table_destroy = flow_hw_table_destroy,\n };\n \n #endif\n",
    "prefixes": [
        "v3",
        "07/14"
    ]
}