get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 118900,
    "url": "https://patches.dpdk.org/api/patches/118900/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1666339323-24016-5-git-send-email-chaoyong.he@corigine.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": "<1666339323-24016-5-git-send-email-chaoyong.he@corigine.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1666339323-24016-5-git-send-email-chaoyong.he@corigine.com",
    "date": "2022-10-21T08:01:40",
    "name": "[v6,04/27] net/nfp: add the structures and functions for flow offload",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "1faf6e86047a1366a0b214bd920b5759a0b5b0b4",
    "submitter": {
        "id": 2554,
        "url": "https://patches.dpdk.org/api/people/2554/?format=api",
        "name": "Chaoyong He",
        "email": "chaoyong.he@corigine.com"
    },
    "delegate": {
        "id": 319,
        "url": "https://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1666339323-24016-5-git-send-email-chaoyong.he@corigine.com/mbox/",
    "series": [
        {
            "id": 25363,
            "url": "https://patches.dpdk.org/api/series/25363/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=25363",
            "date": "2022-10-21T08:01:36",
            "name": "add the basic rte_flow offload support of nfp PMD",
            "version": 6,
            "mbox": "https://patches.dpdk.org/series/25363/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/118900/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/118900/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 27366A0032;\n\tFri, 21 Oct 2022 10:02:52 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 9197A42BD9;\n\tFri, 21 Oct 2022 10:02:33 +0200 (CEST)",
            "from NAM10-MW2-obe.outbound.protection.outlook.com\n (mail-mw2nam10on2092.outbound.protection.outlook.com [40.107.94.92])\n by mails.dpdk.org (Postfix) with ESMTP id 4502D42BD1\n for <dev@dpdk.org>; Fri, 21 Oct 2022 10:02:31 +0200 (CEST)",
            "from SJ0PR13MB5545.namprd13.prod.outlook.com (2603:10b6:a03:424::5)\n by DM6PR13MB4493.namprd13.prod.outlook.com (2603:10b6:5:1b9::16) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5723.22; Fri, 21 Oct\n 2022 08:02:29 +0000",
            "from SJ0PR13MB5545.namprd13.prod.outlook.com\n ([fe80::7c26:1a0b:2825:6f4b]) by SJ0PR13MB5545.namprd13.prod.outlook.com\n ([fe80::7c26:1a0b:2825:6f4b%4]) with mapi id 15.20.5723.014; Fri, 21 Oct 2022\n 08:02:29 +0000"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=DlhC0EqNTjzW2/FPBHe596e4sLtLPyqh9/WE/zGquxdWvqnlOAwn6SJSwqRkNWu+3Q4en3l1vbzUMzvhmwxPTkR3xtUCije/WPJPSqCoVpjqeJK5zRcbLGNrMWoQZwAI7fsmdoRxB7Ke9CxRn2eS5peH+2EKYKeYEB8HiKrLtS5GByzkEwdChW6sKLVmzrRWYlOqPqsoxpAKzHVSfWU2vCmrStmZ/qwX7zdEnJ8mm4T9P6USwjmehbk+2R7V1DikBpVL1oQ8eUztkRcxnPszyjvZso/DqecnjuyI8cU4TwyrvWt5IVqj88yY3N080Y+Yf2dXq+2yjpt3aCTstS0M4w==",
        "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=erg4ckLzV3FPjzs2cULbkRnA+wEVH6qqI6NjATIrr14=;\n b=liDOlnMUjKfzsjF8OVDQ15MvA4BxdvfFZAVoHY7nNprLbDaHXR/vY31SAXRcKJFMBWRgtkhlFT+ppBkLL1NFqzHg+pmyOsQ76ZXL+0pfRTQEvrHQo7J4MRtDxWHaJAiIeCv4hmAP8KALOwtKw0pR1LFG8axqFIHdGQXCfwiWnpelQ9mkRoqofACMqAXh0NSgHJQQZgO2w2MDPD2JtYsTht+OAo8vqMaTSgesdNWBn5CkmffcyLUXFDE5vQ0N6X3C8iXv0GAzyZenfk9Eitj5X8XHZ1WeN36KLkDnXM8OOBRC6KXAKsrnJv2s8UXPWC3OykQ4cL+XP6Nw3AzO8Nefog==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass\n smtp.mailfrom=corigine.com; dmarc=pass action=none header.from=corigine.com;\n dkim=pass header.d=corigine.com; arc=none",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=corigine.onmicrosoft.com; s=selector2-corigine-onmicrosoft-com;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=erg4ckLzV3FPjzs2cULbkRnA+wEVH6qqI6NjATIrr14=;\n b=v2IrY4kCxDENTfljFsf1Bl/7bX3kI2MmuL2mXyhgk5TbZjWmOFNF2RGwYVJdr6dQcvzk55zzQpJ9kLjjWBO9yzQvEwL8fW0viTBBv3GXwbgcHQryun5HyfUtdTt0J1rQIkkgKSi4xooihjvep0XLdTEg+1E77zzGPOOlob/eQBw=",
        "Authentication-Results": "dkim=none (message not signed)\n header.d=none;dmarc=none action=none header.from=corigine.com;",
        "From": "Chaoyong He <chaoyong.he@corigine.com>",
        "To": "dev@dpdk.org",
        "Cc": "oss-drivers@corigine.com, niklas.soderlund@corigine.com,\n Chaoyong He <chaoyong.he@corigine.com>",
        "Subject": "[PATCH v6 04/27] net/nfp: add the structures and functions for flow\n offload",
        "Date": "Fri, 21 Oct 2022 16:01:40 +0800",
        "Message-Id": "<1666339323-24016-5-git-send-email-chaoyong.he@corigine.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1666339323-24016-1-git-send-email-chaoyong.he@corigine.com>",
        "References": "<1666232391-29152-1-git-send-email-chaoyong.he@corigine.com>\n <1666339323-24016-1-git-send-email-chaoyong.he@corigine.com>",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "X-ClientProxiedBy": "SI2PR01CA0051.apcprd01.prod.exchangelabs.com\n (2603:1096:4:193::6) To SJ0PR13MB5545.namprd13.prod.outlook.com\n (2603:10b6:a03:424::5)",
        "MIME-Version": "1.0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "SJ0PR13MB5545:EE_|DM6PR13MB4493:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "e103497b-7289-4a35-7777-08dab33a99a8",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n emZ5GqCDESCtPOqrdi/yzQytOKXK0DwKETts6PHVm9/hKBR86uoGgu/RHU/V/LSUgqKhj1zRfVQxLzprtWCtt3A6J8UQOPYoA22khkz5DB9K0uTeFfF0cLniPXfRm483J4H3vmNQitaN+gz9LTVFDExpllQdFPaPZ92dAB3sBqNc1yaMrojX5eCJFZGSHbm5GqAamrUW6Kjusb2l+IWyljypw5Vr129neT0Gcj+K/yftvUyAt0H0rOz8VerUdoIpaJIk9xo+Bkll9/K2YtIf1vMFdc9Ws1vLG2HB9wiUBm2K6AOBscTkniI/UvLgcLM+EO63184NgRWgV7rRHhYRpVXkgbEQpOrJP8Rn++pbGRyRL2Mte+4PDsiOhYP8W4+CN0ds3CtXBDHE/Gp2bC2V5eft4IozdjJukDJtLvtfzkJPgCLWWFc2nf3mBnGt2fbg0e7PoiXCAd+/2GvW1SkgsXkd9zcvbiOMU1EouscRHA8hhR0MErg2guteqdszrDuIPExy72vhSsTisui6IXTngh812dzEaKkUIUTRMWNf4BwmWcN1jECF1grB9TGJuw2PoUbXcX/+t6kV74oSFkRYpEB2CinrBeTcAZJxU3U4bSvMnaK7SbUrAxkis8mmZGfJ2pNVq4SJG0+icpQVt427CSwG7CyidZDwAbYqWinCJbIg0VQ5iGeAukylgWmRUySyoYahwq9AoEjKrqrXg7uC1LWZl0KuDduyRBYYOszB+RHDE2ct9Me4LuRlPsARoYPa7LCBPbEtWG/b6rlcX8W0VA==",
        "X-Forefront-Antispam-Report": "CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;\n IPV:NLI; SFV:NSPM; H:SJ0PR13MB5545.namprd13.prod.outlook.com; PTR:; CAT:NONE;\n SFS:(13230022)(4636009)(346002)(366004)(136003)(396003)(376002)(39830400003)(451199015)(36756003)(30864003)(8936002)(66556008)(86362001)(41300700001)(478600001)(83380400001)(2906002)(5660300002)(186003)(6916009)(38350700002)(2616005)(4326008)(6512007)(66574015)(66476007)(52116002)(66946007)(316002)(8676002)(6666004)(6506007)(26005)(107886003)(38100700002)(6486002)(44832011);\n DIR:OUT; SFP:1102;",
        "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1",
        "X-MS-Exchange-AntiSpam-MessageData-0": "=?utf-8?q?sJqhSGnHLnGXJ1RxWv9swJZR5EQR?=\n\t=?utf-8?q?FBHaOBGWTdq8AzoE4o8WqNRUIKUCA1gx1sA51NLEKjo+gpqhUSfh5BetYyWBwqEXn?=\n\t=?utf-8?q?r1cYQqBLyxLbWK9TgfBr7LYnraAj851QiSa/qZikpdmw0RWbLrOUTQWG+r5Vgage7?=\n\t=?utf-8?q?sp1z5nDynnynCrmv54zjBZCOReFtcYs800UL5w96eB5481qlXw75eKPdwwiXyKoFJ?=\n\t=?utf-8?q?Qwkz/05p91a/JA+/0HMngNqbqEReTmDKW6nCeQHCwclDUSRT3mzvthl4AWvNOiMP/?=\n\t=?utf-8?q?MH2I+Ln7WJIfsUwmvDuxe8wexslz9mln+WBqvESCIq1JjHDHqpK2vc7wypfP9VXAW?=\n\t=?utf-8?q?UjOXSqwOOoDFOej5CvFE8eRouGrldmtMlWrkFnKAlRS6GdU7YzaE943DMDnbSTKuU?=\n\t=?utf-8?q?wXXek+TWwX4OPvcMAe+2cgnrgOrd4bzUgraT6pWYd+KMaBmKAcU0hABSZNmJ+Av+M?=\n\t=?utf-8?q?DtFG3BFXts/Kq/emlG1dOp6MbN5CU1ckfznAKwGVqfTKb4OH+aB5VErbDPNzOVg1j?=\n\t=?utf-8?q?F4JzbUCDgG/+l/wt7p0YG6ET1vSxZfai0Njb24pIal3p6+jySlZDngfIBVDtuDwiQ?=\n\t=?utf-8?q?0iN6sjzaLaVoIwVShiYHpsycnhpiMkiMPBuaE1I7bduoFGy7KnMMT6dcd/z5wyv1n?=\n\t=?utf-8?q?+bWV+A7MfUvB3bPHDf8idr67R2BtOSsorg4jdj9C7CU3xA0Z8KepA6PXzLtZ6rCrC?=\n\t=?utf-8?q?TqgwU4xDT80YBwZpzcPu0Pd3xdMJu5b0vBV991tGVfwbwI9x5hknl9JstkUU2tJyW?=\n\t=?utf-8?q?oX9f2esKJ7MyleGGruYCMZeAM8mbd2jk2HDPkb8dIzqXa2K4g6VFy5Cl+hdnRrIuu?=\n\t=?utf-8?q?vA4hryQ9t2SN1isPlLVTLjzFn9ms0ETrixMCMLhLiPn1ZrilF21RnVGfJCJItbIAG?=\n\t=?utf-8?q?KGPY32d1PtR1AlYHlgMQnMv4QITsXo5IaYBT4WSxWvcc04G4lq53pw37pryqkw2c6?=\n\t=?utf-8?q?D/z4kJnaA2bsLDja3qxWciXbvsy41OpCngTsaOxNG+fW4g3oOCqnC3fsJk4fKkcim?=\n\t=?utf-8?q?zk52XFre+DD+mPohlHvSi+EVAr3M+pdSjKWXgYiGPoDVS+/3ehjHnjxwwlwUcp/wX?=\n\t=?utf-8?q?wQWaQWKwESB7Ic3RotFK+5uAC79m8KJ9qFTVPTDyl6oKgT9lJfw6x5TnVIqb9+p9v?=\n\t=?utf-8?q?wcUb+SPK1A821eyznPhjTmdeyGw5uIEoJNpZhL6lWFKWSkIH/92RlH/u7nMEqnh/y?=\n\t=?utf-8?q?veYlPl5uahGj1xBgP1JMW1Y+4+VMnmLQ519qEY7lTSquiNJlMgQb/z59+1GNfUizh?=\n\t=?utf-8?q?9z4FF9Dhl8pUIm1pewaCibxM8iF6/x1awiBzqLVML5qg/sTsLrnH0LFv8yH98RkSg?=\n\t=?utf-8?q?J052zSGjGMUJ5PvRsFVCjvKIxmnO58RjbRYN+gXZWYmrH3upF32v7dfCFZP7PVvUU?=\n\t=?utf-8?q?mHKiKpaM+zEBLM6Rehnh4gwesjkS4JD6HSnvktxMYRtxlHT9DQXKZSfLERI2ekdMa?=\n\t=?utf-8?q?xQ56aft61q0iKIf/2FXHP3JwC1sMcDg4ob7csAky1sRTvvvG+dOdMWzlzB3PTg/k9?=\n\t=?utf-8?q?+8YKIXsoBldJQMfzz2+rMbU42MC9l0bcyw=3D=3D?=",
        "X-OriginatorOrg": "corigine.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n e103497b-7289-4a35-7777-08dab33a99a8",
        "X-MS-Exchange-CrossTenant-AuthSource": "SJ0PR13MB5545.namprd13.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Internal",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "21 Oct 2022 08:02:29.5182 (UTC)",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "Hosted",
        "X-MS-Exchange-CrossTenant-Id": "fe128f2c-073b-4c20-818e-7246a585940c",
        "X-MS-Exchange-CrossTenant-MailboxType": "HOSTED",
        "X-MS-Exchange-CrossTenant-UserPrincipalName": "\n T6y0wcQsaG1e+BqKEb21juW9Ecafg1pUOraAAyeaiDyoyYNJWDPnPv4bm7q/pLa+TSNXMp/i3CORDkd2O0EvKuS+Q3bbgUqhqe4iIS66a2M=",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "DM6PR13MB4493",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "Add the structures and functions to process mask table, flow\ntable, and flow stats id, which are used in the rte_flow\noffload logics.\n\nSigned-off-by: Chaoyong He <chaoyong.he@corigine.com>\nReviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>\n---\n drivers/net/nfp/flower/nfp_flower.c |  11 +-\n drivers/net/nfp/flower/nfp_flower.h |   2 +\n drivers/net/nfp/meson.build         |   3 +\n drivers/net/nfp/nfp_flow.c          | 496 ++++++++++++++++++++++++++++++++++++\n drivers/net/nfp/nfp_flow.h          | 104 ++++++++\n 5 files changed, 615 insertions(+), 1 deletion(-)\n create mode 100644 drivers/net/nfp/nfp_flow.c\n create mode 100644 drivers/net/nfp/nfp_flow.h",
    "diff": "diff --git a/drivers/net/nfp/flower/nfp_flower.c b/drivers/net/nfp/flower/nfp_flower.c\nindex 1db085e..41b0fe2 100644\n--- a/drivers/net/nfp/flower/nfp_flower.c\n+++ b/drivers/net/nfp/flower/nfp_flower.c\n@@ -15,6 +15,7 @@\n #include \"../nfp_ctrl.h\"\n #include \"../nfp_cpp_bridge.h\"\n #include \"../nfp_rxtx.h\"\n+#include \"../nfp_flow.h\"\n #include \"../nfpcore/nfp_mip.h\"\n #include \"../nfpcore/nfp_rtsym.h\"\n #include \"../nfpcore/nfp_nsp.h\"\n@@ -1090,13 +1091,19 @@\n \n \tpf_dev->app_fw_priv = app_fw_flower;\n \n+\tret = nfp_flow_priv_init(pf_dev);\n+\tif (ret != 0) {\n+\t\tPMD_INIT_LOG(ERR, \"init flow priv failed\");\n+\t\tgoto app_cleanup;\n+\t}\n+\n \t/* Allocate memory for the PF AND ctrl vNIC here (hence the * 2) */\n \tpf_hw = rte_zmalloc_socket(\"nfp_pf_vnic\", 2 * sizeof(struct nfp_net_adapter),\n \t\t\tRTE_CACHE_LINE_SIZE, numa_node);\n \tif (pf_hw == NULL) {\n \t\tPMD_INIT_LOG(ERR, \"Could not malloc nfp pf vnic\");\n \t\tret = -ENOMEM;\n-\t\tgoto app_cleanup;\n+\t\tgoto flow_priv_cleanup;\n \t}\n \n \t/* Map the PF ctrl bar */\n@@ -1174,6 +1181,8 @@\n \tnfp_cpp_area_free(pf_dev->ctrl_area);\n vnic_cleanup:\n \trte_free(pf_hw);\n+flow_priv_cleanup:\n+\tnfp_flow_priv_uninit(pf_dev);\n app_cleanup:\n \trte_free(app_fw_flower);\n \ndiff --git a/drivers/net/nfp/flower/nfp_flower.h b/drivers/net/nfp/flower/nfp_flower.h\nindex 8521ae4..12a0fb5 100644\n--- a/drivers/net/nfp/flower/nfp_flower.h\n+++ b/drivers/net/nfp/flower/nfp_flower.h\n@@ -54,6 +54,8 @@ struct nfp_app_fw_flower {\n \n \t/* service id of ctrl vnic service */\n \tuint32_t ctrl_vnic_id;\n+\n+\tstruct nfp_flow_priv *flow_priv;\n };\n \n int nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev);\ndiff --git a/drivers/net/nfp/meson.build b/drivers/net/nfp/meson.build\nindex 8a63979..7416fd3 100644\n--- a/drivers/net/nfp/meson.build\n+++ b/drivers/net/nfp/meson.build\n@@ -27,4 +27,7 @@ sources = files(\n         'nfp_cpp_bridge.c',\n         'nfp_ethdev_vf.c',\n         'nfp_ethdev.c',\n+        'nfp_flow.c',\n )\n+\n+deps += ['hash']\ndiff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c\nnew file mode 100644\nindex 0000000..dd690cd\n--- /dev/null\n+++ b/drivers/net/nfp/nfp_flow.c\n@@ -0,0 +1,496 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright (c) 2022 Corigine, Inc.\n+ * All rights reserved.\n+ */\n+\n+#include <rte_flow_driver.h>\n+#include <rte_hash.h>\n+#include <rte_jhash.h>\n+#include <bus_pci_driver.h>\n+\n+#include \"nfp_common.h\"\n+#include \"nfp_flow.h\"\n+#include \"nfp_logs.h\"\n+#include \"flower/nfp_flower.h\"\n+#include \"nfpcore/nfp_mip.h\"\n+#include \"nfpcore/nfp_rtsym.h\"\n+\n+struct nfp_mask_id_entry {\n+\tuint32_t hash_key;\n+\tuint32_t ref_cnt;\n+\tuint8_t mask_id;\n+};\n+\n+static int\n+nfp_mask_id_alloc(struct nfp_flow_priv *priv, uint8_t *mask_id)\n+{\n+\tuint8_t temp_id;\n+\tuint8_t freed_id;\n+\tstruct circ_buf *ring;\n+\n+\t/* Checking for unallocated entries first. */\n+\tif (priv->mask_ids.init_unallocated > 0) {\n+\t\t*mask_id = priv->mask_ids.init_unallocated;\n+\t\tpriv->mask_ids.init_unallocated--;\n+\t\treturn 0;\n+\t}\n+\n+\t/* Checking if buffer is empty. */\n+\tfreed_id = NFP_FLOWER_MASK_ENTRY_RS - 1;\n+\tring = &priv->mask_ids.free_list;\n+\tif (ring->head == ring->tail) {\n+\t\t*mask_id = freed_id;\n+\t\treturn -ENOENT;\n+\t}\n+\n+\trte_memcpy(&temp_id, &ring->buf[ring->tail], NFP_FLOWER_MASK_ELEMENT_RS);\n+\t*mask_id = temp_id;\n+\n+\trte_memcpy(&ring->buf[ring->tail], &freed_id, NFP_FLOWER_MASK_ELEMENT_RS);\n+\tring->tail = (ring->tail + NFP_FLOWER_MASK_ELEMENT_RS) %\n+\t\t\t(NFP_FLOWER_MASK_ENTRY_RS * NFP_FLOWER_MASK_ELEMENT_RS);\n+\n+\treturn 0;\n+}\n+\n+static int\n+nfp_mask_id_free(struct nfp_flow_priv *priv, uint8_t mask_id)\n+{\n+\tstruct circ_buf *ring;\n+\n+\tring = &priv->mask_ids.free_list;\n+\n+\t/* Checking if buffer is full. */\n+\tif (CIRC_SPACE(ring->head, ring->tail, NFP_FLOWER_MASK_ENTRY_RS) == 0)\n+\t\treturn -ENOBUFS;\n+\n+\trte_memcpy(&ring->buf[ring->head], &mask_id, NFP_FLOWER_MASK_ELEMENT_RS);\n+\tring->head = (ring->head + NFP_FLOWER_MASK_ELEMENT_RS) %\n+\t\t\t(NFP_FLOWER_MASK_ENTRY_RS * NFP_FLOWER_MASK_ELEMENT_RS);\n+\n+\treturn 0;\n+}\n+\n+static int\n+nfp_mask_table_add(struct nfp_flow_priv *priv,\n+\t\tchar *mask_data,\n+\t\tuint32_t mask_len,\n+\t\tuint8_t *id)\n+{\n+\tint ret;\n+\tuint8_t mask_id;\n+\tuint32_t hash_key;\n+\tstruct nfp_mask_id_entry *mask_entry;\n+\n+\tmask_entry = rte_zmalloc(\"mask_entry\", sizeof(struct nfp_mask_id_entry), 0);\n+\tif (mask_entry == NULL) {\n+\t\tret = -ENOMEM;\n+\t\tgoto exit;\n+\t}\n+\n+\tret = nfp_mask_id_alloc(priv, &mask_id);\n+\tif (ret != 0)\n+\t\tgoto mask_entry_free;\n+\n+\thash_key = rte_jhash(mask_data, mask_len, priv->hash_seed);\n+\tmask_entry->mask_id  = mask_id;\n+\tmask_entry->hash_key = hash_key;\n+\tmask_entry->ref_cnt  = 1;\n+\tPMD_DRV_LOG(DEBUG, \"hash_key=%#x id=%u ref=%u\", hash_key,\n+\t\t\tmask_id, mask_entry->ref_cnt);\n+\n+\tret = rte_hash_add_key_data(priv->mask_table, &hash_key, mask_entry);\n+\tif (ret != 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Add to mask table failed.\");\n+\t\tgoto mask_id_free;\n+\t}\n+\n+\t*id = mask_id;\n+\treturn 0;\n+\n+mask_id_free:\n+\tnfp_mask_id_free(priv, mask_id);\n+mask_entry_free:\n+\trte_free(mask_entry);\n+exit:\n+\treturn ret;\n+}\n+\n+static int\n+nfp_mask_table_del(struct nfp_flow_priv *priv,\n+\t\tchar *mask_data,\n+\t\tuint32_t mask_len,\n+\t\tuint8_t id)\n+{\n+\tint ret;\n+\tuint32_t hash_key;\n+\n+\thash_key = rte_jhash(mask_data, mask_len, priv->hash_seed);\n+\tret = rte_hash_del_key(priv->mask_table, &hash_key);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Delete from mask table failed.\");\n+\t\treturn ret;\n+\t}\n+\n+\tret = nfp_mask_id_free(priv, id);\n+\tif (ret != 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Free mask id failed.\");\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static struct nfp_mask_id_entry *\n+nfp_mask_table_search(struct nfp_flow_priv *priv,\n+\t\tchar *mask_data,\n+\t\tuint32_t mask_len)\n+{\n+\tint index;\n+\tuint32_t hash_key;\n+\tstruct nfp_mask_id_entry *entry;\n+\n+\thash_key = rte_jhash(mask_data, mask_len, priv->hash_seed);\n+\tindex = rte_hash_lookup_data(priv->mask_table, &hash_key, (void **)&entry);\n+\tif (index < 0) {\n+\t\tPMD_DRV_LOG(DEBUG, \"Data NOT found in the mask table.\");\n+\t\treturn NULL;\n+\t}\n+\n+\treturn entry;\n+}\n+\n+__rte_unused static bool\n+nfp_check_mask_add(struct nfp_flow_priv *priv,\n+\t\tchar *mask_data,\n+\t\tuint32_t mask_len,\n+\t\tuint8_t *meta_flags,\n+\t\tuint8_t *mask_id)\n+{\n+\tint ret;\n+\tstruct nfp_mask_id_entry *mask_entry;\n+\n+\tmask_entry = nfp_mask_table_search(priv, mask_data, mask_len);\n+\tif (mask_entry == NULL) {\n+\t\t/* mask entry does not exist, let's create one */\n+\t\tret = nfp_mask_table_add(priv, mask_data, mask_len, mask_id);\n+\t\tif (ret != 0)\n+\t\t\treturn false;\n+\n+\t\t*meta_flags |= NFP_FL_META_FLAG_MANAGE_MASK;\n+\t} else {\n+\t\t/* mask entry already exist */\n+\t\tmask_entry->ref_cnt++;\n+\t\t*mask_id = mask_entry->mask_id;\n+\t}\n+\n+\treturn true;\n+}\n+\n+__rte_unused static bool\n+nfp_check_mask_remove(struct nfp_flow_priv *priv,\n+\t\tchar *mask_data,\n+\t\tuint32_t mask_len,\n+\t\tuint8_t *meta_flags)\n+{\n+\tint ret;\n+\tstruct nfp_mask_id_entry *mask_entry;\n+\n+\tmask_entry = nfp_mask_table_search(priv, mask_data, mask_len);\n+\tif (mask_entry == NULL)\n+\t\treturn false;\n+\n+\tmask_entry->ref_cnt--;\n+\tif (mask_entry->ref_cnt == 0) {\n+\t\tret = nfp_mask_table_del(priv, mask_data, mask_len,\n+\t\t\t\tmask_entry->mask_id);\n+\t\tif (ret != 0)\n+\t\t\treturn false;\n+\n+\t\trte_free(mask_entry);\n+\t\tif (meta_flags)\n+\t\t\t*meta_flags &= ~NFP_FL_META_FLAG_MANAGE_MASK;\n+\t}\n+\n+\treturn true;\n+}\n+\n+__rte_unused static int\n+nfp_flow_table_add(struct nfp_flow_priv *priv,\n+\t\tstruct rte_flow *nfp_flow)\n+{\n+\tint ret;\n+\n+\tret = rte_hash_add_key_data(priv->flow_table, &nfp_flow->hash_key, nfp_flow);\n+\tif (ret != 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Add to flow table failed.\");\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+__rte_unused static int\n+nfp_flow_table_delete(struct nfp_flow_priv *priv,\n+\t\tstruct rte_flow *nfp_flow)\n+{\n+\tint ret;\n+\n+\tret = rte_hash_del_key(priv->flow_table, &nfp_flow->hash_key);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Delete from flow table failed.\");\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+__rte_unused static struct rte_flow *\n+nfp_flow_table_search(struct nfp_flow_priv *priv,\n+\t\tstruct rte_flow *nfp_flow)\n+{\n+\tint index;\n+\tstruct rte_flow *flow_find;\n+\n+\tindex = rte_hash_lookup_data(priv->flow_table, &nfp_flow->hash_key,\n+\t\t\t(void **)&flow_find);\n+\tif (index < 0) {\n+\t\tPMD_DRV_LOG(DEBUG, \"Data NOT found in the flow table.\");\n+\t\treturn NULL;\n+\t}\n+\n+\treturn flow_find;\n+}\n+\n+__rte_unused static struct rte_flow *\n+nfp_flow_alloc(struct nfp_fl_key_ls *key_layer)\n+{\n+\tchar *tmp;\n+\tsize_t len;\n+\tstruct rte_flow *nfp_flow;\n+\tstruct nfp_fl_payload *payload;\n+\n+\tnfp_flow = rte_zmalloc(\"nfp_flow\", sizeof(struct rte_flow), 0);\n+\tif (nfp_flow == NULL)\n+\t\tgoto exit;\n+\n+\tlen = key_layer->key_size + key_layer->key_size + key_layer->act_size;\n+\ttmp = rte_zmalloc(\"nfp_flow_payload\", len + sizeof(struct nfp_fl_rule_metadata), 0);\n+\tif (tmp == NULL)\n+\t\tgoto free_flow;\n+\n+\tnfp_flow->length = len;\n+\n+\tpayload                = &nfp_flow->payload;\n+\tpayload->meta          = (struct nfp_fl_rule_metadata *)tmp;\n+\tpayload->unmasked_data = tmp + sizeof(struct nfp_fl_rule_metadata);\n+\tpayload->mask_data     = payload->unmasked_data + key_layer->key_size;\n+\tpayload->action_data   = payload->mask_data + key_layer->key_size;\n+\n+\treturn nfp_flow;\n+\n+free_flow:\n+\trte_free(nfp_flow);\n+exit:\n+\treturn NULL;\n+}\n+\n+__rte_unused static void\n+nfp_flow_free(struct rte_flow *nfp_flow)\n+{\n+\trte_free(nfp_flow->payload.meta);\n+\trte_free(nfp_flow);\n+}\n+\n+__rte_unused static int\n+nfp_stats_id_alloc(struct nfp_flow_priv *priv, uint32_t *ctx)\n+{\n+\tstruct circ_buf *ring;\n+\tuint32_t temp_stats_id;\n+\tuint32_t freed_stats_id;\n+\n+\t/* Check for unallocated entries first. */\n+\tif (priv->stats_ids.init_unallocated > 0) {\n+\t\t*ctx = ((priv->stats_ids.init_unallocated - 1) & NFP_FL_STAT_ID_STAT) |\n+\t\t\t\t(priv->active_mem_unit & NFP_FL_STAT_ID_MU_NUM);\n+\t\tif (++priv->active_mem_unit == priv->total_mem_units) {\n+\t\t\tpriv->stats_ids.init_unallocated--;\n+\t\t\tpriv->active_mem_unit = 0;\n+\t\t}\n+\t\treturn 0;\n+\t}\n+\n+\t/* Check if buffer is empty */\n+\tring = &priv->stats_ids.free_list;\n+\tfreed_stats_id = priv->stats_ring_size;\n+\tif (ring->head == ring->tail) {\n+\t\t*ctx = freed_stats_id;\n+\t\treturn -ENOENT;\n+\t}\n+\n+\tmemcpy(&temp_stats_id, &ring->buf[ring->tail], NFP_FL_STATS_ELEM_RS);\n+\t*ctx = temp_stats_id;\n+\tmemcpy(&ring->buf[ring->tail], &freed_stats_id, NFP_FL_STATS_ELEM_RS);\n+\tring->tail = (ring->tail + NFP_FL_STATS_ELEM_RS) %\n+\t\t\t(priv->stats_ring_size * NFP_FL_STATS_ELEM_RS);\n+\n+\treturn 0;\n+}\n+\n+__rte_unused static int\n+nfp_stats_id_free(struct nfp_flow_priv *priv, uint32_t ctx)\n+{\n+\tstruct circ_buf *ring;\n+\n+\t/* Check if buffer is full */\n+\tring = &priv->stats_ids.free_list;\n+\tif (!CIRC_SPACE(ring->head, ring->tail, priv->stats_ring_size *\n+\t\t\tNFP_FL_STATS_ELEM_RS - NFP_FL_STATS_ELEM_RS + 1))\n+\t\treturn -ENOBUFS;\n+\n+\tmemcpy(&ring->buf[ring->head], &ctx, NFP_FL_STATS_ELEM_RS);\n+\tring->head = (ring->head + NFP_FL_STATS_ELEM_RS) %\n+\t\t\t(priv->stats_ring_size * NFP_FL_STATS_ELEM_RS);\n+\n+\treturn 0;\n+}\n+\n+int\n+nfp_flow_priv_init(struct nfp_pf_dev *pf_dev)\n+{\n+\tint ret = 0;\n+\tsize_t stats_size;\n+\tuint64_t ctx_count;\n+\tuint64_t ctx_split;\n+\tstruct nfp_flow_priv *priv;\n+\tstruct nfp_app_fw_flower *app_fw_flower;\n+\n+\tstruct rte_hash_parameters mask_hash_params = {\n+\t\t.name       = \"mask_hash_table\",\n+\t\t.entries    = NFP_MASK_TABLE_ENTRIES,\n+\t\t.hash_func  = rte_jhash,\n+\t\t.socket_id  = rte_socket_id(),\n+\t\t.key_len    = sizeof(uint32_t),\n+\t\t.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,\n+\t};\n+\n+\tstruct rte_hash_parameters flow_hash_params = {\n+\t\t.name       = \"flow_hash_table\",\n+\t\t.hash_func  = rte_jhash,\n+\t\t.socket_id  = rte_socket_id(),\n+\t\t.key_len    = sizeof(uint32_t),\n+\t\t.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,\n+\t};\n+\n+\tctx_count = nfp_rtsym_read_le(pf_dev->sym_tbl,\n+\t\t\t\"CONFIG_FC_HOST_CTX_COUNT\", &ret);\n+\tif (ret < 0) {\n+\t\tPMD_INIT_LOG(ERR, \"Read CTX_COUNT from symbol table failed\");\n+\t\tgoto exit;\n+\t}\n+\n+\tctx_split = nfp_rtsym_read_le(pf_dev->sym_tbl,\n+\t\t\t\"CONFIG_FC_HOST_CTX_SPLIT\", &ret);\n+\tif (ret < 0) {\n+\t\tPMD_INIT_LOG(ERR, \"Read CTX_SPLIT from symbol table failed\");\n+\t\tgoto exit;\n+\t}\n+\n+\tpriv = rte_zmalloc(\"nfp_app_flow_priv\", sizeof(struct nfp_flow_priv), 0);\n+\tif (priv == NULL) {\n+\t\tPMD_INIT_LOG(ERR, \"nfp app flow priv creation failed\");\n+\t\tret = -ENOMEM;\n+\t\tgoto exit;\n+\t}\n+\n+\tapp_fw_flower = NFP_PRIV_TO_APP_FW_FLOWER(pf_dev->app_fw_priv);\n+\tapp_fw_flower->flow_priv = priv;\n+\tpriv->hash_seed = (uint32_t)rte_rand();\n+\tpriv->stats_ring_size = ctx_count;\n+\tpriv->total_mem_units = ctx_split;\n+\n+\t/* Init ring buffer and unallocated mask_ids. */\n+\tpriv->mask_ids.init_unallocated = NFP_FLOWER_MASK_ENTRY_RS - 1;\n+\tpriv->mask_ids.free_list.buf = rte_zmalloc(\"nfp_app_mask_ids\",\n+\t\t\tNFP_FLOWER_MASK_ENTRY_RS * NFP_FLOWER_MASK_ELEMENT_RS, 0);\n+\tif (priv->mask_ids.free_list.buf == NULL) {\n+\t\tPMD_INIT_LOG(ERR, \"mask id free list creation failed\");\n+\t\tret = -ENOMEM;\n+\t\tgoto free_priv;\n+\t}\n+\n+\t/* Init ring buffer and unallocated stats_ids. */\n+\tpriv->stats_ids.init_unallocated = ctx_count / ctx_split;\n+\tpriv->stats_ids.free_list.buf = rte_zmalloc(\"nfp_app_stats_ids\",\n+\t\t\tpriv->stats_ring_size * NFP_FL_STATS_ELEM_RS, 0);\n+\tif (priv->stats_ids.free_list.buf == NULL) {\n+\t\tPMD_INIT_LOG(ERR, \"stats id free list creation failed\");\n+\t\tret = -ENOMEM;\n+\t\tgoto free_mask_id;\n+\t}\n+\n+\t/* flow stats */\n+\trte_spinlock_init(&priv->stats_lock);\n+\tstats_size = (ctx_count & NFP_FL_STAT_ID_STAT) |\n+\t\t\t((ctx_split - 1) & NFP_FL_STAT_ID_MU_NUM);\n+\tPMD_INIT_LOG(INFO, \"ctx_count:%0lx, ctx_split:%0lx, stats_size:%0lx \",\n+\t\t\tctx_count, ctx_split, stats_size);\n+\tpriv->stats = rte_zmalloc(\"nfp_flow_stats\",\n+\t\t\tstats_size * sizeof(struct nfp_fl_stats), 0);\n+\tif (priv->stats == NULL) {\n+\t\tPMD_INIT_LOG(ERR, \"flow stats creation failed\");\n+\t\tret = -ENOMEM;\n+\t\tgoto free_stats_id;\n+\t}\n+\n+\t/* mask table */\n+\tmask_hash_params.hash_func_init_val = priv->hash_seed;\n+\tpriv->mask_table = rte_hash_create(&mask_hash_params);\n+\tif (priv->mask_table == NULL) {\n+\t\tPMD_INIT_LOG(ERR, \"mask hash table creation failed\");\n+\t\tret = -ENOMEM;\n+\t\tgoto free_stats;\n+\t}\n+\n+\t/* flow table */\n+\tflow_hash_params.hash_func_init_val = priv->hash_seed;\n+\tflow_hash_params.entries = ctx_count;\n+\tpriv->flow_table = rte_hash_create(&flow_hash_params);\n+\tif (priv->flow_table == NULL) {\n+\t\tPMD_INIT_LOG(ERR, \"flow hash table creation failed\");\n+\t\tret = -ENOMEM;\n+\t\tgoto free_mask_table;\n+\t}\n+\n+\treturn 0;\n+\n+free_mask_table:\n+\trte_free(priv->mask_table);\n+free_stats:\n+\trte_free(priv->stats);\n+free_stats_id:\n+\trte_free(priv->stats_ids.free_list.buf);\n+free_mask_id:\n+\trte_free(priv->mask_ids.free_list.buf);\n+free_priv:\n+\trte_free(priv);\n+exit:\n+\treturn ret;\n+}\n+\n+void\n+nfp_flow_priv_uninit(struct nfp_pf_dev *pf_dev)\n+{\n+\tstruct nfp_flow_priv *priv;\n+\tstruct nfp_app_fw_flower *app_fw_flower;\n+\n+\tapp_fw_flower = NFP_PRIV_TO_APP_FW_FLOWER(pf_dev->app_fw_priv);\n+\tpriv = app_fw_flower->flow_priv;\n+\n+\trte_hash_free(priv->flow_table);\n+\trte_hash_free(priv->mask_table);\n+\trte_free(priv->stats);\n+\trte_free(priv->stats_ids.free_list.buf);\n+\trte_free(priv->mask_ids.free_list.buf);\n+\trte_free(priv);\n+}\ndiff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h\nnew file mode 100644\nindex 0000000..8eec84c\n--- /dev/null\n+++ b/drivers/net/nfp/nfp_flow.h\n@@ -0,0 +1,104 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright (c) 2022 Corigine, Inc.\n+ * All rights reserved.\n+ */\n+\n+#ifndef _NFP_FLOW_H_\n+#define _NFP_FLOW_H_\n+\n+#include <rte_bitops.h>\n+\n+#define NFP_FL_META_FLAG_MANAGE_MASK    RTE_BIT32(7)\n+\n+#define NFP_MASK_TABLE_ENTRIES          1024\n+\n+enum nfp_flower_tun_type {\n+\tNFP_FL_TUN_NONE   = 0,\n+\tNFP_FL_TUN_GRE    = 1,\n+\tNFP_FL_TUN_VXLAN  = 2,\n+\tNFP_FL_TUN_GENEVE = 4,\n+};\n+\n+struct nfp_fl_key_ls {\n+\tuint32_t key_layer_two;\n+\tuint8_t key_layer;\n+\tint key_size;\n+\tint act_size;\n+\tuint32_t port;\n+\tuint16_t vlan;\n+\tenum nfp_flower_tun_type tun_type;\n+};\n+\n+struct nfp_fl_rule_metadata {\n+\tuint8_t key_len;\n+\tuint8_t mask_len;\n+\tuint8_t act_len;\n+\tuint8_t flags;\n+\trte_be32_t host_ctx_id;\n+\trte_be64_t host_cookie __rte_packed;\n+\trte_be64_t flow_version __rte_packed;\n+\trte_be32_t shortcut;\n+};\n+\n+struct nfp_fl_payload {\n+\tstruct nfp_fl_rule_metadata *meta;\n+\tchar *unmasked_data;\n+\tchar *mask_data;\n+\tchar *action_data;\n+};\n+\n+#define CIRC_CNT(head, tail, size)     (((head) - (tail)) & ((size) - 1))\n+#define CIRC_SPACE(head, tail, size)   CIRC_CNT((tail), ((head) + 1), (size))\n+struct circ_buf {\n+\tuint32_t head;\n+\tuint32_t tail;\n+\tchar *buf;\n+};\n+\n+#define NFP_FLOWER_MASK_ENTRY_RS        256\n+#define NFP_FLOWER_MASK_ELEMENT_RS      sizeof(uint8_t)\n+struct nfp_fl_mask_id {\n+\tstruct circ_buf free_list;\n+\tuint8_t init_unallocated;\n+};\n+\n+#define NFP_FL_STATS_ELEM_RS            sizeof(uint32_t)\n+struct nfp_fl_stats_id {\n+\tstruct circ_buf free_list;\n+\tuint32_t init_unallocated;\n+};\n+\n+#define NFP_FL_STAT_ID_MU_NUM           0xffc00000\n+#define NFP_FL_STAT_ID_STAT             0x003fffff\n+struct nfp_fl_stats {\n+\tuint64_t pkts;\n+\tuint64_t bytes;\n+};\n+\n+struct nfp_flow_priv {\n+\tuint32_t hash_seed; /**< Hash seed for hash tables in this structure. */\n+\t/* mask hash table */\n+\tstruct nfp_fl_mask_id mask_ids; /**< Entry for mask hash table */\n+\tstruct rte_hash *mask_table; /**< Hash table to store mask ids. */\n+\t/* flow hash table */\n+\tstruct rte_hash *flow_table; /**< Hash table to store flow rules. */\n+\t/* flow stats */\n+\tuint32_t active_mem_unit; /**< The size of active mem units. */\n+\tuint32_t total_mem_units; /**< The size of total mem units. */\n+\tuint32_t stats_ring_size; /**< The size of stats id ring. */\n+\tstruct nfp_fl_stats_id stats_ids; /**< The stats id ring. */\n+\tstruct nfp_fl_stats *stats; /**< Store stats of flow. */\n+\trte_spinlock_t stats_lock; /** < Lock the update of 'stats' field. */\n+};\n+\n+struct rte_flow {\n+\tstruct nfp_fl_payload payload;\n+\tsize_t length;\n+\tuint32_t hash_key;\n+\tbool install_flag;\n+};\n+\n+int nfp_flow_priv_init(struct nfp_pf_dev *pf_dev);\n+void nfp_flow_priv_uninit(struct nfp_pf_dev *pf_dev);\n+\n+#endif /* _NFP_FLOW_H_ */\n",
    "prefixes": [
        "v6",
        "04/27"
    ]
}