get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 132574,
    "url": "http://patchwork.dpdk.org/api/patches/132574/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20231012085031.444483-3-mattias.ronnblom@ericsson.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.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": "<20231012085031.444483-3-mattias.ronnblom@ericsson.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20231012085031.444483-3-mattias.ronnblom@ericsson.com",
    "date": "2023-10-12T08:50:30",
    "name": "[v8,2/3] test: add dispatcher test suite",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "03a04dac224c8cf0c76bcea4545bffb28334e5e8",
    "submitter": {
        "id": 1077,
        "url": "http://patchwork.dpdk.org/api/people/1077/?format=api",
        "name": "Mattias Rönnblom",
        "email": "mattias.ronnblom@ericsson.com"
    },
    "delegate": {
        "id": 24651,
        "url": "http://patchwork.dpdk.org/api/users/24651/?format=api",
        "username": "dmarchand",
        "first_name": "David",
        "last_name": "Marchand",
        "email": "david.marchand@redhat.com"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20231012085031.444483-3-mattias.ronnblom@ericsson.com/mbox/",
    "series": [
        {
            "id": 29824,
            "url": "http://patchwork.dpdk.org/api/series/29824/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=29824",
            "date": "2023-10-12T08:50:28",
            "name": "Add dispatcher library",
            "version": 8,
            "mbox": "http://patchwork.dpdk.org/series/29824/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/132574/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/132574/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 A982242364;\n\tThu, 12 Oct 2023 10:56:00 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 4837F402DE;\n\tThu, 12 Oct 2023 10:55:57 +0200 (CEST)",
            "from EUR04-VI1-obe.outbound.protection.outlook.com\n (mail-vi1eur04on2084.outbound.protection.outlook.com [40.107.8.84])\n by mails.dpdk.org (Postfix) with ESMTP id B5F974028C;\n Thu, 12 Oct 2023 10:55:53 +0200 (CEST)",
            "from DU6P191CA0025.EURP191.PROD.OUTLOOK.COM (2603:10a6:10:53f::25)\n by AS4PR07MB8659.eurprd07.prod.outlook.com (2603:10a6:20b:4ce::20) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6863.45; Thu, 12 Oct\n 2023 08:55:51 +0000",
            "from DB1PEPF0003922E.eurprd03.prod.outlook.com\n (2603:10a6:10:53f:cafe::8c) by DU6P191CA0025.outlook.office365.com\n (2603:10a6:10:53f::25) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6886.29 via Frontend\n Transport; Thu, 12 Oct 2023 08:55:51 +0000",
            "from oa.msg.ericsson.com (192.176.1.74) by\n DB1PEPF0003922E.mail.protection.outlook.com (10.167.8.101) with Microsoft\n SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id\n 15.20.6838.22 via Frontend Transport; Thu, 12 Oct 2023 08:55:51 +0000",
            "from ESESBMB501.ericsson.se (153.88.183.168) by\n ESESSMB505.ericsson.se (153.88.183.166) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id\n 15.1.2507.32; Thu, 12 Oct 2023 10:55:50 +0200",
            "from seliicinfr00049.seli.gic.ericsson.se (153.88.183.153) by\n smtp.internal.ericsson.com (153.88.183.184) with Microsoft SMTP Server id\n 15.1.2507.32 via Frontend Transport; Thu, 12 Oct 2023 10:55:50 +0200",
            "from breslau.. (seliicwb00002.seli.gic.ericsson.se [10.156.25.100])\n by seliicinfr00049.seli.gic.ericsson.se (Postfix) with ESMTP id\n 84A75380061; Thu, 12 Oct 2023 10:55:50 +0200 (CEST)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=WsRxqrwfo0Y2CPOqtvwvk057vvFIQ/tEtek0LvpTAq/yU2l5qqri0D016GXkas98RULjXG1k6uJDgq11zqNN0Z1CI+gxsOXLuzoPFTP/K/Tt4qkFjcR/q8beFPdpfDI7rLK4RqC0Z71B09tXwuwpvhL1/SfdbgN3RTxZmqSQ9eODiJdAWQ36j5WxM01G09aikuQ+rIji3CHtD08h5mUSqKa+C96pSQ5kYYgahw75VosqWeXmbkzilRSBCdJyRQyW6BMoskjyK105q1+QlpjoLZwKBojLI+6llbVM40+7CzU+wKRIqS4fr7XxH7e9gQPU/fMjcn4hNIcBOSsCUE5gEQ==",
        "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=5chxlDqIYH1NWjJUpUHx5BiXZuA66FDsGVyNctquCFU=;\n b=c/d5jXIvyC4VsJF6+Cna4pwpuLp+M3VRPCvJuMNebwWl15lrda+M+E7n3C5P8KS4ZMNkmobdxGx/FlvRaph09XW8fJP8ZuKX26cP5f1Kn1Uxh2QnZd2G3eaHblMj5XpPBm1HXps1Ml4HU7/Q5xjmqyWD90E0iFF4WrX7/OPXA7JHGnPtXLuz0tlnY4hSu5yckh/U3KjEECXeOV4Ta+k4r7Vwd/vsWdwjGhT/8a9taikVLpoeX8LWPMH1DBKQ07Kda5kEE9LQak6sGpI7cc0f+WHiT1OqpC0ByQaL6ISonspq99m4CCN8s4pfUuZ10KY1dkU8UxHvI8/Inz37tzwJ0Q==",
        "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=5chxlDqIYH1NWjJUpUHx5BiXZuA66FDsGVyNctquCFU=;\n b=TuKMlgYY7lMDzuQRrZnDguVyCzd/R6KBWIC+E7iVNP68yMVpWbn5OwMND6P43yqq8hAZxJN3/nMVYUQNYZKA66cfnbkEGh+nM45V8MVecaQcQQwGDuJdlGEYcg4+Od0uyNv7cb1fgVvfRRa8g80KmpNRdd0pOk7uHputmq6/4V4=",
        "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>, <david.marchand@redhat.com>",
        "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 v8 2/3] test: add dispatcher test suite",
        "Date": "Thu, 12 Oct 2023 10:50:30 +0200",
        "Message-ID": "<20231012085031.444483-3-mattias.ronnblom@ericsson.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20231012085031.444483-1-mattias.ronnblom@ericsson.com>",
        "References": "<20231011071700.442795-2-mattias.ronnblom@ericsson.com>\n <20231012085031.444483-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": "DB1PEPF0003922E:EE_|AS4PR07MB8659:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "2f563cbe-084e-4c79-949e-08dbcb01093c",
        "X-LD-Processed": "92e84ceb-fbfd-47ab-be52-080c6b87953f,ExtAddr",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n 69dE1MtRuuWpQIWII2oDuga3hnGGl/Gwob33EZrC/hBlgq+kb7ugbv3IeJDT6V+34lkg1FItJUBmoU6P4YLBE3uADoW77PTKXP7ZWOiByDpCSVWExewDx+aOEUPuTSJTtGgwf4Cnz/Ghqu5ejyuW/uQ62N2VuZPJjqVqJ0Y1H2U2glqwDUaykYbzUKY7ps+zGKpHWQ8pbhilZmctBePJ9N5fgvpT4CkNALfoLEGHUKRbshi1lG8pxD/srU1Sm+WIdE4WADQbVp8NtaCBTjl00l3eej5MJZd9r7Id7CodI42+wfi9fynkzy+/vf+6bgNQUszJ96SFNLxuChkJt786SMo5s5/EhYb3MLRDkx7S1CbgEp5SrGk4FQ0BDEuumsRweZFilhoNNKwJUFIqNp1gYYlhDyH/PmSJK0BrpVvaYkZziFia/r9tondHIas3Gw35NWRsfT4HLvkLdwD8dWCiqOwIR5Vj+Tz62rkrhgFrup7gwJ6l1wsHBtnWcck52MgqJAyC8jabTn/0FXSD7Wsxs2MeLpUVnx/u2j03fLox7qi3Pnm8vnkhuJRgkrU0Kh3AP+gXXqPozHsyRTosJjxoefi8wtnmmVYFkHsJnyiOaCz7nVZ+BNPaxmIITyRGsBjdECsw4y8NeGqMJf+UxgZPO0huHNDOe/XsDwRfHIM3Q46m+u2i0ysUK/+5KNvcc8vSwafWSGuJRLRe8X/p85EgmO2XRsQrhG3noncoLLllFLHpFnnh3UWP2yOs3oEaPRcfaMNDde+yN8OZDuZFCez0dipBw0fSaWdHbb3B0nBu6OsrAOMNwszLl/1M18IlZTmm7nK4YeQFpuBRIGCwVSxfey6VvFLG0AdvC4OvAktY3jo=",
        "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)(346002)(39860400002)(136003)(396003)(376002)(230922051799003)(1800799009)(64100799003)(451199024)(186009)(82310400011)(46966006)(40470700004)(36840700001)(47076005)(36860700001)(478600001)(83380400001)(40460700003)(26005)(7636003)(2616005)(66574015)(6266002)(336012)(40480700001)(7416002)(86362001)(30864003)(2906002)(41300700001)(5660300002)(8676002)(4326008)(8936002)(6666004)(316002)(54906003)(110136005)(70586007)(70206006)(36756003)(356005)(107886003)(82740400003)(1076003)(82960400001)(2101003);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "ericsson.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "12 Oct 2023 08:55:51.2490 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 2f563cbe-084e-4c79-949e-08dbcb01093c",
        "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 DB1PEPF0003922E.eurprd03.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "AS4PR07MB8659",
        "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--\n\nPATCH v8:\n o Adjust test code to match the fact that the dispatcher start and\n   stop functions no longer return a value.\n\nPATCH v7:\n o Skip (not fail) tests in case too few lcores are available or if\n   the DSW event device is not available. (David Marchand)\n o Properly clean up resources in the above-mentioned scenarios.\n\nPATCH v6:\n o Register test as \"fast\". (David Marchand)\n o Use single tab as indentation for continuation lines in multiple-line\n   function prototypes. (David Marchand)\n o Add Signed-off-by line. (David Marchand)\n o Use DPDK atomics wrapper API instead of C11 atomics.\n\nPATCH v5:\n o Update test suite to use pointer and not integer id when calling\n   dispatcher functions.\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 | 1056 ++++++++++++++++++++++++++++++++++++\n 3 files changed, 1058 insertions(+)\n create mode 100644 app/test/test_dispatcher.c",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex a7039b06dc..0e24da11fe 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -1737,6 +1737,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 \n Test Applications\ndiff --git a/app/test/meson.build b/app/test/meson.build\nindex 20a9333c72..c238f4b21c 100644\n--- a/app/test/meson.build\n+++ b/app/test/meson.build\n@@ -59,6 +59,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..6eb3f572cf\n--- /dev/null\n+++ b/app/test/test_dispatcher.c\n@@ -0,0 +1,1056 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Ericsson AB\n+ */\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+#include <rte_stdatomic.h>\n+\n+#include \"test.h\"\n+\n+#define NUM_WORKERS 3\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+#define MIN_LCORES (NUM_SERVICE_CORES + 1)\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+\tRTE_ATOMIC(int) count;\n+};\n+\n+struct test_app {\n+\tuint8_t event_dev_id;\n+\tstruct rte_dispatcher *dispatcher;\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+\tRTE_ATOMIC(int) completed_events;\n+\tRTE_ATOMIC(int) errors;\n+};\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 != TEST_SUCCESS)\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 = rte_dispatcher_create(app->event_dev_id);\n+\n+\tTEST_ASSERT(app->dispatcher != NULL, \"Unable to create event \"\n+\t\t    \"dispatcher\");\n+\n+\tapp->dispatcher_service_id =\n+\t\trte_dispatcher_service_id_get(app->dispatcher);\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+\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to set dispatcher service runstate\");\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+\trc = rte_dispatcher_free(app->dispatcher);\n+\tTEST_ASSERT_SUCCESS(rc, \"Error freeing dispatcher\");\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, 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,\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+\trte_atomic_fetch_add_explicit(&app->errors, 1, rte_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+\tstruct rte_event *in_events, uint16_t num,\n+\tvoid *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\trte_atomic_fetch_add_explicit(&app->completed_events, num,\n+\t\t\t\t\t      rte_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, uint8_t event_port_id,\n+\tstruct rte_event *in_events __rte_unused, 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\trte_atomic_fetch_add_explicit(&count->count, num,\n+\t\t\t\t\t      rte_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\trte_atomic_fetch_add_explicit(&count->count, 1,\n+\t\t\t\t\t      rte_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, 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,\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,\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, 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,\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\tif (rc != TEST_SUCCESS)\n+\t\t\treturn rc;\n+\t}\n+\n+\tif (app->finalize_reg_id >= 0) {\n+\t\trc = rte_dispatcher_finalize_unregister(\n+\t\t\tapp->dispatcher, 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 void\n+test_app_start_dispatcher(struct test_app *app)\n+{\n+\trte_dispatcher_start(app->dispatcher);\n+}\n+\n+static void\n+test_app_stop_dispatcher(struct test_app *app)\n+{\n+\trte_dispatcher_stop(app->dispatcher);\n+}\n+\n+static int\n+test_app_reset_dispatcher_stats(struct test_app *app)\n+{\n+\tstruct rte_dispatcher_stats stats;\n+\n+\trte_dispatcher_stats_reset(app->dispatcher);\n+\n+\tmemset(&stats, 0xff, sizeof(stats));\n+\n+\trte_dispatcher_stats_get(app->dispatcher, &stats);\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\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+\t\tif (rc != TEST_SUCCESS)\n+\t\t\treturn 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+\t\tif (rc != TEST_SUCCESS)\n+\t\t\treturn 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+\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+\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+\tif (rc != TEST_SUCCESS)\n+\t\treturn rc;\n+\n+\trc = test_app_start_service_cores(app);\n+\tif (rc != TEST_SUCCESS)\n+\t\treturn rc;\n+\n+\ttest_app_start_dispatcher(app);\n+\n+\tapp->running = true;\n+\n+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_app_stop(struct test_app *app)\n+{\n+\tint rc;\n+\n+\ttest_app_stop_dispatcher(app);\n+\n+\trc = test_app_stop_service_cores(app);\n+\tif (rc != TEST_SUCCESS)\n+\t\treturn rc;\n+\n+\ttest_app_stop_event_dev(app);\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+\tif (rte_lcore_count() < MIN_LCORES) {\n+\t\tprintf(\"Not enough cores for dispatcher_autotest; expecting at \"\n+\t\t       \"least %d.\\n\", MIN_LCORES);\n+\t\treturn TEST_SKIPPED;\n+\t}\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+\tif (rc != TEST_SUCCESS)\n+\t\tgoto err_free_app;\n+\n+\trc = test_app_create_dispatcher(test_app);\n+\tif (rc != TEST_SUCCESS)\n+\t\tgoto err_teardown_event_dev;\n+\n+\trc = test_app_setup_service_cores(test_app);\n+\tif (rc != TEST_SUCCESS)\n+\t\tgoto err_free_dispatcher;\n+\n+\trc = test_app_register_callbacks(test_app);\n+\tif (rc != TEST_SUCCESS)\n+\t\tgoto err_teardown_service_cores;\n+\n+\trc = test_app_bind_ports(test_app);\n+\tif (rc != TEST_SUCCESS)\n+\t\tgoto err_unregister_callbacks;\n+\n+\treturn TEST_SUCCESS;\n+\n+err_unregister_callbacks:\n+\ttest_app_unregister_callbacks(test_app);\n+err_teardown_service_cores:\n+\ttest_app_teardown_service_cores(test_app);\n+err_free_dispatcher:\n+\ttest_app_free_dispatcher(test_app);\n+err_teardown_event_dev:\n+\ttest_app_teardown_event_dev(test_app);\n+err_free_app:\n+\ttest_app_free(test_app);\n+\n+\ttest_app = NULL;\n+\n+\treturn rc;\n+}\n+\n+static void test_teardown(void)\n+{\n+\tif (test_app == NULL)\n+\t\treturn;\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 rte_atomic_load_explicit(&app->completed_events,\n+\t\t\t\t\trte_memory_order_relaxed);\n+}\n+\n+static int\n+test_app_get_errors(struct test_app *app)\n+{\n+\treturn rte_atomic_load_explicit(&app->errors, rte_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+\tif (rc != TEST_SUCCESS)\n+\t\treturn 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+\tif (rc != TEST_SUCCESS)\n+\t\treturn rc;\n+\n+\tstruct rte_dispatcher_stats stats;\n+\trte_dispatcher_stats_get(test_app->dispatcher, &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\trte_atomic_load_explicit(&test_app->finalize_count.count,\n+\t\t\t\t\t rte_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+\tif (rc != TEST_SUCCESS)\n+\t\treturn 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+\tif (rc != TEST_SUCCESS)\n+\t\treturn rc;\n+\n+\trc = test_app_unregister_callback(test_app, unhandled_queue);\n+\tif (rc != TEST_SUCCESS)\n+\t\treturn 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\trte_dispatcher_stats_get(test_app->dispatcher, &stats);\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+\tif (rc != TEST_SUCCESS)\n+\t\treturn 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+\tif (rc != TEST_SUCCESS)\n+\t\treturn rc;\n+\n+\tfor (i = 0; i < MORE_THAN_MAX_HANDLERS; i++) {\n+\t\treg_id = rte_dispatcher_register(test_app->dispatcher,\n+\t\t\t\t\t\t never_match, NULL,\n+\t\t\t\t\t\t test_app_never_process, 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,\n+\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+\tif (rc != TEST_SUCCESS)\n+\t\treturn 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, 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, 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_FAST_TEST(dispatcher_autotest, false, true, test_dispatcher);\n",
    "prefixes": [
        "v8",
        "2/3"
    ]
}