get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 136850,
    "url": "https://patches.dpdk.org/api/patches/136850/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20240216102348.480407-1-mattias.ronnblom@ericsson.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20240216102348.480407-1-mattias.ronnblom@ericsson.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20240216102348.480407-1-mattias.ronnblom@ericsson.com",
    "date": "2024-02-16T10:23:45",
    "name": "[RFC,v4,1/4] eal: add bitset type",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "bb2f4c06f315efabe92ebd1c4156ef7659ee527f",
    "submitter": {
        "id": 1077,
        "url": "https://patches.dpdk.org/api/people/1077/?format=api",
        "name": "Mattias Rönnblom",
        "email": "mattias.ronnblom@ericsson.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20240216102348.480407-1-mattias.ronnblom@ericsson.com/mbox/",
    "series": [
        {
            "id": 31128,
            "url": "https://patches.dpdk.org/api/series/31128/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=31128",
            "date": "2024-02-16T10:23:45",
            "name": "[RFC,v4,1/4] eal: add bitset type",
            "version": 4,
            "mbox": "https://patches.dpdk.org/series/31128/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/136850/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/136850/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 74F4A43B30;\n\tFri, 16 Feb 2024 11:41:47 +0100 (CET)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 5A12543001;\n\tFri, 16 Feb 2024 11:41:47 +0100 (CET)",
            "from EUR05-VI1-obe.outbound.protection.outlook.com\n (mail-vi1eur05on2059.outbound.protection.outlook.com [40.107.21.59])\n by mails.dpdk.org (Postfix) with ESMTP id 40B8D4064A\n for <dev@dpdk.org>; Fri, 16 Feb 2024 11:41:46 +0100 (CET)",
            "from AS4PR09CA0030.eurprd09.prod.outlook.com (2603:10a6:20b:5d4::20)\n by PA4PR07MB7648.eurprd07.prod.outlook.com (2603:10a6:102:c5::21)\n with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7292.31; Fri, 16 Feb\n 2024 10:41:43 +0000",
            "from AM4PEPF00027A61.eurprd04.prod.outlook.com\n (2603:10a6:20b:5d4:cafe::e2) by AS4PR09CA0030.outlook.office365.com\n (2603:10a6:20b:5d4::20) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7270.39 via Frontend\n Transport; Fri, 16 Feb 2024 10:41:43 +0000",
            "from oa.msg.ericsson.com (192.176.1.74) by\n AM4PEPF00027A61.mail.protection.outlook.com (10.167.16.70) with Microsoft\n SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.20.7292.25 via Frontend Transport; Fri, 16 Feb 2024 10:41:43 +0000",
            "from seliicinfr00050.seli.gic.ericsson.se (153.88.142.248) by\n smtp-central.internal.ericsson.com (100.87.178.64) with Microsoft SMTP Server\n id 15.2.1258.12; Fri, 16 Feb 2024 11:41:42 +0100",
            "from breslau.. (seliicwb00002.seli.gic.ericsson.se [10.156.25.100])\n by seliicinfr00050.seli.gic.ericsson.se (Postfix) with ESMTP id\n A15E51C007C; Fri, 16 Feb 2024 11:31:44 +0100 (CET)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=jCBMHG+JyYRwyH+JudVs/MnoxW6/+Qamgsg9heJ9WLHTKqjlVwct54pBEE1uZlZg8OyEyo1017/+A5HeYqTkzlgea+2Pwi1C4QA5PpsMhKpbDQf4fp4ZWbXXSwCwwf4EFDz3KfC//sPkwwGohYEf9gwfSWYjbYIIDQAEvG1Kme2lRq4xxUY8R1MDaMnAnJsXwA3LPpNzGZ40drUBBzwUpRHzvrvLBlTW46P9UDcJ9EwDfjdRYV0RFjf00c6GJ5UsmWQRGjdwY/194cs5Bg7ef3jw0L6ryRPFI0LAGuQ5bheaXix7f36WDTQSCEPoG9/7j6jZRrn5Ne8Z8I00sUNrQQ==",
        "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=TutJfe/HOO3zDhYGKbGWx/NlCBc3uRoTXQOhXJG5nbs=;\n b=AVD5++mTPnarvYnko2KZZA64gytakxqbgFNQI7Xuyh1WssyibFiZSjP+TFzeX7bhyEvWvARQ+RsumEXsAHBamIqoQ1fZe659usjBEVlY71oRhpXjVXgMQ1KymFEtWJH29lF0ee0nfbwx32j0deFs3nRLPPBoO1EVfGeJo3f6dsQj3iH5Ndi8C4se6LDX67SHlQ6X5fJkYUoN8rAzwGa1stpTTJNJEig4w/QQOPnadM/k5XIFaHoyHrwgT6BrVxhEyAf3u3lHZTmJPGoT1PZw0zGKVtBAdxZK0hqai6bLeszjaWDYP20OJRSDv5ZinyHf4XYiD+AvG3rHUe2hQkKjrw==",
        "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 (0)",
        "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=TutJfe/HOO3zDhYGKbGWx/NlCBc3uRoTXQOhXJG5nbs=;\n b=v7tYcW0mhIfOeFkM1S2jQnR2qlY9NM+2/lbRhMbJ/ml7C+ooXsCu7CkdFQifqhEoSk75VOvdUbAM27bCfK4RixsF5eX4KKTrv5T+VMMVj+2/DDabgYF+kBi5mr7OdJncvDROuzPHGAXqkKgQLRbx+YVQDyjjxOLjpZcQkSpwyVgWOgcKTdq8OM3lbXSH0bePkZf+0nzKpUVxPQq1NU0W9klDTK0BdvYjrlgqAAl1miBpgLGMGzx6BH9etLHrsj5kpefPWxXG7bFCAvLzOyNX9X/q8fHf4GAV69sF8gKsrnUSoSKTHQgD3UoAG/FsqoBAeMkX2StegoUg2eN1aMl/dg==",
        "X-MS-Exchange-Authentication-Results": "spf=pass (sender IP is 192.176.1.74)\n smtp.mailfrom=ericsson.com; dkim=none (message not signed)\n header.d=none;dmarc=pass action=none header.from=ericsson.com;",
        "Received-SPF": "Pass (protection.outlook.com: domain of ericsson.com designates\n 192.176.1.74 as permitted sender)\n receiver=protection.outlook.com;\n client-ip=192.176.1.74; helo=oa.msg.ericsson.com; pr=C",
        "From": "=?utf-8?q?Mattias_R=C3=B6nnblom?= <mattias.ronnblom@ericsson.com>",
        "To": "<dev@dpdk.org>",
        "CC": "<hofors@lysator.liu.se>,\n =?utf-8?q?Morten_Br=C3=B8rup?= <mb@smartsharesystems.com>,\n Tyler Retzlaff <roretzla@linux.microsoft.com>,\n Stephen Hemminger <stephen@networkplumber.org>,\n Harry van Haaren <harry.van.haaren@intel.com>, =?utf-8?q?Mattias_R=C3=B6nnb?=\n\t=?utf-8?q?lom?= <mattias.ronnblom@ericsson.com>",
        "Subject": "[RFC v4 1/4] eal: add bitset type",
        "Date": "Fri, 16 Feb 2024 11:23:45 +0100",
        "Message-ID": "<20240216102348.480407-1-mattias.ronnblom@ericsson.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20240131131301.418361-1-mattias.ronnblom@ericsson.com>",
        "References": "<20240131131301.418361-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": "AM4PEPF00027A61:EE_|PA4PR07MB7648:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "6e8af048-0c55-4282-bdc0-08dc2edbde01",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n 5WV6itClTCcKLsahzq7pT1KHtlUZcfm7d/hd6+OT6X2yCL40VC9bPgaL/i4kNd7d8sutU6R2mS8/2AZjYjUqTg/Vz+n/nVJst2a3tpQDs3W154nCPuuTJKoffx2mJA2tpBZqwd6++P6WGcb2GKfag/Nu7iQ48WhLfPLkuBPLb1IzqWyqVeg9i8ZjKzKhsZtvSN0xv3cuwiCpfrlMmReZQpzHN1wdmOC+XW8MAlbVU5hm0mTnrtZJOwej8JXSDVh5ep7gSpmXMuDhxw1cyEHQbxVTJ8epiIu9nE2zvxJRKdS0Nb5vLGS+Ysqq+BZRIEpCFQmGtVDiGOAm1ia8Am7oa73gNNrjuKFXiWey6+Ki1lJCLQqKWJzsi4JlAfVM2FnQpyeV928NxvFtJhcdW8RF6naVZRQSr1TIngurRIrSjS+yccyD7EJO0R9lTEQkZZhao7ski9hYXojIGWH9o+Eb/aZBmrMSI52sZApzwcmQcS3BRVgaYd95V7ZW7Vphh3Wwnh77c9ZKbY527a8ITPDsf0RQKTRD+f60rcFR2HaYXC8Qn7Q+HCK64mwlSdRgjbYc+fCgHvU2SqjPOo3PVJBBhkVxnr5xW98SuMykWvIuB/yekT2AU/f/R4bMhFQoLdW5hL5o2rHchQXNSse/Gk7S8kYLh4jNpC8mJVYxtxZCcEQ=",
        "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)(396003)(376002)(346002)(39860400002)(136003)(230273577357003)(230922051799003)(451199024)(36860700004)(186009)(82310400011)(1800799012)(64100799003)(40470700004)(46966006)(30864003)(2906002)(5660300002)(6916009)(4326008)(7636003)(41300700001)(86362001)(82740400003)(82960400001)(107886003)(356005)(26005)(1076003)(2616005)(54906003)(70206006)(316002)(70586007)(8676002)(8936002)(83380400001)(36756003)(336012)(6266002)(66574015)(478600001);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "ericsson.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "16 Feb 2024 10:41:43.5889 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 6e8af048-0c55-4282-bdc0-08dc2edbde01",
        "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 AM4PEPF00027A61.eurprd04.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "PA4PR07MB7648",
        "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": "Introduce a set of functions and macros that operate on sets of bits,\nkept in arrays of 64-bit words.\n\nRTE bitset is designed for bitsets which are larger than what fits in\na single machine word (i.e., 64 bits). For very large bitsets, the\n<rte_bitmap.h> API may be a more appropriate choice.\n\nRFC v4:\n * Add function rte_bitset_flip() to change the value of a bit.\n * Add function rte_bitset_complement(), flipping the value of all bits.\n * Add function rte_bitset_assign(), setting the value of a bit based\n   on a 'bool' parameter.\n * Add functions to perform logical shift the bitset left or right.\n * Add explicit destination bitset to logic operation type functions\n   (e.g., rte_bitset_and()), to increase flexibility.\n * Split implementation and test suite into distinct commits.\n\nRFC v3:\n * Split the bitset from the htimer patchset, where it was originally\n   hosted.\n * Rebase to current DPDK main.\n * Add note that rte_bitset_init() need not be called if bitset words\n   have already been zeroed.\n * Use REGISTER_FAST_TEST instead of REGISTER_TEST_COMMAND.\n * Use rte_popcount64() instead of compiler builtin.\n\nRFC v2:\n * Replaced <sys/types.h> with <stddef.h> include, to properly get\n   size_t typedef.\n * Add <rte_compat.h> to get __rte_experimental in <rte_bitset.h>.\n\nSigned-off-by: Mattias Rönnblom <mattias.ronnblom@ericsson.com>\n---\n lib/eal/common/meson.build   |    1 +\n lib/eal/common/rte_bitset.c  |   29 +\n lib/eal/include/meson.build  |    1 +\n lib/eal/include/rte_bitset.h | 1080 ++++++++++++++++++++++++++++++++++\n lib/eal/version.map          |    3 +\n 5 files changed, 1114 insertions(+)\n create mode 100644 lib/eal/common/rte_bitset.c\n create mode 100644 lib/eal/include/rte_bitset.h",
    "diff": "diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build\nindex 22a626ba6f..c1bbf26654 100644\n--- a/lib/eal/common/meson.build\n+++ b/lib/eal/common/meson.build\n@@ -31,6 +31,7 @@ sources += files(\n         'eal_common_uuid.c',\n         'malloc_elem.c',\n         'malloc_heap.c',\n+        'rte_bitset.c',\n         'rte_malloc.c',\n         'rte_random.c',\n         'rte_reciprocal.c',\ndiff --git a/lib/eal/common/rte_bitset.c b/lib/eal/common/rte_bitset.c\nnew file mode 100644\nindex 0000000000..35e55a64db\n--- /dev/null\n+++ b/lib/eal/common/rte_bitset.c\n@@ -0,0 +1,29 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Ericsson AB\n+ */\n+\n+#include <errno.h>\n+\n+#include \"rte_bitset.h\"\n+\n+ssize_t\n+rte_bitset_to_str(const uint64_t *bitset, size_t num_bits, char *buf,\n+\t\t  size_t capacity)\n+{\n+\tsize_t i;\n+\n+\tif (capacity < (num_bits + 1))\n+\t\treturn -EINVAL;\n+\n+\tfor (i = 0; i < num_bits; i++) {\n+\t\tbool value;\n+\n+\t\tvalue = rte_bitset_test(bitset, num_bits - 1 - i);\n+\n+\t\tbuf[i] = value ? '1' : '0';\n+\t}\n+\n+\tbuf[num_bits] = '\\0';\n+\n+\treturn num_bits + 1;\n+}\ndiff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build\nindex e94b056d46..4b5f120a66 100644\n--- a/lib/eal/include/meson.build\n+++ b/lib/eal/include/meson.build\n@@ -5,6 +5,7 @@ includes += include_directories('.')\n \n headers += files(\n         'rte_alarm.h',\n+        'rte_bitset.h',\n         'rte_bitmap.h',\n         'rte_bitops.h',\n         'rte_branch_prediction.h',\ndiff --git a/lib/eal/include/rte_bitset.h b/lib/eal/include/rte_bitset.h\nnew file mode 100644\nindex 0000000000..35631a2a12\n--- /dev/null\n+++ b/lib/eal/include/rte_bitset.h\n@@ -0,0 +1,1080 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Ericsson AB\n+ */\n+\n+#ifndef _RTE_BITSET_H_\n+#define _RTE_BITSET_H_\n+\n+/**\n+ * @file\n+ * RTE Bitset\n+ *\n+ * This file provides functions and macros for querying and\n+ * manipulating sets of bits kept in arrays of @c uint64_t-sized\n+ * elements.\n+ *\n+ * The bits in a bitset are numbered from 0 to @c size - 1, with the\n+ * lowest index being the least significant bit.\n+ *\n+ * The bitset array must be properly aligned.\n+ *\n+ * For optimal performance, the @c size parameter, required by\n+ * many of the API's functions, should be a compile-time constant.\n+ *\n+ * For large bitsets, the rte_bitmap.h API may be more appropriate.\n+ *\n+ * @warning\n+ * All functions modifying a bitset may overwrite any unused bits of\n+ * the last word. Such unused bits are ignored by all functions reading\n+ * bits.\n+ *\n+ */\n+\n+#include <limits.h>\n+#include <stdbool.h>\n+#include <stddef.h>\n+#include <stdint.h>\n+\n+#include <rte_bitops.h>\n+#include <rte_branch_prediction.h>\n+#include <rte_common.h>\n+#include <rte_compat.h>\n+#include <rte_debug.h>\n+#include <rte_memcpy.h>\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+/**\n+ * The size (in bytes) of each element in the array used to represent\n+ * a bitset.\n+ */\n+#define RTE_BITSET_WORD_SIZE (sizeof(uint64_t))\n+\n+/**\n+ * The size (in bits) of each element in the array used to represent\n+ * a bitset.\n+ */\n+#define RTE_BITSET_WORD_BITS (RTE_BITSET_WORD_SIZE * CHAR_BIT)\n+\n+/**\n+ * Computes the number of words required to store @c size bits.\n+ */\n+#define RTE_BITSET_NUM_WORDS(size)\t\t\t\t\t\\\n+\t((size + RTE_BITSET_WORD_BITS - 1) / RTE_BITSET_WORD_BITS)\n+\n+/**\n+ * Computes the amount of memory (in bytes) required to fit a bitset\n+ * holding @c size bits.\n+ */\n+#define RTE_BITSET_SIZE(size)\t\t\t\t\t\t\\\n+\t((size_t)(RTE_BITSET_NUM_WORDS(size) * RTE_BITSET_WORD_SIZE))\n+\n+#define __RTE_BITSET_WORD_IDX(bit_num) ((bit_num) / RTE_BITSET_WORD_BITS)\n+#define __RTE_BITSET_BIT_OFFSET(bit_num) ((bit_num) % RTE_BITSET_WORD_BITS)\n+#define __RTE_BITSET_UNUSED(size)\t\t\t     \\\n+\t((RTE_BITSET_NUM_WORDS(size) * RTE_BITSET_WORD_BITS) \\\n+\t - (size))\n+#define __RTE_BITSET_USED_MASK(size)\t\t\t\\\n+\t(UINT64_MAX >> __RTE_BITSET_UNUSED(size))\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Declare a bitset.\n+ *\n+ * Declare (e.g., as a struct field) or define (e.g., as a stack\n+ * variable) a bitset of the specified size.\n+ *\n+ * @param size\n+ *   The number of bits the bitset must be able to represent. Must be\n+ *   a compile-time constant.\n+ * @param name\n+ *   The field or variable name of the resulting definition.\n+ */\n+#define RTE_BITSET_DECLARE(name, size)\t\t\\\n+\tuint64_t name[RTE_BITSET_NUM_WORDS(size)]\n+\n+/* XXX: should one include flags here and use to avoid a comparison? */\n+/* XXX: would this be better off as a function? */\n+\n+#define __RTE_BITSET_FOREACH_LEFT(var, size, start_bit, len)\t\t\\\n+\t((len) - 1 - ((var) >= (start_bit) ? (var) - (start_bit) :\t\\\n+\t\t  (size) - (start_bit) + (var)))\n+\n+#define __RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, flags)\t\\\n+\tfor ((var) = __rte_bitset_find(bitset, size, start_bit, len,\t\\\n+\t\t\t\t       flags);\t\t\t\t\\\n+\t     (var) != -1;\t\t\t\t\t\t\\\n+\t     (var) = __RTE_BITSET_FOREACH_LEFT(var, size, start_bit,\t\\\n+\t\t\t\t\t       len) > 0\t?\t\t\\\n+\t\t     __rte_bitset_find(bitset, size,\t\t\t\\\n+\t\t\t\t       ((var) + 1) % (size),\t\t\\\n+\t\t\t\t       __RTE_BITSET_FOREACH_LEFT(var,\t\\\n+\t\t\t\t\t\t\t\t size,\t\\\n+\t\t\t\t\t\t\t\t start_bit, \\\n+\t\t\t\t\t\t\t\t len),\t\\\n+\t\t\t\t       flags) : -1)\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Iterate over all bits set.\n+ *\n+ * This macro iterates over all bits set (i.e., all ones) in the\n+ * bitset, in the forward direction (i.e., starting with the least\n+ * significant '1').\n+ *\n+ * @param var\n+ *   An iterator variable of type @c ssize_t. For each successive\n+ *   iteration, this variable will hold the bit index of a set bit.\n+ * @param bitset\n+ *   A <tt>const uint64_t *</tt> pointer to the bitset array.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ */\n+\n+#define RTE_BITSET_FOREACH_SET(var, bitset, size)\t\t\t\\\n+\t__RTE_BITSET_FOREACH(var, bitset, size, 0, size, 0)\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Iterate over all bits cleared.\n+ *\n+ * This macro iterates over all bits cleared in the bitset, in the\n+ * forward direction (i.e., starting with the lowest-indexed set bit).\n+ *\n+ * @param var\n+ *   An iterator variable of type @c ssize_t. For each successive iteration,\n+ *   this variable will hold the bit index of a cleared bit.\n+ * @param bitset\n+ *   A <tt>const uint64_t *</tt> pointer to the bitset array.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ */\n+\n+#define RTE_BITSET_FOREACH_CLEAR(var, bitset, size)\t\t\t\\\n+\t__RTE_BITSET_FOREACH(var, bitset, size, 0, size,\t\t\\\n+\t\t\t     __RTE_BITSET_FIND_FLAG_FIND_CLEAR)\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Iterate over all bits set within a range.\n+ *\n+ * This macro iterates over all bits set (i.e., all ones) in the\n+ * specified range, in the forward direction (i.e., starting with the\n+ * least significant '1').\n+ *\n+ * @param var\n+ *   An iterator variable of type @c ssize_t. For each successive iteration,\n+ *   this variable will hold the bit index of a set bit.\n+ * @param bitset\n+ *   A <tt>const uint64_t *</tt> pointer to the bitset array.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ * @param start_bit\n+ *   The index of the first bit to check. Must be less than @c size.\n+ * @param len\n+ *   The length (in bits) of the range. @c start_bit + @c len must be less\n+ *   than or equal to @c size.\n+ */\n+\n+#define RTE_BITSET_FOREACH_SET_RANGE(var, bitset, size, start_bit,     \\\n+\t\t\t\t     len)\t\t\t       \\\n+\t__RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, 0)\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Iterate over all cleared bits within a range.\n+ *\n+ * This macro iterates over all bits cleared (i.e., all zeroes) in the\n+ * specified range, in the forward direction (i.e., starting with the\n+ * least significant '0').\n+ *\n+ * @param var\n+ *   An iterator variable of type @c ssize_t. For each successive iteration,\n+ *   this variable will hold the bit index of a set bit.\n+ * @param bitset\n+ *   A <tt>const uint64_t *</tt> pointer to the bitset array.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ * @param start_bit\n+ *   The index of the first bit to check. Must be less than @c size.\n+ * @param len\n+ *   The length (in bits) of the range. @c start_bit + @c len must be less\n+ *   than or equal to @c size.\n+ */\n+\n+#define RTE_BITSET_FOREACH_CLEAR_RANGE(var, bitset, size, start_bit,\t\\\n+\t\t\t\t       len)\t\t\t\t\\\n+\t__RTE_BITSET_FOREACH(var, bitset, size, start_bit, len,\t\t\\\n+\t\t\t     __RTE_BITSET_FIND_FLAG_FIND_CLEAR)\n+\n+#define RTE_BITSET_FOREACH_SET_WRAP(var, bitset, size, start_bit,      \\\n+\t\t\t\t    len)\t\t\t       \\\n+\t__RTE_BITSET_FOREACH(var, bitset, size, start_bit, len,\t       \\\n+\t\t\t     __RTE_BITSET_FIND_FLAG_WRAP)\n+\n+#define RTE_BITSET_FOREACH_CLEAR_WRAP(var, bitset, size, start_bit,\t\\\n+\t\t\t\t       len)\t\t\t\t\\\n+\t__RTE_BITSET_FOREACH(var, bitset, size, start_bit, len,\t\t\\\n+\t\t\t     __RTE_BITSET_FIND_FLAG_WRAP |\t\t\\\n+\t\t\t     __RTE_BITSET_FIND_FLAG_FIND_CLEAR)\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Initializes a bitset.\n+ *\n+ * All bits are cleared.\n+ *\n+ * In case all words in the bitset array are already set to zero by\n+ * other means (e.g., at the time of memory allocation), this function\n+ * need not be called.\n+ *\n+ * @param bitset\n+ *   A pointer to the array of bitset 64-bit words.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_init(uint64_t *bitset, size_t size)\n+{\n+\tmemset(bitset, 0, RTE_BITSET_SIZE(size));\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Set a bit in the bitset.\n+ *\n+ * Bits are numbered from 0 to (size - 1) (inclusive).\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param bit_num\n+ *   The index of the bit to be set.\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_set(uint64_t *bitset, size_t bit_num)\n+{\n+\tsize_t word;\n+\tsize_t offset;\n+\tuint64_t mask;\n+\n+\tword = __RTE_BITSET_WORD_IDX(bit_num);\n+\toffset = __RTE_BITSET_BIT_OFFSET(bit_num);\n+\tmask = UINT64_C(1) << offset;\n+\n+\tbitset[word] |= mask;\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Clear a bit in the bitset.\n+ *\n+ * Bits are numbered 0 to (size - 1) (inclusive).\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param bit_num\n+ *   The index of the bit to be cleared.\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_clear(uint64_t *bitset, size_t bit_num)\n+{\n+\tsize_t word;\n+\tsize_t offset;\n+\tuint64_t mask;\n+\n+\tword = __RTE_BITSET_WORD_IDX(bit_num);\n+\toffset = __RTE_BITSET_BIT_OFFSET(bit_num);\n+\tmask = ~(UINT64_C(1) << offset);\n+\n+\tbitset[word] &= mask;\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Set or clear a bit in the bitset.\n+ *\n+ * Bits are numbered 0 to (size - 1) (inclusive).\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param bit_num\n+ *   The index of the bit to be set or cleared.\n+ * @param bit_value\n+ *   Control if the bit should be set or cleared.\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_assign(uint64_t *bitset, size_t bit_num, bool bit_value)\n+{\n+\tif (bit_value)\n+\t\trte_bitset_set(bitset, bit_num);\n+\telse\n+\t\trte_bitset_clear(bitset, bit_num);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Change the value of a bit in the bitset.\n+ *\n+ * Bits are numbered 0 to (size - 1) (inclusive).\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param bit_num\n+ *   The index of the bit to be flipped.\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_flip(uint64_t *bitset, size_t bit_num)\n+{\n+\tsize_t word;\n+\tsize_t offset;\n+\tuint64_t mask;\n+\n+\tword = __RTE_BITSET_WORD_IDX(bit_num);\n+\toffset = __RTE_BITSET_BIT_OFFSET(bit_num);\n+\tmask = UINT64_C(1) << offset;\n+\n+\tbitset[word] ^= mask;\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Set all bits in the bitset.\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_set_all(uint64_t *bitset, size_t size)\n+{\n+\tmemset(bitset, 0xFF, RTE_BITSET_SIZE(size));\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Clear all bits in the bitset.\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_clear_all(uint64_t *bitset, size_t size)\n+{\n+\trte_bitset_init(bitset, size);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Count all set bits (also known as the @e weight).\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ * @return\n+ *   Returns the number of '1' bits in the bitset.\n+ */\n+\n+__rte_experimental\n+static inline size_t\n+rte_bitset_count_set(const uint64_t *bitset, size_t size)\n+{\n+\tsize_t i;\n+\tsize_t total = 0;\n+\n+\t/*\n+\t * Unused bits in a rte_bitset are always '0', and thus are\n+\t * not included in this count.\n+\t */\n+\tfor (i = 0; i < RTE_BITSET_NUM_WORDS(size) - 1; i++)\n+\t\ttotal += rte_popcount64(bitset[i]);\n+\n+\ttotal += rte_popcount64(bitset[i] & __RTE_BITSET_USED_MASK(size));\n+\n+\treturn total;\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Count all cleared bits.\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ * @return\n+ *   Returns the number of '0' bits in the bitset.\n+ */\n+\n+__rte_experimental\n+static inline size_t\n+rte_bitset_count_clear(const uint64_t *bitset, size_t size)\n+{\n+\treturn size - rte_bitset_count_set(bitset, size);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Test if a bit is set.\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param bit_num\n+ *   Index of the bit to test. Index 0 is the least significant bit.\n+ * @return\n+ *   Returns true if the bit is '1', and false if the bit is '0'.\n+ */\n+\n+__rte_experimental\n+static inline bool\n+rte_bitset_test(const uint64_t *bitset, size_t bit_num)\n+{\n+\tsize_t word;\n+\tsize_t offset;\n+\n+\tword = __RTE_BITSET_WORD_IDX(bit_num);\n+\toffset = __RTE_BITSET_BIT_OFFSET(bit_num);\n+\n+\treturn (bitset[word] >> offset) & 1;\n+}\n+\n+#define __RTE_BITSET_FIND_FLAG_FIND_CLEAR (1U << 0)\n+#define __RTE_BITSET_FIND_FLAG_WRAP (1U << 1)\n+\n+__rte_experimental\n+static inline ssize_t\n+__rte_bitset_find_nowrap(const uint64_t *bitset, size_t __rte_unused size,\n+\t\t\t size_t start_bit, size_t len, bool find_clear)\n+{\n+\tsize_t word_idx;\n+\tsize_t offset;\n+\tsize_t end_bit = start_bit + len;\n+\n+\tRTE_ASSERT(end_bit <= size);\n+\n+\tif (unlikely(len == 0))\n+\t\treturn -1;\n+\n+\tword_idx = __RTE_BITSET_WORD_IDX(start_bit);\n+\toffset = __RTE_BITSET_BIT_OFFSET(start_bit);\n+\n+\twhile (word_idx <= __RTE_BITSET_WORD_IDX(end_bit - 1)) {\n+\t\tuint64_t word;\n+\t\tint word_ffs;\n+\n+\t\tword = bitset[word_idx];\n+\t\tif (find_clear)\n+\t\t\tword = ~word;\n+\n+\t\tword >>= offset;\n+\n+\t\tword_ffs = __builtin_ffsll(word);\n+\n+\t\tif (word_ffs != 0) {\n+\t\t\tssize_t ffs = start_bit + word_ffs - 1;\n+\n+\t\t\t/*\n+\t\t\t * Check if set bit were among the last,\n+\t\t\t * unused bits, in the last word.\n+\t\t\t */\n+\t\t\tif (unlikely(ffs >= (ssize_t)end_bit))\n+\t\t\t\treturn -1;\n+\n+\t\t\treturn ffs;\n+\t\t}\n+\n+\t\tstart_bit += (RTE_BITSET_WORD_BITS - offset);\n+\t\tword_idx++;\n+\t\toffset = 0;\n+\t}\n+\n+\treturn -1;\n+\n+}\n+\n+__rte_experimental\n+static inline ssize_t\n+__rte_bitset_find(const uint64_t *bitset, size_t size, size_t start_bit,\n+\t\t  size_t len, unsigned int flags)\n+{\n+\tbool find_clear = flags & __RTE_BITSET_FIND_FLAG_FIND_CLEAR;\n+\tbool may_wrap = flags & __RTE_BITSET_FIND_FLAG_WRAP;\n+\tbool does_wrap = (start_bit + len) > size;\n+\tssize_t rc;\n+\n+\tRTE_ASSERT(len <= size);\n+\tif (!may_wrap)\n+\t\tRTE_ASSERT(!does_wrap);\n+\n+\tif (may_wrap && does_wrap) {\n+\t\tsize_t len0 = size - start_bit;\n+\t\tsize_t len1 = len - len0;\n+\n+\t\trc = __rte_bitset_find_nowrap(bitset, size, start_bit, len0,\n+\t\t\t\t\t      find_clear);\n+\t\tif (rc < 0)\n+\t\t\trc =  __rte_bitset_find_nowrap(bitset, size,\n+\t\t\t\t\t\t       0, len1, find_clear);\n+\t} else\n+\t\trc = __rte_bitset_find_nowrap(bitset, size, start_bit,\n+\t\t\t\t\t      len, find_clear);\n+\n+\treturn rc;\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Find first bit set.\n+ *\n+ * Scans the bitset in the forward direction (i.e., starting at the\n+ * least significant bit), and returns the index of the first '1'.\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ * @return\n+ *   Returns the index of the least significant '1', or -1 if all\n+ *   bits are '0'.\n+ */\n+\n+__rte_experimental\n+static inline ssize_t\n+rte_bitset_find_first_set(const uint64_t *bitset, size_t size)\n+{\n+\treturn __rte_bitset_find(bitset, size, 0, size, 0);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Find first bit set at offset.\n+ *\n+ * Scans the bitset in the forward direction (i.e., starting at the\n+ * least significant bit), starting at an offset @c start_bit into the\n+ * bitset, and returns the index of the first '1' encountered.\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ * @param start_bit\n+ *   The index of the first bit to check. Must be less than @c size.\n+ * @param len\n+ *   The number of bits to scan. @c start_bit + @c len must be less\n+ *   than or equal to @c size.\n+ * @return\n+ *   Returns the index of the least significant '1', or -1 if all\n+ *   bits are '0'.\n+ */\n+\n+__rte_experimental\n+static inline ssize_t\n+rte_bitset_find_set(const uint64_t *bitset, size_t size,\n+\t\t    size_t start_bit, size_t len)\n+{\n+\treturn __rte_bitset_find(bitset, size, start_bit, len, 0);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Find first bit set at offset, with wrap-around.\n+ *\n+ * Scans the bitset in the forward direction (i.e., starting at the\n+ * least significant bit), starting at an offset @c start_bit into the\n+ * bitset. If no '1' is encountered before the end of the bitset, the search\n+ * will continue at index 0.\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ * @param start_bit\n+ *   The index of the first bit to check. Must be less than @c size.\n+ * @param len\n+ *   The number of bits to scan. @c start_bit + @c len must be less\n+ *   than or equal to @c size.\n+ * @return\n+ *   Returns the index of the least significant '1', or -1 if all\n+ *   bits are '0'.\n+ */\n+\n+__rte_experimental\n+static inline ssize_t\n+rte_bitset_find_set_wrap(const uint64_t *bitset, size_t size,\n+\t\t\t size_t start_bit, size_t len)\n+{\n+\treturn __rte_bitset_find(bitset, size, start_bit, len,\n+\t\t\t\t __RTE_BITSET_FIND_FLAG_WRAP);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Find first cleared bit.\n+ *\n+ * Scans the bitset in the forward direction (i.e., starting at the\n+ * least significant bit), and returns the index of the first '0'.\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ * @return\n+ *   Returns the index of the least significant '0', or -1 if all\n+ *   bits are '1'.\n+ */\n+\n+__rte_experimental\n+static inline ssize_t\n+rte_bitset_find_first_clear(const uint64_t *bitset, size_t size)\n+{\n+\treturn __rte_bitset_find(bitset, size, 0, size,\n+\t\t\t\t __RTE_BITSET_FIND_FLAG_FIND_CLEAR);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Find first cleared bit at offset.\n+ *\n+ * Scans the bitset in the forward direction (i.e., starting at the\n+ * least significant bit), starting at an offset @c start_bit into the\n+ * bitset, and returns the index of the first '0' encountered.\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ * @param start_bit\n+ *   The index of the first bit to check. Must be less than @c size.\n+ * @param len\n+ *   The number of bits to scan. @c start_bit + @c len must be less\n+ *   than or equal to @c size.\n+ * @return\n+ *   Returns the index of the least significant '0', or -1 if all\n+ *   bits are '1'.\n+ */\n+\n+__rte_experimental\n+static inline ssize_t\n+rte_bitset_find_clear(const uint64_t *bitset, size_t size,\n+\t\t\t   size_t start_bit, size_t len)\n+{\n+\treturn __rte_bitset_find(bitset, size, start_bit, len,\n+\t\t\t\t __RTE_BITSET_FIND_FLAG_FIND_CLEAR);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Find first cleared bit at offset, with wrap-around.\n+ *\n+ * Scans the bitset in the forward direction (i.e., starting at the\n+ * least significant bit), starting at an offset @c start_bit into the\n+ * bitset. If no '0' is encountered before the end of the bitset, the\n+ * search will continue at index 0.\n+ *\n+ * @param bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param size\n+ *   The size of the bitset (in bits).\n+ * @param start_bit\n+ *   The index of the first bit to check. Must be less than @c size.\n+ * @param len\n+ *   The number of bits to scan. @c start_bit + @c len must be less\n+ *   than or equal to @c size.\n+ * @return\n+ *   Returns the index of the least significant '0', or -1 if all\n+ *   bits are '1'.\n+ */\n+\n+__rte_experimental\n+static inline ssize_t\n+rte_bitset_find_clear_wrap(const uint64_t *bitset, size_t size,\n+\t\t\t   size_t start_bit, size_t len)\n+{\n+\treturn __rte_bitset_find(bitset, size, start_bit, len,\n+\t\t\t\t __RTE_BITSET_FIND_FLAG_FIND_CLEAR |\n+\t\t\t\t __RTE_BITSET_FIND_FLAG_WRAP);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Copy bitset.\n+ *\n+ * Copy the bits of the @c src_bitset to the @c dst_bitset.\n+ *\n+ * The bitsets may not overlap and must be of equal size.\n+ *\n+ * @param dst_bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param src_bitset\n+ *   A pointer to the array of words making up the bitset.\n+ * @param size\n+ *   The size of the bitsets (in bits).\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_copy(uint64_t *__rte_restrict dst_bitset,\n+\t\tconst uint64_t *__rte_restrict src_bitset,\n+\t\tsize_t size)\n+{\n+\trte_memcpy(dst_bitset, src_bitset, RTE_BITSET_SIZE(size));\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Bitwise or two bitsets.\n+ *\n+ * Perform a bitwise OR operation on all bits in the two equal-size\n+ * bitsets @c src_bitset0 and @c src_bitset1, and store the results in\n+ * @c dst_bitset.\n+ *\n+ * @param dst_bitset\n+ *   A pointer to the destination bitset.\n+ * @param src_bitset0\n+ *   A pointer to the first source bitset.\n+ * @param src_bitset1\n+ *   A pointer to the second source bitset.\n+ * @param size\n+ *   The size of the bitsets (in bits).\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_or(uint64_t *dst_bitset, const uint64_t *src_bitset0,\n+\t      const uint64_t *src_bitset1, size_t size)\n+{\n+\tsize_t i;\n+\n+\tfor (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++)\n+\t\tdst_bitset[i] = src_bitset0[i] | src_bitset1[i];\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Bitwise and two bitsets.\n+ *\n+ * Perform a bitwise AND operation on all bits in the two equal-size\n+ * bitsets @c src_bitset0 and @c src_bitset1, and store the result in\n+ * @c dst_bitset.\n+ *\n+ * @param dst_bitset\n+ *   A pointer to the destination bitset.\n+ * @param src_bitset0\n+ *   A pointer to the first source bitset.\n+ * @param src_bitset1\n+ *   A pointer to the second source bitset.\n+ * @param size\n+ *   The size of the bitsets (in bits).\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_and(uint64_t *dst_bitset, const uint64_t *src_bitset0,\n+\t       const uint64_t *src_bitset1, size_t size)\n+{\n+\tsize_t i;\n+\n+\tfor (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++)\n+\t\tdst_bitset[i] = src_bitset0[i] & src_bitset1[i];\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Bitwise xor two bitsets.\n+ *\n+ * Perform a bitwise XOR operation on all bits in the two equal-size\n+ * bitsets @c src_bitset0 and @c src_bitset1, and store the result in\n+ * @c dst_bitset.\n+ *\n+ * @param dst_bitset\n+ *   A pointer to the destination bitset.\n+ * @param src_bitset0\n+ *   A pointer to the first source bitset.\n+ * @param src_bitset1\n+ *   A pointer to the second source bitset.\n+ * @param size\n+ *   The size of the bitsets (in bits).\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_xor(uint64_t *dst_bitset, const uint64_t *src_bitset0,\n+\t       const uint64_t *src_bitset1, size_t size)\n+{\n+\tsize_t i;\n+\n+\tfor (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++)\n+\t\tdst_bitset[i] = src_bitset0[i] ^ src_bitset1[i];\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Compute the bitwise complement of a bitset.\n+ *\n+ * Flip every bit in the @c src_bitset, and store the result in @c\n+ * dst_bitset.\n+ *\n+ * @param dst_bitset\n+ *   A pointer to the destination bitset.\n+ * @param src_bitset\n+ *   A pointer to the source bitset.\n+ * @param size\n+ *   The size of the bitsets (in bits).\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_complement(uint64_t *dst_bitset, const uint64_t *src_bitset,\n+\t\t      size_t size)\n+{\n+\tsize_t i;\n+\n+\tfor (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++)\n+\t\tdst_bitset[i] = ~src_bitset[i];\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Shift bitset left.\n+ *\n+ * Perform a logical shift left of (multiply) @c src_bitset, and store\n+ * the result in @c dst_bitset.\n+ *\n+ * @param dst_bitset\n+ *   A pointer to the destination bitset.\n+ * @param src_bitset\n+ *   A pointer to the source bitset.\n+ * @param size\n+ *   The size of the bitsets (in bits).\n+ * @param shift_bits\n+ *   The number of bits to shift the bitset.\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_shift_left(uint64_t *dst_bitset, const uint64_t *src_bitset,\n+\t\t      size_t size, size_t shift_bits)\n+{\n+\tconst int src_word_offset = shift_bits / RTE_BITSET_WORD_BITS;\n+\tconst int src_bit_offset = shift_bits % RTE_BITSET_WORD_BITS;\n+\tunsigned int dst_idx;\n+\n+\tfor (dst_idx = 0; dst_idx < RTE_BITSET_NUM_WORDS(size); dst_idx++) {\n+\t\tint src_high_idx = dst_idx - src_word_offset;\n+\t\tuint64_t low_bits = 0;\n+\t\tuint64_t high_bits = 0;\n+\n+\t\tif (src_high_idx >= 0) {\n+\t\t\tint src_low_idx = src_high_idx - 1;\n+\n+\t\t\thigh_bits = src_bitset[src_high_idx] << src_bit_offset;\n+\n+\t\t\tif (src_bit_offset > 0 && src_low_idx >= 0)\n+\t\t\t\tlow_bits = src_bitset[src_low_idx] >>\n+\t\t\t\t\t(RTE_BITSET_WORD_BITS - src_bit_offset);\n+\t\t}\n+\t\tdst_bitset[dst_idx] = low_bits | high_bits;\n+\t}\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Shift bitset right.\n+ *\n+ * Perform a logical shift right of (divide) @c src_bitset, and store\n+ * the result in @c dst_bitset.\n+ *\n+ * @param dst_bitset\n+ *   A pointer to the destination bitset.\n+ * @param src_bitset\n+ *   A pointer to the source bitset.\n+ * @param size\n+ *   The size of the bitsets (in bits).\n+ * @param shift_bits\n+ *   The number of bits to shift the bitset.\n+ */\n+\n+__rte_experimental\n+static inline void\n+rte_bitset_shift_right(uint64_t *dst_bitset, const uint64_t *src_bitset,\n+\t\t       size_t size, size_t shift_bits)\n+{\n+\tconst int num_words = RTE_BITSET_NUM_WORDS(size);\n+\tconst uint64_t used_mask = __RTE_BITSET_USED_MASK(size);\n+\tconst int src_word_offset = shift_bits / RTE_BITSET_WORD_BITS;\n+\tconst int src_bit_offset = shift_bits % RTE_BITSET_WORD_BITS;\n+\tint dst_idx;\n+\n+\tfor (dst_idx = 0; dst_idx < num_words; dst_idx++) {\n+\t\tint src_low_idx = src_word_offset + dst_idx;\n+\t\tint src_high_idx = src_low_idx + 1;\n+\t\tuint64_t src_low_word_bits = 0;\n+\t\tuint64_t src_high_word_bits = 0;\n+\n+\t\tif (src_low_idx < num_words) {\n+\t\t\tsrc_low_word_bits = src_bitset[src_low_idx];\n+\n+\t\t\tif (src_low_idx == (num_words - 1))\n+\t\t\t\tsrc_low_word_bits &= used_mask;\n+\n+\t\t\tsrc_low_word_bits >>= src_bit_offset;\n+\n+\t\t\tif (src_bit_offset > 0 && src_high_idx < num_words) {\n+\t\t\t\tsrc_high_word_bits = src_bitset[src_high_idx];\n+\n+\t\t\t\tif (src_high_idx == (num_words - 1))\n+\t\t\t\t\tsrc_high_word_bits &= used_mask;\n+\n+\t\t\t\tsrc_high_word_bits <<=\n+\t\t\t\t\t(RTE_BITSET_WORD_BITS - src_bit_offset);\n+\t\t\t}\n+\t\t}\n+\t\tdst_bitset[dst_idx] = src_low_word_bits | src_high_word_bits;\n+\t}\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Compare two bitsets.\n+ *\n+ * Compare two bitsets for equality.\n+ *\n+ * @param bitset_a\n+ *   A pointer to the destination bitset.\n+ * @param bitset_b\n+ *   A pointer to the source bitset.\n+ * @param size\n+ *   The size of the bitsets (in bits).\n+ */\n+\n+__rte_experimental\n+static inline bool\n+rte_bitset_equal(const uint64_t *bitset_a, const uint64_t *bitset_b,\n+\t\t size_t size)\n+{\n+\tsize_t i;\n+\tuint64_t last_a, last_b;\n+\n+\tfor (i = 0; i < RTE_BITSET_NUM_WORDS(size) - 1; i++)\n+\t\tif (bitset_a[i] != bitset_b[i])\n+\t\t\treturn false;\n+\n+\tlast_a = bitset_a[i] << __RTE_BITSET_UNUSED(size);\n+\tlast_b = bitset_b[i] << __RTE_BITSET_UNUSED(size);\n+\n+\treturn last_a == last_b;\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Converts a bitset to a string.\n+ *\n+ * This function prints a string representation of the bitstring to\n+ * the supplied buffer.\n+ *\n+ * Each bit is represented either by '0' or '1' in the output, with\n+ * the first (left-most) character in the output being the most\n+ * significant bit. The resulting string is NUL terminated.\n+ *\n+ * @param bitset\n+ *   A pointer to the array of bitset 64-bit words.\n+ * @param size\n+ *   The number of bits the bitset represent.\n+ * @param buf\n+ *   A buffer to hold the output.\n+ * @param capacity\n+ *   The size of the buffer. Must be @c size + 1 or larger.\n+ * @return\n+ *   Returns the number of bytes written (i.e., @c size + 1), or -EINVAL\n+ *   in case the buffer capacity was too small.\n+ */\n+\n+__rte_experimental\n+ssize_t\n+rte_bitset_to_str(const uint64_t *bitset, size_t size, char *buf,\n+\t\t  size_t capacity);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* _RTE_BITSET_H_ */\ndiff --git a/lib/eal/version.map b/lib/eal/version.map\nindex 5e0cd47c82..639ccfe4b0 100644\n--- a/lib/eal/version.map\n+++ b/lib/eal/version.map\n@@ -393,6 +393,9 @@ EXPERIMENTAL {\n \t# added in 23.07\n \trte_memzone_max_get;\n \trte_memzone_max_set;\n+\n+\t# added in 24.03\n+\trte_bitset_to_str;\n };\n \n INTERNAL {\n",
    "prefixes": [
        "RFC",
        "v4",
        "1/4"
    ]
}