get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 116573,
    "url": "https://patches.dpdk.org/api/patches/116573/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20220921145409.511328-3-michaelba@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": "<20220921145409.511328-3-michaelba@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220921145409.511328-3-michaelba@nvidia.com",
    "date": "2022-09-21T14:54:08",
    "name": "[2/3] ethdev: add queue-based API to report aged flow rules",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "8c7fbf4789e6a0f458e6a90d523a1f71881f6a2b",
    "submitter": {
        "id": 1949,
        "url": "https://patches.dpdk.org/api/people/1949/?format=api",
        "name": "Michael Baum",
        "email": "michaelba@nvidia.com"
    },
    "delegate": {
        "id": 3961,
        "url": "https://patches.dpdk.org/api/users/3961/?format=api",
        "username": "arybchenko",
        "first_name": "Andrew",
        "last_name": "Rybchenko",
        "email": "andrew.rybchenko@oktetlabs.ru"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20220921145409.511328-3-michaelba@nvidia.com/mbox/",
    "series": [
        {
            "id": 24755,
            "url": "https://patches.dpdk.org/api/series/24755/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=24755",
            "date": "2022-09-21T14:54:06",
            "name": "ethdev: AGE action preparation",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/24755/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/116573/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/116573/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 B362CA00C3;\n\tWed, 21 Sep 2022 16:54:42 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id C984742826;\n\tWed, 21 Sep 2022 16:54:35 +0200 (CEST)",
            "from NAM12-BN8-obe.outbound.protection.outlook.com\n (mail-bn8nam12on2073.outbound.protection.outlook.com [40.107.237.73])\n by mails.dpdk.org (Postfix) with ESMTP id B4545410D0\n for <dev@dpdk.org>; Wed, 21 Sep 2022 16:54:32 +0200 (CEST)",
            "from MW4PR04CA0147.namprd04.prod.outlook.com (2603:10b6:303:84::32)\n by DM4PR12MB5868.namprd12.prod.outlook.com (2603:10b6:8:67::17) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5632.18; Wed, 21 Sep\n 2022 14:54:29 +0000",
            "from CO1NAM11FT054.eop-nam11.prod.protection.outlook.com\n (2603:10b6:303:84:cafe::93) by MW4PR04CA0147.outlook.office365.com\n (2603:10b6:303:84::32) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5654.17 via Frontend\n Transport; Wed, 21 Sep 2022 14:54:29 +0000",
            "from mail.nvidia.com (216.228.117.160) by\n CO1NAM11FT054.mail.protection.outlook.com (10.13.174.70) with Microsoft SMTP\n Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.20.5654.14 via Frontend Transport; Wed, 21 Sep 2022 14:54:29 +0000",
            "from rnnvmail204.nvidia.com (10.129.68.6) 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.26; Wed, 21 Sep\n 2022 07:54:19 -0700",
            "from rnnvmail203.nvidia.com (10.129.68.9) by rnnvmail204.nvidia.com\n (10.129.68.6) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.29; Wed, 21 Sep\n 2022 07:54:19 -0700",
            "from nvidia.com (10.127.8.13) by mail.nvidia.com (10.129.68.9) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.29 via Frontend\n Transport; Wed, 21 Sep 2022 07:54:17 -0700"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=GdIhjQNKPyOsNGt08jFNokViuUaMUoXfVKFrr3t6eB5uqppSQapPvtNxDD6NgvIMgIiVAjMNQFyUnNC7ZmIc+1HJZZItP2E3sd/FfNH8nrX09/8FKFjTfTymZI9oQmxgAk/17A5lqNrk+NVer2TixkY+fAV+Yo+IZc0ZDDPG9BYTvgxe9GdZsYpJMXCHxK6GMsNgkLxaTR1alnLJZxhPIcEXEf75W+LdbWqn+YyAUGBiAfwqcTXQL0xSCuda9iLc5QoCZJIqQuu8HV89RUZy5hIS25xDkwQoMEHV1gAXvfhQYAoOeeMz91FR7nkrhIL0sfN1LAGBlYEj3yFQrLUi9g==",
        "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=0xtEUuh6xraKQOYgKR2gxq/W9ZWgNrZmsgocOZoksps=;\n b=FkqDrQ4d82h9ppZe3FNzi9Iv/+fdXc+O6NVP70/XOwSHAtGD8jSwdqQtScS+gASNm3L+2pkcsYkPb1408Rc4ezUvhPT4R85MdE/C2e7OOfp+FVdE2VER2TiaD/vwvlSZTzIGim0jyieqtEfjOkcIRM74g7embOnQ7MOHOejz6Hs8JahoYzuGndHB3JjGHwj7xk8keEIScinHXj3iRedMm9X2dp6p2csecvPn3zQB/UmP66RSxPMHZYprm9osbBg7zUpOgThH//KPe2fXS849lHYeUF2ImycDe1V9DGb4NHxjcBV963m0aJF92qK1RVzsw/LXqi0XkXutjeRHqDhnCg==",
        "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=0xtEUuh6xraKQOYgKR2gxq/W9ZWgNrZmsgocOZoksps=;\n b=nQKnoifHTRA2wRsxkwTC8QhgQpn31PbgR3eLhi+Hb70/FLwE9SCc1R6qx1PS/7dWBaoFlyLjIT+Lo3Lu6DjP84pWeLt/xQSUjjEogPNGw5EQ9hG28BKPxeP7IVPbbInuFf5ytkk4l4hXaxGculAcjrMXn2fRbCSxRmB3H03cpxaAZiww89CUk8BwwcDTwQaSRK1BXxqcECNzfO14qmP4BaVbwkIm48wG/4wbba38q1mlPbFzEZ/hJzGeUrCQMS4mFJAjjD0X/lfV2RQ1QGm+fCNH5bc4OQaN/trFXW7YhTnIgU/nsbCb11gVUP8cOJMgGs78HnULgcVhgo9stxpDBQ==",
        "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": "Michael Baum <michaelba@nvidia.com>",
        "To": "<dev@dpdk.org>",
        "CC": "Matan Azrad <matan@nvidia.com>, Raslan Darawsheh <rasland@nvidia.com>,\n \"Ori Kam\" <orika@nvidia.com>",
        "Subject": "[PATCH 2/3] ethdev: add queue-based API to report aged flow rules",
        "Date": "Wed, 21 Sep 2022 17:54:08 +0300",
        "Message-ID": "<20220921145409.511328-3-michaelba@nvidia.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20220921145409.511328-1-michaelba@nvidia.com>",
        "References": "<20220921145409.511328-1-michaelba@nvidia.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-EOPAttributedMessage": "0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "CO1NAM11FT054:EE_|DM4PR12MB5868:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "b993083e-e8cc-4f80-e9f5-08da9be12f9e",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n r4Q3Dx6L8D6umGyKw/JQQVC06mVJ2eF3FU54bytKx57wRcF1egly55eFHW+3LRt7uM6Hn1cIu0GKCS1oUgvQv02IEB7VLlMx2u1/nQ2lDXB3VDObHNeREhM2HYjFrU7LlPkQCYCQNmoBCmT0jPs27JcTmE4YYtOj9zdI5Vgtgv+s3Xc5/nrVNQoxbuE6c+/+Mt3SfLf+8WCq3wOIROw2r9WPS7KR96z7J2t0OTgMyHFRSyhgxgFcALl44TbuOz9NwVodjNc2svEU/37AhWTordYrzUFzVDx9uH1PFUQED8XWSmuBfQUU0W7moNwZRwyopg5lTV+ZeEgvn8i7KiddDuMLEMO1Q/CMhL/5Ne8tHpO55xoZPWB3to/0MdTmr2qAvWNR69GEMFiE4GU2WrTn1mD55F8cTWeDuF87XNJP+Zn/L464dQo4j6EuLqreNIsIHjOUbt+WqBtNUPYHYNytD33hagHTW8qOaTe5afCJ5X1f8A4LLcE/yB1cwQP4RAorEJ/BsnEySSp3seKaalFsnAeQ0bxPoFDIaomfdwgdQ+80QJ3v+nQFn6l2oGx+bBv8OM39Nvo3gJljlzbDNVMHEe0w1stxb3qB4iXyR5o7SHJBujV7RKlEPdrCKNaDRZvCyoCWvJ0KRcUg7LDR6EqtCTjoWUZDdvZFffM1dMcBAn3ALUY42yGjYP9VXJGFpYpYPT7qWJlyrsc4ctzZ37U7hLlF8VMvmfDKv00PDKFSZB3Jl1wNbOr86/p1ZQ/DL6UzmtFhBLKods7Ikt+79lzo4w==",
        "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:(13230022)(4636009)(396003)(136003)(346002)(39860400002)(376002)(451199015)(36840700001)(46966006)(40470700004)(36756003)(86362001)(70586007)(2906002)(30864003)(5660300002)(54906003)(8936002)(83380400001)(55016003)(40460700003)(40480700001)(47076005)(426003)(478600001)(82740400003)(26005)(6666004)(316002)(336012)(7696005)(2616005)(6916009)(7636003)(186003)(107886003)(41300700001)(6286002)(356005)(1076003)(36860700001)(4326008)(8676002)(70206006)(82310400005);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "Nvidia.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "21 Sep 2022 14:54:29.4299 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n b993083e-e8cc-4f80-e9f5-08da9be12f9e",
        "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 CO1NAM11FT054.eop-nam11.prod.protection.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "DM4PR12MB5868",
        "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": "When application use queue-based flow rule management and operate the\nsame flow rule on the same queue, e.g create/destroy/query, API of\nquerying aged flow rules should also have queue id parameter just like\nother queue-based flow APIs.\n\nBy this way, PMD can work in more optimized way since resources are\nisolated by queue and needn't synchronize.\n\nIf application do use queue-based flow management but configure port\nwithout RTE_FLOW_PORT_FLAG_STRICT_QUEUE, which means application operate\na given flow rule on different queues, the queue id parameter will\nbe ignored.\n\nSigned-off-by: Michael Baum <michaelba@nvidia.com>\n---\n app/test-pmd/cmdline_flow.c                 |  17 ++-\n app/test-pmd/config.c                       | 159 +++++++++++++++++++-\n app/test-pmd/testpmd.h                      |   1 +\n doc/guides/testpmd_app_ug/testpmd_funcs.rst |  86 ++++++++++-\n lib/ethdev/rte_flow.c                       |  22 +++\n lib/ethdev/rte_flow.h                       |  48 +++++-\n lib/ethdev/rte_flow_driver.h                |   7 +\n lib/ethdev/version.map                      |   3 +\n 8 files changed, 333 insertions(+), 10 deletions(-)",
    "diff": "diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c\nindex a982083d27..4fb90a92cb 100644\n--- a/app/test-pmd/cmdline_flow.c\n+++ b/app/test-pmd/cmdline_flow.c\n@@ -127,6 +127,7 @@ enum index {\n \t/* Queue arguments. */\n \tQUEUE_CREATE,\n \tQUEUE_DESTROY,\n+\tQUEUE_AGED,\n \tQUEUE_INDIRECT_ACTION,\n \n \t/* Queue create arguments. */\n@@ -1159,6 +1160,7 @@ static const enum index next_table_destroy_attr[] = {\n static const enum index next_queue_subcmd[] = {\n \tQUEUE_CREATE,\n \tQUEUE_DESTROY,\n+\tQUEUE_AGED,\n \tQUEUE_INDIRECT_ACTION,\n \tZERO,\n };\n@@ -2942,6 +2944,13 @@ static const struct token token_list[] = {\n \t\t.args = ARGS(ARGS_ENTRY(struct buffer, queue)),\n \t\t.call = parse_qo_destroy,\n \t},\n+\t[QUEUE_AGED] = {\n+\t\t.name = \"aged\",\n+\t\t.help = \"list and destroy aged flows\",\n+\t\t.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),\n+\t\t.args = ARGS(ARGS_ENTRY(struct buffer, queue)),\n+\t\t.call = parse_aged,\n+\t},\n \t[QUEUE_INDIRECT_ACTION] = {\n \t\t.name = \"indirect_action\",\n \t\t.help = \"queue indirect actions\",\n@@ -8640,8 +8649,8 @@ parse_aged(struct context *ctx, const struct token *token,\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 != AGED)\n+\tif (!out->command || out->command == QUEUE) {\n+\t\tif (ctx->curr != AGED && ctx->curr != QUEUE_AGED)\n \t\t\treturn -1;\n \t\tif (sizeof(*out) > size)\n \t\t\treturn -1;\n@@ -10496,6 +10505,10 @@ 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 QUEUE_AGED:\n+\t\tport_queue_flow_aged(in->port, in->queue,\n+\t\t\t\t     in->args.aged.destroy);\n+\t\tbreak;\n \tcase QUEUE_INDIRECT_ACTION_CREATE:\n \t\tport_queue_action_handle_create(\n \t\t\t\tin->port, in->queue, in->postpone,\ndiff --git a/app/test-pmd/config.c b/app/test-pmd/config.c\nindex a2939867c4..31952467fb 100644\n--- a/app/test-pmd/config.c\n+++ b/app/test-pmd/config.c\n@@ -2662,6 +2662,7 @@ port_queue_flow_create(portid_t port_id, queueid_t queue_id,\n \t\t       const struct rte_flow_action *actions)\n {\n \tstruct rte_flow_op_attr op_attr = { .postpone = postpone };\n+\tstruct rte_flow_attr flow_attr = { 0 };\n \tstruct rte_flow *flow;\n \tstruct rte_port *port;\n \tstruct port_flow *pf;\n@@ -2713,7 +2714,7 @@ port_queue_flow_create(portid_t port_id, queueid_t queue_id,\n \t\treturn -EINVAL;\n \t}\n \n-\tpf = port_flow_new(NULL, pattern, actions, &error);\n+\tpf = port_flow_new(&flow_attr, pattern, actions, &error);\n \tif (!pf)\n \t\treturn port_flow_complain(&error);\n \tif (age) {\n@@ -2950,6 +2951,162 @@ port_queue_flow_push(portid_t port_id, queueid_t queue_id)\n \treturn ret;\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,\n+\t\t\t     const uint32_t *rule, int nb_flows)\n+{\n+\tstruct rte_port *port = &ports[port_id];\n+\tstruct rte_flow_op_result *res;\n+\tstruct rte_flow_error error;\n+\tuint32_t n = nb_flows;\n+\tint ret = 0;\n+\tint i;\n+\n+\tres = calloc(port->queue_sz, sizeof(struct rte_flow_op_result));\n+\tif (!res) {\n+\t\tprintf(\"Failed to allocate memory for pulled results\\n\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tmemset(&error, 0x66, sizeof(error));\n+\twhile (nb_flows > 0) {\n+\t\tint success = 0;\n+\n+\t\tif (n > port->queue_sz)\n+\t\t\tn = port->queue_sz;\n+\t\tret = port_queue_flow_destroy(port_id, queue_id, true, n, rule);\n+\t\tif (ret < 0) {\n+\t\t\tfree(res);\n+\t\t\treturn ret;\n+\t\t}\n+\t\tret = rte_flow_push(port_id, queue_id, &error);\n+\t\tif (ret < 0) {\n+\t\t\tprintf(\"Failed to push operations in the queue: %s\\n\",\n+\t\t\t       strerror(-ret));\n+\t\t\tfree(res);\n+\t\t\treturn ret;\n+\t\t}\n+\t\twhile (success < nb_flows) {\n+\t\t\tret = rte_flow_pull(port_id, queue_id, res,\n+\t\t\t\t\t    port->queue_sz, &error);\n+\t\t\tif (ret < 0) {\n+\t\t\t\tprintf(\"Failed to pull a operation results: %s\\n\",\n+\t\t\t\t       strerror(-ret));\n+\t\t\t\tfree(res);\n+\t\t\t\treturn ret;\n+\t\t\t}\n+\n+\t\t\tfor (i = 0; i < ret; i++) {\n+\t\t\t\tif (res[i].status == RTE_FLOW_OP_SUCCESS)\n+\t\t\t\t\tsuccess++;\n+\t\t\t}\n+\t\t}\n+\t\trule += n;\n+\t\tnb_flows -= n;\n+\t\tn = nb_flows;\n+\t}\n+\n+\tfree(res);\n+\treturn ret;\n+}\n+\n+/** List simply and destroy all aged flows per queue. */\n+void\n+port_queue_flow_aged(portid_t port_id, uint32_t queue_id, uint8_t destroy)\n+{\n+\tvoid **contexts;\n+\tint nb_context, total = 0, idx;\n+\tuint32_t *rules = NULL;\n+\tstruct rte_port *port;\n+\tstruct rte_flow_error error;\n+\tenum age_action_context_type *type;\n+\tunion {\n+\t\tstruct port_flow *pf;\n+\t\tstruct port_indirect_action *pia;\n+\t} ctx;\n+\n+\tif (port_id_is_invalid(port_id, ENABLED_WARN) ||\n+\t    port_id == (portid_t)RTE_PORT_ALL)\n+\t\treturn;\n+\tport = &ports[port_id];\n+\tif (queue_id >= port->queue_nb) {\n+\t\tprintf(\"Error: queue #%u is invalid\\n\", queue_id);\n+\t\treturn;\n+\t}\n+\ttotal = rte_flow_get_q_aged_flows(port_id, queue_id, NULL, 0, &error);\n+\tif (total < 0) {\n+\t\tport_flow_complain(&error);\n+\t\treturn;\n+\t}\n+\tprintf(\"Port %u queue %u total aged flows: %d\\n\",\n+\t       port_id, queue_id, total);\n+\tif (total == 0)\n+\t\treturn;\n+\tcontexts = calloc(total, sizeof(void *));\n+\tif (contexts == NULL) {\n+\t\tprintf(\"Cannot allocate contexts for aged flow\\n\");\n+\t\treturn;\n+\t}\n+\tprintf(\"%-20s\\tID\\tGroup\\tPrio\\tAttr\\n\", \"Type\");\n+\tnb_context = rte_flow_get_q_aged_flows(port_id, queue_id, contexts,\n+\t\t\t\t\t       total, &error);\n+\tif (nb_context > total) {\n+\t\tprintf(\"Port %u queue %u get aged flows count(%d) > total(%d)\\n\",\n+\t\t       port_id, queue_id, nb_context, total);\n+\t\tfree(contexts);\n+\t\treturn;\n+\t}\n+\tif (destroy) {\n+\t\trules = malloc(sizeof(uint32_t) * nb_context);\n+\t\tif (rules == NULL)\n+\t\t\tprintf(\"Cannot allocate memory for destroy aged flow\\n\");\n+\t}\n+\ttotal = 0;\n+\tfor (idx = 0; idx < nb_context; idx++) {\n+\t\tif (!contexts[idx]) {\n+\t\t\tprintf(\"Error: get Null context in port %u queue %u\\n\",\n+\t\t\t       port_id, queue_id);\n+\t\t\tcontinue;\n+\t\t}\n+\t\ttype = (enum age_action_context_type *)contexts[idx];\n+\t\tswitch (*type) {\n+\t\tcase ACTION_AGE_CONTEXT_TYPE_FLOW:\n+\t\t\tctx.pf = container_of(type, struct port_flow, age_type);\n+\t\t\tprintf(\"%-20s\\t%\" PRIu32 \"\\t%\" PRIu32 \"\\t%\" PRIu32\n+\t\t\t\t\t\t\t\t \"\\t%c%c%c\\t\\n\",\n+\t\t\t       \"Flow\",\n+\t\t\t       ctx.pf->id,\n+\t\t\t       ctx.pf->rule.attr->group,\n+\t\t\t       ctx.pf->rule.attr->priority,\n+\t\t\t       ctx.pf->rule.attr->ingress ? 'i' : '-',\n+\t\t\t       ctx.pf->rule.attr->egress ? 'e' : '-',\n+\t\t\t       ctx.pf->rule.attr->transfer ? 't' : '-');\n+\t\t\tif (rules != NULL) {\n+\t\t\t\trules[total] = ctx.pf->id;\n+\t\t\t\ttotal++;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION:\n+\t\t\tctx.pia = container_of(type,\n+\t\t\t\t\t       struct port_indirect_action,\n+\t\t\t\t\t       age_type);\n+\t\t\tprintf(\"%-20s\\t%\" PRIu32 \"\\n\", \"Indirect action\",\n+\t\t\t       ctx.pia->id);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tprintf(\"Error: invalid context type %u\\n\", port_id);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tif (rules != NULL) {\n+\t\tport_queue_aged_flow_destroy(port_id, queue_id, rules, total);\n+\t\tfree(rules);\n+\t}\n+\tprintf(\"\\n%d flows destroyed\\n\", total);\n+\tfree(contexts);\n+}\n+\n /** Pull queue operation results from the queue. */\n int\n port_queue_flow_pull(portid_t port_id, queueid_t queue_id)\ndiff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h\nindex fb2f5195d3..4e24dd9ee0 100644\n--- a/app/test-pmd/testpmd.h\n+++ b/app/test-pmd/testpmd.h\n@@ -982,6 +982,7 @@ int port_queue_action_handle_update(portid_t port_id, uint32_t queue_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+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,\n \t\t       const struct rte_flow_item *pattern,\ndiff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst\nindex 6c12e0286c..e68b852e29 100644\n--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst\n+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst\n@@ -3085,9 +3085,10 @@ following sections.\n        [meters_number {number}] [flags {number}]\n \n - Create a pattern template::\n+\n    flow pattern_template {port_id} create [pattern_template_id {id}]\n        [relaxed {boolean}] [ingress] [egress] [transfer]\n-\t   template {item} [/ {item} [...]] / end\n+       template {item} [/ {item} [...]] / end\n \n - Destroy a pattern template::\n \n@@ -3186,6 +3187,10 @@ following sections.\n \n    flow aged {port_id} [destroy]\n \n+- Enqueue list and destroy aged flow rules::\n+\n+   flow queue {port_id} aged {queue_id} [destroy]\n+\n - Tunnel offload - create a tunnel stub::\n \n    flow tunnel create {port_id} type {tunnel_type}\n@@ -4427,7 +4432,7 @@ Disabling isolated mode::\n  testpmd>\n \n Dumping HW internal information\n-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n \n ``flow dump`` dumps the hardware's internal representation information of\n all flows. It is bound to ``rte_flow_dev_dump()``::\n@@ -4443,10 +4448,10 @@ Otherwise, it will complain error occurred::\n    Caught error type [...] ([...]): [...]\n \n Listing and destroying aged flow rules\n-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n \n ``flow aged`` simply lists aged flow rules be get from api ``rte_flow_get_aged_flows``,\n-and ``destroy`` parameter can be used to destroy those flow rules in PMD.\n+and ``destroy`` parameter can be used to destroy those flow rules in PMD::\n \n    flow aged {port_id} [destroy]\n \n@@ -4481,7 +4486,7 @@ will be ID 3, ID 1, ID 0::\n    1       0       0       i--\n    0       0       0       i--\n \n-If attach ``destroy`` parameter, the command will destroy all the list aged flow rules.\n+If attach ``destroy`` parameter, the command will destroy all the list aged flow rules::\n \n    testpmd> flow aged 0 destroy\n    Port 0 total aged flows: 4\n@@ -4499,6 +4504,77 @@ If attach ``destroy`` parameter, the command will destroy all the list aged flow\n    testpmd> flow aged 0\n    Port 0 total aged flows: 0\n \n+\n+Enqueueing listing and destroying aged flow rules\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+``flow queue aged`` simply lists aged flow rules be get from\n+``rte_flow_get_q_aged_flows`` API, and ``destroy`` parameter can be used to\n+destroy those flow rules in PMD::\n+\n+   flow queue {port_id} aged {queue_id} [destroy]\n+\n+Listing current aged flow rules::\n+\n+   testpmd> flow queue 0 aged 0\n+   Port 0 queue 0 total aged flows: 0\n+   testpmd> flow queue 0 create 0 ingress tanle 0 item_template 0 action_template 0\n+      pattern eth / ipv4 src is 2.2.2.14 / end\n+      actions age timeout 5 / queue index 0 /  end\n+   Flow rule #0 creation enqueued\n+   testpmd> flow queue 0 create 0 ingress tanle 0 item_template 0 action_template 0\n+      pattern eth / ipv4 src is 2.2.2.15 / end\n+      actions age timeout 4 / queue index 0 /  end\n+   Flow rule #1 creation enqueued\n+   testpmd> flow queue 0 create 0 ingress tanle 0 item_template 0 action_template 0\n+      pattern eth / ipv4 src is 2.2.2.16 / end\n+      actions age timeout 4 / queue index 0 /  end\n+   Flow rule #2 creation enqueued\n+   testpmd> flow queue 0 create 0 ingress tanle 0 item_template 0 action_template 0\n+      pattern eth / ipv4 src is 2.2.2.17 / end\n+      actions age timeout 4 / queue index 0 /  end\n+   Flow rule #3 creation enqueued\n+   testpmd> flow pull 0 queue 0\n+   Queue #0 pulled 4 operations (0 failed, 4 succeeded)\n+\n+Aged Rules are simply list as command ``flow queue {port_id} list {queue_id}``,\n+but strip the detail rule information, all the aged flows are sorted by the\n+longest timeout time. For example, if those rules is configured in the same time,\n+ID 2 will be the first aged out rule, the next will be ID 3, ID 1, ID 0::\n+\n+   testpmd> flow queue 0 aged 0\n+   Port 0 queue 0 total aged flows: 4\n+   ID      Group   Prio    Attr\n+   2       0       0       ---\n+   3       0       0       ---\n+   1       0       0       ---\n+   0       0       0       ---\n+\n+   0 flows destroyed\n+\n+If attach ``destroy`` parameter, the command will destroy all the list aged flow rules::\n+\n+   testpmd> flow queue 0 aged 0 destroy\n+   Port 0 queue 0 total aged flows: 4\n+   ID      Group   Prio    Attr\n+   2       0       0       ---\n+   3       0       0       ---\n+   1       0       0       ---\n+   0       0       0       ---\n+   Flow rule #2 destruction enqueued\n+   Flow rule #3 destruction enqueued\n+   Flow rule #1 destruction enqueued\n+   Flow rule #0 destruction enqueued\n+\n+   4 flows destroyed\n+   testpmd> flow queue 0 aged 0\n+   Port 0 total aged flows: 0\n+\n+.. note::\n+\n+   The queue must be empty before attaching ``destroy`` parameter.\n+\n+\n Creating indirect actions\n ~~~~~~~~~~~~~~~~~~~~~~~~~\n \ndiff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c\nindex 501be9d602..5c95ac7f8b 100644\n--- a/lib/ethdev/rte_flow.c\n+++ b/lib/ethdev/rte_flow.c\n@@ -1133,6 +1133,28 @@ rte_flow_get_aged_flows(uint16_t port_id, void **contexts,\n \t\t\t\t  NULL, rte_strerror(ENOTSUP));\n }\n \n+int\n+rte_flow_get_q_aged_flows(uint16_t port_id, uint32_t queue_id, void **contexts,\n+\t\t\t  uint32_t nb_contexts, struct rte_flow_error *error)\n+{\n+\tstruct rte_eth_dev *dev = &rte_eth_devices[port_id];\n+\tconst struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error);\n+\tint ret;\n+\n+\tif (unlikely(!ops))\n+\t\treturn -rte_errno;\n+\tif (likely(!!ops->get_q_aged_flows)) {\n+\t\tfts_enter(dev);\n+\t\tret = ops->get_q_aged_flows(dev, queue_id, contexts,\n+\t\t\t\t\t    nb_contexts, error);\n+\t\tfts_exit(dev);\n+\t\treturn flow_err(port_id, ret, error);\n+\t}\n+\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t  NULL, rte_strerror(ENOTSUP));\n+}\n+\n struct rte_flow_action_handle *\n rte_flow_action_handle_create(uint16_t port_id,\n \t\t\t      const struct rte_flow_indir_action_conf *conf,\ndiff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h\nindex c552771472..d830b02321 100644\n--- a/lib/ethdev/rte_flow.h\n+++ b/lib/ethdev/rte_flow.h\n@@ -2930,8 +2930,8 @@ struct rte_flow_action_queue {\n  * on the flow. RTE_ETH_EVENT_FLOW_AGED event is triggered when a\n  * port detects new aged-out flows.\n  *\n- * The flow context and the flow handle will be reported by the\n- * rte_flow_get_aged_flows API.\n+ * The flow context and the flow handle will be reported by the either\n+ * rte_flow_get_aged_flows or rte_flow_get_q_aged_flows APIs.\n  */\n struct rte_flow_action_age {\n \tuint32_t timeout:24; /**< Time in seconds. */\n@@ -4443,6 +4443,50 @@ int\n rte_flow_get_aged_flows(uint16_t port_id, void **contexts,\n \t\t\tuint32_t nb_contexts, struct rte_flow_error *error);\n \n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Get aged-out flows of a given port on the given flow queue.\n+ *\n+ * If application configure port attribute with RTE_FLOW_PORT_FLAG_STRICT_QUEUE,\n+ * there is no RTE_ETH_EVENT_FLOW_AGED event and this function must be called to\n+ * get the aged flows synchronously.\n+ *\n+ * If application configure port attribute without\n+ * RTE_FLOW_PORT_FLAG_STRICT_QUEUE, RTE_ETH_EVENT_FLOW_AGED event will be\n+ * triggered at least one new aged out flow was detected on any flow queue after\n+ * the last call to rte_flow_get_q_aged_flows.\n+ * In addition, the @p queue_id will be ignored.\n+ * This function can be called to get the aged flows asynchronously from the\n+ * event callback or synchronously regardless the event.\n+ *\n+ * @param[in] port_id\n+ *   Port identifier of Ethernet device.\n+ * @param[in] queue_id\n+ *   Flow queue to query. Ignored when RTE_FLOW_PORT_FLAG_STRICT_QUEUE not set.\n+ * @param[in, out] contexts\n+ *   The address of an array of pointers to the aged-out flows contexts.\n+ * @param[in] nb_contexts\n+ *   The length of context array pointers.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL. Initialized in case of\n+ *   error only.\n+ *\n+ * @return\n+ *   if nb_contexts is 0, return the amount of all aged contexts.\n+ *   if nb_contexts is not 0 , return the amount of aged flows reported\n+ *   in the context array, otherwise negative errno value.\n+ *\n+ * @see rte_flow_action_age\n+ * @see RTE_ETH_EVENT_FLOW_AGED\n+ * @see rte_flow_port_flag\n+ */\n+__rte_experimental\n+int\n+rte_flow_get_q_aged_flows(uint16_t port_id, uint32_t queue_id, void **contexts,\n+\t\t\t  uint32_t nb_contexts, struct rte_flow_error *error);\n+\n /**\n  * Specify indirect action object configuration\n  */\ndiff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h\nindex 2bff732d6a..f0a03bf149 100644\n--- a/lib/ethdev/rte_flow_driver.h\n+++ b/lib/ethdev/rte_flow_driver.h\n@@ -84,6 +84,13 @@ struct rte_flow_ops {\n \t\t void **context,\n \t\t uint32_t nb_contexts,\n \t\t struct rte_flow_error *err);\n+\t/** See rte_flow_get_q_aged_flows() */\n+\tint (*get_q_aged_flows)\n+\t\t(struct rte_eth_dev *dev,\n+\t\t uint32_t queue_id,\n+\t\t void **contexts,\n+\t\t uint32_t nb_contexts,\n+\t\t struct rte_flow_error *error);\n \t/** See rte_flow_action_handle_create() */\n \tstruct rte_flow_action_handle *(*action_handle_create)\n \t\t(struct rte_eth_dev *dev,\ndiff --git a/lib/ethdev/version.map b/lib/ethdev/version.map\nindex 03f52fee91..4a40d24d8f 100644\n--- a/lib/ethdev/version.map\n+++ b/lib/ethdev/version.map\n@@ -285,6 +285,9 @@ EXPERIMENTAL {\n \trte_mtr_color_in_protocol_priority_get;\n \trte_mtr_color_in_protocol_set;\n \trte_mtr_meter_vlan_table_update;\n+\n+\t# added in 22.11\n+\trte_flow_get_q_aged_flows;\n };\n \n INTERNAL {\n",
    "prefixes": [
        "2/3"
    ]
}