get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 133810,
    "url": "http://patchwork.dpdk.org/api/patches/133810/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20231103062606.2632012-5-chaoyong.he@corigine.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": "<20231103062606.2632012-5-chaoyong.he@corigine.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20231103062606.2632012-5-chaoyong.he@corigine.com",
    "date": "2023-11-03T06:25:59",
    "name": "[04/11] net/nfp: support flow API for CoreNIC firmware",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "1dfac57c7d52bdf74085935d780a7ecf47a7a3da",
    "submitter": {
        "id": 2554,
        "url": "http://patchwork.dpdk.org/api/people/2554/?format=api",
        "name": "Chaoyong He",
        "email": "chaoyong.he@corigine.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patchwork.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20231103062606.2632012-5-chaoyong.he@corigine.com/mbox/",
    "series": [
        {
            "id": 30130,
            "url": "http://patchwork.dpdk.org/api/series/30130/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=30130",
            "date": "2023-11-03T06:25:55",
            "name": "Add basic flow support for corenic firmware",
            "version": 1,
            "mbox": "http://patchwork.dpdk.org/series/30130/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/133810/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/133810/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 6056E43275;\n\tFri,  3 Nov 2023 07:27:03 +0100 (CET)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id C9EBF42DCD;\n\tFri,  3 Nov 2023 07:26:40 +0100 (CET)",
            "from NAM10-DM6-obe.outbound.protection.outlook.com\n (mail-dm6nam10on2112.outbound.protection.outlook.com [40.107.93.112])\n by mails.dpdk.org (Postfix) with ESMTP id 7918F42D35\n for <dev@dpdk.org>; Fri,  3 Nov 2023 07:26:38 +0100 (CET)",
            "from SJ0PR13MB5545.namprd13.prod.outlook.com (2603:10b6:a03:424::5)\n by MN2PR13MB4102.namprd13.prod.outlook.com (2603:10b6:208:262::16)\n with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6954.24; Fri, 3 Nov\n 2023 06:26:36 +0000",
            "from SJ0PR13MB5545.namprd13.prod.outlook.com\n ([fe80::45b3:d83c:cff2:4a1b]) by SJ0PR13MB5545.namprd13.prod.outlook.com\n ([fe80::45b3:d83c:cff2:4a1b%6]) with mapi id 15.20.6954.021; Fri, 3 Nov 2023\n 06:26:36 +0000"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=FBHemgOHQSgsJ7rqCTpxjhnG2Ea7CBCr+jt2qkoPros6VzOdZHWsVVTnFhVpNIWGAxjIroa8z981mITfhAk5qVjdrc6n2Cb/djCF/cxNz64rVpm0Oyy0K8ik11YRs3f/oZDXYwauyMaC4iJi1J7A98B9cpbUx8qMJG8lLEp25IhtrQcsWkEtdRfBo3Nd+fQNx/auvQX15XT9n8zkZMpfatsFWaEc7ssZC0js2hb1TBiBhnvm9S4PCQs/rHOGXzRWT4Dcw4YEYV+WK3O4Sf81yXf7yvDIkj27JzrJJisQCbOo7UEs1zm/PkhgkZWG0HVBRg2U38mKgtkzby7qG/0SaA==",
        "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=ceMV+MrpGUpYXxDZbJQFvXi/mL4FVWpG6B9pSrH9EUg=;\n b=hn7B88WHcpb3emQx3X0GWeLdePTadZikH4yH3FIevVuiJnZDYG7k+j1vz+LRWwWA/YiUAbebEoS7N+Kau24mMewuF+GVKxnN4H0y4zkgYSjCN4dkRRMpcwU4U9xhG6prDcXXei7EEqNKu5NZf+R4QxO1mb9eSMi4QXqK9fZedzUxjSoxAbTb0UQQ1DQMXLWzDyIh5QnKApP0BsbXdsw17plY8y8hCj5P7F8R8TKWlIBvRXTDTK9gqZLYsZUDWHdvIWStTH32tYILbS8X1Q/EBoX9uUKpfalBR/X3jzgJD5gBxHo/11UU7ham12CKjpEbQuYEJ2raaUvLbhpOvBm7FQ==",
        "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=ceMV+MrpGUpYXxDZbJQFvXi/mL4FVWpG6B9pSrH9EUg=;\n b=j5KaRX1ytqDSVEpUCj/7UtDohTdHQ3nsjzsHRosmcjuPEwRpkdYDTNdtF1vNoHYTAWGHBXQ7Geolqw0bHQWYSW7Kpq9dCMoQPuAm/entUr2RCMHKsoaCErvpio/Iq4a4eCpROC8eiRhqi6TVP83GsF5QUnfjIAQdgGYg1nX1sD0=",
        "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, Chaoyong He <chaoyong.he@corigine.com>,\n Long Wu <long.wu@corigine.com>, Peng Zhang <peng.zhang@corigine.com>",
        "Subject": "[PATCH 04/11] net/nfp: support flow API for CoreNIC firmware",
        "Date": "Fri,  3 Nov 2023 14:25:59 +0800",
        "Message-Id": "<20231103062606.2632012-5-chaoyong.he@corigine.com>",
        "X-Mailer": "git-send-email 2.39.1",
        "In-Reply-To": "<20231103062606.2632012-1-chaoyong.he@corigine.com>",
        "References": "<20231103062606.2632012-1-chaoyong.he@corigine.com>",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "X-ClientProxiedBy": "BYAPR02CA0044.namprd02.prod.outlook.com\n (2603:10b6:a03:54::21) 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_|MN2PR13MB4102:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "d65fb47b-3353-4557-d794-08dbdc35d4a8",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n dAgJtL4JrKk0w4bOf1fe4iaq+gJx6FhDr3yppRhaK58KHERJ28Vd1lsd1f0r+XJgbC49Di7gctzdeXN+dRVVgQIXddq+9/OM2asIoWI8cE7xWSdANcxcDwlDGoEGAiSR316sYP9jY8vlqs376L01U99DDpXgB6rtZon1HAaNKz7ZLRXSN49mZ8hQ4RLfUWrYq/kOb+j8qLdzGDpo0B6X3YNMS3bKs6MODk+ZOiWw/LZxH0eoqnNBmnzu50pgnO7u4Lnd8f9Xaf2zFfflFCUKy1YUP+JXuvDVDsGliIH4l/ouGSxnwa0YHntZW9enPwiWUy0wvnkw2cqdxPUhyZZGxu41tKPOZCN025y4j78/JX8osODU1DP323HMzrHOHoGKT1O+/jWgpBfExxsJc2I5JFfC7C7XTyAB7flSUE5qYmQ7td7za1Kks9AOBu7QCdtJp+A5SvPBJLe/kC7fNPtVzcgxYS5LPDu/T0nGm4nY8aN/B61Amk8vcfCQQijYpiHX9xCZNgnUEYlPG9tpGMOP1NHlKHVyAaM2pa3+sBP2SAYU6sMV7R2DxfHD6WueA1PdXoZLMaNP0zLIHhMTcDm1wIhm42TWAjQ78VHvt8tIPzUKQ9jZkw5MXfN64Mj3jrUB1Ryv24tTp9nQ0XXBc/ehVcVputfPMvSavtoHMeaQ0kA=",
        "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:(13230031)(39840400004)(346002)(396003)(366004)(136003)(376002)(230922051799003)(186009)(64100799003)(451199024)(1800799009)(316002)(6916009)(54906003)(66476007)(66556008)(66946007)(6666004)(6486002)(478600001)(52116002)(6506007)(30864003)(5660300002)(38350700005)(41300700001)(36756003)(2906002)(86362001)(4326008)(8676002)(8936002)(44832011)(107886003)(1076003)(2616005)(26005)(83380400001)(38100700002)(6512007);\n DIR:OUT; SFP:1102;",
        "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1",
        "X-MS-Exchange-AntiSpam-MessageData-0": "=?utf-8?q?y16Jj7aglouzPWL2auwecEBeJ2qf?=\n\t=?utf-8?q?U3fUCakD4zsKPZL9B6fZ/lb7lI3JU7z++Z0QzEDloWbmMVyKmbV8nt/GhSmyPobJw?=\n\t=?utf-8?q?qMaeasSdWdP9GXgbrb+P1gVh4niHX1aY3Iwnd+5rvnk2NgOrQIF2oYOb889S1IsPX?=\n\t=?utf-8?q?DO/SJf+MJ4j6xU/1mMlYUnQTF1qmN3hfa3nwDU8LbGziGkv8xHZVA/tHFHyMNXH/i?=\n\t=?utf-8?q?pdqkvmg6LJo/Ej0DRIALU2Zi5RRpJNw0arjagMELIMlrP881aA5MXl6hYvLJ99G2t?=\n\t=?utf-8?q?8yqru2WMK4keX3f12o8MrPEsHqAUyL/9y4kV84dE3mV68C1VT/Fi19bXdVdAOm4xh?=\n\t=?utf-8?q?pggvb5OCmS4g+nIXErgVoRAGRKOwK+f697fk83TK6wkavvzS6pEwQke7MU3br26dk?=\n\t=?utf-8?q?P3SuzWVipVBD/bPD1a0V9x5+wvjWqyUehXs81Ez2dEhp/F4x3KHLHIkXaf3anQEj3?=\n\t=?utf-8?q?cxYQKGh6hnyeQKuZ0ml5UlRqzNOJ3dzeXRm5fRKaePryK2gm2G4eWK1ZK03NPIiEV?=\n\t=?utf-8?q?aQmUHSZhUzJ+uiT3Hq5a8W4c7koQ+5HS8dBVVEtaxFmaIZgrXe0wELmKTa4qdjd38?=\n\t=?utf-8?q?PW3Flr4U71cy/2jW6cVp8eCpg3P+Iu8qxs+s7BeFYaaIPNX4VCdIdb8Ctme9ioDSu?=\n\t=?utf-8?q?TJSjVL9LVahpABoqn1gzF8Pqv9l73Gs/UEIknoG2S+LNc+O9fbJg+HPY5qYmsuy27?=\n\t=?utf-8?q?ERJRnfpDqtET+BgAyK65DB6x0OVKRdaO7fJgxOS0X4YWzbfcrfAvL6omfrQlFM/jw?=\n\t=?utf-8?q?s2I7TTmjDyvmFjgNkbre6uVHW4H39D28CAmeKixaopLVclNi5M6JT1MrZL/LsJf2S?=\n\t=?utf-8?q?wm7+8IjfDZRt73ZooOiS1QBsq3oXpt10rztZJetbPMEqul1BbK+FM1Fpg2L+eKqxy?=\n\t=?utf-8?q?9B9zz7ZmkeU/W53YeGDp+7f0Ekrrw6bP8uKgNzCUqSB+XntLBuEKJCSvrNC7ZPhpY?=\n\t=?utf-8?q?iZgULElQKjWpquGlWSn/c1LSLQqrG6e4oLOAAho1VQa3kf0SWxPP9u5VCOFv4TKqG?=\n\t=?utf-8?q?coUuNj/JcHIxTs6sxIYDws/lsQS4m747u6cOhhF+ZP/f9JH8RKqAkPrsFE3FkaV2T?=\n\t=?utf-8?q?v8hv7ZQM5+zv35WqiMWVU3mwka/RHqngX5focPm6Oa5YSU/n7ZIEmc8uumVdSl7r9?=\n\t=?utf-8?q?B0vEQGyj3PvohWTA+rOZRcZ1Xw7uSCMcVhf0Wlx91w8+5iYYbkvsYJ/pwYC7wMUdz?=\n\t=?utf-8?q?m39636Tz9UKkxLmleC6/c3XfNFyPxoXnK7n+esZ4R0ZEXAJj5ToQvP7MU+vHJtvO+?=\n\t=?utf-8?q?Alyk9wmyaQqv24X1qgiHLszn65ulRGPmunC50pgxxAUgLvnU/E3c0Q77W4YokpB+X?=\n\t=?utf-8?q?jwx0fx+iskUi/mmCbo2sabyzF3mfz8uZmO6v2Cexgxu2a+Gaql4+/k/Z5oyyxUqAm?=\n\t=?utf-8?q?pKrCSiT1hqz+30+Smcu+G+ZhzJ1ftxvsCJ9NH4+uL77POdHG90XYhF+Td1W15BmcW?=\n\t=?utf-8?q?Zuxuec+hkZnYXtWvETjBSAuNY71XZi9N1Tt2Pd2bTIfvJFbwF+Vfb723ejVz4ACRy?=\n\t=?utf-8?q?OBP+6iJO9GOaGkrgg85aKARwhySkevO0Jw=3D=3D?=",
        "X-OriginatorOrg": "corigine.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n d65fb47b-3353-4557-d794-08dbdc35d4a8",
        "X-MS-Exchange-CrossTenant-AuthSource": "SJ0PR13MB5545.namprd13.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Internal",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "03 Nov 2023 06:26:36.4920 (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 NRQcOAQUhQ70SOH0uPnb2MNvDWqgjNKo7e2aaPyaNdAOcCWaFoPuVH548biF30LsGlxLtX8fplk4ZYbAKrSo4rVjZuV38CX8FEOmwwr2SXM=",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "MN2PR13MB4102",
        "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 flow validate/create/destroy/flush API of nfp PMD with CoreNIC\nfirmware.\n\nThe flow create API construct a control cmsg and send it to\nfirmware, then add this flow to the hash table.\n\nThe flow destroy API construct a control cmsg and send it to\nfirmware, then delete this flow from the hash table.\n\nThe flow flush API just iterate the flows in hash table and\ncall the flow destroy API.\n\nSigned-off-by: Chaoyong He <chaoyong.he@corigine.com>\nReviewed-by: Long Wu <long.wu@corigine.com>\nReviewed-by: Peng Zhang <peng.zhang@corigine.com>\n---\n drivers/net/nfp/nfp_ethdev.c     |   1 +\n drivers/net/nfp/nfp_net_cmsg.h   |  28 +++\n drivers/net/nfp/nfp_net_common.h |   1 +\n drivers/net/nfp/nfp_net_flow.c   | 409 ++++++++++++++++++++++++++++++-\n drivers/net/nfp/nfp_net_flow.h   |   2 +\n 5 files changed, 434 insertions(+), 7 deletions(-)",
    "diff": "diff --git a/drivers/net/nfp/nfp_ethdev.c b/drivers/net/nfp/nfp_ethdev.c\nindex af5e5d333a..37dae8a82a 100644\n--- a/drivers/net/nfp/nfp_ethdev.c\n+++ b/drivers/net/nfp/nfp_ethdev.c\n@@ -530,6 +530,7 @@ static const struct eth_dev_ops nfp_net_eth_dev_ops = {\n \t.fw_version_get         = nfp_net_firmware_version_get,\n \t.flow_ctrl_get          = nfp_net_flow_ctrl_get,\n \t.flow_ctrl_set          = nfp_net_flow_ctrl_set,\n+\t.flow_ops_get           = nfp_net_flow_ops_get,\n };\n \n static inline void\ndiff --git a/drivers/net/nfp/nfp_net_cmsg.h b/drivers/net/nfp/nfp_net_cmsg.h\nindex 15e0bb60d8..b526feaff2 100644\n--- a/drivers/net/nfp/nfp_net_cmsg.h\n+++ b/drivers/net/nfp/nfp_net_cmsg.h\n@@ -8,6 +8,34 @@\n \n #include \"nfp_net_common.h\"\n \n+#define NFP_NET_CMSG_ACTION_DROP          (0x1 << 0) /* Drop action */\n+#define NFP_NET_CMSG_ACTION_QUEUE         (0x1 << 1) /* Queue action */\n+#define NFP_NET_CMSG_ACTION_MARK          (0x1 << 2) /* Mark action */\n+\n+/**\n+ * Action data\n+ * Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0\n+ * -----\\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0\n+ * Word  +-------------------------------+-------------------------------+\n+ *    0  |                 |    Queue    |              Actions          |\n+ *       +-----------------+-------------+-------------------------------+\n+ *    1  |                         Mark ID                               |\n+ *       +---------------------------------------------------------------+\n+ *\n+ * Queue – Queue ID, 7 bits.\n+ * Actions – An action bitmap, each bit represents an action type:\n+ *       - Bit 0: Drop action. Drop the packet.\n+ *       - Bit 1: Queue action. Use the queue specified by “Queue” field.\n+ *                If not set, the queue is usually specified by RSS.\n+ *       - Bit 2: Mark action. Mark packet with Mark ID.\n+ */\n+struct nfp_net_cmsg_action {\n+\tuint16_t action;\n+\tuint8_t queue;\n+\tuint8_t spare;\n+\tuint16_t mark_id;\n+};\n+\n enum nfp_net_cfg_mbox_cmd {\n \tNFP_NET_CFG_MBOX_CMD_FS_ADD_V4,       /* Add Flow Steer rule for V4 table */\n \tNFP_NET_CFG_MBOX_CMD_FS_DEL_V4,       /* Delete Flow Steer rule for V4 table */\ndiff --git a/drivers/net/nfp/nfp_net_common.h b/drivers/net/nfp/nfp_net_common.h\nindex 48791af93a..464a191a9c 100644\n--- a/drivers/net/nfp/nfp_net_common.h\n+++ b/drivers/net/nfp/nfp_net_common.h\n@@ -114,6 +114,7 @@ struct nfp_net_priv {\n \tuint32_t hash_seed; /**< Hash seed for hash tables in this structure. */\n \tstruct rte_hash *flow_table; /**< Hash table to store flow rules. */\n \tuint16_t flow_count; /**< Flow count in hash table */\n+\tbool flow_position[NFP_NET_FLOW_LIMIT]; /**< Flow position array */\n };\n \n struct nfp_app_fw_nic {\ndiff --git a/drivers/net/nfp/nfp_net_flow.c b/drivers/net/nfp/nfp_net_flow.c\nindex 6c02b0f82e..88386a31f0 100644\n--- a/drivers/net/nfp/nfp_net_flow.c\n+++ b/drivers/net/nfp/nfp_net_flow.c\n@@ -11,8 +11,9 @@\n #include <rte_malloc.h>\n \n #include \"nfp_logs.h\"\n+#include \"nfp_net_cmsg.h\"\n \n-__rte_unused static int\n+static int\n nfp_net_flow_table_add(struct nfp_net_priv *priv,\n \t\tstruct rte_flow *nfp_flow)\n {\n@@ -27,7 +28,7 @@ nfp_net_flow_table_add(struct nfp_net_priv *priv,\n \treturn 0;\n }\n \n-__rte_unused static int\n+static int\n nfp_net_flow_table_delete(struct nfp_net_priv *priv,\n \t\tstruct rte_flow *nfp_flow)\n {\n@@ -42,7 +43,7 @@ nfp_net_flow_table_delete(struct nfp_net_priv *priv,\n \treturn 0;\n }\n \n-__rte_unused static struct rte_flow *\n+static struct rte_flow *\n nfp_net_flow_table_search(struct nfp_net_priv *priv,\n \t\tstruct rte_flow *nfp_flow)\n {\n@@ -59,11 +60,58 @@ nfp_net_flow_table_search(struct nfp_net_priv *priv,\n \treturn flow_find;\n }\n \n-__rte_unused static struct rte_flow *\n-nfp_net_flow_alloc(uint32_t match_len,\n+static int\n+nfp_net_flow_position_acquire(struct nfp_net_priv *priv,\n+\t\tuint32_t priority,\n+\t\tstruct rte_flow *nfp_flow)\n+{\n+\tuint32_t i;\n+\n+\tif (priority != 0) {\n+\t\ti = NFP_NET_FLOW_LIMIT - priority - 1;\n+\n+\t\tif (priv->flow_position[i]) {\n+\t\t\tPMD_DRV_LOG(ERR, \"There is already a flow rule in this place.\");\n+\t\t\treturn -EAGAIN;\n+\t\t}\n+\n+\t\tpriv->flow_position[i] = true;\n+\t\tnfp_flow->position = priority;\n+\t\treturn 0;\n+\t}\n+\n+\tfor (i = 0; i < NFP_NET_FLOW_LIMIT; i++) {\n+\t\tif (!priv->flow_position[i]) {\n+\t\t\tpriv->flow_position[i] = true;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (i == NFP_NET_FLOW_LIMIT) {\n+\t\tPMD_DRV_LOG(ERR, \"The limited flow number is reach.\");\n+\t\treturn -ERANGE;\n+\t}\n+\n+\tnfp_flow->position = NFP_NET_FLOW_LIMIT - i - 1;\n+\n+\treturn 0;\n+}\n+\n+static void\n+nfp_net_flow_position_free(struct nfp_net_priv *priv,\n+\t\tstruct rte_flow *nfp_flow)\n+{\n+\tpriv->flow_position[nfp_flow->position] = false;\n+}\n+\n+static struct rte_flow *\n+nfp_net_flow_alloc(struct nfp_net_priv *priv,\n+\t\tuint32_t priority,\n+\t\tuint32_t match_len,\n \t\tuint32_t action_len,\n \t\tuint32_t port_id)\n {\n+\tint ret;\n \tchar *data;\n \tstruct rte_flow *nfp_flow;\n \tstruct nfp_net_flow_payload *payload;\n@@ -76,6 +124,10 @@ nfp_net_flow_alloc(uint32_t match_len,\n \tif (data == NULL)\n \t\tgoto free_flow;\n \n+\tret = nfp_net_flow_position_acquire(priv, priority, nfp_flow);\n+\tif (ret != 0)\n+\t\tgoto free_payload;\n+\n \tnfp_flow->port_id      = port_id;\n \tpayload                = &nfp_flow->payload;\n \tpayload->match_len     = match_len;\n@@ -85,19 +137,362 @@ nfp_net_flow_alloc(uint32_t match_len,\n \n \treturn nfp_flow;\n \n+free_payload:\n+\trte_free(data);\n free_flow:\n \trte_free(nfp_flow);\n \n \treturn NULL;\n }\n \n-__rte_unused static void\n-nfp_net_flow_free(struct rte_flow *nfp_flow)\n+static void\n+nfp_net_flow_free(struct nfp_net_priv *priv,\n+\t\tstruct rte_flow *nfp_flow)\n {\n+\tnfp_net_flow_position_free(priv, nfp_flow);\n \trte_free(nfp_flow->payload.match_data);\n \trte_free(nfp_flow);\n }\n \n+static int\n+nfp_net_flow_calculate_items(const struct rte_flow_item items[],\n+\t\tuint32_t *match_len)\n+{\n+\tconst struct rte_flow_item *item;\n+\n+\tfor (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; ++item) {\n+\t\tswitch (item->type) {\n+\t\tdefault:\n+\t\t\tPMD_DRV_LOG(ERR, \"Can't calculate match length\");\n+\t\t\t*match_len = 0;\n+\t\t\treturn -ENOTSUP;\n+\t\t}\n+\t}\n+\n+\treturn -EINVAL;\n+}\n+\n+static void\n+nfp_net_flow_process_priority(__rte_unused struct rte_flow *nfp_flow,\n+\t\tuint32_t match_len)\n+{\n+\tswitch (match_len) {\n+\tdefault:\n+\t\tbreak;\n+\t}\n+}\n+\n+static struct rte_flow *\n+nfp_net_flow_setup(struct rte_eth_dev *dev,\n+\t\tconst struct rte_flow_attr *attr,\n+\t\tconst struct rte_flow_item items[],\n+\t\t__rte_unused const struct rte_flow_action actions[])\n+{\n+\tint ret;\n+\tchar *hash_data;\n+\tuint32_t port_id;\n+\tuint32_t action_len;\n+\tstruct nfp_net_hw *hw;\n+\tuint32_t match_len = 0;\n+\tstruct nfp_net_priv *priv;\n+\tstruct rte_flow *nfp_flow;\n+\tstruct rte_flow *flow_find;\n+\tstruct nfp_app_fw_nic *app_fw_nic;\n+\n+\thw = dev->data->dev_private;\n+\tapp_fw_nic = NFP_PRIV_TO_APP_FW_NIC(hw->pf_dev->app_fw_priv);\n+\tpriv = app_fw_nic->ports[hw->idx]->priv;\n+\n+\tret = nfp_net_flow_calculate_items(items, &match_len);\n+\tif (ret != 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Key layers calculate failed.\");\n+\t\treturn NULL;\n+\t}\n+\n+\taction_len = sizeof(struct nfp_net_cmsg_action);\n+\tport_id = ((struct nfp_net_hw *)dev->data->dev_private)->nfp_idx;\n+\n+\tnfp_flow = nfp_net_flow_alloc(priv, attr->priority, match_len, action_len, port_id);\n+\tif (nfp_flow == NULL) {\n+\t\tPMD_DRV_LOG(ERR, \"Alloc nfp flow failed.\");\n+\t\treturn NULL;\n+\t}\n+\n+\t/* Calculate and store the hash_key for later use */\n+\thash_data = nfp_flow->payload.match_data;\n+\tnfp_flow->hash_key = rte_jhash(hash_data, match_len + action_len,\n+\t\t\tpriv->hash_seed);\n+\n+\t/* Find the flow in hash table */\n+\tflow_find = nfp_net_flow_table_search(priv, nfp_flow);\n+\tif (flow_find != NULL) {\n+\t\tPMD_DRV_LOG(ERR, \"This flow is already exist.\");\n+\t\tgoto free_flow;\n+\t}\n+\n+\tpriv->flow_count++;\n+\n+\tnfp_net_flow_process_priority(nfp_flow, match_len);\n+\n+\treturn nfp_flow;\n+\n+free_flow:\n+\tnfp_net_flow_free(priv, nfp_flow);\n+\n+\treturn NULL;\n+}\n+\n+static int\n+nfp_net_flow_teardown(struct nfp_net_priv *priv,\n+\t\t__rte_unused struct rte_flow *nfp_flow)\n+{\n+\tpriv->flow_count--;\n+\n+\treturn 0;\n+}\n+\n+static int\n+nfp_net_flow_offload(struct nfp_net_hw *hw,\n+\t\tstruct rte_flow *flow,\n+\t\tbool delete_flag)\n+{\n+\tint ret;\n+\tchar *tmp;\n+\tuint32_t msg_size;\n+\tstruct nfp_net_cmsg *cmsg;\n+\n+\tmsg_size = sizeof(uint32_t) + flow->payload.match_len +\n+\t\t\tflow->payload.action_len;\n+\tcmsg = nfp_net_cmsg_alloc(msg_size);\n+\tif (cmsg == NULL) {\n+\t\tPMD_DRV_LOG(ERR, \"Alloc cmsg failed.\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tcmsg->cmd = flow->payload.cmsg_type;\n+\tif (delete_flag)\n+\t\tcmsg->cmd++;\n+\n+\ttmp = (char *)cmsg->data;\n+\trte_memcpy(tmp, flow->payload.match_data, flow->payload.match_len);\n+\ttmp += flow->payload.match_len;\n+\trte_memcpy(tmp, flow->payload.action_data, flow->payload.action_len);\n+\n+\tret = nfp_net_cmsg_xmit(hw, cmsg, msg_size);\n+\tif (ret != 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Send cmsg failed.\");\n+\t\tret = -EINVAL;\n+\t\tgoto free_cmsg;\n+\t}\n+\n+free_cmsg:\n+\tnfp_net_cmsg_free(cmsg);\n+\n+\treturn ret;\n+}\n+\n+static int\n+nfp_net_flow_validate(struct rte_eth_dev *dev,\n+\t\tconst struct rte_flow_attr *attr,\n+\t\tconst struct rte_flow_item items[],\n+\t\tconst struct rte_flow_action actions[],\n+\t\tstruct rte_flow_error *error)\n+{\n+\tint ret;\n+\tstruct nfp_net_hw *hw;\n+\tstruct rte_flow *nfp_flow;\n+\tstruct nfp_net_priv *priv;\n+\tstruct nfp_app_fw_nic *app_fw_nic;\n+\n+\thw = dev->data->dev_private;\n+\tapp_fw_nic = NFP_PRIV_TO_APP_FW_NIC(hw->pf_dev->app_fw_priv);\n+\tpriv = app_fw_nic->ports[hw->idx]->priv;\n+\n+\tnfp_flow = nfp_net_flow_setup(dev, attr, items, actions);\n+\tif (nfp_flow == NULL) {\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\tNULL, \"This flow can not be offloaded.\");\n+\t}\n+\n+\tret = nfp_net_flow_teardown(priv, nfp_flow);\n+\tif (ret != 0) {\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\tNULL, \"Flow resource free failed.\");\n+\t}\n+\n+\tnfp_net_flow_free(priv, nfp_flow);\n+\n+\treturn 0;\n+}\n+\n+static struct rte_flow *\n+nfp_net_flow_create(struct rte_eth_dev *dev,\n+\t\tconst struct rte_flow_attr *attr,\n+\t\tconst struct rte_flow_item items[],\n+\t\tconst struct rte_flow_action actions[],\n+\t\tstruct rte_flow_error *error)\n+{\n+\tint ret;\n+\tstruct nfp_net_hw *hw;\n+\tstruct rte_flow *nfp_flow;\n+\tstruct nfp_net_priv *priv;\n+\tstruct nfp_app_fw_nic *app_fw_nic;\n+\n+\thw = dev->data->dev_private;\n+\tapp_fw_nic = NFP_PRIV_TO_APP_FW_NIC(hw->pf_dev->app_fw_priv);\n+\tpriv = app_fw_nic->ports[hw->idx]->priv;\n+\n+\tnfp_flow = nfp_net_flow_setup(dev, attr, items, actions);\n+\tif (nfp_flow == NULL) {\n+\t\trte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\tNULL, \"This flow can not be offloaded.\");\n+\t\treturn NULL;\n+\t}\n+\n+\t/* Add the flow to flow hash table */\n+\tret = nfp_net_flow_table_add(priv, nfp_flow);\n+\tif (ret != 0) {\n+\t\trte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\tNULL, \"Add flow to the flow table failed.\");\n+\t\tgoto flow_teardown;\n+\t}\n+\n+\t/* Add the flow to hardware */\n+\tret = nfp_net_flow_offload(hw, nfp_flow, false);\n+\tif (ret != 0) {\n+\t\trte_flow_error_set(error, EINVAL,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\tNULL, \"Add flow to firmware failed.\");\n+\t\tgoto table_delete;\n+\t}\n+\n+\treturn nfp_flow;\n+\n+table_delete:\n+\tnfp_net_flow_table_delete(priv, nfp_flow);\n+flow_teardown:\n+\tnfp_net_flow_teardown(priv, nfp_flow);\n+\tnfp_net_flow_free(priv, nfp_flow);\n+\n+\treturn NULL;\n+}\n+\n+static int\n+nfp_net_flow_destroy(struct rte_eth_dev *dev,\n+\t\tstruct rte_flow *nfp_flow,\n+\t\tstruct rte_flow_error *error)\n+{\n+\tint ret;\n+\tstruct nfp_net_hw *hw;\n+\tstruct nfp_net_priv *priv;\n+\tstruct rte_flow *flow_find;\n+\tstruct nfp_app_fw_nic *app_fw_nic;\n+\n+\thw = dev->data->dev_private;\n+\tapp_fw_nic = NFP_PRIV_TO_APP_FW_NIC(hw->pf_dev->app_fw_priv);\n+\tpriv = app_fw_nic->ports[hw->idx]->priv;\n+\n+\t/* Find the flow in flow hash table */\n+\tflow_find = nfp_net_flow_table_search(priv, nfp_flow);\n+\tif (flow_find == NULL) {\n+\t\trte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\tNULL, \"Flow does not exist.\");\n+\t\tret = -EINVAL;\n+\t\tgoto exit;\n+\t}\n+\n+\t/* Delete the flow from hardware */\n+\tret = nfp_net_flow_offload(hw, nfp_flow, true);\n+\tif (ret != 0) {\n+\t\trte_flow_error_set(error, EINVAL,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\tNULL, \"Delete flow from firmware failed.\");\n+\t\tret = -EINVAL;\n+\t\tgoto exit;\n+\t}\n+\n+\t/* Delete the flow from flow hash table */\n+\tret = nfp_net_flow_table_delete(priv, nfp_flow);\n+\tif (ret != 0) {\n+\t\trte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\tNULL, \"Delete flow from the flow table failed.\");\n+\t\tret = -EINVAL;\n+\t\tgoto exit;\n+\t}\n+\n+\tret = nfp_net_flow_teardown(priv, nfp_flow);\n+\tif (ret != 0) {\n+\t\trte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\tNULL, \"Flow teardown failed.\");\n+\t\tret = -EINVAL;\n+\t\tgoto exit;\n+\t}\n+\n+exit:\n+\tnfp_net_flow_free(priv, nfp_flow);\n+\n+\treturn ret;\n+}\n+\n+static int\n+nfp_net_flow_flush(struct rte_eth_dev *dev,\n+\t\tstruct rte_flow_error *error)\n+{\n+\tint ret = 0;\n+\tvoid *next_data;\n+\tuint32_t iter = 0;\n+\tconst void *next_key;\n+\tstruct nfp_net_hw *hw;\n+\tstruct rte_flow *nfp_flow;\n+\tstruct rte_hash *flow_table;\n+\tstruct nfp_app_fw_nic *app_fw_nic;\n+\n+\thw = dev->data->dev_private;\n+\tapp_fw_nic = NFP_PRIV_TO_APP_FW_NIC(hw->pf_dev->app_fw_priv);\n+\tflow_table = app_fw_nic->ports[hw->idx]->priv->flow_table;\n+\n+\twhile (rte_hash_iterate(flow_table, &next_key, &next_data, &iter) >= 0) {\n+\t\tnfp_flow = next_data;\n+\t\tret = nfp_net_flow_destroy(dev, nfp_flow, error);\n+\t\tif (ret != 0)\n+\t\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static const struct rte_flow_ops nfp_net_flow_ops = {\n+\t.validate                = nfp_net_flow_validate,\n+\t.create                  = nfp_net_flow_create,\n+\t.destroy                 = nfp_net_flow_destroy,\n+\t.flush                   = nfp_net_flow_flush,\n+};\n+\n+int\n+nfp_net_flow_ops_get(struct rte_eth_dev *dev,\n+\t\tconst struct rte_flow_ops **ops)\n+{\n+\tstruct nfp_net_hw *hw;\n+\n+\tif ((dev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR) != 0) {\n+\t\t*ops = NULL;\n+\t\tPMD_DRV_LOG(ERR, \"Port is a representor.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\thw = dev->data->dev_private;\n+\tif ((hw->super.cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER) == 0) {\n+\t\t*ops = NULL;\n+\t\treturn 0;\n+\t}\n+\n+\t*ops = &nfp_net_flow_ops;\n+\n+\treturn 0;\n+}\n+\n int\n nfp_net_flow_priv_init(struct nfp_pf_dev *pf_dev,\n \t\tuint16_t port)\ndiff --git a/drivers/net/nfp/nfp_net_flow.h b/drivers/net/nfp/nfp_net_flow.h\nindex 5ec80ba3b6..558cd0e2bb 100644\n--- a/drivers/net/nfp/nfp_net_flow.h\n+++ b/drivers/net/nfp/nfp_net_flow.h\n@@ -20,9 +20,11 @@ struct rte_flow {\n \tstruct nfp_net_flow_payload payload;\n \tuint32_t hash_key;\n \tuint32_t port_id;\n+\tuint32_t position;    /**< Use as priority */\n };\n \n int nfp_net_flow_priv_init(struct nfp_pf_dev *pf_dev, uint16_t port);\n void nfp_net_flow_priv_uninit(struct nfp_pf_dev *pf_dev, uint16_t port);\n+int nfp_net_flow_ops_get(struct rte_eth_dev *dev, const struct rte_flow_ops **ops);\n \n #endif /* __NFP_NET_FLOW_H__ */\n",
    "prefixes": [
        "04/11"
    ]
}