get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 117764,
    "url": "http://patches.dpdk.org/api/patches/117764/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1665382142-21684-3-git-send-email-chaoyong.he@corigine.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1665382142-21684-3-git-send-email-chaoyong.he@corigine.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1665382142-21684-3-git-send-email-chaoyong.he@corigine.com",
    "date": "2022-10-10T06:08:40",
    "name": "[v2,02/24] net/nfp: add the structures and functions for flow offload",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "50d04dcdf5f2178045e1f7a0030c188647bd7412",
    "submitter": {
        "id": 2554,
        "url": "http://patches.dpdk.org/api/people/2554/?format=api",
        "name": "Chaoyong He",
        "email": "chaoyong.he@corigine.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1665382142-21684-3-git-send-email-chaoyong.he@corigine.com/mbox/",
    "series": [
        {
            "id": 25072,
            "url": "http://patches.dpdk.org/api/series/25072/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=25072",
            "date": "2022-10-10T06:08:38",
            "name": "add the basic rte_flow offload support of nfp PMD",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/25072/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/117764/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/117764/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 BC0F6A0544;\n\tMon, 10 Oct 2022 08:09:33 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 6260F40E50;\n\tMon, 10 Oct 2022 08:09:27 +0200 (CEST)",
            "from NAM02-SN1-obe.outbound.protection.outlook.com\n (mail-sn1anam02on2101.outbound.protection.outlook.com [40.107.96.101])\n by mails.dpdk.org (Postfix) with ESMTP id 277D2427EB\n for <dev@dpdk.org>; Mon, 10 Oct 2022 08:09:25 +0200 (CEST)",
            "from SJ0PR13MB5545.namprd13.prod.outlook.com (2603:10b6:a03:424::5)\n by SN4PR13MB5296.namprd13.prod.outlook.com (2603:10b6:806:207::14)\n with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5723.14; Mon, 10 Oct\n 2022 06:09:23 +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; Mon, 10 Oct 2022\n 06:09:23 +0000"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=U2QDc6Ca67UQMN1BD2Rpc0jF/NK2gtUwCdHG+Ymqt8bUVt5k580pLdFJzQeOGf8KEO/rCKgFzJ/D11niaOfJ4FX3RccSYmscPj7GveOE2NsjxC5QBwa93i/N3uZHRPrNUi4YprGMQBw7T04lETZXgMmsZAcrHrAVMmgkqb+4JH1AE+SVIpeNvWeIIWjzsEYyUrkbx23gvYUtoHmVQliBXgeJOlQwiBOQLH2xdPULNNChZatERR5oDV0aSW5gIiAhPrHKiFWVhsYfpRRxE233N1/R4vY3TSCmH6182h8v1R+9XciYtMkHFWSmTZVfn7tRaFI5wk+O58eG6UIztSrJfQ==",
        "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=YD8Nh+zySV1HqdJHBwUxHWU5xkvBmSX8p0eo2OHVhog=;\n b=RUkDDtjN0aUG1SULxrfb2RhA38GMGZfhEMmE4o5FUEfnniXRmOWtvlSaX8zg9d57+ikH0AbTVKR1YokcZBQU8rmpB1BiUNN4eozPo5roRxk0Dmy5J5rCITDzc81b21Y2dr0m1gsEbU3Um3ctEIRcJwrWOnAld9pWQOsKoeobJOwHRNhPy45/7Vswntr3F1IVsH9H92O0EADceNwQXaWdO0C/qHPO8ZL8jDzqBlTUwFt8tE71r0H6ZBtX7rTtuUvw32Xai6wXswceHAvR+w/nTwrxiCTZTgtW+TnWX1IzPKqNMyAmLw6FWu1yOfQDObGoj/tn0U5p+8BsZfOoj10cTQ==",
        "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=YD8Nh+zySV1HqdJHBwUxHWU5xkvBmSX8p0eo2OHVhog=;\n b=l1oXw/BscE4ZYMjT8oku0oxYWapAx6YCr7dPg3KGGWMb1cY3M6Boc9NamVP/gcvUEb3lILlQIXa22n7DoIDRo0gKdt53RAcfN3gpqUa8SbwZ8SpEQ7sQ2ZroHE4O/C3SzzXVDGDHji7/11m56mhlchFilhINu3TkeLsHwViLBmU=",
        "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 v2 02/24] net/nfp: add the structures and functions for flow\n offload",
        "Date": "Mon, 10 Oct 2022 14:08:40 +0800",
        "Message-Id": "<1665382142-21684-3-git-send-email-chaoyong.he@corigine.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1665382142-21684-1-git-send-email-chaoyong.he@corigine.com>",
        "References": "<1665382142-21684-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_|SN4PR13MB5296:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "dd13800e-bd48-46ae-13ea-08daaa85fa6d",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n WLwDhlznoVDwWlKcnEcHcBWeybqw+QXV+GXGHGgqstBxVlrEZGgYWoitnoPUNmVfvc/NgCLossuNMrJSqt0rCbkXHmZuivPG3vHteUxjkJ23on681d/OX4pESLIeNM54BT08JWihAoOp2HI+s8bl2AWpJ8aBi8Tkzx6C1YZbmxK4TqvMlA24NQApSLGflGpfQRk0y63VicnNHvqO1NUnVyp2jG+EyWf+UfQMs/pZmUpvOyDBT3oYgoFq0qhPhDjsyfRbs8oE5Nh+voB0yu+vCECNrVO0xS/6c9hqOCsO6vIFkP8VjzVVY5c+/WVcrnrTywUuqjsjH0xsqU7J9nKsHwAWkJF2eoEh7wxgsu4mPKEkzRXAd4Gcn3WWRa6KaamIe4Hs4CDV3wUEfA15eTf9x2rkAdlKTx85j6VK4iszLzH/Dh8xkw7EInTdKcpx7xOTnn9oKHKovESMT8D9XcZ6fDdObGlqx0g76D988o3SM+f369j5ZOtB2JA+T3AuO0EunmUrsWr7c8aSWcr2/sQPga/2XTCSYSWDNUEozgs7ZbWR7eRZwAOZE/QG3yM+NG257fj/2BxbLpZschfOPZEbOj/yCJVAa93OaL7/JRGz0ztvGdI0g+3DfclnME3H+PCoNq1Ge0w9vjkLXtq6BICuZLxAK1PiLSj/YUtuCHhSwk9zxyJvKaumonM/A95dpqTA8mSY7tfaJByZ/+FMDIz5U5d3Zad0vH00hC18BuTI0/DYHDXSH3kcSdq9SFl1QwgL8QVK3iMTC3ztbgV77EglC8Ze6SBrxG7gmLCmsmW7KsTLJJ0lGohZCzrA0MoKdw08",
        "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)(366004)(396003)(346002)(376002)(136003)(39830400003)(451199015)(6916009)(316002)(2906002)(186003)(6486002)(2616005)(66476007)(6666004)(107886003)(66556008)(41300700001)(66946007)(83380400001)(30864003)(8936002)(8676002)(4326008)(5660300002)(66574015)(44832011)(26005)(6506007)(6512007)(52116002)(86362001)(478600001)(36756003)(38350700002)(38100700002);\n DIR:OUT; SFP:1102;",
        "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1",
        "X-MS-Exchange-AntiSpam-MessageData-0": "=?utf-8?q?lHzNbuWtapvTf5QuoPBGmdTBtyHP?=\n\t=?utf-8?q?unL4/xbr7pV3UVzeagKUM7v7nEAZv5JcoG0qOiIK97eUajYce0bQsz6xAvaRjV8gj?=\n\t=?utf-8?q?4Bz3s3fXKuXdBQHLgfwLHC4GPW4LN6MnqjHQGaj2adE3gGNRVOmqwe/wwuRuWD9jR?=\n\t=?utf-8?q?m4a6mMcAjcl58UsobWlwK/4xhCwLHnl2yYTuP0p0Ts2C1bhGwhnGiZ6zOUn8siZS3?=\n\t=?utf-8?q?rlvUxNu2rA3S8XA62r06xNnvUo9yz71U/O5fm24oqXpCKIqsIidaWCeSwel4hvXBI?=\n\t=?utf-8?q?NJjxii4npQ4pllQImDAvj0teVrAarHRLzaLDikGdL8JLqNIJT1zMhDSRcdujllPwf?=\n\t=?utf-8?q?K3FzN4gWBNwKXSKsopADSNa2EvkEudM3JArS7dXyCsh/r/2XFkQXM/JTYUxX3pyQn?=\n\t=?utf-8?q?wkcQctc46X63mQIZOd5+wfCFRZTOCGLlKr3RlN1Hn5m48qGcGD2zTkSfZpyu5elkA?=\n\t=?utf-8?q?nX6UtXzgBRJakr41oHpzjq40rDAN9KfdYp/A6mhFPQoXYBIPKl8eOa6zY7QKpoW2Q?=\n\t=?utf-8?q?K7tpoM5jLlXU/m8+UyV+bTa7HwPxX2dpGUMATrCqu54sbvNceeotKyOBtdzzJwY1C?=\n\t=?utf-8?q?XhUXMV7Su8FHCTqxEgs9Prq1xuIXA1237UjreEroh+RCGrhjzyeWj4c30YVQbR5Wq?=\n\t=?utf-8?q?77JrVsi6sd0YdRNyM/9z0SB7Z3CIbnTn7FuKjbdhw4pwBCQ5fPBSoUT5KF8UyjHVs?=\n\t=?utf-8?q?BIBAukEvu2ad942aB42rvg/Ou6uxWvkYYfmVp4PYhAMjCLvB+fr4nU+sZi4QiKcA3?=\n\t=?utf-8?q?gEGPETD7y3593bxv9PgdOmly1p8BneVTTPWjHJl+VfGFQfhlFFemSS4u6ci0eo8v/?=\n\t=?utf-8?q?t5gNredO1b39gE1FfxI9CASTdla1EJyDD4kReqlnNTWLPKVPYe4LyJ3QbrChgRvow?=\n\t=?utf-8?q?ndzAq6pfjiNwV623VVL/stAldAtBwJszNEUAftUY+aaZzV2Ya8kXxIuK59aT/oYEo?=\n\t=?utf-8?q?gWh7mvXJ/ddHebPKD8vJqcDk1HmzcAlfRoKlxMyOkQUTCUFU2RjC6GXdVW/XeJOuY?=\n\t=?utf-8?q?0LgXaZu4KlsdQIQst0zlyPd1dz/VXZ94lgS942YNb+zwSHjEOmc/pCK61b2w4bz8p?=\n\t=?utf-8?q?KbbKvswfj93r1iDFfWBWHXunu24GmDi22FZmS1Ab+Nd3nc8pjiuhoM1DAHjIHDfqh?=\n\t=?utf-8?q?wYW9266Zrhl+aU2Ja7wIMjy1KhVGN1Q7G3vbb755U/wsw+E2p1yc6LVHlZPn5FMQo?=\n\t=?utf-8?q?OFUbGxzJLl1m/j+UauN8Uev6ai0AHLILNf85wtHKNcmRL9+93J621RIoGf1epZysc?=\n\t=?utf-8?q?NXzRmB3WPh8kQsmB+cmo/rYrl/YI/EP7g6hqMWDPdkM8WDHasDPNpiT/xy/LbZZZI?=\n\t=?utf-8?q?R2I3Qs1pm0lCUcF0QVwb0jdp/aBUxCwNbdwAO6JX6b3Lx8Efh4K+72SKLkEjDNt0j?=\n\t=?utf-8?q?hodS9hAYkcZp2H6MhklDEHv7GUQMxxn5nWO0w3sjvl9iDl/LW/7h23DOkxdmER33r?=\n\t=?utf-8?q?/U1PFOgPkOVb/R7Yhxkdg1MTpHemF88ra1Q4nUzyKKpScp+2WIHnNbNEldSbuLCsg?=\n\t=?utf-8?q?FtmYB351FUMfCvmvKNexBgFQWCKAtbTRSQ=3D=3D?=",
        "X-OriginatorOrg": "corigine.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n dd13800e-bd48-46ae-13ea-08daaa85fa6d",
        "X-MS-Exchange-CrossTenant-AuthSource": "SJ0PR13MB5545.namprd13.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Internal",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "10 Oct 2022 06:09:23.6577 (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 5pZdMAeZzs/bEyrJ6oBmHMiCh9uTzuR3oAF9Vo23/BJN4b2xk1sMJz87SlNmWJw5cdn7m4akSRVuI/FaAeZTyQ/QWDNVR1xfnXBj0pxv3dc=",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "SN4PR13MB5296",
        "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/meson.build         |   3 +\n drivers/net/nfp/nfp_flow.c          | 507 ++++++++++++++++++++++++++++++++++++\n drivers/net/nfp/nfp_flow.h          |  81 ++++++\n 4 files changed, 601 insertions(+), 1 deletion(-)\n create mode 100644 drivers/net/nfp/nfp_flow.c",
    "diff": "diff --git a/drivers/net/nfp/flower/nfp_flower.c b/drivers/net/nfp/flower/nfp_flower.c\nindex 3e97f5c..3b16c12 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@@ -1089,13 +1090,19 @@\n \n \tpf_dev->app_fw_priv = app_fw_flower;\n \n+\tret = nfp_flow_priv_init(pf_dev);\n+\tif (ret) {\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@@ -1173,6 +1180,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/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..97f5d1b\n--- /dev/null\n+++ b/drivers/net/nfp/nfp_flow.c\n@@ -0,0 +1,507 @@\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+\tchar *hash_data;\n+\tuint32_t hash_key;\n+\n+\thash_data = (char *)(nfp_flow->payload.unmasked_data);\n+\thash_key = rte_jhash(hash_data, nfp_flow->length, priv->hash_seed);\n+\tret = rte_hash_add_key_data(priv->flow_table, &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+\tchar *hash_data;\n+\tuint32_t hash_key;\n+\n+\thash_data = (char *)(nfp_flow->payload.unmasked_data);\n+\thash_key = rte_jhash(hash_data, nfp_flow->length, priv->hash_seed);\n+\tret = rte_hash_del_key(priv->flow_table, &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+\tchar *hash_data;\n+\tuint32_t hash_key;\n+\tstruct rte_flow *flow_find;\n+\n+\thash_data = (char *)(nfp_flow->payload.unmasked_data);\n+\thash_key = rte_jhash(hash_data, nfp_flow->length, priv->hash_seed);\n+\tindex = rte_hash_lookup_data(priv->flow_table, &hash_key, (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 freed_stats_id;\n+\tuint32_t temp_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+\tuint64_t ctx_count;\n+\tuint64_t ctx_split;\n+\tsize_t stats_size;\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_app_fw_flower *app_fw_flower;\n+\tstruct nfp_flow_priv *priv;\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\nindex 971ba69..142d7d5 100644\n--- a/drivers/net/nfp/nfp_flow.h\n+++ b/drivers/net/nfp/nfp_flow.h\n@@ -6,15 +6,96 @@\n #ifndef _NFP_FLOW_H_\n #define _NFP_FLOW_H_\n \n+#define NFP_FL_META_FLAG_MANAGE_MASK    (1 << 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+\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": [
        "v2",
        "02/24"
    ]
}