get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 132501,
    "url": "http://patches.dpdk.org/api/patches/132501/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20231011071700.442795-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": "<20231011071700.442795-3-mattias.ronnblom@ericsson.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20231011071700.442795-3-mattias.ronnblom@ericsson.com",
    "date": "2023-10-11T07:16:59",
    "name": "[v7,2/3] test: add dispatcher test suite",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "43b554ec23a7ea498529711ff649bc3f1f9e1653",
    "submitter": {
        "id": 1077,
        "url": "http://patches.dpdk.org/api/people/1077/?format=api",
        "name": "Mattias Rönnblom",
        "email": "mattias.ronnblom@ericsson.com"
    },
    "delegate": {
        "id": 24651,
        "url": "http://patches.dpdk.org/api/users/24651/?format=api",
        "username": "dmarchand",
        "first_name": "David",
        "last_name": "Marchand",
        "email": "david.marchand@redhat.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20231011071700.442795-3-mattias.ronnblom@ericsson.com/mbox/",
    "series": [
        {
            "id": 29812,
            "url": "http://patches.dpdk.org/api/series/29812/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=29812",
            "date": "2023-10-11T07:16:57",
            "name": "Add dispatcher library",
            "version": 7,
            "mbox": "http://patches.dpdk.org/series/29812/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/132501/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/132501/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 EC3994235C;\n\tWed, 11 Oct 2023 09:22:47 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id E99E440A71;\n\tWed, 11 Oct 2023 09:22:28 +0200 (CEST)",
            "from EUR02-VI1-obe.outbound.protection.outlook.com\n (mail-vi1eur02on2061.outbound.protection.outlook.com [40.107.241.61])\n by mails.dpdk.org (Postfix) with ESMTP id D829140647;\n Wed, 11 Oct 2023 09:22:24 +0200 (CEST)",
            "from DUZPR01CA0212.eurprd01.prod.exchangelabs.com\n (2603:10a6:10:4b4::18) by DU2PR07MB8152.eurprd07.prod.outlook.com\n (2603:10a6:10:275::7) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6863.38; Wed, 11 Oct\n 2023 07:22:21 +0000",
            "from DB5PEPF00014B8D.eurprd02.prod.outlook.com\n (2603:10a6:10:4b4:cafe::8d) by DUZPR01CA0212.outlook.office365.com\n (2603:10a6:10:4b4::18) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6863.38 via Frontend\n Transport; Wed, 11 Oct 2023 07:22:21 +0000",
            "from oa.msg.ericsson.com (192.176.1.74) by\n DB5PEPF00014B8D.mail.protection.outlook.com (10.167.8.201) 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; Wed, 11 Oct 2023 07:22:21 +0000",
            "from SESSMB602.ericsson.se (100.87.178.24) by ESESBMB502.ericsson.se\n (153.88.183.57) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.32; Wed, 11\n Oct 2023 09:22:21 +0200",
            "from ESESSMB502.ericsson.se (153.88.183.39) by SESSMB602.ericsson.se\n (100.87.178.24) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.2.1118.26; Wed, 11 Oct\n 2023 09:22:20 +0200",
            "from seliicinfr00050.seli.gic.ericsson.se (153.88.183.153) by\n smtp.internal.ericsson.com (153.88.183.190) with Microsoft SMTP Server id\n 15.1.2507.32 via Frontend Transport; Wed, 11 Oct 2023 09:22:20 +0200",
            "from breslau.. (seliicwb00002.seli.gic.ericsson.se [10.156.25.100])\n by seliicinfr00050.seli.gic.ericsson.se (Postfix) with ESMTP id\n 9F69F1C006A; Wed, 11 Oct 2023 09:22:20 +0200 (CEST)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=JaxtYP21cg5uFRHospdOySY51gtzcU+1TX9uD/ImmddVYaP73IjLWvFBlMWAcROshMv99KlQnjnVqpwEcVHx+qAEJaR3tmp0uf+U8BkYgAJl7QQcCvQt9kXz+mJSnkjCmAeGALPA8qyOA94UL1tpSSsrSBmXgBT9Dgj4waITrieWF0p4kDYpaqLDLLob3l1+nsmwhs+bMy6LKDl+etuKu+/abn37t2/kZwCo7s1utOmuZx45A+siVD5NeCEm9qQN0EaYCizjnE5dmN4TxcKQutoATtsdF3imHV0ka9a+YHOtaADCTZ6mGzl093ASbmSl5U9cVJq/4K43pLokMW+YpA==",
        "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=5dAbdAGsagWt26Fiudtsw1neSxOf7pzLZebVp8TRXbo=;\n b=ieiqJS7z1YQAKbZCXfuPl1Oxdr3kOAdh72R/XuvzUZ4qr0hStp9ZjBpZobYVDjkjanpySupP/TjMP3VhbzauFLbyjCztPqeB5BskI3g3iM7aMaW9IebA22vNX5lf1SChmLMN08YWgyl3WbkVQuBPcI8XVTtsjrY0AP/QyF8aNIMFETKWpsxkOMiL19f80TtHMDCCXDDVzRCinw62zOewqYAWqsrKhZRVh2aJbv1sLVCb94FNIPF4rnU+D7FIG7hbZpjUTVMfbxx6NKBlmFbAct1/QmMYZRWKEmMoPuHtlnKZj2SFqNHBgD/jm+cEPbRquqOpS6D7ZqB0vDIJ3Yhf1A==",
        "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=5dAbdAGsagWt26Fiudtsw1neSxOf7pzLZebVp8TRXbo=;\n b=L2Z4hfjTmYZJYrXwN8e6e2tkC3bKpChp0nfZ2phfBo7p5vjTjzLTmrzFJLfgRP0MTzhdoAOCzGvBv8nCAHa7CjAESQnFTIledYdwscADUEX6t/4kRF5581oguY4t9LiBpsmcO3wBQs1438CDxMUC4X55dyRfuj1R7nCnOwj2VzU=",
        "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 v7 2/3] test: add dispatcher test suite",
        "Date": "Wed, 11 Oct 2023 09:16:59 +0200",
        "Message-ID": "<20231011071700.442795-3-mattias.ronnblom@ericsson.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20231011071700.442795-1-mattias.ronnblom@ericsson.com>",
        "References": "<20231009181711.440865-2-mattias.ronnblom@ericsson.com>\n <20231011071700.442795-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": "DB5PEPF00014B8D:EE_|DU2PR07MB8152:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "531d90ca-35fb-40a2-8891-08dbca2acf48",
        "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 OzolTblLI5uZrwjWfwLl8wLen9CP4CXexYb0LVx/UgXOE1/pUu+6wCwo/2aUPcQNzCI9Kxcbu6GBaGc+hdCFOHyV7qbEy7DSQjpEglj0o4wIJVOABOLvRrfB02FOv3JjfD5T+A/osB1aeJ7b1RfZPARBu0JiWv92krFgy2JID9FcKtjhb4zKtefV98KrBE2/qTqJp1kNwOS0dBHuOjfk3jKHdGPXI+LGsea31RX/ovk8cMB3fw5gMEHguVORI3KyE1qWogaKDdWUZ7XkDCKs9vqAiUFm2+7k3E2ISAt5gkAq1xRTPGeF7bZwhYD/XNDS8oS8bk/i7JZMYRDzYD+GkdLHGBVlqc52H0nDSGdqfyAhKpaR0HnbhXIXYwjpcQ6Tf84HaMsJHRH2fH66tvhXVJjLOD5nluS7hbNrnN1ybGPiQ3Zc7jpuqvjrgH6u4FU5H48utDZqkGkm/3E61sg8hb9X75SGdbCnuGNkxnXimIvIt4RXWEMhfWtAJhLKudf0ofEEjSJK0k9txVHWFMtWLxueGZdsht6ieu5grFZXGgaGW806sASWpJtPwQ9hT1EmH9i54RtEmK0V4m99awnIwaBuhQQDnZsUizbUebsfpjbH7Y0xS4hl5CUqCPdRd+j1EwZWZZhLQ86zisIApoiguPbCTOPITzvSL8RkS6Bai/HDz10N7WtUfOesFXUhZpbl9NRGl50KZfTbcW8/NRkb5bYxEdkDPktQ7k+T6bIRl4/bo6Kp1YxYb1MOj3HROsMusZlNiej8uhbscQHp2GiER2Q3+Cp1fuTAQYOKEK99b1Gkv4KAvoPv8bvL6bOSab1FSYGZJwFrSI7QpvT4vm/lQ5dijZ/CVcY0AV3KpHsfwn0=",
        "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)(376002)(136003)(39860400002)(396003)(230922051799003)(64100799003)(186009)(1800799009)(82310400011)(451199024)(46966006)(40470700004)(36840700001)(40460700003)(107886003)(1076003)(478600001)(6666004)(2616005)(30864003)(47076005)(2906002)(6266002)(26005)(336012)(7416002)(83380400001)(66574015)(4326008)(70586007)(54906003)(5660300002)(70206006)(110136005)(8676002)(8936002)(316002)(41300700001)(356005)(82960400001)(7636003)(82740400003)(36860700001)(36756003)(40480700001)(86362001)(2101003);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "ericsson.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "11 Oct 2023 07:22:21.7350 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 531d90ca-35fb-40a2-8891-08dbca2acf48",
        "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 DB5PEPF00014B8D.eurprd02.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "DU2PR07MB8152",
        "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 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 | 1074 ++++++++++++++++++++++++++++++++++++\n 3 files changed, 1076 insertions(+)\n create mode 100644 app/test/test_dispatcher.c",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex a4372701c4..262401d43d 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -1736,6 +1736,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 bf9fc90612..ace10327f8 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..f9dc097f32\n--- /dev/null\n+++ b/app/test/test_dispatcher.c\n@@ -0,0 +1,1074 @@\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 int\n+test_app_start_dispatcher(struct test_app *app)\n+{\n+\tint rc;\n+\n+\trc = rte_dispatcher_start(app->dispatcher);\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);\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+\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+\trc = test_app_start_dispatcher(app);\n+\tif (rc != TEST_SUCCESS)\n+\t\treturn rc;\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+\trc = test_app_stop_dispatcher(app);\n+\tif (rc != TEST_SUCCESS)\n+\t\treturn rc;\n+\n+\ttest_app_stop_service_cores(app);\n+\tif (rc != TEST_SUCCESS)\n+\t\treturn rc;\n+\n+\ttest_app_stop_event_dev(app);\n+\tif (rc != TEST_SUCCESS)\n+\t\treturn 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+\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": [
        "v7",
        "2/3"
    ]
}