get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 127112,
    "url": "https://patches.dpdk.org/api/patches/127112/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20230519115947.331304-1-getelson@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": "<20230519115947.331304-1-getelson@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230519115947.331304-1-getelson@nvidia.com",
    "date": "2023-05-19T11:59:47",
    "name": "[v4] ethdev: add indirect list flow action",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "20e6353f810ffa9aa8dca0c499b1c48abb09832d",
    "submitter": {
        "id": 1882,
        "url": "https://patches.dpdk.org/api/people/1882/?format=api",
        "name": "Gregory Etelson",
        "email": "getelson@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/20230519115947.331304-1-getelson@nvidia.com/mbox/",
    "series": [
        {
            "id": 28091,
            "url": "https://patches.dpdk.org/api/series/28091/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=28091",
            "date": "2023-05-19T11:59:47",
            "name": "[v4] ethdev: add indirect list flow action",
            "version": 4,
            "mbox": "https://patches.dpdk.org/series/28091/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/127112/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/127112/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 16C2042B49;\n\tFri, 19 May 2023 14:00:49 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 08AFC4161A;\n\tFri, 19 May 2023 14:00:49 +0200 (CEST)",
            "from NAM11-BN8-obe.outbound.protection.outlook.com\n (mail-bn8nam11on2041.outbound.protection.outlook.com [40.107.236.41])\n by mails.dpdk.org (Postfix) with ESMTP id B6D4541148\n for <dev@dpdk.org>; Fri, 19 May 2023 14:00:46 +0200 (CEST)",
            "from MN2PR05CA0013.namprd05.prod.outlook.com (2603:10b6:208:c0::26)\n by BN9PR12MB5132.namprd12.prod.outlook.com (2603:10b6:408:119::7)\n with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6411.21; Fri, 19 May\n 2023 12:00:43 +0000",
            "from BL02EPF000145B9.namprd05.prod.outlook.com\n (2603:10b6:208:c0:cafe::b4) by MN2PR05CA0013.outlook.office365.com\n (2603:10b6:208:c0::26) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6411.14 via Frontend\n Transport; Fri, 19 May 2023 12:00:43 +0000",
            "from mail.nvidia.com (216.228.117.160) by\n BL02EPF000145B9.mail.protection.outlook.com (10.167.241.209) with Microsoft\n SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.20.6433.8 via Frontend Transport; Fri, 19 May 2023 12:00:42 +0000",
            "from rnnvmail201.nvidia.com (10.129.68.8) by mail.nvidia.com\n (10.129.200.66) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.5; Fri, 19 May 2023\n 05:00:18 -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.37; Fri, 19 May\n 2023 05:00:14 -0700"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=CFYDDYcKroD+aF0t3m6R3643+wr/KzIhF0zPHSM/eYyMzKRkUOuSQPZUNEU4u07zjAq8GgrY+A3BS1G9JsAAqGPaMIvv8Hk4BMvYKTfq3PNxi+6cvpwCnZJnOEVbap2OmlZObSBY9lwoSyuHOOHlwn+H9KVV7PSPWH5sSqaxLUcSGfNPQ/e783voE0POglVTvOPHQd2E1hriLjnSdRhM0F/l4g8GsY81MeYUrCHdoJbGkNqYAwO2Its7MfPltAoc2w1D9OK8cFpN74GfOSOrLNdl+4rujuc6HOIe+gnpmM4HiCp+5Svk5MzFGm1olTvP6x8cGbDnmpYGUL/ktpkbYQ==",
        "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=QvSu+sVVO6xS6LQawNw2TNBIJH7bee7jy8/0Hyov7Bw=;\n b=OC7DD+nYUiPv4eMEGhKdfJ2OGRPFRlqlLGQeolDo7qrrh2sLqFVU9Hp0xsdHjUr12wKbNooO7bWJOYFg6lOViW+tvQEZ5jR2v8B11WmJe5pzR/sKWitBm3IG0d+joTPocIXFCRTs1MbmT4D91j7X3nDMJpdj093w8vWSorDghu5tBa2iEZ5LiZFqF0F/MEefpjQu8yf2yOv2gmql1dLdHcrNaPCUOrT/l4Nq1ZGp1mFG+64zFNrunJYhwEd6R0ctB46dtB2gT6jVkVBUlGe3SY6NCPVBqDTvYkJfsXoK/phUujLHX3UpJ/fKmg0vI2nwgVeEnUr9/B3W5VMxUDX1qQ==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass (sender ip is\n 216.228.117.160) smtp.rcpttodomain=dpdk.org 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=QvSu+sVVO6xS6LQawNw2TNBIJH7bee7jy8/0Hyov7Bw=;\n b=VxxgUoUgUiPpFI6upGETTbRWvHG4paU8ceK7K40IiXPOFMAa50urV0qzDX6dYAdOUiRynorg6Peew/nk1mcie0Rb4QeOWS/h27a6ik66YG5olxXUrVeb/FT/gJn+G2qANE02SiGFmcVIbQulRYgdKQ3IqyEhn4hBHuhhLYj+MeDl4QRBh/HN1Aje064bEkbRMWcfiQqYsjzpw+R8g1KcrZuHgnY9HChGLmLk2ZGOJWuhe32Obegyq8Ax20DWuEH2AforilJoH/FAMkAyqx0YBIEvbIbFlnBgg6cWZfCZT5x/4OXea2LnIeS7ixwaickFg/ZztElm2Y/o3wypKlx4eg==",
        "X-MS-Exchange-Authentication-Results": "spf=pass (sender IP is 216.228.117.160)\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.160 as permitted sender) receiver=protection.outlook.com;\n client-ip=216.228.117.160; helo=mail.nvidia.com; pr=C",
        "From": "Gregory Etelson <getelson@nvidia.com>",
        "To": "<dev@dpdk.org>",
        "CC": "<getelson@nvidia.com>, <mkashani@nvidia.com>, <rasland@nvidia.com>, \"Ori\n Kam\" <orika@nvidia.com>, Aman Singh <aman.deep.singh@intel.com>, Yuying Zhang\n <yuying.zhang@intel.com>, Ferruh Yigit <ferruh.yigit@amd.com>, \"Thomas\n Monjalon\" <thomas@monjalon.net>, Andrew Rybchenko\n <andrew.rybchenko@oktetlabs.ru>",
        "Subject": "[PATCH v4] ethdev: add indirect list flow action",
        "Date": "Fri, 19 May 2023 14:59:47 +0300",
        "Message-ID": "<20230519115947.331304-1-getelson@nvidia.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20230418172144.24365-1-getelson@nvidia.com>",
        "References": "<20230418172144.24365-1-getelson@nvidia.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"UTF-8\"",
        "Content-Transfer-Encoding": "8bit",
        "X-Originating-IP": "[10.126.230.35]",
        "X-ClientProxiedBy": "rnnvmail203.nvidia.com (10.129.68.9) To\n rnnvmail201.nvidia.com (10.129.68.8)",
        "X-EOPAttributedMessage": "0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "BL02EPF000145B9:EE_|BN9PR12MB5132:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "9e85ec81-c26a-43ed-5729-08db5860ac0c",
        "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 7ejbSxaMhchDEBW0pSt/t0LH6dtyRN5xCb08GTNii/EoMS7X8pRwFfNoRdWB/+A7gj62r00G/azXnSIXJ7si0b754kroAv2VKsyUX3pzeK1rmRCy7WTApD7oOMcAf/BfTd6TjsQsmrt6LKUO6rGjjTbHPXVLonuUEOVzO1tT6TsXAK+du07vEZH85li6Uic/I8/soPG/PYk9wHxzEp5cPxhqtG2eWoxrRf1qBmoBHPHOvYQcLiEQDU3jBJN02iTl6F61UFjfCwPyVlu+DHdc7cGNuPcWuCQPAff+oZm0LNlEWb9sRuUuQQklps9TAvZPWS/Tgqb5slI2UyPDDN25PgC6CEpvWkHROsFGNrbMVtkDAjLPSs+VIgeQuKWeTDW5f9sve2Vy+IpxZHqjrvTb2q72VyRSY1Idv5VO76psW1XLrwK2jzwtiJU00JAoHWceLAsRO7rg8umR+1KwVW/bwymWAyIPq1AIm1b7hqAfiTe3KmQWVSeUQpP46gvlrREO/I5ClJU/pljyplR1E9OEkOkjAP0S044j430hg6fDlCf60gronJL3qB3aiZKtMQoOTq96GHfV0jk7GAr0qt+g7ExYVgae747pJT3H1LW9g0ciSkxp01TozB4+yj7QZjF+I3E14IMx07U+j/MZP0X03PIIuhGIRpl/seRBEvTbJ/WgHlQM18O+OsglZMgoVifFQuw+d7NhCB6JCAS3bpOODfV79DAq/DrwewUX38VPnka5hg1M5M/tg1uIqIbjDo+v",
        "X-Forefront-Antispam-Report": "CIP:216.228.117.160; CTRY:US; LANG:en; SCL:1;\n SRV:;\n IPV:NLI; SFV:NSPM; H:mail.nvidia.com; PTR:dc6edge1.nvidia.com; CAT:NONE;\n SFS:(13230028)(4636009)(376002)(39860400002)(396003)(136003)(346002)(451199021)(40470700004)(46966006)(36840700001)(54906003)(30864003)(478600001)(316002)(70206006)(6916009)(186003)(6666004)(70586007)(2906002)(4326008)(8676002)(5660300002)(8936002)(26005)(1076003)(16526019)(6286002)(2616005)(47076005)(336012)(426003)(83380400001)(36860700001)(7696005)(41300700001)(55016003)(356005)(82740400003)(7636003)(82310400005)(40460700003)(86362001)(40480700001)(36756003)(579004)(559001);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "Nvidia.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "19 May 2023 12:00:42.7776 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 9e85ec81-c26a-43ed-5729-08db5860ac0c",
        "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.160];\n Helo=[mail.nvidia.com]",
        "X-MS-Exchange-CrossTenant-AuthSource": "\n BL02EPF000145B9.namprd05.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "BN9PR12MB5132",
        "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": "Indirect API creates a shared flow action with unique action handle.\nFlow rules can access the shared flow action and resources related to\nthat action through the indirect action handle.\nIn addition, the API allows to update existing shared flow action\nconfiguration.  After the update completes, new action configuration\nis available to all flows that reference that shared action.\n\nIndirect actions list expands the indirect action API:\n• Indirect action list creates a handle for one or several\n  flow actions, while legacy indirect action handle references\n  single action only.\n  Input flow actions arranged in END terminated list.\n• Flow rule can provide rule specific configuration parameters to\n  existing shared handle.\n  Updates of flow rule specific configuration will not change the base\n  action configuration.\n  Base action configuration was set during the action creation.\n\nIndirect action list handle defines 2 types of resources:\n• Mutable handle resource can be changed during handle lifespan.\n• Immutable handle resource value is set during handle creation\n  and cannot be changed.\n\nThere are 2 types of mutable indirect handle contexts:\n• Action mutable context is always shared between all flows\n  that referenced indirect actions list handle.\n  Action mutable context can be changed by explicit invocation\n  of indirect handle update function.\n• Flow mutable context is private to a flow.\n  Flow mutable context can be updated by indirect list handle\n  flow rule configuration.\n\nflow 1:\n / indirect handle H conf C1 /\n                   |       |\n                   |       |\n                   |       |         flow 2:\n                   |       |         / indirect handle H conf C2 /\n                   |       |                           |      |\n                   |       |                           |      |\n                   |       |                           |      |\n            =========================================================\n            ^      |       |                           |      |\n            |      |       V                           |      V\n            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~\n            |     flow mutable                        flow mutable\n            |     context 1                           context 2\n            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~\n  indirect  |      |                                   |\n  action    |      |                                   |\n  context   |      V                                   V\n            |   -----------------------------------------------------\n            |                 action mutable context\n            |   -----------------------------------------------------\n            v                action immutable context\n            =========================================================\n\nIndirect action types - immutable, action / flow mutable, are mutually\nexclusive and depend on the action definition.\nFor example:\n• Indirect METER_MARK policy is immutable action member and profile is\n  action mutable action member.\n• Indirect METER_MARK flow action defines init_color as flow mutable\n  member.\n• Indirect QUOTA flow action does not define flow mutable members.\n\nIf indirect list handle was created from a list of actions\nA1 / A2 ... An / END\nindirect list flow action can update Ai flow mutable context in the\naction configuration parameter.\nIndirect list action configuration is and array [C1, C2,  .., Cn]\nwhere Ci corresponds to Ai in the action handle source.\nCi configuration element points Ai flow mutable update, or it's NULL\nif Ai has no flow mutable update.\nIndirect list action configuration can be NULL if the action\nhas no flow mutable updates.\n\nTemplate API:\n\nAction template format:\n\n\ttemplate .. indirect_list handle Htmpl conf Ctmpl ..\n\tmask     .. indirect_list handle Hmask conf Cmask ..\n\n1 If Htmpl was masked (Hmask != 0), it will be fixed in that template.\n  Otherwise, indirect action value is set in a flow rule.\n\n2 If Htmpl and Ctmpl[i] were masked (Hmask !=0 and Cmask[i] != 0),\n  Htmpl's Ai action flow mutable context fill be updated to\n  Ctmpl[i] values and will be fixed in that template.\n\nFlow rule format:\n\n\tactions .. indirect_list handle Hflow conf Cflow ..\n\n3 If Htmpl was not masked in actions template, Hflow references an\n  action of the same type as Htmpl.\n\n4 Cflow[i] updates handle's Ai flow mutable configuration if\n  the Ci was not masked in action template.\n\nSigned-off-by: Gregory Etelson <getelson@nvidia.com>\n---\n app/test-pmd/cmdline_flow.c            | 207 ++++++++++++++++++-\n app/test-pmd/config.c                  | 163 +++++++++++----\n app/test-pmd/testpmd.h                 |   9 +-\n doc/guides/nics/features/default.ini   |   1 +\n doc/guides/prog_guide/rte_flow.rst     | 119 +++++++++++\n doc/guides/rel_notes/release_23_07.rst |   2 +\n lib/ethdev/ethdev_trace.h              |  88 ++++++++\n lib/ethdev/ethdev_trace_points.c       |  18 ++\n lib/ethdev/rte_flow.c                  | 171 ++++++++++++++++\n lib/ethdev/rte_flow.h                  | 269 +++++++++++++++++++++++++\n lib/ethdev/rte_flow_driver.h           |  41 ++++\n lib/ethdev/version.map                 |   8 +\n 12 files changed, 1054 insertions(+), 42 deletions(-)",
    "diff": "diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c\nindex 58939ec321..4663b6217f 100644\n--- a/app/test-pmd/cmdline_flow.c\n+++ b/app/test-pmd/cmdline_flow.c\n@@ -145,6 +145,7 @@ enum index {\n \n \t/* Queue indirect action arguments */\n \tQUEUE_INDIRECT_ACTION_CREATE,\n+\tQUEUE_INDIRECT_ACTION_LIST_CREATE,\n \tQUEUE_INDIRECT_ACTION_UPDATE,\n \tQUEUE_INDIRECT_ACTION_DESTROY,\n \tQUEUE_INDIRECT_ACTION_QUERY,\n@@ -157,6 +158,7 @@ enum index {\n \tQUEUE_INDIRECT_ACTION_TRANSFER,\n \tQUEUE_INDIRECT_ACTION_CREATE_POSTPONE,\n \tQUEUE_INDIRECT_ACTION_SPEC,\n+\tQUEUE_INDIRECT_ACTION_LIST,\n \n \t/* Queue indirect action update arguments */\n \tQUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,\n@@ -242,6 +244,8 @@ enum index {\n \n \t/* Indirect action arguments */\n \tINDIRECT_ACTION_CREATE,\n+\tINDIRECT_ACTION_LIST_CREATE,\n+\tINDIRECT_ACTION_FLOW_CONF_CREATE,\n \tINDIRECT_ACTION_UPDATE,\n \tINDIRECT_ACTION_DESTROY,\n \tINDIRECT_ACTION_QUERY,\n@@ -253,6 +257,8 @@ enum index {\n \tINDIRECT_ACTION_EGRESS,\n \tINDIRECT_ACTION_TRANSFER,\n \tINDIRECT_ACTION_SPEC,\n+\tINDIRECT_ACTION_LIST,\n+\tINDIRECT_ACTION_FLOW_CONF,\n \n \t/* Indirect action destroy arguments */\n \tINDIRECT_ACTION_DESTROY_ID,\n@@ -626,6 +632,11 @@ enum index {\n \tACTION_SAMPLE_INDEX,\n \tACTION_SAMPLE_INDEX_VALUE,\n \tACTION_INDIRECT,\n+\tACTION_INDIRECT_LIST,\n+\tACTION_INDIRECT_LIST_HANDLE,\n+\tACTION_INDIRECT_LIST_CONF,\n+\tINDIRECT_LIST_ACTION_ID2PTR_HANDLE,\n+\tINDIRECT_LIST_ACTION_ID2PTR_CONF,\n \tACTION_SHARED_INDIRECT,\n \tINDIRECT_ACTION_PORT,\n \tINDIRECT_ACTION_ID2PTR,\n@@ -1266,6 +1277,7 @@ static const enum index next_qia_create_attr[] = {\n \tQUEUE_INDIRECT_ACTION_TRANSFER,\n \tQUEUE_INDIRECT_ACTION_CREATE_POSTPONE,\n \tQUEUE_INDIRECT_ACTION_SPEC,\n+\tQUEUE_INDIRECT_ACTION_LIST,\n \tZERO,\n };\n \n@@ -1294,6 +1306,8 @@ static const enum index next_ia_create_attr[] = {\n \tINDIRECT_ACTION_EGRESS,\n \tINDIRECT_ACTION_TRANSFER,\n \tINDIRECT_ACTION_SPEC,\n+\tINDIRECT_ACTION_LIST,\n+\tINDIRECT_ACTION_FLOW_CONF,\n \tZERO,\n };\n \n@@ -1303,6 +1317,13 @@ static const enum index next_ia[] = {\n \tZERO\n };\n \n+static const enum index next_ial[] = {\n+\tACTION_INDIRECT_LIST_HANDLE,\n+\tACTION_INDIRECT_LIST_CONF,\n+\tACTION_NEXT,\n+\tZERO\n+};\n+\n static const enum index next_qia_qu_attr[] = {\n \tQUEUE_INDIRECT_ACTION_QU_MODE,\n \tQUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,\n@@ -2013,6 +2034,7 @@ static const enum index next_action[] = {\n \tACTION_AGE_UPDATE,\n \tACTION_SAMPLE,\n \tACTION_INDIRECT,\n+\tACTION_INDIRECT_LIST,\n \tACTION_SHARED_INDIRECT,\n \tACTION_MODIFY_FIELD,\n \tACTION_CONNTRACK,\n@@ -2289,6 +2311,7 @@ static const enum index next_action_sample[] = {\n \tACTION_RAW_ENCAP,\n \tACTION_VXLAN_ENCAP,\n \tACTION_NVGRE_ENCAP,\n+\tACTION_REPRESENTED_PORT,\n \tACTION_NEXT,\n \tZERO,\n };\n@@ -2539,6 +2562,10 @@ static int parse_ia_destroy(struct context *ctx, const struct token *token,\n static int parse_ia_id2ptr(struct context *ctx, const struct token *token,\n \t\t\t   const char *str, unsigned int len, void *buf,\n \t\t\t   unsigned int size);\n+\n+static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,\n+\t\t\t       const char *str, unsigned int len, void *buf,\n+\t\t\t       unsigned int size);\n static int parse_ia_port(struct context *ctx, const struct token *token,\n \t\t\t const char *str, unsigned int len, void *buf,\n \t\t\t unsigned int size);\n@@ -2627,6 +2654,16 @@ static int\n comp_qu_mode_name(struct context *ctx, const struct token *token,\n \t\t  unsigned int ent, char *buf, unsigned int size);\n \n+struct indlst_conf {\n+\tuint32_t id;\n+\tuint32_t conf_num;\n+\tstruct rte_flow_action *actions;\n+\tconst void **conf;\n+\tSLIST_ENTRY(indlst_conf) next;\n+};\n+\n+static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);\n+\n /** Token definitions. */\n static const struct token token_list[] = {\n \t/* Special tokens. */\n@@ -3426,6 +3463,12 @@ static const struct token token_list[] = {\n \t\t.help = \"specify action to create indirect handle\",\n \t\t.next = NEXT(next_action),\n \t},\n+\t[QUEUE_INDIRECT_ACTION_LIST] = {\n+\t\t.name = \"list\",\n+\t\t.help = \"specify actions for indirect handle list\",\n+\t\t.next = NEXT(NEXT_ENTRY(ACTIONS, END)),\n+\t\t.call = parse_qia,\n+\t},\n \t/* Top-level command. */\n \t[PUSH] = {\n \t\t.name = \"push\",\n@@ -6775,6 +6818,37 @@ static const struct token token_list[] = {\n \t\t.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),\n \t\t.call = parse_vc,\n \t},\n+\t[ACTION_INDIRECT_LIST] = {\n+\t\t.name = \"indirect_list\",\n+\t\t.help = \"apply indirect list action by id\",\n+\t\t.priv = PRIV_ACTION(INDIRECT_LIST,\n+\t\t\t\t    sizeof(struct\n+\t\t\t\t           rte_flow_action_indirect_list)),\n+\t\t.next = NEXT(next_ial),\n+\t\t.call = parse_vc,\n+\t},\n+\t[ACTION_INDIRECT_LIST_HANDLE] = {\n+\t\t.name = \"handle\",\n+\t\t.help = \"indirect list handle\",\n+\t\t.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),\n+\t\t.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uintptr_t))),\n+\t},\n+\t[ACTION_INDIRECT_LIST_CONF] = {\n+\t\t.name = \"conf\",\n+\t\t.help = \"indirect list configuration\",\n+\t\t.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),\n+\t\t.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uintptr_t))),\n+\t},\n+\t[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {\n+\t\t.type = \"UNSIGNED\",\n+\t\t.help = \"unsigned integer value\",\n+\t\t.call = parse_indlst_id2ptr,\n+\t},\n+\t[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {\n+\t\t.type = \"UNSIGNED\",\n+\t\t.help = \"unsigned integer value\",\n+\t\t.call = parse_indlst_id2ptr,\n+\t},\n \t[ACTION_SHARED_INDIRECT] = {\n \t\t.name = \"shared_indirect\",\n \t\t.help = \"apply indirect action by id and port\",\n@@ -6823,6 +6897,18 @@ static const struct token token_list[] = {\n \t\t.help = \"specify action to create indirect handle\",\n \t\t.next = NEXT(next_action),\n \t},\n+\t[INDIRECT_ACTION_LIST] = {\n+\t\t.name = \"list\",\n+\t\t.help = \"specify actions for indirect handle list\",\n+\t\t.next = NEXT(NEXT_ENTRY(ACTIONS, END)),\n+\t\t.call = parse_ia,\n+\t},\n+\t[INDIRECT_ACTION_FLOW_CONF] = {\n+\t\t.name = \"flow_conf\",\n+\t\t.help = \"specify actions configuration for indirect handle list\",\n+\t\t.next = NEXT(NEXT_ENTRY(ACTIONS, END)),\n+\t\t.call = parse_ia,\n+\t},\n \t[ACTION_POL_G] = {\n \t\t.name = \"g_actions\",\n \t\t.help = \"submit a list of associated actions for green\",\n@@ -7181,6 +7267,12 @@ parse_ia(struct context *ctx, const struct token *token,\n \t\treturn len;\n \tcase INDIRECT_ACTION_QU_MODE:\n \t\treturn len;\n+\tcase INDIRECT_ACTION_LIST:\n+\t\tout->command = INDIRECT_ACTION_LIST_CREATE;\n+\t\treturn len;\n+        case INDIRECT_ACTION_FLOW_CONF:\n+\t\tout->command = INDIRECT_ACTION_FLOW_CONF_CREATE;\n+\t\treturn len;\n \tdefault:\n \t\treturn -1;\n \t}\n@@ -7278,6 +7370,9 @@ parse_qia(struct context *ctx, const struct token *token,\n \t\treturn len;\n \tcase QUEUE_INDIRECT_ACTION_QU_MODE:\n \t\treturn len;\n+\tcase QUEUE_INDIRECT_ACTION_LIST:\n+\t\tout->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;\n+\t\treturn len;\n \tdefault:\n \t\treturn -1;\n \t}\n@@ -7454,10 +7549,12 @@ parse_vc(struct context *ctx, const struct token *token,\n \t\t\treturn -1;\n \t\tbreak;\n \tcase ACTIONS:\n-\t\tout->args.vc.actions =\n+\t\tout->args.vc.actions = out->args.vc.pattern ?\n \t\t\t(void *)RTE_ALIGN_CEIL((uintptr_t)\n \t\t\t\t\t       (out->args.vc.pattern +\n \t\t\t\t\t\tout->args.vc.pattern_n),\n+\t\t\t\t\t       sizeof(double)) :\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.actions;\n \t\tctx->objmask = NULL;\n@@ -10412,6 +10509,49 @@ parse_ia_id2ptr(struct context *ctx, const struct token *token,\n \treturn ret;\n }\n \n+static int\n+parse_indlst_id2ptr(struct context *ctx, const struct token *token,\n+\t\t    const char *str, unsigned int len,\n+\t\t    void __rte_unused *buf, unsigned int __rte_unused size)\n+{\n+\tstruct rte_flow_action *action = ctx->object;\n+\tstruct rte_flow_action_indirect_list *action_conf;\n+\tconst struct indlst_conf *indlst_conf;\n+\tuint32_t id;\n+\tint ret;\n+\n+\tif (!action)\n+\t\treturn -1;\n+\tctx->objdata = 0;\n+\tctx->object = &id;\n+\tctx->objmask = NULL;\n+\tret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));\n+\tif (ret != (int)len)\n+\t\treturn ret;\n+\tctx->object = action;\n+\taction_conf = (void *)(uintptr_t)action->conf;\n+\taction_conf->conf = NULL;\n+\tswitch (ctx->curr) {\n+\tcase INDIRECT_LIST_ACTION_ID2PTR_HANDLE:\n+        action_conf->handle = (typeof(action_conf->handle))\n+\t\t\t\tport_action_handle_get_by_id(ctx->port, id);\n+\t\tif (!action_conf->handle) {\n+\t\t\tprintf(\"no indirect list handle for id %u\\n\", id);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbreak;\n+\tcase INDIRECT_LIST_ACTION_ID2PTR_CONF:\n+\t\tindlst_conf = indirect_action_list_conf_get(id);\n+\t\tif (!indlst_conf)\n+\t\t\treturn -1;\n+\t\taction_conf->conf = (const void **)indlst_conf->conf;\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\treturn ret;\n+}\n+\n static int\n parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,\n \t\tconst char *str, unsigned int len,\n@@ -11453,6 +11593,64 @@ cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,\n \t*hdr = &cmd_flow_token_hdr;\n }\n \n+static SLIST_HEAD(, indlst_conf) indlst_conf_head =\n+\tSLIST_HEAD_INITIALIZER();\n+\n+static void\n+indirect_action_flow_conf_create(const struct buffer *in)\n+{\n+\tint len, ret;\n+\tuint32_t i;\n+\tstruct indlst_conf *indlst_conf = NULL;\n+\tsize_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);\n+\tstruct rte_flow_action *src = in->args.vc.actions;\n+\n+\tif (!in->args.vc.actions_n)\n+\t\tgoto end;\n+\tlen = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);\n+\tif (len <= 0)\n+\t\tgoto end;\n+\tlen = RTE_ALIGN(len, 16);\n+\n+\tindlst_conf = calloc(1, base + len +\n+\t\t\t     in->args.vc.actions_n * sizeof(uintptr_t));\n+\tif (!indlst_conf)\n+\t\tgoto end;\n+\tindlst_conf->id = in->args.vc.attr.group;\n+\tindlst_conf->conf_num = in->args.vc.actions_n - 1;\n+\tindlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);\n+\tret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,\n+\t\t\t    len, src, NULL);\n+\tif (ret <= 0) {\n+\t\tfree(indlst_conf);\n+\t\tindlst_conf = NULL;\n+\t\tgoto end;\n+\t}\n+\tindlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);\n+\tfor (i = 0; i < indlst_conf->conf_num; i++)\n+\t\tindlst_conf->conf[i] = indlst_conf->actions[i].conf;\n+\tSLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);\n+end:\n+\tif (indlst_conf)\n+        printf(\"created indirect action list configuration %u\\n\",\n+               in->args.vc.attr.group);\n+\telse\n+        printf(\"cannot create indirect action list configuration %u\\n\",\n+               in->args.vc.attr.group);\n+}\n+\n+static const struct indlst_conf *\n+indirect_action_list_conf_get(uint32_t conf_id)\n+{\n+\tconst struct indlst_conf *conf;\n+\n+\tSLIST_FOREACH(conf, &indlst_conf_head, next) {\n+\t\tif (conf->id == conf_id)\n+\t\t\treturn conf;\n+\t}\n+\treturn NULL;\n+}\n+\n /** Dispatch parsed buffer to function calls. */\n static void\n cmd_flow_parsed(const struct buffer *in)\n@@ -11532,6 +11730,7 @@ cmd_flow_parsed(const struct buffer *in)\n \t\t\t\t     in->args.aged.destroy);\n \t\tbreak;\n \tcase QUEUE_INDIRECT_ACTION_CREATE:\n+\tcase QUEUE_INDIRECT_ACTION_LIST_CREATE:\n \t\tport_queue_action_handle_create(\n \t\t\t\tin->port, in->queue, in->postpone,\n \t\t\t\tin->args.vc.attr.group,\n@@ -11567,8 +11766,10 @@ cmd_flow_parsed(const struct buffer *in)\n \t\t\t\t\t\t      in->args.vc.actions);\n \t\tbreak;\n \tcase INDIRECT_ACTION_CREATE:\n+\tcase INDIRECT_ACTION_LIST_CREATE:\n \t\tport_action_handle_create(\n \t\t\t\tin->port, in->args.vc.attr.group,\n+\t\t\t\tin->command == INDIRECT_ACTION_LIST_CREATE,\n \t\t\t\t&((const struct rte_flow_indir_action_conf) {\n \t\t\t\t\t.ingress = in->args.vc.attr.ingress,\n \t\t\t\t\t.egress = in->args.vc.attr.egress,\n@@ -11576,6 +11777,9 @@ cmd_flow_parsed(const struct buffer *in)\n \t\t\t\t}),\n \t\t\t\tin->args.vc.actions);\n \t\tbreak;\n+\tcase INDIRECT_ACTION_FLOW_CONF_CREATE:\n+\t\tindirect_action_flow_conf_create(in);\n+\t\tbreak;\n \tcase INDIRECT_ACTION_DESTROY:\n \t\tport_action_handle_destroy(in->port,\n \t\t\t\t\t   in->args.ia_destroy.action_id_n,\n@@ -11653,6 +11857,7 @@ cmd_flow_parsed(const struct buffer *in)\n \tdefault:\n \t\tbreak;\n \t}\n+\tfflush(stdout);\n }\n \n /** Token generator and output processing callback (cmdline API). */\ndiff --git a/app/test-pmd/config.c b/app/test-pmd/config.c\nindex 096c218c12..f35088a6e9 100644\n--- a/app/test-pmd/config.c\n+++ b/app/test-pmd/config.c\n@@ -1764,19 +1764,13 @@ port_flow_configure(portid_t port_id,\n \treturn 0;\n }\n \n-/** Create indirect action */\n-int\n-port_action_handle_create(portid_t port_id, uint32_t id,\n-\t\t\t  const struct rte_flow_indir_action_conf *conf,\n-\t\t\t  const struct rte_flow_action *action)\n+static int\n+action_handle_create(portid_t port_id,\n+\t\t     struct port_indirect_action *pia,\n+\t\t     const struct rte_flow_indir_action_conf *conf,\n+\t\t     const struct rte_flow_action *action,\n+\t\t     struct rte_flow_error *error)\n {\n-\tstruct port_indirect_action *pia;\n-\tint ret;\n-\tstruct rte_flow_error error;\n-\n-\tret = action_alloc(port_id, id, &pia);\n-\tif (ret)\n-\t\treturn ret;\n \tif (action->type == RTE_FLOW_ACTION_TYPE_AGE) {\n \t\tstruct rte_flow_action_age *age =\n \t\t\t(struct rte_flow_action_age *)(uintptr_t)(action->conf);\n@@ -1785,20 +1779,52 @@ port_action_handle_create(portid_t port_id, uint32_t id,\n \t\tage->context = &pia->age_type;\n \t} else if (action->type == RTE_FLOW_ACTION_TYPE_CONNTRACK) {\n \t\tstruct rte_flow_action_conntrack *ct =\n-\t\t(struct rte_flow_action_conntrack *)(uintptr_t)(action->conf);\n+\t\t\t(struct rte_flow_action_conntrack *)(uintptr_t)(action->conf);\n \n \t\tmemcpy(ct, &conntrack_context, sizeof(*ct));\n \t}\n+\tpia->type = action->type;\n+\tpia->handle = rte_flow_action_handle_create(port_id, conf, action,\n+\t\t\t\t\t\t    error);\n+\treturn pia->handle ? 0 : -1;\n+}\n+\n+static int\n+action_list_handle_create(portid_t port_id,\n+\t\t\t  struct port_indirect_action *pia,\n+\t\t\t  const struct rte_flow_indir_action_conf *conf,\n+\t\t\t  const struct rte_flow_action *actions,\n+\t\t\t  struct rte_flow_error *error)\n+{\n+\tpia->type = RTE_FLOW_ACTION_TYPE_INDIRECT_LIST;\n+\tpia->list_handle =\n+\t\trte_flow_action_list_handle_create(port_id, conf,\n+\t\t\t\t\t\t   actions, error);\n+\treturn pia->list_handle ? 0 : -1;\n+}\n+/** Create indirect action */\n+int\n+port_action_handle_create(portid_t port_id, uint32_t id, bool indirect_list,\n+\t\t\t  const struct rte_flow_indir_action_conf *conf,\n+\t\t\t  const struct rte_flow_action *action)\n+{\n+\tstruct port_indirect_action *pia;\n+\tint ret;\n+\tstruct rte_flow_error error;\n+\n+\tret = action_alloc(port_id, id, &pia);\n+\tif (ret)\n+\t\treturn ret;\n \t/* Poisoning to make sure PMDs update it in case of error. */\n \tmemset(&error, 0x22, sizeof(error));\n-\tpia->handle = rte_flow_action_handle_create(port_id, conf, action,\n-\t\t\t\t\t\t    &error);\n-\tif (!pia->handle) {\n+\tret = indirect_list ?\n+\t       action_list_handle_create(port_id, pia, conf, action, &error) :\n+\t       action_handle_create(port_id, pia, conf, action, &error);\n+\tif (ret) {\n \t\tuint32_t destroy_id = pia->id;\n \t\tport_action_handle_destroy(port_id, 1, &destroy_id);\n \t\treturn port_flow_complain(&error);\n \t}\n-\tpia->type = action->type;\n \tprintf(\"Indirect action #%u created\\n\", pia->id);\n \treturn 0;\n }\n@@ -1833,10 +1859,17 @@ port_action_handle_destroy(portid_t port_id,\n \t\t\t */\n \t\t\tmemset(&error, 0x33, sizeof(error));\n \n-\t\t\tif (pia->handle && rte_flow_action_handle_destroy(\n-\t\t\t\t\tport_id, pia->handle, &error)) {\n-\t\t\t\tret = port_flow_complain(&error);\n-\t\t\t\tcontinue;\n+\t\t\tif (pia->handle) {\n+\t\t\t\tret = pia->type ==\n+\t\t\t\t      RTE_FLOW_ACTION_TYPE_INDIRECT_LIST ?\n+\t\t\t\t\trte_flow_action_list_handle_destroy\n+\t\t\t\t\t(port_id, pia->list_handle, &error) :\n+\t\t\t\t\trte_flow_action_handle_destroy\n+\t\t\t\t\t(port_id, pia->handle, &error);\n+\t\t\t\tif (ret) {\n+\t\t\t\t\tret = port_flow_complain(&error);\n+\t\t\t\t\tcontinue;\n+\t\t\t\t}\n \t\t\t}\n \t\t\t*tmp = pia->next;\n \t\t\tprintf(\"Indirect action #%u destroyed\\n\", pia->id);\n@@ -1867,11 +1900,18 @@ port_action_handle_flush(portid_t port_id)\n \n \t\t/* Poisoning to make sure PMDs update it in case of error. */\n \t\tmemset(&error, 0x44, sizeof(error));\n-\t\tif (pia->handle != NULL &&\n-\t\t    rte_flow_action_handle_destroy\n-\t\t\t\t\t(port_id, pia->handle, &error) != 0) {\n-\t\t\tprintf(\"Indirect action #%u not destroyed\\n\", pia->id);\n-\t\t\tret = port_flow_complain(&error);\n+\t\tif (pia->handle != NULL) {\n+\t\t\tret = pia->type ==\n+\t\t\t      RTE_FLOW_ACTION_TYPE_INDIRECT_LIST ?\n+\t\t\t      rte_flow_action_list_handle_destroy\n+\t\t\t\t      (port_id, pia->list_handle, &error) :\n+\t\t\t      rte_flow_action_handle_destroy\n+\t\t\t\t      (port_id, pia->handle, &error);\n+\t\t\tif (ret) {\n+\t\t\t\tprintf(\"Indirect action #%u not destroyed\\n\",\n+\t\t\t\t       pia->id);\n+\t\t\t\tret = port_flow_complain(&error);\n+\t\t\t}\n \t\t\ttmp = &pia->next;\n \t\t} else {\n \t\t\t*tmp = pia->next;\n@@ -2822,6 +2862,45 @@ port_queue_flow_destroy(portid_t port_id, queueid_t queue_id,\n \treturn ret;\n }\n \n+static void\n+queue_action_handle_create(portid_t port_id, uint32_t queue_id,\n+\t\t\t   struct port_indirect_action *pia,\n+\t\t\t   struct queue_job *job,\n+\t\t\t   const struct rte_flow_op_attr *attr,\n+\t\t\t   const struct rte_flow_indir_action_conf *conf,\n+\t\t\t   const struct rte_flow_action *action,\n+\t\t\t   struct rte_flow_error *error)\n+{\n+\tif (action->type == RTE_FLOW_ACTION_TYPE_AGE) {\n+\t\tstruct rte_flow_action_age *age =\n+\t\t\t(struct rte_flow_action_age *)(uintptr_t)(action->conf);\n+\n+\t\tpia->age_type = ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION;\n+\t\tage->context = &pia->age_type;\n+\t}\n+\t/* Poisoning to make sure PMDs update it in case of error. */\n+\tpia->handle = rte_flow_async_action_handle_create(port_id, queue_id,\n+\t\t\t\t\t\t\t  attr, conf, action,\n+\t\t\t\t\t\t\t  job, error);\n+\tpia->type = action->type;\n+}\n+\n+static void\n+queue_action_list_handle_create(portid_t port_id, uint32_t queue_id,\n+\t\t\t\tstruct port_indirect_action *pia,\n+\t\t\t\tstruct queue_job *job,\n+\t\t\t\tconst struct rte_flow_op_attr *attr,\n+\t\t\t\tconst struct rte_flow_indir_action_conf *conf,\n+\t\t\t\tconst struct rte_flow_action *action,\n+\t\t\t\tstruct rte_flow_error *error)\n+{\n+\t/* Poisoning to make sure PMDs update it in case of error. */\n+\tpia->type = RTE_FLOW_ACTION_TYPE_INDIRECT_LIST;\n+\tpia->list_handle = rte_flow_async_action_list_handle_create\n+\t\t(port_id, queue_id, attr, conf, action,\n+\t\t job, error);\n+}\n+\n /** Enqueue indirect action create operation. */\n int\n port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,\n@@ -2835,6 +2914,8 @@ port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,\n \tint ret;\n \tstruct rte_flow_error error;\n \tstruct queue_job *job;\n+\tbool is_indirect_list = action[1].type != RTE_FLOW_ACTION_TYPE_END;\n+\n \n \tret = action_alloc(port_id, id, &pia);\n \tif (ret)\n@@ -2853,17 +2934,16 @@ port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,\n \tjob->type = QUEUE_JOB_TYPE_ACTION_CREATE;\n \tjob->pia = pia;\n \n-\tif (action->type == RTE_FLOW_ACTION_TYPE_AGE) {\n-\t\tstruct rte_flow_action_age *age =\n-\t\t\t(struct rte_flow_action_age *)(uintptr_t)(action->conf);\n-\n-\t\tpia->age_type = ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION;\n-\t\tage->context = &pia->age_type;\n-\t}\n \t/* Poisoning to make sure PMDs update it in case of error. */\n \tmemset(&error, 0x88, sizeof(error));\n-\tpia->handle = rte_flow_async_action_handle_create(port_id, queue_id,\n-\t\t\t\t\t&attr, conf, action, job, &error);\n+\n+\tif (is_indirect_list)\n+\t\tqueue_action_list_handle_create(port_id, queue_id, pia, job,\n+\t\t\t\t\t\t&attr, conf, action, &error);\n+\telse\n+\t\tqueue_action_handle_create(port_id, queue_id, pia, job, &attr,\n+\t\t\t\t\t   conf, action, &error);\n+\n \tif (!pia->handle) {\n \t\tuint32_t destroy_id = pia->id;\n \t\tport_queue_action_handle_destroy(port_id, queue_id,\n@@ -2871,7 +2951,6 @@ port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,\n \t\tfree(job);\n \t\treturn port_flow_complain(&error);\n \t}\n-\tpia->type = action->type;\n \tprintf(\"Indirect action #%u creation queued\\n\", pia->id);\n \treturn 0;\n }\n@@ -2920,9 +2999,15 @@ port_queue_action_handle_destroy(portid_t port_id,\n \t\t\t}\n \t\t\tjob->type = QUEUE_JOB_TYPE_ACTION_DESTROY;\n \t\t\tjob->pia = pia;\n-\n-\t\t\tif (rte_flow_async_action_handle_destroy(port_id,\n-\t\t\t\tqueue_id, &attr, pia->handle, job, &error)) {\n+\t\t\tret = pia->type == RTE_FLOW_ACTION_TYPE_INDIRECT_LIST ?\n+\t\t\t      rte_flow_async_action_list_handle_destroy\n+\t\t\t\t      (port_id, queue_id,\n+\t\t\t\t       &attr, pia->list_handle,\n+\t\t\t\t       job, &error) :\n+\t\t\t      rte_flow_async_action_handle_destroy\n+\t\t\t\t      (port_id, queue_id, &attr, pia->handle,\n+\t\t\t\t       job, &error);\n+\t\t\tif (ret) {\n \t\t\t\tfree(job);\n \t\t\t\tret = port_flow_complain(&error);\n \t\t\t\tcontinue;\ndiff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h\nindex bdfbfd36d3..5c43b4db0b 100644\n--- a/app/test-pmd/testpmd.h\n+++ b/app/test-pmd/testpmd.h\n@@ -228,7 +228,12 @@ struct port_indirect_action {\n \tstruct port_indirect_action *next; /**< Next flow in list. */\n \tuint32_t id; /**< Indirect action ID. */\n \tenum rte_flow_action_type type; /**< Action type. */\n-\tstruct rte_flow_action_handle *handle;\t/**< Indirect action handle. */\n+\tunion {\n+\t\tstruct rte_flow_action_handle *handle;\n+\t\t/**< Indirect action handle. */\n+\t\tstruct rte_flow_action_list_handle *list_handle;\n+\t\t/**< Indirect action list handle*/\n+\t};\n \tenum age_action_context_type age_type; /**< Age action context type. */\n };\n \n@@ -921,7 +926,7 @@ void update_fwd_ports(portid_t new_pid);\n void set_fwd_eth_peer(portid_t port_id, char *peer_addr);\n \n void port_mtu_set(portid_t port_id, uint16_t mtu);\n-int port_action_handle_create(portid_t port_id, uint32_t id,\n+int port_action_handle_create(portid_t port_id, uint32_t id, bool indirect_list,\n \t\t\t      const struct rte_flow_indir_action_conf *conf,\n \t\t\t      const struct rte_flow_action *action);\n int port_action_handle_destroy(portid_t port_id,\ndiff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini\nindex 1a5087abad..10a1c1af77 100644\n--- a/doc/guides/nics/features/default.ini\n+++ b/doc/guides/nics/features/default.ini\n@@ -158,6 +158,7 @@ drop                 =\n flag                 =\n inc_tcp_ack          =\n inc_tcp_seq          =\n+indirect_list        =\n jump                 =\n mac_swap             =\n mark                 =\ndiff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst\nindex 32fc45516a..25699ebaec 100644\n--- a/doc/guides/prog_guide/rte_flow.rst\n+++ b/doc/guides/prog_guide/rte_flow.rst\n@@ -3300,6 +3300,125 @@ The ``quota`` value is reduced according to ``mode`` setting.\n    | ``RTE_FLOW_QUOTA_MODE_L3``      | Count packet bytes starting from L3 |\n    +------------------+----------------------------------------------------+\n \n+Action: ``INDIRECT_LIST``\n+^^^^^^^^^^^^^^^^^^^^^^^^^\n+\n+Indirect API creates a shared flow action with unique action handle.\n+Flow rules can access the shared flow action and resources related to\n+that action through the indirect action handle.\n+In addition, the API allows to update existing shared flow action\n+configuration.  After the update completes, new action configuration\n+is available to all flows that reference that shared action.\n+\n+Indirect actions list expands the indirect action API:\n+\n+- Indirect action list creates a handle for one or several\n+  flow actions, while legacy indirect action handle references\n+  single action only.\n+  Input flow actions arranged in END terminated list.\n+\n+- Flow rule can provide rule specific configuration parameters to\n+  existing shared handle.\n+  Updates of flow rule specific configuration will not change the base\n+  action configuration.\n+  Base action configuration was set during the action creation.\n+\n+Indirect action list handle defines 2 types of resources:\n+\n+- Mutable handle resource can be changed during handle lifespan.\n+\n+- Immutable handle resource value is set during handle creation\n+  and cannot be changed.\n+\n+There are 2 types of mutable indirect handle contexts:\n+\n+- Action mutable context is always shared between all flows\n+  that referenced indirect actions list handle.\n+  Action mutable context can be changed by explicit invocation\n+  of indirect handle update function.\n+\n+- Flow mutable context is private to a flow.\n+  Flow mutable context can be updated by indirect list handle\n+  flow rule configuration.\n+\n+Indirect action types - immutable, action / flow mutable, are mutually\n+exclusive and depend on the action definition.\n+\n+If indirect list handle was created from a list of actions A1 / A2 ... An / END\n+indirect list flow action can update Ai flow mutable context in the\n+action configuration parameter.\n+Indirect list action configuration is and array [C1, C2,  .., Cn]\n+where Ci corresponds to Ai in the action handle source.\n+Ci configuration element points Ai flow mutable update, or it's NULL\n+if Ai has no flow mutable update.\n+Indirect list action configuration is NULL if the action has no flow\n+mutable updates. Otherwise it points to an array of n flow mutable\n+configuration pointers.\n+\n+**Template API:**\n+\n+*Action template format:*\n+\n+``template .. indirect_list handle Htmpl conf Ctmpl ..``\n+\n+``mask     .. indirect_list handle Hmask conf Cmask ..``\n+\n+- If Htmpl was masked (Hmask != 0), it will be fixed in that template.\n+  Otherwise, indirect action value is set in a flow rule.\n+\n+- If Htmpl and Ctmpl[i] were masked (Hmask !=0 and Cmask[i] != 0),\n+  Htmpl's Ai action flow mutable context fill be updated to\n+  Ctmpl[i] values and will be fixed in that template.\n+\n+*Flow rule format:*\n+\n+``actions .. indirect_list handle Hflow conf Cflow ..``\n+\n+- If Htmpl was not masked in actions template, Hflow references an\n+  action of the same type as Htmpl.\n+\n+- Cflow[i] updates handle's Ai flow mutable configuration if\n+  the Ci was not masked in action template.\n+\n+.. _table_rte_flow_action_indirect_list:\n+\n+.. table:: INDIRECT_LIST\n+\n+   +------------------+----------------------------------+\n+   | Field            | Value                            |\n+   +==================+==================================+\n+   | ``handle``       | Indirect action list handle      |\n+   +------------------+----------------------------------+\n+   | ``conf``         | Flow mutable configuration array |\n+   +------------------+----------------------------------+\n+\n+.. code-block:: text\n+\n+ flow 1:\n+  / indirect handle H conf C1 /\n+                    |       |\n+                    |       |\n+                    |       |         flow 2:\n+                    |       |         / indirect handle H conf C2 /\n+                    |       |                           |      |\n+                    |       |                           |      |\n+                    |       |                           |      |\n+            =========================================================\n+            ^       |       |                           |      |\n+            |       |       V                           |      V\n+            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~\n+            |     flow mutable                        flow mutable\n+            |     context 1                           context 2\n+            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~\n+  indirect  |       |                                   |\n+  action    |       |                                   |\n+  context   |       V                                   V\n+            |   -----------------------------------------------------\n+            |                 action mutable context\n+            |   -----------------------------------------------------\n+            v                action immutable context\n+            =========================================================\n+\n Negative types\n ~~~~~~~~~~~~~~\n \ndiff --git a/doc/guides/rel_notes/release_23_07.rst b/doc/guides/rel_notes/release_23_07.rst\nindex a9b1293689..d9643a35ef 100644\n--- a/doc/guides/rel_notes/release_23_07.rst\n+++ b/doc/guides/rel_notes/release_23_07.rst\n@@ -55,6 +55,8 @@ New Features\n      Also, make sure to start the actual text at the margin.\n      =======================================================\n \n+   * **Added INDIRECT_LIST flow action.**\n+\n \n Removed Items\n -------------\ndiff --git a/lib/ethdev/ethdev_trace.h b/lib/ethdev/ethdev_trace.h\nindex 3dc7d028b8..7577faf8ed 100644\n--- a/lib/ethdev/ethdev_trace.h\n+++ b/lib/ethdev/ethdev_trace.h\n@@ -2447,6 +2447,94 @@ RTE_TRACE_POINT_FP(\n \trte_trace_point_emit_int(ret);\n )\n \n+RTE_TRACE_POINT_FP(\n+\trte_flow_trace_action_list_handle_create,\n+\tRTE_TRACE_POINT_ARGS\n+\t\t(uint16_t port_id,\n+\t\t const struct rte_flow_indir_action_conf *conf,\n+\t\t const struct rte_flow_action *actions, int ret),\n+\trte_trace_point_emit_u16(port_id);\n+\trte_trace_point_emit_ptr(conf);\n+\trte_trace_point_emit_ptr(actions);\n+\trte_trace_point_emit_int(ret);\n+)\n+\n+RTE_TRACE_POINT_FP(\n+\trte_flow_trace_action_list_handle_destroy,\n+\tRTE_TRACE_POINT_ARGS\n+\t\t(uint16_t port_id,\n+\t\t const struct rte_flow_action_list_handle *handle, int ret),\n+\trte_trace_point_emit_u16(port_id);\n+\trte_trace_point_emit_ptr(handle);\n+\trte_trace_point_emit_int(ret);\n+)\n+\n+RTE_TRACE_POINT_FP(\n+\trte_flow_trace_async_action_list_handle_create,\n+\tRTE_TRACE_POINT_ARGS\n+\t\t(uint16_t port_id, uint32_t queue_id,\n+\t\t const struct rte_flow_op_attr *op_attr,\n+\t\t const struct rte_flow_indir_action_conf *conf,\n+\t\t const struct rte_flow_action *action,\n+\t\t const void *user_data, int ret),\n+\trte_trace_point_emit_u16(port_id);\n+\trte_trace_point_emit_u32(queue_id);\n+\trte_trace_point_emit_ptr(op_attr);\n+\trte_trace_point_emit_ptr(conf);\n+\trte_trace_point_emit_ptr(action);\n+\trte_trace_point_emit_ptr(user_data);\n+\trte_trace_point_emit_int(ret);\n+)\n+\n+RTE_TRACE_POINT_FP(\n+\trte_flow_trace_async_action_list_handle_destroy,\n+\tRTE_TRACE_POINT_ARGS\n+\t\t(uint16_t port_id, uint32_t queue_id,\n+\t\t const struct rte_flow_op_attr *op_attr,\n+\t\t const struct rte_flow_action_list_handle *handle,\n+\t\t const void *user_data, int ret),\n+\trte_trace_point_emit_u16(port_id);\n+\trte_trace_point_emit_u32(queue_id);\n+\trte_trace_point_emit_ptr(op_attr);\n+\trte_trace_point_emit_ptr(handle);\n+\trte_trace_point_emit_ptr(user_data);\n+\trte_trace_point_emit_int(ret);\n+)\n+\n+RTE_TRACE_POINT_FP(\n+\trte_flow_trace_action_list_handle_query_update,\n+\tRTE_TRACE_POINT_ARGS\n+\t\t(uint16_t port_id,\n+\t\t const struct rte_flow_action_list_handle *handle,\n+\t\t const void **update, void **query,\n+\t\t enum rte_flow_query_update_mode mode, int ret),\n+\t\trte_trace_point_emit_u16(port_id);\n+\t\trte_trace_point_emit_ptr(handle);\n+\t\trte_trace_point_emit_ptr(update);\n+\t\trte_trace_point_emit_ptr(query);\n+\t\trte_trace_point_emit_int(mode);\n+\t\trte_trace_point_emit_int(ret);\n+)\n+\n+RTE_TRACE_POINT_FP(\n+\trte_flow_trace_async_action_list_handle_query_update,\n+\tRTE_TRACE_POINT_ARGS\n+\t\t(uint16_t port_id, uint32_t queue_id,\n+\t\t const struct rte_flow_op_attr *attr,\n+\t\t const struct rte_flow_action_list_handle *handle,\n+\t\t const void **update, void **query,\n+\t\t enum rte_flow_query_update_mode mode,\n+\t\t void *user_data, int ret),\n+\trte_trace_point_emit_u16(port_id);\n+\trte_trace_point_emit_u32(queue_id);\n+\trte_trace_point_emit_ptr(attr);\n+\trte_trace_point_emit_ptr(handle);\n+\trte_trace_point_emit_ptr(update);\n+\trte_trace_point_emit_ptr(query);\n+\trte_trace_point_emit_int(mode);\n+\trte_trace_point_emit_ptr(user_data);\n+\trte_trace_point_emit_int(ret);\n+)\n #ifdef __cplusplus\n }\n #endif\ndiff --git a/lib/ethdev/ethdev_trace_points.c b/lib/ethdev/ethdev_trace_points.c\nindex 61010cae56..5e1462a6fb 100644\n--- a/lib/ethdev/ethdev_trace_points.c\n+++ b/lib/ethdev/ethdev_trace_points.c\n@@ -750,3 +750,21 @@ RTE_TRACE_POINT_REGISTER(rte_tm_trace_wred_profile_add,\n \n RTE_TRACE_POINT_REGISTER(rte_tm_trace_wred_profile_delete,\n \tlib.ethdev.tm.wred_profile_delete)\n+\n+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_create,\n+\t\t\t lib.ethdev.flow.action_list_handle_create)\n+\n+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_destroy,\n+\t\t\t lib.ethdev.flow.action_list_handle_destroy)\n+\n+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_query_update,\n+\t\t\t lib.ethdev.flow.action_list_handle_query_update)\n+\n+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_create,\n+\tlib.ethdev.flow.async_action_list_handle_create)\n+\n+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_destroy,\n+\tlib.ethdev.flow.async_action_list_handle_destroy)\n+\n+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_query_update,\n+\t\t\t lib.ethdev.flow.async_action_list_handle_query_update)\ndiff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c\nindex 69e6e749f7..71c9b6cb84 100644\n--- a/lib/ethdev/rte_flow.c\n+++ b/lib/ethdev/rte_flow.c\n@@ -259,6 +259,8 @@ static const struct rte_flow_desc_data rte_flow_desc_action[] = {\n \tMK_FLOW_ACTION(METER_MARK, sizeof(struct rte_flow_action_meter_mark)),\n \tMK_FLOW_ACTION(SEND_TO_KERNEL, 0),\n \tMK_FLOW_ACTION(QUOTA, sizeof(struct rte_flow_action_quota)),\n+\tMK_FLOW_ACTION(INDIRECT_LIST,\n+\t\t       sizeof(struct rte_flow_action_indirect_list)),\n };\n \n int\n@@ -2171,3 +2173,172 @@ rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id,\n \t\t\t\t\t\t    user_data, error);\n \treturn flow_err(port_id, ret, error);\n }\n+\n+struct rte_flow_action_list_handle *\n+rte_flow_action_list_handle_create(uint16_t port_id,\n+\t\t\t\t   const\n+\t\t\t\t   struct rte_flow_indir_action_conf *conf,\n+\t\t\t\t   const struct rte_flow_action *actions,\n+\t\t\t\t   struct rte_flow_error *error)\n+{\n+\tint ret;\n+\tstruct rte_eth_dev *dev;\n+\tconst struct rte_flow_ops *ops;\n+\tstruct rte_flow_action_list_handle *handle;\n+\n+\tRTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, NULL);\n+\tops = rte_flow_ops_get(port_id, error);\n+\tif (!ops || !ops->action_list_handle_create) {\n+\t\trte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t   \"action_list handle not supported\");\n+\t\treturn NULL;\n+\t}\n+\tdev = &rte_eth_devices[port_id];\n+\thandle = ops->action_list_handle_create(dev, conf, actions, error);\n+\tret = flow_err(port_id, -rte_errno, error);\n+\trte_flow_trace_action_list_handle_create(port_id, conf, actions, ret);\n+\treturn handle;\n+}\n+\n+int\n+rte_flow_action_list_handle_destroy(uint16_t port_id,\n+\t\t\t\t    struct rte_flow_action_list_handle *handle,\n+\t\t\t\t    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->action_list_handle_destroy)\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 handle not supported\");\n+\tdev = &rte_eth_devices[port_id];\n+\tret = ops->action_list_handle_destroy(dev, handle, error);\n+\tret = flow_err(port_id, ret, error);\n+\trte_flow_trace_action_list_handle_destroy(port_id, handle, ret);\n+\treturn ret;\n+}\n+\n+struct rte_flow_action_list_handle *\n+rte_flow_async_action_list_handle_create(uint16_t port_id, uint32_t queue_id,\n+\t\t\t\t\t const struct rte_flow_op_attr *attr,\n+\t\t\t\t\t const struct\n+\t\t\t\t\t      rte_flow_indir_action_conf *conf,\n+\t\t\t\t\t const struct rte_flow_action *actions,\n+\t\t\t\t\t void *user_data,\n+\t\t\t\t\t struct rte_flow_error *error)\n+{\n+\tint ret;\n+\tstruct rte_eth_dev *dev;\n+\tconst struct rte_flow_ops *ops;\n+\tstruct rte_flow_action_list_handle *handle;\n+\n+\tRTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, NULL);\n+\tops = rte_flow_ops_get(port_id, error);\n+\tif (!ops || !ops->async_action_list_handle_create) {\n+\t\trte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t   \"action_list handle not supported\");\n+\t\treturn NULL;\n+\t}\n+\tdev = &rte_eth_devices[port_id];\n+\thandle = ops->async_action_list_handle_create(dev, queue_id, attr, conf,\n+\t\t\t\t\t\t      actions, user_data,\n+\t\t\t\t\t\t      error);\n+\tret = flow_err(port_id, -rte_errno, error);\n+\trte_flow_trace_async_action_list_handle_create(port_id, queue_id, attr,\n+\t\t\t\t\t\t       conf, actions, user_data,\n+\t\t\t\t\t\t       ret);\n+\treturn handle;\n+}\n+\n+int\n+rte_flow_async_action_list_handle_destroy\n+\t\t\t\t(uint16_t port_id, uint32_t queue_id,\n+\t\t\t\t const struct rte_flow_op_attr *op_attr,\n+\t\t\t\t struct rte_flow_action_list_handle *handle,\n+\t\t\t\t void *user_data, 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->async_action_list_handle_destroy)\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  \"async action_list handle not supported\");\n+\tdev = &rte_eth_devices[port_id];\n+\tret = ops->async_action_list_handle_destroy(dev, queue_id, op_attr,\n+\t\t\t\t\t\t    handle, user_data, error);\n+\tret = flow_err(port_id, ret, error);\n+\trte_flow_trace_async_action_list_handle_destroy(port_id, queue_id,\n+\t\t\t\t\t\t\top_attr, handle,\n+\t\t\t\t\t\t\tuser_data, ret);\n+\treturn ret;\n+}\n+\n+int\n+rte_flow_action_list_handle_query_update\n+\t\t\t(uint16_t port_id,\n+\t\t\t const struct rte_flow_action_list_handle *handle,\n+\t\t\t const void **update, void **query,\n+\t\t\t enum rte_flow_query_update_mode mode,\n+\t\t\t 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->action_list_handle_query_update)\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 query_update not supported\");\n+\tdev = &rte_eth_devices[port_id];\n+\tret = ops->action_list_handle_query_update(dev, handle, update, query,\n+\t\t\t\t\t\t   mode, error);\n+\tret = flow_err(port_id, ret, error);\n+\trte_flow_trace_action_list_handle_query_update(port_id, handle, update,\n+\t\t\t\t\t\t       query, mode, ret);\n+\treturn ret;\n+}\n+\n+int\n+rte_flow_async_action_list_handle_query_update\n+\t\t\t(uint16_t port_id, uint32_t queue_id,\n+\t\t\t const struct rte_flow_op_attr *attr,\n+\t\t\t const struct rte_flow_action_list_handle *handle,\n+\t\t\t const void **update, void **query,\n+\t\t\t enum rte_flow_query_update_mode mode,\n+\t\t\t void *user_data, 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->async_action_list_handle_query_update)\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->async_action_list_handle_query_update(dev, queue_id, attr,\n+\t\t\t\t\t\t\t handle, update, query,\n+\t\t\t\t\t\t\t mode, user_data,\n+\t\t\t\t\t\t\t error);\n+\tret = flow_err(port_id, ret, error);\n+\trte_flow_trace_async_action_list_handle_query_update(port_id, queue_id,\n+\t\t\t\t\t\t\t     attr, handle,\n+\t\t\t\t\t\t\t     update, query,\n+\t\t\t\t\t\t\t     mode, user_data,\n+\t\t\t\t\t\t\t     ret);\n+\treturn ret;\n+}\ndiff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h\nindex 713ba8b65c..b65096b3b7 100644\n--- a/lib/ethdev/rte_flow.h\n+++ b/lib/ethdev/rte_flow.h\n@@ -2912,6 +2912,13 @@ enum rte_flow_action_type {\n \t * applied to the given ethdev Rx queue.\n \t */\n \tRTE_FLOW_ACTION_TYPE_SKIP_CMAN,\n+\n+\t/**\n+\t * Action handle to reference flow actions list.\n+\t *\n+\t * @see struct rte_flow_action_indirect_list\n+\t */\n+\tRTE_FLOW_ACTION_TYPE_INDIRECT_LIST,\n };\n \n /**\n@@ -6118,6 +6125,268 @@ rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id,\n \t\t\t\t\t  void *user_data,\n \t\t\t\t\t  struct rte_flow_error *error);\n \n+struct rte_flow_action_list_handle;\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Configure INDIRECT_LIST flow action.\n+ *\n+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST\n+ */\n+struct rte_flow_action_indirect_list {\n+\t/** Indirect action list handle */\n+\tstruct rte_flow_action_list_handle *handle;\n+\t/**\n+\t * Flow mutable configuration array.\n+\t * NULL if the handle has no flow mutable configuration update.\n+\t * Otherwise, if the handle was created with list A1 / A2 .. An / END\n+\t * size of conf is n.\n+\t * conf[i] points to flow mutable update of Ai in the handle\n+\t * actions list or NULL if Ai has no update.\n+\t */\n+\tconst void **conf;\n+};\n+\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Create an indirect flow action object from flow actions list.\n+ * The object is identified by a unique handle.\n+ * The handle has single state and configuration\n+ * across all the flow rules using it.\n+ *\n+ * @param[in] port_id\n+ *    The port identifier of the Ethernet device.\n+ * @param[in] conf\n+ *   Action configuration for the indirect action list creation.\n+ * @param[in] actions\n+ *   Specific configuration of the indirect action lists.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL. PMDs initialize this\n+ *   structure in case of error only.\n+ * @return\n+ *   A valid handle in case of success, NULL otherwise and rte_errno is set\n+ *   to one of the error codes defined:\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - (-ENOSYS) if underlying device does not support this functionality.\n+ *   - (-EIO) if underlying device is removed.\n+ *   - (-EINVAL) if *actions* list invalid.\n+ *   - (-ENOTSUP) if *action* list element valid but unsupported.\n+ */\n+__rte_experimental\n+struct rte_flow_action_list_handle *\n+rte_flow_action_list_handle_create(uint16_t port_id,\n+\t\t\t\t   const\n+\t\t\t\t   struct rte_flow_indir_action_conf *conf,\n+\t\t\t\t   const struct rte_flow_action *actions,\n+\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+ * Async function call to create an indirect flow action object\n+ * from flow actions list.\n+ * The object is identified by a unique handle.\n+ * The handle has single state and configuration\n+ * across all the flow rules using it.\n+ *\n+ * @param[in] port_id\n+ *    The port identifier of the Ethernet device.\n+ * @param[in] queue_id\n+ *   Flow queue which is used to update the rule.\n+ * @param[in] attr\n+ *   Indirect action update operation attributes.\n+ * @param[in] conf\n+ *   Action configuration for the indirect action list creation.\n+ * @param[in] actions\n+ *   Specific configuration of the indirect action list.\n+ * @param[in] user_data\n+ *   The user data that will be returned on async completion event.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL. PMDs initialize this\n+ *   structure in case of error only.\n+ * @return\n+ *   A valid handle in case of success, NULL otherwise and rte_errno is set\n+ *   to one of the error codes defined:\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - (-ENOSYS) if underlying device does not support this functionality.\n+ *   - (-EIO) if underlying device is removed.\n+ *   - (-EINVAL) if *actions* list invalid.\n+ *   - (-ENOTSUP) if *action* list element valid but unsupported.\n+ */\n+__rte_experimental\n+struct rte_flow_action_list_handle *\n+rte_flow_async_action_list_handle_create(uint16_t port_id, uint32_t queue_id,\n+\t\t\t\t\t const struct rte_flow_op_attr *attr,\n+\t\t\t\t\t const struct\n+\t\t\t\t\t rte_flow_indir_action_conf *conf,\n+\t\t\t\t\t const struct rte_flow_action *actions,\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+ * Destroy indirect actions list by handle.\n+ *\n+ * @param[in] port_id\n+ *    The port identifier of the Ethernet device.\n+ * @param[in] handle\n+ *   Handle for the indirect actions list to be destroyed.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL. PMDs initialize this\n+ *   structure in case of error only.\n+ * @return\n+ *   - (0) if success.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - (-ENOSYS) if underlying device does not support this functionality.\n+ *   - (-EIO) if underlying device is removed.\n+ *   - (-ENOENT) if actions list pointed by *action* handle was not found.\n+ *   - (-EBUSY) if actions list pointed by *action* handle still used\n+ */\n+__rte_experimental\n+int\n+rte_flow_action_list_handle_destroy(uint16_t port_id,\n+\t\t\t\t    struct rte_flow_action_list_handle *handle,\n+\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+ * Enqueue indirect action list destruction operation.\n+ * The destroy queue must be the same\n+ * as the queue on which the action was created.\n+ *\n+ * @param[in] port_id\n+ *   Port identifier of Ethernet device.\n+ * @param[in] queue_id\n+ *   Flow queue which is used to destroy the rule.\n+ * @param[in] op_attr\n+ *   Indirect action destruction operation attributes.\n+ * @param[in] handle\n+ *   Handle for the indirect action object to be destroyed.\n+ * @param[in] user_data\n+ *   The user data that will be returned on the completion events.\n+ * @param[out] 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+ *   - (-ENOSYS) if underlying device does not support this functionality.\n+ *   - (-EIO) if underlying device is removed.\n+ *   - (-ENOENT) if actions list pointed by *action* handle was not found.\n+ *   - (-EBUSY) if actions list pointed by *action* handle still used\n+ */\n+__rte_experimental\n+int\n+rte_flow_async_action_list_handle_destroy\n+\t\t(uint16_t port_id, uint32_t queue_id,\n+\t\t const struct rte_flow_op_attr *op_attr,\n+\t\t struct rte_flow_action_list_handle *handle,\n+\t\t void *user_data, struct rte_flow_error *error);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Query and/or update indirect flow actions list.\n+ * If both query and update not NULL, the function atomically\n+ * queries and updates indirect action. Query and update are carried in order\n+ * specified in the mode parameter.\n+ * If ether query or update is NULL, the function executes\n+ * complementing operation.\n+ *\n+ * @param port_id\n+ *   Port identifier of Ethernet device.\n+ * @param handle\n+ *   Handle for the indirect actions list object to be updated.\n+ * @param update\n+ *   If not NULL, update profile specification used to modify the action\n+ *   pointed by handle.\n+ *   @see struct rte_flow_action_indirect_list\n+ * @param query\n+ *   If not NULL pointer to storage for the associated query data type.\n+ *   @see struct rte_flow_action_indirect_list\n+ * @param mode\n+ *   Operational mode.\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+ * - (-EINVAL) if *handle* or *mode* invalid or\n+ *             both *query* and *update* are NULL.\n+ */\n+__rte_experimental\n+int\n+rte_flow_action_list_handle_query_update(uint16_t port_id,\n+\t\t\t\t\t const struct\n+\t\t\t\t\t rte_flow_action_list_handle *handle,\n+\t\t\t\t\t const void **update, void **query,\n+\t\t\t\t\t enum rte_flow_query_update_mode mode,\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+ * Enqueue async indirect flow actions list query and/or update\n+ *\n+ * @param port_id\n+ *   Port identifier of Ethernet device.\n+ * @param queue_id\n+ *   Flow queue which is used to update the rule.\n+ * @param attr\n+ *   Indirect action update operation attributes.\n+ * @param handle\n+ *   Handle for the indirect actions list object to be updated.\n+ * @param update\n+ *   If not NULL, update profile specification used to modify the action\n+ *   pointed by handle.\n+ *   @see struct rte_flow_action_indirect_list\n+ * @param query\n+ *   If not NULL, pointer to storage for the associated query data type.\n+ *   Query result returned on async completion event.\n+ *   @see struct rte_flow_action_indirect_list\n+ * @param mode\n+ *   Operational mode.\n+ * @param user_data\n+ *   The user data that will be returned on async completion event.\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+ * - (-EINVAL) if *handle* or *mode* invalid or\n+ *             both *update* and *query* are NULL.\n+ */\n+__rte_experimental\n+int\n+rte_flow_async_action_list_handle_query_update(uint16_t port_id, uint32_t queue_id,\n+\t\t\t\t\t  const struct rte_flow_op_attr *attr,\n+\t\t\t\t\t  const struct\n+\t\t\t\t\t  rte_flow_action_list_handle *handle,\n+\t\t\t\t\t  const void **update, void **query,\n+\t\t\t\t\t  enum rte_flow_query_update_mode mode,\n+\t\t\t\t\t  void *user_data,\n+\t\t\t\t\t  struct rte_flow_error *error);\n+\n+\n #ifdef __cplusplus\n }\n #endif\ndiff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h\nindex a129a4605d..af63ef9b5c 100644\n--- a/lib/ethdev/rte_flow_driver.h\n+++ b/lib/ethdev/rte_flow_driver.h\n@@ -121,6 +121,17 @@ struct rte_flow_ops {\n \t\t const void *update, void *query,\n \t\t enum rte_flow_query_update_mode qu_mode,\n \t\t struct rte_flow_error *error);\n+\t/** @see rte_flow_action_list_handle_create() */\n+\tstruct rte_flow_action_list_handle *(*action_list_handle_create)\n+\t\t(struct rte_eth_dev *dev,\n+\t\t const struct rte_flow_indir_action_conf *conf,\n+\t\t const struct rte_flow_action actions[],\n+\t\t struct rte_flow_error *error);\n+\t/** @see rte_flow_action_list_handle_destroy() */\n+\tint (*action_list_handle_destroy)\n+\t\t(struct rte_eth_dev *dev,\n+\t\t struct rte_flow_action_list_handle *handle,\n+\t\t struct rte_flow_error *error);\n \t/** See rte_flow_tunnel_decap_set() */\n \tint (*tunnel_decap_set)\n \t\t(struct rte_eth_dev *dev,\n@@ -302,6 +313,36 @@ struct rte_flow_ops {\n \t\t const void *update, void *query,\n \t\t enum rte_flow_query_update_mode qu_mode,\n \t\t void *user_data, struct rte_flow_error *error);\n+\t/** @see rte_flow_async_action_list_handle_create() */\n+\tstruct rte_flow_action_list_handle *\n+\t(*async_action_list_handle_create)\n+\t\t(struct rte_eth_dev *dev, uint32_t queue_id,\n+\t\t const struct rte_flow_op_attr *attr,\n+\t\t const struct rte_flow_indir_action_conf *conf,\n+\t\t const struct rte_flow_action *actions,\n+\t\t void *user_data, struct rte_flow_error *error);\n+\t/** @see rte_flow_async_action_list_handle_destroy() */\n+\tint (*async_action_list_handle_destroy)\n+\t\t(struct rte_eth_dev *dev, uint32_t queue_id,\n+\t\t const struct rte_flow_op_attr *op_attr,\n+\t\t struct rte_flow_action_list_handle *action_handle,\n+\t\t void *user_data, struct rte_flow_error *error);\n+\t/** @see rte_flow_action_list_handle_query_update() */\n+\tint (*action_list_handle_query_update)\n+\t\t(struct rte_eth_dev *dev,\n+\t\t const struct rte_flow_action_list_handle *handle,\n+\t\t const void **update, void **query,\n+\t\t enum rte_flow_query_update_mode mode,\n+\t\t struct rte_flow_error *error);\n+\t/** @see rte_flow_async_action_list_handle_query_update() */\n+\tint (*async_action_list_handle_query_update)\n+\t\t(struct rte_eth_dev *dev, uint32_t queue_id,\n+\t\t const struct rte_flow_op_attr *attr,\n+\t\t const struct rte_flow_action_list_handle *handle,\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+\n };\n \n /**\ndiff --git a/lib/ethdev/version.map b/lib/ethdev/version.map\nindex 357d1a88c0..02372b3a7e 100644\n--- a/lib/ethdev/version.map\n+++ b/lib/ethdev/version.map\n@@ -299,6 +299,14 @@ EXPERIMENTAL {\n \trte_flow_action_handle_query_update;\n \trte_flow_async_action_handle_query_update;\n \trte_flow_async_create_by_index;\n+\n+\t# added in 23.07\n+    rte_flow_action_list_handle_create;\n+    rte_flow_action_list_handle_destroy;\n+    rte_flow_action_list_handle_query_update;\n+    rte_flow_async_action_list_handle_create;\n+    rte_flow_async_action_list_handle_destroy;\n+    rte_flow_async_action_list_handle_query_update;\n };\n \n INTERNAL {\n",
    "prefixes": [
        "v4"
    ]
}