get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 128713,
    "url": "http://patchwork.dpdk.org/api/patches/128713/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20230614172527.157664-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": "<20230614172527.157664-3-mattias.ronnblom@ericsson.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230614172527.157664-3-mattias.ronnblom@ericsson.com",
    "date": "2023-06-14T17:25:26",
    "name": "[2/3] test: add event dispatcher test suite",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "531cc13d22e038df672a56bca309c21df6c769e5",
    "submitter": {
        "id": 1077,
        "url": "http://patchwork.dpdk.org/api/people/1077/?format=api",
        "name": "Mattias Rönnblom",
        "email": "mattias.ronnblom@ericsson.com"
    },
    "delegate": {
        "id": 310,
        "url": "http://patchwork.dpdk.org/api/users/310/?format=api",
        "username": "jerin",
        "first_name": "Jerin",
        "last_name": "Jacob",
        "email": "jerinj@marvell.com"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20230614172527.157664-3-mattias.ronnblom@ericsson.com/mbox/",
    "series": [
        {
            "id": 28515,
            "url": "http://patchwork.dpdk.org/api/series/28515/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=28515",
            "date": "2023-06-14T17:25:24",
            "name": "Add event dispatcher",
            "version": 1,
            "mbox": "http://patchwork.dpdk.org/series/28515/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/128713/comments/",
    "check": "warning",
    "checks": "http://patchwork.dpdk.org/api/patches/128713/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 EC5FB42CBC;\n\tWed, 14 Jun 2023 19:32:04 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 959EB42D12;\n\tWed, 14 Jun 2023 19:31:54 +0200 (CEST)",
            "from EUR01-DB5-obe.outbound.protection.outlook.com\n (mail-db5eur01on2071.outbound.protection.outlook.com [40.107.15.71])\n by mails.dpdk.org (Postfix) with ESMTP id 28A6842C24\n for <dev@dpdk.org>; Wed, 14 Jun 2023 19:31:52 +0200 (CEST)",
            "from DB6P192CA0008.EURP192.PROD.OUTLOOK.COM (2603:10a6:4:b8::18) by\n PA4PR07MB9605.eurprd07.prod.outlook.com (2603:10a6:102:26e::22) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6477.29; Wed, 14 Jun\n 2023 17:31:50 +0000",
            "from DB5EUR02FT020.eop-EUR02.prod.protection.outlook.com\n (2603:10a6:4:b8:cafe::94) by DB6P192CA0008.outlook.office365.com\n (2603:10a6:4:b8::18) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6477.34 via Frontend\n Transport; Wed, 14 Jun 2023 17:31:50 +0000",
            "from oa.msg.ericsson.com (192.176.1.74) by\n DB5EUR02FT020.mail.protection.outlook.com (10.13.59.231) with Microsoft SMTP\n Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id\n 15.20.6500.20 via Frontend Transport; Wed, 14 Jun 2023 17:31:50 +0000",
            "from ESESBMB501.ericsson.se (153.88.183.168) by\n ESESSMB504.ericsson.se (153.88.183.54) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id\n 15.1.2507.23; Wed, 14 Jun 2023 19:31:49 +0200",
            "from seliicinfr00050.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.23 via Frontend Transport; Wed, 14 Jun 2023 19:31:49 +0200",
            "from breslau.. (seliicwb00002.seli.gic.ericsson.se [10.156.25.100])\n by seliicinfr00050.seli.gic.ericsson.se (Postfix) with ESMTP id\n 25A6B1C006A; Wed, 14 Jun 2023 19:31:49 +0200 (CEST)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=T9IVkx4sEFh8dIqQ1gWk7kA6l6SF7By0kX0G8rFwsgmKB0RwTzBGJyGmjSp5ZXm8Q+qHDbUuQAAhJBbf+nuJZH3z7BgBrbBDlM8sER8WSVCeEhQdgsuPEx4MFsupklG30lg5A/Uj/ICC7ZuHZiENL0MdqXmQcf/AcgMKPdXa+pt9LcYRPD3ze1ghg+XTMNZrMF4XpvRkFFSujKkW2UDAr1UvcqLkUSrz5Y0ufJCY16F/t4S0speRhD0w5mXJnZin67iVzvfdddNu7yMgSmzVyDH1SyyUg98O2oWq1Mzf45g3PA+I6/aIlJwYATbcUCq6aCPCmjaE0NwUDOyrpgyVeA==",
        "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=Xd69MIugIimTHVi00PMCPWlXEHLjwwkd+zqD1T0zuV0=;\n b=aCfbe+P2FUWuvZx+CYaBr4k0plwisa7/enS59wBy3Fu/17//b7GjCsb80sY8l5IVOl+LcuEx0BjcpPflxiH0cUbbJ7BmKsQxtaxUzCUeMIR6Wr0+m7eLkTK87m1K8SrwNuEBMwufwiurrMgaNEw7eb+ZR5L5IeM0RQqGsgBaz8LdB5GTzvigOJGi3A5A8Y/97KpOVJfCblRJD0Orsykm50JDab1AIeEBUseKZDa/5YAmSHFJh3ZH7sg7QK8nX0v7NTGNbTPhbK1K5gJZIvAdfVktth7hQ76i8J+FErxMQSpf+x70+Bg1wpa/r7D5njHSC2YfY9zDfXAwplVaLKa+4Q==",
        "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=Xd69MIugIimTHVi00PMCPWlXEHLjwwkd+zqD1T0zuV0=;\n b=ow4LgLK6Wk4wEHQjMKaOdynx6902ryJMWHWqlgLn31nIGmbHfjFl9Q6j9BEZ/QoUpUMG3jB8y9hJjUYtBhc36DowpnZl9YsUffRG9iGgdl9n+YFQFmCqELCh0THwNDwGxPl3q4kCM1F2Of/pv2fxC6CMnlkrnJdtjddDkDgNrbw=",
        "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": "<jerinj@marvell.com>",
        "CC": "Jerin Jacob <jerinjacobk@gmail.com>, <hofors@lysator.liu.se>,\n <dev@dpdk.org>, <harry.van.haaren@intel.com>, <peter.j.nilsson@ericsson.com>,\n  Stephen Hemminger <stephen@networkplumber.org>,\n Heng Wang <heng.wang@ericsson.com>,\n =?utf-8?q?Mattias_R=C3=B6nnblom?= <mattias.ronnblom@ericsson.com>",
        "Subject": "[PATCH 2/3] test: add event dispatcher test suite",
        "Date": "Wed, 14 Jun 2023 19:25:26 +0200",
        "Message-ID": "<20230614172527.157664-3-mattias.ronnblom@ericsson.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20230614172527.157664-1-mattias.ronnblom@ericsson.com>",
        "References": "<20230609070826.149336-2-mattias.ronnblom@ericsson.com>\n <20230614172527.157664-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": "DB5EUR02FT020:EE_|PA4PR07MB9605:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "410ffaf7-b571-47bf-382f-08db6cfd3cb7",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n x1ysQTrrEYWvGGsg0R3h+C3oBwRteXHICSTTqRmhiyvMTDiQaqqGLdwyxxzJMM++IkcDNV+WvH0ksH6Ybrvyg35Kqtw1MikzW0Tb7IQBMd94McGnq4ssjcqDzd0d1XWHPG6DU4opPhwIm53d0Wyf1IkxV3DqZAVFGev6geiXhG3VlyO2SktIIctO6aYJOaMcmxV1d2ubDTmqFFtOPu6p26DP5JAwX7HVg1LPQFQUufli+vO2auad1jCqZvMN5SxaGivh2a2EK0/dOtkdP7VsoeS+Z/d5qy+e5xZu8+xC05b2CxCJbY2fqGtS0/N6textxMWUBhmshaO4aI34FzMTuO6g1HRkBKpC0D5udUgp01PKEop8E5rnbFhwVJvqU4GWybHba6vkbgEfbJ9K4wHrHQ37YA3G+OW0CsTJlPt0JidDJ91vtK9dN4L0VwH5gMD74q0Z5jfZykkMu7NNXNYWY2W4H92+k1kDvINbTt2C4MBCPN13Cjax0fZwrxOuRqoKgn9kbAcUglJaWVlSAL/rgvm0YHDOalmWjFFPTrith0fASITPtcEo3LW4Xv4n7RKLlHv7+WgyLEpV4Up2k4qtbN8o8sHDSdFhmDbtUjgv+0yGAs8vGzjuafVVGQQxbeeRttC8oFxju6SqD8IO7zY7fbHNieF0LfMfjz9pm0BsMuOxEAP6Z9Nry+ThwzmmsKxf4PJ7oH1+Uhis0xfCS0q5al/n+VJhXOWpAwJ/SUKYYqwb0ITFecgpVs5i5+plwlatHLPpFVTxKwqlhhmY2Dy12I44vQQD1KKc6UGbgOpW8eY=",
        "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:(13230028)(4636009)(39860400002)(376002)(396003)(346002)(136003)(451199021)(36840700001)(46966006)(40470700004)(336012)(2616005)(66574015)(83380400001)(47076005)(36860700001)(356005)(7636003)(82740400003)(82960400001)(36756003)(40480700001)(82310400005)(86362001)(40460700003)(478600001)(54906003)(8936002)(6666004)(8676002)(30864003)(2906002)(4326008)(5660300002)(70586007)(70206006)(316002)(186003)(6266002)(41300700001)(107886003)(6916009)(26005)(1076003);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "ericsson.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "14 Jun 2023 17:31:50.3442 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 410ffaf7-b571-47bf-382f-08db6cfd3cb7",
        "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 DB5EUR02FT020.eop-EUR02.prod.protection.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "PA4PR07MB9605",
        "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 event dispatcher.\n\n--\n\nPATCH:\n o Extend test to cover often-used handler optimization feature.\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 app/test/meson.build             |   1 +\n app/test/test_event_dispatcher.c | 861 +++++++++++++++++++++++++++++++\n 2 files changed, 862 insertions(+)\n create mode 100644 app/test/test_event_dispatcher.c",
    "diff": "diff --git a/app/test/meson.build b/app/test/meson.build\nindex b9b5432496..fac3b6b88b 100644\n--- a/app/test/meson.build\n+++ b/app/test/meson.build\n@@ -50,6 +50,7 @@ test_sources = files(\n         'test_errno.c',\n         'test_ethdev_link.c',\n         'test_event_crypto_adapter.c',\n+        'test_event_dispatcher.c',\n         'test_event_eth_rx_adapter.c',\n         'test_event_ring.c',\n         'test_event_timer_adapter.c',\ndiff --git a/app/test/test_event_dispatcher.c b/app/test/test_event_dispatcher.c\nnew file mode 100644\nindex 0000000000..356ef8df44\n--- /dev/null\n+++ b/app/test/test_event_dispatcher.c\n@@ -0,0 +1,861 @@\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_event_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 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+\tuint64_t never_process_count;\n+\n+\tstruct app_queue queues[NUM_QUEUES];\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_event_dispatcher_create(app->dispatcher_id,\n+\t\t\t\t\t app->event_dev_id);\n+\n+\tTEST_ASSERT_SUCCESS(rc, \"Unable to create event dispatcher\");\n+\n+\trc = rte_event_dispatcher_service_id_get(app->dispatcher_id,\n+\t\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_event_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+\tfor (i = 0; i < NUM_WORKERS; i++) {\n+\t\tunsigned int lcore_id = app->service_lcores[i];\n+\n+\t\tint rc = rte_event_dispatcher_bind_port_to_lcore(\n+\t\t\tapp->dispatcher_id, WORKER_PORT_ID(i),\n+\t\t\tDEQUEUE_BURST_SIZE, 0, lcore_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\", WORKER_PORT_ID(i),\n+\t\t\t\t    lcore_id);\n+\t}\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_event_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 __rte_unused,\n+\t\t       uint8_t event_port_id __rte_unused,\n+\t\t       struct rte_event *in_events __rte_unused,\n+\t\t       uint16_t num, void *cb_data)\n+{\n+\tuint64_t *count = cb_data;\n+\n+\t(*count) += num;\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_event_dispatcher_register(app->dispatcher_id,\n+\t\t\t\t\t      never_match,\n+\t\t\t\t\t      &app->never_match_count,\n+\t\t\t\t\t      test_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_event_dispatcher_register(app->dispatcher_id,\n+\t\t\t\t\t\t       match_queue,\n+\t\t\t\t\t\t       (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+\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+\n+\tif (reg_id < 0) /* unregistered already */\n+\t\treturn 0;\n+\n+\tint rc = rte_event_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+\n+\tfor (i = 0; i < NUM_QUEUES; i++) {\n+\t\tint rc;\n+\n+\t\trc = test_app_unregister_callback(app, i);\n+\t\tRETURN_ON_ERROR(rc);\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_event_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_event_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_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_event_dispatcher_stats stats;\n+\trc = rte_event_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, 0, \"Never-match \"\n+\t\t\t  \"handler's process function has been called\");\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+\treturn TEST_SUCCESS;\n+}\n+\n+static int\n+test_drop(void)\n+{\n+\tint rc;\n+\tuint8_t unhandled_queue = 1;\n+\tstruct rte_event_dispatcher_stats stats;\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_event_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+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_CASES_END()\n+\t}\n+};\n+\n+static int\n+test_event_dispatcher(void)\n+{\n+\treturn unit_test_suite_runner(&test_suite);\n+}\n+\n+REGISTER_TEST_COMMAND(event_dispatcher_autotest, test_event_dispatcher);\n",
    "prefixes": [
        "2/3"
    ]
}