get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 131151,
    "url": "http://patches.dpdk.org/api/patches/131151/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20230904130313.327809-3-mattias.ronnblom@ericsson.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20230904130313.327809-3-mattias.ronnblom@ericsson.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230904130313.327809-3-mattias.ronnblom@ericsson.com",
    "date": "2023-09-04T13:03:12",
    "name": "[v3,2/3] test: add dispatcher test suite",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "64e96d3298eb7b26ad97ebed16748edde4d0be5f",
    "submitter": {
        "id": 1077,
        "url": "http://patches.dpdk.org/api/people/1077/?format=api",
        "name": "Mattias Rönnblom",
        "email": "mattias.ronnblom@ericsson.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20230904130313.327809-3-mattias.ronnblom@ericsson.com/mbox/",
    "series": [
        {
            "id": 29419,
            "url": "http://patches.dpdk.org/api/series/29419/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=29419",
            "date": "2023-09-04T13:03:10",
            "name": "Add dispatcher library",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/29419/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/131151/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/131151/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 F1A4C424F0;\n\tMon,  4 Sep 2023 15:09:14 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 5583A40A72;\n\tMon,  4 Sep 2023 15:09:06 +0200 (CEST)",
            "from EUR04-VI1-obe.outbound.protection.outlook.com\n (mail-vi1eur04on2044.outbound.protection.outlook.com [40.107.8.44])\n by mails.dpdk.org (Postfix) with ESMTP id B58374068A;\n Mon,  4 Sep 2023 15:09:04 +0200 (CEST)",
            "from AM6PR04CA0052.eurprd04.prod.outlook.com (2603:10a6:20b:f0::29)\n by GVXPR07MB9678.eurprd07.prod.outlook.com (2603:10a6:150:114::10)\n with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6745.30; Mon, 4 Sep\n 2023 13:09:02 +0000",
            "from AM1PEPF000252DC.eurprd07.prod.outlook.com\n (2603:10a6:20b:f0:cafe::90) by AM6PR04CA0052.outlook.office365.com\n (2603:10a6:20b:f0::29) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6745.32 via Frontend\n Transport; Mon, 4 Sep 2023 13:09:02 +0000",
            "from oa.msg.ericsson.com (192.176.1.74) by\n AM1PEPF000252DC.mail.protection.outlook.com (10.167.16.54) with Microsoft\n SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id\n 15.20.6768.25 via Frontend Transport; Mon, 4 Sep 2023 13:09:02 +0000",
            "from ESESSMB505.ericsson.se (153.88.183.166) by\n ESESBMB504.ericsson.se (153.88.183.171) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id\n 15.1.2507.32; Mon, 4 Sep 2023 15:09:00 +0200",
            "from seliicinfr00049.seli.gic.ericsson.se (153.88.183.153) by\n smtp.internal.ericsson.com (153.88.183.193) with Microsoft SMTP Server id\n 15.1.2507.32 via Frontend Transport; Mon, 4 Sep 2023 15:09:00 +0200",
            "from breslau.. (seliicwb00002.seli.gic.ericsson.se [10.156.25.100])\n by seliicinfr00049.seli.gic.ericsson.se (Postfix) with ESMTP id\n D82F9380061; Mon,  4 Sep 2023 15:09:00 +0200 (CEST)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=Ce3VvbUzS0TouyItSEXBZc2fQu6czZmT7kQrOKmUgyRo51hwK9b2NXKkFCR5cZrpo6B+ZbRKQqODeC+Pen8h8BzMMOjUXti11pI9zCTI1G9Sin5TjsgrMVAzIYjx+6OsT1BQFmW77aFF7Gpc4btUXc/VnDNpDdYnMaf7+HIb8vWD9x4K5t78M52onXR8zsw7PGBukerALCu2YxkvMFlMS5GOnSFRtcU6HQB0hMPUuGsx9Ryu2O+6WhQAPXdjphV7gAzvnMwyFNbLNDS79uLNsOp4adt1KYOjCCl/5F0A0HOhy3r1jvK1x3GJwxHZDu3i7vCykBf3rnedJItqY1cLJw==",
        "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=O81l1Gm7+W3DSgkbGl8b4FTheJc2eCZM/cAkcG6GwpE=;\n b=ZoPNUZHwWJ+/SHU7uf6rdfKgqtUyFavXFs866m2/j1DvlsEQiRhUrevWCtp6NXEeVtB07cLgxXHxOa01HF2GquJ23/cKSC8mXvjt+FD8Xfpt0FnqxCY39MaJ1I5dEswoMDMo7x309hCNhNHod38JQeiHGNUaKz3vri0dGagWt5rOLnvm3bV3hCut+ZYrgyg8R0MQQTwmN1JQgVlgSEebYkb9lPPpHfifIuoUfSg9RFB05ADihMuAvIabvjCZOOWQlX6E8rQDgTt4mIweONH3d5SnAOqfPAFyKeVhFss8j/kcgCxf0atFnTuH2Fsec3dZ8qXypcc4QWDu2e7/KM+tWA==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass (sender ip is\n 192.176.1.74) smtp.rcpttodomain=dpdk.org smtp.mailfrom=ericsson.com;\n dmarc=pass (p=reject sp=reject pct=100) action=none header.from=ericsson.com;\n dkim=none (message not signed); arc=none",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=ericsson.com;\n s=selector1;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=O81l1Gm7+W3DSgkbGl8b4FTheJc2eCZM/cAkcG6GwpE=;\n b=e5E5xXKIPx7Tta6g45oUlj2BRDDYwXGBVSTvHAhPx+tH8kRbGNrh+I5UhKQrJa5NCovWUHwQ/Lkxu+1+Irp4e6Zj5oToUIUFMGJPJ+dDDNz55GgMyZHcQdczLRuNJ/DSyHSuEXP21das2lMkXFLVsxlQ4pJg5cpO7qrLiWM4FYo=",
        "X-MS-Exchange-Authentication-Results": "spf=pass (sender IP is 192.176.1.74)\n smtp.mailfrom=ericsson.com; dkim=none (message not signed)\n header.d=none;dmarc=pass action=none header.from=ericsson.com;",
        "Received-SPF": "Pass (protection.outlook.com: domain of ericsson.com designates\n 192.176.1.74 as permitted sender)\n receiver=protection.outlook.com;\n client-ip=192.176.1.74; helo=oa.msg.ericsson.com; pr=C",
        "From": "=?utf-8?q?Mattias_R=C3=B6nnblom?= <mattias.ronnblom@ericsson.com>",
        "To": "<dev@dpdk.org>",
        "CC": "Jerin Jacob <jerinj@marvell.com>, <techboard@dpdk.org>,\n <harry.van.haaren@intel.com>, <hofors@lysator.liu.se>,\n Peter Nilsson <peter.j.nilsson@ericsson.com>,\n Heng Wang <heng.wang@ericsson.com>,\n \"Naga Harish K S V\" <s.v.naga.harish.k@intel.com>,\n Pavan Nikhilesh <pbhagavatula@marvell.com>,\n Gujjar Abhinandan S <abhinandan.gujjar@intel.com>,\n Erik Gabriel Carrillo <erik.g.carrillo@intel.com>,\n Shijith Thotton <sthotton@marvell.com>,\n \"Hemant Agrawal\" <hemant.agrawal@nxp.com>,\n Sachin Saxena <sachin.saxena@oss.nxp.com>,  Liang Ma <liangma@liangbit.com>,\n Peter Mccarthy <peter.mccarthy@intel.com>, Zhirun Yan <zhirun.yan@intel.com>,\n =?utf-8?q?Mattias_R=C3=B6nnblom?= <mattias.ronnblom@ericsson.com>",
        "Subject": "[PATCH v3 2/3] test: add dispatcher test suite",
        "Date": "Mon, 4 Sep 2023 15:03:12 +0200",
        "Message-ID": "<20230904130313.327809-3-mattias.ronnblom@ericsson.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20230904130313.327809-1-mattias.ronnblom@ericsson.com>",
        "References": "<20230616074041.159675-2-mattias.ronnblom@ericsson.com>\n <20230904130313.327809-1-mattias.ronnblom@ericsson.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"UTF-8\"",
        "Content-Transfer-Encoding": "8bit",
        "X-EOPAttributedMessage": "0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "AM1PEPF000252DC:EE_|GVXPR07MB9678:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "618181e7-ff80-41a4-598f-08dbad481c31",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n HKqC8APPXPxzXYQYZt+rw5dmfyJytOHRv23+SOmsc6GqxmJMx55FNdrFUW7a7RfyqD6EOl5nYVZ5cGqoVoI1MryTcT4qKANvvGNAvNXfJRHiB15x0BjRR8MLJLlPHciMnQl0lGpb2EtiMOEgwenkJUdwVntq3PA/DILogyb7F0fNmOvg01CVITM6UQw3rNmHEHn1AJLtPHv286o5SlXcBHeCY435y6lDgXML48v7k9P04RErf6YH+Z+P2YZ1ax+M40/MrMV6H4NbhhmOZ4iv7Zz8FiEJGsHUtcTEiMOZ89yYuuAFB0uKL18pX8mqG+WculjtIqXQxI6ayotWRwzEADdLSfR/4KSQGnT2psgCEu5GRm4J/445rP4d0C6nkHM91TNe78fv6u/ivwCVY3qi8xsZjQ9ZyIf/44DiWhCLHVkWBT8nhx8s9nK0HRkcSysrCnhe7/toqMv+Rl8PLZmJY54DfFW3vmKacSSYksZIOWgW+Eu2OWie04OQOMi+M3a8DXq4IWkIxcmXpjEJt1Hxv8dqIkD7deNn4vA97QdMLookkgw62yk4L5UZPGWA2UPPq/fa3zYs+GLB6e0MRZwjAYvseyAT0qV6pk9MWz4Ppsrz+DIWuugpeTB2CCglN7JTgt6UHJMA0s7WMlrstaDcaTW61vBWmns3+1JzPSt9kEv0vOmlbJufY3+tVPUid6gcOw7J1GuEzNhuZMc7CiPWoXsegc/ZeVHWP7hKa5IuP0dAp5Sn0sz3yy+FG3IiVcUnilFxJeSeyYB7TCCWt1pk12BT9JOuUcikfgZgBMyfvJE=",
        "X-Forefront-Antispam-Report": "CIP:192.176.1.74; CTRY:SE; LANG:en; SCL:1; SRV:;\n IPV:NLI; SFV:NSPM; H:oa.msg.ericsson.com; PTR:office365.se.ericsson.net;\n CAT:NONE;\n SFS:(13230031)(4636009)(39860400002)(346002)(136003)(376002)(396003)(451199024)(1800799009)(82310400011)(186009)(46966006)(36840700001)(40470700004)(30864003)(7416002)(41300700001)(8936002)(40480700001)(83380400001)(66574015)(478600001)(6916009)(6666004)(2906002)(70586007)(70206006)(5660300002)(4326008)(8676002)(54906003)(316002)(107886003)(2616005)(1076003)(40460700003)(26005)(36860700001)(336012)(6266002)(356005)(36756003)(7636003)(82740400003)(82960400001)(47076005)(86362001);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "ericsson.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "04 Sep 2023 13:09:02.4366 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 618181e7-ff80-41a4-598f-08dbad481c31",
        "X-MS-Exchange-CrossTenant-Id": "92e84ceb-fbfd-47ab-be52-080c6b87953f",
        "X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp": "\n TenantId=92e84ceb-fbfd-47ab-be52-080c6b87953f; Ip=[192.176.1.74];\n Helo=[oa.msg.ericsson.com]",
        "X-MS-Exchange-CrossTenant-AuthSource": "\n AM1PEPF000252DC.eurprd07.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "GVXPR07MB9678",
        "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": "Add unit tests for the dispatcher.\n\n--\nPATCH v3:\n o Adapt the test suite to dispatcher API name changes.\n\nPATCH v2:\n o Test finalize callback functionality.\n o Test handler and finalizer count upper limits.\n o Add statistics reset test.\n o Make sure dispatcher supply the proper event dev id and port id back\n   to the application.\n\nPATCH:\n o Extend test to cover often-used handler optimization feature.\n\nRFC v4:\n o Adapt to non-const events in process function prototype.\n\nSigned-off-by: Mattias Rönnblom <mattias.ronnblom@ericsson.com>\n---\n MAINTAINERS                |    1 +\n app/test/meson.build       |    1 +\n app/test/test_dispatcher.c | 1054 ++++++++++++++++++++++++++++++++++++\n 3 files changed, 1056 insertions(+)\n create mode 100644 app/test/test_dispatcher.c",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex 6704cd5b2c..43890cad0e 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -1729,6 +1729,7 @@ F: lib/node/\n Dispatcher - EXPERIMENTAL\n M: Mattias Rönnblom <mattias.ronnblom@ericsson.com>\n F: lib/dispatcher/\n+F: app/test/test_dispatcher.c\n \n Test Applications\n -----------------\ndiff --git a/app/test/meson.build b/app/test/meson.build\nindex 05bae9216d..3303c73817 100644\n--- a/app/test/meson.build\n+++ b/app/test/meson.build\n@@ -55,6 +55,7 @@ source_file_deps = {\n     'test_cycles.c': [],\n     'test_debug.c': [],\n     'test_devargs.c': ['kvargs'],\n+    'test_dispatcher.c': ['dispatcher'],\n     'test_distributor.c': ['distributor'],\n     'test_distributor_perf.c': ['distributor'],\n     'test_dmadev.c': ['dmadev', 'bus_vdev'],\ndiff --git a/app/test/test_dispatcher.c b/app/test/test_dispatcher.c\nnew file mode 100644\nindex 0000000000..b64103c48e\n--- /dev/null\n+++ b/app/test/test_dispatcher.c\n@@ -0,0 +1,1054 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Ericsson AB\n+ */\n+\n+#include \"test.h\"\n+\n+#include <stdatomic.h>\n+\n+#include <rte_bus_vdev.h>\n+#include <rte_dispatcher.h>\n+#include <rte_eventdev.h>\n+#include <rte_random.h>\n+#include <rte_service.h>\n+\n+#define NUM_WORKERS 3\n+\n+#define NUM_PORTS (NUM_WORKERS + 1)\n+#define WORKER_PORT_ID(worker_idx) (worker_idx)\n+#define DRIVER_PORT_ID (NUM_PORTS - 1)\n+\n+#define NUM_SERVICE_CORES NUM_WORKERS\n+\n+/* Eventdev */\n+#define NUM_QUEUES 8\n+#define LAST_QUEUE_ID (NUM_QUEUES - 1)\n+#define MAX_EVENTS 4096\n+#define NEW_EVENT_THRESHOLD (MAX_EVENTS / 2)\n+#define DEQUEUE_BURST_SIZE 32\n+#define ENQUEUE_BURST_SIZE 32\n+\n+#define NUM_EVENTS 10000000\n+#define NUM_FLOWS 16\n+\n+#define DSW_VDEV \"event_dsw0\"\n+\n+struct app_queue {\n+\tuint8_t queue_id;\n+\tuint64_t sn[NUM_FLOWS];\n+\tint dispatcher_reg_id;\n+};\n+\n+struct cb_count {\n+\tuint8_t expected_event_dev_id;\n+\tuint8_t expected_event_port_id[RTE_MAX_LCORE];\n+\tatomic_int count;\n+};\n+\n+struct test_app {\n+\tuint8_t event_dev_id;\n+\tuint8_t dispatcher_id;\n+\tuint32_t dispatcher_service_id;\n+\n+\tunsigned int service_lcores[NUM_SERVICE_CORES];\n+\n+\tint never_match_reg_id;\n+\tuint64_t never_match_count;\n+\tstruct cb_count never_process_count;\n+\n+\tstruct app_queue queues[NUM_QUEUES];\n+\n+\tint finalize_reg_id;\n+\tstruct cb_count finalize_count;\n+\n+\tbool running;\n+\n+\tatomic_int completed_events;\n+\tatomic_int errors;\n+};\n+\n+#define RETURN_ON_ERROR(rc) \\\n+\tdo {\t\t\t\t\t\\\n+\t\tif (rc != TEST_SUCCESS)\t\t\\\n+\t\t\treturn rc;\t\t\\\n+\t} while (0)\n+\n+static struct test_app *\n+test_app_create(void)\n+{\n+\tint i;\n+\tstruct test_app *app;\n+\n+\tapp = calloc(1, sizeof(struct test_app));\n+\n+\tif (app == NULL)\n+\t\treturn NULL;\n+\n+\tfor (i = 0; i < NUM_QUEUES; i++)\n+\t\tapp->queues[i].queue_id = i;\n+\n+\treturn app;\n+}\n+\n+static void\n+test_app_free(struct test_app *app)\n+{\n+\tfree(app);\n+}\n+\n+static int\n+test_app_create_vdev(struct test_app *app)\n+{\n+\tint rc;\n+\n+\trc = rte_vdev_init(DSW_VDEV, NULL);\n+\tif (rc < 0)\n+\t\treturn TEST_SKIPPED;\n+\n+\trc = rte_event_dev_get_dev_id(DSW_VDEV);\n+\n+\tapp->event_dev_id = (uint8_t)rc;\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_destroy_vdev(struct test_app *app)\n+{\n+\tint rc;\n+\n+\trc = rte_event_dev_close(app->event_dev_id);\n+\tTEST_ASSERT_SUCCESS(rc, \"Error while closing event device\");\n+\n+\trc = rte_vdev_uninit(DSW_VDEV);\n+\tTEST_ASSERT_SUCCESS(rc, \"Error while uninitializing virtual device\");\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_setup_event_dev(struct test_app *app)\n+{\n+\tint rc;\n+\tint i;\n+\n+\trc = test_app_create_vdev(app);\n+\tif (rc < 0)\n+\t\treturn rc;\n+\n+\tstruct rte_event_dev_config config = {\n+\t\t.nb_event_queues = NUM_QUEUES,\n+\t\t.nb_event_ports = NUM_PORTS,\n+\t\t.nb_events_limit = MAX_EVENTS,\n+\t\t.nb_event_queue_flows = 64,\n+\t\t.nb_event_port_dequeue_depth = DEQUEUE_BURST_SIZE,\n+\t\t.nb_event_port_enqueue_depth = ENQUEUE_BURST_SIZE\n+\t};\n+\n+\trc = rte_event_dev_configure(app->event_dev_id, &config);\n+\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to configure event device\");\n+\n+\tstruct rte_event_queue_conf queue_config = {\n+\t\t.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,\n+\t\t.schedule_type = RTE_SCHED_TYPE_ATOMIC,\n+\t\t.nb_atomic_flows = 64\n+\t};\n+\n+\tfor (i = 0; i < NUM_QUEUES; i++) {\n+\t\tuint8_t queue_id = i;\n+\n+\t\trc = rte_event_queue_setup(app->event_dev_id, queue_id,\n+\t\t\t\t\t   &queue_config);\n+\n+\t\tTEST_ASSERT_SUCCESS(rc, \"Unable to setup queue %d\", queue_id);\n+\t}\n+\n+\tstruct rte_event_port_conf port_config = {\n+\t\t.new_event_threshold = NEW_EVENT_THRESHOLD,\n+\t\t.dequeue_depth = DEQUEUE_BURST_SIZE,\n+\t\t.enqueue_depth = ENQUEUE_BURST_SIZE\n+\t};\n+\n+\tfor (i = 0; i < NUM_PORTS; i++) {\n+\t\tuint8_t event_port_id = i;\n+\n+\t\trc = rte_event_port_setup(app->event_dev_id, event_port_id,\n+\t\t\t\t\t  &port_config);\n+\t\tTEST_ASSERT_SUCCESS(rc, \"Failed to create event port %d\",\n+\t\t\t\t    event_port_id);\n+\n+\t\tif (event_port_id == DRIVER_PORT_ID)\n+\t\t\tcontinue;\n+\n+\t\trc = rte_event_port_link(app->event_dev_id, event_port_id,\n+\t\t\t\t\t NULL, NULL, 0);\n+\n+\t\tTEST_ASSERT_EQUAL(rc, NUM_QUEUES, \"Failed to link port %d\",\n+\t\t\t\t  event_port_id);\n+\t}\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_teardown_event_dev(struct test_app *app)\n+{\n+\treturn test_app_destroy_vdev(app);\n+}\n+\n+static int\n+test_app_start_event_dev(struct test_app *app)\n+{\n+\tint rc;\n+\n+\trc = rte_event_dev_start(app->event_dev_id);\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to start event device\");\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static void\n+test_app_stop_event_dev(struct test_app *app)\n+{\n+\trte_event_dev_stop(app->event_dev_id);\n+}\n+\n+static int\n+test_app_create_dispatcher(struct test_app *app)\n+{\n+\tint rc;\n+\n+\tapp->dispatcher_id = rte_rand_max(256);\n+\n+\trc = rte_dispatcher_create(app->dispatcher_id, app->event_dev_id);\n+\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to create event dispatcher\");\n+\n+\trc = rte_dispatcher_service_id_get(app->dispatcher_id,\n+\t\t\t\t\t   &app->dispatcher_service_id);\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to get event dispatcher service ID\");\n+\n+\trc = rte_service_set_stats_enable(app->dispatcher_service_id, 1);\n+\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to enable event dispatcher service \"\n+\t\t\t    \"stats\");\n+\n+\trc = rte_service_runstate_set(app->dispatcher_service_id, 1);\n+\tTEST_ASSERT_SUCCESS(rc, \"Error disabling dispatcher service\");\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_free_dispatcher(struct test_app *app)\n+{\n+\tint rc;\n+\n+\trc = rte_service_runstate_set(app->dispatcher_service_id, 0);\n+\tTEST_ASSERT_SUCCESS(rc, \"Error disabling dispatcher service\");\n+\n+\trte_dispatcher_free(app->dispatcher_id);\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_bind_ports(struct test_app *app)\n+{\n+\tint i;\n+\n+\tapp->never_process_count.expected_event_dev_id =\n+\t\tapp->event_dev_id;\n+\tapp->finalize_count.expected_event_dev_id =\n+\t\tapp->event_dev_id;\n+\n+\tfor (i = 0; i < NUM_WORKERS; i++) {\n+\t\tunsigned int lcore_id = app->service_lcores[i];\n+\t\tuint8_t port_id = WORKER_PORT_ID(i);\n+\n+\t\tint rc = rte_dispatcher_bind_port_to_lcore(\n+\t\t\tapp->dispatcher_id, port_id, DEQUEUE_BURST_SIZE, 0,\n+\t\t\tlcore_id\n+\t\t);\n+\n+\t\tTEST_ASSERT_SUCCESS(rc, \"Unable to bind event device port %d \"\n+\t\t\t\t    \"to lcore %d\", port_id, lcore_id);\n+\n+\t\tapp->never_process_count.expected_event_port_id[lcore_id] =\n+\t\t\tport_id;\n+\t\tapp->finalize_count.expected_event_port_id[lcore_id] = port_id;\n+\t}\n+\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_unbind_ports(struct test_app *app)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < NUM_WORKERS; i++) {\n+\t\tunsigned int lcore_id = app->service_lcores[i];\n+\n+\t\tint rc = rte_dispatcher_unbind_port_from_lcore(\n+\t\t\tapp->dispatcher_id,\n+\t\t\tWORKER_PORT_ID(i),\n+\t\t\tlcore_id\n+\t\t);\n+\n+\t\tTEST_ASSERT_SUCCESS(rc, \"Unable to unbind event device port %d \"\n+\t\t\t\t    \"from lcore %d\", WORKER_PORT_ID(i),\n+\t\t\t\t    lcore_id);\n+\t}\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static bool\n+match_queue(const struct rte_event *event, void *cb_data)\n+{\n+\tuintptr_t queue_id = (uintptr_t)cb_data;\n+\n+\treturn event->queue_id == queue_id;\n+}\n+\n+static int\n+test_app_get_worker_index(struct test_app *app, unsigned int lcore_id)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < NUM_SERVICE_CORES; i++)\n+\t\tif (app->service_lcores[i] == lcore_id)\n+\t\t\treturn i;\n+\n+\treturn -1;\n+}\n+\n+static int\n+test_app_get_worker_port(struct test_app *app, unsigned int lcore_id)\n+{\n+\tint worker;\n+\n+\tworker = test_app_get_worker_index(app, lcore_id);\n+\n+\tif (worker < 0)\n+\t\treturn -1;\n+\n+\treturn WORKER_PORT_ID(worker);\n+}\n+\n+static void\n+test_app_queue_note_error(struct test_app *app)\n+{\n+\tatomic_fetch_add_explicit(&app->errors, 1, memory_order_relaxed);\n+}\n+\n+static void\n+test_app_process_queue(uint8_t p_event_dev_id, uint8_t p_event_port_id,\n+\t\t       struct rte_event *in_events, uint16_t num,\n+\t\t       void *cb_data)\n+{\n+\tstruct app_queue *app_queue = cb_data;\n+\tstruct test_app *app = container_of(app_queue, struct test_app,\n+\t\t\t\t\t    queues[app_queue->queue_id]);\n+\tunsigned int lcore_id = rte_lcore_id();\n+\tbool intermediate_queue = app_queue->queue_id != LAST_QUEUE_ID;\n+\tint event_port_id;\n+\tuint16_t i;\n+\tstruct rte_event out_events[num];\n+\n+\tevent_port_id = test_app_get_worker_port(app, lcore_id);\n+\n+\tif (event_port_id < 0 || p_event_dev_id != app->event_dev_id ||\n+\t    p_event_port_id != event_port_id) {\n+\t\ttest_app_queue_note_error(app);\n+\t\treturn;\n+\t}\n+\n+\tfor (i = 0; i < num; i++) {\n+\t\tconst struct rte_event *in_event = &in_events[i];\n+\t\tstruct rte_event *out_event = &out_events[i];\n+\t\tuint64_t sn = in_event->u64;\n+\t\tuint64_t expected_sn;\n+\n+\t\tif (in_event->queue_id != app_queue->queue_id) {\n+\t\t\ttest_app_queue_note_error(app);\n+\t\t\treturn;\n+\t\t}\n+\n+\t\texpected_sn = app_queue->sn[in_event->flow_id]++;\n+\n+\t\tif (expected_sn != sn) {\n+\t\t\ttest_app_queue_note_error(app);\n+\t\t\treturn;\n+\t\t}\n+\n+\t\tif (intermediate_queue)\n+\t\t\t*out_event = (struct rte_event) {\n+\t\t\t\t.queue_id = in_event->queue_id + 1,\n+\t\t\t\t.flow_id = in_event->flow_id,\n+\t\t\t\t.sched_type = RTE_SCHED_TYPE_ATOMIC,\n+\t\t\t\t.op = RTE_EVENT_OP_FORWARD,\n+\t\t\t\t.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,\n+\t\t\t\t.u64 = sn\n+\t\t\t};\n+\t}\n+\n+\tif (intermediate_queue) {\n+\t\tuint16_t n = 0;\n+\n+\t\tdo {\n+\t\t\tn += rte_event_enqueue_forward_burst(p_event_dev_id,\n+\t\t\t\t\t\t\t     p_event_port_id,\n+\t\t\t\t\t\t\t     out_events + n,\n+\t\t\t\t\t\t\t     num - n);\n+\t\t} while (n != num);\n+\t} else\n+\t\tatomic_fetch_add_explicit(&app->completed_events, num,\n+\t\t\t\t\t  memory_order_relaxed);\n+}\n+\n+static bool\n+never_match(const struct rte_event *event __rte_unused, void *cb_data)\n+{\n+\tuint64_t *count = cb_data;\n+\n+\t(*count)++;\n+\n+\treturn false;\n+}\n+\n+static void\n+test_app_never_process(uint8_t event_dev_id,\n+\t\t       uint8_t event_port_id,\n+\t\t       struct rte_event *in_events __rte_unused,\n+\t\t       uint16_t num, void *cb_data)\n+{\n+\tstruct cb_count *count = cb_data;\n+\tunsigned int lcore_id = rte_lcore_id();\n+\n+\tif (event_dev_id == count->expected_event_dev_id &&\n+\t    event_port_id == count->expected_event_port_id[lcore_id])\n+\t\tatomic_fetch_add_explicit(&count->count, num,\n+\t\t\t\t\t  memory_order_relaxed);\n+}\n+\n+static void\n+finalize(uint8_t event_dev_id, uint8_t event_port_id, void *cb_data)\n+{\n+\tstruct cb_count *count = cb_data;\n+\tunsigned int lcore_id = rte_lcore_id();\n+\n+\tif (event_dev_id == count->expected_event_dev_id &&\n+\t    event_port_id == count->expected_event_port_id[lcore_id])\n+\t\tatomic_fetch_add_explicit(&count->count, 1,\n+\t\t\t\t\t  memory_order_relaxed);\n+}\n+\n+static int\n+test_app_register_callbacks(struct test_app *app)\n+{\n+\tint i;\n+\n+\tapp->never_match_reg_id =\n+\t\trte_dispatcher_register(app->dispatcher_id, never_match,\n+\t\t\t\t\t&app->never_match_count,\n+\t\t\t\t\ttest_app_never_process,\n+\t\t\t\t\t&app->never_process_count);\n+\n+\tTEST_ASSERT(app->never_match_reg_id >= 0, \"Unable to register \"\n+\t\t    \"never-match handler\");\n+\n+\tfor (i = 0; i < NUM_QUEUES; i++) {\n+\t\tstruct app_queue *app_queue = &app->queues[i];\n+\t\tuintptr_t queue_id = app_queue->queue_id;\n+\t\tint reg_id;\n+\n+\t\treg_id = rte_dispatcher_register(app->dispatcher_id,\n+\t\t\t\t\t\t match_queue, (void *)queue_id,\n+\t\t\t\t\t\t test_app_process_queue,\n+\t\t\t\t\t\t app_queue);\n+\n+\t\tTEST_ASSERT(reg_id >= 0, \"Unable to register consumer \"\n+\t\t\t    \"callback for queue %d\", i);\n+\n+\t\tapp_queue->dispatcher_reg_id = reg_id;\n+\t}\n+\n+\tapp->finalize_reg_id =\n+\t\trte_dispatcher_finalize_register(app->dispatcher_id,\n+\t\t\t\t\t\t       finalize,\n+\t\t\t\t\t\t       &app->finalize_count);\n+\tTEST_ASSERT_SUCCESS(app->finalize_reg_id, \"Error registering \"\n+\t\t\t    \"finalize callback\");\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_unregister_callback(struct test_app *app, uint8_t queue_id)\n+{\n+\tint reg_id = app->queues[queue_id].dispatcher_reg_id;\n+\tint rc;\n+\n+\tif (reg_id < 0) /* unregistered already */\n+\t\treturn 0;\n+\n+\trc = rte_dispatcher_unregister(app->dispatcher_id, reg_id);\n+\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to unregister consumer \"\n+\t\t\t    \"callback for queue %d\", queue_id);\n+\n+\tapp->queues[queue_id].dispatcher_reg_id = -1;\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_unregister_callbacks(struct test_app *app)\n+{\n+\tint i;\n+\tint rc;\n+\n+\tif (app->never_match_reg_id >= 0) {\n+\t\trc = rte_dispatcher_unregister(app->dispatcher_id,\n+\t\t\t\t\t\t     app->never_match_reg_id);\n+\n+\t\tTEST_ASSERT_SUCCESS(rc, \"Unable to unregister never-match \"\n+\t\t\t\t    \"handler\");\n+\t\tapp->never_match_reg_id = -1;\n+\t}\n+\n+\tfor (i = 0; i < NUM_QUEUES; i++) {\n+\t\trc = test_app_unregister_callback(app, i);\n+\t\tRETURN_ON_ERROR(rc);\n+\t}\n+\n+\tif (app->finalize_reg_id >= 0) {\n+\t\trc = rte_dispatcher_finalize_unregister(\n+\t\t\tapp->dispatcher_id, app->finalize_reg_id\n+\t\t);\n+\t\tapp->finalize_reg_id = -1;\n+\t}\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_start_dispatcher(struct test_app *app)\n+{\n+\tint rc;\n+\n+\trc = rte_dispatcher_start(app->dispatcher_id);\n+\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to start the event dispatcher\");\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_stop_dispatcher(struct test_app *app)\n+{\n+\tint rc;\n+\n+\trc = rte_dispatcher_stop(app->dispatcher_id);\n+\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to stop the event dispatcher\");\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_reset_dispatcher_stats(struct test_app *app)\n+{\n+\tint rc;\n+\tstruct rte_dispatcher_stats stats;\n+\n+\trc = rte_dispatcher_stats_reset(app->dispatcher_id);\n+\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to reset event dispatcher statistics\");\n+\n+\trc = rte_dispatcher_stats_get(app->dispatcher_id, &stats);\n+\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to retrieve event dispatcher \"\n+\t\t\t    \"statistics\");\n+\n+\tTEST_ASSERT_EQUAL(stats.poll_count, 0, \"Poll count not zero\");\n+\tTEST_ASSERT_EQUAL(stats.ev_batch_count, 0, \"Batch count not zero\");\n+\tTEST_ASSERT_EQUAL(stats.ev_dispatch_count, 0, \"Dispatch count \"\n+\t\t\t  \"not zero\");\n+\tTEST_ASSERT_EQUAL(stats.ev_drop_count, 0, \"Drop count not zero\");\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_setup_service_core(struct test_app *app, unsigned int lcore_id)\n+{\n+\tint rc;\n+\n+\trc = rte_service_lcore_add(lcore_id);\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to make lcore %d an event dispatcher \"\n+\t\t\t    \"service core\", lcore_id);\n+\n+\trc = rte_service_map_lcore_set(app->dispatcher_service_id, lcore_id, 1);\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to map event dispatcher service\");\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_setup_service_cores(struct test_app *app)\n+{\n+\tint i;\n+\tint lcore_id = -1;\n+\n+\tfor (i = 0; i < NUM_SERVICE_CORES; i++) {\n+\t\tlcore_id = rte_get_next_lcore(lcore_id, 1, 0);\n+\n+\t\tTEST_ASSERT(lcore_id != RTE_MAX_LCORE,\n+\t\t\t    \"Too few lcores. Needs at least %d worker lcores\",\n+\t\t\t    NUM_SERVICE_CORES);\n+\n+\t\tapp->service_lcores[i] = lcore_id;\n+\t}\n+\n+\tfor (i = 0; i < NUM_SERVICE_CORES; i++) {\n+\t\tint rc;\n+\n+\t\trc = test_app_setup_service_core(app, app->service_lcores[i]);\n+\n+\t\tRETURN_ON_ERROR(rc);\n+\t}\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_teardown_service_core(struct test_app *app, unsigned int lcore_id)\n+{\n+\tint rc;\n+\n+\trc = rte_service_map_lcore_set(app->dispatcher_service_id, lcore_id, 0);\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to unmap event dispatcher service\");\n+\n+\trc = rte_service_lcore_del(lcore_id);\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable change role of service lcore %d\",\n+\t\t\t    lcore_id);\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_teardown_service_cores(struct test_app *app)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < NUM_SERVICE_CORES; i++) {\n+\t\tunsigned int lcore_id = app->service_lcores[i];\n+\t\tint rc;\n+\n+\t\trc = test_app_teardown_service_core(app, lcore_id);\n+\n+\t\tRETURN_ON_ERROR(rc);\n+\t}\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_start_service_cores(struct test_app *app)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < NUM_SERVICE_CORES; i++) {\n+\t\tunsigned int lcore_id = app->service_lcores[i];\n+\t\tint rc;\n+\n+\t\trc = rte_service_lcore_start(lcore_id);\n+\t\tTEST_ASSERT_SUCCESS(rc, \"Unable to start service lcore %d\",\n+\t\t\t\t    lcore_id);\n+\n+\t\tRETURN_ON_ERROR(rc);\n+\t}\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_stop_service_cores(struct test_app *app)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < NUM_SERVICE_CORES; i++) {\n+\t\tunsigned int lcore_id = app->service_lcores[i];\n+\t\tint rc;\n+\n+\t\trc = rte_service_lcore_stop(lcore_id);\n+\t\tTEST_ASSERT_SUCCESS(rc, \"Unable to stop service lcore %d\",\n+\t\t\t\t    lcore_id);\n+\n+\t\tRETURN_ON_ERROR(rc);\n+\t}\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_start(struct test_app *app)\n+{\n+\tint rc;\n+\n+\trc = test_app_start_event_dev(app);\n+\tRETURN_ON_ERROR(rc);\n+\n+\trc = test_app_start_service_cores(app);\n+\tRETURN_ON_ERROR(rc);\n+\n+\trc = test_app_start_dispatcher(app);\n+\n+\tapp->running = true;\n+\n+\treturn rc;\n+}\n+\n+static int\n+test_app_stop(struct test_app *app)\n+{\n+\tint rc;\n+\n+\trc = test_app_stop_dispatcher(app);\n+\tRETURN_ON_ERROR(rc);\n+\n+\ttest_app_stop_service_cores(app);\n+\tRETURN_ON_ERROR(rc);\n+\n+\ttest_app_stop_event_dev(app);\n+\tRETURN_ON_ERROR(rc);\n+\n+\tapp->running = false;\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+struct test_app *test_app;\n+\n+static int\n+test_setup(void)\n+{\n+\tint rc;\n+\n+\ttest_app = test_app_create();\n+\tTEST_ASSERT(test_app != NULL, \"Unable to allocate memory\");\n+\n+\trc = test_app_setup_event_dev(test_app);\n+\tRETURN_ON_ERROR(rc);\n+\n+\trc = test_app_create_dispatcher(test_app);\n+\n+\trc = test_app_setup_service_cores(test_app);\n+\tRETURN_ON_ERROR(rc);\n+\n+\trc = test_app_register_callbacks(test_app);\n+\tRETURN_ON_ERROR(rc);\n+\n+\trc = test_app_bind_ports(test_app);\n+\n+\treturn rc;\n+}\n+\n+static void test_teardown(void)\n+{\n+\tif (test_app->running)\n+\t\ttest_app_stop(test_app);\n+\n+\ttest_app_teardown_service_cores(test_app);\n+\n+\ttest_app_unregister_callbacks(test_app);\n+\n+\ttest_app_unbind_ports(test_app);\n+\n+\ttest_app_free_dispatcher(test_app);\n+\n+\ttest_app_teardown_event_dev(test_app);\n+\n+\ttest_app_free(test_app);\n+\n+\ttest_app = NULL;\n+}\n+\n+static int\n+test_app_get_completed_events(struct test_app *app)\n+{\n+\treturn atomic_load_explicit(&app->completed_events,\n+\t\t\t\t    memory_order_relaxed);\n+}\n+\n+static int\n+test_app_get_errors(struct test_app *app)\n+{\n+\treturn atomic_load_explicit(&app->errors, memory_order_relaxed);\n+}\n+\n+static int\n+test_basic(void)\n+{\n+\tint rc;\n+\tint i;\n+\n+\trc = test_app_start(test_app);\n+\tRETURN_ON_ERROR(rc);\n+\n+\tuint64_t sns[NUM_FLOWS] = { 0 };\n+\n+\tfor (i = 0; i < NUM_EVENTS;) {\n+\t\tstruct rte_event events[ENQUEUE_BURST_SIZE];\n+\t\tint left;\n+\t\tint batch_size;\n+\t\tint j;\n+\t\tuint16_t n = 0;\n+\n+\t\tbatch_size = 1 + rte_rand_max(ENQUEUE_BURST_SIZE);\n+\t\tleft = NUM_EVENTS - i;\n+\n+\t\tbatch_size = RTE_MIN(left, batch_size);\n+\n+\t\tfor (j = 0; j < batch_size; j++) {\n+\t\t\tstruct rte_event *event = &events[j];\n+\t\t\tuint64_t sn;\n+\t\t\tuint32_t flow_id;\n+\n+\t\t\tflow_id = rte_rand_max(NUM_FLOWS);\n+\n+\t\t\tsn = sns[flow_id]++;\n+\n+\t\t\t*event = (struct rte_event) {\n+\t\t\t\t.queue_id = 0,\n+\t\t\t\t.flow_id = flow_id,\n+\t\t\t\t.sched_type = RTE_SCHED_TYPE_ATOMIC,\n+\t\t\t\t.op = RTE_EVENT_OP_NEW,\n+\t\t\t\t.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,\n+\t\t\t\t.u64 = sn\n+\t\t\t};\n+\t\t}\n+\n+\t\twhile (n < batch_size)\n+\t\t\tn += rte_event_enqueue_new_burst(test_app->event_dev_id,\n+\t\t\t\t\t\t\t DRIVER_PORT_ID,\n+\t\t\t\t\t\t\t events + n,\n+\t\t\t\t\t\t\t batch_size - n);\n+\n+\t\ti += batch_size;\n+\t}\n+\n+\twhile (test_app_get_completed_events(test_app) != NUM_EVENTS)\n+\t\trte_event_maintain(test_app->event_dev_id, DRIVER_PORT_ID, 0);\n+\n+\trc = test_app_get_errors(test_app);\n+\tTEST_ASSERT(rc == 0, \"%d errors occurred\", rc);\n+\n+\trc = test_app_stop(test_app);\n+\tRETURN_ON_ERROR(rc);\n+\n+\tstruct rte_dispatcher_stats stats;\n+\trc = rte_dispatcher_stats_get(test_app->dispatcher_id,\n+\t\t\t\t\t    &stats);\n+\n+\tTEST_ASSERT_EQUAL(stats.ev_drop_count, 0, \"Drop count is not zero\");\n+\tTEST_ASSERT_EQUAL(stats.ev_dispatch_count, NUM_EVENTS * NUM_QUEUES,\n+\t\t\t  \"Invalid dispatch count\");\n+\tTEST_ASSERT(stats.poll_count > 0, \"Poll count is zero\");\n+\n+\tTEST_ASSERT_EQUAL(test_app->never_process_count.count, 0,\n+\t\t\t  \"Never-match handler's process function has \"\n+\t\t\t  \"been called\");\n+\n+\tint finalize_count =\n+\t\tatomic_load_explicit(&test_app->finalize_count.count,\n+\t\t\t\t     memory_order_relaxed);\n+\n+\tTEST_ASSERT(finalize_count > 0, \"Finalize count is zero\");\n+\tTEST_ASSERT(finalize_count <= (int)stats.ev_dispatch_count,\n+\t\t    \"Finalize count larger than event count\");\n+\n+\tTEST_ASSERT_EQUAL(finalize_count, (int)stats.ev_batch_count,\n+\t\t\t  \"%\"PRIu64\" batches dequeued, but finalize called %d \"\n+\t\t\t  \"times\", stats.ev_batch_count, finalize_count);\n+\n+\t/*\n+\t * The event dispatcher should call often-matching match functions\n+\t * more often, and thus this never-matching match function should\n+\t * be called relatively infrequently.\n+\t */\n+\tTEST_ASSERT(test_app->never_match_count <\n+\t\t    (stats.ev_dispatch_count / 4),\n+\t\t    \"Never-matching match function called suspiciously often\");\n+\n+\trc = test_app_reset_dispatcher_stats(test_app);\n+\tRETURN_ON_ERROR(rc);\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_drop(void)\n+{\n+\tint rc;\n+\tuint8_t unhandled_queue;\n+\tstruct rte_dispatcher_stats stats;\n+\n+\tunhandled_queue = (uint8_t)rte_rand_max(NUM_QUEUES);\n+\n+\trc = test_app_start(test_app);\n+\tRETURN_ON_ERROR(rc);\n+\n+\trc = test_app_unregister_callback(test_app, unhandled_queue);\n+\tRETURN_ON_ERROR(rc);\n+\n+\tstruct rte_event event = {\n+\t    .queue_id = unhandled_queue,\n+\t    .flow_id = 0,\n+\t    .sched_type = RTE_SCHED_TYPE_ATOMIC,\n+\t    .op = RTE_EVENT_OP_NEW,\n+\t    .priority = RTE_EVENT_DEV_PRIORITY_NORMAL,\n+\t    .u64 = 0\n+\t};\n+\n+\tdo {\n+\t\trc = rte_event_enqueue_burst(test_app->event_dev_id,\n+\t\t\t\t\t     DRIVER_PORT_ID, &event, 1);\n+\t} while (rc == 0);\n+\n+\tdo {\n+\t\trc = rte_dispatcher_stats_get(test_app->dispatcher_id,\n+\t\t\t\t\t\t    &stats);\n+\t\tRETURN_ON_ERROR(rc);\n+\n+\t\trte_event_maintain(test_app->event_dev_id, DRIVER_PORT_ID, 0);\n+\t} while (stats.ev_drop_count == 0 && stats.ev_dispatch_count == 0);\n+\n+\trc = test_app_stop(test_app);\n+\tRETURN_ON_ERROR(rc);\n+\n+\tTEST_ASSERT_EQUAL(stats.ev_drop_count, 1, \"Drop count is not one\");\n+\tTEST_ASSERT_EQUAL(stats.ev_dispatch_count, 0,\n+\t\t\t  \"Dispatch count is not zero\");\n+\tTEST_ASSERT(stats.poll_count > 0, \"Poll count is zero\");\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+#define MORE_THAN_MAX_HANDLERS 1000\n+#define MIN_HANDLERS 32\n+\n+static int\n+test_many_handler_registrations(void)\n+{\n+\tint rc;\n+\tint num_regs = 0;\n+\tint reg_ids[MORE_THAN_MAX_HANDLERS];\n+\tint reg_id;\n+\tint i;\n+\n+\trc = test_app_unregister_callbacks(test_app);\n+\n+\tRETURN_ON_ERROR(rc);\n+\n+\tfor (i = 0; i < MORE_THAN_MAX_HANDLERS; i++) {\n+\t\treg_id = rte_dispatcher_register(test_app->dispatcher_id,\n+\t\t\t\t\t\t       never_match, NULL,\n+\t\t\t\t\t\t       test_app_never_process,\n+\t\t\t\t\t\t       NULL);\n+\t\tif (reg_id < 0)\n+\t\t\tbreak;\n+\n+\t\treg_ids[num_regs++] = reg_id;\n+\t}\n+\n+\tTEST_ASSERT_EQUAL(reg_id, -ENOMEM, \"Incorrect return code. Expected \"\n+\t\t\t  \"%d but was %d\", -ENOMEM, reg_id);\n+\tTEST_ASSERT(num_regs >= MIN_HANDLERS, \"Registration failed already \"\n+\t\t    \"after %d handler registrations.\", num_regs);\n+\n+\tfor (i = 0; i < num_regs; i++) {\n+\t\trc = rte_dispatcher_unregister(test_app->dispatcher_id,\n+\t\t\t\t\t\t     reg_ids[i]);\n+\t\tTEST_ASSERT_SUCCESS(rc, \"Unable to unregister handler %d\",\n+\t\t\t\t    reg_ids[i]);\n+\t}\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static void\n+dummy_finalize(uint8_t event_dev_id __rte_unused,\n+\t       uint8_t event_port_id __rte_unused,\n+\t       void *cb_data __rte_unused)\n+{\n+}\n+\n+#define MORE_THAN_MAX_FINALIZERS 1000\n+#define MIN_FINALIZERS 16\n+\n+static int\n+test_many_finalize_registrations(void)\n+{\n+\tint rc;\n+\tint num_regs = 0;\n+\tint reg_ids[MORE_THAN_MAX_FINALIZERS];\n+\tint reg_id;\n+\tint i;\n+\n+\trc = test_app_unregister_callbacks(test_app);\n+\n+\tRETURN_ON_ERROR(rc);\n+\n+\tfor (i = 0; i < MORE_THAN_MAX_FINALIZERS; i++) {\n+\t\treg_id = rte_dispatcher_finalize_register(\n+\t\t\ttest_app->dispatcher_id, dummy_finalize, NULL\n+\t\t);\n+\n+\t\tif (reg_id < 0)\n+\t\t\tbreak;\n+\n+\t\treg_ids[num_regs++] = reg_id;\n+\t}\n+\n+\tTEST_ASSERT_EQUAL(reg_id, -ENOMEM, \"Incorrect return code. Expected \"\n+\t\t\t  \"%d but was %d\", -ENOMEM, reg_id);\n+\tTEST_ASSERT(num_regs >= MIN_FINALIZERS, \"Finalize registration failed \"\n+\t\t    \"already after %d registrations.\", num_regs);\n+\n+\tfor (i = 0; i < num_regs; i++) {\n+\t\trc = rte_dispatcher_finalize_unregister(\n+\t\t\ttest_app->dispatcher_id, reg_ids[i]\n+\t\t);\n+\t\tTEST_ASSERT_SUCCESS(rc, \"Unable to unregister finalizer %d\",\n+\t\t\t\t    reg_ids[i]);\n+\t}\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static struct unit_test_suite test_suite = {\n+\t.suite_name = \"Event dispatcher test suite\",\n+\t.unit_test_cases = {\n+\t\tTEST_CASE_ST(test_setup, test_teardown, test_basic),\n+\t\tTEST_CASE_ST(test_setup, test_teardown, test_drop),\n+\t\tTEST_CASE_ST(test_setup, test_teardown,\n+\t\t\t     test_many_handler_registrations),\n+\t\tTEST_CASE_ST(test_setup, test_teardown,\n+\t\t\t     test_many_finalize_registrations),\n+\t\tTEST_CASES_END()\n+\t}\n+};\n+\n+static int\n+test_dispatcher(void)\n+{\n+\treturn unit_test_suite_runner(&test_suite);\n+}\n+\n+REGISTER_TEST_COMMAND(dispatcher_autotest, test_dispatcher);\n",
    "prefixes": [
        "v3",
        "2/3"
    ]
}