get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 139864,
    "url": "http://patchwork.dpdk.org/api/patches/139864/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20240505073313.118515-1-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": "<20240505073313.118515-1-mattias.ronnblom@ericsson.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20240505073313.118515-1-mattias.ronnblom@ericsson.com",
    "date": "2024-05-05T07:33:08",
    "name": "[RFC,v5,1/6] eal: add bitset type",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "d07f8951dbaddd32948210a8427acef11bc48b88",
    "submitter": {
        "id": 1077,
        "url": "http://patchwork.dpdk.org/api/people/1077/?format=api",
        "name": "Mattias Rönnblom",
        "email": "mattias.ronnblom@ericsson.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patchwork.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20240505073313.118515-1-mattias.ronnblom@ericsson.com/mbox/",
    "series": [
        {
            "id": 31881,
            "url": "http://patchwork.dpdk.org/api/series/31881/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=31881",
            "date": "2024-05-05T07:33:08",
            "name": "[RFC,v5,1/6] eal: add bitset type",
            "version": 5,
            "mbox": "http://patchwork.dpdk.org/series/31881/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/139864/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/139864/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 40C7943FAC;\n\tSun,  5 May 2024 09:43:59 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 1B6A340647;\n\tSun,  5 May 2024 09:43:42 +0200 (CEST)",
            "from EUR02-AM0-obe.outbound.protection.outlook.com\n (mail-am0eur02on2058.outbound.protection.outlook.com [40.107.247.58])\n by mails.dpdk.org (Postfix) with ESMTP id 669AC402DE\n for <dev@dpdk.org>; Sun,  5 May 2024 09:43:37 +0200 (CEST)",
            "from AM5PR0101CA0024.eurprd01.prod.exchangelabs.com\n (2603:10a6:206:16::37) by AS8PR07MB7384.eurprd07.prod.outlook.com\n (2603:10a6:20b:289::24) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7544.39; Sun, 5 May\n 2024 07:43:34 +0000",
            "from AM3PEPF00009B9C.eurprd04.prod.outlook.com\n (2603:10a6:206:16:cafe::fe) by AM5PR0101CA0024.outlook.office365.com\n (2603:10a6:206:16::37) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7544.40 via Frontend\n Transport; Sun, 5 May 2024 07:43:34 +0000",
            "from oa.msg.ericsson.com (192.176.1.74) by\n AM3PEPF00009B9C.mail.protection.outlook.com (10.167.16.21) with Microsoft\n SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.20.7544.18 via Frontend Transport; Sun, 5 May 2024 07:43:34 +0000",
            "from seliicinfr00049.seli.gic.ericsson.se (153.88.142.248) by\n smtp-central.internal.ericsson.com (100.87.178.66) with Microsoft SMTP Server\n id 15.2.1544.9; Sun, 5 May 2024 09:43:32 +0200",
            "from breslau.. (seliicwb00002.seli.gic.ericsson.se [10.156.25.100])\n by seliicinfr00049.seli.gic.ericsson.se (Postfix) with ESMTP id\n 079CC38007A; Sun,  5 May 2024 09:43:32 +0200 (CEST)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=CHV2nx0q8BD6nhpVv6sTu9Ua5Kpprn2oqvG+afk1vt8CyZPzsGT2zDPC9IrrLvqRDOnt/rOsu2Cu9gC1WrPyIu+7R14Jlo+38sgfGZa7CcPGTyGNuQMj+I7/vIUMSLAqbVVsk+3R70GD4V9GnGkJ7JoVkXHkkbIy4RcTHDdAhWvuIfnuYmquVWWqiRuanO26Lfr5Fyu8l3BvDEY0Z5/W6ZF9azK1wfn48PYLyrlkVpJJ3nlJ3hw9FcGgt6v2fMvxVFl4HXOs9RbxMw9gjlFuTtb5w4r9e9QS4I6aKGBB98sunoZJFPAOFjJMNiXklGoktsa6UtXTxZMKK6aNLymDPQ==",
        "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=25zFeH5qAZJpWPxBUYFWpgHUkxk41okgz7mGFvGIbL8=;\n b=D89qWK2n0MqFDHXfuTSZhbQQzkACWckd03uUuiZUtXXeVNZc+weXbySx1ibBQkNk2pA6yImycLLe2BVNPRThIuhXn5DRdqMuBuNYcKxp0uA848NWwIVMalaHfqHAkQnwqJG6ADK8CG0eLEuQibhnCYCzLVz/4HGUjBjNsWgeXXT/7FZkTIlA7unOWkQt+v8wdsh/oVT80pmm2G9BA/qYrSCmNEsVvl9BtpJE2Ykeu4A27Y/cQmOKb51P3wI4DyKxCw9X7+MddVT7kaNu+TZ1YJ5KZvaK2JjB24JEBQ8stY4dfVnYVG95wKa7AZ30Kt8xgcMJzkpbeJiLU1OKhmYPNQ==",
        "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=25zFeH5qAZJpWPxBUYFWpgHUkxk41okgz7mGFvGIbL8=;\n b=L4gitdVprvdajJp1A4DqSRo9o7TMoPM4Zk8+xmSenhyVZmDCY6tYu988sC//wtgGZWVDQhCDAjoQmJ9opmHu8yMELTrEzruLWSJNjT24k8+DlS22kOr4eLkqAoCVZOGVY1l3SkbcGzOgd+Iw/PX0DxNdWE595iIYE2pt4yptWDqSrOIWXnD3pJZblpuG7bj2lyBZUR2gD8CvBOW03TyxQfnBsKDwUsEI6mMadp7zPyG0JnSqOl9MooaJsB5XoMQJE6AEXIEArMteZs2LnrzigLDwJJIjjXYObjwBdMuXH76tTdY+aR4+SJmnDp3N3FB6/ni6rWecNrfgHwCDIjbF5Q==",
        "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 v5 1/6] eal: add bitset type",
        "Date": "Sun, 5 May 2024 09:33:08 +0200",
        "Message-ID": "<20240505073313.118515-1-mattias.ronnblom@ericsson.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20240216102348.480407-1-mattias.ronnblom@ericsson.com>",
        "References": "<20240216102348.480407-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": "AM3PEPF00009B9C:EE_|AS8PR07MB7384:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "f16aadfc-658f-4bf8-d32f-08dc6cd71169",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;\n ARA:13230031|1800799015|376005|36860700004|82310400017;",
        "X-Microsoft-Antispam-Message-Info": "=?utf-8?q?IFT6MyWC32wiCK0y6psvc6hdUzXVOWF?=\n\t=?utf-8?q?q/OrItqlIAxKAfcLdx14xl4F14ithWy8XO/aVyCbHe0OlQV3ja0N82oHPI0ylJXO1?=\n\t=?utf-8?q?BadKeZxUHJ/LxzRmVvkzRiMT2C7QGm1HaB0AGjSdgGWWmj1s8JxkXKye+KUPZjtVe?=\n\t=?utf-8?q?Y+cyvHX9OPmACR93JrwZl57lki3Ng9W8RrylNqZorXjKh6mfbywomJ6K+ieLguSvV?=\n\t=?utf-8?q?ljxDZP7rwMV9nH0uQ3rPKM+UKpCRTb9MdacZOKFLb7Kyr5JWJoQtyQzKQBh5gAUZq?=\n\t=?utf-8?q?NwDba/B8lpLXr0ns8X9TXrhE3QL17beq9rgytP/z+kSEeE/4lbkEe9ql0ts3b6e6I?=\n\t=?utf-8?q?oVoUW4fARsxUyRH0bQYjj9LnOFv35ro7dUf+WtpXDvHyYjXGs2mMQ7+WfESxe+Wz6?=\n\t=?utf-8?q?+uz2kN5GRSqQBTEcT9+wfBsuZkJaiTxo3vUKYv/GhvcqwdE6VXiS3Jjehr130Vwl7?=\n\t=?utf-8?q?5tCyPCDvXSzzXeme0FwakbGKKEGUFjkqjTM58WDVdg6fY1QJbP6QQ1tnQ981gJfgz?=\n\t=?utf-8?q?WZZKhbaS7IkEGhBrCOmrV+B6YZl1is7DqHZoO1f98HeR5amAk77dvja0+eq6Y7N4e?=\n\t=?utf-8?q?OvJePuZiXdDoYdDUI5Y3t7LTL/AvZFghwK6wATXlvHC+HhXB31rISXjDuvHuPCegr?=\n\t=?utf-8?q?mODezP+XTxmc6nDxNpecCfdtTMFnLANR8PNYMp4NnwwkZ4ZjDbUvKF0bjUt8y3YFB?=\n\t=?utf-8?q?gNeicTcO/4Q3oiyxt2Vk4Tzckd8tUiIyc3MqbIePAQxc9rFIIOTfWUlSTJLFxcH9u?=\n\t=?utf-8?q?eSPb+7WMBpPhfoX4LYS+4AQ18KNlxpBQIfsefKs1cnetr5fMtYufp/grV2czAp1EC?=\n\t=?utf-8?q?Saz4XR4SGTGr2ACB7KPiF8krgL5HOdk8dqMHU8633gY+pOjgz3LBCbxPbWdYSkbmJ?=\n\t=?utf-8?q?cHHWr0vUD0gCCr1dlvLj3b7pLTXMkGjokjAQfpyKzcwNNintQgSi/T5l0CEjH7tp2?=\n\t=?utf-8?q?nQq3ZB4xJCNQ0H5Gtx+75UtXCHe2D9zv07Yki3nmpTS/tks6/5txnq8WtpaoN7Hly?=\n\t=?utf-8?q?Pqt2RBTxr1oRTpPfxHoL6JiJ/s0UAPh+Okq7hEu00Ro/WkE29CoATTE8Jna81x1sI?=\n\t=?utf-8?q?4EmwIt65kKsuXYlMLKvsOsXmI87DoMSMy6GZrp0FOK/aWVXt7/vYuNFLTk3iG+cNN?=\n\t=?utf-8?q?+7sjDg9Q1Za0lb1U3ng1UMPXVTCQw2XmfKxT65s+1GOcH0mw2ew0XyTZ5KVXtJpgU?=\n\t=?utf-8?q?+oNxCg1BniFHYhRTxmv5p2fCCNb7dTE3wvvkTdGjcu3SfAddb3Bq4oYwNjSTqqAY6?=\n\t=?utf-8?q?qvpX9Y0zEqEa/sfxay7UwTkNrZ0vid3PkBS0nK/0ZkfE39U0QtB7iTsE=3D?=",
        "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; SFS:(13230031)(1800799015)(376005)(36860700004)(82310400017);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "ericsson.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "05 May 2024 07:43:34.5059 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n f16aadfc-658f-4bf8-d32f-08dc6cd71169",
        "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 AM3PEPF00009B9C.eurprd04.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "AS8PR07MB7384",
        "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\nDepends-on: series-31863 (\"Improve EAL bit operations API\")\n\nRFC v5:\n * Delegate bit test/set/clear/assign/flip to RTE bitops.\n * Note in the documentation that set/clear/assign/flip are not\n   atomic.\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 doc/api/doxy-api-index.md    |    1 +\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 | 1061 ++++++++++++++++++++++++++++++++++\n lib/eal/version.map          |    2 +\n 6 files changed, 1095 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/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md\nindex 8c1eb8fafa..1ce04a8edf 100644\n--- a/doc/api/doxy-api-index.md\n+++ b/doc/api/doxy-api-index.md\n@@ -173,6 +173,7 @@ The public API headers are grouped by topics:\n   [ring](@ref rte_ring.h),\n   [stack](@ref rte_stack.h),\n   [tailq](@ref rte_tailq.h),\n+  [bitset](@ref rte_bitset.h),\n   [bitmap](@ref rte_bitmap.h)\n \n - **packet framework**:\ndiff --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..49a07c77b8\n--- /dev/null\n+++ b/lib/eal/include/rte_bitset.h\n@@ -0,0 +1,1061 @@\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+#define __RTE_BITSET_DELEGATE_N(fun, bitset, bit_num, ...)\t\t\\\n+\tfun(&(bitset)[__RTE_BITSET_WORD_IDX(bit_num)],\t\t\t\\\n+\t    __RTE_BITSET_BIT_OFFSET(bit_num), __VA_ARGS__)\n+\n+/* MSVC doesn't have ##__VA_ARGS__, so argument-less -> special case */\n+#define __RTE_BITSET_DELEGATE(fun, bitset, bit_num)\t\t\t\\\n+\tfun(&(bitset)[__RTE_BITSET_WORD_IDX(bit_num)],\t\t\t\\\n+\t    __RTE_BITSET_BIT_OFFSET(bit_num))\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+#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+ * 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+\treturn __RTE_BITSET_DELEGATE(rte_bit_test, bitset, bit_num);\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+ * The operation is not guaranteed to be atomic.\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+\t__RTE_BITSET_DELEGATE(rte_bit_set, bitset, bit_num);\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+ * The operation is not guaranteed to be atomic.\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+\t__RTE_BITSET_DELEGATE(rte_bit_clear, bitset, bit_num);\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+ * The operation is not guaranteed to be atomic.\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+\t__RTE_BITSET_DELEGATE_N(rte_bit_assign, bitset, bit_num, bit_value);\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+ * The operation is not guaranteed to be atomic.\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+\t__RTE_BITSET_DELEGATE(rte_bit_flip, bitset, bit_num);\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+#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 3df50c3fbb..254d3fd4b2 100644\n--- a/lib/eal/version.map\n+++ b/lib/eal/version.map\n@@ -396,6 +396,8 @@ EXPERIMENTAL {\n \n \t# added in 24.03\n \trte_vfio_get_device_info; # WINDOWS_NO_EXPORT\n+\n+\trte_bitset_to_str;\n };\n \n INTERNAL {\n",
    "prefixes": [
        "RFC",
        "v5",
        "1/6"
    ]
}