get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 132462,
    "url": "https://patches.dpdk.org/api/patches/132462/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20231010142401.27289-1-orika@nvidia.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<20231010142401.27289-1-orika@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20231010142401.27289-1-orika@nvidia.com",
    "date": "2023-10-10T14:24:01",
    "name": "[v2] ethdev: add calculate hash function",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "9048a64beb0025181e3be52d409a75222a27c5d5",
    "submitter": {
        "id": 1869,
        "url": "https://patches.dpdk.org/api/people/1869/?format=api",
        "name": "Ori Kam",
        "email": "orika@nvidia.com"
    },
    "delegate": {
        "id": 319,
        "url": "https://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20231010142401.27289-1-orika@nvidia.com/mbox/",
    "series": [
        {
            "id": 29791,
            "url": "https://patches.dpdk.org/api/series/29791/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=29791",
            "date": "2023-10-10T14:24:01",
            "name": "[v2] ethdev: add calculate hash function",
            "version": 2,
            "mbox": "https://patches.dpdk.org/series/29791/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/132462/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/132462/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 2BB794234D;\n\tTue, 10 Oct 2023 16:25:02 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id A89C2402C2;\n\tTue, 10 Oct 2023 16:25:01 +0200 (CEST)",
            "from NAM02-BN1-obe.outbound.protection.outlook.com\n (mail-bn1nam02on2087.outbound.protection.outlook.com [40.107.212.87])\n by mails.dpdk.org (Postfix) with ESMTP id EDCDD40297\n for <dev@dpdk.org>; Tue, 10 Oct 2023 16:24:59 +0200 (CEST)",
            "from BYAPR08CA0039.namprd08.prod.outlook.com (2603:10b6:a03:117::16)\n by CO6PR12MB5474.namprd12.prod.outlook.com (2603:10b6:303:139::9)\n with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6863.38; Tue, 10 Oct\n 2023 14:24:57 +0000",
            "from SN1PEPF0002BA4E.namprd03.prod.outlook.com\n (2603:10b6:a03:117:cafe::ef) by BYAPR08CA0039.outlook.office365.com\n (2603:10b6:a03:117::16) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6886.27 via Frontend\n Transport; Tue, 10 Oct 2023 14:24:57 +0000",
            "from mail.nvidia.com (216.228.117.161) by\n SN1PEPF0002BA4E.mail.protection.outlook.com (10.167.242.71) with Microsoft\n SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.20.6838.22 via Frontend Transport; Tue, 10 Oct 2023 14:24:56 +0000",
            "from rnnvmail201.nvidia.com (10.129.68.8) by mail.nvidia.com\n (10.129.200.67) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.41; Tue, 10 Oct\n 2023 07:24:25 -0700",
            "from nvidia.com (10.126.230.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.41; Tue, 10 Oct\n 2023 07:24:21 -0700"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=XSb21Szu3gxZpsfcU5yNVDB13xesXdvjvg38t4FU8vu84Puhb9eVuZUb9QwRoX2/w6tho659/ukPtvu5zCqOFWAceFGnT0VDmwlv+iAi+Ae5g2JT5muQ8J4oZJakU+zZUJEfZqxrb+Wid70mpWynKeAoEBf5Ms8rciCaHwkP2hJHAE1f0YQkaCiuyD10Ef8GKMPuEkv+pQ3I9KjhL3zGUhzmfJ6OICg9xCOBzo3gYLXI6BPMc3V5EnZHvrKfdW/+eRTtddroIfUA75ZxIuE9b4ulWXi2WjO6UOKCRH7h/gfwzbSkknwGTgVIGXVqLpZ/5/xkbt9W99moJNayHLnmlg==",
        "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=Yh2OfMxHNe0PtMkYRGNmJG02UBOff+psiO3iY0aZyDk=;\n b=aQMAuUfVr+jg7xcuL4Qz3yQtgYI9VtlPov983u6NUXJNMLurleqO9KpAaVF1J0AfSdotJ62QypHOvhM7BiggY/zhB1iaU6TFbLATHmfrAVxRo2YUWnxYvIXluzK8r1AJmWm5wCwxLSerAgF1l1IPkirktSWcjjHvK6SnOnz4GisTsmGpgR+id4rHiG2jZsG4ZBfyDiXGNEnAQm0ruwHlGqapp+NhgLXVC2gCUtuUbWyb48cEltaUNT+A7ikjcWw6SfZNFHrDG2X2GdYxe/t92xFpxo2w6RKgiIbBQBBowp6TtVdw3FjiNf6G6ZWKZmqLkRRQ9aLgo5g5HBkQHuwpCw==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass (sender ip is\n 216.228.117.161) smtp.rcpttodomain=intel.com smtp.mailfrom=nvidia.com;\n dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com;\n dkim=none (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=Yh2OfMxHNe0PtMkYRGNmJG02UBOff+psiO3iY0aZyDk=;\n b=PWuXXGrA01nkbyGtcwxdR6G7AlDfeuulK9cjV8zHWEM4nu0DcqSDEHtJ94jKDog8Su1jiYRKf7uIi3DcCotLHBjFOB86/O8zCyt3ODrFtSL2oK1q0nL72NjeyIc+oBI8Dp3NS7pbc3k9RwO5qXpM+FGFehwZu7yXFr1npn1k74lse6IlWDIC2lQcGGUKbqAnAwfiVW/t3UCDpkamdlHjOqBGcQG2vModydNY+jLCDm/4wF6pQQG5H8U8C4ca+L/lYgzF04lPFwQo1qh8FR0BOf/K3puG/wgqzdZfVnySXiH3FVq2bdl2ZuLABN5TqrpV4jlNJRrTMZ7ZtzIiXBlWvw==",
        "X-MS-Exchange-Authentication-Results": "spf=pass (sender IP is 216.228.117.161)\n smtp.mailfrom=nvidia.com;\n 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 216.228.117.161 as permitted sender) receiver=protection.outlook.com;\n client-ip=216.228.117.161; helo=mail.nvidia.com; pr=C",
        "From": "Ori Kam <orika@nvidia.com>",
        "To": "<cristian.dumitrescu@intel.com>, Aman Singh <aman.deep.singh@intel.com>,\n Yuying Zhang <yuying.zhang@intel.com>, Thomas Monjalon <thomas@monjalon.net>,\n Ferruh Yigit <ferruh.yigit@amd.com>, Andrew Rybchenko\n <andrew.rybchenko@oktetlabs.ru>",
        "CC": "<dev@dpdk.org>, <orika@nvidia.com>, <rasland@nvidia.com>",
        "Subject": "[PATCH v2] ethdev: add calculate hash function",
        "Date": "Tue, 10 Oct 2023 17:24:01 +0300",
        "Message-ID": "<20231010142401.27289-1-orika@nvidia.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20230926113753.28765-1-orika@nvidia.com>",
        "References": "<20230926113753.28765-1-orika@nvidia.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[10.126.230.35]",
        "X-ClientProxiedBy": "rnnvmail202.nvidia.com (10.129.68.7) To\n rnnvmail201.nvidia.com (10.129.68.8)",
        "X-EOPAttributedMessage": "0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "SN1PEPF0002BA4E:EE_|CO6PR12MB5474:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "d1d4a61c-f055-48db-661b-08dbc99cadca",
        "X-LD-Processed": "43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n B0bdG4hSk3I71JaL916qAwGTtNjxjXdlTP8+b+L1U1/Diw9usiLMP5eJP65FGK8q743UlbQME5qsEokHCtWaqGATc15KC6ivZCv3MpViWgCCOy1cFSh605yuI+fVfgImHU5GyNxUxTUBXE0/nO0zj3Q9WQ5/j4Cf4eYR3T7Ju4UvJxv0pvv+EawFLOk5nnzC1ZkF2LEvM7ufDacKCZzViZPT0gOGfS5Krni8Qark/7v3Q9n+azJY/jD6fpqJ8eHfbA68DrspFHsRz3Bb25DPJdRSQFsIZcLRfvUlHTG6S9ZKThgMLq+C7jco7sJhsNOFRgCIe+rSl6sf9ESi0T2iaVNf7khHTgkp1fQCAW0eO5iZlUrb0QpVWzGPw6pcGWv9y/aJALirogvbj2O3g+Pr2e3GrozDQI2oAmYtvFclT4t1Jv716KYj992lasHlS6LGUUjDFifOPWboBYinp0Bm4Po/OGvIslGIaW+YB4K8pG+TA/wv3M692UfWxXnIEWZhpzvIvFxdP0K3NV8brTIgHWhcqfjRuJbBz3hEDz96PNcWYlmZSbmN17cc3zItf/3rjixl5rKfxaQfFL2ZQ3ph+niViyc9B9TjNHNl0YqpdM5HSGSU7cEcXlyfgR9jSABxfv9l2ffBVpVfsn3d9Xm9TtH/AE/CSKnsgfGj9iaQkqsvFqJkcccOhvDWZ6OSNb7XS3UUdA1KakCRpA6eVERrMoG/vpKou4GRL1T7KQqBQchgm245CLVL+XiEnbhEvDXqBrtAsrNjos9TjGLc3srSxw==",
        "X-Forefront-Antispam-Report": "CIP:216.228.117.161; CTRY:US; LANG:en; SCL:1;\n SRV:;\n IPV:NLI; SFV:NSPM; H:mail.nvidia.com; PTR:dc6edge2.nvidia.com; CAT:NONE;\n SFS:(13230031)(4636009)(39860400002)(396003)(346002)(376002)(136003)(230922051799003)(82310400011)(64100799003)(451199024)(1800799009)(186009)(46966006)(40470700004)(36840700001)(110136005)(316002)(70206006)(54906003)(966005)(41300700001)(5660300002)(8936002)(4326008)(70586007)(8676002)(30864003)(40460700003)(36860700001)(1076003)(107886003)(2616005)(86362001)(83380400001)(7636003)(7696005)(2906002)(40480700001)(82740400003)(356005)(55016003)(36756003)(6666004)(336012)(6286002)(16526019)(426003)(26005)(478600001)(47076005);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "Nvidia.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "10 Oct 2023 14:24:56.9454 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n d1d4a61c-f055-48db-661b-08dbc99cadca",
        "X-MS-Exchange-CrossTenant-Id": "43083d15-7273-40c1-b7db-39efd9ccc17a",
        "X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp": "\n TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[216.228.117.161];\n Helo=[mail.nvidia.com]",
        "X-MS-Exchange-CrossTenant-AuthSource": "\n SN1PEPF0002BA4E.namprd03.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "CO6PR12MB5474",
        "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": "rte_flow supports insert by index table[1].\n\nUsing the above table, the application can create rules\nthat are based on hash.\nFor example application can create the following logic in order\nto create load balancing:\n1. Create insert by index table with 2 rules, that hashes based on dmac\n2. Insert to index 0 a rule that sends the traffic to port A.\n3. Insert to index 1 a rule that sends the traffic to port B.\n\nLet's also assume that before this table, there is a 5 tuple\nmatch table that jumps to the above table.\n\nSo each packet that matches one of the 5 tuple rules is RSSed\nto port A or B, based on dmac hash.\n\nThe issue arises when there is a miss on the 5 tuple table,\nwhich resulted due to the packet being the first packet of this flow, or\nfragmented packet or any other reason.\nIn this case, the application must calculate what would be the\nhash calculated by the HW so it can send the packet to the correct\nport.\n\nThis new API allows applications to calculate the hash value of a given\npacket for a given table.\n\n[1] - http://patches.dpdk.org/project/dpdk/patch/20230208030624.78465-2-akozyrev@nvidia.com/\n\nSigned-off-by: Ori Kam <orika@nvidia.com>\n---\n\nv2: add rst documentations\n\n---\n app/test-pmd/cmdline_flow.c                 | 86 ++++++++++++++++++++-\n app/test-pmd/config.c                       | 54 +++++++++++++\n app/test-pmd/testpmd.h                      |  2 +\n doc/guides/prog_guide/rte_flow.rst          | 17 ++++\n doc/guides/testpmd_app_ug/testpmd_funcs.rst | 22 ++++++\n lib/ethdev/rte_flow.c                       | 21 +++++\n lib/ethdev/rte_flow.h                       | 32 ++++++++\n lib/ethdev/rte_flow_driver.h                |  5 ++\n lib/ethdev/version.map                      |  1 +\n 9 files changed, 239 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c\nindex 12809f1042..dd66429554 100644\n--- a/app/test-pmd/cmdline_flow.c\n+++ b/app/test-pmd/cmdline_flow.c\n@@ -102,6 +102,7 @@ enum index {\n \tQUEUE,\n \tPUSH,\n \tPULL,\n+\tHASH,\n \n \t/* Flex arguments */\n \tFLEX_ITEM_INIT,\n@@ -214,6 +215,11 @@ enum index {\n \tGROUP_TRANSFER,\n \tGROUP_SET_MISS_ACTIONS,\n \n+\t/* Hash calculation arguments. */\n+\tHASH_CALC_TABLE,\n+\tHASH_CALC_PATTERN_INDEX,\n+\tHASH_CALC_PATTERN,\n+\n \t/* Tunnel arguments. */\n \tTUNNEL_CREATE,\n \tTUNNEL_CREATE_TYPE,\n@@ -2708,6 +2714,9 @@ static int parse_pull(struct context *, const struct token *,\n static int parse_group(struct context *, const struct token *,\n \t\t       const char *, unsigned int,\n \t\t       void *, unsigned int);\n+static int parse_hash(struct context *, const struct token *,\n+\t\t      const char *, unsigned int,\n+\t\t      void *, unsigned int);\n static int parse_tunnel(struct context *, const struct token *,\n \t\t\tconst char *, unsigned int,\n \t\t\tvoid *, unsigned int);\n@@ -3066,7 +3075,8 @@ static const struct token token_list[] = {\n \t\t\t      FLEX,\n \t\t\t      QUEUE,\n \t\t\t      PUSH,\n-\t\t\t      PULL)),\n+\t\t\t      PULL,\n+\t\t\t      HASH)),\n \t\t.call = parse_init,\n \t},\n \t/* Top-level command. */\n@@ -3751,6 +3761,33 @@ static const struct token token_list[] = {\n \t\t.args = ARGS(ARGS_ENTRY(struct buffer, queue)),\n \t},\n \t/* Top-level command. */\n+\t[HASH] = {\n+\t\t.name = \"hash\",\n+\t\t.help = \"calculate hash for a given pattern in a given template table\",\n+\t\t.next = NEXT(NEXT_ENTRY(HASH_CALC_TABLE), NEXT_ENTRY(COMMON_PORT_ID)),\n+\t\t.args = ARGS(ARGS_ENTRY(struct buffer, port)),\n+\t\t.call = parse_hash,\n+\t},\n+\t/* Sub-level commands. */\n+\t[HASH_CALC_TABLE] = {\n+\t\t.name = \"template_table\",\n+\t\t.help = \"specify table id\",\n+\t\t.next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX),\n+\t\t\t     NEXT_ENTRY(COMMON_TABLE_ID)),\n+\t\t.args = ARGS(ARGS_ENTRY(struct buffer,\n+\t\t\t\t\targs.vc.table_id)),\n+\t\t.call = parse_hash,\n+\t},\n+\t[HASH_CALC_PATTERN_INDEX] = {\n+\t\t.name = \"pattern_template\",\n+\t\t.help = \"specify pattern template id\",\n+\t\t.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),\n+\t\t\t     NEXT_ENTRY(COMMON_UNSIGNED)),\n+\t\t.args = ARGS(ARGS_ENTRY(struct buffer,\n+\t\t\t\t\targs.vc.pat_templ_id)),\n+\t\t.call = parse_hash,\n+\t},\n+\t/* Top-level command. */\n \t[INDIRECT_ACTION] = {\n \t\t.name = \"indirect_action\",\n \t\t.type = \"{command} {port_id} [{arg} [...]]\",\n@@ -10544,6 +10581,48 @@ parse_pull(struct context *ctx, const struct token *token,\n \treturn len;\n }\n \n+/** Parse tokens for hash calculation commands. */\n+static int\n+parse_hash(struct context *ctx, const struct token *token,\n+\t const char *str, unsigned int len,\n+\t void *buf, unsigned int size)\n+{\n+\tstruct buffer *out = buf;\n+\n+\t/* Token name must match. */\n+\tif (parse_default(ctx, token, str, len, NULL, 0) < 0)\n+\t\treturn -1;\n+\t/* Nothing else to do if there is no buffer. */\n+\tif (!out)\n+\t\treturn len;\n+\tif (!out->command) {\n+\t\tif (ctx->curr != HASH)\n+\t\t\treturn -1;\n+\t\tif (sizeof(*out) > size)\n+\t\t\treturn -1;\n+\t\tout->command = ctx->curr;\n+\t\tctx->objdata = 0;\n+\t\tctx->object = out;\n+\t\tctx->objmask = NULL;\n+\t\tout->args.vc.data = (uint8_t *)out + size;\n+\t\treturn len;\n+\t}\n+\tswitch (ctx->curr) {\n+\tcase HASH_CALC_TABLE:\n+\tcase HASH_CALC_PATTERN_INDEX:\n+\t\treturn len;\n+\tcase ITEM_PATTERN:\n+\t\tout->args.vc.pattern =\n+\t\t\t(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),\n+\t\t\t\t\t       sizeof(double));\n+\t\tctx->object = out->args.vc.pattern;\n+\t\tctx->objmask = NULL;\n+\t\treturn len;\n+\tdefault:\n+\t\treturn -1;\n+\t}\n+}\n+\n static int\n parse_group(struct context *ctx, const struct token *token,\n \t    const char *str, unsigned int len,\n@@ -12498,6 +12577,11 @@ cmd_flow_parsed(const struct buffer *in)\n \tcase PULL:\n \t\tport_queue_flow_pull(in->port, in->queue);\n \t\tbreak;\n+\tcase HASH:\n+\t\tport_flow_hash_calc(in->port, in->args.vc.table_id,\n+\t\t\t\t    in->args.vc.pat_templ_id,\n+\t\t\t\t    in->args.vc.pattern);\n+\t\tbreak;\n \tcase QUEUE_AGED:\n \t\tport_queue_flow_aged(in->port, in->queue,\n \t\t\t\t     in->args.aged.destroy);\ndiff --git a/app/test-pmd/config.c b/app/test-pmd/config.c\nindex 709864bb44..35586e0ad2 100644\n--- a/app/test-pmd/config.c\n+++ b/app/test-pmd/config.c\n@@ -6,6 +6,7 @@\n #include <ctype.h>\n #include <stdarg.h>\n #include <errno.h>\n+#include <stdbool.h>\n #include <stdio.h>\n #include <stdlib.h>\n #include <string.h>\n@@ -3301,6 +3302,59 @@ port_queue_flow_push(portid_t port_id, queueid_t queue_id)\n \treturn ret;\n }\n \n+/** Calculate the hash result for a given pattern in a given table. */\n+int\n+port_flow_hash_calc(portid_t port_id, uint32_t table_id,\n+\t\t    uint8_t pattern_template_index, const struct rte_flow_item pattern[])\n+{\n+\tuint32_t hash;\n+\tbool found;\n+\tstruct port_table *pt;\n+\tstruct rte_port *port;\n+\tstruct rte_flow_error error;\n+\tint ret = 0;\n+\n+\tif (port_id_is_invalid(port_id, ENABLED_WARN) ||\n+\t    port_id == (portid_t)RTE_PORT_ALL)\n+\t\treturn -EINVAL;\n+\tport = &ports[port_id];\n+\n+\tfound = false;\n+\tpt = port->table_list;\n+\twhile (pt) {\n+\t\tif (table_id == pt->id) {\n+\t\t\tfound = true;\n+\t\t\tbreak;\n+\t\t}\n+\t\tpt = pt->next;\n+\t}\n+\tif (!found) {\n+\t\tprintf(\"Table #%u is invalid\\n\", table_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tmemset(&error, 0x55, sizeof(error));\n+\tret = rte_flow_calc_table_hash(port_id, pt->table, pattern,\n+\t\t\t\t       pattern_template_index, &hash, &error);\n+\tif (ret < 0) {\n+\t\tprintf(\"Failed to calculate hash \");\n+\t\tswitch (abs(ret)) {\n+\t\tcase ENODEV:\n+\t\t\tprintf(\"no such device\\n\");\n+\t\t\tbreak;\n+\t\tcase ENOTSUP:\n+\t\t\tprintf(\"device doesn't support this operation\\n\");\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tprintf(\"\\n\");\n+\t\t\tbreak;\n+\t\t}\n+\t\treturn ret;\n+\t}\n+\tprintf(\"Hash results 0x%x\\n\", hash);\n+\treturn 0;\n+}\n+\n /** Pull queue operation results from the queue. */\n static int\n port_queue_aged_flow_destroy(portid_t port_id, queueid_t queue_id,\ndiff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h\nindex e236845a81..dec333a8fa 100644\n--- a/app/test-pmd/testpmd.h\n+++ b/app/test-pmd/testpmd.h\n@@ -1014,6 +1014,8 @@ port_queue_action_handle_query_update(portid_t port_id,\n \t\t\t\t      const struct rte_flow_action *action);\n int port_queue_flow_push(portid_t port_id, queueid_t queue_id);\n int port_queue_flow_pull(portid_t port_id, queueid_t queue_id);\n+int port_flow_hash_calc(portid_t port_id, uint32_t table_id,\n+\t\t\tuint8_t pattern_template_index, const struct rte_flow_item pattern[]);\n void port_queue_flow_aged(portid_t port_id, uint32_t queue_id, uint8_t destroy);\n int port_flow_validate(portid_t port_id,\n \t\t       const struct rte_flow_attr *attr,\ndiff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst\nindex 860e42025f..a11eb2977a 100644\n--- a/doc/guides/prog_guide/rte_flow.rst\n+++ b/doc/guides/prog_guide/rte_flow.rst\n@@ -4173,6 +4173,23 @@ User data may be provided during a flow creation/destruction in order\n to distinguish between multiple operations. User data is returned as part\n of the result to provide a method to detect which operation is completed.\n \n+Calculate hash\n+~~~~~~~~~~~~~~\n+\n+Calculating hash of a packet in SW as it would be calculated in HW.\n+\n+The application can use this function to calculate the hash of a given packet\n+as it would be calculated in the HW.\n+\n+.. code-block:: c\n+\n+   int\n+   rte_flow_calc_table_hash(uint16_t port_id,\n+                            const struct rte_flow_template_table *table,\n+\t\t\t                   const struct rte_flow_item pattern[],\n+                            uint8_t pattern_template_index,\n+\t\t\t                   uint32_t *hash, struct rte_flow_error *error);\n+\n .. _flow_isolated_mode:\n \n Flow isolated mode\ndiff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst\nindex e6d218caaa..1006239d86 100644\n--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst\n+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst\n@@ -3276,6 +3276,28 @@ The usual error message is shown when operations results cannot be pulled::\n \n    Caught error type [...] ([...]): [...]\n \n+Calculating hash\n+~~~~~~~~~~~~~~~~\n+\n+``flow hash`` calculates the hash for a given pattern.\n+It is bound to ``rte_flow_calc_table_hash()``::\n+\n+   flow hash {port_id} template_table {table_id}\n+       pattern_template {pattern_template_index}\n+       actions_template {actions_template_index}\n+       pattern {item} [/ {item} [...]] / end\n+\n+If successful, it will show the calculated hash result as seen below::\n+\n+   Hash results 0x[...]\n+\n+Otherwise, it will show an error message of the form::\n+\n+   Caught error type [...] ([...]): [...]\n+\n+This command uses the same pattern items as ``flow create``,\n+their format is described in `Creating flow rules`_.\n+\n Creating a tunnel stub for offload\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n \ndiff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c\nindex c9d23da702..6917fbd262 100644\n--- a/lib/ethdev/rte_flow.c\n+++ b/lib/ethdev/rte_flow.c\n@@ -2454,3 +2454,24 @@ rte_flow_async_action_list_handle_query_update(uint16_t port_id, uint32_t queue_\n \t\t\t\t\t\t\t     ret);\n \treturn ret;\n }\n+\n+int\n+rte_flow_calc_table_hash(uint16_t port_id, const struct rte_flow_template_table *table,\n+\t\t\t const struct rte_flow_item pattern[], uint8_t pattern_template_index,\n+\t\t\t uint32_t *hash, struct rte_flow_error *error)\n+{\n+\tint ret;\n+\tstruct rte_eth_dev *dev;\n+\tconst struct rte_flow_ops *ops;\n+\n+\tRTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);\n+\tops = rte_flow_ops_get(port_id, error);\n+\tif (!ops || !ops->flow_calc_table_hash)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\t  \"action_list async query_update not supported\");\n+\tdev = &rte_eth_devices[port_id];\n+\tret = ops->flow_calc_table_hash(dev, table, pattern, pattern_template_index,\n+\t\t\t\t\thash, error);\n+\treturn flow_err(port_id, ret, error);\n+}\ndiff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h\nindex e576b15e3d..00e472b65b 100644\n--- a/lib/ethdev/rte_flow.h\n+++ b/lib/ethdev/rte_flow.h\n@@ -6717,6 +6717,38 @@ rte_flow_async_action_list_handle_query_update(uint16_t port_id, uint32_t queue_\n \t\t\t\t\t  void *user_data,\n \t\t\t\t\t  struct rte_flow_error *error);\n \n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Calculate the hash for a given pattern in a given table as\n+ * calculated by the HW.\n+ *\n+ * @param port_id\n+ *   Port identifier of Ethernet device.\n+ * @param table\n+ *   The table the SW wishes to simulate.\n+ * @param pattern\n+ *   The values to be used in the hash calculation.\n+ * @param pattern_template_index\n+ *   The pattern index in the table to be used for the calculation.\n+ * @param hash\n+ *   Used to return the calculated hash.\n+ * @param error\n+ *   Perform verbose error reporting if not NULL.\n+ *   PMDs initialize this structure in case of error only.\n+ *\n+ * @return\n+ *   - (0) if success.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - (-ENOTSUP) if underlying device does not support this functionality.\n+ */\n+__rte_experimental\n+int\n+rte_flow_calc_table_hash(uint16_t port_id, const struct rte_flow_template_table *table,\n+\t\t\t const struct rte_flow_item pattern[], uint8_t pattern_template_index,\n+\t\t\t uint32_t *hash, struct rte_flow_error *error);\n+\n #ifdef __cplusplus\n }\n #endif\ndiff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h\nindex 3ced086c47..f35f659503 100644\n--- a/lib/ethdev/rte_flow_driver.h\n+++ b/lib/ethdev/rte_flow_driver.h\n@@ -365,6 +365,11 @@ struct rte_flow_ops {\n \t\t const void **update, void **query,\n \t\t enum rte_flow_query_update_mode mode,\n \t\t void *user_data, struct rte_flow_error *error);\n+\t/** @see rte_flow_calc_table_hash() */\n+\tint (*flow_calc_table_hash)\n+\t\t(struct rte_eth_dev *dev, const struct rte_flow_template_table *table,\n+\t\t const struct rte_flow_item pattern[], uint8_t pattern_template_index,\n+\t\t uint32_t *hash, struct rte_flow_error *error);\n };\n \n /**\ndiff --git a/lib/ethdev/version.map b/lib/ethdev/version.map\nindex 1e51478405..919ba5b8e6 100644\n--- a/lib/ethdev/version.map\n+++ b/lib/ethdev/version.map\n@@ -316,6 +316,7 @@ EXPERIMENTAL {\n \t# added in 23.11\n \trte_eth_recycle_rx_queue_info_get;\n \trte_flow_group_set_miss_actions;\n+\trte_flow_calc_table_hash;\n };\n \n INTERNAL {\n",
    "prefixes": [
        "v2"
    ]
}