get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 131093,
    "url": "http://patchwork.dpdk.org/api/patches/131093/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20230901121824.3250409-5-mko-plv@napatech.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": "<20230901121824.3250409-5-mko-plv@napatech.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230901121824.3250409-5-mko-plv@napatech.com",
    "date": "2023-09-01T12:18:21",
    "name": "[v13,5/8] net/ntnic: adds FPGA abstraction layer",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "fb25be8cd66c3534f63cc5f0be442b4a86bdce3f",
    "submitter": {
        "id": 3153,
        "url": "http://patchwork.dpdk.org/api/people/3153/?format=api",
        "name": "Mykola Kostenok",
        "email": "mko-plv@napatech.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patchwork.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20230901121824.3250409-5-mko-plv@napatech.com/mbox/",
    "series": [
        {
            "id": 29404,
            "url": "http://patchwork.dpdk.org/api/series/29404/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=29404",
            "date": "2023-09-01T12:18:20",
            "name": "[v13,1/8] net/ntnic: initial commit which adds register defines",
            "version": 13,
            "mbox": "http://patchwork.dpdk.org/series/29404/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/131093/comments/",
    "check": "warning",
    "checks": "http://patchwork.dpdk.org/api/patches/131093/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 C30ED42220;\n\tFri,  1 Sep 2023 14:19:54 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 6C04A402CE;\n\tFri,  1 Sep 2023 14:18:32 +0200 (CEST)",
            "from egress-ip4a.ess.de.barracuda.com\n (egress-ip4a.ess.de.barracuda.com [18.184.203.227])\n by mails.dpdk.org (Postfix) with ESMTP id BD1F2402D0\n for <dev@dpdk.org>; Fri,  1 Sep 2023 14:18:30 +0200 (CEST)",
            "from EUR04-DB3-obe.outbound.protection.outlook.com\n (mail-db3eur04lp2050.outbound.protection.outlook.com [104.47.12.50]) by\n mx-outbound14-5.eu-central-1a.ess.aws.cudaops.com (version=TLSv1.2\n cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO);\n Fri, 01 Sep 2023 12:18:15 +0000",
            "from DUZPR01CA0028.eurprd01.prod.exchangelabs.com\n (2603:10a6:10:46b::7) by PA4P190MB1358.EURP190.PROD.OUTLOOK.COM\n (2603:10a6:102:104::9) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6745.20; Fri, 1 Sep\n 2023 12:18:00 +0000",
            "from DB5PEPF00014B9C.eurprd02.prod.outlook.com\n (2603:10a6:10:46b:cafe::8e) by DUZPR01CA0028.outlook.office365.com\n (2603:10a6:10:46b::7) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.36 via Frontend\n Transport; Fri, 1 Sep 2023 12:17:59 +0000",
            "from k8s-node.default.svc.cluster.local (178.72.21.4) by\n DB5PEPF00014B9C.mail.protection.outlook.com (10.167.8.170) with Microsoft\n SMTP Server id 15.20.6745.17 via Frontend Transport; Fri, 1 Sep 2023 12:17:59\n +0000"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=TZXo4YNuwpQkKQosAEvySb7BaMwvm0DPMo13J1E1MhGNPA+ai/Mb62bcR0bRTZ3q1X8bK8wU+HfnjEbHuZd+BbviPC6RAo/UjvRGxbDszbS0ulBZ1g+TrMBt1nmUakdIhLmGD49TSjY+GMSKtY9tY0aU8xlBuuVR9yc4oAv3U+1rtQBiFRHaibMMB8uIXowc9CPGm51WNq16imd1Cedb9G9Vc/vFYwoP5U9pgRV2ouDQpLxu0YagCGmx+MpG8F0kNm+8aejnUZ9KVFOBRI0xssF9xxyMVAKPDJDEyqDdZhoQPXc2msrvmHFfxxa/gU7pjyf20FnOJ9ZmwoGrst79Dw==",
        "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=mZPaMPcC3AxS5JE8RU3ziL8WjIhbf6y0YeiyZnHF4Wg=;\n b=oYNJq2QURRkifrVyvZRCKFPgKjJTpRHL1yQMsKVFGNziiGXaskstNORGRHYde6Gb8WWKmEqjN47QN3jWyG527xjeh5ysM8xKSsYs92J6Q46ErOjJ6sB1VgzOOjeDZmapO8aRiMM6vyPJ3AOCeGcL08M/LDJAjlM3M6UIwfTLZfbMBH2Bv209DhrDRwn7KnG47CX7JzjwtWCOnQTNus+X0jYBO1FXXWBgw5yzovt+H/3FhEM3K+TEsmQBzYvCMvnWRizt+fDmuazLpnvr4xO03slobStY3M3YUdJiCSrcqSACNN7OEOG16eGKugiU2pZtBwQX20qiMuCbRJ6+Cgpq6g==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=fail (sender ip is\n 178.72.21.4) smtp.rcpttodomain=dpdk.org smtp.mailfrom=napatech.com;\n dmarc=fail (p=none sp=none pct=100) action=none header.from=napatech.com;\n dkim=none (message not signed); arc=none",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=napatech.com;\n s=selector1;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=mZPaMPcC3AxS5JE8RU3ziL8WjIhbf6y0YeiyZnHF4Wg=;\n b=G0slkD0WCzxq9+EIFJDjIRYQvA31hGKENcidQ1SUinYXyke7r45607g4atDROxdZUUD+cVsmTZrdeTA6v8QKSw59+1WJxlfPheYFq4/V6v9+hfTkszDKNDjG/Ff7zWoSFqzdgWumsZdXU2mHYRVmA187AQ9ThTL6M9zijWJlQJA=",
        "X-MS-Exchange-Authentication-Results": "spf=fail (sender IP is 178.72.21.4)\n smtp.mailfrom=napatech.com; dkim=none (message not signed)\n header.d=none;dmarc=fail action=none header.from=napatech.com;",
        "Received-SPF": "Fail (protection.outlook.com: domain of napatech.com does not\n designate 178.72.21.4 as permitted sender) receiver=protection.outlook.com;\n client-ip=178.72.21.4; helo=k8s-node.default.svc.cluster.local;",
        "From": "Mykola Kostenok <mko-plv@napatech.com>",
        "To": "dev@dpdk.org",
        "Cc": "mko-plv@napatech.com, thomas@monjalon.net, ckm@napatech.com,\n andrew.rybchenko@oktetlabs.ru, ferruh.yigit@amd.com",
        "Subject": "[PATCH v13 5/8] net/ntnic: adds FPGA abstraction layer",
        "Date": "Fri,  1 Sep 2023 14:18:21 +0200",
        "Message-Id": "<20230901121824.3250409-5-mko-plv@napatech.com>",
        "X-Mailer": "git-send-email 2.39.3",
        "In-Reply-To": "<20230901121824.3250409-1-mko-plv@napatech.com>",
        "References": "<20230816132552.2483752-1-mko-plv@napatech.com>\n <20230901121824.3250409-1-mko-plv@napatech.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-EOPAttributedMessage": "0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "DB5PEPF00014B9C:EE_|PA4P190MB1358:EE_",
        "Content-Type": "text/plain",
        "X-MS-Office365-Filtering-Correlation-Id": "f099ed55-8a38-493d-be2a-08dbaae57b83",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n gDfG6yLgGuwew4v18+e4OUiX9KGglOSzKsYY4wua5+gRljq5yUf80Ohoa8gdro0WiHo8UXoyWS2CY7OHxq+u/QBT331asCHvbfkUUTKnVinQGd3L9JMaxdFQiGX8SvbT0XTkBAmhlFUHtsWTJZ4t8xGT83Qk8JZyPqsfYnbRsczRENiCIq3xgHc9YrdPdECIYLrycuJwxVe0FM2CGrvxZ/VTxF7HQe7GJsCl4x5WvrnWgxcIskKb3c0zV0cY2aNj1Ck4pzw1KwCbyaM0CNHvxBA2iWdrpY0uCWyZavlLUWq5TjSsP+mjzvNA6UuemrQUKspgCK6h6R3Ljw5Zr44VZ1ElmKT8VE/JTlr0KUs3PAvN88IHj2ykrtY5xFF1bA2HFvXM7d/4+ovfyosfrWPGRR+V04gYlMCo9TK5BWn2Wshkb1lSXGajPOE7sRwHMqs2i+BMDAUzPgfZJnEpwhA3925V/u5xn7ViXIDpOs+KJjxma/nULkg7/JF8g7Qz3CE8zktRpWj6QZ0pEX2lqYUvqOh9lijMozfp986YBvnYWvSiuzskOLkkqckRlqEUnVbUkJcuroUziBpDdTKzpuLaeWuq11BHzvWs3gsDOZJpU5KyRkTTF+SpeHYv386XDfYBuT/bdtjebs7I2TY/5Coz1vCVcCzMITbn5xofQf1mlfZN03tbrv7CSBAyCPe1vZvw1UoV6mtztw+6azDeBa4lBwAxPWUiRdzj1KDRVgdTQFkwI733jmg9+L1+AFJq1yzAZUpW5Dwpi2H2xCS6rtXx1NMU4E35HKHIpNzgh5WyPWo=",
        "X-Forefront-Antispam-Report": "CIP:178.72.21.4; CTRY:DK; LANG:en; SCL:1; SRV:;\n IPV:NLI; SFV:NSPM; H:k8s-node.default.svc.cluster.local;\n PTR:InfoDomainNonexistent; CAT:NONE;\n SFS:(13230031)(136003)(376002)(39840400004)(396003)(346002)(1800799009)(186009)(451199024)(82310400011)(36840700001)(46966006)(40480700001)(316002)(36736006)(30864003)(70586007)(70206006)(6916009)(81166007)(356005)(2906002)(41300700001)(8936002)(5660300002)(8676002)(4326008)(2616005)(6486002)(956004)(86362001)(83380400001)(6506007)(6512007)(336012)(47076005)(36860700001)(26005)(6666004)(1076003)(478600001)(9316004)(36756003)(21314003)(36900700001)(559001)(579004)(309714004);\n DIR:OUT; SFP:1101;",
        "X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount": "1",
        "X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0": "\n BZyCNYdeQd0QLiVuVuKeDYs6M9yEKe80zdw2+kwrwma1AVVVYAwg4cmxxS8rHH2O58YGunKGlYIR04fhlQSTUYovMNazJ9EvYm2HHj1KPus27UxPIkjm/X94B+92L8uuPS2If4PeeapaeHoYo5gSLRx7phdCkBp+Jbnzu2r9vHJxs7yE8tiwLOsigIXMC5flDVa8PEaVHd8q8flKPIRirKU8gWWGLFeNE/shs0iAzjxPWy8FxDY8Dgiob1KUv7ngEUAVYv2WfmDmOozTCzQ1FzlqvinFH4sl1RKLyVWGyJqVGPqokHlno9qQcikQOr8hKftshcjH5/zKsUxtf3J68HniB+iZ+gQQxf3KFosco+kIYFwMh+gpsinMRZEF1+d3WzHUIiGZIgFDzdIZ/ToHsO9a9BbH86Zzy7poebb7DRX4AW2j1ovFhQdqF0W40w5iNlFA/dxB1LQ30xAYu21Gle/BU94syCGLtAW2PCjjPLx8h4vqbOgTQHJI/RbbOHfRrTJWsuPlRhlO94oBzrwJj9OE3lYGE0/3ZKC0Eqp3IuI7Kii08bdqlQtz3Mpbe8reo559k8+X3TomAVK0kR8iQUqZ/cbiIuoYZz7yGZxiKyGHnBdiI8wtLeIpF1872nxdhQxClEdddlK/CVh2HeqbL2hGeMaQ2R8+n69esB4u+NXUeQNomSHI7bHZjsggcfLFDg7a0OOxIkJdVY3P3gk8HPtAx0soA9/QeG3A+0yIllr/hi+yJLlynonwmKRqw721YKsfjQIh/N9YDvfNu+nhwxoLnWqlMaX+wIn6yJ9bXrg=",
        "X-OriginatorOrg": "napatech.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "01 Sep 2023 12:17:59.7021 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n f099ed55-8a38-493d-be2a-08dbaae57b83",
        "X-MS-Exchange-CrossTenant-Id": "c4540d0b-728a-4233-9da5-9ea30c7ec3ed",
        "X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp": "\n TenantId=c4540d0b-728a-4233-9da5-9ea30c7ec3ed; Ip=[178.72.21.4];\n Helo=[k8s-node.default.svc.cluster.local]",
        "X-MS-Exchange-CrossTenant-AuthSource": "\n DB5PEPF00014B9C.eurprd02.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "PA4P190MB1358",
        "X-BESS-ID": "1693570695-303589-16401-17888-1",
        "X-BESS-VER": "2019.1_20230831.1729",
        "X-BESS-Apparent-Source-IP": "104.47.12.50",
        "X-BESS-Parts": "H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKViYGFgaWxkB2BlA4zdw0zSjRwi\n Q52TTJ1CzFwiDVxNAgOc0izdAo0cjAIlWpNhYAw2aWv0MAAAA=",
        "X-BESS-Outbound-Spam-Score": "0.00",
        "X-BESS-Outbound-Spam-Report": "Code version 3.2,\n rules version 3.2.2.250535 [from\n cloudscan17-210.eu-central-1b.ess.aws.cudaops.com]\n Rule breakdown below\n pts rule name              description\n ---- ---------------------- --------------------------------\n 0.00 LARGE_BODY_SHORTCUT    META:  ",
        "X-BESS-Outbound-Spam-Status": "SCORE=0.00 using account:ESS113687 scores of\n KILL_LEVEL=7.0 tests=LARGE_BODY_SHORTCUT",
        "X-BESS-BRTS-Status": "1",
        "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": "From: Christian Koue Muf <ckm@napatech.com>\n\nThe FPGA abstraction layer limits the need to rewrite flow logic\nwhen new FPGA modules are created.\n\nSigned-off-by: Christian Koue Muf <ckm@napatech.com>\nReviewed-by: Mykola Kostenok <mko-plv@napatech.com>\n---\nv2:\n* Fixed compilation with Fedora 38\n* Fixed WARNING:TYPO_SPELLING\nv11:\n* Fix dereferencing type-punned pointer in macro\nv13:\n* Fix typo spelling warnings\n---\n drivers/net/ntnic/meson.build                 |   21 +\n .../ntnic/nthw/flow_api/flow_api_actions.c    |  205 ++\n .../ntnic/nthw/flow_api/flow_api_actions.h    |  284 +++\n .../ntnic/nthw/flow_api/flow_api_backend.c    |  182 ++\n .../ntnic/nthw/flow_api/flow_api_backend.h    | 1818 +++++++++++++++++\n .../net/ntnic/nthw/flow_api/flow_api_engine.h |  475 +++++\n .../ntnic/nthw/flow_api/flow_api_nic_setup.h  |   32 +\n .../nthw/flow_api/flow_engine/flow_group.c    |  125 ++\n .../nthw/flow_api/flow_engine/flow_hasher.c   |  213 ++\n .../nthw/flow_api/flow_engine/flow_hasher.h   |   20 +\n .../nthw/flow_api/flow_engine/flow_kcc.c      |  434 ++++\n .../ntnic/nthw/flow_api/flow_engine/flow_km.c | 1434 +++++++++++++\n .../nthw/flow_api/flow_engine/flow_tunnel.c   |  787 +++++++\n .../ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c   | 1789 ++++++++++++++++\n .../nthw/flow_api/hw_mod/hw_mod_cat_v18.h     |  138 ++\n .../nthw/flow_api/hw_mod/hw_mod_cat_v21.h     |   88 +\n .../nthw/flow_api/hw_mod/hw_mod_cat_v22.h     |   83 +\n .../ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c   | 1099 ++++++++++\n .../nthw/flow_api/hw_mod/hw_mod_flm_v17.h     |  265 +++\n .../nthw/flow_api/hw_mod/hw_mod_flm_v20.h     |  102 +\n .../ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c   |  195 ++\n .../nthw/flow_api/hw_mod/hw_mod_hsh_v5.h      |   36 +\n .../ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c   |  178 ++\n .../nthw/flow_api/hw_mod/hw_mod_hst_v2.h      |   32 +\n .../ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c   |  271 +++\n .../nthw/flow_api/hw_mod/hw_mod_ioa_v4.h      |   36 +\n .../ntnic/nthw/flow_api/hw_mod/hw_mod_km.c    |  629 ++++++\n .../ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h |   93 +\n .../ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c   |  219 ++\n .../nthw/flow_api/hw_mod/hw_mod_pdb_v9.h      |   39 +\n .../ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c   |  348 ++++\n .../nthw/flow_api/hw_mod/hw_mod_qsl_v7.h      |   45 +\n .../ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c   |  112 +\n .../nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h    |   20 +\n .../ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c   |  358 ++++\n .../nthw/flow_api/hw_mod/hw_mod_roa_v6.h      |   49 +\n .../ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c   |  132 ++\n .../nthw/flow_api/hw_mod/hw_mod_slc_lr.c      |  132 ++\n .../nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h   |   19 +\n .../nthw/flow_api/hw_mod/hw_mod_slc_v1.h      |   19 +\n .../ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c   |  983 +++++++++\n .../nthw/flow_api/hw_mod/hw_mod_tpe_v1.h      |  103 +\n .../nthw/flow_api/hw_mod/hw_mod_tpe_v2.h      |   37 +\n .../nthw/flow_api/stream_binary_flow_api.h    |  697 +++++++\n 44 files changed, 14376 insertions(+)\n create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_actions.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_actions.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_backend.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_backend.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_engine.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h\n create mode 100644 drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h",
    "diff": "diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build\nindex 8c065ee9a3..8a5a3d5deb 100644\n--- a/drivers/net/ntnic/meson.build\n+++ b/drivers/net/ntnic/meson.build\n@@ -18,6 +18,7 @@ includes = [\n     include_directories('nthw'),\n     include_directories('nthw/core'),\n     include_directories('nthw/supported'),\n+    include_directories('nthw/flow_api'),\n     include_directories('nthw/flow_filter'),\n     include_directories('sensors'),\n     include_directories('sensors/avr_sensors'),\n@@ -60,6 +61,26 @@ sources = files(\n     'nthw/core/nthw_spim.c',\n     'nthw/core/nthw_spis.c',\n     'nthw/core/nthw_tsm.c',\n+    'nthw/flow_api/flow_api_actions.c',\n+    'nthw/flow_api/flow_api_backend.c',\n+    'nthw/flow_api/flow_engine/flow_group.c',\n+    'nthw/flow_api/flow_engine/flow_hasher.c',\n+    'nthw/flow_api/flow_engine/flow_kcc.c',\n+    'nthw/flow_api/flow_engine/flow_km.c',\n+    'nthw/flow_api/flow_engine/flow_tunnel.c',\n+    'nthw/flow_api/hw_mod/hw_mod_cat.c',\n+    'nthw/flow_api/hw_mod/hw_mod_flm.c',\n+    'nthw/flow_api/hw_mod/hw_mod_hsh.c',\n+    'nthw/flow_api/hw_mod/hw_mod_hst.c',\n+    'nthw/flow_api/hw_mod/hw_mod_ioa.c',\n+    'nthw/flow_api/hw_mod/hw_mod_km.c',\n+    'nthw/flow_api/hw_mod/hw_mod_pdb.c',\n+    'nthw/flow_api/hw_mod/hw_mod_qsl.c',\n+    'nthw/flow_api/hw_mod/hw_mod_rmc.c',\n+    'nthw/flow_api/hw_mod/hw_mod_roa.c',\n+    'nthw/flow_api/hw_mod/hw_mod_slc.c',\n+    'nthw/flow_api/hw_mod/hw_mod_slc_lr.c',\n+    'nthw/flow_api/hw_mod/hw_mod_tpe.c',\n     'nthw/flow_filter/flow_nthw_cat.c',\n     'nthw/flow_filter/flow_nthw_csu.c',\n     'nthw/flow_filter/flow_nthw_flm.c',\ndiff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_actions.c b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.c\nnew file mode 100644\nindex 0000000000..945ab7d743\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.c\n@@ -0,0 +1,205 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdio.h>\n+#include <stdarg.h>\n+#include <string.h>\n+#include <stdlib.h>\n+#include <assert.h>\n+#include <arpa/inet.h> /* htons, htonl, ntohs */\n+\n+#include \"ntlog.h\"\n+\n+#include \"stream_binary_flow_api.h\"\n+#include \"flow_api_actions.h\"\n+#include \"flow_api_backend.h\"\n+#include \"flow_api_engine.h\"\n+\n+int flow_actions_create_roa_tunhdr(struct flow_api_backend_s *be, int index,\n+\t\t\t\t   struct tunnel_header_s *tun)\n+{\n+\tint err = 0;\n+\tint num_writes = (tun->ip_version == 4) ? 4 : 8;\n+\n+\t/*\n+\t * Write 4 * 4 words = 64 bytes (IPv4) or 8 * 4 words = 128 bytes (IPv6)\n+\t */\n+\tfor (int i = 0; (i < num_writes) && !err; i++) {\n+\t\tfor (int ii = 0; (ii < 4) && !err; ii++) {\n+\t\t\t/* must write each 4 words backwards! */\n+\t\t\terr |= hw_mod_roa_tunhdr_set(be, HW_ROA_TUNHDR,\n+\t\t\t\t\t\t     index, i * 4 + ii,\n+\t\t\t\t\t\t     ntohl(tun->d.hdr32[(i + 1) * 4 - ii - 1]));\n+\t\t}\n+\t}\n+\n+\treturn err;\n+}\n+\n+int flow_actions_create_roa_tuncfg(struct flow_api_backend_s *be, int index,\n+\t\t\t\t   uint64_t color_actions)\n+{\n+\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_PRESET_ALL, index, 0);\n+\t/*\n+\t * If tunnel header specified\n+\t */\n+\tint tun_len = get_roa_tunhdr_len(color_actions);\n+\n+\tif (tun_len) {\n+\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TUN_LEN, index,\n+\t\t\t\t      tun_len);\n+\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TUN_TYPE, index,\n+\t\t\t\t      roa_get_tun_type(color_actions));\n+\n+\t\t/* set the total tunnel IP header length */\n+\t\tif (get_roa_tun_ip_type(color_actions) == 1) {\n+\t\t\t/* IPv6 */\n+\t\t\tif ((size_t)tun_len > (sizeof(struct flow_elem_eth) +\n+\t\t\t\t\t       sizeof(struct flow_elem_ipv6))) {\n+\t\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_UPD, index, 1);\n+\t\t\t\t/* tunnel header length excludes the IPv6 header itself */\n+\t\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_PRECALC, index,\n+\t\t\t\t\t(uint32_t)(tun_len -\n+\t\t\t\t\t\t   (sizeof(struct flow_elem_eth) +\n+\t\t\t\t\t\t    sizeof(struct flow_elem_ipv6))));\n+\t\t\t}\n+\t\t} else {\n+\t\t\t/* IPv4 */\n+\t\t\tif ((size_t)tun_len > sizeof(struct flow_elem_eth)) {\n+\t\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_UPD,\n+\t\t\t\t\t\t      index, 1);\n+\t\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_PRECALC, index,\n+\t\t\t\t\t(uint32_t)(tun_len -\n+\t\t\t\t\t\t   sizeof(struct flow_elem_eth)));\n+\t\t\t}\n+\t\t}\n+\n+\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IP_TYPE, index,\n+\t\t\t\t      get_roa_tun_ip_type(color_actions));\n+\n+\t\tif (get_roa_tun_ip_type(color_actions) == 1) {\n+\t\t\t/* IPv6 - Do not update the IP checksum in the tunnel header */\n+\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_UPD, index,\n+\t\t\t\t\t      0);\n+\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_PRECALC,\n+\t\t\t\t\t      index, 0);\n+\t\t} else {\n+\t\t\t/* IPv4 */\n+\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_UPD,\n+\t\t\t\t\t      index, 1);\n+\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_PRECALC,\n+\t\t\t\t\t      index,\n+\t\t\t\t\t      get_roa_tun_ip_csum(color_actions));\n+\t\t}\n+\n+\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_VXLAN_UDP_LEN_UPD,\n+\t\t\t\t      index, 1);\n+\n+\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_PUSH_TUNNEL, index, 1);\n+\t}\n+\n+\t/* bypass must be > 0 or recirculate_port >= 0 - bypass wins */\n+\tuint8_t recirculate_bypass = roa_get_recirc_bypass_port(color_actions);\n+\n+\tif (recirculate_bypass) {\n+\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_BYPASS, index,\n+\t\t\t\t      recirculate_bypass);\n+\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRCULATE, index, 1);\n+\n+\t} else {\n+\t\tint32_t recirculate_port = roa_get_recirc_port(color_actions);\n+\n+\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_BYPASS, index,\n+\t\t\t\t      255);\n+\n+\t\tif (recirculate_port >= 0) {\n+\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_PORT,\n+\t\t\t\t\t      index, recirculate_port);\n+\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRCULATE,\n+\t\t\t\t\t      index, 1);\n+\t\t}\n+\t}\n+\n+\tuint8_t tx = roa_get_tx(color_actions);\n+\n+\tif (tx) {\n+\t\tif (tx == DESTINATION_TX_PHY0) {\n+\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TX_LAG_IX,\n+\t\t\t\t\t      index, ROA_TX_PHY0);\n+\t\t} else if (tx == DESTINATION_TX_PHY1) {\n+\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TX_LAG_IX,\n+\t\t\t\t\t      index, ROA_TX_PHY1);\n+\t\t} else if (tx == (DESTINATION_TX_PHY0 | DESTINATION_TX_PHY1)) {\n+\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TX_LAG_IX,\n+\t\t\t\t\t      index, ROA_TX_PHY0);\n+\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_BYPASS,\n+\t\t\t\t\t      index, 0x81); /* port 1 - only port left */\n+\t\t\thw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRCULATE,\n+\t\t\t\t\t      index, 1);\n+\n+\t\t} else {\n+\t\t\treturn -1; /* ERR */\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Special IOA memory that contains ROA information - bad FPGA design\n+\t */\n+\tif (tx || tun_len) {\n+\t\tif (be->ioa.ver > 3 && tun_len &&\n+\t\t\t\tget_roa_tun_ip_type(color_actions) == 1) {\n+\t\t\t/* IPv6 VxLAN tunnel. Select EPP recipe 2 */\n+\t\t\thw_mod_ioa_roa_epp_set(be, HW_IOA_ROA_EPP_PUSH_TUNNEL,\n+\t\t\t\t\t       index, 2);\n+\t\t} else {\n+\t\t\t/* IPv4 VxLAN tunnel or no tunnel (select recipe 1 or 0) */\n+\t\t\thw_mod_ioa_roa_epp_set(be, HW_IOA_ROA_EPP_PUSH_TUNNEL,\n+\t\t\t\t\t       index, !!tun_len);\n+\t\t}\n+\t\thw_mod_ioa_roa_epp_set(be, HW_IOA_ROA_EPP_TX_PORT, index, tx);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int flow_actions_create_ioa_config(struct flow_api_backend_s *be, int index,\n+\t\t\t\t   uint64_t color_actions)\n+{\n+\tif (color_actions & ioa_set_vxlan_pop(0)) {\n+\t\thw_mod_ioa_rcp_set(be, HW_IOA_RCP_TUNNEL_POP, index, 1);\n+\t\tNT_LOG(DBG, FILTER, \"Pop outer Tunnel (Vxlan)\\n\");\n+\t}\n+\n+\tif (color_actions & ioa_set_vlan_pop(0)) {\n+\t\thw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_POP, index, 1);\n+\t\tNT_LOG(DBG, FILTER, \"Pop outer Vlan\\n\");\n+\t}\n+\n+\tint tpid_sel = ioa_get_tpid_sel(color_actions);\n+\n+\tif (color_actions & ioa_set_vlan_push(0, 0)) {\n+\t\tuint16_t tci = ioa_get_vlan_tci(color_actions);\n+\n+\t\tNT_LOG(DBG, FILTER, \"Push Vlan with TPID/TCI %04x/%04x\\n\",\n+\t\t       tpid_sel ? 0x88a8 : 0x8100, tci);\n+\t\thw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_VID, index,\n+\t\t\t\t   tci & 0x0FFF);\n+\t\thw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_DEI, index,\n+\t\t\t\t   (tci >> 12) & 0x1);\n+\t\thw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_PCP, index,\n+\t\t\t\t   (tci >> 13) & 0x7);\n+\t\thw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_PUSH, index, 1);\n+\t}\n+\n+\tint queue = ioa_get_queue(color_actions);\n+\n+\tif (queue >= 0) {\n+\t\thw_mod_ioa_rcp_set(be, HW_IOA_RCP_QUEUE_OVERRIDE_EN, index, 1);\n+\t\thw_mod_ioa_rcp_set(be, HW_IOA_RCP_QUEUE_ID, index, queue);\n+\t}\n+\n+\thw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_TPID_SEL, index, tpid_sel);\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_actions.h b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.h\nnew file mode 100644\nindex 0000000000..400066e817\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.h\n@@ -0,0 +1,284 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _FLOW_ACTIONS_H_\n+#define _FLOW_ACTIONS_H_\n+\n+struct flow_api_backend_s;\n+struct tunnel_header_s;\n+\n+#define MAX_COLOR_FLOW_STATS 0x400\n+\n+#define ROA_RECIRC_BYPASS_PHY_OFFSET 0x80\n+#define MAX_REPLICATION_PORTS 2\n+\n+enum {\n+\tDESTINATION_TX_NONE = 0,\n+\tDESTINATION_TX_PHY0 = 1,\n+\tDESTINATION_TX_PHY1 = 2\n+};\n+\n+enum { TUN_IPV4 = 0, TUN_IPV6 };\n+\n+enum {\n+\tVLAN_TPID_802_1Q = 0,\n+\tVLAN_TPID_802_1AD,\n+\tVLAN_TPID_CUSTOM_0,\n+\tVLAN_TPID_CUSTOM_1\n+};\n+\n+enum { ROA_TX_NO_RETRANSMIT = 0, ROA_TX_PHY0, ROA_TX_PHY1, ROA_TX_RESERVED };\n+\n+/*\n+ * before version 6 of QSL\n+ */\n+#if (MAX_COLOR_FLOW_STATS == 0x4000)\n+#define MAX_HW_FLOW_STATS_OLD 0x3fff\n+\n+#else\n+#if (MAX_COLOR_FLOW_STATS == 0x400)\n+#define MAX_HW_FLOW_STATS_OLD 0x03ff\n+#else\n+#error *** Unsupported number of color statistics counter ***\n+#endif\n+#endif\n+\n+/*\n+ * OLD behavior substituted from 4.1+\n+ *\n+ * 13:0   Mark (color) 16384 flow stats\n+ * 21:14  IOA index      256 entries\n+ * 29:22  ROA index      256 entries\n+ * 31:30  1 to indicate this layout\n+ * or\n+ *  9:0   Mark (color) 1024 flow stats\n+ * 19:10  IOA index    1024 entries\n+ * 29:20  ROA index    1024 entries\n+ * 31:30  0 to indicate this layout\n+ */\n+static inline uint32_t set_color_action_old(uint32_t color, uint32_t ioa_rcp,\n+\t\tuint32_t roa_rcp)\n+{\n+#if (MAX_COLOR_FLOW_STATS == 0x400)\n+\tuint32_t color_action = (color & MAX_HW_FLOW_STATS_OLD) |\n+\t\t\t\t((ioa_rcp & 0x3ff) << 10) |\n+\t\t\t\t((roa_rcp & 0x3ff) << 20) | (0 << 30);\n+#else\n+\tuint32_t color_action = (color & MAX_HW_FLOW_STATS_OLD) |\n+\t\t\t\t((ioa_rcp & 0xff) << 14) |\n+\t\t\t\t((roa_rcp & 0xff) << 22) | (1 << 30);\n+#endif\n+\treturn color_action;\n+}\n+\n+#define BITMASK(a, b) ((1U << ((a) - (b) + 1)) - 1)\n+\n+/*\n+ *  9:0   Mark (color) 1024 flow stats\n+ * 17:10  IOA index     256 entries\n+ * 25:18  ROA index     256 entries\n+ * 30:26  QSL and HSH    32 recipes indexable\n+ * 31:31  CAO               implicitly when color_action is set\n+ */\n+#define FLOW_MARK_MASK BITMASK(9, 0)\n+#define IOA_RCP_MASK BITMASK(17, 10)\n+#define ROA_RCP_MASK BITMASK(25, 18)\n+#define QSL_HSH_MASK BITMASK(30, 26)\n+\n+static inline uint32_t set_color_action(uint32_t mark, uint32_t ioa_rcp,\n+\t\t\t\t\tuint32_t roa_rcp, uint32_t qsl_hsh)\n+{\n+\tuint32_t color_action = (mark & FLOW_MARK_MASK) |\n+\t\t\t\t((ioa_rcp & IOA_RCP_MASK) << 10) |\n+\t\t\t\t((roa_rcp & ROA_RCP_MASK) << 18) |\n+\t\t\t\t((qsl_hsh & QSL_HSH_MASK) << 26) | (1 << 31);\n+\treturn color_action;\n+}\n+\n+/*\n+ *  This is a bitmask representation in SW for\n+ *  roa config settings. It is mostly done for\n+ *  effective cache matching\n+ *\n+ *  ROA config  bit offs  bits\n+ *  ----------------------------\n+ *  recirc port      7:0    8   -> uses hbx > 0\n+ *  recirc bypass   15:8    8   -> uses hbx > 0  if set, will override\n+ *  tunnel type     19:16   4\n+ *  tx port         23:20   4   -> txport + 1\n+ *  tun_ip_type     24:24   1\n+ *  recirculate     25:25   1   -> recirculate port set\n+ *  tunhdr_len      33:26   8   -> tunnel header length - 0 if none\n+ *  ip_csum_prec    49:34  16   -> tunnel ip header checksum pre-calculated\n+ *  new_recirc_port 50:50   1   -> indication of a new port for recirculate has been allocated.\n+ *                                 Needs default queue\n+ */\n+\n+static inline uint64_t set_roa_new_recirc_port(uint64_t actions)\n+{\n+\tactions |= 1ULL << 50;\n+\treturn actions;\n+}\n+\n+static inline uint8_t get_roa_new_recirc_port(uint64_t actions)\n+{\n+\treturn (uint8_t)((actions >> 50) & 1);\n+}\n+\n+static inline uint64_t set_roa_tun_ip_type(uint64_t actions, uint8_t ip_type)\n+{\n+\tactions |= (uint64_t)(ip_type & 1) << 24;\n+\treturn actions;\n+}\n+\n+static inline uint8_t get_roa_tun_ip_type(uint64_t actions)\n+{\n+\treturn (uint8_t)((actions >> 24) & 1);\n+}\n+\n+static inline uint64_t set_roa_tun_ip_csum(uint64_t actions, uint16_t csum)\n+{\n+\tactions |= (uint64_t)csum << 34;\n+\treturn actions;\n+}\n+\n+static inline uint16_t get_roa_tun_ip_csum(uint64_t actions)\n+{\n+\treturn (uint16_t)((actions >> 34) & 0xffff);\n+}\n+\n+static inline uint64_t set_roa_tunhdr_len(uint64_t actions, uint8_t length)\n+{\n+\tactions |= (uint64_t)length << 26;\n+\treturn actions;\n+}\n+\n+static inline uint8_t get_roa_tunhdr_len(uint64_t actions)\n+{\n+\treturn (uint8_t)((actions >> 26) & 0xff);\n+}\n+\n+static inline uint64_t set_roa_tx(uint64_t actions, uint8_t txport)\n+{\n+\tactions |= ((txport + ROA_TX_PHY0) & 0x0f) << 20;\n+\treturn actions;\n+}\n+\n+static inline uint8_t roa_get_tx(uint64_t actions)\n+{\n+\treturn (actions >> 20) & 0x0f;\n+}\n+\n+static inline uint64_t set_roa_tun_type(uint64_t actions, uint8_t type)\n+{\n+\tactions |= (type & 0x0f) << 16;\n+\treturn actions;\n+}\n+\n+static inline uint8_t roa_get_tun_type(uint64_t actions)\n+{\n+\treturn (actions >> 16) & 0x0f;\n+}\n+\n+static inline uint64_t set_roa_recirculate(uint64_t actions, uint8_t port)\n+{\n+\tactions |= (1ULL << 25) | port;\n+\treturn actions;\n+}\n+\n+static inline int32_t roa_get_recirc_port(uint64_t actions)\n+{\n+\tif (!((1ULL << 25) & actions))\n+\t\treturn -1;\n+\treturn (actions & 0xff);\n+}\n+\n+static inline uint64_t set_roa_recirc_bypass(uint64_t actions, uint8_t port)\n+{\n+\tactions |= ((uint64_t)port & 0xff) << 8;\n+\treturn actions;\n+}\n+\n+static inline uint8_t roa_get_recirc_bypass_port(uint64_t actions)\n+{\n+\treturn ((actions >> 8) & 0xff);\n+}\n+\n+/*\n+ *  This is a bitmask representation in SW for\n+ *  ioa action settings. It is mostly done for\n+ *  effective cache matching\n+ *\n+ *  IOA action    bit offs    bits\n+ *  --------------------------------\n+ *  tci         15:0    16\n+ *  queue     23:16   8  uses hbx\n+ *  tpid select   27:24   4\n+ *  pop vxlan    28     1\n+ *  pop vlan     29     1\n+ *  push vlan    30     1\n+ *  queue override   31     1\n+ */\n+\n+static inline uint64_t ioa_set_queue(uint64_t actions, uint8_t hb)\n+{\n+\tactions |= (1 << 31) | ((uint64_t)hb << 16);\n+\treturn actions;\n+}\n+\n+static inline int ioa_get_queue(uint64_t actions)\n+{\n+\tif (!(actions & (1 << 31)))\n+\t\treturn -1;\n+\treturn ((actions >> 16) & 0xff);\n+}\n+\n+static inline uint64_t ioa_set_vxlan_pop(uint64_t actions)\n+{\n+\tactions |= 1 << 28;\n+\treturn actions;\n+}\n+\n+static inline uint64_t ioa_set_vlan_pop(uint64_t actions)\n+{\n+\tactions |= 1 << 29;\n+\treturn actions;\n+}\n+\n+static inline uint64_t ioa_set_vlan_push_qinq(uint64_t actions)\n+{\n+\tactions |= (VLAN_TPID_802_1AD & 0x0f) << 24;\n+\treturn actions;\n+}\n+\n+static inline uint8_t ioa_get_tpid_sel(uint64_t actions)\n+{\n+\treturn (uint8_t)((actions >> 24) & 0x0f);\n+}\n+\n+static inline uint64_t ioa_set_vlan_push(uint64_t actions, uint16_t tci)\n+{\n+\tactions |= (1 << 30) | tci;\n+\treturn actions;\n+}\n+\n+static inline uint64_t ioa_set_vlan_pcp(uint64_t actions, uint8_t pcp)\n+{\n+\tactions |= (1 << 30) | ((uint16_t)(pcp & 7) << 13);\n+\treturn actions;\n+}\n+\n+static inline uint16_t ioa_get_vlan_tci(uint64_t actions)\n+{\n+\treturn (uint16_t)(actions & 0xffff);\n+}\n+\n+int flow_actions_create_roa_tunhdr(struct flow_api_backend_s *be, int index,\n+\t\t\t\t   struct tunnel_header_s *tun);\n+int flow_actions_create_roa_tuncfg(struct flow_api_backend_s *be, int index,\n+\t\t\t\t   uint64_t color_actions);\n+int flow_actions_create_ioa_config(struct flow_api_backend_s *be, int index,\n+\t\t\t\t   uint64_t color_actions);\n+\n+#endif /* _FLOW_ACTIONS_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_backend.c b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.c\nnew file mode 100644\nindex 0000000000..f4d71acb51\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.c\n@@ -0,0 +1,182 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdio.h>\n+#include <stdarg.h>\n+#include <stdlib.h>\n+#include <ctype.h>\n+#include <string.h>\n+#include <assert.h>\n+\n+#include \"flow_api_backend.h\"\n+\n+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))\n+\n+static const struct {\n+\tconst char *name;\n+\tint (*allocate)(struct flow_api_backend_s *be);\n+\tvoid (*free)(struct flow_api_backend_s *be);\n+\tint (*reset)(struct flow_api_backend_s *be);\n+\tbool (*present)(struct flow_api_backend_s *be);\n+} module[] = {\n+\t{\t\"CAT\", hw_mod_cat_alloc, hw_mod_cat_free, hw_mod_cat_reset,\n+\t\thw_mod_cat_present\n+\t},\n+\t{\t\"KM\", hw_mod_km_alloc, hw_mod_km_free, hw_mod_km_reset,\n+\t\thw_mod_km_present\n+\t},\n+\t{\t\"FLM\", hw_mod_flm_alloc, hw_mod_flm_free, hw_mod_flm_reset,\n+\t\thw_mod_flm_present\n+\t},\n+\t{\t\"HSH\", hw_mod_hsh_alloc, hw_mod_hsh_free, hw_mod_hsh_reset,\n+\t\thw_mod_hsh_present\n+\t},\n+\t{\t\"HST\", hw_mod_hst_alloc, hw_mod_hst_free, hw_mod_hst_reset,\n+\t\thw_mod_hst_present\n+\t},\n+\t{\t\"QSL\", hw_mod_qsl_alloc, hw_mod_qsl_free, hw_mod_qsl_reset,\n+\t\thw_mod_qsl_present\n+\t},\n+\t{\t\"SLC\", hw_mod_slc_alloc, hw_mod_slc_free, hw_mod_slc_reset,\n+\t\thw_mod_slc_present\n+\t},\n+\t{\t\"SLC LR\", hw_mod_slc_lr_alloc, hw_mod_slc_lr_free,\n+\t\thw_mod_slc_lr_reset, hw_mod_slc_lr_present\n+\t},\n+\t{\t\"PDB\", hw_mod_pdb_alloc, hw_mod_pdb_free, hw_mod_pdb_reset,\n+\t\thw_mod_pdb_present\n+\t},\n+\t{\t\"IOA\", hw_mod_ioa_alloc, hw_mod_ioa_free, hw_mod_ioa_reset,\n+\t\thw_mod_ioa_present\n+\t},\n+\t{\t\"ROA\", hw_mod_roa_alloc, hw_mod_roa_free, hw_mod_roa_reset,\n+\t\thw_mod_roa_present\n+\t},\n+\t{\t\"RMC\", hw_mod_rmc_alloc, hw_mod_rmc_free, hw_mod_rmc_reset,\n+\t\thw_mod_rmc_present\n+\t},\n+\t{\t\"TPE\", hw_mod_tpe_alloc, hw_mod_tpe_free, hw_mod_tpe_reset,\n+\t\thw_mod_tpe_present\n+\t},\n+};\n+\n+#define MOD_COUNT (ARRAY_SIZE(module))\n+\n+void *callocate_mod(struct common_func_s *mod, int sets, ...)\n+{\n+#define MAX_SETS 38\n+\tvoid *base = NULL;\n+\tvoid **plist[MAX_SETS];\n+\tint len[MAX_SETS];\n+\tint offs[MAX_SETS];\n+\tunsigned int total_bytes = 0;\n+\tint cnt, elem_size;\n+\n+\tassert(sets <= MAX_SETS);\n+\tassert(sets > 0);\n+\n+\tva_list args;\n+\n+\tva_start(args, sets);\n+\n+\tfor (int i = 0; i < sets; i++) {\n+\t\tplist[i] = va_arg(args, void *);\n+\t\tcnt = va_arg(args, int);\n+\t\telem_size = va_arg(args, int);\n+\t\toffs[i] = EXTRA_INDEXES * elem_size;\n+\t\tlen[i] = offs[i] + cnt * elem_size;\n+\t\ttotal_bytes += len[i];\n+\t}\n+\tbase = calloc(1, total_bytes);\n+\tif (base) {\n+\t\tchar *p_b = (char *)base;\n+\n+\t\tfor (int i = 0; i < sets; i++) {\n+\t\t\t(*plist[i]) = (void *)((char *)p_b + offs[i]);\n+\t\t\tp_b += len[i];\n+\t\t}\n+\t} else {\n+\t\tNT_LOG(ERR, FILTER, \"ERROR: module memory allocation failed\\n\");\n+\t}\n+\n+\tva_end(args);\n+\n+\tmod->base = base;\n+\tmod->allocated_size = total_bytes;\n+\n+\treturn base;\n+}\n+\n+void zero_module_cache(struct common_func_s *mod)\n+{\n+\tmemset(mod->base, 0, mod->allocated_size);\n+}\n+\n+int flow_api_backend_init(struct flow_api_backend_s *dev,\n+\t\t\t  const struct flow_api_backend_ops *iface,\n+\t\t\t  void *be_dev)\n+{\n+\tassert(dev);\n+\tdev->iface = iface;\n+\tdev->be_dev = be_dev;\n+\tdev->num_phy_ports = iface->get_nb_phy_port(be_dev);\n+\tdev->num_rx_ports = iface->get_nb_rx_port(be_dev);\n+\tdev->max_categories = iface->get_nb_categories(be_dev);\n+\tdev->max_queues = iface->get_nb_queues(be_dev);\n+\n+\tNT_LOG(DBG, FILTER,\n+\t       \"*************** FLOW REGISTER MODULES AND INITIALIZE - SET ALL TO DEFAULT *****************\\n\");\n+\t/*\n+\t * Create Cache and SW, version independent, NIC module representation\n+\t */\n+\tfor (unsigned int mod = 0; mod < MOD_COUNT; mod++) {\n+\t\tif (!module[mod].present(dev))\n+\t\t\tcontinue;\n+\t\tif (module[mod].allocate(dev) == 0 &&\n+\t\t\t\tmodule[mod].reset(dev) == 0) {\n+\t\t\t/* OK */\n+\t\t\tcontinue;\n+\t\t} else {\n+\t\t\tNT_LOG(ERR, FILTER,\n+\t\t\t       \"ERROR: Initialization of NIC module failed : [ %s ]\\n\",\n+\t\t\t       module[mod].name);\n+\t\t\tflow_api_backend_done(dev);\n+\t\t\tNT_LOG(ERR, FILTER,\n+\t\t\t       \"*************** Failed to create Binary Flow API *******************\\n\");\n+\t\t\tNT_LOG(ERR, FILTER,\n+\t\t\t       \"******** ERROR ERROR: Binary Flow API will not be available ********\\n\");\n+\t\t\tNT_LOG(ERR, FILTER,\n+\t\t\t       \"********************************************************************\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int flow_api_backend_reset(struct flow_api_backend_s *dev)\n+{\n+\tassert(dev);\n+\n+\tfor (unsigned int mod = 0; mod < MOD_COUNT; mod++) {\n+\t\tif (module[mod].reset(dev) == 0) {\n+\t\t\t/* OK */\n+\t\t\tcontinue;\n+\t\t} else {\n+\t\t\tNT_LOG(ERR, FILTER,\n+\t\t\t       \"ERROR: Resetting NIC module failed : [ %s ]\\n\",\n+\t\t\t       module[mod].name);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int flow_api_backend_done(struct flow_api_backend_s *dev)\n+{\n+\tfor (unsigned int mod = 0; mod < MOD_COUNT; mod++)\n+\t\tmodule[mod].free(dev);\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_backend.h b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.h\nnew file mode 100644\nindex 0000000000..c3386adea9\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.h\n@@ -0,0 +1,1818 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __FLOW_API_BACKEND_H__\n+#define __FLOW_API_BACKEND_H__\n+\n+/*\n+ * Flow API\n+ * Direct access to NIC HW module memory and register fields in a\n+ * module version independent representation\n+ */\n+\n+#include <stdint.h>\n+#include <string.h>\n+#include <stdbool.h>\n+\n+#include \"ntlog.h\"\n+\n+/* supported module versions */\n+#include \"../flow_api/hw_mod/hw_mod_km_v7.h\"\n+#include \"flow_api/hw_mod/hw_mod_cat_v18.h\"\n+#include \"flow_api/hw_mod/hw_mod_cat_v21.h\"\n+#include \"flow_api/hw_mod/hw_mod_cat_v22.h\"\n+#include \"flow_api/hw_mod/hw_mod_flm_v17.h\"\n+#include \"flow_api/hw_mod/hw_mod_flm_v20.h\"\n+#include \"flow_api/hw_mod/hw_mod_hst_v2.h\"\n+#include \"flow_api/hw_mod/hw_mod_km_v7.h\"\n+#include \"flow_api/hw_mod/hw_mod_qsl_v7.h\"\n+#include \"flow_api/hw_mod/hw_mod_pdb_v9.h\"\n+#include \"flow_api/hw_mod/hw_mod_slc_v1.h\"\n+#include \"flow_api/hw_mod/hw_mod_slc_lr_v2.h\"\n+#include \"flow_api/hw_mod/hw_mod_roa_v6.h\"\n+#include \"flow_api/hw_mod/hw_mod_hsh_v5.h\"\n+#include \"flow_api/hw_mod/hw_mod_ioa_v4.h\"\n+#include \"flow_api/hw_mod/hw_mod_rmc_v1_3.h\"\n+#include \"flow_api/hw_mod/hw_mod_tpe_v1.h\"\n+#include \"flow_api/hw_mod/hw_mod_tpe_v2.h\"\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+#define MAX_PHYS_ADAPTERS 8\n+\n+#define VER_MAJOR(ver) (((ver) >> 16) & 0xffff)\n+#define VER_MINOR(ver) ((ver) & 0xffff)\n+\n+struct flow_api_backend_s;\n+struct common_func_s;\n+\n+#define CAST_COMMON(mod) ((struct common_func_s *)(mod))\n+\n+void *callocate_mod(struct common_func_s *mod, int sets, ...);\n+void zero_module_cache(struct common_func_s *mod);\n+\n+#define ZERO_MOD_CACHE(mod) (zero_module_cache(CAST_COMMON(mod)))\n+\n+#define ALL_ENTRIES -1000\n+#define ALL_BANK_ENTRIES -1001\n+\n+static inline int error_index_too_large(const char *func)\n+{\n+\tNT_LOG(INF, FILTER, \"ERROR:%s: Index too large\\n\", func);\n+\treturn -2;\n+}\n+\n+static inline int error_word_off_too_large(const char *func)\n+{\n+\tNT_LOG(INF, FILTER, \"ERROR:%s: Word offset too large\\n\", func);\n+\treturn -3;\n+}\n+\n+static inline int error_unsup_ver(const char *func, const char *mod, int ver)\n+{\n+\tNT_LOG(INF, FILTER, \"ERROR:%s: Unsupported NIC module: %s ver %i.%i\\n\",\n+\t       func, mod, VER_MAJOR(ver), VER_MINOR(ver));\n+\treturn -4;\n+}\n+\n+static inline int error_unsup_field(const char *func)\n+{\n+\tNT_LOG(INF, FILTER, \"ERROR:%s: Unsupported field in NIC module\\n\",\n+\t\tfunc);\n+\treturn -5;\n+}\n+\n+static inline int error_resource_count(const char *func, const char *resource,\n+\tconst char *mod, int ver)\n+{\n+\tNT_LOG(INF, FILTER,\n+\t       \"ERROR:%s: Insufficient resource [ %s ] : NIC module:\"\n+\t       \"%s ver %i.%i\\n\",\n+\t       func, resource, mod, VER_MAJOR(ver), VER_MINOR(ver));\n+\treturn -4;\n+}\n+\n+#define NOT_FOUND 0xffffffff\n+\n+enum { EXTRA_INDEXES };\n+#define COPY_INDEX (EXTRA_INDEX_COPY - EXTRA_INDEXES)\n+\n+static inline void get_set(uint32_t *cached_val, uint32_t *val, int get)\n+{\n+\tif (get)\n+\t\t*val = *cached_val;\n+\telse\n+\t\t*cached_val = *val;\n+}\n+\n+static inline void get_set_signed(int32_t *cached_val, uint32_t *val, int get)\n+{\n+\tif (get)\n+\t\t*val = (uint32_t)*cached_val;\n+\telse\n+\t\t*cached_val = (int32_t)*val;\n+}\n+\n+static inline int find_equal_index(void *be_module_reg,\n+\tunsigned int type_size, unsigned int idx, unsigned int start,\n+\tunsigned int nb_elements, uint32_t *value, int get, const char *func)\n+{\n+\tunsigned int i;\n+\tif (!get)\n+\t\treturn error_unsup_field(func);\n+\t*value = NOT_FOUND;\n+\tif (start >= nb_elements)\n+\t\treturn error_index_too_large(func);\n+\tfor (i = start; i < nb_elements; i++) {\n+\t\tif (idx == i)\n+\t\t\tcontinue;\n+\t\tif (memcmp((uint8_t *)be_module_reg + idx * type_size,\n+\t\t\t   (uint8_t *)be_module_reg + i * type_size,\n+\t\t\t   type_size) == 0) {\n+\t\t\t*value = i;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static inline int do_compare_indexes(void *be_module_reg,\n+\tunsigned int type_size, unsigned int idx, unsigned int cmp_idx,\n+\tunsigned int nb_elements, int get, const char *func)\n+{\n+\tif (!get)\n+\t\treturn error_unsup_field(func);\n+\tif (cmp_idx >= nb_elements)\n+\t\treturn error_index_too_large(func);\n+\tif (idx != cmp_idx &&\n+\t    (memcmp((uint8_t *)be_module_reg + idx * type_size,\n+\t\t    (uint8_t *)be_module_reg + cmp_idx * type_size,\n+\t\t    type_size) == 0))\n+\t\treturn 1;\n+\treturn 0;\n+}\n+\n+static inline int is_non_zero(const void *addr, size_t n)\n+{\n+\tsize_t i = 0;\n+\tconst uint8_t *p = (const uint8_t *)addr;\n+\n+\tfor (i = 0; i < n; i++) {\n+\t\tif (p[i] != 0)\n+\t\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n+\n+static inline int is_all_bits_set(const void *addr, size_t n)\n+{\n+\tsize_t i = 0;\n+\tconst uint8_t *p = (const uint8_t *)addr;\n+\n+\tfor (i = 0; i < n; i++) {\n+\t\tif (p[i] != 0xff)\n+\t\t\treturn 0;\n+\t}\n+\treturn 1;\n+}\n+\n+enum cte_index_e {\n+\tCT_COL = 0,\n+\tCT_COR = 1,\n+\tCT_HSH = 2,\n+\tCT_QSL = 3,\n+\tCT_IPF = 4,\n+\tCT_SLC = 5,\n+\tCT_PDB = 6,\n+\tCT_MSK = 7,\n+\tCT_HST = 8,\n+\tCT_EPP = 9,\n+\tCT_TPE = 10,\n+\tCT_RRB = 11,\n+\tCT_CNT\n+};\n+\n+/* Sideband info bit indicator */\n+#define SWX_INFO (1 << 6)\n+\n+enum frame_offs_e {\n+\tDYN_SOF = 0,\n+\tDYN_L2 = 1,\n+\tDYN_FIRST_VLAN = 2,\n+\tDYN_MPLS = 3,\n+\tDYN_L3 = 4,\n+\tDYN_ID_IPV4_6 = 5,\n+\tDYN_FINAL_IP_DST = 6,\n+\tDYN_L4 = 7,\n+\tDYN_L4_PAYLOAD = 8,\n+\tDYN_TUN_PAYLOAD = 9,\n+\tDYN_TUN_L2 = 10,\n+\tDYN_TUN_VLAN = 11,\n+\tDYN_TUN_MPLS = 12,\n+\tDYN_TUN_L3 = 13,\n+\tDYN_TUN_ID_IPV4_6 = 14,\n+\tDYN_TUN_FINAL_IP_DST = 15,\n+\tDYN_TUN_L4 = 16,\n+\tDYN_TUN_L4_PAYLOAD = 17,\n+\tDYN_EOF = 18,\n+\tDYN_L3_PAYLOAD_END = 19,\n+\tDYN_TUN_L3_PAYLOAD_END = 20,\n+\tSB_VNI = SWX_INFO | 1,\n+\tSB_MAC_PORT = SWX_INFO | 2,\n+\tSB_KCC_ID = SWX_INFO | 3\n+};\n+\n+enum km_flm_if_select_e { KM_FLM_IF_FIRST = 0, KM_FLM_IF_SECOND = 1 };\n+\n+enum {\n+\tQW0_SEL_EXCLUDE = 0,\n+\tQW0_SEL_FIRST32 = 1,\n+\tQW0_SEL_SECOND32 = 2,\n+\tQW0_SEL_FIRST64 = 3,\n+\tQW0_SEL_ALL128 = 4,\n+};\n+\n+enum {\n+\tQW4_SEL_EXCLUDE = 0,\n+\tQW4_SEL_FIRST32 = 1,\n+\tQW4_SEL_FIRST64 = 2,\n+\tQW4_SEL_ALL128 = 3,\n+};\n+\n+enum {\n+\tSW8_SEL_EXCLUDE = 0,\n+\tSW8_SEL_FIRST16 = 1,\n+\tSW8_SEL_SECOND16 = 2,\n+\tSW8_SEL_ALL32 = 3,\n+};\n+\n+enum {\n+\tDW8_SEL_EXCLUDE = 0,\n+\tDW8_SEL_FIRST16 = 1,\n+\tDW8_SEL_SECOND16 = 2,\n+\tDW8_SEL_FIRST32 = 3,\n+\tDW8_SEL_FIRST32_SWAP16 = 4,\n+\tDW8_SEL_ALL64 = 5,\n+};\n+\n+enum {\n+\tSW9_SEL_EXCLUDE = 0,\n+\tSW9_SEL_FIRST16 = 1,\n+\tSW9_SEL_ALL32 = 2,\n+};\n+\n+enum {\n+\tDW10_SEL_EXCLUDE = 0,\n+\tDW10_SEL_FIRST16 = 1,\n+\tDW10_SEL_FIRST32 = 2,\n+\tDW10_SEL_ALL64 = 3,\n+};\n+\n+enum {\n+\tSWX_SEL_EXCLUDE = 0,\n+\tSWX_SEL_ALL32 = 1,\n+};\n+\n+enum {\n+\tPROT_OTHER = 0,\n+\tPROT_L2_ETH2 = 1,\n+\tPROT_L2_SNAP = 2,\n+\tPROT_L2_LLC = 3,\n+\tPROT_L2_RAW = 4,\n+\tPROT_L2_PPPOE_D = 5,\n+\tPROT_L2_PPOE_S = 6\n+};\n+\n+enum { PROT_L3_IPV4 = 1, PROT_L3_IPV6 = 2 };\n+\n+enum { PROT_L4_TCP = 1, PROT_L4_UDP = 2, PROT_L4_SCTP = 3, PROT_L4_ICMP = 4 };\n+\n+enum {\n+\tPROT_TUN_IP_IN_IP = 1,\n+\tPROT_TUN_ETHER_IP = 2,\n+\tPROT_TUN_GREV0 = 3,\n+\tPROT_TUN_GREV1 = 4,\n+\tPROT_TUN_GTPV0U = 5,\n+\tPROT_TUN_GTPV1U = 6,\n+\tPROT_TUN_GTPV1C = 7,\n+\tPROT_TUN_GTPV2C = 8,\n+\tPROT_TUN_VXLAN = 9,\n+\tPROT_TUN_PSEUDO_WIRE = 10\n+};\n+\n+enum { PROT_TUN_L2_OTHER = 0, PROT_TUN_L2_ETH2 = 1 };\n+\n+enum { PROT_TUN_L3_OTHER = 0, PROT_TUN_L3_IPV4 = 1, PROT_TUN_L3_IPV6 = 2 };\n+\n+enum {\n+\tPROT_TUN_L4_OTHER = 0,\n+\tPROT_TUN_L4_TCP = 1,\n+\tPROT_TUN_L4_UDP = 2,\n+\tPROT_TUN_L4_SCTP = 3,\n+\tPROT_TUN_L4_ICMP = 4\n+};\n+\n+enum {\n+\tIP_FRAG_NOT_A_FRAG = 0,\n+\tIP_FRAG_FIRST = 1,\n+\tIP_FRAG_MIDDLE = 2,\n+\tIP_FRAG_LAST = 3\n+};\n+\n+enum {\n+\tHASH_HASH_NONE = 0,\n+\tHASH_USER_DEFINED = 1,\n+\tHASH_LAST_MPLS_LABEL = 2,\n+\tHASH_ALL_MPLS_LABELS = 3,\n+\tHASH_2TUPLE = 4,\n+\tHASH_2TUPLESORTED = 5,\n+\tHASH_LAST_VLAN_ID = 6,\n+\tHASH_ALL_VLAN_IDS = 7,\n+\tHASH_5TUPLE = 8,\n+\tHASH_5TUPLESORTED = 9,\n+\tHASH_3TUPLE_GRE_V0 = 10,\n+\tHASH_3TUPLE_GRE_V0_SORTED = 11,\n+\tHASH_5TUPLE_SCTP = 12,\n+\tHASH_5TUPLE_SCTP_SORTED = 13,\n+\tHASH_3TUPLE_GTP_V0 = 14,\n+\tHASH_3TUPLE_GTP_V0_SORTED = 15,\n+\tHASH_3TUPLE_GTP_V1V2 = 16,\n+\tHASH_3TUPLE_GTP_V1V2_SORTED = 17,\n+\tHASH_HASHINNER_2TUPLE = 18,\n+\tHASH_HASHINNER_2TUPLESORTED = 19,\n+\tHASH_HASHINNER_5TUPLE = 20,\n+\tHASH_HASHINNER_5TUPLESORTED = 21,\n+\tHASH_KM = 30,\n+\tHASH_ROUND_ROBIN = 31,\n+\tHASH_OUTER_DST_IP = 32,\n+\tHASH_INNER_SRC_IP = 33,\n+};\n+\n+enum {\n+\tCPY_SELECT_DSCP_IPV4 = 0,\n+\tCPY_SELECT_DSCP_IPV6 = 1,\n+\tCPY_SELECT_RQI_QFI = 2,\n+\tCPY_SELECT_IPV4 = 3,\n+\tCPY_SELECT_PORT = 4,\n+\tCPY_SELECT_TEID = 5,\n+};\n+\n+#define RCK_CML(_comp_) (1 << ((_comp_) * 4))\n+#define RCK_CMU(_comp_) (1 << ((_comp_) * 4 + 1))\n+#define RCK_SEL(_comp_) (1 << ((_comp_) * 4 + 2))\n+#define RCK_SEU(_comp_) (1 << ((_comp_) * 4 + 3))\n+\n+#define RCK_EXT(x) (((uint32_t)(x) << 6))\n+\n+#define FIELD_START_INDEX 100\n+\n+#define COMMON_FUNC_INFO_S         \\\n+\tint ver;                   \\\n+\tvoid *base;                \\\n+\tunsigned int allocated_size; \\\n+\tint debug\n+\n+struct common_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+};\n+\n+struct cat_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+\tuint32_t nb_cat_funcs;\n+\tuint32_t nb_flow_types;\n+\tuint32_t nb_pm_ext;\n+\tuint32_t nb_len;\n+\tuint32_t kcc_size;\n+\tuint32_t cts_num;\n+\tuint32_t kcc_banks;\n+\tuint32_t kcc_id_bit_size;\n+\tuint32_t kcc_records;\n+\tuint32_t km_if_count;\n+\tint32_t km_if_m0;\n+\tint32_t km_if_m1;\n+\n+\tunion {\n+\t\tstruct hw_mod_cat_v18_s v18;\n+\t\tstruct hw_mod_cat_v21_s v21;\n+\t\tstruct hw_mod_cat_v22_s v22;\n+\t};\n+};\n+\n+enum hw_cat_e {\n+\t/*\n+\t *  functions initial CAT v18\n+\t */\n+\t/* 00 */ HW_CAT_CFN_SET_ALL_DEFAULTS = 0,\n+\t/* 01 */ HW_CAT_CFN_PRESET_ALL,\n+\t/* 02 */ HW_CAT_CFN_COMPARE,\n+\t/* 03 */ HW_CAT_CFN_FIND,\n+\t/* 04 */ HW_CAT_CFN_COPY_FROM,\n+\t/* 05 */ HW_CAT_COT_PRESET_ALL,\n+\t/* 06 */ HW_CAT_COT_COMPARE,\n+\t/* 07 */ HW_CAT_COT_FIND,\n+\t/* fields */\n+\t/* 00 */ HW_CAT_CFN_ENABLE = FIELD_START_INDEX,\n+\t/* 01 */ HW_CAT_CFN_INV,\n+\t/* 02 */ HW_CAT_CFN_PTC_INV,\n+\t/* 03 */ HW_CAT_CFN_PTC_ISL,\n+\t/* 04 */ HW_CAT_CFN_PTC_CFP,\n+\t/* 05 */ HW_CAT_CFN_PTC_MAC,\n+\t/* 06 */ HW_CAT_CFN_PTC_L2,\n+\t/* 07 */ HW_CAT_CFN_PTC_VNTAG,\n+\t/* 08 */ HW_CAT_CFN_PTC_VLAN,\n+\t/* 09 */ HW_CAT_CFN_PTC_MPLS,\n+\t/* 10 */ HW_CAT_CFN_PTC_L3,\n+\t/* 11 */ HW_CAT_CFN_PTC_FRAG,\n+\t/* 12 */ HW_CAT_CFN_PTC_IP_PROT,\n+\t/* 13 */ HW_CAT_CFN_PTC_L4,\n+\t/* 14 */ HW_CAT_CFN_PTC_TUNNEL,\n+\t/* 15 */ HW_CAT_CFN_PTC_TNL_L2,\n+\t/* 16 */ HW_CAT_CFN_PTC_TNL_VLAN,\n+\t/* 17 */ HW_CAT_CFN_PTC_TNL_MPLS,\n+\t/* 18 */ HW_CAT_CFN_PTC_TNL_L3,\n+\t/* 19 */ HW_CAT_CFN_PTC_TNL_FRAG,\n+\t/* 20 */ HW_CAT_CFN_PTC_TNL_IP_PROT,\n+\t/* 21 */ HW_CAT_CFN_PTC_TNL_L4,\n+\t/* 22 */ HW_CAT_CFN_ERR_INV,\n+\t/* 23 */ HW_CAT_CFN_ERR_CV,\n+\t/* 24 */ HW_CAT_CFN_ERR_FCS,\n+\t/* 25 */ HW_CAT_CFN_ERR_TRUNC,\n+\t/* 26 */ HW_CAT_CFN_ERR_L3_CS,\n+\t/* 27 */ HW_CAT_CFN_ERR_L4_CS,\n+\t/* 28 */ HW_CAT_CFN_MAC_PORT,\n+\t/* 29 */ HW_CAT_CFN_PM_CMP,\n+\t/* 30 */ HW_CAT_CFN_PM_DCT,\n+\t/* 31 */ HW_CAT_CFN_PM_EXT_INV,\n+\t/* 32 */ HW_CAT_CFN_PM_CMB,\n+\t/* 33 */ HW_CAT_CFN_PM_AND_INV,\n+\t/* 34 */ HW_CAT_CFN_PM_OR_INV,\n+\t/* 35 */ HW_CAT_CFN_PM_INV,\n+\t/* 36 */ HW_CAT_CFN_LC,\n+\t/* 37 */ HW_CAT_CFN_LC_INV,\n+\t/* 38 */ HW_CAT_CFN_KM0_OR,\n+\t/* 39 */ HW_CAT_CFN_KM1_OR,\n+\t/* 40 */ HW_CAT_KCE_ENABLE_BM,\n+\t/* 41 */ HW_CAT_KCS_CATEGORY,\n+\t/* 42 */ HW_CAT_FTE_ENABLE_BM,\n+\t/* 43 */ HW_CAT_CTE_ENABLE_BM,\n+\t/* 44 */ HW_CAT_CTS_CAT_A,\n+\t/* 45 */ HW_CAT_CTS_CAT_B,\n+\t/* 46 */ HW_CAT_COT_COLOR,\n+\t/* 47 */ HW_CAT_COT_KM,\n+\t/* 48 */ HW_CAT_CCT_COLOR,\n+\t/* 49 */ HW_CAT_CCT_KM,\n+\t/* 50 */ HW_CAT_KCC_KEY,\n+\t/* 51 */ HW_CAT_KCC_CATEGORY,\n+\t/* 52 */ HW_CAT_KCC_ID,\n+\t/* 53 */ HW_CAT_EXO_DYN,\n+\t/* 54 */ HW_CAT_EXO_OFS,\n+\t/* 55 */ HW_CAT_RCK_DATA,\n+\t/* 56 */ HW_CAT_LEN_LOWER,\n+\t/* 57 */ HW_CAT_LEN_UPPER,\n+\t/* 58 */ HW_CAT_LEN_DYN1,\n+\t/* 59 */ HW_CAT_LEN_DYN2,\n+\t/* 60 */ HW_CAT_LEN_INV,\n+\t/* 61 */ HW_CAT_CFN_ERR_TNL_L3_CS,\n+\t/* 62 */ HW_CAT_CFN_ERR_TNL_L4_CS,\n+\t/* 63 */ HW_CAT_CFN_ERR_TTL_EXP,\n+\t/* 64 */ HW_CAT_CFN_ERR_TNL_TTL_EXP,\n+\n+\t/* 65 */ HW_CAT_CCE_IMM,\n+\t/* 66 */ HW_CAT_CCE_IND,\n+\t/* 67 */ HW_CAT_CCS_COR_EN,\n+\t/* 68 */ HW_CAT_CCS_COR,\n+\t/* 69 */ HW_CAT_CCS_HSH_EN,\n+\t/* 70 */ HW_CAT_CCS_HSH,\n+\t/* 71 */ HW_CAT_CCS_QSL_EN,\n+\t/* 72 */ HW_CAT_CCS_QSL,\n+\t/* 73 */ HW_CAT_CCS_IPF_EN,\n+\t/* 74 */ HW_CAT_CCS_IPF,\n+\t/* 75 */ HW_CAT_CCS_SLC_EN,\n+\t/* 76 */ HW_CAT_CCS_SLC,\n+\t/* 77 */ HW_CAT_CCS_PDB_EN,\n+\t/* 78 */ HW_CAT_CCS_PDB,\n+\t/* 79 */ HW_CAT_CCS_MSK_EN,\n+\t/* 80 */ HW_CAT_CCS_MSK,\n+\t/* 81 */ HW_CAT_CCS_HST_EN,\n+\t/* 82 */ HW_CAT_CCS_HST,\n+\t/* 83 */ HW_CAT_CCS_EPP_EN,\n+\t/* 84 */ HW_CAT_CCS_EPP,\n+\t/* 85 */ HW_CAT_CCS_TPE_EN,\n+\t/* 86 */ HW_CAT_CCS_TPE,\n+\t/* 87 */ HW_CAT_CCS_RRB_EN,\n+\t/* 88 */ HW_CAT_CCS_RRB,\n+\t/* 89 */ HW_CAT_CCS_SB0_TYPE,\n+\t/* 90 */ HW_CAT_CCS_SB0_DATA,\n+\t/* 91 */ HW_CAT_CCS_SB1_TYPE,\n+\t/* 92 */ HW_CAT_CCS_SB1_DATA,\n+\t/* 93 */ HW_CAT_CCS_SB2_TYPE,\n+\t/* 94 */ HW_CAT_CCS_SB2_DATA,\n+\n+};\n+\n+bool hw_mod_cat_present(struct flow_api_backend_s *be);\n+int hw_mod_cat_alloc(struct flow_api_backend_s *be);\n+void hw_mod_cat_free(struct flow_api_backend_s *be);\n+int hw_mod_cat_reset(struct flow_api_backend_s *be);\n+int hw_mod_cat_cfn_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_cat_cfn_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, int word_off, uint32_t value);\n+int hw_mod_cat_cfn_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, int word_off, uint32_t *value);\n+/* KCE/KCS/FTE KM */\n+int hw_mod_cat_kce_km_flush(struct flow_api_backend_s *be,\n+\t\t\t    enum km_flm_if_select_e if_num, int start_idx,\n+\t\t\t    int count);\n+int hw_mod_cat_kce_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t  enum km_flm_if_select_e if_num, int index,\n+\t\t\t  uint32_t value);\n+int hw_mod_cat_kce_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t  enum km_flm_if_select_e if_num, int index,\n+\t\t\t  uint32_t *value);\n+int hw_mod_cat_kcs_km_flush(struct flow_api_backend_s *be,\n+\t\t\t    enum km_flm_if_select_e if_num, int start_idx,\n+\t\t\t    int count);\n+int hw_mod_cat_kcs_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t  enum km_flm_if_select_e if_num, int index,\n+\t\t\t  uint32_t value);\n+int hw_mod_cat_kcs_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t  enum km_flm_if_select_e if_num, int index,\n+\t\t\t  uint32_t *value);\n+int hw_mod_cat_fte_km_flush(struct flow_api_backend_s *be,\n+\t\t\t    enum km_flm_if_select_e if_num, int start_idx,\n+\t\t\t    int count);\n+int hw_mod_cat_fte_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t  enum km_flm_if_select_e if_num, int index,\n+\t\t\t  uint32_t value);\n+int hw_mod_cat_fte_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t  enum km_flm_if_select_e if_num, int index,\n+\t\t\t  uint32_t *value);\n+/* KCE/KCS/FTE FLM */\n+int hw_mod_cat_kce_flm_flush(struct flow_api_backend_s *be,\n+\t\t\t     enum km_flm_if_select_e if_num, int start_idx,\n+\t\t\t     int count);\n+int hw_mod_cat_kce_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t   enum km_flm_if_select_e if_num, int index,\n+\t\t\t   uint32_t value);\n+int hw_mod_cat_kce_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t   enum km_flm_if_select_e if_num, int index,\n+\t\t\t   uint32_t *value);\n+int hw_mod_cat_kcs_flm_flush(struct flow_api_backend_s *be,\n+\t\t\t     enum km_flm_if_select_e if_num, int start_idx,\n+\t\t\t     int count);\n+int hw_mod_cat_kcs_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t   enum km_flm_if_select_e if_num, int index,\n+\t\t\t   uint32_t value);\n+int hw_mod_cat_kcs_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t   enum km_flm_if_select_e if_num, int index,\n+\t\t\t   uint32_t *value);\n+int hw_mod_cat_fte_flm_flush(struct flow_api_backend_s *be,\n+\t\t\t     enum km_flm_if_select_e if_num, int start_idx,\n+\t\t\t     int count);\n+int hw_mod_cat_fte_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t   enum km_flm_if_select_e if_num, int index,\n+\t\t\t   uint32_t value);\n+int hw_mod_cat_fte_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t   enum km_flm_if_select_e if_num, int index,\n+\t\t\t   uint32_t *value);\n+\n+int hw_mod_cat_cte_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_cat_cte_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value);\n+int hw_mod_cat_cte_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value);\n+int hw_mod_cat_cts_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_cat_cts_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value);\n+int hw_mod_cat_cts_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value);\n+int hw_mod_cat_cot_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_cat_cot_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value);\n+int hw_mod_cat_cot_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value);\n+int hw_mod_cat_cct_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_cat_cct_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value);\n+int hw_mod_cat_cct_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value);\n+int hw_mod_cat_kcc_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_cat_kcc_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, int word_off, uint32_t value);\n+int hw_mod_cat_kcc_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, int word_off, uint32_t *value);\n+\n+int hw_mod_cat_exo_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_cat_exo_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value);\n+int hw_mod_cat_exo_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value);\n+int hw_mod_cat_rck_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_cat_rck_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value);\n+int hw_mod_cat_rck_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value);\n+int hw_mod_cat_len_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_cat_len_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value);\n+int hw_mod_cat_len_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value);\n+/* added in v22 */\n+int hw_mod_cat_cce_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_cat_cce_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value);\n+int hw_mod_cat_cce_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value);\n+int hw_mod_cat_ccs_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_cat_ccs_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value);\n+int hw_mod_cat_ccs_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value);\n+\n+struct km_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+\tuint32_t nb_categories;\n+\tuint32_t nb_cam_banks;\n+\tuint32_t nb_cam_record_words;\n+\tuint32_t nb_cam_records;\n+\tuint32_t nb_tcam_banks;\n+\tuint32_t nb_tcam_bank_width;\n+\t/* not read from backend, but rather set using version */\n+\tuint32_t nb_km_rcp_mask_a_word_size;\n+\tuint32_t nb_km_rcp_mask_b_word_size;\n+\tunion {\n+\t\tstruct hw_mod_km_v7_s v7;\n+\t};\n+};\n+\n+enum hw_km_e {\n+\t/* functions */\n+\tHW_KM_RCP_PRESET_ALL = 0,\n+\tHW_KM_CAM_PRESET_ALL,\n+\t/* to sync and reset hw with cache - force write all entries in a bank */\n+\tHW_KM_TCAM_BANK_RESET,\n+\t/* fields */\n+\tHW_KM_RCP_QW0_DYN = FIELD_START_INDEX,\n+\tHW_KM_RCP_QW0_OFS,\n+\tHW_KM_RCP_QW0_SEL_A,\n+\tHW_KM_RCP_QW0_SEL_B,\n+\tHW_KM_RCP_QW4_DYN,\n+\tHW_KM_RCP_QW4_OFS,\n+\tHW_KM_RCP_QW4_SEL_A,\n+\tHW_KM_RCP_QW4_SEL_B,\n+\tHW_KM_RCP_DW8_DYN,\n+\tHW_KM_RCP_DW8_OFS,\n+\tHW_KM_RCP_DW8_SEL_A,\n+\tHW_KM_RCP_DW8_SEL_B,\n+\tHW_KM_RCP_DW10_DYN,\n+\tHW_KM_RCP_DW10_OFS,\n+\tHW_KM_RCP_DW10_SEL_A,\n+\tHW_KM_RCP_DW10_SEL_B,\n+\tHW_KM_RCP_SWX_CCH,\n+\tHW_KM_RCP_SWX_SEL_A,\n+\tHW_KM_RCP_SWX_SEL_B,\n+\tHW_KM_RCP_MASK_A,\n+\tHW_KM_RCP_MASK_B,\n+\tHW_KM_RCP_DUAL,\n+\tHW_KM_RCP_PAIRED,\n+\tHW_KM_RCP_EL_A,\n+\tHW_KM_RCP_EL_B,\n+\tHW_KM_RCP_INFO_A,\n+\tHW_KM_RCP_INFO_B,\n+\tHW_KM_RCP_FTM_A,\n+\tHW_KM_RCP_FTM_B,\n+\tHW_KM_RCP_BANK_A,\n+\tHW_KM_RCP_BANK_B,\n+\tHW_KM_RCP_KL_A,\n+\tHW_KM_RCP_KL_B,\n+\tHW_KM_RCP_KEYWAY_A,\n+\tHW_KM_RCP_KEYWAY_B,\n+\tHW_KM_RCP_SYNERGY_MODE,\n+\tHW_KM_RCP_DW0_B_DYN,\n+\tHW_KM_RCP_DW0_B_OFS,\n+\tHW_KM_RCP_DW2_B_DYN,\n+\tHW_KM_RCP_DW2_B_OFS,\n+\tHW_KM_RCP_SW4_B_DYN,\n+\tHW_KM_RCP_SW4_B_OFS,\n+\tHW_KM_RCP_SW5_B_DYN,\n+\tHW_KM_RCP_SW5_B_OFS,\n+\tHW_KM_CAM_W0,\n+\tHW_KM_CAM_W1,\n+\tHW_KM_CAM_W2,\n+\tHW_KM_CAM_W3,\n+\tHW_KM_CAM_W4,\n+\tHW_KM_CAM_W5,\n+\tHW_KM_CAM_FT0,\n+\tHW_KM_CAM_FT1,\n+\tHW_KM_CAM_FT2,\n+\tHW_KM_CAM_FT3,\n+\tHW_KM_CAM_FT4,\n+\tHW_KM_CAM_FT5,\n+\tHW_KM_TCAM_T,\n+\tHW_KM_TCI_COLOR,\n+\tHW_KM_TCI_FT,\n+\tHW_KM_TCQ_BANK_MASK,\n+\tHW_KM_TCQ_QUAL\n+};\n+\n+bool hw_mod_km_present(struct flow_api_backend_s *be);\n+int hw_mod_km_alloc(struct flow_api_backend_s *be);\n+void hw_mod_km_free(struct flow_api_backend_s *be);\n+int hw_mod_km_reset(struct flow_api_backend_s *be);\n+int hw_mod_km_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\tint count);\n+int hw_mod_km_rcp_set(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int index, int word_off, uint32_t value);\n+int hw_mod_km_rcp_get(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int index, int word_off, uint32_t *value);\n+int hw_mod_km_cam_flush(struct flow_api_backend_s *be, int start_bank,\n+\t\t\tint start_record, int count);\n+int hw_mod_km_cam_set(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int bank, int record, uint32_t value);\n+int hw_mod_km_cam_get(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int bank, int record, uint32_t *value);\n+int hw_mod_km_tcam_flush(struct flow_api_backend_s *be, int start_bank,\n+\t\t\t int count);\n+int hw_mod_km_tcam_set(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t       int bank, int byte, int byte_val, uint32_t *value_set);\n+int hw_mod_km_tcam_get(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t       int bank, int byte, int byte_val, uint32_t *value_set);\n+int hw_mod_km_tci_flush(struct flow_api_backend_s *be, int start_bank,\n+\t\t\tint start_record, int count);\n+int hw_mod_km_tci_set(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int bank, int record, uint32_t value);\n+int hw_mod_km_tci_get(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int bank, int record, uint32_t *value);\n+int hw_mod_km_tcq_flush(struct flow_api_backend_s *be, int start_bank,\n+\t\t\tint start_record, int count);\n+int hw_mod_km_tcq_set(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int bank, int record, uint32_t *value);\n+int hw_mod_km_tcq_get(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int bank, int record, uint32_t *value);\n+\n+struct hst_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+\tuint32_t nb_hst_rcp_categories;\n+\tunion {\n+\t\tstruct hw_mod_hst_v2_s v2;\n+\t};\n+};\n+\n+enum hw_hst_e {\n+\t/* functions */\n+\tHW_HST_RCP_PRESET_ALL = 0,\n+\tHW_HST_RCP_FIND,\n+\tHW_HST_RCP_COMPARE,\n+\t/* Control fields */\n+\tHW_HST_RCP_STRIP_MODE = FIELD_START_INDEX,\n+\tHW_HST_RCP_START_DYN,\n+\tHW_HST_RCP_START_OFS,\n+\tHW_HST_RCP_END_DYN,\n+\tHW_HST_RCP_END_OFS,\n+\tHW_HST_RCP_MODIF0_CMD,\n+\tHW_HST_RCP_MODIF0_DYN,\n+\tHW_HST_RCP_MODIF0_OFS,\n+\tHW_HST_RCP_MODIF0_VALUE,\n+\tHW_HST_RCP_MODIF1_CMD,\n+\tHW_HST_RCP_MODIF1_DYN,\n+\tHW_HST_RCP_MODIF1_OFS,\n+\tHW_HST_RCP_MODIF1_VALUE,\n+\tHW_HST_RCP_MODIF2_CMD,\n+\tHW_HST_RCP_MODIF2_DYN,\n+\tHW_HST_RCP_MODIF2_OFS,\n+\tHW_HST_RCP_MODIF2_VALUE,\n+\n+};\n+\n+bool hw_mod_hst_present(struct flow_api_backend_s *be);\n+int hw_mod_hst_alloc(struct flow_api_backend_s *be);\n+void hw_mod_hst_free(struct flow_api_backend_s *be);\n+int hw_mod_hst_reset(struct flow_api_backend_s *be);\n+\n+int hw_mod_hst_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_hst_rcp_set(struct flow_api_backend_s *be, enum hw_hst_e field,\n+\t\t       int index, uint32_t value);\n+int hw_mod_hst_rcp_get(struct flow_api_backend_s *be, enum hw_hst_e field,\n+\t\t       int index, uint32_t *value);\n+\n+struct flm_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+\tuint32_t nb_categories;\n+\tuint32_t nb_size_mb;\n+\tuint32_t nb_entry_size;\n+\tuint32_t nb_variant;\n+\tuint32_t nb_prios;\n+\tuint32_t nb_pst_profiles;\n+\tunion {\n+\t\tstruct hw_mod_flm_v17_s v17;\n+\t\tstruct hw_mod_flm_v20_s v20;\n+\t};\n+};\n+\n+enum hw_flm_e {\n+\t/* functions */\n+\tHW_FLM_CONTROL_PRESET_ALL = 0,\n+\tHW_FLM_RCP_PRESET_ALL,\n+\tHW_FLM_FLOW_LRN_DATA_V17,\n+\tHW_FLM_FLOW_INF_DATA_V17,\n+\tHW_FLM_FLOW_STA_DATA_V17,\n+\t/* Control fields */\n+\tHW_FLM_CONTROL_ENABLE = FIELD_START_INDEX,\n+\tHW_FLM_CONTROL_INIT,\n+\tHW_FLM_CONTROL_LDS,\n+\tHW_FLM_CONTROL_LFS,\n+\tHW_FLM_CONTROL_LIS,\n+\tHW_FLM_CONTROL_UDS,\n+\tHW_FLM_CONTROL_UIS,\n+\tHW_FLM_CONTROL_RDS,\n+\tHW_FLM_CONTROL_RIS,\n+\tHW_FLM_CONTROL_PDS,\n+\tHW_FLM_CONTROL_PIS,\n+\tHW_FLM_CONTROL_CRCWR,\n+\tHW_FLM_CONTROL_CRCRD,\n+\tHW_FLM_CONTROL_RBL,\n+\tHW_FLM_CONTROL_EAB,\n+\tHW_FLM_CONTROL_SPLIT_SDRAM_USAGE,\n+\tHW_FLM_STATUS_CALIBDONE,\n+\tHW_FLM_STATUS_INITDONE,\n+\tHW_FLM_STATUS_IDLE,\n+\tHW_FLM_STATUS_CRITICAL,\n+\tHW_FLM_STATUS_PANIC,\n+\tHW_FLM_STATUS_CRCERR,\n+\tHW_FLM_STATUS_EFT_BP,\n+\tHW_FLM_TIMEOUT_T,\n+\tHW_FLM_SCRUB_I,\n+\tHW_FLM_LOAD_BIN,\n+\tHW_FLM_LOAD_PPS,\n+\tHW_FLM_LOAD_LPS,\n+\tHW_FLM_LOAD_APS,\n+\tHW_FLM_PRIO_LIMIT0,\n+\tHW_FLM_PRIO_FT0,\n+\tHW_FLM_PRIO_LIMIT1,\n+\tHW_FLM_PRIO_FT1,\n+\tHW_FLM_PRIO_LIMIT2,\n+\tHW_FLM_PRIO_FT2,\n+\tHW_FLM_PRIO_LIMIT3,\n+\tHW_FLM_PRIO_FT3,\n+\tHW_FLM_PST_PRESET_ALL,\n+\tHW_FLM_PST_BP,\n+\tHW_FLM_PST_PP,\n+\tHW_FLM_PST_TP,\n+\tHW_FLM_RCP_LOOKUP,\n+\tHW_FLM_RCP_QW0_DYN,\n+\tHW_FLM_RCP_QW0_OFS,\n+\tHW_FLM_RCP_QW0_SEL,\n+\tHW_FLM_RCP_QW4_DYN,\n+\tHW_FLM_RCP_QW4_OFS,\n+\tHW_FLM_RCP_SW8_DYN,\n+\tHW_FLM_RCP_SW8_OFS,\n+\tHW_FLM_RCP_SW8_SEL,\n+\tHW_FLM_RCP_SW9_DYN,\n+\tHW_FLM_RCP_SW9_OFS,\n+\tHW_FLM_RCP_MASK,\n+\tHW_FLM_RCP_KID,\n+\tHW_FLM_RCP_OPN,\n+\tHW_FLM_RCP_IPN,\n+\tHW_FLM_RCP_BYT_DYN,\n+\tHW_FLM_RCP_BYT_OFS,\n+\tHW_FLM_RCP_TXPLM,\n+\tHW_FLM_RCP_AUTO_IPV4_MASK,\n+\tHW_FLM_BUF_CTRL_LRN_FREE,\n+\tHW_FLM_BUF_CTRL_INF_AVAIL,\n+\tHW_FLM_BUF_CTRL_STA_AVAIL,\n+\tHW_FLM_STAT_LRN_DONE,\n+\tHW_FLM_STAT_LRN_IGNORE,\n+\tHW_FLM_STAT_LRN_FAIL,\n+\tHW_FLM_STAT_UNL_DONE,\n+\tHW_FLM_STAT_UNL_IGNORE,\n+\tHW_FLM_STAT_REL_DONE,\n+\tHW_FLM_STAT_REL_IGNORE,\n+\tHW_FLM_STAT_PRB_DONE,\n+\tHW_FLM_STAT_PRB_IGNORE,\n+\tHW_FLM_STAT_AUL_DONE,\n+\tHW_FLM_STAT_AUL_IGNORE,\n+\tHW_FLM_STAT_AUL_FAIL,\n+\tHW_FLM_STAT_TUL_DONE,\n+\tHW_FLM_STAT_FLOWS,\n+\tHW_FLM_STAT_STA_DONE, /* module ver 0.20 */\n+\tHW_FLM_STAT_INF_DONE, /* module ver 0.20 */\n+\tHW_FLM_STAT_INF_SKIP, /* module ver 0.20 */\n+\tHW_FLM_STAT_PCK_HIT, /* module ver 0.20 */\n+\tHW_FLM_STAT_PCK_MISS, /* module ver 0.20 */\n+\tHW_FLM_STAT_PCK_UNH, /* module ver 0.20 */\n+\tHW_FLM_STAT_PCK_DIS, /* module ver 0.20 */\n+\tHW_FLM_STAT_CSH_HIT, /* module ver 0.20 */\n+\tHW_FLM_STAT_CSH_MISS, /* module ver 0.20 */\n+\tHW_FLM_STAT_CSH_UNH, /* module ver 0.20 */\n+\tHW_FLM_STAT_CUC_START, /* module ver 0.20 */\n+\tHW_FLM_STAT_CUC_MOVE, /* module ver 0.20 */\n+};\n+\n+bool hw_mod_flm_present(struct flow_api_backend_s *be);\n+int hw_mod_flm_alloc(struct flow_api_backend_s *be);\n+void hw_mod_flm_free(struct flow_api_backend_s *be);\n+int hw_mod_flm_reset(struct flow_api_backend_s *be);\n+\n+int hw_mod_flm_control_flush(struct flow_api_backend_s *be);\n+int hw_mod_flm_control_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t   uint32_t value);\n+int hw_mod_flm_control_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t   uint32_t *value);\n+\n+int hw_mod_flm_status_flush(struct flow_api_backend_s *be);\n+int hw_mod_flm_status_update(struct flow_api_backend_s *be);\n+int hw_mod_flm_status_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t  uint32_t value);\n+int hw_mod_flm_status_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t  uint32_t *value);\n+\n+int hw_mod_flm_timeout_flush(struct flow_api_backend_s *be);\n+int hw_mod_flm_timeout_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t   uint32_t value);\n+int hw_mod_flm_timeout_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t   uint32_t *value);\n+\n+int hw_mod_flm_scrub_flush(struct flow_api_backend_s *be);\n+int hw_mod_flm_scrub_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t uint32_t value);\n+int hw_mod_flm_scrub_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t uint32_t *value);\n+\n+int hw_mod_flm_load_bin_flush(struct flow_api_backend_s *be);\n+int hw_mod_flm_load_bin_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t value);\n+int hw_mod_flm_load_bin_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t *value);\n+\n+int hw_mod_flm_load_pps_flush(struct flow_api_backend_s *be);\n+int hw_mod_flm_load_pps_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t value);\n+int hw_mod_flm_load_pps_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t *value);\n+\n+int hw_mod_flm_load_lps_flush(struct flow_api_backend_s *be);\n+int hw_mod_flm_load_lps_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t value);\n+int hw_mod_flm_load_lps_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t *value);\n+\n+int hw_mod_flm_load_aps_flush(struct flow_api_backend_s *be);\n+int hw_mod_flm_load_aps_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t value);\n+int hw_mod_flm_load_aps_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t *value);\n+\n+int hw_mod_flm_prio_flush(struct flow_api_backend_s *be);\n+int hw_mod_flm_prio_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\tuint32_t value);\n+int hw_mod_flm_prio_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\tuint32_t *value);\n+\n+int hw_mod_flm_pst_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_flm_pst_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t       int index, uint32_t value);\n+int hw_mod_flm_pst_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t       int index, uint32_t *value);\n+\n+int hw_mod_flm_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_flm_rcp_set_mask(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    int index, uint32_t *value);\n+int hw_mod_flm_rcp_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t       int index, uint32_t value);\n+int hw_mod_flm_rcp_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t       int index, uint32_t *value);\n+\n+int hw_mod_flm_buf_ctrl_update(struct flow_api_backend_s *be);\n+int hw_mod_flm_buf_ctrl_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t *value);\n+\n+int hw_mod_flm_stat_update(struct flow_api_backend_s *be);\n+int hw_mod_flm_stat_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\tuint32_t *value);\n+\n+int hw_mod_flm_lrn_data_set_flush(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_flm_e field, const uint32_t *value);\n+int hw_mod_flm_inf_data_update_get(struct flow_api_backend_s *be,\n+\t\t\t\t   enum hw_flm_e field, uint32_t *value,\n+\t\t\t\t   uint32_t word_cnt);\n+int hw_mod_flm_sta_data_update_get(struct flow_api_backend_s *be,\n+\t\t\t\t   enum hw_flm_e field, uint32_t *value);\n+\n+struct hsh_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+\tuint32_t nb_rcp;\n+\tunion {\n+\t\tstruct hw_mod_hsh_v5_s v5;\n+\t};\n+};\n+\n+enum hw_hsh_e {\n+\t/* functions */\n+\tHW_HSH_RCP_PRESET_ALL = 0,\n+\tHW_HSH_RCP_COMPARE,\n+\tHW_HSH_RCP_FIND,\n+\t/* fields */\n+\tHW_HSH_RCP_LOAD_DIST_TYPE = FIELD_START_INDEX,\n+\tHW_HSH_RCP_MAC_PORT_MASK,\n+\tHW_HSH_RCP_SORT,\n+\tHW_HSH_RCP_QW0_PE,\n+\tHW_HSH_RCP_QW0_OFS,\n+\tHW_HSH_RCP_QW4_PE,\n+\tHW_HSH_RCP_QW4_OFS,\n+\tHW_HSH_RCP_W8_PE,\n+\tHW_HSH_RCP_W8_OFS,\n+\tHW_HSH_RCP_W8_SORT,\n+\tHW_HSH_RCP_W9_PE,\n+\tHW_HSH_RCP_W9_OFS,\n+\tHW_HSH_RCP_W9_SORT,\n+\tHW_HSH_RCP_W9_P,\n+\tHW_HSH_RCP_P_MASK,\n+\tHW_HSH_RCP_WORD_MASK,\n+\tHW_HSH_RCP_SEED,\n+\tHW_HSH_RCP_TNL_P,\n+\tHW_HSH_RCP_HSH_VALID,\n+\tHW_HSH_RCP_HSH_TYPE,\n+\tHW_HSH_RCP_AUTO_IPV4_MASK\n+\n+};\n+\n+bool hw_mod_hsh_present(struct flow_api_backend_s *be);\n+int hw_mod_hsh_alloc(struct flow_api_backend_s *be);\n+void hw_mod_hsh_free(struct flow_api_backend_s *be);\n+int hw_mod_hsh_reset(struct flow_api_backend_s *be);\n+int hw_mod_hsh_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_hsh_rcp_set(struct flow_api_backend_s *be, enum hw_hsh_e field,\n+\t\t       uint32_t index, uint32_t word_off, uint32_t value);\n+int hw_mod_hsh_rcp_get(struct flow_api_backend_s *be, enum hw_hsh_e field,\n+\t\t       uint32_t index, uint32_t word_off, uint32_t *value);\n+\n+struct qsl_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+\tuint32_t nb_rcp_categories;\n+\tuint32_t nb_qst_entries;\n+\tunion {\n+\t\tstruct hw_mod_qsl_v7_s v7;\n+\t};\n+};\n+\n+enum hw_qsl_e {\n+\t/* functions */\n+\tHW_QSL_RCP_PRESET_ALL = 0,\n+\tHW_QSL_RCP_COMPARE,\n+\tHW_QSL_RCP_FIND,\n+\tHW_QSL_QST_PRESET_ALL,\n+\t/* fields */\n+\tHW_QSL_RCP_DISCARD = FIELD_START_INDEX,\n+\tHW_QSL_RCP_DROP,\n+\tHW_QSL_RCP_TBL_LO,\n+\tHW_QSL_RCP_TBL_HI,\n+\tHW_QSL_RCP_TBL_IDX,\n+\tHW_QSL_RCP_TBL_MSK,\n+\tHW_QSL_RCP_LR,\n+\tHW_QSL_RCP_TSA,\n+\tHW_QSL_RCP_VLI,\n+\tHW_QSL_QST_QUEUE,\n+\tHW_QSL_QST_EN, /* Alias: HW_QSL_QST_QEN */\n+\tHW_QSL_QST_TX_PORT,\n+\tHW_QSL_QST_LRE,\n+\tHW_QSL_QST_TCI,\n+\tHW_QSL_QST_VEN,\n+\tHW_QSL_QEN_EN,\n+\tHW_QSL_UNMQ_DEST_QUEUE,\n+\tHW_QSL_UNMQ_EN,\n+\n+};\n+\n+bool hw_mod_qsl_present(struct flow_api_backend_s *be);\n+int hw_mod_qsl_alloc(struct flow_api_backend_s *be);\n+void hw_mod_qsl_free(struct flow_api_backend_s *be);\n+int hw_mod_qsl_reset(struct flow_api_backend_s *be);\n+int hw_mod_qsl_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_qsl_rcp_set(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t       uint32_t index, uint32_t value);\n+int hw_mod_qsl_rcp_get(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t       uint32_t index, uint32_t *value);\n+int hw_mod_qsl_qst_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_qsl_qst_set(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t       uint32_t index, uint32_t value);\n+int hw_mod_qsl_qst_get(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t       uint32_t index, uint32_t *value);\n+int hw_mod_qsl_qen_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_qsl_qen_set(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t       uint32_t index, uint32_t value);\n+int hw_mod_qsl_qen_get(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t       uint32_t index, uint32_t *value);\n+int hw_mod_qsl_unmq_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t  int count);\n+int hw_mod_qsl_unmq_set(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t\tuint32_t index, uint32_t value);\n+int hw_mod_qsl_unmq_get(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t\tuint32_t index, uint32_t *value);\n+\n+struct slc_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+\tunion {\n+\t\tstruct hw_mod_slc_v1_s v1;\n+\t};\n+};\n+\n+enum hw_slc_e {\n+\t/* functions */\n+\tHW_SLC_RCP_PRESET_ALL = 0,\n+\tHW_SLC_RCP_COMPARE,\n+\tHW_SLC_RCP_FIND,\n+\t/* fields */\n+\tHW_SLC_RCP_SLC_EN = FIELD_START_INDEX,\n+\tHW_SLC_RCP_DYN,\n+\tHW_SLC_RCP_OFS,\n+\tHW_SLC_RCP_PCAP\n+};\n+\n+bool hw_mod_slc_present(struct flow_api_backend_s *be);\n+int hw_mod_slc_alloc(struct flow_api_backend_s *be);\n+void hw_mod_slc_free(struct flow_api_backend_s *be);\n+int hw_mod_slc_reset(struct flow_api_backend_s *be);\n+int hw_mod_slc_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_slc_rcp_set(struct flow_api_backend_s *be, enum hw_slc_e field,\n+\t\t       uint32_t index, uint32_t value);\n+int hw_mod_slc_rcp_get(struct flow_api_backend_s *be, enum hw_slc_e field,\n+\t\t       uint32_t index, uint32_t *value);\n+\n+struct slc_lr_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+\tunion {\n+\t\tstruct hw_mod_slc_lr_v2_s v2;\n+\t};\n+};\n+\n+enum hw_slc_lr_e {\n+\t/* functions */\n+\tHW_SLC_LR_RCP_PRESET_ALL = 0,\n+\tHW_SLC_LR_RCP_COMPARE,\n+\tHW_SLC_LR_RCP_FIND,\n+\t/* fields */\n+\tHW_SLC_LR_RCP_SLC_EN = FIELD_START_INDEX,\n+\tHW_SLC_LR_RCP_DYN,\n+\tHW_SLC_LR_RCP_OFS,\n+\tHW_SLC_LR_RCP_PCAP\n+};\n+\n+bool hw_mod_slc_lr_present(struct flow_api_backend_s *be);\n+int hw_mod_slc_lr_alloc(struct flow_api_backend_s *be);\n+void hw_mod_slc_lr_free(struct flow_api_backend_s *be);\n+int hw_mod_slc_lr_reset(struct flow_api_backend_s *be);\n+int hw_mod_slc_lr_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t    int count);\n+int hw_mod_slc_lr_rcp_set(struct flow_api_backend_s *be, enum hw_slc_lr_e field,\n+\t\t\t  uint32_t index, uint32_t value);\n+int hw_mod_slc_lr_rcp_get(struct flow_api_backend_s *be, enum hw_slc_lr_e field,\n+\t\t\t  uint32_t index, uint32_t *value);\n+\n+struct pdb_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+\tuint32_t nb_pdb_rcp_categories;\n+\n+\tunion {\n+\t\tstruct hw_mod_pdb_v9_s v9;\n+\t};\n+};\n+\n+enum hw_pdb_e {\n+\t/* functions */\n+\tHW_PDB_RCP_PRESET_ALL = 0,\n+\tHW_PDB_RCP_COMPARE,\n+\tHW_PDB_RCP_FIND,\n+\t/* fields */\n+\tHW_PDB_RCP_DESCRIPTOR = FIELD_START_INDEX,\n+\tHW_PDB_RCP_DESC_LEN,\n+\tHW_PDB_RCP_TX_PORT,\n+\tHW_PDB_RCP_TX_IGNORE,\n+\tHW_PDB_RCP_TX_NOW,\n+\tHW_PDB_RCP_CRC_OVERWRITE,\n+\tHW_PDB_RCP_ALIGN,\n+\tHW_PDB_RCP_OFS0_DYN,\n+\tHW_PDB_RCP_OFS0_REL,\n+\tHW_PDB_RCP_OFS1_DYN,\n+\tHW_PDB_RCP_OFS1_REL,\n+\tHW_PDB_RCP_OFS2_DYN,\n+\tHW_PDB_RCP_OFS2_REL,\n+\tHW_PDB_RCP_IP_PROT_TNL,\n+\tHW_PDB_RCP_PPC_HSH,\n+\tHW_PDB_RCP_DUPLICATE_EN,\n+\tHW_PDB_RCP_DUPLICATE_BIT,\n+\tHW_PDB_RCP_PCAP_KEEP_FCS,\n+\tHW_PDB_CONFIG_TS_FORMAT,\n+\tHW_PDB_CONFIG_PORT_OFS,\n+};\n+\n+bool hw_mod_pdb_present(struct flow_api_backend_s *be);\n+int hw_mod_pdb_alloc(struct flow_api_backend_s *be);\n+void hw_mod_pdb_free(struct flow_api_backend_s *be);\n+int hw_mod_pdb_reset(struct flow_api_backend_s *be);\n+int hw_mod_pdb_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_pdb_rcp_set(struct flow_api_backend_s *be, enum hw_pdb_e field,\n+\t\t       uint32_t index, uint32_t value);\n+int hw_mod_pdb_rcp_get(struct flow_api_backend_s *be, enum hw_pdb_e field,\n+\t\t       uint32_t index, uint32_t *value);\n+int hw_mod_pdb_config_flush(struct flow_api_backend_s *be);\n+int hw_mod_pdb_config_set(struct flow_api_backend_s *be, enum hw_pdb_e field,\n+\t\t\t  uint32_t value);\n+\n+struct ioa_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+\tuint32_t nb_rcp_categories;\n+\tuint32_t nb_roa_epp_entries;\n+\tunion {\n+\t\tstruct hw_mod_ioa_v4_s v4;\n+\t};\n+};\n+\n+enum hw_ioa_e {\n+\t/* functions */\n+\tHW_IOA_RCP_PRESET_ALL = 0,\n+\tHW_IOA_RCP_COMPARE,\n+\tHW_IOA_RCP_FIND,\n+\tHW_IOA_ROA_EPP_PRESET_ALL,\n+\tHW_IOA_ROA_EPP_COMPARE,\n+\tHW_IOA_ROA_EPP_FIND,\n+\t/* fields */\n+\tHW_IOA_RCP_TUNNEL_POP = FIELD_START_INDEX,\n+\tHW_IOA_RCP_VLAN_POP,\n+\tHW_IOA_RCP_VLAN_PUSH,\n+\tHW_IOA_RCP_VLAN_VID,\n+\tHW_IOA_RCP_VLAN_DEI,\n+\tHW_IOA_RCP_VLAN_PCP,\n+\tHW_IOA_RCP_VLAN_TPID_SEL,\n+\tHW_IOA_RCP_QUEUE_OVERRIDE_EN,\n+\tHW_IOA_RCP_QUEUE_ID,\n+\tHW_IOA_CONFIG_CUST_TPID_0,\n+\tHW_IOA_CONFIG_CUST_TPID_1,\n+\tHW_IOA_ROA_EPP_PUSH_TUNNEL,\n+\tHW_IOA_ROA_EPP_TX_PORT,\n+};\n+\n+bool hw_mod_ioa_present(struct flow_api_backend_s *be);\n+int hw_mod_ioa_alloc(struct flow_api_backend_s *be);\n+void hw_mod_ioa_free(struct flow_api_backend_s *be);\n+int hw_mod_ioa_reset(struct flow_api_backend_s *be);\n+int hw_mod_ioa_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count);\n+int hw_mod_ioa_rcp_set(struct flow_api_backend_s *be, enum hw_ioa_e field,\n+\t\t       uint32_t index, uint32_t value);\n+int hw_mod_ioa_rcp_get(struct flow_api_backend_s *be, enum hw_ioa_e field,\n+\t\t       uint32_t index, uint32_t *value);\n+int hw_mod_ioa_config_flush(struct flow_api_backend_s *be);\n+int hw_mod_ioa_config_set(struct flow_api_backend_s *be, enum hw_ioa_e field,\n+\t\t\t  uint32_t value);\n+\n+int hw_mod_ioa_roa_epp_set(struct flow_api_backend_s *be, enum hw_ioa_e field,\n+\t\t\t   uint32_t index, uint32_t value);\n+int hw_mod_ioa_roa_epp_get(struct flow_api_backend_s *be, enum hw_ioa_e field,\n+\t\t\t   uint32_t index, uint32_t *value);\n+int hw_mod_ioa_roa_epp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count);\n+\n+struct roa_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+\tuint32_t nb_tun_categories;\n+\tuint32_t nb_lag_entries;\n+\tunion {\n+\t\tstruct hw_mod_roa_v6_s v6;\n+\t};\n+};\n+\n+enum hw_roa_e {\n+\t/* functions */\n+\tHW_ROA_TUNHDR_COMPARE = 0,\n+\tHW_ROA_TUNCFG_PRESET_ALL,\n+\tHW_ROA_TUNCFG_COMPARE,\n+\tHW_ROA_TUNCFG_FIND,\n+\t/* fields */\n+\tHW_ROA_TUNHDR = FIELD_START_INDEX,\n+\tHW_ROA_TUNCFG_TUN_LEN,\n+\tHW_ROA_TUNCFG_TUN_TYPE,\n+\tHW_ROA_TUNCFG_TUN_VLAN,\n+\tHW_ROA_TUNCFG_IP_TYPE,\n+\tHW_ROA_TUNCFG_IPCS_UPD,\n+\tHW_ROA_TUNCFG_IPCS_PRECALC,\n+\tHW_ROA_TUNCFG_IPTL_UPD,\n+\tHW_ROA_TUNCFG_IPTL_PRECALC,\n+\tHW_ROA_TUNCFG_VXLAN_UDP_LEN_UPD,\n+\tHW_ROA_TUNCFG_TX_LAG_IX,\n+\tHW_ROA_TUNCFG_RECIRCULATE,\n+\tHW_ROA_TUNCFG_PUSH_TUNNEL,\n+\tHW_ROA_TUNCFG_RECIRC_PORT,\n+\tHW_ROA_TUNCFG_RECIRC_BYPASS,\n+\tHW_ROA_CONFIG_FWD_RECIRCULATE,\n+\tHW_ROA_CONFIG_FWD_NORMAL_PCKS,\n+\tHW_ROA_CONFIG_FWD_TXPORT0,\n+\tHW_ROA_CONFIG_FWD_TXPORT1,\n+\tHW_ROA_CONFIG_FWD_CELLBUILDER_PCKS,\n+\tHW_ROA_CONFIG_FWD_NON_NORMAL_PCKS,\n+\tHW_ROA_LAGCFG_TXPHY_PORT,\n+\tHW_ROA_IGS_PKT_DROP,\n+\tHW_ROA_IGS_BYTE_DROP,\n+\tHW_ROA_RCC_PKT_DROP,\n+\tHW_ROA_RCC_BYTE_DROP,\n+};\n+\n+bool hw_mod_roa_present(struct flow_api_backend_s *be);\n+int hw_mod_roa_alloc(struct flow_api_backend_s *be);\n+void hw_mod_roa_free(struct flow_api_backend_s *be);\n+int hw_mod_roa_reset(struct flow_api_backend_s *be);\n+int hw_mod_roa_tunhdr_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t    int count);\n+int hw_mod_roa_tunhdr_set(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t index, uint32_t word_off, uint32_t value);\n+int hw_mod_roa_tunhdr_get(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t index, uint32_t word_off, uint32_t *value);\n+int hw_mod_roa_tuncfg_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t    int count);\n+int hw_mod_roa_tuncfg_set(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t index, uint32_t value);\n+int hw_mod_roa_tuncfg_get(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t index, uint32_t *value);\n+int hw_mod_roa_config_flush(struct flow_api_backend_s *be);\n+int hw_mod_roa_config_set(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t value);\n+int hw_mod_roa_config_get(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t *value);\n+int hw_mod_roa_lagcfg_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t    int count);\n+int hw_mod_roa_lagcfg_set(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t index, uint32_t value);\n+int hw_mod_roa_lagcfg_get(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t index, uint32_t *value);\n+int hw_mod_roa_igs_pkt_set(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t   uint32_t value);\n+int hw_mod_roa_igs_pkt_get(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t   uint32_t *value);\n+int hw_mod_roa_igs_pkt_flush(struct flow_api_backend_s *be);\n+int hw_mod_roa_igs_byte_set(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t    uint32_t value);\n+int hw_mod_roa_igs_byte_get(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t    uint32_t *value);\n+int hw_mod_roa_igs_byte_flush(struct flow_api_backend_s *be);\n+int hw_mod_roa_rcc_pkt_set(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t   uint32_t value);\n+int hw_mod_roa_rcc_pkt_get(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t   uint32_t *value);\n+int hw_mod_roa_rcc_pkt_flush(struct flow_api_backend_s *be);\n+int hw_mod_roa_rcc_byte_set(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t    uint32_t value);\n+int hw_mod_roa_rcc_byte_get(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t    uint32_t *value);\n+int hw_mod_roa_rcc_byte_flush(struct flow_api_backend_s *be);\n+\n+struct rmc_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+\tunion {\n+\t\tstruct hw_mod_rmc_v1_3_s v1_3;\n+\t};\n+};\n+\n+enum hw_rmc_e {\n+\tHW_RMC_BLOCK_STATT = FIELD_START_INDEX,\n+\tHW_RMC_BLOCK_KEEPA,\n+\tHW_RMC_BLOCK_RPP_SLICE,\n+\tHW_RMC_BLOCK_MAC_PORT,\n+\tHW_RMC_LAG_PHY_ODD_EVEN,\n+};\n+\n+bool hw_mod_rmc_present(struct flow_api_backend_s *be);\n+int hw_mod_rmc_alloc(struct flow_api_backend_s *be);\n+void hw_mod_rmc_free(struct flow_api_backend_s *be);\n+int hw_mod_rmc_reset(struct flow_api_backend_s *be);\n+int hw_mod_rmc_ctrl_set(struct flow_api_backend_s *be, enum hw_rmc_e field,\n+\t\t\tuint32_t value);\n+int hw_mod_rmc_ctrl_get(struct flow_api_backend_s *be, enum hw_rmc_e field,\n+\t\t\tuint32_t *value);\n+int hw_mod_rmc_ctrl_flush(struct flow_api_backend_s *be);\n+\n+struct tpe_func_s {\n+\tCOMMON_FUNC_INFO_S;\n+\tuint32_t nb_rcp_categories;\n+\tuint32_t nb_ifr_categories;\n+\tuint32_t nb_cpy_writers;\n+\tuint32_t nb_rpl_depth;\n+\tuint32_t nb_rpl_ext_categories;\n+\tunion {\n+\t\tstruct hw_mod_tpe_v1_s v1;\n+\t\tstruct hw_mod_tpe_v2_s v2;\n+\t};\n+};\n+\n+enum hw_tpe_e {\n+\t/* functions */\n+\tHW_TPE_PRESET_ALL = 0,\n+\tHW_TPE_FIND,\n+\tHW_TPE_COMPARE,\n+\t/* Control fields */\n+\tHW_TPE_RPP_RCP_EXP = FIELD_START_INDEX,\n+\tHW_TPE_IFR_RCP_EN,\n+\tHW_TPE_IFR_RCP_MTU,\n+\tHW_TPE_INS_RCP_DYN,\n+\tHW_TPE_INS_RCP_OFS,\n+\tHW_TPE_INS_RCP_LEN,\n+\tHW_TPE_RPL_RCP_DYN,\n+\tHW_TPE_RPL_RCP_OFS,\n+\tHW_TPE_RPL_RCP_LEN,\n+\tHW_TPE_RPL_RCP_RPL_PTR,\n+\tHW_TPE_RPL_RCP_EXT_PRIO,\n+\tHW_TPE_RPL_EXT_RPL_PTR,\n+\tHW_TPE_RPL_EXT_META_RPL_LEN, /* SW only */\n+\tHW_TPE_RPL_RPL_VALUE,\n+\tHW_TPE_CPY_RCP_READER_SELECT,\n+\tHW_TPE_CPY_RCP_DYN,\n+\tHW_TPE_CPY_RCP_OFS,\n+\tHW_TPE_CPY_RCP_LEN,\n+\tHW_TPE_HFU_RCP_LEN_A_WR,\n+\tHW_TPE_HFU_RCP_LEN_A_OUTER_L4_LEN,\n+\tHW_TPE_HFU_RCP_LEN_A_POS_DYN,\n+\tHW_TPE_HFU_RCP_LEN_A_POS_OFS,\n+\tHW_TPE_HFU_RCP_LEN_A_ADD_DYN,\n+\tHW_TPE_HFU_RCP_LEN_A_ADD_OFS,\n+\tHW_TPE_HFU_RCP_LEN_A_SUB_DYN,\n+\tHW_TPE_HFU_RCP_LEN_B_WR,\n+\tHW_TPE_HFU_RCP_LEN_B_POS_DYN,\n+\tHW_TPE_HFU_RCP_LEN_B_POS_OFS,\n+\tHW_TPE_HFU_RCP_LEN_B_ADD_DYN,\n+\tHW_TPE_HFU_RCP_LEN_B_ADD_OFS,\n+\tHW_TPE_HFU_RCP_LEN_B_SUB_DYN,\n+\tHW_TPE_HFU_RCP_LEN_C_WR,\n+\tHW_TPE_HFU_RCP_LEN_C_POS_DYN,\n+\tHW_TPE_HFU_RCP_LEN_C_POS_OFS,\n+\tHW_TPE_HFU_RCP_LEN_C_ADD_DYN,\n+\tHW_TPE_HFU_RCP_LEN_C_ADD_OFS,\n+\tHW_TPE_HFU_RCP_LEN_C_SUB_DYN,\n+\tHW_TPE_HFU_RCP_TTL_WR,\n+\tHW_TPE_HFU_RCP_TTL_POS_DYN,\n+\tHW_TPE_HFU_RCP_TTL_POS_OFS,\n+\tHW_TPE_HFU_RCP_CS_INF,\n+\tHW_TPE_HFU_RCP_L3_PRT,\n+\tHW_TPE_HFU_RCP_L3_FRAG,\n+\tHW_TPE_HFU_RCP_TUNNEL,\n+\tHW_TPE_HFU_RCP_L4_PRT,\n+\tHW_TPE_HFU_RCP_OUTER_L3_OFS,\n+\tHW_TPE_HFU_RCP_OUTER_L4_OFS,\n+\tHW_TPE_HFU_RCP_INNER_L3_OFS,\n+\tHW_TPE_HFU_RCP_INNER_L4_OFS,\n+\tHW_TPE_CSU_RCP_OUTER_L3_CMD,\n+\tHW_TPE_CSU_RCP_OUTER_L4_CMD,\n+\tHW_TPE_CSU_RCP_INNER_L3_CMD,\n+\tHW_TPE_CSU_RCP_INNER_L4_CMD,\n+};\n+\n+bool hw_mod_tpe_present(struct flow_api_backend_s *be);\n+int hw_mod_tpe_alloc(struct flow_api_backend_s *be);\n+void hw_mod_tpe_free(struct flow_api_backend_s *be);\n+int hw_mod_tpe_reset(struct flow_api_backend_s *be);\n+\n+int hw_mod_tpe_rpp_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count);\n+int hw_mod_tpe_rpp_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value);\n+int hw_mod_tpe_rpp_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value);\n+\n+int hw_mod_tpe_rpp_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t\t int count);\n+int hw_mod_tpe_rpp_ifr_rcp_set(struct flow_api_backend_s *be,\n+\t\t\t       enum hw_tpe_e field, int index, uint32_t value);\n+int hw_mod_tpe_rpp_ifr_rcp_get(struct flow_api_backend_s *be,\n+\t\t\t       enum hw_tpe_e field, int index, uint32_t *value);\n+\n+int hw_mod_tpe_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count);\n+int hw_mod_tpe_ifr_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value);\n+int hw_mod_tpe_ifr_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value);\n+\n+int hw_mod_tpe_ins_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count);\n+int hw_mod_tpe_ins_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value);\n+int hw_mod_tpe_ins_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value);\n+\n+int hw_mod_tpe_rpl_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count);\n+int hw_mod_tpe_rpl_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value);\n+int hw_mod_tpe_rpl_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value);\n+\n+int hw_mod_tpe_rpl_ext_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count);\n+int hw_mod_tpe_rpl_ext_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value);\n+int hw_mod_tpe_rpl_ext_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value);\n+\n+int hw_mod_tpe_rpl_rpl_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count);\n+int hw_mod_tpe_rpl_rpl_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value);\n+int hw_mod_tpe_rpl_rpl_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value);\n+\n+int hw_mod_tpe_cpy_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count);\n+int hw_mod_tpe_cpy_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value);\n+int hw_mod_tpe_cpy_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value);\n+\n+int hw_mod_tpe_hfu_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count);\n+int hw_mod_tpe_hfu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value);\n+int hw_mod_tpe_hfu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value);\n+\n+int hw_mod_tpe_csu_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count);\n+int hw_mod_tpe_csu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value);\n+int hw_mod_tpe_csu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value);\n+\n+enum debug_mode_e {\n+\tFLOW_BACKEND_DEBUG_MODE_NONE = 0x0000,\n+\tFLOW_BACKEND_DEBUG_MODE_WRITE = 0x0001\n+};\n+\n+struct flow_api_backend_ops {\n+\tint version;\n+\tint (*set_debug_mode)(void *dev, enum debug_mode_e mode);\n+\tint (*get_nb_phy_port)(void *dev);\n+\tint (*get_nb_rx_port)(void *dev);\n+\tint (*get_ltx_avail)(void *dev);\n+\tint (*get_nb_cat_funcs)(void *dev);\n+\tint (*get_nb_categories)(void *dev);\n+\tint (*get_nb_cat_km_if_cnt)(void *dev);\n+\tint (*get_nb_cat_km_if_m0)(void *dev);\n+\tint (*get_nb_cat_km_if_m1)(void *dev);\n+\n+\tint (*get_nb_queues)(void *dev);\n+\tint (*get_nb_km_flow_types)(void *dev);\n+\tint (*get_nb_pm_ext)(void *dev);\n+\tint (*get_nb_len)(void *dev);\n+\tint (*get_kcc_size)(void *dev);\n+\tint (*get_kcc_banks)(void *dev);\n+\tint (*get_nb_km_categories)(void *dev);\n+\tint (*get_nb_km_cam_banks)(void *dev);\n+\tint (*get_nb_km_cam_record_words)(void *dev);\n+\tint (*get_nb_km_cam_records)(void *dev);\n+\tint (*get_nb_km_tcam_banks)(void *dev);\n+\tint (*get_nb_km_tcam_bank_width)(void *dev);\n+\tint (*get_nb_flm_categories)(void *dev);\n+\tint (*get_nb_flm_size_mb)(void *dev);\n+\tint (*get_nb_flm_entry_size)(void *dev);\n+\tint (*get_nb_flm_variant)(void *dev);\n+\tint (*get_nb_flm_prios)(void *dev);\n+\tint (*get_nb_flm_pst_profiles)(void *dev);\n+\tint (*get_nb_hst_categories)(void *dev);\n+\tint (*get_nb_qsl_categories)(void *dev);\n+\tint (*get_nb_qsl_qst_entries)(void *dev);\n+\tint (*get_nb_pdb_categories)(void *dev);\n+\tint (*get_nb_ioa_categories)(void *dev);\n+\tint (*get_nb_roa_categories)(void *dev);\n+\tint (*get_nb_tpe_categories)(void *dev);\n+\tint (*get_nb_tx_cpy_writers)(void *dev);\n+\tint (*get_nb_tx_cpy_mask_mem)(void *dev);\n+\tint (*get_nb_tx_rpl_depth)(void *dev);\n+\tint (*get_nb_tx_rpl_ext_categories)(void *dev);\n+\tint (*get_nb_tpe_ifr_categories)(void *dev);\n+\n+\tint (*alloc_rx_queue)(void *dev, int queue_id);\n+\tint (*free_rx_queue)(void *dev, int hw_queue);\n+\n+\t/* CAT */\n+\tbool (*get_cat_present)(void *dev);\n+\tuint32_t (*get_cat_version)(void *dev);\n+\tint (*cat_cfn_flush)(void *dev, const struct cat_func_s *cat,\n+\t\t\t     int cat_func, int cnt);\n+\tint (*cat_kce_flush)(void *dev, const struct cat_func_s *cat,\n+\t\t\t     int km_if_idx, int index, int cnt);\n+\tint (*cat_kcs_flush)(void *dev, const struct cat_func_s *cat,\n+\t\t\t     int km_if_idx, int cat_func, int cnt);\n+\tint (*cat_fte_flush)(void *dev, const struct cat_func_s *cat,\n+\t\t\t     int km_if_idx, int index, int cnt);\n+\tint (*cat_cte_flush)(void *dev, const struct cat_func_s *cat,\n+\t\t\t     int cat_func, int cnt);\n+\tint (*cat_cts_flush)(void *dev, const struct cat_func_s *cat, int index,\n+\t\t\t     int cnt);\n+\tint (*cat_cot_flush)(void *dev, const struct cat_func_s *cat,\n+\t\t\t     int cat_func, int cnt);\n+\tint (*cat_cct_flush)(void *dev, const struct cat_func_s *cat, int index,\n+\t\t\t     int cnt);\n+\tint (*cat_exo_flush)(void *dev, const struct cat_func_s *cat, int index,\n+\t\t\t     int cnt);\n+\tint (*cat_rck_flush)(void *dev, const struct cat_func_s *cat, int index,\n+\t\t\t     int cnt);\n+\tint (*cat_len_flush)(void *dev, const struct cat_func_s *cat, int index,\n+\t\t\t     int cnt);\n+\tint (*cat_kcc_flush)(void *dev, const struct cat_func_s *cat, int index,\n+\t\t\t     int cnt);\n+\tint (*cat_cce_flush)(void *dev, const struct cat_func_s *cat, int index,\n+\t\t\t     int cnt);\n+\tint (*cat_ccs_flush)(void *dev, const struct cat_func_s *cat, int index,\n+\t\t\t     int cnt);\n+\n+\t/* KM */\n+\tbool (*get_km_present)(void *dev);\n+\tuint32_t (*get_km_version)(void *dev);\n+\tint (*km_rcp_flush)(void *dev, const struct km_func_s *km, int category,\n+\t\t\t    int cnt);\n+\tint (*km_cam_flush)(void *dev, const struct km_func_s *km, int bank,\n+\t\t\t    int record, int cnt);\n+\tint (*km_tcam_flush)(void *dev, const struct km_func_s *km, int bank,\n+\t\t\t     int byte, int value, int cnt);\n+\tint (*km_tci_flush)(void *dev, const struct km_func_s *km, int bank,\n+\t\t\t    int record, int cnt);\n+\tint (*km_tcq_flush)(void *dev, const struct km_func_s *km, int bank,\n+\t\t\t    int record, int cnt);\n+\n+\t/* FLM */\n+\tbool (*get_flm_present)(void *dev);\n+\tuint32_t (*get_flm_version)(void *dev);\n+\tint (*flm_control_flush)(void *dev, const struct flm_func_s *flm);\n+\tint (*flm_status_flush)(void *dev, const struct flm_func_s *flm);\n+\tint (*flm_status_update)(void *dev, const struct flm_func_s *flm);\n+\tint (*flm_timeout_flush)(void *dev, const struct flm_func_s *flm);\n+\tint (*flm_scrub_flush)(void *dev, const struct flm_func_s *flm);\n+\tint (*flm_load_bin_flush)(void *dev, const struct flm_func_s *flm);\n+\tint (*flm_load_pps_flush)(void *dev, const struct flm_func_s *flm);\n+\tint (*flm_load_lps_flush)(void *dev, const struct flm_func_s *flm);\n+\tint (*flm_load_aps_flush)(void *dev, const struct flm_func_s *flm);\n+\tint (*flm_prio_flush)(void *dev, const struct flm_func_s *flm);\n+\tint (*flm_pst_flush)(void *dev, const struct flm_func_s *flm, int index,\n+\t\t\t     int cnt);\n+\tint (*flm_rcp_flush)(void *dev, const struct flm_func_s *flm, int index,\n+\t\t\t     int cnt);\n+\tint (*flm_buf_ctrl_update)(void *dev, const struct flm_func_s *flm);\n+\tint (*flm_stat_update)(void *dev, const struct flm_func_s *flm);\n+\tint (*flm_lrn_data_flush)(void *be_dev, const struct flm_func_s *flm,\n+\t\t\t\t  const uint32_t *lrn_data, uint32_t size);\n+\tint (*flm_inf_data_update)(void *be_dev, const struct flm_func_s *flm,\n+\t\t\t\t   uint32_t *lrn_data, uint32_t size);\n+\tint (*flm_sta_data_update)(void *be_dev, const struct flm_func_s *flm,\n+\t\t\t\t   uint32_t *lrn_data, uint32_t size);\n+\n+\t/* HSH */\n+\tbool (*get_hsh_present)(void *dev);\n+\tuint32_t (*get_hsh_version)(void *dev);\n+\tint (*hsh_rcp_flush)(void *dev, const struct hsh_func_s *hsh,\n+\t\t\t     int category, int cnt);\n+\n+\t/* HST */\n+\tbool (*get_hst_present)(void *dev);\n+\tuint32_t (*get_hst_version)(void *dev);\n+\tint (*hst_rcp_flush)(void *dev, const struct hst_func_s *hst,\n+\t\t\t     int category, int cnt);\n+\n+\t/* QSL */\n+\tbool (*get_qsl_present)(void *dev);\n+\tuint32_t (*get_qsl_version)(void *dev);\n+\tint (*qsl_rcp_flush)(void *dev, const struct qsl_func_s *qsl,\n+\t\t\t     int category, int cnt);\n+\tint (*qsl_qst_flush)(void *dev, const struct qsl_func_s *qsl, int entry,\n+\t\t\t     int cnt);\n+\tint (*qsl_qen_flush)(void *dev, const struct qsl_func_s *qsl, int entry,\n+\t\t\t     int cnt);\n+\tint (*qsl_unmq_flush)(void *dev, const struct qsl_func_s *qsl,\n+\t\t\t      int entry, int cnt);\n+\n+\t/* SLC */\n+\tbool (*get_slc_present)(void *dev);\n+\tuint32_t (*get_slc_version)(void *dev);\n+\tint (*slc_rcp_flush)(void *dev, const struct slc_func_s *slc,\n+\t\t\t     int category, int cnt);\n+\n+\t/* SLC LR */\n+\tbool (*get_slc_lr_present)(void *dev);\n+\tuint32_t (*get_slc_lr_version)(void *dev);\n+\tint (*slc_lr_rcp_flush)(void *dev, const struct slc_lr_func_s *slc_lr,\n+\t\t\t\tint category, int cnt);\n+\n+\t/* PDB */\n+\tbool (*get_pdb_present)(void *dev);\n+\tuint32_t (*get_pdb_version)(void *dev);\n+\tint (*pdb_rcp_flush)(void *dev, const struct pdb_func_s *pdb,\n+\t\t\t     int category, int cnt);\n+\tint (*pdb_config_flush)(void *dev, const struct pdb_func_s *pdb);\n+\n+\t/* IOA */\n+\tbool (*get_ioa_present)(void *dev);\n+\tuint32_t (*get_ioa_version)(void *dev);\n+\tint (*ioa_rcp_flush)(void *dev, const struct ioa_func_s *ioa, int index,\n+\t\t\t     int cnt);\n+\tint (*ioa_special_tpid_flush)(void *dev, const struct ioa_func_s *ioa);\n+\tint (*ioa_roa_epp_flush)(void *dev, const struct ioa_func_s *ioa,\n+\t\t\t\t int index, int cnt);\n+\n+\t/* ROA */\n+\tbool (*get_roa_present)(void *dev);\n+\tuint32_t (*get_roa_version)(void *dev);\n+\tint (*roa_tunhdr_flush)(void *dev, const struct roa_func_s *roa,\n+\t\t\t\tint index, int cnt);\n+\tint (*roa_tuncfg_flush)(void *dev, const struct roa_func_s *roa,\n+\t\t\t\tint index, int cnt);\n+\tint (*roa_config_flush)(void *dev, const struct roa_func_s *roa);\n+\tint (*roa_lagcfg_flush)(void *dev, const struct roa_func_s *roa,\n+\t\t\t\tint index, int cnt);\n+\n+\t/* RMC */\n+\tbool (*get_rmc_present)(void *dev);\n+\tuint32_t (*get_rmc_version)(void *dev);\n+\tint (*rmc_ctrl_flush)(void *dev, const struct rmc_func_s *rmc);\n+\n+\t/* TPE */\n+\tbool (*get_tpe_present)(void *dev);\n+\tuint32_t (*get_tpe_version)(void *dev);\n+\tint (*tpe_rpp_rcp_flush)(void *dev, const struct tpe_func_s *tpe,\n+\t\t\t\t int index, int cnt);\n+\tint (*tpe_rpp_ifr_rcp_flush)(void *dev, const struct tpe_func_s *tpe,\n+\t\t\t\t     int index, int cnt);\n+\tint (*tpe_ifr_rcp_flush)(void *dev, const struct tpe_func_s *tpe,\n+\t\t\t\t int index, int cnt);\n+\tint (*tpe_ins_rcp_flush)(void *dev, const struct tpe_func_s *tpe,\n+\t\t\t\t int index, int cnt);\n+\tint (*tpe_rpl_rcp_flush)(void *dev, const struct tpe_func_s *tpe,\n+\t\t\t\t int index, int cnt);\n+\tint (*tpe_rpl_ext_flush)(void *dev, const struct tpe_func_s *tpe,\n+\t\t\t\t int index, int cnt);\n+\tint (*tpe_rpl_rpl_flush)(void *dev, const struct tpe_func_s *tpe,\n+\t\t\t\t int index, int cnt);\n+\tint (*tpe_cpy_rcp_flush)(void *dev, const struct tpe_func_s *tpe,\n+\t\t\t\t int index, int cnt);\n+\tint (*tpe_hfu_rcp_flush)(void *dev, const struct tpe_func_s *tpe,\n+\t\t\t\t int index, int cnt);\n+\tint (*tpe_csu_rcp_flush)(void *dev, const struct tpe_func_s *tpe,\n+\t\t\t\t int index, int cnt);\n+};\n+\n+struct flow_api_backend_s {\n+\tvoid *be_dev;\n+\tconst struct flow_api_backend_ops *iface;\n+\n+\t/* flow filter FPGA modules */\n+\tstruct cat_func_s cat;\n+\tstruct km_func_s km;\n+\tstruct flm_func_s flm;\n+\tstruct hsh_func_s hsh;\n+\tstruct hst_func_s hst;\n+\tstruct qsl_func_s qsl;\n+\tstruct slc_func_s slc;\n+\tstruct slc_lr_func_s slc_lr;\n+\tstruct pdb_func_s pdb;\n+\tstruct ioa_func_s ioa;\n+\tstruct roa_func_s roa;\n+\tstruct rmc_func_s rmc;\n+\tstruct tpe_func_s tpe;\n+\n+\t/* NIC attributes */\n+\tunsigned int num_phy_ports;\n+\tunsigned int num_rx_ports;\n+\n+\t/* flow filter resource capacities */\n+\tunsigned int max_categories;\n+\tunsigned int max_queues;\n+};\n+\n+int flow_api_backend_init(struct flow_api_backend_s *dev,\n+\t\t\t  const struct flow_api_backend_ops *iface,\n+\t\t\t  void *be_dev);\n+int flow_api_backend_reset(struct flow_api_backend_s *dev);\n+int flow_api_backend_done(struct flow_api_backend_s *dev);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* __FLOW_API_BACKEND_H__ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_engine.h b/drivers/net/ntnic/nthw/flow_api/flow_api_engine.h\nnew file mode 100644\nindex 0000000000..b63730c07e\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_engine.h\n@@ -0,0 +1,475 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _FLOW_API_ENGINE_H_\n+#define _FLOW_API_ENGINE_H_\n+\n+#include <stdint.h>\n+#include \"stream_binary_flow_api.h\"\n+\n+struct flow_elem;\n+/*\n+ * ****************************************************\n+ *                Resource management\n+ * ****************************************************\n+ */\n+#define BIT_CONTAINER_8_ALIGN(x) (((x) + 7) / 8)\n+\n+/*\n+ * Resource management\n+ * These are free resources in FPGA\n+ * Other FPGA memory lists are linked to one of these\n+ * and will implicitly follow them\n+ */\n+enum res_type_e {\n+\tRES_QUEUE,\n+\tRES_CAT_CFN,\n+\tRES_CAT_COT,\n+\tRES_CAT_EXO,\n+\tRES_CAT_LEN,\n+\tRES_KM_FLOW_TYPE,\n+\tRES_KM_CATEGORY,\n+\tRES_HSH_RCP,\n+\tRES_PDB_RCP,\n+\tRES_QSL_RCP,\n+\tRES_QSL_QST,\n+\tRES_SLC_RCP,\n+\tRES_IOA_RCP,\n+\tRES_ROA_RCP,\n+\tRES_FLM_FLOW_TYPE,\n+\tRES_FLM_RCP,\n+\tRES_HST_RCP,\n+\tRES_TPE_RCP,\n+\tRES_TPE_EXT,\n+\tRES_TPE_RPL,\n+\tRES_COUNT,\n+\tRES_INVALID\n+};\n+\n+/*\n+ * ****************************************************\n+ *           Flow NIC offload management\n+ * ****************************************************\n+ */\n+#define MAX_OUTPUT_DEST (128)\n+#define NB_QSL_QEN_ADDR 32\n+\n+#define INVALID_FLOW_STAT_ID 0xffffffff\n+\n+#define MAX_WORD_NUM 24\n+#define MAX_BANKS 6\n+\n+#define MAX_TCAM_START_OFFSETS 4\n+\n+#define MAX_TAG_INDEX 8\n+\n+#define MAX_FLM_MTRS_SUPPORTED 4\n+#define MAX_CPY_WRITERS_SUPPORTED 8\n+\n+/*\n+ *          128      128     32     32    32\n+ * Have  |  QW0  ||  QW4  || SW8 || SW9 | SWX   in FPGA\n+ *\n+ * Each word may start at any offset, though\n+ * they are combined in chronological order, with all enabled to\n+ * build the extracted match data, thus that is how the match key\n+ * must be build\n+ *\n+ */\n+enum extractor_e {\n+\tKM_USE_EXTRACTOR_UNDEF,\n+\tKM_USE_EXTRACTOR_QWORD,\n+\tKM_USE_EXTRACTOR_SWORD,\n+};\n+\n+struct match_elem_s {\n+\tenum extractor_e extr;\n+\tint masked_for_tcam; /* if potentially selected for TCAM */\n+\tuint32_t e_word[4];\n+\tuint32_t e_mask[4];\n+\n+\tint extr_start_offs_id;\n+\tint8_t rel_offs;\n+\tuint32_t word_len;\n+};\n+\n+enum cam_tech_use_e { KM_CAM, KM_TCAM, KM_SYNERGY };\n+\n+#define MAX_MATCH_FIELDS 16\n+\n+struct km_flow_def_s {\n+\tstruct flow_api_backend_s *be;\n+\n+\t/* For keeping track of identical entries */\n+\tstruct km_flow_def_s *reference;\n+\tstruct km_flow_def_s *root;\n+\n+\t/* For collect flow elements and sorting */\n+\tstruct match_elem_s match[MAX_MATCH_FIELDS];\n+\tstruct match_elem_s *match_map[MAX_MATCH_FIELDS];\n+\tint num_ftype_elem;\n+\n+\t/* Finally formatted CAM/TCAM entry */\n+\tenum cam_tech_use_e target;\n+\tuint32_t entry_word[MAX_WORD_NUM];\n+\tuint32_t entry_mask[MAX_WORD_NUM];\n+\tint key_word_size;\n+\n+\t/* TCAM calculated possible bank start offsets */\n+\tint start_offsets[MAX_TCAM_START_OFFSETS];\n+\tint num_start_offsets;\n+\n+\t/* Flow information */\n+\n+\t/*\n+\t * HW input port ID needed for compare. In port must be identical on flow\n+\t * types\n+\t */\n+\tuint32_t port_id;\n+\tuint32_t info; /* used for color (actions) */\n+\tint info_set;\n+\tint flow_type; /* 0 is illegal and used as unset */\n+\tint flushed_to_target; /* if this km entry has been finally programmed into NIC hw */\n+\n+\t/* CAM specific bank management */\n+\tint cam_paired;\n+\tint record_indexes[MAX_BANKS];\n+\tint bank_used;\n+\tuint32_t *cuckoo_moves; /* for CAM statistics only */\n+\tstruct cam_distrib_s *cam_dist;\n+\tstruct hasher_s *hsh;\n+\n+\t/* TCAM specific bank management */\n+\tstruct tcam_distrib_s *tcam_dist;\n+\tint tcam_start_bank;\n+\tint tcam_record;\n+};\n+\n+/*\n+ * KCC-CAM\n+ */\n+struct kcc_key_s {\n+\tuint64_t sb_data : 32;\n+\tuint64_t sb_type : 8;\n+\tuint64_t cat_cfn : 8;\n+\tuint64_t port : 16;\n+};\n+\n+#define KCC_ID_INVALID 0xffffffff\n+\n+struct kcc_flow_def_s {\n+\tstruct flow_api_backend_s *be;\n+\tunion {\n+\t\tuint64_t key64;\n+\t\tuint32_t key32[2];\n+\t\tstruct kcc_key_s key;\n+\t};\n+\tuint32_t km_category;\n+\tuint32_t id;\n+\n+\tuint8_t *kcc_unique_ids;\n+\n+\tint flushed_to_target;\n+\tint record_indexes[MAX_BANKS];\n+\tint bank_used;\n+\tuint32_t *cuckoo_moves; /* for CAM statistics only */\n+\tstruct kcc_cam_distrib_s *cam_dist;\n+\tstruct hasher_s *hsh;\n+};\n+\n+/*\n+ * Tunnel encapsulation header definition\n+ */\n+enum { TUN_TYPE_VXLAN = 0, TUN_TYPE_NVGRE = 1 };\n+\n+#define MAX_TUN_HDR_SIZE 128\n+\n+struct tunnel_header_s {\n+\tunion {\n+\t\tuint8_t hdr8[MAX_TUN_HDR_SIZE];\n+\t\tuint32_t hdr32[(MAX_TUN_HDR_SIZE + 3) / 4];\n+\t} d;\n+\tuint32_t user_port_id;\n+\tuint8_t len;\n+\n+\tuint8_t nb_vlans;\n+\n+\tuint8_t ip_version; /* 4: v4, 6: v6 */\n+\tuint16_t ip_csum_precalc;\n+\n+\tuint8_t new_outer;\n+\tuint8_t l2_len;\n+\tuint8_t l3_len;\n+\tuint8_t l4_len;\n+};\n+\n+enum port_type_e {\n+\tPORT_NONE, /* not defined or drop */\n+\tPORT_INTERNAL, /* no queues attached */\n+\tPORT_PHY, /* MAC phy output queue */\n+\tPORT_VIRT, /* Memory queues to Host */\n+};\n+\n+enum special_partial_match_e {\n+\tSPECIAL_MATCH_NONE,\n+\tSPECIAL_MATCH_LACP,\n+};\n+\n+#define PORT_ID_NONE 0xffffffff\n+\n+struct output_s {\n+\tuint32_t owning_port_id; /* the port who owns this output destination */\n+\tenum port_type_e type;\n+\tint id; /* depending on port type: queue ID or physical port id or not used */\n+\tint active; /* activated */\n+};\n+\n+struct nic_flow_def {\n+\t/*\n+\t * Frame Decoder match info collected\n+\t */\n+\tint l2_prot;\n+\tint l3_prot;\n+\tint l4_prot;\n+\tint tunnel_prot;\n+\tint tunnel_l3_prot;\n+\tint tunnel_l4_prot;\n+\tint vlans;\n+\tint fragmentation;\n+\t/*\n+\t * Additional meta data for various functions\n+\t */\n+\tint in_port_override;\n+\tint l4_dst_port;\n+\t/*\n+\t * Output destination info collection\n+\t */\n+\tstruct output_s dst_id[MAX_OUTPUT_DEST]; /* define the output to use */\n+\t/* total number of available queues defined for all outputs - i.e. number of dst_id's */\n+\tint dst_num_avail;\n+\n+\t/*\n+\t * To identify high priority match with mark for special SW processing (non-OVS)\n+\t */\n+\tenum special_partial_match_e special_match;\n+\n+\t/*\n+\t * Mark or Action info collection\n+\t */\n+\tuint32_t mark;\n+\tuint64_t roa_actions;\n+\tuint64_t ioa_actions;\n+\n+\tuint32_t jump_to_group;\n+\n+\tuint32_t mtr_ids[MAX_FLM_MTRS_SUPPORTED];\n+\n+\tint full_offload;\n+\t/*\n+\t * Action push tunnel\n+\t */\n+\tstruct tunnel_header_s tun_hdr;\n+\n+\t/*\n+\t * If DPDK RTE tunnel helper API used\n+\t * this holds the tunnel if used in flow\n+\t */\n+\tstruct tunnel_s *tnl;\n+\n+\t/*\n+\t * Header Stripper\n+\t */\n+\tint header_strip_start_dyn;\n+\tint header_strip_start_ofs;\n+\tint header_strip_end_dyn;\n+\tint header_strip_end_ofs;\n+\tint header_strip_removed_outer_ip;\n+\n+\t/*\n+\t * Modify field\n+\t */\n+\tstruct {\n+\t\tuint32_t select;\n+\t\tuint32_t dyn;\n+\t\tuint32_t ofs;\n+\t\tuint32_t len;\n+\t\tuint32_t level;\n+\t\tunion {\n+\t\t\tuint8_t value8[16];\n+\t\t\tuint16_t value16[8];\n+\t\t\tuint32_t value32[4];\n+\t\t};\n+\t} modify_field[MAX_CPY_WRITERS_SUPPORTED];\n+\n+\tuint32_t modify_field_count;\n+\tuint8_t ttl_sub_enable;\n+\tuint8_t ttl_sub_ipv4;\n+\tuint8_t ttl_sub_outer;\n+\n+\t/*\n+\t * Key Matcher flow definitions\n+\t */\n+\tstruct km_flow_def_s km;\n+\n+\t/*\n+\t * Key Matcher Category CAM\n+\t */\n+\tstruct kcc_flow_def_s *kcc;\n+\tint kcc_referenced;\n+\n+\t/*\n+\t * TX fragmentation IFR/RPP_LR MTU recipe\n+\t */\n+\tuint8_t flm_mtu_fragmentation_recipe;\n+};\n+\n+enum flow_handle_type {\n+\tFLOW_HANDLE_TYPE_FLOW,\n+\tFLOW_HANDLE_TYPE_FLM,\n+};\n+\n+struct flow_handle {\n+\tenum flow_handle_type type;\n+\n+\tstruct flow_eth_dev *dev;\n+\tstruct flow_handle *next;\n+\tstruct flow_handle *prev;\n+\n+\tunion {\n+\t\tstruct {\n+\t\t\t/*\n+\t\t\t * 1st step conversion and validation of flow\n+\t\t\t * verified and converted flow match + actions structure\n+\t\t\t */\n+\t\t\tstruct nic_flow_def *fd;\n+\t\t\t/*\n+\t\t\t * 2nd step NIC HW resource allocation and configuration\n+\t\t\t * NIC resource management structures\n+\t\t\t */\n+\t\t\tstruct {\n+\t\t\t\tint index; /* allocation index into NIC raw resource table */\n+\t\t\t\t/* number of contiguous allocations needed for this resource */\n+\t\t\t\tint count;\n+\t\t\t\t/*\n+\t\t\t\t * This resource if not initially created by this flow, but reused\n+\t\t\t\t * by it\n+\t\t\t\t */\n+\t\t\t\tint referenced;\n+\t\t\t} resource[RES_COUNT];\n+\t\t\tint flushed;\n+\n+\t\t\tuint32_t flow_stat_id;\n+\t\t\tuint32_t color;\n+\t\t\tint cao_enabled;\n+\t\t\tuint32_t cte;\n+\n+\t\t\tuint32_t port_id; /* MAC port ID or override of virtual in_port */\n+\t\t\tuint32_t flm_ref_count;\n+\t\t\tuint8_t flm_group_index;\n+\t\t\tuint8_t flm_ft_index;\n+\t\t};\n+\n+\t\tstruct {\n+\t\t\tuint32_t flm_data[10];\n+\t\t\tuint8_t flm_prot;\n+\t\t\tuint8_t flm_kid;\n+\t\t\tuint8_t flm_prio;\n+\n+\t\t\tuint16_t flm_rpl_ext_ptr;\n+\t\t\tuint32_t flm_nat_ipv4;\n+\t\t\tuint16_t flm_nat_port;\n+\t\t\tuint8_t flm_dscp;\n+\t\t\tuint32_t flm_teid;\n+\t\t\tuint8_t flm_rqi;\n+\t\t\tuint8_t flm_qfi;\n+\n+\t\t\tuint8_t flm_mtu_fragmentation_recipe;\n+\n+\t\t\tstruct flow_handle *flm_owner;\n+\t\t};\n+\t};\n+};\n+\n+void km_attach_ndev_resource_management(struct km_flow_def_s *km,\n+\t\t\t\t\tvoid **handle);\n+void km_free_ndev_resource_management(void **handle);\n+\n+int km_get_cam_population_level(void *cam_dist, uint32_t *cam_elem,\n+\t\t\t\tuint32_t *cuckoo_moves);\n+\n+int km_add_match_elem(struct km_flow_def_s *km, uint32_t e_word[4],\n+\t\t      uint32_t e_mask[4], uint32_t word_len,\n+\t\t      enum frame_offs_e start, int8_t offset);\n+\n+int km_key_create(struct km_flow_def_s *km, uint32_t port_id);\n+/*\n+ * Compares 2 KM key definitions after first collect validate and optimization.\n+ * km is compared against an existing km1.\n+ * if identical, km1 flow_type is returned\n+ */\n+int km_key_compare(struct km_flow_def_s *km, struct km_flow_def_s *km1);\n+\n+void km_set_info(struct km_flow_def_s *km, int on);\n+int km_rcp_set(struct km_flow_def_s *km, int index);\n+\n+int km_refer_data_match_entry(struct km_flow_def_s *km,\n+\t\t\t      struct km_flow_def_s *km1);\n+int km_write_data_match_entry(struct km_flow_def_s *km, uint32_t color);\n+int km_clear_data_match_entry(struct km_flow_def_s *km);\n+\n+void kcc_attach_ndev_resource_management(struct kcc_flow_def_s *kcc,\n+\t\tvoid **handle);\n+void kcc_free_ndev_resource_management(void **handle);\n+int kcc_alloc_unique_id(struct kcc_flow_def_s *kcc);\n+void kcc_free_unique_id(struct kcc_flow_def_s *kcc);\n+int kcc_key_compare(struct kcc_flow_def_s *kcc, struct kcc_flow_def_s *kcc1);\n+int kcc_add_km_category(struct kcc_flow_def_s *kcc, uint32_t category);\n+\n+int kcc_key_add_no_sideband(struct kcc_flow_def_s *kcc);\n+int kcc_key_add_vlan(struct kcc_flow_def_s *kcc, uint16_t tpid, uint16_t vid);\n+int kcc_key_add_vxlan(struct kcc_flow_def_s *kcc, uint32_t vni);\n+int kcc_key_add_port(struct kcc_flow_def_s *kcc, uint16_t port);\n+int kcc_key_add_cat_cfn(struct kcc_flow_def_s *kcc, uint8_t cat_cfn);\n+uint8_t kcc_key_get_cat_cfn(struct kcc_flow_def_s *kcc);\n+\n+int kcc_write_data_match_entry(struct kcc_flow_def_s *kcc);\n+int kcc_key_ref_count_add(struct kcc_flow_def_s *kcc);\n+int kcc_key_ref_count_dec(struct kcc_flow_def_s *kcc);\n+\n+/*\n+ * Group management\n+ */\n+int flow_group_handle_create(void **handle, uint32_t group_count);\n+int flow_group_handle_destroy(void **handle);\n+\n+int flow_group_translate_get(void *handle, uint8_t owner_id, uint32_t group_in,\n+\t\t\t     uint32_t *group_out);\n+int flow_group_translate_release(void *handle, uint32_t translated_group);\n+\n+/*\n+ * Actions management\n+ */\n+uint8_t flow_tunnel_alloc_virt_port(void);\n+uint8_t flow_tunnel_free_virt_port(uint8_t virt_port);\n+struct tunnel_s *tunnel_parse(const struct flow_elem *elem, int *idx,\n+\t\t\t      uint32_t *vni);\n+int tunnel_release(struct tunnel_s *tnl);\n+uint8_t get_tunnel_vport(struct tunnel_s *rtnl);\n+void tunnel_set_flow_stat_id(struct tunnel_s *rtnl, uint32_t flow_stat_id);\n+int tunnel_get_definition(struct tunnel_cfg_s *tun, uint32_t flow_stat_id,\n+\t\t\t  uint8_t vport);\n+\n+int is_virtual_port(uint8_t virt_port);\n+int flow_tunnel_create_vxlan_hdr(struct flow_api_backend_s *be,\n+\t\t\t\t struct nic_flow_def *fd,\n+\t\t\t\t const struct flow_elem *elem);\n+\n+/*\n+ * statistics\n+ */\n+uint32_t flow_actions_create_flow_stat_id(uint32_t *stat_map, uint32_t mark);\n+void flow_actions_delete_flow_stat_id(uint32_t *stat_map,\n+\t\t\t\t      uint32_t flow_stat_id);\n+\n+#endif /* _FLOW_API_ENGINE_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h b/drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h\nnew file mode 100644\nindex 0000000000..c4db0f4c5c\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h\n@@ -0,0 +1,32 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __FLOW_API_NIC_SETUP_H__\n+#define __FLOW_API_NIC_SETUP_H__\n+\n+#include <stdio.h>\n+#include <stdint.h>\n+#include <stdbool.h>\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+struct flow_api_backend_ops; /* Operation list for common FPGA module API for backend */\n+struct flow_nic_dev; /* adapter device */\n+\n+/*\n+ * Flow capable NIC backend - creating flow api instance for adapter nr (backend)\n+ */\n+struct flow_nic_dev *flow_api_create(uint8_t adapter_no,\n+\t\t\t\t     const struct flow_api_backend_ops *be_if,\n+\t\t\t\t     void *be_dev);\n+int flow_api_done(struct flow_nic_dev *dev);\n+void *flow_api_get_be_dev(struct flow_nic_dev *dev);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* __FLOW_API_NIC_SETUP_H__ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c\nnew file mode 100644\nindex 0000000000..9b6e5484a0\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c\n@@ -0,0 +1,125 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"flow_api_backend.h\"\n+#include \"flow_api_engine.h\"\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+\n+#define OWNER_ID_COUNT 256\n+\n+struct group_lookup_entry_s {\n+\tuint64_t ref_counter;\n+\tuint32_t *reverse_lookup;\n+};\n+\n+struct group_handle_s {\n+\tuint32_t group_count;\n+\n+\tuint32_t *translation_table;\n+\n+\tstruct group_lookup_entry_s *lookup_entries;\n+};\n+\n+int flow_group_handle_create(void **handle, uint32_t group_count)\n+{\n+\tstruct group_handle_s *group_handle;\n+\n+\t*handle = calloc(1, sizeof(struct group_handle_s));\n+\tgroup_handle = *handle;\n+\n+\tgroup_handle->group_count = group_count;\n+\tgroup_handle->translation_table = calloc((uint32_t)(group_count * OWNER_ID_COUNT),\n+\t\t\t\t\t\t sizeof(uint32_t));\n+\tgroup_handle->lookup_entries =\n+\t\tcalloc(group_count, sizeof(struct group_lookup_entry_s));\n+\n+\treturn *handle != NULL ? 0 : -1;\n+}\n+\n+int flow_group_handle_destroy(void **handle)\n+{\n+\tif (*handle) {\n+\t\tstruct group_handle_s *group_handle =\n+\t\t\t(struct group_handle_s *)*handle;\n+\n+\t\tfree(group_handle->translation_table);\n+\t\tfree(group_handle->lookup_entries);\n+\n+\t\tfree(*handle);\n+\t\t*handle = NULL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int flow_group_translate_get(void *handle, uint8_t owner_id, uint32_t group_in,\n+\t\t\t     uint32_t *group_out)\n+{\n+\tstruct group_handle_s *group_handle = (struct group_handle_s *)handle;\n+\tuint32_t *table_ptr;\n+\tuint32_t lookup;\n+\n+\tif (group_handle == NULL || group_in >= group_handle->group_count)\n+\t\treturn -1;\n+\n+\t/* Don't translate group 0 */\n+\tif (group_in == 0) {\n+\t\t*group_out = 0;\n+\t\treturn 0;\n+\t}\n+\n+\ttable_ptr = &group_handle->translation_table[owner_id * OWNER_ID_COUNT +\n+\t\t\t\t group_in];\n+\tlookup = *table_ptr;\n+\n+\tif (lookup == 0) {\n+\t\tfor (lookup = 1;\n+\t\t\t\tlookup < group_handle->group_count &&\n+\t\t\t\tgroup_handle->lookup_entries[lookup].ref_counter > 0;\n+\t\t\t\t++lookup)\n+\t\t\t;\n+\n+\t\tif (lookup < group_handle->group_count) {\n+\t\t\tgroup_handle->lookup_entries[lookup].reverse_lookup =\n+\t\t\t\ttable_ptr;\n+\t\t\tgroup_handle->lookup_entries[lookup].ref_counter += 1;\n+\n+\t\t\t*table_ptr = lookup;\n+\t\t} else {\n+\t\t\treturn -1;\n+\t\t}\n+\t} else {\n+\t\tgroup_handle->lookup_entries[lookup].ref_counter += 1;\n+\t}\n+\t*group_out = lookup;\n+\treturn 0;\n+}\n+\n+int flow_group_translate_release(void *handle, uint32_t translated_group)\n+{\n+\tstruct group_handle_s *group_handle = (struct group_handle_s *)handle;\n+\tstruct group_lookup_entry_s *lookup;\n+\n+\tif (group_handle == NULL ||\n+\t\t\ttranslated_group >= group_handle->group_count)\n+\t\treturn -1;\n+\n+\t/* Don't translate group 0 */\n+\tif (translated_group == 0)\n+\t\treturn 0;\n+\n+\tlookup = &group_handle->lookup_entries[translated_group];\n+\n+\tif (lookup->reverse_lookup && lookup->ref_counter > 0) {\n+\t\tlookup->ref_counter -= 1;\n+\t\tif (lookup->ref_counter == 0) {\n+\t\t\t*lookup->reverse_lookup = 0;\n+\t\t\tlookup->reverse_lookup = NULL;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c\nnew file mode 100644\nindex 0000000000..6982129e17\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c\n@@ -0,0 +1,213 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"flow_hasher.h\"\n+\n+#include <math.h>\n+\n+/* #define TESTING */\n+\n+#ifdef TESTING\n+#include <stdio.h>\n+int hash_test(struct hasher_s *hsh, int banks, int record_bw);\n+#endif\n+\n+static uint32_t shuffle(uint32_t x)\n+{\n+\treturn (((x & 0x00000002) << 29) | ((x & 0xAAAAAAA8) >> 3) |\n+\t\t((x & 0x15555555) << 3) | ((x & 0x40000000) >> 29));\n+}\n+\n+static uint32_t ror_inv(uint32_t x, const int s)\n+{\n+\treturn ((x >> s) | ((~x) << (32 - s)));\n+}\n+\n+static uint32_t combine(uint32_t x, uint32_t y)\n+{\n+\tuint32_t x1 = ror_inv(x, 15);\n+\tuint32_t x2 = ror_inv(x, 13);\n+\tuint32_t y1 = ror_inv(y, 3);\n+\tuint32_t y2 = ror_inv(y, 27);\n+\n+\treturn (x ^ y ^\n+\t\t((x1 & y1 & ~x2 & ~y2) | (x1 & ~y1 & x2 & ~y2) |\n+\t\t (x1 & ~y1 & ~x2 & y2) | (~x1 & y1 & x2 & ~y2) |\n+\t\t (~x1 & y1 & ~x2 & y2) | (~x1 & ~y1 & x2 & y2)));\n+}\n+\n+static uint32_t mix(uint32_t x, uint32_t y)\n+{\n+\treturn shuffle(combine(x, y));\n+}\n+\n+static uint64_t ror_inv3(uint64_t x)\n+{\n+\tconst uint64_t m = 0xE0000000E0000000ULL;\n+\n+\treturn (((x >> 3) | m) ^ ((x << 29) & m));\n+}\n+\n+static uint64_t ror_inv13(uint64_t x)\n+{\n+\tconst uint64_t m = 0xFFF80000FFF80000ULL;\n+\n+\treturn (((x >> 13) | m) ^ ((x << 19) & m));\n+}\n+\n+static uint64_t ror_inv15(uint64_t x)\n+{\n+\tconst uint64_t m = 0xFFFE0000FFFE0000ULL;\n+\n+\treturn (((x >> 15) | m) ^ ((x << 17) & m));\n+}\n+\n+static uint64_t ror_inv27(uint64_t x)\n+{\n+\tconst uint64_t m = 0xFFFFFFE0FFFFFFE0ULL;\n+\n+\treturn (((x >> 27) | m) ^ ((x << 5) & m));\n+}\n+\n+static uint64_t shuffle64(uint64_t x)\n+{\n+\treturn (((x & 0x0000000200000002) << 29) |\n+\t\t((x & 0xAAAAAAA8AAAAAAA8) >> 3) |\n+\t\t((x & 0x1555555515555555) << 3) |\n+\t\t((x & 0x4000000040000000) >> 29));\n+}\n+\n+static uint64_t pair(uint32_t x, uint32_t y)\n+{\n+\treturn (((uint64_t)x << 32) | y);\n+}\n+\n+static uint64_t combine64(uint64_t x, uint64_t y)\n+{\n+\tuint64_t x1 = ror_inv15(x);\n+\tuint64_t x2 = ror_inv13(x);\n+\tuint64_t y1 = ror_inv3(y);\n+\tuint64_t y2 = ror_inv27(y);\n+\n+\treturn (x ^ y ^\n+\t\t((x1 & y1 & ~x2 & ~y2) | (x1 & ~y1 & x2 & ~y2) |\n+\t\t (x1 & ~y1 & ~x2 & y2) | (~x1 & y1 & x2 & ~y2) |\n+\t\t (~x1 & y1 & ~x2 & y2) | (~x1 & ~y1 & x2 & y2)));\n+}\n+\n+static uint64_t mix64(uint64_t x, uint64_t y)\n+{\n+\treturn shuffle64(combine64(x, y));\n+}\n+\n+static uint32_t calc16(const uint32_t key[16])\n+{\n+\t/* 0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15   Layer 0   */\n+\t/*  \\./     \\./     \\./     \\./     \\./     \\./     \\./     \\./              */\n+\t/*   0       1       2       3       4       5       6       7     Layer 1   */\n+\t/*    \\__.__/         \\__.__/         \\__.__/         \\__.__/                */\n+\t/*       0               1               2               3         Layer 2   */\n+\t/*        \\______.______/                 \\______.______/                    */\n+\t/*               0                               1                 Layer 3   */\n+\t/*                \\______________.______________/                            */\n+\t/*                               0                                 Layer 4   */\n+\t/*                              / \\                                          */\n+\t/*                              \\./                                          */\n+\t/*                               0                                 Layer 5   */\n+\t/*                              / \\                                          */\n+\t/*                              \\./                                Layer 6   */\n+\t/*                             value                                         */\n+\n+\tuint64_t z;\n+\tuint32_t x;\n+\n+\tz = mix64(mix64(mix64(pair(key[0], key[8]), pair(key[1], key[9])),\n+\t\t\tmix64(pair(key[2], key[10]), pair(key[3], key[11]))),\n+\t\t  mix64(mix64(pair(key[4], key[12]), pair(key[5], key[13])),\n+\t\t\tmix64(pair(key[6], key[14]), pair(key[7], key[15]))));\n+\n+\tx = mix((uint32_t)(z >> 32), (uint32_t)z);\n+\tx = mix(x, ror_inv(x, 17));\n+\tx = combine(x, ror_inv(x, 17));\n+\n+\treturn x;\n+}\n+\n+uint32_t gethash(struct hasher_s *hsh, const uint32_t key[16], int *result)\n+{\n+\tuint64_t val;\n+\tuint32_t res;\n+\n+\tval = calc16(key);\n+\tres = (uint32_t)val;\n+\n+\tif (hsh->cam_bw > 32)\n+\t\tval = (val << (hsh->cam_bw - 32)) ^ val;\n+\n+\tfor (int i = 0; i < hsh->banks; i++) {\n+\t\tresult[i] = (unsigned int)(val & hsh->cam_records_bw_mask);\n+\t\tval = val >> hsh->cam_records_bw;\n+\t}\n+\treturn res;\n+}\n+\n+int init_hasher(struct hasher_s *hsh, int banks, int nb_records)\n+{\n+\thsh->banks = banks;\n+\thsh->cam_records_bw = (int)(log2(nb_records - 1) + 1);\n+\thsh->cam_records_bw_mask = (1U << hsh->cam_records_bw) - 1;\n+\thsh->cam_bw = hsh->banks * hsh->cam_records_bw;\n+\n+#ifdef TESTING\n+\tint res = hash_test(hsh, _banks, (int)log2(nb_records - 1) + 1);\n+\n+\tif (res)\n+\t\tprintf(\"ERROR: testing hasher\\n\");\n+#endif\n+\n+\treturn 0;\n+}\n+\n+#ifdef TESTING\n+int hash_test(struct hasher_s *hsh, int banks, int record_bw)\n+{\n+\tint res = 0;\n+\tint val[10], resval[10];\n+\tuint32_t bits = 0;\n+\n+\tuint32_t inval[16] = { 0xaaaabbbb, 0xccccdddd, 0xeeeeffff, 0x88881111 };\n+\tconst uint32_t result = 0xACECAE65;\n+\n+\tfor (int i = 0; i < 16; i++)\n+\t\tprintf(\"%08x,\", inval[i]);\n+\tprintf(\"\\nbanks %i, records bit width: %i\\n\", banks, record_bw);\n+\n+\tuint32_t ret = gethash(hsh, inval, val);\n+\n+\tprintf(\"Return VAL = %08X  ==  %08X\\n\", ret, result);\n+\tres += (ret != result) ? 1 : 0;\n+\n+\tint shft = (banks * record_bw) - 32;\n+\tint mask = (1 << record_bw) - 1;\n+\n+\tif (shft > 0) {\n+\t\tbits = (ret >> (32 - shft));\n+\t\tret ^= ret << shft;\n+\t}\n+\n+\tresval[0] = ret & mask;\n+\tret >>= record_bw;\n+\tresval[1] = ret & mask;\n+\tret >>= record_bw;\n+\tresval[2] = ret & mask;\n+\tresval[2] |= (bits << (record_bw - shft));\n+\n+\tfor (int i = 0; i < 3; i++) {\n+\t\tprintf(\"HASH %i: %i  ==  %i\\n\", i, val[i], resval[i]);\n+\t\tres += (val[i] != resval[i]) ? 1 : 0;\n+\t}\n+\n+\treturn res;\n+}\n+#endif\ndiff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h\nnew file mode 100644\nindex 0000000000..6365a396d2\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h\n@@ -0,0 +1,20 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _FLOW_HASHER_H_\n+#define _FLOW_HASHER_H_\n+\n+#include <stdint.h>\n+\n+struct hasher_s {\n+\tint banks;\n+\tint cam_records_bw;\n+\tuint32_t cam_records_bw_mask;\n+\tint cam_bw;\n+};\n+\n+int init_hasher(struct hasher_s *hsh, int banks, int nb_records);\n+uint32_t gethash(struct hasher_s *hsh, const uint32_t key[16], int *result);\n+\n+#endif /* _FLOW_HASHER_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c\nnew file mode 100644\nindex 0000000000..ddf1742588\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c\n@@ -0,0 +1,434 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <assert.h>\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include \"flow_api_backend.h\"\n+#include \"flow_api_engine.h\"\n+#include \"flow_hasher.h\"\n+\n+/*\n+ * KCC-CAM structures and defines\n+ */\n+struct kcc_cam_distrib_s {\n+\tstruct kcc_flow_def_s *kcc_owner;\n+\tint ref_cnt;\n+};\n+\n+#define BE_CAM_KCC_DIST_IDX(bnk) \\\n+\t({ \\\n+\t\tint _temp_bnk = (bnk); \\\n+\t\t(_temp_bnk * kcc->be->cat.kcc_records + kcc->record_indexes[_temp_bnk]); \\\n+\t})\n+\n+\n+#define BE_CAM_ENTRIES \\\n+\t(kcc->be->cat.kcc_size * sizeof(struct kcc_cam_distrib_s))\n+#define BE_UNIQUE_IDS_SIZE ((1U << kcc->be->cat.kcc_id_bit_size) / 8)\n+\n+#define KCC_CUCKOO_MOVE_MAX_DEPTH 8\n+static int kcc_cam_addr_reserved_stack[KCC_CUCKOO_MOVE_MAX_DEPTH];\n+\n+void kcc_attach_ndev_resource_management(struct kcc_flow_def_s *kcc,\n+\t\tvoid **handle)\n+{\n+\t/*\n+\t *  KCC entries occupied in CAM - to manage the cuckoo shuffling\n+\t *  and manage CAM population and usage\n+\t */\n+\tif (!*handle) {\n+\t\t*handle = calloc(1, BE_CAM_ENTRIES + sizeof(uint32_t) +\n+\t\t\t\t BE_UNIQUE_IDS_SIZE +\n+\t\t\t\t sizeof(struct hasher_s));\n+\t\tNT_LOG(DBG, FILTER,\n+\t\t       \"Allocate NIC DEV KCC-CAM record manager\\n\");\n+\t}\n+\tkcc->cam_dist = (struct kcc_cam_distrib_s *)*handle;\n+\tkcc->cuckoo_moves =\n+\t\t(uint32_t *)((char *)kcc->cam_dist + BE_CAM_ENTRIES);\n+\tkcc->kcc_unique_ids = (uint8_t *)((char *)kcc->cam_dist +\n+\t\t\t\t\t  BE_CAM_ENTRIES + sizeof(uint32_t));\n+\n+\tkcc->hsh = (struct hasher_s *)((char *)kcc->kcc_unique_ids +\n+\t\t\t\t       BE_UNIQUE_IDS_SIZE);\n+\tinit_hasher(kcc->hsh, kcc->be->cat.kcc_banks, kcc->be->cat.kcc_records);\n+}\n+\n+void kcc_free_ndev_resource_management(void **handle)\n+{\n+\tif (*handle) {\n+\t\tfree(*handle);\n+\t\tNT_LOG(DBG, FILTER, \"Free NIC DEV KCC-CAM record manager\\n\");\n+\t}\n+\t*handle = NULL;\n+}\n+\n+/*\n+ * Key for KCC CAM\n+ */\n+int kcc_key_add_no_sideband(struct kcc_flow_def_s *kcc)\n+{\n+\tkcc->key.sb_data = 0xffffffff;\n+\tkcc->key.sb_type = 0;\n+\treturn 0;\n+}\n+\n+int kcc_key_add_vlan(struct kcc_flow_def_s *kcc, uint16_t tpid, uint16_t vid)\n+{\n+\tkcc->key.sb_data = ((uint32_t)tpid << 16) | (vid & 0x0fff);\n+\tkcc->key.sb_type = 1;\n+\treturn 0;\n+}\n+\n+int kcc_key_add_vxlan(struct kcc_flow_def_s *kcc, uint32_t vni)\n+{\n+\tkcc->key.sb_data = (vni & 0x00ffffff) | 0x02000000;\n+\tkcc->key.sb_type = 2;\n+\treturn 0;\n+}\n+\n+int kcc_key_add_port(struct kcc_flow_def_s *kcc, uint16_t port)\n+{\n+\tkcc->key.port = port;\n+\treturn 0;\n+}\n+\n+int kcc_key_add_cat_cfn(struct kcc_flow_def_s *kcc, uint8_t cat_cfn)\n+{\n+\tkcc->key.cat_cfn = cat_cfn;\n+\treturn 0;\n+}\n+\n+uint8_t kcc_key_get_cat_cfn(struct kcc_flow_def_s *kcc)\n+{\n+\treturn kcc->key.cat_cfn;\n+}\n+\n+/*\n+ * other settings for KCC CAM\n+ */\n+int kcc_add_km_category(struct kcc_flow_def_s *kcc, uint32_t category)\n+{\n+\tkcc->km_category = category;\n+\treturn 0;\n+}\n+\n+int kcc_alloc_unique_id(struct kcc_flow_def_s *kcc)\n+{\n+\tuint32_t i, ii;\n+\t/* search a free unique ID in allocation bitmap */\n+\tfor (i = 0; i < BE_UNIQUE_IDS_SIZE; i++)\n+\t\tif (kcc->kcc_unique_ids[i] != 0xff)\n+\t\t\tbreak;\n+\n+\tif (i == BE_UNIQUE_IDS_SIZE)\n+\t\treturn -1;\n+\n+\tfor (ii = 0; ii < 8; ii++) {\n+\t\tif ((kcc->kcc_unique_ids[i] & (uint8_t)(1U << ii)) == 0) {\n+\t\t\tkcc->kcc_unique_ids[i] =\n+\t\t\t\t(uint8_t)(kcc->kcc_unique_ids[i] |\n+\t\t\t\t\t  (uint8_t)(1U << ii));\n+\t\t\tkcc->id = (uint16_t)(i * 8 + ii);\n+\t\t\tNT_LOG(DBG, FILTER, \"Allocate new KCC ID : %i\\n\",\n+\t\t\t       kcc->id);\n+\t\t\treturn (int)kcc->id;\n+\t\t}\n+\t}\n+\treturn -1;\n+}\n+\n+void kcc_free_unique_id(struct kcc_flow_def_s *kcc)\n+{\n+\tif (kcc->id == KCC_ID_INVALID)\n+\t\treturn;\n+\n+\tuint32_t idx = kcc->id >> 3;\n+\tuint8_t shft = (uint8_t)(kcc->id & 7);\n+\n+\tassert(idx < BE_UNIQUE_IDS_SIZE);\n+\tif (idx < BE_UNIQUE_IDS_SIZE) {\n+\t\tassert(kcc->kcc_unique_ids[idx] & (uint8_t)(1 << shft));\n+\t\tkcc->kcc_unique_ids[idx] &= (uint8_t)~(1 << shft);\n+\t\tNT_LOG(DBG, FILTER, \"Free KCC ID : %i\\n\", kcc->id);\n+\t\tkcc->id = KCC_ID_INVALID;\n+\t}\n+}\n+\n+int kcc_key_compare(struct kcc_flow_def_s *kcc, struct kcc_flow_def_s *kcc1)\n+{\n+\tif (kcc->key64 == kcc1->key64)\n+\t\treturn 1;\n+\treturn 0;\n+}\n+\n+static int kcc_cam_populate(struct kcc_flow_def_s *kcc, int bank)\n+{\n+\tint res;\n+\tint idx = bank * kcc->be->cat.kcc_records + kcc->record_indexes[bank];\n+\n+\tres = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 0,\n+\t\t\t\t kcc->key32[0]);\n+\tif (res)\n+\t\treturn -1;\n+\tres = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 1,\n+\t\t\t\t kcc->key32[1]);\n+\tif (res)\n+\t\treturn -1;\n+\tres = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_CATEGORY, idx, 0,\n+\t\t\t\t kcc->km_category);\n+\tif (res)\n+\t\treturn -1;\n+\tres = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_ID, idx, 0, kcc->id);\n+\tif (res)\n+\t\treturn -1;\n+\tres = hw_mod_cat_kcc_flush(kcc->be, idx, 1);\n+\n+\tkcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].kcc_owner = kcc;\n+\tkcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].ref_cnt = 1;\n+\treturn res;\n+}\n+\n+static int kcc_cam_reset_entry(struct kcc_flow_def_s *kcc, int bank)\n+{\n+\tint res = 0;\n+\tint idx = bank * kcc->be->cat.kcc_records + kcc->record_indexes[bank];\n+\n+\tres = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 0, 0);\n+\tif (res)\n+\t\treturn -1;\n+\tres = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 1, 0);\n+\tif (res)\n+\t\treturn -1;\n+\tres = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_CATEGORY, idx, 0, 0);\n+\tif (res)\n+\t\treturn -1;\n+\tres = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_ID, idx, 0, 0);\n+\tif (res)\n+\t\treturn -1;\n+\tres = hw_mod_cat_kcc_flush(kcc->be, idx, 1);\n+\n+\tkcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].kcc_owner = NULL;\n+\tkcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].ref_cnt = 0;\n+\n+\tkcc->key64 = 0UL;\n+\tkcc->km_category = 0;\n+\t/* \"kcc->id\" holds an allocated unique id, so cleared/freed later */\n+\treturn res;\n+}\n+\n+static int kcc_move_cuckoo_index(struct kcc_flow_def_s *kcc)\n+{\n+\tassert(kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)].kcc_owner);\n+\n+\tfor (uint32_t bank = 0; bank < kcc->be->cat.kcc_banks; bank++) {\n+\t\t/* It will not select itself */\n+\t\tif (kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].kcc_owner ==\n+\t\t\t\tNULL) {\n+\t\t\t/*\n+\t\t\t * Populate in new position\n+\t\t\t */\n+\t\t\tint res = kcc_cam_populate(kcc, bank);\n+\n+\t\t\tif (res) {\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"Error: failed to write to KM CAM in cuckoo move\\n\");\n+\t\t\t\treturn 0;\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * Reset/free entry in old bank\n+\t\t\t * HW flushes are really not needed, the old addresses are always taken over\n+\t\t\t * by the caller If you change this code in future updates, this may no\n+\t\t\t * longer be true then!\n+\t\t\t */\n+\t\t\tkcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)]\n+\t\t\t.kcc_owner = NULL;\n+\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t       \"KCC Cuckoo hash moved from bank %i to bank %i (%04X => %04X)\\n\",\n+\t\t\t       kcc->bank_used, bank,\n+\t\t\t       BE_CAM_KCC_DIST_IDX(kcc->bank_used),\n+\t\t\t       BE_CAM_KCC_DIST_IDX(bank));\n+\n+\t\t\tkcc->bank_used = bank;\n+\t\t\t(*kcc->cuckoo_moves)++;\n+\t\t\treturn 1;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int kcc_move_cuckoo_index_level(struct kcc_flow_def_s *kcc_parent,\n+\t\t\t\t       int bank_idx, int levels,\n+\t\t\t\t       int cam_adr_list_len)\n+{\n+\tstruct kcc_flow_def_s *kcc = kcc_parent->cam_dist[bank_idx].kcc_owner;\n+\n+\tassert(levels <= KCC_CUCKOO_MOVE_MAX_DEPTH);\n+\n+\tif (kcc_move_cuckoo_index(kcc))\n+\t\treturn 1;\n+\tif (levels <= 1)\n+\t\treturn 0;\n+\n+\tassert(cam_adr_list_len < KCC_CUCKOO_MOVE_MAX_DEPTH);\n+\n+\tkcc_cam_addr_reserved_stack[cam_adr_list_len++] = bank_idx;\n+\n+\tfor (uint32_t i = 0; i < kcc->be->cat.kcc_banks; i++) {\n+\t\tint reserved = 0;\n+\t\tint new_idx = BE_CAM_KCC_DIST_IDX(i);\n+\n+\t\tfor (int i_reserved = 0; i_reserved < cam_adr_list_len;\n+\t\t\t\ti_reserved++) {\n+\t\t\tif (kcc_cam_addr_reserved_stack[i_reserved] ==\n+\t\t\t\t\tnew_idx) {\n+\t\t\t\treserved = 1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tif (reserved)\n+\t\t\tcontinue;\n+\n+\t\tint res = kcc_move_cuckoo_index_level(kcc, new_idx, levels - 1,\n+\t\t\t\t\t\t      cam_adr_list_len);\n+\t\tif (res) {\n+\t\t\tif (kcc_move_cuckoo_index(kcc))\n+\t\t\t\treturn 1;\n+\n+\t\t\telse\n+\t\t\t\tassert(0);\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static uint32_t kcc_hsh_key[16];\n+\n+static int kcc_write_data_to_cam(struct kcc_flow_def_s *kcc)\n+{\n+\tint res = 0;\n+\tint val[MAX_BANKS];\n+\n+\tkcc_hsh_key[0] = kcc->key32[1];\n+\tkcc_hsh_key[1] = kcc->key32[0];\n+\tNT_LOG(DBG, FILTER, \"TEMP TEMP TEMP\");\n+\tNT_LOG(DBG, FILTER, \"Hash key[0] %08x\", kcc_hsh_key[0]);\n+\tNT_LOG(DBG, FILTER, \"Hash key[1] %08x\", kcc_hsh_key[1]);\n+\tNT_LOG(DBG, FILTER, \"TEMP TEMP TEMP - swapped\");\n+\n+\t/* 2-15 never changed - remains zero */\n+\n+\tgethash(kcc->hsh, kcc_hsh_key, val);\n+\n+\tfor (uint32_t i = 0; i < kcc->be->cat.kcc_banks; i++)\n+\t\tkcc->record_indexes[i] = val[i];\n+\tNT_LOG(DBG, FILTER, \"KCC HASH [%03X, %03X, %03X]\\n\",\n+\t       kcc->record_indexes[0], kcc->record_indexes[1],\n+\t       kcc->record_indexes[2]);\n+\n+\tint bank = -1;\n+\t/*\n+\t * first step, see if any of the banks are free\n+\t */\n+\tfor (uint32_t i_bank = 0; i_bank < kcc->be->cat.kcc_banks; i_bank++) {\n+\t\tif (kcc->cam_dist[BE_CAM_KCC_DIST_IDX(i_bank)].kcc_owner ==\n+\t\t\t\tNULL) {\n+\t\t\tbank = i_bank;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (bank < 0) {\n+\t\t/*\n+\t\t * Second step - cuckoo move existing flows if possible\n+\t\t */\n+\t\tfor (uint32_t i_bank = 0; i_bank < kcc->be->cat.kcc_banks;\n+\t\t\t\ti_bank++) {\n+\t\t\tif (kcc_move_cuckoo_index_level(kcc,\n+\t\t\t\t\t\t\tBE_CAM_KCC_DIST_IDX(i_bank),\n+\t\t\t\t\t\t\t4, 0)) {\n+\t\t\t\tbank = i_bank;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (bank < 0)\n+\t\t\treturn -1;\n+\t}\n+\n+\t/* populate CAM */\n+\tNT_LOG(DBG, FILTER, \"KCC Bank = %i (addr %04X)\\n\", bank,\n+\t       BE_CAM_KCC_DIST_IDX(bank));\n+\tres = kcc_cam_populate(kcc, bank);\n+\tif (res == 0) {\n+\t\tkcc->flushed_to_target = 1;\n+\t\tkcc->bank_used = bank;\n+\t} else {\n+\t\tNT_LOG(DBG, FILTER, \"KCC CAM populate failed\\n\");\n+\t}\n+\treturn res;\n+}\n+\n+int kcc_write_data_match_entry(struct kcc_flow_def_s *kcc)\n+{\n+\tint res = -1;\n+\n+\tNT_LOG(DBG, FILTER,\n+\t       \"KCC Write Data entry. Create New Key: %016lx, KM category %i, id %i\\n\",\n+\t       kcc->key64, kcc->km_category, kcc->id);\n+\tres = kcc_write_data_to_cam(kcc);\n+\treturn res;\n+}\n+\n+static int kcc_clear_data_match_entry(struct kcc_flow_def_s *kcc)\n+{\n+\tint res = 0;\n+\n+\tif (kcc->flushed_to_target) {\n+\t\tres = kcc_cam_reset_entry(kcc, kcc->bank_used);\n+\t\tkcc->flushed_to_target = 0;\n+\t\tkcc->bank_used = 0;\n+\t}\n+\treturn res;\n+}\n+\n+int kcc_key_ref_count_add(struct kcc_flow_def_s *kcc)\n+{\n+\tassert(kcc->bank_used >= 0 &&\n+\t       kcc->bank_used < (int)kcc->be->cat.kcc_banks);\n+\n+\tstruct kcc_cam_distrib_s *cam_entry =\n+\t\t&kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)];\n+\n+\tNT_LOG(DBG, FILTER,\n+\t       \"KCC ADD Ref existing Key: %016lx, KM category %i, id %i (new ref count %i)\\n\",\n+\t       kcc->key64, kcc->km_category, kcc->id, cam_entry->ref_cnt + 1);\n+\treturn ++cam_entry->ref_cnt;\n+}\n+\n+int kcc_key_ref_count_dec(struct kcc_flow_def_s *kcc)\n+{\n+\tif (kcc->bank_used < 0 || kcc->bank_used >= (int)kcc->be->cat.kcc_banks)\n+\t\treturn -1;\n+\n+\tstruct kcc_cam_distrib_s *cam_entry =\n+\t\t&kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)];\n+\n+\tif (cam_entry->ref_cnt) {\n+\t\tif (--cam_entry->ref_cnt == 0) {\n+\t\t\tkcc_clear_data_match_entry(kcc);\n+\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t       \"KCC DEC Ref on Key became zero - Delete\\n\");\n+\t\t}\n+\t}\n+\n+\tNT_LOG(DBG, FILTER,\n+\t       \"KCC DEC Ref on Key: %016lx, KM category %i, id %i (new ref count %i)\\n\",\n+\t       kcc->key64, kcc->km_category, kcc->id, cam_entry->ref_cnt);\n+\treturn cam_entry->ref_cnt;\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c\nnew file mode 100644\nindex 0000000000..560be9f7d3\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c\n@@ -0,0 +1,1434 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <assert.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+\n+#include \"flow_api_backend.h\"\n+#include \"flow_api_engine.h\"\n+#include \"flow_hasher.h\"\n+\n+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))\n+\n+static const struct cam_match_masks_s {\n+\tuint32_t word_len;\n+\tuint32_t key_mask[4];\n+} cam_masks[] = {\n+\t{\t4,\n+\t\t{\t0xffffffff, 0xffffffff, 0xffffffff,\n+\t\t\t0xffffffff\n+\t\t}\n+\t}, /* IP6_SRC, IP6_DST */\n+\t{\t4,\n+\t\t{\t0xffffffff, 0xffffffff, 0xffffffff,\n+\t\t\t0xffff0000\n+\t\t}\n+\t}, /* DMAC,SMAC,ethtype */\n+\t{\t4,\n+\t\t{\t0xffffffff, 0xffff0000, 0x00000000,\n+\t\t\t0xffff0000\n+\t\t}\n+\t}, /* DMAC,ethtype */\n+\t{\t4,\n+\t\t{\t0x00000000, 0x0000ffff, 0xffffffff,\n+\t\t\t0xffff0000\n+\t\t}\n+\t}, /* SMAC,ethtype */\n+\t{ 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000 } }, /* ETH_128 */\n+\t{\t2,\n+\t\t{\t0xffffffff, 0xffffffff, 0x00000000,\n+\t\t\t0x00000000\n+\t\t}\n+\t}, /* IP4_COMBINED */\n+\t{ 1, { 0xffffffff, 0x00000000, 0x00000000, 0x00000000 } },\n+\t\t/*\n+\t\t * ETH_TYPE, IP4_TTL_PROTO, IP4_SRC, IP4_DST, IP6_FLOW_TC,\n+\t\t * IP6_NEXT_HDR_HOP, TP_PORT_COMBINED, SIDEBAND_VNI\n+\t\t */\n+\t{\t1,\n+\t\t{\t0xffff0000, 0x00000000, 0x00000000,\n+\t\t\t0x00000000\n+\t\t}\n+\t}, /* IP4_IHL_TOS, TP_PORT_SRC32_OR_ICMP, TCP_CTRL */\n+\t{\t1,\n+\t\t{\t0x0000ffff, 0x00000000, 0x00000000,\n+\t\t\t0x00000000\n+\t\t}\n+\t}, /* TP_PORT_DST32 */\n+\t{\t1,\n+\t\t{\t0x00030000, 0x00000000, 0x00000000,\n+\t\t\t0x00000000\n+\t\t}\n+\t}, /* IPv4 TOS mask bits used often by OVS */\n+\t{\t1,\n+\t\t{\t0x00300000, 0x00000000, 0x00000000,\n+\t\t\t0x00000000\n+\t\t}\n+\t}, /* IPv6 TOS mask bits used often by OVS */\n+};\n+\n+#define NUM_CAM_MASKS (ARRAY_SIZE(cam_masks))\n+\n+/*\n+ * CAM structures and defines\n+ */\n+struct cam_distrib_s {\n+\tstruct km_flow_def_s *km_owner;\n+};\n+\n+#define CAM_DIST_IDX(bnk, rec) ((bnk) * km->be->km.nb_cam_records + (rec))\n+#define CAM_KM_DIST_IDX(bnk) \\\n+\t({ \\\n+\t\tint _temp_bnk = (bnk); \\\n+\t\tCAM_DIST_IDX(_temp_bnk, km->record_indexes[_temp_bnk]); \\\n+\t})\n+\n+#define CUCKOO_MOVE_MAX_DEPTH 8\n+static int cam_addr_reserved_stack[CUCKOO_MOVE_MAX_DEPTH];\n+\n+/*\n+ * TCAM structures and defines\n+ */\n+struct tcam_distrib_s {\n+\tstruct km_flow_def_s *km_owner;\n+};\n+\n+#define TCAM_DIST_IDX(bnk, rec) ((bnk) * km->be->km.nb_tcam_bank_width + (rec))\n+\n+static int tcam_find_mapping(struct km_flow_def_s *km);\n+\n+void km_attach_ndev_resource_management(struct km_flow_def_s *km, void **handle)\n+{\n+#define CAM_ENTRIES                                            \\\n+\t(km->be->km.nb_cam_banks * km->be->km.nb_cam_records * \\\n+\t sizeof(struct cam_distrib_s))\n+#define TCAM_ENTRIES                                                \\\n+\t(km->be->km.nb_tcam_bank_width * km->be->km.nb_tcam_banks * \\\n+\t sizeof(struct tcam_distrib_s))\n+\t/*\n+\t *  KM entries occupied in CAM - to manage the cuckoo shuffling\n+\t *  and manage CAM population and usage\n+\t *  KM entries occupied in TCAM - to manage population and usage\n+\t */\n+\tif (!*handle) {\n+\t\t*handle = calloc(1, (size_t)CAM_ENTRIES + sizeof(uint32_t) +\n+\t\t\t\t (size_t)TCAM_ENTRIES +\n+\t\t\t\t sizeof(struct hasher_s));\n+\t\tNT_LOG(DBG, FILTER,\n+\t\t       \"Allocate NIC DEV CAM and TCAM record manager\\n\");\n+\t}\n+\tkm->cam_dist = (struct cam_distrib_s *)*handle;\n+\tkm->cuckoo_moves = (uint32_t *)((char *)km->cam_dist + CAM_ENTRIES);\n+\tkm->tcam_dist =\n+\t\t(struct tcam_distrib_s *)((char *)km->cam_dist + CAM_ENTRIES +\n+\t\t\t\t\t  sizeof(uint32_t));\n+\n+\tkm->hsh = (struct hasher_s *)((char *)km->tcam_dist + TCAM_ENTRIES);\n+\tinit_hasher(km->hsh, km->be->km.nb_cam_banks,\n+\t\t    km->be->km.nb_cam_records);\n+}\n+\n+void km_free_ndev_resource_management(void **handle)\n+{\n+\tif (*handle) {\n+\t\tfree(*handle);\n+\t\tNT_LOG(DBG, FILTER,\n+\t\t       \"Free NIC DEV CAM and TCAM record manager\\n\");\n+\t}\n+\t*handle = NULL;\n+}\n+\n+int km_add_match_elem(struct km_flow_def_s *km, uint32_t e_word[4],\n+\t\t      uint32_t e_mask[4], uint32_t word_len,\n+\t\t      enum frame_offs_e start_id, int8_t offset)\n+{\n+#ifdef FLOW_DEBUG\n+\tchar *s = ntlog_helper_str_alloc(\"MATCH: \");\n+\n+\tfor (unsigned int i = 0; i < word_len; i++)\n+\t\tntlog_helper_str_add(s, \"%08x, \", e_word[i]);\n+\tNT_LOG(DBG, FILTER, \"%s\", s);\n+\tntlog_helper_str_reset(s, \"MASK : \");\n+\tfor (unsigned int i = 0; i < word_len; i++)\n+\t\tntlog_helper_str_add(s, \"%08x, \", e_mask[i]);\n+\tNT_LOG(DBG, FILTER, \"%s\", s);\n+\tntlog_helper_str_free(s);\n+#endif\n+\n+\t/* valid word_len 1,2,4 */\n+\tif (word_len == 3) {\n+\t\tword_len = 4;\n+\t\te_word[3] = 0;\n+\t\te_mask[3] = 0;\n+\t}\n+\tif (word_len < 1 || word_len > 4) {\n+\t\tassert(0);\n+\t\treturn -1;\n+\t}\n+\n+\tfor (unsigned int i = 0; i < word_len; i++) {\n+\t\tkm->match[km->num_ftype_elem].e_word[i] = e_word[i];\n+\t\tkm->match[km->num_ftype_elem].e_mask[i] = e_mask[i];\n+\t}\n+\n+\tkm->match[km->num_ftype_elem].word_len = word_len;\n+\tkm->match[km->num_ftype_elem].rel_offs = offset;\n+\tkm->match[km->num_ftype_elem].extr_start_offs_id = start_id;\n+\n+\t/*\n+\t * Determine here if this flow may better be put into TCAM\n+\t * Otherwise it will go into CAM\n+\t * This is dependent on a cam_masks list defined above\n+\t */\n+\tkm->match[km->num_ftype_elem].masked_for_tcam = 1;\n+\tfor (unsigned int msk = 0; msk < NUM_CAM_MASKS; msk++) {\n+\t\tif (word_len == cam_masks[msk].word_len) {\n+\t\t\tint match = 1;\n+\n+\t\t\tfor (unsigned int wd = 0; wd < word_len; wd++) {\n+\t\t\t\tif (e_mask[wd] != cam_masks[msk].key_mask[wd]) {\n+\t\t\t\t\tmatch = 0;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tif (match) {\n+\t\t\t\t/* Can go into CAM */\n+\t\t\t\tkm->match[km->num_ftype_elem].masked_for_tcam =\n+\t\t\t\t\t0;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tkm->num_ftype_elem++;\n+\treturn 0;\n+}\n+\n+void km_set_info(struct km_flow_def_s *km, int on)\n+{\n+\tkm->info_set = !!on;\n+}\n+\n+static int get_word(struct km_flow_def_s *km, uint32_t size, int marked[])\n+{\n+\tfor (int i = 0; i < km->num_ftype_elem; i++) {\n+\t\tif (!marked[i] &&\n+\t\t\t\t!(km->match[i].extr_start_offs_id & SWX_INFO) &&\n+\t\t\t\tkm->match[i].word_len == size)\n+\t\t\treturn i;\n+\t}\n+\treturn -1;\n+}\n+\n+#ifdef FLOW_DEBUG\n+static const char *get_prot_offset_descr(int idx)\n+{\n+\tswitch (idx) {\n+\tcase DYN_SOF:\n+\t\treturn \"SOF\";\n+\tcase DYN_L2:\n+\t\treturn \"L2 header\";\n+\tcase DYN_FIRST_VLAN:\n+\t\treturn \"First VLAN\";\n+\tcase DYN_MPLS:\n+\t\treturn \"First MPLS\";\n+\tcase DYN_L3:\n+\t\treturn \"L3 header\";\n+\tcase DYN_ID_IPV4_6:\n+\t\treturn \"ID field IPv4/6\";\n+\tcase DYN_FINAL_IP_DST:\n+\t\treturn \"Final IP dest\";\n+\tcase DYN_L4:\n+\t\treturn \"L4 header\";\n+\tcase DYN_L4_PAYLOAD:\n+\t\treturn \"L4 payload\";\n+\tcase DYN_TUN_PAYLOAD:\n+\t\treturn \"Tunnel payload\";\n+\tcase DYN_TUN_L2:\n+\t\treturn \"Tunnel L2 header\";\n+\tcase DYN_TUN_VLAN:\n+\t\treturn \"First tunneled VLAN\";\n+\tcase DYN_TUN_MPLS:\n+\t\treturn \"First tunneled MPLS\";\n+\tcase DYN_TUN_L3:\n+\t\treturn \"Tunnel L3 header\";\n+\tcase DYN_TUN_ID_IPV4_6:\n+\t\treturn \"Tunnel ID field IPv4/6\";\n+\tcase DYN_TUN_FINAL_IP_DST:\n+\t\treturn \"Tunnel final IP dest\";\n+\tcase DYN_TUN_L4:\n+\t\treturn \"Tunnel L4 header\";\n+\tcase DYN_TUN_L4_PAYLOAD:\n+\t\treturn \"Tunnel L4 payload\";\n+\tcase SB_VNI:\n+\t\treturn \"VNI\";\n+\tcase SB_MAC_PORT:\n+\t\treturn \"In Port\";\n+\tcase SB_KCC_ID:\n+\t\treturn \"KCC ID\";\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\treturn \"<unknown>\";\n+}\n+#endif\n+\n+#define MAX_QWORDS 2\n+#define MAX_SWORDS 2\n+\n+int km_key_create(struct km_flow_def_s *km, uint32_t port_id)\n+{\n+\t/*\n+\t * Create combined extractor mappings\n+\t *  if key fields may be changed to cover un-mappable otherwise?\n+\t *  split into cam and tcam and use synergy mode when available\n+\t *\n+\t */\n+\tint match_marked[MAX_MATCH_FIELDS];\n+\tint idx = 0;\n+\tint next = 0;\n+\tint m_idx;\n+\tint size;\n+\n+\tmemset(match_marked, 0, sizeof(match_marked));\n+\n+\t/* build QWords */\n+\tfor (int qwords = 0; qwords < MAX_QWORDS; qwords++) {\n+\t\tsize = 4;\n+\t\tm_idx = get_word(km, size, match_marked);\n+\t\tif (m_idx < 0) {\n+\t\t\tsize = 2;\n+\t\t\tm_idx = get_word(km, size, match_marked);\n+\n+\t\t\tif (m_idx < 0) {\n+\t\t\t\tsize = 1;\n+\t\t\t\tm_idx = get_word(km, 1, match_marked);\n+\t\t\t}\n+\t\t}\n+\t\tif (m_idx < 0) {\n+\t\t\t/* no more defined */\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tmatch_marked[m_idx] = 1;\n+\n+\t\t/* build match map list and set final extractor to use */\n+\t\tkm->match_map[next] = &km->match[m_idx];\n+\t\tkm->match[m_idx].extr = KM_USE_EXTRACTOR_QWORD;\n+\n+\t\t/* build final entry words and mask array */\n+\t\tfor (int i = 0; i < size; i++) {\n+\t\t\tkm->entry_word[idx + i] = km->match[m_idx].e_word[i];\n+\t\t\tkm->entry_mask[idx + i] = km->match[m_idx].e_mask[i];\n+\t\t}\n+\n+\t\tidx += size;\n+\t\tnext++;\n+\t}\n+\n+\tm_idx = get_word(km, 4, match_marked);\n+\tif (m_idx >= 0) {\n+\t\t/* cannot match more QWords */\n+\t\treturn -1;\n+\t}\n+\n+\t/*\n+\t *  On km v6+ we have DWORDs here instead. However, we only use them as SWORDs for now\n+\t *  No match would be able to exploit these as DWORDs because of maximum length of 12 words\n+\t *  in CAM\n+\t *  The last 2 words are taken by KCC-ID/SWX and Color. You could have one or none QWORDs\n+\t *  where then both these DWORDs were possible in 10 words, but we don't have such use case\n+\t *  built in yet\n+\t */\n+\t/* build SWords */\n+\tfor (int swords = 0; swords < MAX_SWORDS; swords++) {\n+\t\tm_idx = get_word(km, 1, match_marked);\n+\t\tif (m_idx < 0) {\n+\t\t\t/* no more defined */\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tmatch_marked[m_idx] = 1;\n+\t\t/* build match map list and set final extractor to use */\n+\t\tkm->match_map[next] = &km->match[m_idx];\n+\t\tkm->match[m_idx].extr = KM_USE_EXTRACTOR_SWORD;\n+\n+\t\t/* build final entry words and mask array */\n+\t\tkm->entry_word[idx] = km->match[m_idx].e_word[0];\n+\t\tkm->entry_mask[idx] = km->match[m_idx].e_mask[0];\n+\t\tidx++;\n+\t\tnext++;\n+\t}\n+\n+\t/*\n+\t * Make sure we took them all\n+\t */\n+\tm_idx = get_word(km, 1, match_marked);\n+\tif (m_idx >= 0) {\n+\t\t/* cannot match more SWords */\n+\t\treturn -1;\n+\t}\n+\n+\t/*\n+\t * Handle SWX words specially\n+\t */\n+\tint swx_found = 0;\n+\n+\tfor (int i = 0; i < km->num_ftype_elem; i++) {\n+\t\tif (km->match[i].extr_start_offs_id & SWX_INFO) {\n+\t\t\tkm->match_map[next] = &km->match[i];\n+\t\t\tkm->match[i].extr = KM_USE_EXTRACTOR_SWORD;\n+\t\t\t/* build final entry words and mask array */\n+\t\t\tkm->entry_word[idx] = km->match[i].e_word[0];\n+\t\t\tkm->entry_mask[idx] = km->match[i].e_mask[0];\n+\t\t\tidx++;\n+\t\t\tnext++;\n+\t\t\tswx_found = 1;\n+\t\t}\n+\t}\n+\n+\tassert(next == km->num_ftype_elem);\n+\n+\tkm->key_word_size = idx;\n+\tkm->port_id = port_id;\n+\n+\tkm->target = KM_CAM;\n+\t/*\n+\t * Finally decide if we want to put this match->action into the TCAM\n+\t * When SWX word used we need to put it into CAM always, no matter what mask pattern\n+\t * Later, when synergy mode is applied, we can do a split\n+\t */\n+\tif (!swx_found && km->key_word_size <= 6) {\n+\t\tfor (int i = 0; i < km->num_ftype_elem; i++) {\n+\t\t\tif (km->match_map[i]->masked_for_tcam) {\n+\t\t\t\t/* At least one */\n+\t\t\t\tkm->target = KM_TCAM;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tNT_LOG(DBG, FILTER, \"This flow goes into %s\\n\",\n+\t       (km->target == KM_TCAM) ? \"TCAM\" : \"CAM\");\n+\n+\tif (km->target == KM_TCAM) {\n+\t\tif (km->key_word_size > 10) {\n+\t\t\t/* do not support SWX in TCAM */\n+\t\t\treturn -1;\n+\t\t}\n+\t\t/*\n+\t\t * adjust for unsupported key word size in TCAM\n+\t\t */\n+\t\tif ((km->key_word_size == 5 || km->key_word_size == 7 ||\n+\t\t\t\tkm->key_word_size == 9)) {\n+\t\t\tkm->entry_mask[km->key_word_size] = 0;\n+\t\t\tkm->key_word_size++;\n+\t\t}\n+\n+\t\t/*\n+\t\t * 1. the fact that the length of a key cannot change among the same used banks\n+\t\t *\n+\t\t *  calculate possible start indexes\n+\t\t *  unfortunately restrictions in TCAM lookup\n+\t\t *  makes it hard to handle key lengths larger than 6\n+\t\t *  when other sizes should be possible too\n+\t\t */\n+\t\tswitch (km->key_word_size) {\n+\t\tcase 1:\n+\t\t\tfor (int i = 0; i < 4; i++)\n+\t\t\t\tkm->start_offsets[0] = 8 + i;\n+\t\t\tkm->num_start_offsets = 4;\n+\t\t\tbreak;\n+\t\tcase 2:\n+\t\t\tkm->start_offsets[0] = 6;\n+\t\t\tkm->num_start_offsets = 1;\n+\t\t\tbreak;\n+\t\tcase 3:\n+\t\t\tkm->start_offsets[0] = 0;\n+\t\t\tkm->num_start_offsets = 1;\n+\t\t\t/* enlarge to 6 */\n+\t\t\tkm->entry_mask[km->key_word_size++] = 0;\n+\t\t\tkm->entry_mask[km->key_word_size++] = 0;\n+\t\t\tkm->entry_mask[km->key_word_size++] = 0;\n+\t\t\tbreak;\n+\t\tcase 4:\n+\t\t\tkm->start_offsets[0] = 0;\n+\t\t\tkm->num_start_offsets = 1;\n+\t\t\t/* enlarge to 6 */\n+\t\t\tkm->entry_mask[km->key_word_size++] = 0;\n+\t\t\tkm->entry_mask[km->key_word_size++] = 0;\n+\t\t\tbreak;\n+\t\tcase 6:\n+\t\t\tkm->start_offsets[0] = 0;\n+\t\t\tkm->num_start_offsets = 1;\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t       \"Final Key word size too large: %i\\n\",\n+\t\t\t       km->key_word_size);\n+\t\t\treturn -1;\n+\t\t}\n+\n+#ifdef FLOW_DEBUG\n+\t\tchar *s = ntlog_helper_str_alloc(\"TCAM offs: \");\n+\n+\t\tfor (int i = 0; i < km->num_start_offsets; i++)\n+\t\t\tntlog_helper_str_add(s, \"%i,\", km->start_offsets[i]);\n+\t\tNT_LOG(DBG, FILTER, \"%s\", s);\n+\t\tntlog_helper_str_free(s);\n+#endif\n+\t}\n+\n+#ifdef FLOW_DEBUG\n+\tfor (int i = 0; i < km->num_ftype_elem; i++) {\n+\t\tNT_LOG(DBG, FILTER,\n+\t\t       \"size %i -> Extr: %s, offset id: %s, rel offset: %i\\n\",\n+\t\t       km->match_map[i]->word_len,\n+\t\t       (km->match_map[i]->extr_start_offs_id & SWX_INFO) ?\n+\t\t       \"SIDEBAND\" :\n+\t\t       km->match_map[i]->extr == KM_USE_EXTRACTOR_SWORD ?\n+\t\t       \"SWORD\" :\n+\t\t       \"QWORD\",\n+\t\t       get_prot_offset_descr(km->match_map[i]->extr_start_offs_id),\n+\t\t       km->match_map[i]->rel_offs);\n+\t}\n+\tchar *s = ntlog_helper_str_alloc(\"\");\n+\n+\tfor (int i = 0; i < km->key_word_size; i++)\n+\t\tntlog_helper_str_add(s, \"%08x,\", km->entry_word[i]);\n+\n+\tNT_LOG(DBG, FILTER, \"%s\", s);\n+\n+\tntlog_helper_str_reset(s, \"\");\n+\tfor (int i = 0; i < km->key_word_size; i++)\n+\t\tntlog_helper_str_add(s, \"%08x,\", km->entry_mask[i]);\n+\n+\tNT_LOG(DBG, FILTER, \"%s\", s);\n+\tntlog_helper_str_free(s);\n+#endif\n+\n+\treturn 0;\n+}\n+\n+int km_key_compare(struct km_flow_def_s *km, struct km_flow_def_s *km1)\n+{\n+\tif (km->target != km1->target ||\n+\t\t\tkm->num_ftype_elem != km1->num_ftype_elem ||\n+\t\t\tkm->key_word_size != km1->key_word_size ||\n+\t\t\tkm->info_set != km1->info_set)\n+\t\treturn 0;\n+\n+\t/*\n+\t *  before KCC-CAM:\n+\t *  if port is added to match, then we can have different ports in CAT\n+\t *  that reuses this flow type\n+\t */\n+\tint port_match_included = 0, kcc_swx_used = 0;\n+\n+\tfor (int i = 0; i < km->num_ftype_elem; i++) {\n+\t\tif (km->match[i].extr_start_offs_id == SB_MAC_PORT) {\n+\t\t\tport_match_included = 1;\n+\t\t\tbreak;\n+\t\t} else if (km->match_map[i]->extr_start_offs_id == SB_KCC_ID) {\n+\t\t\tkcc_swx_used = 1;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * If not using KCC and if port match is not included in CAM,\n+\t * we need to have same port_id to reuse\n+\t */\n+\tif (!kcc_swx_used && !port_match_included &&\n+\t\t\tkm->port_id != km1->port_id)\n+\t\treturn 0;\n+\n+\tfor (int i = 0; i < km->num_ftype_elem; i++) {\n+\t\t/* using same extractor types in same sequence */\n+\t\tif (km->match_map[i]->extr_start_offs_id != km1->match_map[i]->extr_start_offs_id ||\n+\t\t\t\tkm->match_map[i]->rel_offs != km1->match_map[i]->rel_offs ||\n+\t\t\t\tkm->match_map[i]->extr != km1->match_map[i]->extr ||\n+\t\t\t\tkm->match_map[i]->word_len != km1->match_map[i]->word_len)\n+\t\t\treturn 0;\n+\t}\n+\n+\tif (km->target == KM_CAM) {\n+\t\t/* in CAM must exactly match on all masks */\n+\t\tfor (int i = 0; i < km->key_word_size; i++) {\n+\t\t\tif (km->entry_mask[i] != km1->entry_mask[i])\n+\t\t\t\treturn 0;\n+\t\t}\n+\n+\t\t/* Would be set later if not reusing from km1 */\n+\t\tkm->cam_paired = km1->cam_paired;\n+\t} else if (km->target == KM_TCAM) {\n+\t\t/*\n+\t\t *  If TCAM, we must make sure Recipe Key Mask does not\n+\t\t *  mask out enable bits in masks\n+\t\t *  Note: it is important that km1 is the original creator\n+\t\t *  of the KM Recipe, since it contains its true masks\n+\t\t */\n+\t\tfor (int i = 0; i < km->key_word_size; i++) {\n+\t\t\tif ((km->entry_mask[i] & km1->entry_mask[i]) !=\n+\t\t\t\t\tkm->entry_mask[i])\n+\t\t\t\treturn 0;\n+\t\t}\n+\n+\t\tkm->tcam_start_bank = km1->tcam_start_bank;\n+\t\tkm->tcam_record = -1; /* needs to be found later */\n+\t} else {\n+\t\tNT_LOG(DBG, FILTER,\n+\t\t       \"ERROR - KM target not defined or supported\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\t/*\n+\t * Check for a flow clash. If already programmed return with -1\n+\t */\n+\tint double_match = 1;\n+\n+\tfor (int i = 0; i < km->key_word_size; i++) {\n+\t\tif ((km->entry_word[i] & km->entry_mask[i]) !=\n+\t\t\t\t(km1->entry_word[i] & km1->entry_mask[i])) {\n+\t\t\tdouble_match = 0;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (double_match)\n+\t\treturn -1;\n+\n+\t/*\n+\t * Note that TCAM and CAM may reuse same RCP and flow type\n+\t * when this happens, CAM entry wins on overlap\n+\t */\n+\n+\t/* Use same KM Recipe and same flow type - return flow type */\n+\treturn km1->flow_type;\n+}\n+\n+int km_rcp_set(struct km_flow_def_s *km, int index)\n+{\n+\tint qw = 0;\n+\tint sw = 0;\n+\tint swx = 0;\n+\n+\thw_mod_km_rcp_set(km->be, HW_KM_RCP_PRESET_ALL, index, 0, 0);\n+\n+\t/* set extractor words, offs, contrib */\n+\tfor (int i = 0; i < km->num_ftype_elem; i++) {\n+\t\tswitch (km->match_map[i]->extr) {\n+\t\tcase KM_USE_EXTRACTOR_SWORD:\n+\t\t\tif (km->match_map[i]->extr_start_offs_id & SWX_INFO) {\n+\t\t\t\tif (km->target == KM_CAM && swx == 0) {\n+\t\t\t\t\t/* SWX */\n+\t\t\t\t\tif (km->match_map[i]\n+\t\t\t\t\t\t\t->extr_start_offs_id ==\n+\t\t\t\t\t\t\tSB_VNI) {\n+\t\t\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t\t\t       \"Set KM SWX sel A - VNI\\n\");\n+\t\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t\t  HW_KM_RCP_SWX_CCH,\n+\t\t\t\t\t\t\t\t  index, 0, 1);\n+\t\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t\t  HW_KM_RCP_SWX_SEL_A,\n+\t\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t\t  SWX_SEL_ALL32);\n+\t\t\t\t\t} else if (km->match_map[i]\n+\t\t\t\t\t\t\t->extr_start_offs_id ==\n+\t\t\t\t\t\t\tSB_MAC_PORT) {\n+\t\t\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t\t\t       \"Set KM SWX sel A - PTC + MAC\\n\");\n+\t\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t\t  HW_KM_RCP_SWX_SEL_A,\n+\t\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t\t  SWX_SEL_ALL32);\n+\t\t\t\t\t} else if (km->match_map[i]\n+\t\t\t\t\t\t\t->extr_start_offs_id ==\n+\t\t\t\t\t\t\tSB_KCC_ID) {\n+\t\t\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t\t\t       \"Set KM SWX sel A - KCC ID\\n\");\n+\t\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t\t  HW_KM_RCP_SWX_CCH,\n+\t\t\t\t\t\t\t\t  index, 0, 1);\n+\t\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t\t  HW_KM_RCP_SWX_SEL_A,\n+\t\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t\t  SWX_SEL_ALL32);\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\treturn -1;\n+\t\t\t\t\t}\n+\t\t\t\t} else {\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t\tswx++;\n+\t\t\t} else {\n+\t\t\t\tif (sw == 0) {\n+\t\t\t\t\t/* DW8 */\n+\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t  HW_KM_RCP_DW8_DYN,\n+\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t  km->match_map[i]\n+\t\t\t\t\t\t\t  ->extr_start_offs_id);\n+\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t  HW_KM_RCP_DW8_OFS,\n+\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t  km->match_map[i]->rel_offs);\n+\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t  HW_KM_RCP_DW8_SEL_A,\n+\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t  DW8_SEL_FIRST32);\n+\t\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t\t       \"Set KM DW8 sel A: dyn: %i, offs: %i\\n\",\n+\t\t\t\t\t       km->match_map[i]\n+\t\t\t\t\t       ->extr_start_offs_id,\n+\t\t\t\t\t       km->match_map[i]->rel_offs);\n+\t\t\t\t} else if (sw == 1) {\n+\t\t\t\t\t/* DW10 */\n+\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t  HW_KM_RCP_DW10_DYN,\n+\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t  km->match_map[i]\n+\t\t\t\t\t\t\t  ->extr_start_offs_id);\n+\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t  HW_KM_RCP_DW10_OFS,\n+\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t  km->match_map[i]->rel_offs);\n+\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t  HW_KM_RCP_DW10_SEL_A,\n+\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t  DW10_SEL_FIRST32);\n+\t\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t\t       \"Set KM DW10 sel A: dyn: %i, offs: %i\\n\",\n+\t\t\t\t\t       km->match_map[i]\n+\t\t\t\t\t       ->extr_start_offs_id,\n+\t\t\t\t\t       km->match_map[i]->rel_offs);\n+\t\t\t\t} else {\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t\tsw++;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\tcase KM_USE_EXTRACTOR_QWORD:\n+\t\t\tif (qw == 0) {\n+\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t  HW_KM_RCP_QW0_DYN,\n+\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t  km->match_map[i]->extr_start_offs_id);\n+\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t  HW_KM_RCP_QW0_OFS,\n+\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t  km->match_map[i]->rel_offs);\n+\t\t\t\tswitch (km->match_map[i]->word_len) {\n+\t\t\t\tcase 1:\n+\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t  HW_KM_RCP_QW0_SEL_A,\n+\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t  QW0_SEL_FIRST32);\n+\t\t\t\t\tbreak;\n+\t\t\t\tcase 2:\n+\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t  HW_KM_RCP_QW0_SEL_A,\n+\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t  QW0_SEL_FIRST64);\n+\t\t\t\t\tbreak;\n+\t\t\t\tcase 4:\n+\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t  HW_KM_RCP_QW0_SEL_A,\n+\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t  QW0_SEL_ALL128);\n+\t\t\t\t\tbreak;\n+\t\t\t\tdefault:\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"Set KM QW0 sel A: dyn: %i, offs: %i, size: %i\\n\",\n+\t\t\t\t       km->match_map[i]->extr_start_offs_id,\n+\t\t\t\t       km->match_map[i]->rel_offs,\n+\t\t\t\t       km->match_map[i]->word_len);\n+\t\t\t} else if (qw == 1) {\n+\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t  HW_KM_RCP_QW4_DYN,\n+\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t  km->match_map[i]->extr_start_offs_id);\n+\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t  HW_KM_RCP_QW4_OFS,\n+\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t  km->match_map[i]->rel_offs);\n+\t\t\t\tswitch (km->match_map[i]->word_len) {\n+\t\t\t\tcase 1:\n+\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t  HW_KM_RCP_QW4_SEL_A,\n+\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t  QW4_SEL_FIRST32);\n+\t\t\t\t\tbreak;\n+\t\t\t\tcase 2:\n+\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t  HW_KM_RCP_QW4_SEL_A,\n+\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t  QW4_SEL_FIRST64);\n+\t\t\t\t\tbreak;\n+\t\t\t\tcase 4:\n+\t\t\t\t\thw_mod_km_rcp_set(km->be,\n+\t\t\t\t\t\t\t  HW_KM_RCP_QW4_SEL_A,\n+\t\t\t\t\t\t\t  index, 0,\n+\t\t\t\t\t\t\t  QW4_SEL_ALL128);\n+\t\t\t\t\tbreak;\n+\t\t\t\tdefault:\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"Set KM QW4 sel A: dyn: %i, offs: %i, size: %i\\n\",\n+\t\t\t\t       km->match_map[i]->extr_start_offs_id,\n+\t\t\t\t       km->match_map[i]->rel_offs,\n+\t\t\t\t       km->match_map[i]->word_len);\n+\t\t\t} else {\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tqw++;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t/* set mask A */\n+\tfor (int i = 0; i < km->key_word_size; i++) {\n+\t\thw_mod_km_rcp_set(km->be, HW_KM_RCP_MASK_A, index,\n+\t\t\t\t  (km->be->km.nb_km_rcp_mask_a_word_size - 1) -\n+\t\t\t\t  i,\n+\t\t\t\t  km->entry_mask[i]);\n+\t\tNT_LOG(DBG, FILTER, \"Set KM mask A: %08x\\n\", km->entry_mask[i]);\n+\t}\n+\n+\tif (km->target == KM_CAM) {\n+\t\t/* set info - Color */\n+\t\tif (km->info_set) {\n+\t\t\thw_mod_km_rcp_set(km->be, HW_KM_RCP_INFO_A, index, 0,\n+\t\t\t\t\t  1);\n+\t\t\tNT_LOG(DBG, FILTER, \"Set KM info A\\n\");\n+\t\t}\n+\t\t/* set key length A */\n+\t\thw_mod_km_rcp_set(km->be, HW_KM_RCP_EL_A, index, 0,\n+\t\t\t\t  km->key_word_size + !!km->info_set -\n+\t\t\t\t  1); /* select id is -1 */\n+\t\t/* set Flow Type for Key A */\n+\t\tNT_LOG(DBG, FILTER, \"Set KM EL A: %i\\n\",\n+\t\t       km->key_word_size + !!km->info_set - 1);\n+\n+\t\thw_mod_km_rcp_set(km->be, HW_KM_RCP_FTM_A, index, 0,\n+\t\t\t\t  1 << km->flow_type);\n+\n+\t\tNT_LOG(DBG, FILTER, \"Set KM FTM A - ft: %i\\n\", km->flow_type);\n+\n+\t\t/* Set Paired - only on the CAM part though... */\n+\t\tif ((uint32_t)(km->key_word_size + !!km->info_set) >\n+\t\t\t\tkm->be->km.nb_cam_record_words) {\n+\t\t\thw_mod_km_rcp_set(km->be, HW_KM_RCP_PAIRED,\n+\t\t\t\t\t  index, 0, 1);\n+\t\t\tNT_LOG(DBG, FILTER, \"Set KM CAM Paired\\n\");\n+\t\t\tkm->cam_paired = 1;\n+\t\t}\n+\t} else if (km->target == KM_TCAM) {\n+\t\tuint32_t bank_bm = 0;\n+\n+\t\tif (tcam_find_mapping(km) < 0) {\n+\t\t\t/* failed mapping into TCAM */\n+\t\t\tNT_LOG(DBG, FILTER, \"INFO: TCAM mapping flow failed\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tassert((uint32_t)(km->tcam_start_bank + km->key_word_size) <=\n+\t\t       km->be->km.nb_tcam_banks);\n+\n+\t\tfor (int i = 0; i < km->key_word_size; i++) {\n+\t\t\tbank_bm |= (1 << (km->be->km.nb_tcam_banks - 1 -\n+\t\t\t\t\t  (km->tcam_start_bank + i)));\n+\t\t}\n+\n+\t\t/* Set BANK_A */\n+\t\thw_mod_km_rcp_set(km->be, HW_KM_RCP_BANK_A, index, 0, bank_bm);\n+\t\t/* Set Kl_A */\n+\t\thw_mod_km_rcp_set(km->be, HW_KM_RCP_KL_A, index, 0,\n+\t\t\t\t  km->key_word_size - 1);\n+\n+\t} else {\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n+\n+static int cam_populate(struct km_flow_def_s *km, int bank)\n+{\n+\tint res = 0;\n+\tint cnt = km->key_word_size + !!km->info_set;\n+\n+\tfor (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt;\n+\t\t\ti++, cnt--) {\n+\t\tres |= hw_mod_km_cam_set(km->be, HW_KM_CAM_W0 + i, bank,\n+\t\t\t\t\t km->record_indexes[bank],\n+\t\t\t\t\t km->entry_word[i]);\n+\t\tres |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i, bank,\n+\t\t\t\t\t km->record_indexes[bank],\n+\t\t\t\t\t km->flow_type);\n+\t}\n+\tkm->cam_dist[CAM_KM_DIST_IDX(bank)].km_owner = km;\n+\n+\tif (cnt) {\n+\t\tassert(km->cam_paired);\n+\t\tfor (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt;\n+\t\t\t\ti++, cnt--) {\n+\t\t\tres |= hw_mod_km_cam_set(km->be,\n+\t\t\t\t\t\t HW_KM_CAM_W0 + i,\n+\t\t\t\t\t\t bank,\n+\t\t\t\t\t\t km->record_indexes[bank] + 1,\n+\t\t\t\t\t\t km->entry_word[km->be->km.nb_cam_record_words +\n+\t\t\t\t\t\t i]);\n+\t\t\tres |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i,\n+\t\t\t\t\t\t bank,\n+\t\t\t\t\t\t km->record_indexes[bank] + 1,\n+\t\t\t\t\t\t km->flow_type);\n+\t\t}\n+\t\tkm->cam_dist[CAM_KM_DIST_IDX(bank) + 1].km_owner = km;\n+\t}\n+\n+\tres |= hw_mod_km_cam_flush(km->be, bank, km->record_indexes[bank],\n+\t\t\t\t   km->cam_paired ? 2 : 1);\n+\n+\treturn res;\n+}\n+\n+static int cam_reset_entry(struct km_flow_def_s *km, int bank)\n+{\n+\tint res = 0;\n+\tint cnt = km->key_word_size + !!km->info_set;\n+\n+\tfor (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt;\n+\t\t\ti++, cnt--) {\n+\t\tres |= hw_mod_km_cam_set(km->be, HW_KM_CAM_W0 + i, bank,\n+\t\t\t\t\t km->record_indexes[bank], 0);\n+\t\tres |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i, bank,\n+\t\t\t\t\t km->record_indexes[bank], 0);\n+\t}\n+\tkm->cam_dist[CAM_KM_DIST_IDX(bank)].km_owner = NULL;\n+\n+\tif (cnt) {\n+\t\tassert(km->cam_paired);\n+\t\tfor (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt;\n+\t\t\t\ti++, cnt--) {\n+\t\t\tres |= hw_mod_km_cam_set(km->be, HW_KM_CAM_W0 + i, bank,\n+\t\t\t\t\t\t km->record_indexes[bank] + 1,\n+\t\t\t\t\t\t 0);\n+\t\t\tres |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i,\n+\t\t\t\t\t\t bank,\n+\t\t\t\t\t\t km->record_indexes[bank] + 1,\n+\t\t\t\t\t\t 0);\n+\t\t}\n+\t\tkm->cam_dist[CAM_KM_DIST_IDX(bank) + 1].km_owner = NULL;\n+\t}\n+\tres |= hw_mod_km_cam_flush(km->be, bank, km->record_indexes[bank],\n+\t\t\t\t   km->cam_paired ? 2 : 1);\n+\treturn res;\n+}\n+\n+static int move_cuckoo_index(struct km_flow_def_s *km)\n+{\n+\tassert(km->cam_dist[CAM_KM_DIST_IDX(km->bank_used)].km_owner);\n+\n+\tfor (uint32_t bank = 0; bank < km->be->km.nb_cam_banks; bank++) {\n+\t\t/* It will not select itself */\n+\t\tif (km->cam_dist[CAM_KM_DIST_IDX(bank)].km_owner == NULL) {\n+\t\t\tif (km->cam_paired) {\n+\t\t\t\tif (km->cam_dist[CAM_KM_DIST_IDX(bank) + 1]\n+\t\t\t\t\t\t.km_owner != NULL)\n+\t\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * Populate in new position\n+\t\t\t */\n+\t\t\tint res = cam_populate(km, bank);\n+\n+\t\t\tif (res) {\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"Error: failed to write to KM CAM in cuckoo move\\n\");\n+\t\t\t\treturn 0;\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * Reset/free entry in old bank\n+\t\t\t * HW flushes are really not needed, the old addresses are always taken over\n+\t\t\t * by the caller\n+\t\t\t * If you change this code in future updates, this may no longer be true\n+\t\t\t * then!\n+\t\t\t */\n+\t\t\tkm->cam_dist[CAM_KM_DIST_IDX(km->bank_used)].km_owner =\n+\t\t\t\tNULL;\n+\t\t\tif (km->cam_paired)\n+\t\t\t\tkm->cam_dist[CAM_KM_DIST_IDX(km->bank_used) + 1]\n+\t\t\t\t.km_owner = NULL;\n+\n+\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t       \"KM Cuckoo hash moved from bank %i to bank %i (%04X => %04X)\\n\",\n+\t\t\t       km->bank_used, bank,\n+\t\t\t       CAM_KM_DIST_IDX(km->bank_used),\n+\t\t\t       CAM_KM_DIST_IDX(bank));\n+\t\t\tkm->bank_used = bank;\n+\t\t\t(*km->cuckoo_moves)++;\n+\t\t\treturn 1;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int move_cuckoo_index_level(struct km_flow_def_s *km_parent,\n+\t\t\t\t   int bank_idx, int levels,\n+\t\t\t\t   int cam_adr_list_len)\n+{\n+\tstruct km_flow_def_s *km = km_parent->cam_dist[bank_idx].km_owner;\n+\n+\tassert(levels <= CUCKOO_MOVE_MAX_DEPTH);\n+\n+\t/*\n+\t * Only move if same pairness\n+\t * Can be extended later to handle both move of paired and single entries\n+\t */\n+\tif (!km || km_parent->cam_paired != km->cam_paired)\n+\t\treturn 0;\n+\n+\tif (move_cuckoo_index(km))\n+\t\treturn 1;\n+\tif (levels <= 1)\n+\t\treturn 0;\n+\n+\tassert(cam_adr_list_len < CUCKOO_MOVE_MAX_DEPTH);\n+\n+\tcam_addr_reserved_stack[cam_adr_list_len++] = bank_idx;\n+\n+\tfor (uint32_t i = 0; i < km->be->km.nb_cam_banks; i++) {\n+\t\tint reserved = 0;\n+\t\tint new_idx = CAM_KM_DIST_IDX(i);\n+\n+\t\tfor (int i_reserved = 0; i_reserved < cam_adr_list_len;\n+\t\t\t\ti_reserved++) {\n+\t\t\tif (cam_addr_reserved_stack[i_reserved] == new_idx) {\n+\t\t\t\treserved = 1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tif (reserved)\n+\t\t\tcontinue;\n+\n+\t\tint res = move_cuckoo_index_level(km, new_idx, levels - 1,\n+\t\t\t\t\t\t  cam_adr_list_len);\n+\t\tif (res) {\n+\t\t\tif (move_cuckoo_index(km))\n+\t\t\t\treturn 1;\n+\n+\t\t\telse\n+\t\t\t\tassert(0);\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int km_write_data_to_cam(struct km_flow_def_s *km)\n+{\n+\tint res = 0;\n+\tint val[MAX_BANKS];\n+\n+\tassert(km->be->km.nb_cam_banks <= MAX_BANKS);\n+\tassert(km->cam_dist);\n+\n+\t/* word list without info set */\n+\tgethash(km->hsh, km->entry_word, val);\n+\n+\tfor (uint32_t i = 0; i < km->be->km.nb_cam_banks; i++) {\n+\t\t/* if paired we start always on an even address - reset bit 0 */\n+\t\tkm->record_indexes[i] = (km->cam_paired) ? val[i] & ~1 : val[i];\n+\t}\n+\tNT_LOG(DBG, FILTER, \"KM HASH [%03X, %03X, %03X]\\n\",\n+\t       km->record_indexes[0], km->record_indexes[1],\n+\t       km->record_indexes[2]);\n+\n+\tif (km->info_set) {\n+\t\tkm->entry_word[km->key_word_size] =\n+\t\t\tkm->info; /* finally set info */\n+\t}\n+\n+\tint bank = -1;\n+\t/*\n+\t * first step, see if any of the banks are free\n+\t */\n+\tfor (uint32_t i_bank = 0; i_bank < km->be->km.nb_cam_banks; i_bank++) {\n+\t\tif (km->cam_dist[CAM_KM_DIST_IDX(i_bank)].km_owner == NULL) {\n+\t\t\tif (km->cam_paired == 0 ||\n+\t\t\t\t\t(km->cam_dist[CAM_KM_DIST_IDX(i_bank) + 1]\n+\t\t\t\t\t .km_owner == NULL)) {\n+\t\t\t\tbank = i_bank;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif (bank < 0) {\n+\t\t/*\n+\t\t * Second step - cuckoo move existing flows if possible\n+\t\t */\n+\t\tfor (uint32_t i_bank = 0; i_bank < km->be->km.nb_cam_banks;\n+\t\t\t\ti_bank++) {\n+\t\t\tif (move_cuckoo_index_level(km, CAM_KM_DIST_IDX(i_bank),\n+\t\t\t\t\t\t    4, 0)) {\n+\t\t\t\tbank = i_bank;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\tif (bank < 0)\n+\t\treturn -1;\n+\n+\t/* populate CAM */\n+\tNT_LOG(DBG, FILTER, \"KM Bank = %i (addr %04X)\\n\", bank,\n+\t       CAM_KM_DIST_IDX(bank));\n+\tres = cam_populate(km, bank);\n+\tif (res == 0) {\n+\t\tkm->flushed_to_target = 1;\n+\t\tkm->bank_used = bank;\n+\t}\n+\n+\treturn res;\n+}\n+\n+/*\n+ * TCAM\n+ */\n+static int tcam_find_free_record(struct km_flow_def_s *km, int start_bank)\n+{\n+\tfor (uint32_t rec = 0; rec < km->be->km.nb_tcam_bank_width; rec++) {\n+\t\tif (km->tcam_dist[TCAM_DIST_IDX(start_bank, rec)].km_owner ==\n+\t\t\t\tNULL) {\n+\t\t\tint pass = 1;\n+\n+\t\t\tfor (int ii = 1; ii < km->key_word_size; ii++) {\n+\t\t\t\tif (km->tcam_dist[TCAM_DIST_IDX(start_bank + ii,\n+\t\t\t\t\t\t\t\t\t\t\t rec)]\n+\t\t\t\t\t\t.km_owner != NULL) {\n+\t\t\t\t\tpass = 0;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tif (pass) {\n+\t\t\t\tkm->tcam_record = rec;\n+\t\t\t\treturn 1;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int tcam_find_mapping(struct km_flow_def_s *km)\n+{\n+\t/* Search record and start index for this flow */\n+\tfor (int bs_idx = 0; bs_idx < km->num_start_offsets; bs_idx++) {\n+\t\tif (tcam_find_free_record(km, km->start_offsets[bs_idx])) {\n+\t\t\tkm->tcam_start_bank = km->start_offsets[bs_idx];\n+\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t       \"Found space in TCAM start bank %i, record %i\\n\",\n+\t\t\t       km->tcam_start_bank, km->tcam_record);\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\treturn -1;\n+}\n+\n+static int tcam_write_word(struct km_flow_def_s *km, int bank, int record,\n+\t\t\t   uint32_t word, uint32_t mask)\n+{\n+\tint err = 0;\n+\tuint32_t all_recs[3];\n+\n+\tint rec_val = record / 32;\n+\tint rec_bit_shft = record % 32;\n+\tuint32_t rec_bit = (1 << rec_bit_shft);\n+\n+\tassert((km->be->km.nb_tcam_bank_width + 31) / 32 <= 3);\n+\n+\tfor (int byte = 0; byte < 4; byte++) {\n+\t\tuint8_t a = (uint8_t)((word >> (24 - (byte * 8))) & 0xff);\n+\t\tuint8_t a_m = (uint8_t)((mask >> (24 - (byte * 8))) & 0xff);\n+\t\t/* calculate important value bits */\n+\t\ta = a & a_m;\n+\n+#ifdef FLOW_DEBUG\n+\t\tif (a_m == 0) {\n+\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t       \"bank %i, byte %i, All values, rec_val %i rec bit %08x\\n\",\n+\t\t\t       bank, byte, rec_val, rec_bit);\n+\t\t}\n+#endif\n+\n+\t\tfor (int val = 0; val < 256; val++) {\n+\t\t\terr |= hw_mod_km_tcam_get(km->be, HW_KM_TCAM_T, bank,\n+\t\t\t\t\t\t  byte, val, all_recs);\n+\t\t\tif ((val & a_m) == a) {\n+\t\t\t\tall_recs[rec_val] |= rec_bit;\n+#ifdef FLOW_DEBUG\n+\t\t\t\tif (a_m) {\n+\t\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t\t       \"bank %i, byte %i, val %i(%02x), \"\n+\t\t\t\t\t       \"rec_val %i rec bit %08x\\n\",\n+\t\t\t\t\t       bank, byte, val, val, rec_val,\n+\t\t\t\t\t       rec_bit);\n+\t\t\t\t}\n+#endif\n+\t\t\t} else {\n+\t\t\t\tall_recs[rec_val] &= ~rec_bit;\n+\t\t\t}\n+\t\t\terr |= hw_mod_km_tcam_set(km->be, HW_KM_TCAM_T, bank,\n+\t\t\t\t\t\t  byte, val, all_recs);\n+\t\t\tif (err)\n+\t\t\t\tbreak;\n+\t\t}\n+\t}\n+\t/* flush bank */\n+\terr |= hw_mod_km_tcam_flush(km->be, bank, ALL_BANK_ENTRIES);\n+\tif (err == 0) {\n+\t\tassert(km->tcam_dist[TCAM_DIST_IDX(bank, record)].km_owner ==\n+\t\t       NULL);\n+\t\tkm->tcam_dist[TCAM_DIST_IDX(bank, record)].km_owner = km;\n+\t}\n+\treturn err;\n+}\n+\n+static int km_write_data_to_tcam(struct km_flow_def_s *km)\n+{\n+\tint err = 0;\n+\n+\tif (km->tcam_record < 0) {\n+\t\ttcam_find_free_record(km, km->tcam_start_bank);\n+\t\tif (km->tcam_record < 0) {\n+\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t       \"FAILED to find space in TCAM for flow\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tNT_LOG(DBG, FILTER,\n+\t\t       \"Reused RCP: Found space in TCAM start bank %i, record %i\\n\",\n+\t\t       km->tcam_start_bank, km->tcam_record);\n+\t}\n+\n+\t/* Write KM_TCI */\n+\terr |= hw_mod_km_tci_set(km->be, HW_KM_TCI_COLOR, km->tcam_start_bank,\n+\t\t\t\t km->tcam_record, km->info);\n+\terr |= hw_mod_km_tci_set(km->be, HW_KM_TCI_FT, km->tcam_start_bank,\n+\t\t\t\t km->tcam_record, km->flow_type);\n+\terr |= hw_mod_km_tci_flush(km->be, km->tcam_start_bank, km->tcam_record,\n+\t\t\t\t   1);\n+\n+#ifdef FLOW_DEBUG\n+\tkm->be->iface->set_debug_mode(km->be->be_dev,\n+\t\t\t\t      FLOW_BACKEND_DEBUG_MODE_NONE);\n+#endif\n+\n+\tfor (int i = 0; i < km->key_word_size && !err; i++) {\n+\t\terr = tcam_write_word(km, km->tcam_start_bank + i,\n+\t\t\t\t      km->tcam_record, km->entry_word[i],\n+\t\t\t\t      km->entry_mask[i]);\n+\t}\n+#ifdef FLOW_DEBUG\n+\tkm->be->iface->set_debug_mode(km->be->be_dev,\n+\t\t\t\t      FLOW_BACKEND_DEBUG_MODE_WRITE);\n+#endif\n+\n+\tif (err == 0)\n+\t\tkm->flushed_to_target = 1;\n+\n+\treturn err;\n+}\n+\n+static int tcam_reset_bank(struct km_flow_def_s *km, int bank, int record)\n+{\n+\tint err = 0;\n+\tuint32_t all_recs[3];\n+\n+\tint rec_val = record / 32;\n+\tint rec_bit_shft = record % 32;\n+\tuint32_t rec_bit = (1 << rec_bit_shft);\n+\n+\tassert((km->be->km.nb_tcam_bank_width + 31) / 32 <= 3);\n+\n+\tfor (int byte = 0; byte < 4; byte++) {\n+\t\tfor (int val = 0; val < 256; val++) {\n+\t\t\terr = hw_mod_km_tcam_get(km->be, HW_KM_TCAM_T, bank,\n+\t\t\t\t\t\t byte, val, all_recs);\n+\t\t\tif (err)\n+\t\t\t\tbreak;\n+\t\t\tall_recs[rec_val] &= ~rec_bit;\n+\t\t\terr = hw_mod_km_tcam_set(km->be, HW_KM_TCAM_T, bank,\n+\t\t\t\t\t\t byte, val, all_recs);\n+\t\t\tif (err)\n+\t\t\t\tbreak;\n+\t\t}\n+\t}\n+\tif (err)\n+\t\treturn err;\n+\n+\t/* flush bank */\n+\terr = hw_mod_km_tcam_flush(km->be, bank, ALL_BANK_ENTRIES);\n+\tkm->tcam_dist[TCAM_DIST_IDX(bank, record)].km_owner = NULL;\n+\n+\tNT_LOG(DBG, FILTER, \"Reset TCAM bank %i, rec_val %i rec bit %08x\\n\",\n+\t       bank, rec_val, rec_bit);\n+\n+\treturn err;\n+}\n+\n+static int tcam_reset_entry(struct km_flow_def_s *km)\n+{\n+\tint err = 0;\n+\n+\tif (km->tcam_start_bank < 0 || km->tcam_record < 0) {\n+\t\tNT_LOG(DBG, FILTER, \"FAILED to find space in TCAM for flow\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* Write KM_TCI */\n+\thw_mod_km_tci_set(km->be, HW_KM_TCI_COLOR, km->tcam_start_bank,\n+\t\t\t  km->tcam_record, 0);\n+\thw_mod_km_tci_set(km->be, HW_KM_TCI_FT, km->tcam_start_bank,\n+\t\t\t  km->tcam_record, 0);\n+\thw_mod_km_tci_flush(km->be, km->tcam_start_bank, km->tcam_record, 1);\n+\n+#ifdef FLOW_DEBUG\n+\tkm->be->iface->set_debug_mode(km->be->be_dev,\n+\t\t\t\t      FLOW_BACKEND_DEBUG_MODE_NONE);\n+#endif\n+\n+\tfor (int i = 0; i < km->key_word_size && !err; i++) {\n+\t\terr = tcam_reset_bank(km, km->tcam_start_bank + i,\n+\t\t\t\t      km->tcam_record);\n+\t}\n+#ifdef FLOW_DEBUG\n+\tkm->be->iface->set_debug_mode(km->be->be_dev,\n+\t\t\t\t      FLOW_BACKEND_DEBUG_MODE_WRITE);\n+#endif\n+\n+\treturn err;\n+}\n+\n+int km_refer_data_match_entry(struct km_flow_def_s *km,\n+\t\t\t      struct km_flow_def_s *km1)\n+{\n+\tint res = 0;\n+\n+\tkm->root = km1->root ? km1->root : km1;\n+\twhile (km1->reference)\n+\t\tkm1 = km1->reference;\n+\tkm1->reference = km;\n+\n+\tkm->info = km1->info;\n+\n+\tswitch (km->target) {\n+\tcase KM_CAM:\n+\t\tkm->cam_paired = km1->cam_paired;\n+\t\tkm->bank_used = km1->bank_used;\n+\t\tkm->flushed_to_target = km1->flushed_to_target;\n+\t\tbreak;\n+\tcase KM_TCAM:\n+\t\tkm->tcam_start_bank = km1->tcam_start_bank;\n+\t\tkm->tcam_record = km1->tcam_record;\n+\t\tkm->flushed_to_target = km1->flushed_to_target;\n+\t\tbreak;\n+\tcase KM_SYNERGY:\n+\tdefault:\n+\t\tres = -1;\n+\t\tbreak;\n+\t}\n+\n+\treturn res;\n+}\n+\n+int km_write_data_match_entry(struct km_flow_def_s *km, uint32_t color)\n+{\n+\tint res = -1;\n+\n+\tkm->info = color;\n+\tNT_LOG(DBG, FILTER, \"Write Data entry Color: %08x\\n\", color);\n+\n+\tswitch (km->target) {\n+\tcase KM_CAM:\n+\t\tres = km_write_data_to_cam(km);\n+\t\tbreak;\n+\tcase KM_TCAM:\n+\t\tres = km_write_data_to_tcam(km);\n+\t\tbreak;\n+\tcase KM_SYNERGY:\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\treturn res;\n+}\n+\n+int km_clear_data_match_entry(struct km_flow_def_s *km)\n+{\n+\tint res = 0;\n+\n+\tif (km->root) {\n+\t\tstruct km_flow_def_s *km1 = km->root;\n+\n+\t\twhile (km1->reference != km)\n+\t\t\tkm1 = km1->reference;\n+\n+\t\tkm1->reference = km->reference;\n+\n+\t\tkm->flushed_to_target = 0;\n+\t\tkm->bank_used = 0;\n+\t} else if (km->reference) {\n+\t\tkm->reference->root = NULL;\n+\n+\t\tswitch (km->target) {\n+\t\tcase KM_CAM:\n+\t\t\tkm->cam_dist[CAM_KM_DIST_IDX(km->bank_used)].km_owner =\n+\t\t\t\tkm->reference;\n+\t\t\tif (km->key_word_size + !!km->info_set > 1) {\n+\t\t\t\tassert(km->cam_paired);\n+\t\t\t\tkm->cam_dist[CAM_KM_DIST_IDX(km->bank_used) + 1]\n+\t\t\t\t.km_owner = km->reference;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase KM_TCAM:\n+\t\t\tfor (int i = 0; i < km->key_word_size; i++) {\n+\t\t\t\tkm->tcam_dist[TCAM_DIST_IDX(km->tcam_start_bank + i,\n+\t\t\t\t\tkm->tcam_record)].km_owner = km->reference;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase KM_SYNERGY:\n+\t\tdefault:\n+\t\t\tres = -1;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tkm->flushed_to_target = 0;\n+\t\tkm->bank_used = 0;\n+\t} else if (km->flushed_to_target) {\n+\t\tswitch (km->target) {\n+\t\tcase KM_CAM:\n+\t\t\tres = cam_reset_entry(km, km->bank_used);\n+\t\t\tbreak;\n+\t\tcase KM_TCAM:\n+\t\t\tres = tcam_reset_entry(km);\n+\t\t\tbreak;\n+\t\tcase KM_SYNERGY:\n+\t\tdefault:\n+\t\t\tres = -1;\n+\t\t\tbreak;\n+\t\t}\n+\t\tkm->flushed_to_target = 0;\n+\t\tkm->bank_used = 0;\n+\t}\n+\n+\treturn res;\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c\nnew file mode 100644\nindex 0000000000..17717da8e2\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c\n@@ -0,0 +1,787 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdarg.h>\n+#include <string.h>\n+#include <stdlib.h>\n+#include <assert.h>\n+#include <arpa/inet.h> /* htons, htonl, ntohs */\n+#include <stdio.h>\n+#include \"stream_binary_flow_api.h\"\n+\n+#include \"flow_api_backend.h\"\n+#include \"flow_api_engine.h\"\n+\n+#define MAX_HW_VIRT_PORTS 127 /* 255 reserved */\n+#define VIRTUAL_TUNNEL_PORT_OFFSET 72\n+\n+struct tunnel_s {\n+\tstruct tunnel_cfg_s cfg;\n+\tstruct tunnel_cfg_s cfg_mask;\n+\tuint32_t flow_stat_id;\n+\tuint8_t vport;\n+\tint refcnt;\n+\tstruct tunnel_s *next; /* linked list of defined tunnels */\n+};\n+\n+int is_virtual_port(uint8_t virt_port)\n+{\n+\treturn !!(virt_port >= VIRTUAL_TUNNEL_PORT_OFFSET &&\n+\t\t  virt_port < MAX_HW_VIRT_PORTS);\n+}\n+\n+/*\n+ * New function for use with OVS 2.17.2\n+ */\n+static struct tunnel_s *tunnels;\n+\n+static uint8_t vport[MAX_HW_VIRT_PORTS - VIRTUAL_TUNNEL_PORT_OFFSET + 1];\n+\n+uint8_t flow_tunnel_alloc_virt_port(void)\n+{\n+\tfor (uint8_t i = VIRTUAL_TUNNEL_PORT_OFFSET; i < MAX_HW_VIRT_PORTS;\n+\t\t\ti++) {\n+\t\tif (!vport[i - VIRTUAL_TUNNEL_PORT_OFFSET]) {\n+\t\t\tvport[i - VIRTUAL_TUNNEL_PORT_OFFSET] = 1;\n+\t\t\treturn i;\n+\t\t}\n+\t}\n+\n+\t/* no more virtual ports */\n+\treturn 255;\n+}\n+\n+uint8_t flow_tunnel_free_virt_port(uint8_t virt_port)\n+{\n+\tif (virt_port >= VIRTUAL_TUNNEL_PORT_OFFSET &&\n+\t\t\tvirt_port < MAX_HW_VIRT_PORTS) {\n+\t\tvport[virt_port - VIRTUAL_TUNNEL_PORT_OFFSET] = 0;\n+\t\treturn 0;\n+\t}\n+\treturn -1;\n+}\n+\n+#define check(_v1, _v2, _msk1, _msk2) ({ \\\n+\t__typeof__(_v1) (v1) = (_v1); \\\n+\t__typeof__(_v2) (v2) = (_v2); \\\n+\t__typeof__(_msk1) (msk1) = (_msk1); \\\n+\t__typeof__(_msk2) (msk2) = (_msk2); \\\n+\t(((v1) & (msk1) & (msk2)) == ((v2) & (msk1) & (msk2))); \\\n+})\n+\n+#define check_tun_v4_equal(_tun_cfg, _tun_msk, _tun1_cfg, _tun1_msk) ({      \\\n+\t__typeof__(_tun_cfg) (tun_cfg) = (_tun_cfg); \\\n+\t__typeof__(_tun_msk) (tun_msk) = (_tun_msk); \\\n+\t__typeof__(_tun1_cfg) (tun1_cfg) = (_tun1_cfg); \\\n+\t__typeof__(_tun1_msk) (tun1_msk) = (_tun1_msk); \\\n+\t(check((tun_cfg)->v4.src_ip, (tun1_cfg)->v4.src_ip,              \\\n+\t\t(tun_msk)->v4.src_ip, (tun1_msk)->v4.src_ip) &&           \\\n+\t check((tun_cfg)->v4.dst_ip, (tun1_cfg)->v4.dst_ip,              \\\n+\t\t(tun_msk)->v4.dst_ip, (tun1_msk)->v4.dst_ip) &&           \\\n+\t check((tun_cfg)->s_port, (tun1_cfg)->s_port, (tun_msk)->s_port, \\\n+\t\t(tun1_msk)->s_port) &&                                    \\\n+\t check((tun_cfg)->d_port, (tun1_cfg)->d_port, (tun_msk)->d_port, \\\n+\t\t(tun1_msk)->d_port)); \\\n+})\n+\n+#define check_tun_v6_equal(_tun_cfg, _tun_msk, _tun1_cfg, _tun1_msk) ({        \\\n+\t__typeof__(_tun_cfg) (tun_cfg) = (_tun_cfg); \\\n+\t__typeof__(_tun_msk) (tun_msk) = (_tun_msk); \\\n+\t__typeof__(_tun1_cfg) (tun1_cfg) = (_tun1_cfg); \\\n+\t__typeof__(_tun1_msk) (tun1_msk) = (_tun1_msk); \\\n+\t(check((tun_cfg)->v6_long.src_ip[0], (tun1_cfg)->v6_long.src_ip[0],    \\\n+\t\t(tun_msk)->v6_long.src_ip[0], (tun1_msk)->v6_long.src_ip[0]) && \\\n+\t check((tun_cfg)->v6_long.src_ip[1], (tun1_cfg)->v6_long.src_ip[1],    \\\n+\t\t(tun_msk)->v6_long.src_ip[1], (tun1_msk)->v6_long.src_ip[1]) && \\\n+\t check((tun_cfg)->v6_long.dst_ip[0], (tun1_cfg)->v6_long.dst_ip[0],    \\\n+\t\t(tun_msk)->v6_long.dst_ip[0], (tun1_msk)->v6_long.dst_ip[0]) && \\\n+\t check((tun_cfg)->v6_long.dst_ip[1], (tun1_cfg)->v6_long.dst_ip[1],    \\\n+\t\t(tun_msk)->v6_long.dst_ip[1], (tun1_msk)->v6_long.dst_ip[1]) && \\\n+\t check((tun_cfg)->s_port, (tun1_cfg)->s_port, (tun_msk)->s_port,       \\\n+\t\t(tun1_msk)->s_port) &&                                          \\\n+\t check((tun_cfg)->d_port, (tun1_cfg)->d_port, (tun_msk)->d_port,       \\\n+\t\t(tun1_msk)->d_port)); \\\n+})\n+\n+static int check_tun_match(struct tunnel_s *tun,\n+\t\t\t   const struct tunnel_cfg_s *tnlcfg,\n+\t\t\t   const struct tunnel_cfg_s *tnlcfg_mask)\n+{\n+\tif (tun->cfg.tun_type == tnlcfg->tun_type) {\n+\t\tif (tun->cfg.ipversion == 4) {\n+\t\t\treturn check_tun_v4_equal(&tun->cfg, &tun->cfg_mask,\n+\t\t\t\t\t\t  tnlcfg, tnlcfg_mask);\n+\t\t} else {\n+\t\t\treturn check_tun_v6_equal(&tun->cfg, &tun->cfg_mask,\n+\t\t\t\t\t\t  tnlcfg, tnlcfg_mask);\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static struct tunnel_s *tunnel_get(const struct tunnel_cfg_s *tnlcfg,\n+\t\t\t\t   const struct tunnel_cfg_s *tnlcfg_mask,\n+\t\t\t\t   int tun_set)\n+{\n+\tstruct tunnel_s *tun = tunnels;\n+\n+\twhile (tun) {\n+\t\tif (tun->flow_stat_id != (uint32_t)-1) {\n+\t\t\t/* This tun is already defined and set */\n+\t\t\tif (tun_set) {\n+\t\t\t\t/*\n+\t\t\t\t * A tunnel full match definition - search for duplicate\n+\t\t\t\t */\n+\t\t\t\tif (memcmp(&tun->cfg, tnlcfg,\n+\t\t\t\t\t\tsizeof(struct tunnel_cfg_s)) == 0 &&\n+\t\t\t\t\t\tmemcmp(&tun->cfg_mask, tnlcfg_mask,\n+\t\t\t\t\t\t       sizeof(struct tunnel_cfg_s)) == 0)\n+\t\t\t\t\tbreak;\n+\t\t\t} else {\n+\t\t\t\t/*\n+\t\t\t\t * A tunnel match search\n+\t\t\t\t */\n+\t\t\t\tif (check_tun_match(tun, tnlcfg, tnlcfg_mask))\n+\t\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t} else if (tun_set) {\n+\t\t\t/*\n+\t\t\t * Check if this is a pre-configured tunnel for this one to be set\n+\t\t\t * try match them\n+\t\t\t */\n+\t\t\tif (check_tun_match(tun, tnlcfg, tnlcfg_mask)) {\n+\t\t\t\t/*\n+\t\t\t\t * Change the tun into the defining one - flow_stat_id is set later\n+\t\t\t\t */\n+\t\t\t\tmemcpy(&tun->cfg, tnlcfg,\n+\t\t\t\t       sizeof(struct tunnel_cfg_s));\n+\t\t\t\tmemcpy(&tun->cfg_mask, tnlcfg_mask,\n+\t\t\t\t       sizeof(struct tunnel_cfg_s));\n+\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t} /* else ignore - both unset */\n+\t\ttun = tun->next;\n+\t}\n+\n+\t/*\n+\t * If not found, create and add it to db\n+\t */\n+\tif (!tun) {\n+\t\tuint8_t vport = flow_tunnel_alloc_virt_port();\n+\n+\t\tNT_LOG(DBG, FILTER, \"Create NEW tunnel allocate vport %i\\n\",\n+\t\t       vport);\n+\n+\t\tif (vport < 0xff) {\n+\t\t\ttun = calloc(1, sizeof(struct tunnel_s));\n+\t\t\tmemcpy(&tun->cfg, tnlcfg, sizeof(struct tunnel_cfg_s));\n+\t\t\tmemcpy(&tun->cfg_mask, tnlcfg_mask,\n+\t\t\t       sizeof(struct tunnel_cfg_s));\n+\n+\t\t\t/* flow_stat_id is set later from flow code */\n+\t\t\ttun->flow_stat_id = (uint32_t)-1;\n+\t\t\ttun->vport = vport;\n+\t\t\ttun->refcnt = 1;\n+\n+\t\t\ttun->next = tunnels;\n+\t\t\ttunnels = tun;\n+\t\t}\n+\t} else {\n+\t\ttun->refcnt++;\n+\t\tNT_LOG(DBG, FILTER, \"Found tunnel has vport %i - ref %i\\n\",\n+\t\t       tun->vport, tun->refcnt);\n+\t}\n+\n+\treturn tun;\n+}\n+\n+int tunnel_release(struct tunnel_s *tnl)\n+{\n+\tstruct tunnel_s *tun = tunnels, *prev = NULL;\n+\n+\tNT_LOG(DBG, FILTER, \"release tunnel vport %i, ref cnt %i..\\n\",\n+\t       tnl->vport, tnl->refcnt);\n+\t/* find tunnel in list */\n+\twhile (tun) {\n+\t\tif (tun == tnl)\n+\t\t\tbreak;\n+\t\tprev = tun;\n+\t\ttun = tun->next;\n+\t}\n+\n+\tif (!tun) {\n+\t\tNT_LOG(DBG, FILTER,\n+\t\t       \"ERROR: Tunnel not found in tunnel release!\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* if last ref, take out of list */\n+\tif (--tun->refcnt == 0) {\n+\t\tif (prev)\n+\t\t\tprev->next = tun->next;\n+\t\telse\n+\t\t\ttunnels = tun->next;\n+\t\tflow_tunnel_free_virt_port(tun->vport);\n+\n+\t\tNT_LOG(DBG, FILTER,\n+\t\t       \"tunnel ref count == 0 remove tunnel vport %i\\n\",\n+\t\t       tun->vport);\n+\t\tfree(tun);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+struct tunnel_s *tunnel_parse(const struct flow_elem *elem, int *idx,\n+\t\t\t      uint32_t *vni)\n+{\n+\tint eidx = *idx;\n+\tstruct tunnel_cfg_s tnlcfg;\n+\tstruct tunnel_cfg_s tnlcfg_mask;\n+\tstruct tunnel_s *rtnl = NULL;\n+\n+\tif (elem) {\n+\t\teidx++;\n+\t\tmemset(&tnlcfg, 0, sizeof(struct tunnel_cfg_s));\n+\t\tint valid = 1;\n+\t\tenum flow_elem_type last_type = FLOW_ELEM_TYPE_END;\n+\n+\t\ttnlcfg.d_port = 0xffff;\n+\t\ttnlcfg.tun_type = -1;\n+\n+\t\tif (vni)\n+\t\t\t*vni = (uint32_t)-1;\n+\n+\t\twhile (elem[eidx].type != FLOW_ELEM_TYPE_END &&\n+\t\t\t\telem[eidx].type >= last_type && valid) {\n+\t\t\tswitch (elem[eidx].type) {\n+\t\t\tcase FLOW_ELEM_TYPE_ANY:\n+\t\t\tcase FLOW_ELEM_TYPE_ETH:\n+\t\t\t\t/* Ignore */\n+\t\t\t\tbreak;\n+\t\t\tcase FLOW_ELEM_TYPE_IPV4: {\n+\t\t\t\tconst struct flow_elem_ipv4 *ipv4 =\n+\t\t\t\t\t(const struct flow_elem_ipv4 *)elem[eidx]\n+\t\t\t\t\t.spec;\n+\t\t\t\tconst struct flow_elem_ipv4 *ipv4_mask =\n+\t\t\t\t\t(const struct flow_elem_ipv4 *)elem[eidx]\n+\t\t\t\t\t.mask;\n+\n+\t\t\t\ttnlcfg.v4.src_ip = ipv4->hdr.src_ip;\n+\t\t\t\ttnlcfg.v4.dst_ip = ipv4->hdr.dst_ip;\n+\t\t\t\ttnlcfg_mask.v4.src_ip = ipv4_mask->hdr.src_ip;\n+\t\t\t\ttnlcfg_mask.v4.dst_ip = ipv4_mask->hdr.dst_ip;\n+\n+\t\t\t\ttnlcfg.ipversion = 4;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t\tcase FLOW_ELEM_TYPE_IPV6: {\n+\t\t\t\tconst struct flow_elem_ipv6 *ipv6 =\n+\t\t\t\t\t(const struct flow_elem_ipv6 *)elem[eidx]\n+\t\t\t\t\t.spec;\n+\t\t\t\tconst struct flow_elem_ipv6 *ipv6_mask =\n+\t\t\t\t\t(const struct flow_elem_ipv6 *)elem[eidx]\n+\t\t\t\t\t.mask;\n+\n+\t\t\t\tmemcpy(tnlcfg.v6.src_ip, ipv6->hdr.src_addr,\n+\t\t\t\t       sizeof(tnlcfg.v6.src_ip));\n+\t\t\t\tmemcpy(tnlcfg.v6.dst_ip, ipv6->hdr.dst_addr,\n+\t\t\t\t       sizeof(tnlcfg.v6.dst_ip));\n+\t\t\t\tmemcpy(tnlcfg_mask.v6.src_ip,\n+\t\t\t\t       ipv6_mask->hdr.src_addr,\n+\t\t\t\t       sizeof(tnlcfg.v6.src_ip));\n+\t\t\t\tmemcpy(tnlcfg_mask.v6.dst_ip,\n+\t\t\t\t       ipv6_mask->hdr.dst_addr,\n+\t\t\t\t       sizeof(tnlcfg.v6.dst_ip));\n+\n+\t\t\t\ttnlcfg.ipversion = 6;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t\tcase FLOW_ELEM_TYPE_UDP: {\n+\t\t\t\tconst struct flow_elem_udp *udp =\n+\t\t\t\t\t(const struct flow_elem_udp *)elem[eidx]\n+\t\t\t\t\t.spec;\n+\t\t\t\tconst struct flow_elem_udp *udp_mask =\n+\t\t\t\t\t(const struct flow_elem_udp *)elem[eidx]\n+\t\t\t\t\t.mask;\n+\n+\t\t\t\ttnlcfg.s_port = udp->hdr.src_port;\n+\t\t\t\ttnlcfg.d_port = udp->hdr.dst_port;\n+\t\t\t\ttnlcfg_mask.s_port = udp_mask->hdr.src_port;\n+\t\t\t\ttnlcfg_mask.d_port = udp_mask->hdr.dst_port;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t\tcase FLOW_ELEM_TYPE_VXLAN: {\n+\t\t\t\tconst struct flow_elem_vxlan *vxlan =\n+\t\t\t\t\t(const struct flow_elem_vxlan *)\n+\t\t\t\t\telem[eidx]\n+\t\t\t\t\t.spec;\n+\t\t\t\tif (vni)\n+\t\t\t\t\t*vni = (uint32_t)(((uint32_t)\n+\t\t\t\t\t\t\t   vxlan->vni[0]\n+\t\t\t\t\t\t\t   << 16) |\n+\t\t\t\t\t\t\t  ((uint32_t)\n+\t\t\t\t\t\t\t   vxlan->vni[1]\n+\t\t\t\t\t\t\t   << 8) |\n+\t\t\t\t\t\t\t  ((uint32_t)vxlan\n+\t\t\t\t\t\t\t   ->vni[2]));\n+\n+\t\t\t\ttnlcfg.tun_type = FLOW_ELEM_TYPE_VXLAN;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tvalid = 0;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tlast_type = elem[eidx].type;\n+\t\t\teidx++;\n+\t\t}\n+\n+\t\t/*\n+\t\t * vxlan ports : 4789 or 8472\n+\t\t */\n+\t\tif (tnlcfg.tun_type < 0 &&\n+\t\t\t\t(tnlcfg.d_port == 0xb512 || tnlcfg.d_port == 0x1821))\n+\t\t\ttnlcfg.tun_type = FLOW_ELEM_TYPE_VXLAN;\n+\n+\t\tif (!valid || tnlcfg.ipversion == 0 || tnlcfg.tun_type < 0 ||\n+\t\t\t\ttnlcfg.d_port == 0xffff) {\n+\t\t\tNT_LOG(DBG, FILTER, \"Invalid tunnel received\\n\");\n+\t\t\treturn NULL;\n+\t\t}\n+\n+\t\t/* search/add to DB */\n+\t\trtnl = tunnel_get(&tnlcfg, &tnlcfg_mask,\n+\t\t\t\t  vni ? 0 :\n+\t\t\t\t  1); /* if vni == NULL it is a tun set command */\n+\n+#ifdef FLOW_DEBUG\n+\t\tif (rtnl) {\n+\t\t\tif (vni)\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"MATCH A TUNNEL DEFINITION - PRESET \"\n+\t\t\t\t       \"(PREALLOC VPORT) IF NOT FOUND:\\n\");\n+\t\t\telse\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"SET A TUNNEL DEFINITION:\\n\");\n+\t\t\tstruct in_addr addr, mask;\n+\t\t\tchar buf[64];\n+\n+\t\t\taddr.s_addr = rtnl->cfg.v4.src_ip;\n+\t\t\tsprintf(buf, \"%s\", inet_ntoa(addr));\n+\t\t\tmask.s_addr = rtnl->cfg_mask.v4.src_ip;\n+\t\t\tNT_LOG(DBG, FILTER, \"    tun src IP: %s / %s\\n\", buf,\n+\t\t\t       inet_ntoa(mask));\n+\t\t\taddr.s_addr = rtnl->cfg.v4.dst_ip;\n+\t\t\tsprintf(buf, \"%s\", inet_ntoa(addr));\n+\t\t\tmask.s_addr = rtnl->cfg_mask.v4.dst_ip;\n+\t\t\tNT_LOG(DBG, FILTER, \"    tun dst IP: %s / %s\\n\", buf,\n+\t\t\t       inet_ntoa(mask));\n+\t\t\tNT_LOG(DBG, FILTER, \"    tun tp_src: %i / %04x\\n\",\n+\t\t\t       htons(rtnl->cfg.s_port),\n+\t\t\t       htons(rtnl->cfg_mask.s_port));\n+\t\t\tNT_LOG(DBG, FILTER, \"    tun tp_dst: %i / %04x\\n\",\n+\t\t\t       htons(rtnl->cfg.d_port),\n+\t\t\t       htons(rtnl->cfg_mask.d_port));\n+\t\t\tNT_LOG(DBG, FILTER, \"    tun ipver:  %i\\n\",\n+\t\t\t       rtnl->cfg.ipversion);\n+\t\t\tNT_LOG(DBG, FILTER, \"    tun flow_stat_id: %i\\n\",\n+\t\t\t       rtnl->flow_stat_id);\n+\t\t\tNT_LOG(DBG, FILTER, \"    tun vport:  %i\\n\",\n+\t\t\t       rtnl->vport);\n+\t\t\tNT_LOG(DBG, FILTER, \"    tun refcnt: %i\\n\",\n+\t\t\t       rtnl->refcnt);\n+\t\t}\n+#endif\n+\n+\t\t*idx = eidx; /* pointing to next or END */\n+\t}\n+\n+\treturn rtnl;\n+}\n+\n+uint8_t get_tunnel_vport(struct tunnel_s *rtnl)\n+{\n+\treturn rtnl->vport;\n+}\n+\n+void tunnel_set_flow_stat_id(struct tunnel_s *rtnl, uint32_t flow_stat_id)\n+{\n+\trtnl->flow_stat_id = flow_stat_id;\n+}\n+\n+int tunnel_get_definition(struct tunnel_cfg_s *tuncfg, uint32_t flow_stat_id,\n+\t\t\t  uint8_t vport)\n+{\n+\tstruct tunnel_s *tun = tunnels;\n+\n+\twhile (tun) {\n+\t\tif (tun->vport == vport && (flow_stat_id == tun->flow_stat_id ||\n+\t\t\t\t\t    flow_stat_id == (uint32_t)-1)) {\n+\t\t\tmemcpy(tuncfg, &tun->cfg, sizeof(struct tunnel_cfg_s));\n+\t\t\treturn 0;\n+\t\t}\n+\t\ttun = tun->next;\n+\t}\n+\n+\treturn -1;\n+}\n+\n+static be16_t ip_checksum_sum(const be16_t *data, unsigned int size,\n+\t\t\t      be16_t seed)\n+{\n+\tunsigned int sum = seed;\n+\tunsigned int idx;\n+\n+\tfor (idx = 0; idx < size / 2; idx++)\n+\t\tsum += (unsigned int)(data[idx]);\n+\tif (size & 1)\n+\t\tsum += (unsigned char)data[idx];\n+\t/* unfold */\n+\twhile (sum >> 16)\n+\t\tsum = (sum & 0xffff) + (sum >> 16);\n+\treturn (be16_t)sum;\n+}\n+\n+static void copy_unmasked(uint8_t *result, const struct flow_elem *elem,\n+\t\t\t  uint8_t size)\n+{\n+\tfor (uint8_t i = 0; i < size; i++)\n+\t\tresult[i] = ((const uint8_t *)elem->spec)[i];\n+}\n+\n+int flow_tunnel_create_vxlan_hdr(struct flow_api_backend_s *be,\n+\t\t\t\t struct nic_flow_def *fd,\n+\t\t\t\t const struct flow_elem *elem)\n+{\n+\tuint32_t eidx = 0;\n+\tuint8_t size;\n+\tstruct ipv4_hdr_s *tun_ipv4 = NULL;\n+\tuint16_t *tun_hdr_eth_type_p = NULL;\n+\n+\tif (elem) {\n+\t\twhile (elem[eidx].type != FLOW_ELEM_TYPE_END) {\n+\t\t\tswitch (elem[eidx].type) {\n+\t\t\tcase FLOW_ELEM_TYPE_ETH: {\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"Tunnel: RTE_FLOW_ITEM_TYPE_ETH\\n\");\n+\t\t\t\tstruct flow_elem_eth eth;\n+\n+\t\t\t\tsize = sizeof(struct flow_elem_eth);\n+\n+\t\t\t\tcopy_unmasked((uint8_t *)&eth, &elem[eidx],\n+\t\t\t\t\t      size);\n+\n+\t\t\t\tmemcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],\n+\t\t\t\t       &eth, size);\n+\n+\t\t\t\t/*\n+\t\t\t\t * Save a pointer to the tun header ethtype field\n+\t\t\t\t * (needed later in the IPv4 and IPv6 flow elem cases)\n+\t\t\t\t */\n+\t\t\t\ttun_hdr_eth_type_p =\n+\t\t\t\t\t(uint16_t *)&fd->tun_hdr.d\n+\t\t\t\t\t.hdr8[fd->tun_hdr.len + 12];\n+\n+#ifdef FLOW_DEBUG\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"dmac   : %02x:%02x:%02x:%02x:%02x:%02x\\n\",\n+\t\t\t\t       eth.d_addr.addr_b[0],\n+\t\t\t\t       eth.d_addr.addr_b[1],\n+\t\t\t\t       eth.d_addr.addr_b[2],\n+\t\t\t\t       eth.d_addr.addr_b[3],\n+\t\t\t\t       eth.d_addr.addr_b[5],\n+\t\t\t\t       eth.d_addr.addr_b[5]);\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"smac   : %02x:%02x:%02x:%02x:%02x:%02x\\n\",\n+\t\t\t\t       eth.s_addr.addr_b[0],\n+\t\t\t\t       eth.s_addr.addr_b[1],\n+\t\t\t\t       eth.s_addr.addr_b[2],\n+\t\t\t\t       eth.s_addr.addr_b[3],\n+\t\t\t\t       eth.s_addr.addr_b[5],\n+\t\t\t\t       eth.s_addr.addr_b[5]);\n+\t\t\t\tNT_LOG(DBG, FILTER, \"type   : %04x\\n\",\n+\t\t\t\t       ntohs(eth.ether_type));\n+#endif\n+\t\t\t\tfd->tun_hdr.len =\n+\t\t\t\t\t(uint8_t)(fd->tun_hdr.len + size);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t\t/* VLAN is not supported */\n+\n+\t\t\tcase FLOW_ELEM_TYPE_IPV4: {\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"Tunnel:  RTE_FLOW_ITEM_TYPE_IPV4\\n\");\n+\t\t\t\tstruct flow_elem_ipv4 ipv4;\n+\n+\t\t\t\tsize = sizeof(struct flow_elem_ipv4);\n+\n+\t\t\t\tcopy_unmasked((uint8_t *)&ipv4, &elem[eidx],\n+\t\t\t\t\t      size);\n+\n+\t\t\t\tif (ipv4.hdr.version_ihl != 0x45)\n+\t\t\t\t\tipv4.hdr.version_ihl = 0x45;\n+\n+\t\t\t\tif (ipv4.hdr.ttl == 0)\n+\t\t\t\t\tipv4.hdr.ttl = 64;\n+\n+\t\t\t\tif (ipv4.hdr.next_proto_id !=\n+\t\t\t\t\t\t17)   /* must be UDP */\n+\t\t\t\t\tipv4.hdr.next_proto_id = 17;\n+\n+\t\t\t\tipv4.hdr.frag_offset =\n+\t\t\t\t\thtons(1 << 14); /* DF flag */\n+\n+\t\t\t\tsize = sizeof(struct ipv4_hdr_s);\n+\t\t\t\tmemcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],\n+\t\t\t\t       &ipv4.hdr, size);\n+\n+\t\t\t\t/* Set the tun header ethtype field to IPv4 (if empty) */\n+\t\t\t\tif (tun_hdr_eth_type_p &&\n+\t\t\t\t\t\t(*tun_hdr_eth_type_p == 0)) {\n+\t\t\t\t\t*tun_hdr_eth_type_p =\n+\t\t\t\t\t\thtons(0x0800); /* IPv4 */\n+\t\t\t\t}\n+\n+\t\t\t\ttun_ipv4 = (struct ipv4_hdr_s *)&fd->tun_hdr.d\n+\t\t\t\t\t   .hdr8[fd->tun_hdr.len];\n+\n+\t\t\t\tNT_LOG(DBG, FILTER, \"v_ihl  : %02x\\n\",\n+\t\t\t\t       tun_ipv4->version_ihl);\n+\t\t\t\tNT_LOG(DBG, FILTER, \"tos    : %02x\\n\",\n+\t\t\t\t       tun_ipv4->tos);\n+\t\t\t\tNT_LOG(DBG, FILTER, \"len    : %d\\n\",\n+\t\t\t\t       ntohs(tun_ipv4->length));\n+\t\t\t\tNT_LOG(DBG, FILTER, \"id     : %02x\\n\",\n+\t\t\t\t       tun_ipv4->id);\n+\t\t\t\tNT_LOG(DBG, FILTER, \"fl/frg : %04x\\n\",\n+\t\t\t\t       ntohs(tun_ipv4->frag_offset));\n+\t\t\t\tNT_LOG(DBG, FILTER, \"ttl    : %02x\\n\",\n+\t\t\t\t       tun_ipv4->ttl);\n+\t\t\t\tNT_LOG(DBG, FILTER, \"prot   : %02x\\n\",\n+\t\t\t\t       tun_ipv4->next_proto_id);\n+\t\t\t\tNT_LOG(DBG, FILTER, \"chksum : %04x\\n\",\n+\t\t\t\t       ntohs(tun_ipv4->hdr_csum));\n+\t\t\t\tNT_LOG(DBG, FILTER, \"src    : %d.%d.%d.%d\\n\",\n+\t\t\t\t       (tun_ipv4->src_ip & 0xff),\n+\t\t\t\t       ((tun_ipv4->src_ip >> 8) & 0xff),\n+\t\t\t\t       ((tun_ipv4->src_ip >> 16) & 0xff),\n+\t\t\t\t       ((tun_ipv4->src_ip >> 24) & 0xff));\n+\t\t\t\tNT_LOG(DBG, FILTER, \"dst    : %d.%d.%d.%d\\n\",\n+\t\t\t\t       (tun_ipv4->dst_ip & 0xff),\n+\t\t\t\t       ((tun_ipv4->dst_ip >> 8) & 0xff),\n+\t\t\t\t       ((tun_ipv4->dst_ip >> 16) & 0xff),\n+\t\t\t\t       ((tun_ipv4->dst_ip >> 24) & 0xff));\n+\n+\t\t\t\tfd->tun_hdr.len =\n+\t\t\t\t\t(uint8_t)(fd->tun_hdr.len + size);\n+\t\t\t\tfd->tun_hdr.ip_version = 4;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t\tcase FLOW_ELEM_TYPE_IPV6: {\n+\t\t\t\tif (be->roa.ver < 6) {\n+\t\t\t\t\tNT_LOG(ERR, FILTER,\n+\t\t\t\t\t       \"Tunnel flow element type IPv6 requires ROA version 6 or higher (current version=%d)\\n\",\n+\t\t\t\t\t       be->roa.ver);\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"Tunnel:  RTE_FLOW_ITEM_TYPE_IPV6\\n\");\n+\t\t\t\tstruct flow_elem_ipv6 ipv6;\n+\n+\t\t\t\tsize = sizeof(struct flow_elem_ipv6);\n+\n+\t\t\t\tcopy_unmasked((uint8_t *)&ipv6, &elem[eidx],\n+\t\t\t\t\t      size);\n+\n+\t\t\t\t/*\n+\t\t\t\t * Make sure the version field (the 4 most significant bits of\n+\t\t\t\t * \"vtc_flow\") is set to 6\n+\t\t\t\t */\n+\t\t\t\tif ((ipv6.hdr.vtc_flow & htonl(0x60000000)) ==\n+\t\t\t\t\t\t0) {\n+\t\t\t\t\tipv6.hdr.vtc_flow |= htonl(0x60000000); /* Version = 6 */\n+\t\t\t\t}\n+\n+\t\t\t\tif (ipv6.hdr.proto != 17)   /* must be UDP */\n+\t\t\t\t\tipv6.hdr.proto = 17;\n+\n+\t\t\t\tif (ipv6.hdr.hop_limits == 0)\n+\t\t\t\t\tipv6.hdr.hop_limits = 64;\n+\n+\t\t\t\tsize = sizeof(struct ipv6_hdr_s);\n+\t\t\t\tmemcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],\n+\t\t\t\t       &ipv6.hdr, size);\n+\n+\t\t\t\t/* Set the tun header ethtype field to IPv6 (if empty) */\n+\t\t\t\tif (tun_hdr_eth_type_p &&\n+\t\t\t\t\t\t(*tun_hdr_eth_type_p == 0)) {\n+\t\t\t\t\t*tun_hdr_eth_type_p =\n+\t\t\t\t\t\thtons(0x86DD); /* IPv6 */\n+\t\t\t\t}\n+\n+\t\t\t\tNT_LOG(DBG, FILTER, \"vtc_flow    : %08x\\n\",\n+\t\t\t\t       ntohl(ipv6.hdr.vtc_flow));\n+\t\t\t\tNT_LOG(DBG, FILTER, \"payload_len : %04x\\n\",\n+\t\t\t\t       ntohs(ipv6.hdr.payload_len));\n+\t\t\t\tNT_LOG(DBG, FILTER, \"proto       : %02x\\n\",\n+\t\t\t\t       ipv6.hdr.proto);\n+\t\t\t\tNT_LOG(DBG, FILTER, \"hop_limits  : %02x\\n\",\n+\t\t\t\t       ipv6.hdr.hop_limits);\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"src         : %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\\n\",\n+\t\t\t\t       ipv6.hdr.src_addr[0],\n+\t\t\t\t       ipv6.hdr.src_addr[1],\n+\t\t\t\t       ipv6.hdr.src_addr[2],\n+\t\t\t\t       ipv6.hdr.src_addr[3],\n+\t\t\t\t       ipv6.hdr.src_addr[4],\n+\t\t\t\t       ipv6.hdr.src_addr[5],\n+\t\t\t\t       ipv6.hdr.src_addr[6],\n+\t\t\t\t       ipv6.hdr.src_addr[7],\n+\t\t\t\t       ipv6.hdr.src_addr[8],\n+\t\t\t\t       ipv6.hdr.src_addr[9],\n+\t\t\t\t       ipv6.hdr.src_addr[10],\n+\t\t\t\t       ipv6.hdr.src_addr[11],\n+\t\t\t\t       ipv6.hdr.src_addr[12],\n+\t\t\t\t       ipv6.hdr.src_addr[13],\n+\t\t\t\t       ipv6.hdr.src_addr[14],\n+\t\t\t\t       ipv6.hdr.src_addr[15]);\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"dst         : %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\\n\",\n+\t\t\t\t       ipv6.hdr.dst_addr[0],\n+\t\t\t\t       ipv6.hdr.dst_addr[1],\n+\t\t\t\t       ipv6.hdr.dst_addr[2],\n+\t\t\t\t       ipv6.hdr.dst_addr[3],\n+\t\t\t\t       ipv6.hdr.dst_addr[4],\n+\t\t\t\t       ipv6.hdr.dst_addr[5],\n+\t\t\t\t       ipv6.hdr.dst_addr[6],\n+\t\t\t\t       ipv6.hdr.dst_addr[7],\n+\t\t\t\t       ipv6.hdr.dst_addr[8],\n+\t\t\t\t       ipv6.hdr.dst_addr[9],\n+\t\t\t\t       ipv6.hdr.dst_addr[10],\n+\t\t\t\t       ipv6.hdr.dst_addr[11],\n+\t\t\t\t       ipv6.hdr.dst_addr[12],\n+\t\t\t\t       ipv6.hdr.dst_addr[13],\n+\t\t\t\t       ipv6.hdr.dst_addr[14],\n+\t\t\t\t       ipv6.hdr.dst_addr[15]);\n+\n+\t\t\t\tfd->tun_hdr.len =\n+\t\t\t\t\t(uint8_t)(fd->tun_hdr.len + size);\n+\t\t\t\tfd->tun_hdr.ip_version = 6;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t\tcase FLOW_ELEM_TYPE_UDP: {\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"Tunnel: RTE_FLOW_ITEM_TYPE_UDP\\n\");\n+\t\t\t\tstruct flow_elem_udp udp;\n+\n+\t\t\t\tsize = sizeof(struct flow_elem_udp);\n+\n+\t\t\t\tcopy_unmasked((uint8_t *)&udp, &elem[eidx],\n+\t\t\t\t\t      size);\n+\n+\t\t\t\tudp.hdr.cksum =\n+\t\t\t\t\t0; /* set always the UDP checksum to 0 */\n+\n+\t\t\t\tsize = sizeof(struct udp_hdr_s);\n+\t\t\t\tmemcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],\n+\t\t\t\t       &udp.hdr, size);\n+\n+\t\t\t\tNT_LOG(DBG, FILTER, \"src p  : %d\\n\",\n+\t\t\t\t       ntohs(udp.hdr.src_port));\n+\t\t\t\tNT_LOG(DBG, FILTER, \"dst p  : %d\\n\",\n+\t\t\t\t       ntohs(udp.hdr.dst_port));\n+\t\t\t\tNT_LOG(DBG, FILTER, \"len    : %d\\n\",\n+\t\t\t\t       ntohs(udp.hdr.len));\n+\t\t\t\tNT_LOG(DBG, FILTER, \"chksum : %04x\\n\",\n+\t\t\t\t       ntohs(udp.hdr.cksum));\n+\n+\t\t\t\tfd->tun_hdr.len =\n+\t\t\t\t\t(uint8_t)(fd->tun_hdr.len + size);\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t\tcase FLOW_ELEM_TYPE_VXLAN: {\n+\t\t\t\tstruct flow_elem_vxlan vxlan_m;\n+\n+\t\t\t\tsize = sizeof(struct flow_elem_vxlan);\n+\n+\t\t\t\tcopy_unmasked((uint8_t *)&vxlan_m, &elem[eidx],\n+\t\t\t\t\t      size);\n+\n+\t\t\t\tvxlan_m.flags =\n+\t\t\t\t\t0x08; /* set always I-flag - valid VNI */\n+\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"Tunnel: RTE_FLOW_ITEM_TYPE_VXLAN - vni %u\\n\",\n+\t\t\t\t       (vxlan_m.vni[0] << 16) +\n+\t\t\t\t       (vxlan_m.vni[1] << 8) +\n+\t\t\t\t       vxlan_m.vni[2]);\n+\n+\t\t\t\tmemcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],\n+\t\t\t\t       &vxlan_m, size);\n+\n+\t\t\t\tNT_LOG(DBG, FILTER, \"flags  : %02x\\n\",\n+\t\t\t\t       vxlan_m.flags);\n+\t\t\t\tNT_LOG(DBG, FILTER, \"vni    : %d\\n\",\n+\t\t\t\t       (vxlan_m.vni[0] << 16) +\n+\t\t\t\t       (vxlan_m.vni[1] << 8) +\n+\t\t\t\t       vxlan_m.vni[2]);\n+\n+\t\t\t\tfd->tun_hdr.len =\n+\t\t\t\t\t(uint8_t)(fd->tun_hdr.len + size);\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t\tcase FLOW_ELEM_TYPE_PORT_ID: {\n+\t\t\t\tconst struct flow_elem_port_id *port =\n+\t\t\t\t\t(const struct flow_elem_port_id *)\n+\t\t\t\t\telem[eidx]\n+\t\t\t\t\t.spec;\n+\t\t\t\tfd->tun_hdr.user_port_id = port->id;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t\tcase FLOW_ELEM_TYPE_VOID: {\n+\t\t\t\tNT_LOG(DBG, FILTER,\n+\t\t\t\t       \"Tunnel: RTE_FLOW_ITEM_TYPE_VOID (ignoring)\\n\");\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t\tdefault:\n+\t\t\t\tNT_LOG(INF, FILTER,\n+\t\t\t\t       \"unsupported Tunnel flow element type %u\\n\",\n+\t\t\t\t       elem[eidx].type);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\n+\t\t\teidx++;\n+\t\t}\n+\t}\n+\n+\tif (tun_ipv4) {\n+\t\ttun_ipv4->hdr_csum = 0;\n+\t\ttun_ipv4->length = 0;\n+\t\tfd->tun_hdr.ip_csum_precalc = ntohs(ip_checksum_sum((const be16_t *)&fd->tun_hdr.d\n+\t\t\t.hdr8[14],\n+\t\t\t(unsigned int)sizeof(struct ipv4_hdr_s),\n+\t\t\t(be16_t)htons((uint16_t)(fd->tun_hdr.len - sizeof(struct flow_elem_eth)))));\n+\n+\t\tNT_LOG(DBG, FILTER,\n+\t\t       \"chksum precalc: %04x, precalc hdr len %u\\n\",\n+\t\t       fd->tun_hdr.ip_csum_precalc,\n+\t\t       fd->tun_hdr.len - sizeof(struct flow_elem_eth));\n+\t}\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c\nnew file mode 100644\nindex 0000000000..5a62343718\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c\n@@ -0,0 +1,1789 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <string.h>\n+#include \"flow_api_backend.h\"\n+\n+#define _MOD_ \"CAT\"\n+#define _VER_ be->cat.ver\n+\n+static int hw_mod_cat_kce_flush(struct flow_api_backend_s *be,\n+\t\t\t\tenum km_flm_if_select_e if_num, int km_if_id,\n+\t\t\t\tint start_idx, int count);\n+static int hw_mod_cat_kcs_flush(struct flow_api_backend_s *be,\n+\t\t\t\tenum km_flm_if_select_e if_num, int km_if_id,\n+\t\t\t\tint start_idx, int count);\n+static int hw_mod_cat_fte_flush(struct flow_api_backend_s *be,\n+\t\t\t\tenum km_flm_if_select_e if_num, int km_if_id,\n+\t\t\t\tint start_idx, int count);\n+\n+bool hw_mod_cat_present(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->get_cat_present(be->be_dev);\n+}\n+\n+int hw_mod_cat_alloc(struct flow_api_backend_s *be)\n+{\n+\t_VER_ = be->iface->get_cat_version(be->be_dev);\n+\tNT_LOG(DBG, FILTER, \"CAT MODULE VERSION  %i.%i\\n\", VER_MAJOR(_VER_),\n+\t       VER_MINOR(_VER_));\n+\n+\tint nb = be->iface->get_nb_cat_funcs(be->be_dev);\n+\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"cat_funcs\", _MOD_, _VER_);\n+\tbe->cat.nb_cat_funcs = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_km_flow_types(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"km_flow_types\", _MOD_, _VER_);\n+\tbe->cat.nb_flow_types = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_pm_ext(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"pm_ext\", _MOD_, _VER_);\n+\tbe->cat.nb_pm_ext = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_len(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"len\", _MOD_, _VER_);\n+\tbe->cat.nb_len = (uint32_t)nb;\n+\n+\tnb = be->iface->get_kcc_size(be->be_dev);\n+\tif (nb < 0)\n+\t\treturn error_resource_count(__func__, \"kcc_size\", _MOD_, _VER_);\n+\tbe->cat.kcc_size = (uint32_t)nb;\n+\n+\tnb = be->iface->get_kcc_banks(be->be_dev);\n+\tif (nb < 0)\n+\t\treturn error_resource_count(__func__, \"kcc_banks\", _MOD_, _VER_);\n+\tbe->cat.kcc_banks = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_cat_km_if_cnt(be->be_dev);\n+\tif (nb < 0)\n+\t\treturn error_resource_count(__func__, \"km_if_count\", _MOD_, _VER_);\n+\tbe->cat.km_if_count = (uint32_t)nb;\n+\n+\tint idx = be->iface->get_nb_cat_km_if_m0(be->be_dev);\n+\n+\tbe->cat.km_if_m0 = idx;\n+\n+\tidx = be->iface->get_nb_cat_km_if_m1(be->be_dev);\n+\tbe->cat.km_if_m1 = idx;\n+\n+\tif (be->cat.kcc_banks)\n+\t\tbe->cat.kcc_records = be->cat.kcc_size / be->cat.kcc_banks;\n+\telse\n+\t\tbe->cat.kcc_records = 0;\n+\n+\tbe->cat.kcc_id_bit_size = 10;\n+\n+\tswitch (_VER_) {\n+\tcase 18:\n+\t\tbe->cat.cts_num = 11;\n+\t\tif (!callocate_mod(CAST_COMMON(&be->cat), 12,\n+\t\t\t&be->cat.v18.cfn,\n+\t\t\tbe->cat.nb_cat_funcs,\n+\t\t\tsizeof(struct cat_v18_cfn_s),\n+\t\t\t&be->cat.v18.kce,\n+\t\t\t(be->cat.nb_cat_funcs / 8),\n+\t\t\tsizeof(struct cat_v18_kce_s),\n+\t\t\t&be->cat.v18.kcs,\n+\t\t\tbe->cat.nb_cat_funcs,\n+\t\t\tsizeof(struct cat_v18_kcs_s),\n+\t\t\t&be->cat.v18.fte,\n+\t\t\t(be->cat.nb_cat_funcs / 8) * be->cat.nb_flow_types * 2,\n+\t\t\tsizeof(struct cat_v18_fte_s),\n+\t\t\t&be->cat.v18.cte,\n+\t\t\tbe->cat.nb_cat_funcs,\n+\t\t\tsizeof(struct cat_v18_cte_s),\n+\t\t\t&be->cat.v18.cts,\n+\t\t\tbe->cat.nb_cat_funcs * ((be->cat.cts_num + 1) / 2),\n+\t\t\tsizeof(struct cat_v18_cts_s),\n+\t\t\t&be->cat.v18.cot,\n+\t\t\tbe->max_categories,\n+\t\t\tsizeof(struct cat_v18_cot_s),\n+\t\t\t&be->cat.v18.cct,\n+\t\t\tbe->max_categories * 4,\n+\t\t\tsizeof(struct cat_v18_cct_s),\n+\t\t\t&be->cat.v18.exo,\n+\t\t\tbe->cat.nb_pm_ext,\n+\t\t\tsizeof(struct cat_v18_exo_s),\n+\t\t\t&be->cat.v18.rck,\n+\t\t\tbe->cat.nb_pm_ext * 64,\n+\t\t\tsizeof(struct cat_v18_rck_s),\n+\t\t\t&be->cat.v18.len,\n+\t\t\tbe->cat.nb_len,\n+\t\t\tsizeof(struct cat_v18_len_s),\n+\t\t\t&be->cat.v18.kcc_cam,\n+\t\t\tbe->cat.kcc_size,\n+\t\t\tsizeof(struct cat_v18_kcc_s)))\n+\t\t\treturn -1;\n+\n+\t\tbreak;\n+\t/* end case 18 */\n+\tcase 21:\n+\t\tbe->cat.cts_num = 11;\n+\t\tif (!callocate_mod(CAST_COMMON(&be->cat), 12,\n+\t\t\t&be->cat.v21.cfn,\n+\t\t\tbe->cat.nb_cat_funcs,\n+\t\t\tsizeof(struct cat_v21_cfn_s),\n+\t\t\t&be->cat.v21.kce,\n+\t\t\t(be->cat.nb_cat_funcs / 8),\n+\t\t\tsizeof(struct cat_v21_kce_s),\n+\t\t\t&be->cat.v21.kcs,\n+\t\t\tbe->cat.nb_cat_funcs,\n+\t\t\tsizeof(struct cat_v21_kcs_s),\n+\t\t\t&be->cat.v21.fte,\n+\t\t\t(be->cat.nb_cat_funcs / 8) * be->cat.nb_flow_types * 4,\n+\t\t\tsizeof(struct cat_v21_fte_s),\n+\t\t\t&be->cat.v21.cte,\n+\t\t\tbe->cat.nb_cat_funcs,\n+\t\t\tsizeof(struct cat_v18_cte_s),\n+\t\t\t&be->cat.v21.cts,\n+\t\t\tbe->cat.nb_cat_funcs * ((be->cat.cts_num + 1) / 2),\n+\t\t\tsizeof(struct cat_v18_cts_s),\n+\t\t\t&be->cat.v21.cot,\n+\t\t\tbe->max_categories,\n+\t\t\tsizeof(struct cat_v18_cot_s),\n+\t\t\t&be->cat.v21.cct,\n+\t\t\tbe->max_categories * 4,\n+\t\t\tsizeof(struct cat_v18_cct_s),\n+\t\t\t&be->cat.v21.exo,\n+\t\t\tbe->cat.nb_pm_ext,\n+\t\t\tsizeof(struct cat_v18_exo_s),\n+\t\t\t&be->cat.v21.rck,\n+\t\t\tbe->cat.nb_pm_ext * 64,\n+\t\t\tsizeof(struct cat_v18_rck_s),\n+\t\t\t&be->cat.v21.len,\n+\t\t\tbe->cat.nb_len,\n+\t\t\tsizeof(struct cat_v18_len_s),\n+\t\t\t&be->cat.v21.kcc_cam,\n+\t\t\tbe->cat.kcc_size,\n+\t\t\tsizeof(struct cat_v18_kcc_s)))\n+\t\t\treturn -1;\n+\n+\t\tbreak;\n+\t/* end case 21 */\n+\tcase 22:\n+\t\tbe->cat.cts_num = 12;\n+\t\tif (!callocate_mod(CAST_COMMON(&be->cat), 14,\n+\t\t\t&be->cat.v22.cfn,\n+\t\t\tbe->cat.nb_cat_funcs,\n+\t\t\tsizeof(struct cat_v21_cfn_s),\n+\t\t\t&be->cat.v22.kce,\n+\t\t\t(be->cat.nb_cat_funcs / 8),\n+\t\t\tsizeof(struct cat_v21_kce_s),\n+\t\t\t&be->cat.v22.kcs,\n+\t\t\tbe->cat.nb_cat_funcs,\n+\t\t\tsizeof(struct cat_v21_kcs_s),\n+\t\t\t&be->cat.v22.fte,\n+\t\t\t(be->cat.nb_cat_funcs / 8) * be->cat.nb_flow_types * 4,\n+\t\t\tsizeof(struct cat_v21_fte_s),\n+\t\t\t&be->cat.v22.cte,\n+\t\t\tbe->cat.nb_cat_funcs,\n+\t\t\tsizeof(struct cat_v22_cte_s),\n+\t\t\t&be->cat.v22.cts,\n+\t\t\tbe->cat.nb_cat_funcs * ((be->cat.cts_num + 1) / 2),\n+\t\t\tsizeof(struct cat_v18_cts_s),\n+\t\t\t&be->cat.v22.cot,\n+\t\t\tbe->max_categories,\n+\t\t\tsizeof(struct cat_v18_cot_s),\n+\t\t\t&be->cat.v22.cct,\n+\t\t\tbe->max_categories * 4,\n+\t\t\tsizeof(struct cat_v18_cct_s),\n+\t\t\t&be->cat.v22.exo,\n+\t\t\tbe->cat.nb_pm_ext,\n+\t\t\tsizeof(struct cat_v18_exo_s),\n+\t\t\t&be->cat.v22.rck,\n+\t\t\tbe->cat.nb_pm_ext * 64,\n+\t\t\tsizeof(struct cat_v18_rck_s),\n+\t\t\t&be->cat.v22.len,\n+\t\t\tbe->cat.nb_len,\n+\t\t\tsizeof(struct cat_v18_len_s),\n+\t\t\t&be->cat.v22.kcc_cam,\n+\t\t\tbe->cat.kcc_size,\n+\t\t\tsizeof(struct cat_v18_kcc_s),\n+\t\t\t&be->cat.v22.cce,\n+\t\t\t4,\n+\t\t\tsizeof(struct cat_v22_cce_s),\n+\t\t\t&be->cat.v22.ccs,\n+\t\t\t1024,\n+\t\t\tsizeof(struct cat_v22_ccs_s)))\n+\t\t\treturn -1;\n+\n+\t\tbreak;\n+\t/* end case 22 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void hw_mod_cat_free(struct flow_api_backend_s *be)\n+{\n+\tif (be->cat.base) {\n+\t\tfree(be->cat.base);\n+\t\tbe->cat.base = NULL;\n+\t}\n+}\n+\n+static int cfn_reset(struct flow_api_backend_s *be, int i)\n+{\n+\tint err = hw_mod_cat_cfn_set(be, HW_CAT_CFN_PRESET_ALL, i, 0, 0);\n+\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_ISL, i, 0,\n+\t\t\t   0xffffffff); /* accept both ISL or not ISL */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_CFP, i, 0,\n+\t\t\t   0xffffffff); /* accept both CFP or not CFP */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_MAC, i, 0,\n+\t\t\t   0xffffffff); /* accept all MACs */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_L2, i, 0,\n+\t\t\t   0xffffffff); /* accept all L2 prot */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_VNTAG, i, 0,\n+\t\t\t   0xffffffff); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_VLAN, i, 0,\n+\t\t\t   0xffffffff); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_MPLS, i, 0,\n+\t\t\t   0xffffffff); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_L3, i, 0,\n+\t\t\t   0xffffffff); /* accept all L3 prot */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_FRAG, i, 0,\n+\t\t\t   0xffffffff); /* accept all fragments */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_IP_PROT, i, 0,\n+\t\t\t   0xffffffff); /* IP prot check disabled */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_L4, i, 0,\n+\t\t\t   0xffffffff); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TUNNEL, i, 0,\n+\t\t\t   0xffffffff); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_L2, i, 0,\n+\t\t\t   0xffffffff); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_VLAN, i, 0,\n+\t\t\t   0xffffffff); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_MPLS, i, 0,\n+\t\t\t   0xffffffff); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_L3, i, 0,\n+\t\t\t   0xffffffff); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_FRAG, i, 0,\n+\t\t\t   0xffffffff); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_IP_PROT, i, 0,\n+\t\t\t   0xffffffff); /* inner IP prot check disabled */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_L4, i, 0,\n+\t\t\t   0xffffffff); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_CV, i, 0, 3); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_FCS, i, 0, 3); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TRUNC, i, 0,\n+\t\t\t   0xffffffff); /* accept all truncations */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_L3_CS, i, 0, 3); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_L4_CS, i, 0, 3); /* accept all */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_PM_OR_INV, i, 0, 1); /*  */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_LC_INV, i, 0, 1); /*  */\n+\thw_mod_cat_cfn_set(be, HW_CAT_CFN_KM0_OR, i, 0,\n+\t\t\t   0xffffffff); /* or all */\n+\tif (_VER_ >= 21) {\n+\t\thw_mod_cat_cfn_set(be, HW_CAT_CFN_KM1_OR, i, 0,\n+\t\t\t\t   0xffffffff); /* or all */\n+\t\thw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TNL_L3_CS, i, 0,\n+\t\t\t\t   0xffffffff); /* or all */\n+\t\thw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TNL_L4_CS, i, 0,\n+\t\t\t\t   0xffffffff); /* or all */\n+\t\thw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TTL_EXP, i, 0,\n+\t\t\t\t   0xffffffff); /* or all */\n+\t\thw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TNL_TTL_EXP, i, 0,\n+\t\t\t\t   0xffffffff); /* or all */\n+\t}\n+\treturn err;\n+}\n+\n+int hw_mod_cat_reset(struct flow_api_backend_s *be)\n+{\n+\t/* Zero entire cache area */\n+\tZERO_MOD_CACHE(&be->cat);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT CAT CFN\\n\");\n+\tif (hw_mod_cat_cfn_flush(be, 0, ALL_ENTRIES))\n+\t\treturn -1;\n+\n+\tif (_VER_ <= 18) {\n+\t\tNT_LOG(DBG, FILTER, \"INIT CAT KCE\\n\");\n+\t\tif (hw_mod_cat_kce_flush(be, KM_FLM_IF_FIRST, 0, 0,\n+\t\t\t\t\t ALL_ENTRIES))\n+\t\t\treturn -1;\n+\n+\t\tNT_LOG(DBG, FILTER, \"INIT CAT KCS\\n\");\n+\t\tif (hw_mod_cat_kcs_flush(be, KM_FLM_IF_FIRST, 0, 0,\n+\t\t\t\t\t ALL_ENTRIES))\n+\t\t\treturn -1;\n+\n+\t\tNT_LOG(DBG, FILTER, \"INIT CAT FTE\\n\");\n+\t\tif (hw_mod_cat_fte_flush(be, KM_FLM_IF_FIRST, 0, 0,\n+\t\t\t\t\t ALL_ENTRIES))\n+\t\t\treturn -1;\n+\t} else {\n+\t\tNT_LOG(DBG, FILTER, \"INIT CAT KCE 0\\n\");\n+\t\tif (hw_mod_cat_kce_flush(be, KM_FLM_IF_FIRST, be->cat.km_if_m0,\n+\t\t\t\t\t 0, ALL_ENTRIES))\n+\t\t\treturn -1;\n+\n+\t\tNT_LOG(DBG, FILTER, \"INIT CAT KCS 0\\n\");\n+\t\tif (hw_mod_cat_kcs_flush(be, KM_FLM_IF_FIRST, be->cat.km_if_m0,\n+\t\t\t\t\t 0, ALL_ENTRIES))\n+\t\t\treturn -1;\n+\n+\t\tNT_LOG(DBG, FILTER, \"INIT CAT FTE 0\\n\");\n+\t\tif (hw_mod_cat_fte_flush(be, KM_FLM_IF_FIRST, be->cat.km_if_m0,\n+\t\t\t\t\t 0, ALL_ENTRIES))\n+\t\t\treturn -1;\n+\n+\t\tif (be->cat.km_if_count > 1) {\n+\t\t\tNT_LOG(DBG, FILTER, \"INIT CAT KCE 1\\n\");\n+\t\t\tif (hw_mod_cat_kce_flush(be, KM_FLM_IF_SECOND,\n+\t\t\t\t\t\t be->cat.km_if_m1, 0,\n+\t\t\t\t\t\t ALL_ENTRIES))\n+\t\t\t\treturn -1;\n+\n+\t\t\tNT_LOG(DBG, FILTER, \"INIT CAT KCS 1\\n\");\n+\t\t\tif (hw_mod_cat_kcs_flush(be, KM_FLM_IF_SECOND,\n+\t\t\t\t\t\t be->cat.km_if_m1, 0,\n+\t\t\t\t\t\t ALL_ENTRIES))\n+\t\t\t\treturn -1;\n+\n+\t\t\tNT_LOG(DBG, FILTER, \"INIT CAT FTE 1\\n\");\n+\t\t\tif (hw_mod_cat_fte_flush(be, KM_FLM_IF_SECOND,\n+\t\t\t\t\t\t be->cat.km_if_m1, 0,\n+\t\t\t\t\t\t ALL_ENTRIES))\n+\t\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\tNT_LOG(DBG, FILTER, \"INIT CAT CTE\\n\");\n+\tif (hw_mod_cat_cte_flush(be, 0, ALL_ENTRIES))\n+\t\treturn -1;\n+\n+\tNT_LOG(DBG, FILTER, \"INIT CAT CTS\\n\");\n+\tif (hw_mod_cat_cts_flush(be, 0, ALL_ENTRIES))\n+\t\treturn -1;\n+\n+\tNT_LOG(DBG, FILTER, \"INIT CAT COT\\n\");\n+\tif (hw_mod_cat_cot_flush(be, 0, ALL_ENTRIES))\n+\t\treturn -1;\n+\n+\tNT_LOG(DBG, FILTER, \"INIT CAT CCT\\n\");\n+\tif (hw_mod_cat_cct_flush(be, 0, ALL_ENTRIES))\n+\t\treturn -1;\n+\n+\tNT_LOG(DBG, FILTER, \"INIT CAT EXO\\n\");\n+\tif (hw_mod_cat_exo_flush(be, 0, ALL_ENTRIES))\n+\t\treturn -1;\n+\n+\tNT_LOG(DBG, FILTER, \"INIT CAT RCK\\n\");\n+\tif (hw_mod_cat_rck_flush(be, 0, ALL_ENTRIES))\n+\t\treturn -1;\n+\n+\tNT_LOG(DBG, FILTER, \"INIT CAT LEN\\n\");\n+\tif (hw_mod_cat_len_flush(be, 0, ALL_ENTRIES))\n+\t\treturn -1;\n+\n+\tif (be->cat.kcc_size) {\n+\t\tNT_LOG(DBG, FILTER, \"INIT CAT KCC\\n\");\n+\t\tif (hw_mod_cat_kcc_flush(be, 0, ALL_ENTRIES))\n+\t\t\treturn -1;\n+\t}\n+\n+\tif (_VER_ > 21) {\n+\t\tNT_LOG(DBG, FILTER, \"INIT CAT CCE\\n\");\n+\t\tif (hw_mod_cat_cce_flush(be, 0, ALL_ENTRIES))\n+\t\t\treturn -1;\n+\t\tNT_LOG(DBG, FILTER, \"INIT CAT CCS\\n\");\n+\t\tif (hw_mod_cat_ccs_flush(be, 0, ALL_ENTRIES))\n+\t\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_cfn_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tswitch (count) {\n+\tcase ALL_ENTRIES:\n+\t\tif (start_idx != 0)\n+\t\t\treturn error_index_too_large(__func__);\n+\t\treturn be->iface->cat_cfn_flush(be->be_dev, &be->cat, start_idx,\n+\t\t\t\t\t\tbe->cat.nb_cat_funcs);\n+\n+\tdefault:\n+\t\tif ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs)\n+\t\t\treturn error_index_too_large(__func__);\n+\t\treturn be->iface->cat_cfn_flush(be->be_dev, &be->cat, start_idx,\n+\t\t\t\t\t\tcount);\n+\t}\n+}\n+\n+static int hw_mod_cat_cfn_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field, int index, int word_off,\n+\t\t\t      uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif ((unsigned int)index >= be->cat.nb_cat_funcs)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 18:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_CFN_SET_ALL_DEFAULTS:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\treturn cfn_reset(be, index);\n+\t\tcase HW_CAT_CFN_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->cat.v18.cfn[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct cat_v18_cfn_s));\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_COMPARE:\n+\t\t\trv = do_compare_indexes(be->cat.v18.cfn,\n+\t\t\t\tsizeof(struct cat_v18_cfn_s), index, word_off,\n+\t\t\t\tbe->cat.nb_cat_funcs, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_FIND:\n+\t\t\trv = find_equal_index(be->cat.v18.cfn,\n+\t\t\t\tsizeof(struct cat_v18_cfn_s), index, word_off,\n+\t\t\t\tbe->cat.nb_cat_funcs, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ENABLE:\n+\t\t\tget_set(&be->cat.v18.cfn[index].enable, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_INV:\n+\t\t\tget_set(&be->cat.v18.cfn[index].inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_INV:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_ISL:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_isl, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_CFP:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_cfp, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_MAC:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_mac, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_L2:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_l2, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_VNTAG:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_vntag, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_VLAN:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_vlan, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_MPLS:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_mpls, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_L3:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_l3, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_FRAG:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_frag, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_IP_PROT:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_ip_prot, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_L4:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_l4, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TUNNEL:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_tunnel, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_L2:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_tnl_l2, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_VLAN:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_tnl_vlan, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_MPLS:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_tnl_mpls, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_L3:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_tnl_l3, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_FRAG:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_tnl_frag, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_IP_PROT:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_tnl_ip_prot, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_L4:\n+\t\t\tget_set(&be->cat.v18.cfn[index].ptc_tnl_l4, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_INV:\n+\t\t\tget_set(&be->cat.v18.cfn[index].err_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_CV:\n+\t\t\tget_set(&be->cat.v18.cfn[index].err_cv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_FCS:\n+\t\t\tget_set(&be->cat.v18.cfn[index].err_fcs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_TRUNC:\n+\t\t\tget_set(&be->cat.v18.cfn[index].err_trunc, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_L3_CS:\n+\t\t\tget_set(&be->cat.v18.cfn[index].err_l3_cs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_L4_CS:\n+\t\t\tget_set(&be->cat.v18.cfn[index].err_l4_cs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_MAC_PORT:\n+\t\t\tget_set(&be->cat.v18.cfn[index].mac_port, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_CMP:\n+\t\t\tif (word_off > 1)\n+\t\t\t\treturn error_word_off_too_large(__func__);\n+\t\t\tget_set(&be->cat.v18.cfn[index].pm_cmp[word_off], value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_DCT:\n+\t\t\tget_set(&be->cat.v18.cfn[index].pm_dct, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_EXT_INV:\n+\t\t\tget_set(&be->cat.v18.cfn[index].pm_ext_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_CMB:\n+\t\t\tget_set(&be->cat.v18.cfn[index].pm_cmb, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_AND_INV:\n+\t\t\tget_set(&be->cat.v18.cfn[index].pm_and_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_OR_INV:\n+\t\t\tget_set(&be->cat.v18.cfn[index].pm_or_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_INV:\n+\t\t\tget_set(&be->cat.v18.cfn[index].pm_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_LC:\n+\t\t\tget_set(&be->cat.v18.cfn[index].lc, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_LC_INV:\n+\t\t\tget_set(&be->cat.v18.cfn[index].lc_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_KM0_OR:\n+\t\t\tget_set(&be->cat.v18.cfn[index].km_or, value, get);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 18 */\n+\tcase 21:\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_CFN_SET_ALL_DEFAULTS:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\treturn cfn_reset(be, index);\n+\t\tcase HW_CAT_CFN_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->cat.v21.cfn[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct cat_v21_cfn_s));\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_COMPARE:\n+\t\t\trv = do_compare_indexes(be->cat.v21.cfn,\n+\t\t\t\tsizeof(struct cat_v21_cfn_s), index, word_off,\n+\t\t\t\tbe->cat.nb_cat_funcs, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_FIND:\n+\t\t\trv = find_equal_index(be->cat.v21.cfn,\n+\t\t\t\tsizeof(struct cat_v21_cfn_s), index, word_off,\n+\t\t\t\tbe->cat.nb_cat_funcs, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_COPY_FROM:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemcpy(&be->cat.v21.cfn[index],\n+\t\t\t       &be->cat.v21.cfn[*value],\n+\t\t\t       sizeof(struct cat_v21_cfn_s));\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ENABLE:\n+\t\t\tget_set(&be->cat.v21.cfn[index].enable, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_INV:\n+\t\t\tget_set(&be->cat.v21.cfn[index].inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_INV:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_ISL:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_isl, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_CFP:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_cfp, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_MAC:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_mac, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_L2:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_l2, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_VNTAG:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_vntag, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_VLAN:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_vlan, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_MPLS:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_mpls, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_L3:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_l3, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_FRAG:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_frag, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_IP_PROT:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_ip_prot, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_L4:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_l4, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TUNNEL:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_tunnel, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_L2:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_tnl_l2, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_VLAN:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_tnl_vlan, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_MPLS:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_tnl_mpls, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_L3:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_tnl_l3, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_FRAG:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_tnl_frag, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_IP_PROT:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_tnl_ip_prot, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PTC_TNL_L4:\n+\t\t\tget_set(&be->cat.v21.cfn[index].ptc_tnl_l4, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_INV:\n+\t\t\tget_set(&be->cat.v21.cfn[index].err_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_CV:\n+\t\t\tget_set(&be->cat.v21.cfn[index].err_cv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_FCS:\n+\t\t\tget_set(&be->cat.v21.cfn[index].err_fcs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_TRUNC:\n+\t\t\tget_set(&be->cat.v21.cfn[index].err_trunc, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_L3_CS:\n+\t\t\tget_set(&be->cat.v21.cfn[index].err_l3_cs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_L4_CS:\n+\t\t\tget_set(&be->cat.v21.cfn[index].err_l4_cs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_TNL_L3_CS:\n+\t\t\tget_set(&be->cat.v21.cfn[index].err_tnl_l3_cs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_TNL_L4_CS:\n+\t\t\tget_set(&be->cat.v21.cfn[index].err_tnl_l4_cs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_TTL_EXP:\n+\t\t\tget_set(&be->cat.v21.cfn[index].err_ttl_exp, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_ERR_TNL_TTL_EXP:\n+\t\t\tget_set(&be->cat.v21.cfn[index].err_tnl_ttl_exp, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_MAC_PORT:\n+\t\t\tget_set(&be->cat.v21.cfn[index].mac_port, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_CMP:\n+\t\t\tif (word_off > 1)\n+\t\t\t\treturn error_word_off_too_large(__func__);\n+\t\t\tget_set(&be->cat.v21.cfn[index].pm_cmp[word_off], value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_DCT:\n+\t\t\tget_set(&be->cat.v21.cfn[index].pm_dct, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_EXT_INV:\n+\t\t\tget_set(&be->cat.v21.cfn[index].pm_ext_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_CMB:\n+\t\t\tget_set(&be->cat.v21.cfn[index].pm_cmb, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_AND_INV:\n+\t\t\tget_set(&be->cat.v21.cfn[index].pm_and_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_OR_INV:\n+\t\t\tget_set(&be->cat.v21.cfn[index].pm_or_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_PM_INV:\n+\t\t\tget_set(&be->cat.v21.cfn[index].pm_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_LC:\n+\t\t\tget_set(&be->cat.v21.cfn[index].lc, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_LC_INV:\n+\t\t\tget_set(&be->cat.v21.cfn[index].lc_inv, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_KM0_OR:\n+\t\t\tget_set(&be->cat.v21.cfn[index].km0_or, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CFN_KM1_OR:\n+\t\t\tget_set(&be->cat.v21.cfn[index].km1_or, value, get);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 21/22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_cfn_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, int word_off, uint32_t value)\n+{\n+\treturn hw_mod_cat_cfn_mod(be, field, index, word_off, &value, 0);\n+}\n+\n+int hw_mod_cat_cfn_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, int word_off, uint32_t *value)\n+{\n+\treturn hw_mod_cat_cfn_mod(be, field, index, word_off, value, 1);\n+}\n+\n+static inline int\n+find_km_flm_module_interface_index(struct flow_api_backend_s *be,\n+\t\t\t\t   enum km_flm_if_select_e if_num, int km_if_id)\n+{\n+\tint km_if_idx;\n+\n+\tif (_VER_ == 18) {\n+\t\tkm_if_idx = 0;\n+\t} else {\n+\t\tif (if_num == KM_FLM_IF_SECOND) {\n+\t\t\tif (be->cat.km_if_m1 == km_if_id)\n+\t\t\t\tkm_if_idx = 1;\n+\t\t\telse\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t} else {\n+\t\t\tif (be->cat.km_if_m0 == km_if_id)\n+\t\t\t\tkm_if_idx = 0;\n+\t\t\telse if (be->cat.km_if_m1 == km_if_id)\n+\t\t\t\tkm_if_idx = 1;\n+\t\t\telse\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t}\n+\treturn km_if_idx;\n+}\n+\n+/*\n+ * KCE\n+ */\n+\n+static int hw_mod_cat_kce_flush(struct flow_api_backend_s *be,\n+\t\t\t\tenum km_flm_if_select_e if_num, int km_if_id,\n+\t\t\t\tint start_idx, int count)\n+{\n+\t/* writes 8 bits - one for each cfn - at a time */\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->cat.nb_cat_funcs / 8;\n+\tif ((unsigned int)(start_idx + count) > (be->cat.nb_cat_funcs / 8))\n+\t\treturn error_index_too_large(__func__);\n+\t/* find KM module */\n+\tint km_if_idx;\n+\n+\tkm_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);\n+\tif (km_if_idx < 0)\n+\t\treturn km_if_idx;\n+\n+\treturn be->iface->cat_kce_flush(be->be_dev, &be->cat, km_if_idx,\n+\t\t\t\t\tstart_idx, count);\n+}\n+\n+int hw_mod_cat_kce_km_flush(struct flow_api_backend_s *be,\n+\t\t\t    enum km_flm_if_select_e if_num, int start_idx,\n+\t\t\t    int count)\n+{\n+\treturn hw_mod_cat_kce_flush(be, if_num, 0, start_idx, count);\n+}\n+\n+int hw_mod_cat_kce_flm_flush(struct flow_api_backend_s *be,\n+\t\t\t     enum km_flm_if_select_e if_num, int start_idx,\n+\t\t\t     int count)\n+{\n+\treturn hw_mod_cat_kce_flush(be, if_num, 1, start_idx, count);\n+}\n+\n+static int hw_mod_cat_kce_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field,\n+\t\t\t      enum km_flm_if_select_e if_num, int km_if_id,\n+\t\t\t      int index, uint32_t *value, int get)\n+{\n+\tif ((unsigned int)index >= (be->cat.nb_cat_funcs / 8))\n+\t\treturn error_index_too_large(__func__);\n+\n+\t/* find KM module */\n+\tint km_if_idx;\n+\n+\tkm_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);\n+\tif (km_if_idx < 0)\n+\t\treturn km_if_idx;\n+\n+\tswitch (_VER_) {\n+\tcase 18:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_KCE_ENABLE_BM:\n+\t\t\tget_set(&be->cat.v18.kce[index].enable_bm, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 18 */\n+\tcase 21:\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_KCE_ENABLE_BM:\n+\t\t\tget_set(&be->cat.v21.kce[index].enable_bm[km_if_idx],\n+\t\t\t\tvalue, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 21/22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_kce_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t  enum km_flm_if_select_e if_num, int index,\n+\t\t\t  uint32_t value)\n+{\n+\treturn hw_mod_cat_kce_mod(be, field, if_num, 0, index, &value, 0);\n+}\n+\n+int hw_mod_cat_kce_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t  enum km_flm_if_select_e if_num, int index,\n+\t\t\t  uint32_t *value)\n+{\n+\treturn hw_mod_cat_kce_mod(be, field, if_num, 0, index, value, 1);\n+}\n+\n+int hw_mod_cat_kce_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t   enum km_flm_if_select_e if_num, int index,\n+\t\t\t   uint32_t value)\n+{\n+\treturn hw_mod_cat_kce_mod(be, field, if_num, 1, index, &value, 0);\n+}\n+\n+int hw_mod_cat_kce_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t   enum km_flm_if_select_e if_num, int index,\n+\t\t\t   uint32_t *value)\n+{\n+\treturn hw_mod_cat_kce_mod(be, field, if_num, 1, index, value, 1);\n+}\n+\n+/*\n+ * KCS\n+ */\n+static int hw_mod_cat_kcs_flush(struct flow_api_backend_s *be,\n+\t\t\t\tenum km_flm_if_select_e if_num, int km_if_id,\n+\t\t\t\tint start_idx, int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->cat.nb_cat_funcs;\n+\tif ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs)\n+\t\treturn error_index_too_large(__func__);\n+\n+\t/* find KM module */\n+\tint km_if_idx;\n+\n+\tkm_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);\n+\tif (km_if_idx < 0)\n+\t\treturn km_if_idx;\n+\n+\treturn be->iface->cat_kcs_flush(be->be_dev, &be->cat, km_if_idx,\n+\t\t\t\t\tstart_idx, count);\n+}\n+\n+int hw_mod_cat_kcs_km_flush(struct flow_api_backend_s *be,\n+\t\t\t    enum km_flm_if_select_e if_num, int start_idx,\n+\t\t\t    int count)\n+{\n+\treturn hw_mod_cat_kcs_flush(be, if_num, 0, start_idx, count);\n+}\n+\n+int hw_mod_cat_kcs_flm_flush(struct flow_api_backend_s *be,\n+\t\t\t     enum km_flm_if_select_e if_num, int start_idx,\n+\t\t\t     int count)\n+{\n+\treturn hw_mod_cat_kcs_flush(be, if_num, 1, start_idx, count);\n+}\n+\n+static int hw_mod_cat_kcs_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field,\n+\t\t\t      enum km_flm_if_select_e if_num, int km_if_id,\n+\t\t\t      int index, uint32_t *value, int get)\n+{\n+\tif ((unsigned int)index >= be->cat.nb_cat_funcs)\n+\t\treturn error_index_too_large(__func__);\n+\t/* find KM module */\n+\tint km_if_idx;\n+\n+\tkm_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);\n+\tif (km_if_idx < 0)\n+\t\treturn km_if_idx;\n+\n+\tswitch (_VER_) {\n+\tcase 18:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_KCS_CATEGORY:\n+\t\t\tget_set(&be->cat.v18.kcs[index].category, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 18 */\n+\tcase 21:\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_KCS_CATEGORY:\n+\t\t\tget_set(&be->cat.v21.kcs[index].category[km_if_idx],\n+\t\t\t\tvalue, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 21/22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_kcs_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t  enum km_flm_if_select_e if_num, int index,\n+\t\t\t  uint32_t value)\n+{\n+\treturn hw_mod_cat_kcs_mod(be, field, if_num, 0, index, &value, 0);\n+}\n+\n+int hw_mod_cat_kcs_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t  enum km_flm_if_select_e if_num, int index,\n+\t\t\t  uint32_t *value)\n+{\n+\treturn hw_mod_cat_kcs_mod(be, field, if_num, 0, index, value, 1);\n+}\n+\n+int hw_mod_cat_kcs_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t   enum km_flm_if_select_e if_num, int index,\n+\t\t\t   uint32_t value)\n+{\n+\treturn hw_mod_cat_kcs_mod(be, field, if_num, 1, index, &value, 0);\n+}\n+\n+int hw_mod_cat_kcs_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t   enum km_flm_if_select_e if_num, int index,\n+\t\t\t   uint32_t *value)\n+{\n+\treturn hw_mod_cat_kcs_mod(be, field, if_num, 1, index, value, 1);\n+}\n+\n+/*\n+ * FTE\n+ */\n+static int hw_mod_cat_fte_flush(struct flow_api_backend_s *be,\n+\t\t\t\tenum km_flm_if_select_e if_num, int km_if_id,\n+\t\t\t\tint start_idx, int count)\n+{\n+\tconst uint32_t key_cnt = (_VER_ >= 20) ? 4 : 2;\n+\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->cat.nb_cat_funcs / 8 * be->cat.nb_flow_types *\n+\t\t\tkey_cnt;\n+\tif ((unsigned int)(start_idx + count) >\n+\t\t\t(be->cat.nb_cat_funcs / 8 * be->cat.nb_flow_types * key_cnt))\n+\t\treturn error_index_too_large(__func__);\n+\n+\t/* find KM module */\n+\tint km_if_idx;\n+\n+\tkm_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);\n+\tif (km_if_idx < 0)\n+\t\treturn km_if_idx;\n+\n+\treturn be->iface->cat_fte_flush(be->be_dev, &be->cat, km_if_idx,\n+\t\t\t\t\tstart_idx, count);\n+}\n+\n+int hw_mod_cat_fte_km_flush(struct flow_api_backend_s *be,\n+\t\t\t    enum km_flm_if_select_e if_num, int start_idx,\n+\t\t\t    int count)\n+{\n+\treturn hw_mod_cat_fte_flush(be, if_num, 0, start_idx, count);\n+}\n+\n+int hw_mod_cat_fte_flm_flush(struct flow_api_backend_s *be,\n+\t\t\t     enum km_flm_if_select_e if_num, int start_idx,\n+\t\t\t     int count)\n+{\n+\treturn hw_mod_cat_fte_flush(be, if_num, 1, start_idx, count);\n+}\n+\n+static int hw_mod_cat_fte_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field,\n+\t\t\t      enum km_flm_if_select_e if_num, int km_if_id,\n+\t\t\t      int index, uint32_t *value, int get)\n+{\n+\tconst uint32_t key_cnt = (_VER_ >= 20) ? 4 : 2;\n+\n+\tif ((unsigned int)index >=\n+\t\t\t(be->cat.nb_cat_funcs / 8 * be->cat.nb_flow_types * key_cnt))\n+\t\treturn error_index_too_large(__func__);\n+\t/* find KM module */\n+\tint km_if_idx;\n+\n+\tkm_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);\n+\tif (km_if_idx < 0)\n+\t\treturn km_if_idx;\n+\n+\tswitch (_VER_) {\n+\tcase 18:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_FTE_ENABLE_BM:\n+\t\t\tget_set(&be->cat.v18.fte[index].enable_bm, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 18 */\n+\tcase 21:\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_FTE_ENABLE_BM:\n+\t\t\tget_set(&be->cat.v21.fte[index].enable_bm[km_if_idx],\n+\t\t\t\tvalue, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 21/22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_fte_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t  enum km_flm_if_select_e if_num, int index,\n+\t\t\t  uint32_t value)\n+{\n+\treturn hw_mod_cat_fte_mod(be, field, if_num, 0, index, &value, 0);\n+}\n+\n+int hw_mod_cat_fte_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t  enum km_flm_if_select_e if_num, int index,\n+\t\t\t  uint32_t *value)\n+{\n+\treturn hw_mod_cat_fte_mod(be, field, if_num, 0, index, value, 1);\n+}\n+\n+int hw_mod_cat_fte_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t   enum km_flm_if_select_e if_num, int index,\n+\t\t\t   uint32_t value)\n+{\n+\treturn hw_mod_cat_fte_mod(be, field, if_num, 1, index, &value, 0);\n+}\n+\n+int hw_mod_cat_fte_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t\t   enum km_flm_if_select_e if_num, int index,\n+\t\t\t   uint32_t *value)\n+{\n+\treturn hw_mod_cat_fte_mod(be, field, if_num, 1, index, value, 1);\n+}\n+\n+int hw_mod_cat_cte_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->cat.nb_cat_funcs;\n+\tif ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->cat_cte_flush(be->be_dev, &be->cat, start_idx, count);\n+}\n+\n+static int hw_mod_cat_cte_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field, int index, uint32_t *value,\n+\t\t\t      int get)\n+{\n+\tif ((unsigned int)index >= be->cat.nb_cat_funcs)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 18:\n+\tcase 21:\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_CTE_ENABLE_BM:\n+\t\t\tget_set(&be->cat.v18.cte[index].enable_bm, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 18/21/22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_cte_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value)\n+{\n+\treturn hw_mod_cat_cte_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_cat_cte_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value)\n+{\n+\treturn hw_mod_cat_cte_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_cat_cts_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tint addr_size = (_VER_ < 15) ? 8 : ((be->cat.cts_num + 1) / 2);\n+\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->cat.nb_cat_funcs * addr_size;\n+\tif ((unsigned int)(start_idx + count) >\n+\t\t\t(be->cat.nb_cat_funcs * addr_size))\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->cat_cts_flush(be->be_dev, &be->cat, start_idx, count);\n+}\n+\n+static int hw_mod_cat_cts_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field, int index, uint32_t *value,\n+\t\t\t      int get)\n+{\n+\tint addr_size = (be->cat.cts_num + 1) / 2;\n+\n+\tif ((unsigned int)index >= (be->cat.nb_cat_funcs * addr_size))\n+\t\treturn error_index_too_large(__func__);\n+\n+\tswitch (_VER_) {\n+\tcase 18:\n+\tcase 21:\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_CTS_CAT_A:\n+\t\t\tget_set(&be->cat.v18.cts[index].cat_a, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CTS_CAT_B:\n+\t\t\tget_set(&be->cat.v18.cts[index].cat_b, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 18/21/22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_cts_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value)\n+{\n+\treturn hw_mod_cat_cts_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_cat_cts_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value)\n+{\n+\treturn hw_mod_cat_cts_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_cat_cot_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->max_categories;\n+\tif ((unsigned int)(start_idx + count) > be->max_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->cat_cot_flush(be->be_dev, &be->cat, start_idx, count);\n+}\n+\n+static int hw_mod_cat_cot_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field, int index, uint32_t *value,\n+\t\t\t      int get)\n+{\n+\tint rv = 0;\n+\tif ((unsigned int)index >= be->max_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 18:\n+\tcase 21:\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_COT_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->cat.v18.cot[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct cat_v18_cot_s));\n+\t\t\tbreak;\n+\t\tcase HW_CAT_COT_COMPARE:\n+\t\t\trv = do_compare_indexes(be->cat.v18.cot,\n+\t\t\t\tsizeof(struct cat_v18_cot_s), index, *value,\n+\t\t\t\tbe->max_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_CAT_COT_FIND:\n+\t\t\trv = find_equal_index(be->cat.v18.cot,\n+\t\t\t\tsizeof(struct cat_v18_cot_s), index, *value,\n+\t\t\t\tbe->max_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_CAT_COT_COLOR:\n+\t\t\tget_set(&be->cat.v18.cot[index].color, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_COT_KM:\n+\t\t\tget_set(&be->cat.v18.cot[index].km, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 18/21/22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_cot_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value)\n+{\n+\treturn hw_mod_cat_cot_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_cat_cot_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value)\n+{\n+\treturn hw_mod_cat_cot_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_cat_cct_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->cat.nb_cat_funcs * 4;\n+\tif ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs * 4)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->cat_cct_flush(be->be_dev, &be->cat, start_idx, count);\n+}\n+\n+static int hw_mod_cat_cct_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field, int index, uint32_t *value,\n+\t\t\t      int get)\n+{\n+\tif ((unsigned int)index >= be->cat.nb_cat_funcs * 4)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 18:\n+\tcase 21:\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_CCT_COLOR:\n+\t\t\tget_set(&be->cat.v18.cct[index].color, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCT_KM:\n+\t\t\tget_set(&be->cat.v18.cct[index].km, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 18/21/22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_cct_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value)\n+{\n+\treturn hw_mod_cat_cct_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_cat_cct_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value)\n+{\n+\treturn hw_mod_cat_cct_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_cat_kcc_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->cat.kcc_size;\n+\tif ((unsigned int)(start_idx + count) > be->cat.kcc_size)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->cat_kcc_flush(be->be_dev, &be->cat, start_idx, count);\n+}\n+\n+static int hw_mod_cat_kcc_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field, int index, int word_off,\n+\t\t\t      uint32_t *value, int get)\n+{\n+\tif ((unsigned int)index >= be->cat.kcc_size)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 18:\n+\tcase 21:\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_KCC_KEY:\n+\t\t\tif (word_off > 1)\n+\t\t\t\treturn error_word_off_too_large(__func__);\n+\t\t\tget_set(&be->cat.v18.kcc_cam[index].key[word_off], value,\n+\t\t\t\tget);\n+\t\t\tbreak;\n+\n+\t\tcase HW_CAT_KCC_CATEGORY:\n+\t\t\tget_set(&be->cat.v18.kcc_cam[index].category, value, get);\n+\t\t\tbreak;\n+\n+\t\tcase HW_CAT_KCC_ID:\n+\t\t\tget_set(&be->cat.v18.kcc_cam[index].id, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 18/21/22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_kcc_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, int word_off, uint32_t value)\n+{\n+\treturn hw_mod_cat_kcc_mod(be, field, index, word_off, &value, 0);\n+}\n+\n+int hw_mod_cat_kcc_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, int word_off, uint32_t *value)\n+{\n+\treturn hw_mod_cat_kcc_mod(be, field, index, word_off, value, 1);\n+}\n+\n+int hw_mod_cat_exo_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->cat.nb_pm_ext;\n+\tif ((unsigned int)(start_idx + count) > be->cat.nb_pm_ext)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->cat_exo_flush(be->be_dev, &be->cat, start_idx, count);\n+}\n+\n+static int hw_mod_cat_exo_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field, int index, uint32_t *value,\n+\t\t\t      int get)\n+{\n+\tif ((unsigned int)index >= be->cat.nb_pm_ext)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 18:\n+\tcase 21:\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_EXO_DYN:\n+\t\t\tget_set(&be->cat.v18.exo[index].dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_EXO_OFS:\n+\t\t\tget_set_signed(&be->cat.v18.exo[index].ofs, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 18/21/22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_exo_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value)\n+{\n+\treturn hw_mod_cat_exo_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_cat_exo_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value)\n+{\n+\treturn hw_mod_cat_exo_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_cat_rck_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->cat.nb_pm_ext * 64;\n+\tif ((unsigned int)(start_idx + count) > (be->cat.nb_pm_ext * 64))\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->cat_rck_flush(be->be_dev, &be->cat, start_idx, count);\n+}\n+\n+static int hw_mod_cat_rck_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field, int index, uint32_t *value,\n+\t\t\t      int get)\n+{\n+\tif ((unsigned int)index >= (be->cat.nb_pm_ext * 64))\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 18:\n+\tcase 21:\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_RCK_DATA:\n+\t\t\tget_set(&be->cat.v18.rck[index].rck_data, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 18/21/22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_rck_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value)\n+{\n+\treturn hw_mod_cat_rck_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_cat_rck_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value)\n+{\n+\treturn hw_mod_cat_rck_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_cat_len_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->cat.nb_len;\n+\tif ((unsigned int)(start_idx + count) > be->cat.nb_len)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->cat_len_flush(be->be_dev, &be->cat, start_idx, count);\n+}\n+\n+static int hw_mod_cat_len_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field, int index, uint32_t *value,\n+\t\t\t      int get)\n+{\n+\tif ((unsigned int)index >= be->cat.nb_len)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 18:\n+\tcase 21:\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_LEN_LOWER:\n+\t\t\tget_set(&be->cat.v18.len[index].lower, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_LEN_UPPER:\n+\t\t\tget_set(&be->cat.v18.len[index].upper, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_LEN_DYN1:\n+\t\t\tget_set(&be->cat.v18.len[index].dyn1, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_LEN_DYN2:\n+\t\t\tget_set(&be->cat.v18.len[index].dyn2, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_LEN_INV:\n+\t\t\tget_set(&be->cat.v18.len[index].inv, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 18/21/22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_len_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value)\n+{\n+\treturn hw_mod_cat_len_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_cat_len_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value)\n+{\n+\treturn hw_mod_cat_len_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_cat_cce_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = 4;\n+\tif ((unsigned int)(start_idx + count) > 4)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->cat_cce_flush(be->be_dev, &be->cat, start_idx, count);\n+}\n+\n+static int hw_mod_cat_cce_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field, int index, uint32_t *value,\n+\t\t\t      int get)\n+{\n+\tif ((unsigned int)index >= be->cat.nb_len)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_CCE_IMM:\n+\t\t\tget_set(&be->cat.v22.cce[index].imm, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCE_IND:\n+\t\t\tget_set(&be->cat.v22.cce[index].ind, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_cce_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value)\n+{\n+\treturn hw_mod_cat_cce_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_cat_cce_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value)\n+{\n+\treturn hw_mod_cat_cce_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_cat_ccs_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = 1024;\n+\tif ((unsigned int)(start_idx + count) > 1024)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->cat_ccs_flush(be->be_dev, &be->cat, start_idx, count);\n+}\n+\n+static int hw_mod_cat_ccs_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_cat_e field, int index, uint32_t *value,\n+\t\t\t      int get)\n+{\n+\tif ((unsigned int)index >= be->cat.nb_len)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 22:\n+\t\tswitch (field) {\n+\t\tcase HW_CAT_CCS_COR_EN:\n+\t\t\tget_set(&be->cat.v22.ccs[index].cor_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_COR:\n+\t\t\tget_set(&be->cat.v22.ccs[index].cor, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_HSH_EN:\n+\t\t\tget_set(&be->cat.v22.ccs[index].hsh_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_HSH:\n+\t\t\tget_set(&be->cat.v22.ccs[index].hsh, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_QSL_EN:\n+\t\t\tget_set(&be->cat.v22.ccs[index].qsl_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_QSL:\n+\t\t\tget_set(&be->cat.v22.ccs[index].qsl, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_IPF_EN:\n+\t\t\tget_set(&be->cat.v22.ccs[index].ipf_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_IPF:\n+\t\t\tget_set(&be->cat.v22.ccs[index].ipf, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_SLC_EN:\n+\t\t\tget_set(&be->cat.v22.ccs[index].slc_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_SLC:\n+\t\t\tget_set(&be->cat.v22.ccs[index].slc, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_PDB_EN:\n+\t\t\tget_set(&be->cat.v22.ccs[index].pdb_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_PDB:\n+\t\t\tget_set(&be->cat.v22.ccs[index].pdb, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_MSK_EN:\n+\t\t\tget_set(&be->cat.v22.ccs[index].msk_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_MSK:\n+\t\t\tget_set(&be->cat.v22.ccs[index].msk, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_HST_EN:\n+\t\t\tget_set(&be->cat.v22.ccs[index].hst_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_HST:\n+\t\t\tget_set(&be->cat.v22.ccs[index].hst, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_EPP_EN:\n+\t\t\tget_set(&be->cat.v22.ccs[index].epp_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_EPP:\n+\t\t\tget_set(&be->cat.v22.ccs[index].epp, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_TPE_EN:\n+\t\t\tget_set(&be->cat.v22.ccs[index].tpe_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_TPE:\n+\t\t\tget_set(&be->cat.v22.ccs[index].tpe, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_RRB_EN:\n+\t\t\tget_set(&be->cat.v22.ccs[index].rrb_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_RRB:\n+\t\t\tget_set(&be->cat.v22.ccs[index].rrb, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_SB0_TYPE:\n+\t\t\tget_set(&be->cat.v22.ccs[index].sb0_type, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_SB0_DATA:\n+\t\t\tget_set(&be->cat.v22.ccs[index].sb0_data, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_SB1_TYPE:\n+\t\t\tget_set(&be->cat.v22.ccs[index].sb1_type, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_SB1_DATA:\n+\t\t\tget_set(&be->cat.v22.ccs[index].sb1_data, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_SB2_TYPE:\n+\t\t\tget_set(&be->cat.v22.ccs[index].sb2_type, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_CAT_CCS_SB2_DATA:\n+\t\t\tget_set(&be->cat.v22.ccs[index].sb2_data, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 22 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_cat_ccs_set(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t value)\n+{\n+\treturn hw_mod_cat_ccs_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_cat_ccs_get(struct flow_api_backend_s *be, enum hw_cat_e field,\n+\t\t       int index, uint32_t *value)\n+{\n+\treturn hw_mod_cat_ccs_mod(be, field, index, value, 1);\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h\nnew file mode 100644\nindex 0000000000..3dc4a0aac7\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h\n@@ -0,0 +1,138 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_CAT_V18_H_\n+#define _HW_MOD_CAT_V18_H_\n+\n+struct cat_v18_cfn_s {\n+\tuint32_t enable;\n+\tuint32_t inv;\n+\t/* protocol checks */\n+\tuint32_t ptc_inv;\n+\tuint32_t ptc_isl;\n+\tuint32_t ptc_cfp;\n+\tuint32_t ptc_mac;\n+\tuint32_t ptc_l2;\n+\tuint32_t ptc_vntag;\n+\tuint32_t ptc_vlan;\n+\tuint32_t ptc_mpls;\n+\tuint32_t ptc_l3;\n+\tuint32_t ptc_frag;\n+\tuint32_t ptc_ip_prot;\n+\tuint32_t ptc_l4;\n+\tuint32_t ptc_tunnel;\n+\tuint32_t ptc_tnl_l2;\n+\tuint32_t ptc_tnl_vlan;\n+\tuint32_t ptc_tnl_mpls;\n+\tuint32_t ptc_tnl_l3;\n+\tuint32_t ptc_tnl_frag;\n+\tuint32_t ptc_tnl_ip_prot;\n+\tuint32_t ptc_tnl_l4;\n+\t/* error checks */\n+\tuint32_t err_inv;\n+\tuint32_t err_cv;\n+\tuint32_t err_fcs;\n+\tuint32_t err_trunc;\n+\tuint32_t err_l3_cs;\n+\tuint32_t err_l4_cs;\n+\t/* in port */\n+\tuint32_t mac_port;\n+\t/* pattern matcher */\n+\tuint32_t pm_cmp[2];\n+\tuint32_t pm_dct;\n+\tuint32_t pm_ext_inv;\n+\tuint32_t pm_cmb;\n+\tuint32_t pm_and_inv;\n+\tuint32_t pm_or_inv;\n+\tuint32_t pm_inv;\n+\tuint32_t lc;\n+\tuint32_t lc_inv;\n+\tuint32_t km_or;\n+};\n+\n+struct cat_v18_kce_s {\n+\tuint32_t enable_bm;\n+};\n+\n+struct cat_v18_kcs_s {\n+\tuint32_t category;\n+};\n+\n+struct cat_v18_fte_s {\n+\tuint32_t enable_bm;\n+};\n+\n+struct cat_v18_cte_s {\n+\tunion {\n+\t\tuint32_t enable_bm;\n+\t\tstruct {\n+\t\t\tuint32_t col : 1;\n+\t\t\tuint32_t cor : 1;\n+\t\t\tuint32_t hsh : 1;\n+\t\t\tuint32_t qsl : 1;\n+\t\t\tuint32_t ipf : 1;\n+\t\t\tuint32_t slc : 1;\n+\t\t\tuint32_t pdb : 1;\n+\t\t\tuint32_t msk : 1;\n+\t\t\tuint32_t hst : 1;\n+\t\t\tuint32_t epp : 1;\n+\t\t\tuint32_t tpe : 1;\n+\t\t} b;\n+\t};\n+};\n+\n+struct cat_v18_cts_s {\n+\tuint32_t cat_a;\n+\tuint32_t cat_b;\n+};\n+\n+struct cat_v18_cot_s {\n+\tuint32_t color;\n+\tuint32_t km;\n+};\n+\n+struct cat_v18_cct_s {\n+\tuint32_t color;\n+\tuint32_t km;\n+};\n+\n+struct cat_v18_exo_s {\n+\tuint32_t dyn;\n+\tint32_t ofs;\n+};\n+\n+struct cat_v18_rck_s {\n+\tuint32_t rck_data;\n+};\n+\n+struct cat_v18_len_s {\n+\tuint32_t lower;\n+\tuint32_t upper;\n+\tuint32_t dyn1;\n+\tuint32_t dyn2;\n+\tuint32_t inv;\n+};\n+\n+struct cat_v18_kcc_s {\n+\tuint32_t key[2];\n+\tuint32_t category;\n+\tuint32_t id;\n+};\n+\n+struct hw_mod_cat_v18_s {\n+\tstruct cat_v18_cfn_s *cfn;\n+\tstruct cat_v18_kce_s *kce;\n+\tstruct cat_v18_kcs_s *kcs;\n+\tstruct cat_v18_fte_s *fte;\n+\tstruct cat_v18_cte_s *cte;\n+\tstruct cat_v18_cts_s *cts;\n+\tstruct cat_v18_cot_s *cot;\n+\tstruct cat_v18_cct_s *cct;\n+\tstruct cat_v18_exo_s *exo;\n+\tstruct cat_v18_rck_s *rck;\n+\tstruct cat_v18_len_s *len;\n+\tstruct cat_v18_kcc_s *kcc_cam;\n+};\n+\n+#endif /* _HW_MOD_CAT_V18_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h\nnew file mode 100644\nindex 0000000000..fa69ec11f3\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h\n@@ -0,0 +1,88 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_CAT_V21_H_\n+#define _HW_MOD_CAT_V21_H_\n+\n+#include \"hw_mod_cat_v18.h\"\n+\n+struct cat_v21_cfn_s {\n+\tuint32_t enable;\n+\tuint32_t inv;\n+\t/* protocol checks */\n+\tuint32_t ptc_inv;\n+\tuint32_t ptc_isl;\n+\tuint32_t ptc_cfp;\n+\tuint32_t ptc_mac;\n+\tuint32_t ptc_l2;\n+\tuint32_t ptc_vntag;\n+\tuint32_t ptc_vlan;\n+\tuint32_t ptc_mpls;\n+\tuint32_t ptc_l3;\n+\tuint32_t ptc_frag;\n+\tuint32_t ptc_ip_prot;\n+\tuint32_t ptc_l4;\n+\tuint32_t ptc_tunnel;\n+\tuint32_t ptc_tnl_l2;\n+\tuint32_t ptc_tnl_vlan;\n+\tuint32_t ptc_tnl_mpls;\n+\tuint32_t ptc_tnl_l3;\n+\tuint32_t ptc_tnl_frag;\n+\tuint32_t ptc_tnl_ip_prot;\n+\tuint32_t ptc_tnl_l4;\n+\t/* error checks */\n+\tuint32_t err_inv;\n+\tuint32_t err_cv;\n+\tuint32_t err_fcs;\n+\tuint32_t err_trunc;\n+\tuint32_t err_l3_cs;\n+\tuint32_t err_l4_cs;\n+\tuint32_t err_tnl_l3_cs;\n+\tuint32_t err_tnl_l4_cs;\n+\tuint32_t err_ttl_exp;\n+\tuint32_t err_tnl_ttl_exp;\n+\t/* in port */\n+\tuint32_t mac_port;\n+\t/* pattern matcher */\n+\tuint32_t pm_cmp[2];\n+\tuint32_t pm_dct;\n+\tuint32_t pm_ext_inv;\n+\tuint32_t pm_cmb;\n+\tuint32_t pm_and_inv;\n+\tuint32_t pm_or_inv;\n+\tuint32_t pm_inv;\n+\tuint32_t lc;\n+\tuint32_t lc_inv;\n+\tuint32_t km0_or;\n+\tuint32_t km1_or;\n+};\n+\n+struct cat_v21_kce_s {\n+\tuint32_t enable_bm[2];\n+};\n+\n+struct cat_v21_kcs_s {\n+\tuint32_t category[2];\n+};\n+\n+struct cat_v21_fte_s {\n+\tuint32_t enable_bm[2];\n+};\n+\n+struct hw_mod_cat_v21_s {\n+\tstruct cat_v21_cfn_s *cfn;\n+\tstruct cat_v21_kce_s *kce;\n+\tstruct cat_v21_kcs_s *kcs;\n+\tstruct cat_v21_fte_s *fte;\n+\tstruct cat_v18_cte_s *cte;\n+\tstruct cat_v18_cts_s *cts;\n+\tstruct cat_v18_cot_s *cot;\n+\tstruct cat_v18_cct_s *cct;\n+\tstruct cat_v18_exo_s *exo;\n+\tstruct cat_v18_rck_s *rck;\n+\tstruct cat_v18_len_s *len;\n+\tstruct cat_v18_kcc_s *kcc_cam;\n+};\n+\n+#endif /* _HW_MOD_CAT_V21_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h\nnew file mode 100644\nindex 0000000000..fa7dc6f441\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h\n@@ -0,0 +1,83 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_CAT_V22_H_\n+#define _HW_MOD_CAT_V22_H_\n+\n+#include \"hw_mod_cat_v21.h\"\n+\n+struct cat_v22_cte_s {\n+\tunion {\n+\t\tuint32_t enable_bm;\n+\t\tstruct {\n+\t\t\tuint32_t col : 1;\n+\t\t\tuint32_t cor : 1;\n+\t\t\tuint32_t hsh : 1;\n+\t\t\tuint32_t qsl : 1;\n+\t\t\tuint32_t ipf : 1;\n+\t\t\tuint32_t slc : 1;\n+\t\t\tuint32_t pdb : 1;\n+\t\t\tuint32_t msk : 1;\n+\t\t\tuint32_t hst : 1;\n+\t\t\tuint32_t epp : 1;\n+\t\t\tuint32_t tpe : 1;\n+\t\t\tuint32_t rrb : 1;\n+\t\t} b;\n+\t};\n+};\n+\n+struct cat_v22_cce_s {\n+\tuint32_t imm;\n+\tuint32_t ind;\n+};\n+\n+struct cat_v22_ccs_s {\n+\tuint32_t cor_en;\n+\tuint32_t cor;\n+\tuint32_t hsh_en;\n+\tuint32_t hsh;\n+\tuint32_t qsl_en;\n+\tuint32_t qsl;\n+\tuint32_t ipf_en;\n+\tuint32_t ipf;\n+\tuint32_t slc_en;\n+\tuint32_t slc;\n+\tuint32_t pdb_en;\n+\tuint32_t pdb;\n+\tuint32_t msk_en;\n+\tuint32_t msk;\n+\tuint32_t hst_en;\n+\tuint32_t hst;\n+\tuint32_t epp_en;\n+\tuint32_t epp;\n+\tuint32_t tpe_en;\n+\tuint32_t tpe;\n+\tuint32_t rrb_en;\n+\tuint32_t rrb;\n+\tuint32_t sb0_type;\n+\tuint32_t sb0_data;\n+\tuint32_t sb1_type;\n+\tuint32_t sb1_data;\n+\tuint32_t sb2_type;\n+\tuint32_t sb2_data;\n+};\n+\n+struct hw_mod_cat_v22_s {\n+\tstruct cat_v21_cfn_s *cfn;\n+\tstruct cat_v21_kce_s *kce; /* KCE 0/1 */\n+\tstruct cat_v21_kcs_s *kcs; /* KCS 0/1 */\n+\tstruct cat_v21_fte_s *fte; /* FTE 0/1 */\n+\tstruct cat_v22_cte_s *cte;\n+\tstruct cat_v18_cts_s *cts;\n+\tstruct cat_v18_cot_s *cot;\n+\tstruct cat_v18_cct_s *cct;\n+\tstruct cat_v18_exo_s *exo;\n+\tstruct cat_v18_rck_s *rck;\n+\tstruct cat_v18_len_s *len;\n+\tstruct cat_v18_kcc_s *kcc_cam;\n+\tstruct cat_v22_cce_s *cce;\n+\tstruct cat_v22_ccs_s *ccs;\n+};\n+\n+#endif /* _HW_MOD_CAT_V22_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c\nnew file mode 100644\nindex 0000000000..404add5fe6\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c\n@@ -0,0 +1,1099 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <string.h>\n+#include \"flow_api_backend.h\"\n+\n+#define _MOD_ \"FLM\"\n+#define _VER_ be->flm.ver\n+\n+bool hw_mod_flm_present(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->get_flm_present(be->be_dev);\n+}\n+\n+int hw_mod_flm_alloc(struct flow_api_backend_s *be)\n+{\n+\tint nb;\n+\n+\t_VER_ = be->iface->get_flm_version(be->be_dev);\n+\tNT_LOG(DBG, FILTER, \"FLM MODULE VERSION  %i.%i\\n\", VER_MAJOR(_VER_),\n+\t       VER_MINOR(_VER_));\n+\n+\tnb = be->iface->get_nb_flm_categories(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"flm_categories\", _MOD_, _VER_);\n+\tbe->flm.nb_categories = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_flm_size_mb(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"flm_size_mb\", _MOD_, _VER_);\n+\tbe->flm.nb_size_mb = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_flm_entry_size(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"flm_entry_size\", _MOD_, _VER_);\n+\tbe->flm.nb_entry_size = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_flm_variant(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"flm_variant\", _MOD_, _VER_);\n+\tbe->flm.nb_variant = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_flm_prios(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"flm_prios\", _MOD_, _VER_);\n+\tbe->flm.nb_prios = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_flm_pst_profiles(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"flm_variant\", _MOD_, _VER_);\n+\tbe->flm.nb_pst_profiles = (uint32_t)nb;\n+\n+\tswitch (_VER_) {\n+\tcase 17:\n+\t\tif (!callocate_mod(CAST_COMMON(&be->flm), 26,\n+\t\t\t&be->flm.v17.control, 1,\n+\t\t\tsizeof(struct flm_v17_control_s),\n+\t\t\t&be->flm.v17.status, 1,\n+\t\t\tsizeof(struct flm_v17_status_s),\n+\t\t\t&be->flm.v17.timeout, 1,\n+\t\t\tsizeof(struct flm_v17_timeout_s),\n+\t\t\t&be->flm.v17.scrub, 1,\n+\t\t\tsizeof(struct flm_v17_scrub_s),\n+\t\t\t&be->flm.v17.load_bin, 1,\n+\t\t\tsizeof(struct flm_v17_load_bin_s),\n+\t\t\t&be->flm.v17.load_pps, 1,\n+\t\t\tsizeof(struct flm_v17_load_pps_s),\n+\t\t\t&be->flm.v17.load_lps, 1,\n+\t\t\tsizeof(struct flm_v17_load_lps_s),\n+\t\t\t&be->flm.v17.load_aps, 1,\n+\t\t\tsizeof(struct flm_v17_load_aps_s),\n+\t\t\t&be->flm.v17.prio, 1,\n+\t\t\tsizeof(struct flm_v17_prio_s),\n+\t\t\t&be->flm.v17.pst, be->flm.nb_pst_profiles,\n+\t\t\tsizeof(struct flm_v17_pst_s),\n+\t\t\t&be->flm.v17.rcp, be->flm.nb_categories,\n+\t\t\tsizeof(struct flm_v17_rcp_s),\n+\t\t\t&be->flm.v17.buf_ctrl, 1,\n+\t\t\tsizeof(struct flm_v17_buf_ctrl_s),\n+\t\t\t&be->flm.v17.lrn_done, 1,\n+\t\t\tsizeof(struct flm_v17_stat_lrn_done_s),\n+\t\t\t&be->flm.v17.lrn_ignore, 1,\n+\t\t\tsizeof(struct flm_v17_stat_lrn_ignore_s),\n+\t\t\t&be->flm.v17.lrn_fail, 1,\n+\t\t\tsizeof(struct flm_v17_stat_lrn_fail_s),\n+\t\t\t&be->flm.v17.unl_done, 1,\n+\t\t\tsizeof(struct flm_v17_stat_unl_done_s),\n+\t\t\t&be->flm.v17.unl_ignore, 1,\n+\t\t\tsizeof(struct flm_v17_stat_unl_ignore_s),\n+\t\t\t&be->flm.v17.rel_done, 1,\n+\t\t\tsizeof(struct flm_v17_stat_rel_done_s),\n+\t\t\t&be->flm.v17.rel_ignore, 1,\n+\t\t\tsizeof(struct flm_v17_stat_rel_ignore_s),\n+\t\t\t&be->flm.v17.aul_done, 1,\n+\t\t\tsizeof(struct flm_v17_stat_aul_done_s),\n+\t\t\t&be->flm.v17.aul_ignore, 1,\n+\t\t\tsizeof(struct flm_v17_stat_aul_ignore_s),\n+\t\t\t&be->flm.v17.aul_fail, 1,\n+\t\t\tsizeof(struct flm_v17_stat_aul_fail_s),\n+\t\t\t&be->flm.v17.tul_done, 1,\n+\t\t\tsizeof(struct flm_v17_stat_tul_done_s),\n+\t\t\t&be->flm.v17.flows, 1,\n+\t\t\tsizeof(struct flm_v17_stat_flows_s),\n+\t\t\t&be->flm.v17.prb_done, 1,\n+\t\t\tsizeof(struct flm_v17_stat_prb_done_s),\n+\t\t\t&be->flm.v17.prb_ignore, 1,\n+\t\t\tsizeof(struct flm_v17_stat_prb_ignore_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\n+\tcase 20:\n+\t\tif (!callocate_mod(CAST_COMMON(&be->flm), 38,\n+\t\t\t&be->flm.v17.control, 1,\n+\t\t\tsizeof(struct flm_v17_control_s),\n+\t\t\t&be->flm.v17.status, 1,\n+\t\t\tsizeof(struct flm_v17_status_s),\n+\t\t\t&be->flm.v17.timeout, 1,\n+\t\t\tsizeof(struct flm_v17_timeout_s),\n+\t\t\t&be->flm.v17.scrub, 1,\n+\t\t\tsizeof(struct flm_v17_scrub_s),\n+\t\t\t&be->flm.v17.load_bin, 1,\n+\t\t\tsizeof(struct flm_v17_load_bin_s),\n+\t\t\t&be->flm.v17.load_pps, 1,\n+\t\t\tsizeof(struct flm_v17_load_pps_s),\n+\t\t\t&be->flm.v17.load_lps, 1,\n+\t\t\tsizeof(struct flm_v17_load_lps_s),\n+\t\t\t&be->flm.v17.load_aps, 1,\n+\t\t\tsizeof(struct flm_v17_load_aps_s),\n+\t\t\t&be->flm.v17.prio, 1,\n+\t\t\tsizeof(struct flm_v17_prio_s),\n+\t\t\t&be->flm.v17.pst, be->flm.nb_pst_profiles,\n+\t\t\tsizeof(struct flm_v17_pst_s),\n+\t\t\t&be->flm.v17.rcp, be->flm.nb_categories,\n+\t\t\tsizeof(struct flm_v17_rcp_s),\n+\t\t\t&be->flm.v17.buf_ctrl, 1,\n+\t\t\tsizeof(struct flm_v17_buf_ctrl_s),\n+\t\t\t&be->flm.v17.lrn_done, 1,\n+\t\t\tsizeof(struct flm_v17_stat_lrn_done_s),\n+\t\t\t&be->flm.v17.lrn_ignore, 1,\n+\t\t\tsizeof(struct flm_v17_stat_lrn_ignore_s),\n+\t\t\t&be->flm.v17.lrn_fail, 1,\n+\t\t\tsizeof(struct flm_v17_stat_lrn_fail_s),\n+\t\t\t&be->flm.v17.unl_done, 1,\n+\t\t\tsizeof(struct flm_v17_stat_unl_done_s),\n+\t\t\t&be->flm.v17.unl_ignore, 1,\n+\t\t\tsizeof(struct flm_v17_stat_unl_ignore_s),\n+\t\t\t&be->flm.v17.rel_done, 1,\n+\t\t\tsizeof(struct flm_v17_stat_rel_done_s),\n+\t\t\t&be->flm.v17.rel_ignore, 1,\n+\t\t\tsizeof(struct flm_v17_stat_rel_ignore_s),\n+\t\t\t&be->flm.v17.aul_done, 1,\n+\t\t\tsizeof(struct flm_v17_stat_aul_done_s),\n+\t\t\t&be->flm.v17.aul_ignore, 1,\n+\t\t\tsizeof(struct flm_v17_stat_aul_ignore_s),\n+\t\t\t&be->flm.v17.aul_fail, 1,\n+\t\t\tsizeof(struct flm_v17_stat_aul_fail_s),\n+\t\t\t&be->flm.v17.tul_done, 1,\n+\t\t\tsizeof(struct flm_v17_stat_tul_done_s),\n+\t\t\t&be->flm.v17.flows, 1,\n+\t\t\tsizeof(struct flm_v17_stat_flows_s),\n+\t\t\t&be->flm.v17.prb_done, 1,\n+\t\t\tsizeof(struct flm_v17_stat_prb_done_s),\n+\t\t\t&be->flm.v17.prb_ignore, 1,\n+\t\t\tsizeof(struct flm_v17_stat_prb_ignore_s),\n+\t\t\t&be->flm.v20.sta_done, 1,\n+\t\t\tsizeof(struct flm_v20_stat_sta_done_s),\n+\t\t\t&be->flm.v20.inf_done, 1,\n+\t\t\tsizeof(struct flm_v20_stat_inf_done_s),\n+\t\t\t&be->flm.v20.inf_skip, 1,\n+\t\t\tsizeof(struct flm_v20_stat_inf_skip_s),\n+\t\t\t&be->flm.v20.pck_hit, 1,\n+\t\t\tsizeof(struct flm_v20_stat_pck_hit_s),\n+\t\t\t&be->flm.v20.pck_miss, 1,\n+\t\t\tsizeof(struct flm_v20_stat_pck_miss_s),\n+\t\t\t&be->flm.v20.pck_unh, 1,\n+\t\t\tsizeof(struct flm_v20_stat_pck_unh_s),\n+\t\t\t&be->flm.v20.pck_dis, 1,\n+\t\t\tsizeof(struct flm_v20_stat_pck_dis_s),\n+\t\t\t&be->flm.v20.csh_hit, 1,\n+\t\t\tsizeof(struct flm_v20_stat_csh_hit_s),\n+\t\t\t&be->flm.v20.csh_miss, 1,\n+\t\t\tsizeof(struct flm_v20_stat_csh_miss_s),\n+\t\t\t&be->flm.v20.csh_unh, 1,\n+\t\t\tsizeof(struct flm_v20_stat_csh_unh_s),\n+\t\t\t&be->flm.v20.cuc_start, 1,\n+\t\t\tsizeof(struct flm_v20_stat_cuc_start_s),\n+\t\t\t&be->flm.v20.cuc_move, 1,\n+\t\t\tsizeof(struct flm_v20_stat_cuc_move_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void hw_mod_flm_free(struct flow_api_backend_s *be)\n+{\n+\tif (be->flm.base) {\n+\t\tfree(be->flm.base);\n+\t\tbe->flm.base = NULL;\n+\t}\n+}\n+\n+int hw_mod_flm_reset(struct flow_api_backend_s *be)\n+{\n+\t/* Zero entire cache area */\n+\tZERO_MOD_CACHE(&be->flm);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT FLM\\n\");\n+\thw_mod_flm_control_set(be, HW_FLM_CONTROL_SPLIT_SDRAM_USAGE, 0x10);\n+\n+\thw_mod_flm_control_flush(be);\n+\thw_mod_flm_timeout_flush(be);\n+\thw_mod_flm_scrub_flush(be);\n+\thw_mod_flm_rcp_flush(be, 0, ALL_ENTRIES);\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_control_flush(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->flm_control_flush(be->be_dev, &be->flm);\n+}\n+\n+static int hw_mod_flm_control_mod(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_flm_e field, uint32_t *value, int get)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_CONTROL_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(be->flm.v17.control, (uint8_t)*value,\n+\t\t\t       sizeof(struct flm_v17_control_s));\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_ENABLE:\n+\t\t\tget_set(&be->flm.v17.control->enable, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_INIT:\n+\t\t\tget_set(&be->flm.v17.control->init, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_LDS:\n+\t\t\tget_set(&be->flm.v17.control->lds, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_LFS:\n+\t\t\tget_set(&be->flm.v17.control->lfs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_LIS:\n+\t\t\tget_set(&be->flm.v17.control->lis, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_UDS:\n+\t\t\tget_set(&be->flm.v17.control->uds, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_UIS:\n+\t\t\tget_set(&be->flm.v17.control->uis, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_RDS:\n+\t\t\tget_set(&be->flm.v17.control->rds, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_RIS:\n+\t\t\tget_set(&be->flm.v17.control->ris, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_PDS:\n+\t\t\tget_set(&be->flm.v17.control->pds, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_PIS:\n+\t\t\tget_set(&be->flm.v17.control->pis, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_CRCWR:\n+\t\t\tget_set(&be->flm.v17.control->crcwr, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_CRCRD:\n+\t\t\tget_set(&be->flm.v17.control->crcrd, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_RBL:\n+\t\t\tget_set(&be->flm.v17.control->rbl, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_EAB:\n+\t\t\tget_set(&be->flm.v17.control->eab, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_CONTROL_SPLIT_SDRAM_USAGE:\n+\t\t\tget_set(&be->flm.v17.control->split_sdram_usage, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_control_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t   uint32_t value)\n+{\n+\treturn hw_mod_flm_control_mod(be, field, &value, 0);\n+}\n+\n+int hw_mod_flm_control_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t   uint32_t *value)\n+{\n+\treturn hw_mod_flm_control_mod(be, field, value, 1);\n+}\n+\n+int hw_mod_flm_status_flush(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->flm_status_flush(be->be_dev, &be->flm);\n+}\n+\n+int hw_mod_flm_status_update(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->flm_status_update(be->be_dev, &be->flm);\n+}\n+\n+static int hw_mod_flm_status_mod(struct flow_api_backend_s *be,\n+\t\t\t\t enum hw_flm_e field, uint32_t *value, int get)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_STATUS_CALIBDONE:\n+\t\t\tget_set(&be->flm.v17.status->calibdone, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STATUS_INITDONE:\n+\t\t\tget_set(&be->flm.v17.status->initdone, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STATUS_IDLE:\n+\t\t\tget_set(&be->flm.v17.status->idle, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STATUS_CRITICAL:\n+\t\t\tget_set(&be->flm.v17.status->critical, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STATUS_PANIC:\n+\t\t\tget_set(&be->flm.v17.status->panic, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STATUS_CRCERR:\n+\t\t\tget_set(&be->flm.v17.status->crcerr, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STATUS_EFT_BP:\n+\t\t\tget_set(&be->flm.v17.status->eft_bp, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_status_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t  uint32_t value)\n+{\n+\treturn hw_mod_flm_status_mod(be, field, &value, 0);\n+}\n+\n+int hw_mod_flm_status_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t  uint32_t *value)\n+{\n+\treturn hw_mod_flm_status_mod(be, field, value, 1);\n+}\n+\n+int hw_mod_flm_timeout_flush(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->flm_timeout_flush(be->be_dev, &be->flm);\n+}\n+\n+static int hw_mod_flm_timeout_mod(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_flm_e field, uint32_t *value, int get)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_TIMEOUT_T:\n+\t\t\tget_set(&be->flm.v17.timeout->t, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_timeout_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t   uint32_t value)\n+{\n+\treturn hw_mod_flm_timeout_mod(be, field, &value, 0);\n+}\n+\n+int hw_mod_flm_timeout_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t   uint32_t *value)\n+{\n+\treturn hw_mod_flm_timeout_mod(be, field, value, 1);\n+}\n+\n+int hw_mod_flm_scrub_flush(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->flm_scrub_flush(be->be_dev, &be->flm);\n+}\n+\n+static int hw_mod_flm_scrub_mod(struct flow_api_backend_s *be,\n+\t\t\t\tenum hw_flm_e field, uint32_t *value, int get)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_SCRUB_I:\n+\t\t\tget_set(&be->flm.v17.scrub->i, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_scrub_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t uint32_t value)\n+{\n+\treturn hw_mod_flm_scrub_mod(be, field, &value, 0);\n+}\n+\n+int hw_mod_flm_scrub_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t uint32_t *value)\n+{\n+\treturn hw_mod_flm_scrub_mod(be, field, value, 1);\n+}\n+\n+int hw_mod_flm_load_bin_flush(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->flm_load_bin_flush(be->be_dev, &be->flm);\n+}\n+\n+static int hw_mod_flm_load_bin_mod(struct flow_api_backend_s *be,\n+\t\t\t\t   enum hw_flm_e field, uint32_t *value,\n+\t\t\t\t   int get)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_LOAD_BIN:\n+\t\t\tget_set(&be->flm.v17.load_bin->bin, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_load_bin_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t value)\n+{\n+\treturn hw_mod_flm_load_bin_mod(be, field, &value, 0);\n+}\n+\n+int hw_mod_flm_load_bin_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t *value)\n+{\n+\treturn hw_mod_flm_load_bin_mod(be, field, value, 1);\n+}\n+\n+int hw_mod_flm_load_pps_flush(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->flm_load_pps_flush(be->be_dev, &be->flm);\n+}\n+\n+static int hw_mod_flm_load_pps_mod(struct flow_api_backend_s *be,\n+\t\t\t\t   enum hw_flm_e field, uint32_t *value,\n+\t\t\t\t   int get)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_LOAD_PPS:\n+\t\t\tget_set(&be->flm.v17.load_pps->pps, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_load_pps_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t value)\n+{\n+\treturn hw_mod_flm_load_pps_mod(be, field, &value, 0);\n+}\n+\n+int hw_mod_flm_load_pps_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t *value)\n+{\n+\treturn hw_mod_flm_load_pps_mod(be, field, value, 1);\n+}\n+\n+int hw_mod_flm_load_lps_flush(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->flm_load_lps_flush(be->be_dev, &be->flm);\n+}\n+\n+static int hw_mod_flm_load_lps_mod(struct flow_api_backend_s *be,\n+\t\t\t\t   enum hw_flm_e field, uint32_t *value,\n+\t\t\t\t   int get)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_LOAD_LPS:\n+\t\t\tget_set(&be->flm.v17.load_lps->lps, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_load_lps_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t value)\n+{\n+\treturn hw_mod_flm_load_lps_mod(be, field, &value, 0);\n+}\n+\n+int hw_mod_flm_load_lps_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t *value)\n+{\n+\treturn hw_mod_flm_load_lps_mod(be, field, value, 1);\n+}\n+\n+int hw_mod_flm_load_aps_flush(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->flm_load_aps_flush(be->be_dev, &be->flm);\n+}\n+\n+static int hw_mod_flm_load_aps_mod(struct flow_api_backend_s *be,\n+\t\t\t\t   enum hw_flm_e field, uint32_t *value,\n+\t\t\t\t   int get)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_LOAD_APS:\n+\t\t\tget_set(&be->flm.v17.load_aps->aps, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_load_aps_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t value)\n+{\n+\treturn hw_mod_flm_load_aps_mod(be, field, &value, 0);\n+}\n+\n+int hw_mod_flm_load_aps_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t *value)\n+{\n+\treturn hw_mod_flm_load_aps_mod(be, field, value, 1);\n+}\n+\n+int hw_mod_flm_prio_flush(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->flm_prio_flush(be->be_dev, &be->flm);\n+}\n+\n+static int hw_mod_flm_prio_mod(struct flow_api_backend_s *be,\n+\t\t\t       enum hw_flm_e field, uint32_t *value, int get)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_PRIO_LIMIT0:\n+\t\t\tget_set(&be->flm.v17.prio->limit0, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_PRIO_FT0:\n+\t\t\tget_set(&be->flm.v17.prio->ft0, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_PRIO_LIMIT1:\n+\t\t\tget_set(&be->flm.v17.prio->limit1, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_PRIO_FT1:\n+\t\t\tget_set(&be->flm.v17.prio->ft1, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_PRIO_LIMIT2:\n+\t\t\tget_set(&be->flm.v17.prio->limit2, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_PRIO_FT2:\n+\t\t\tget_set(&be->flm.v17.prio->ft2, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_PRIO_LIMIT3:\n+\t\t\tget_set(&be->flm.v17.prio->limit3, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_PRIO_FT3:\n+\t\t\tget_set(&be->flm.v17.prio->ft3, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_prio_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\tuint32_t value)\n+{\n+\treturn hw_mod_flm_prio_mod(be, field, &value, 0);\n+}\n+\n+int hw_mod_flm_prio_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\tuint32_t *value)\n+{\n+\treturn hw_mod_flm_prio_mod(be, field, value, 1);\n+}\n+\n+int hw_mod_flm_pst_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->flm.nb_pst_profiles;\n+\tif ((unsigned int)(start_idx + count) > be->flm.nb_pst_profiles)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->flm_pst_flush(be->be_dev, &be->flm, start_idx, count);\n+}\n+\n+static int hw_mod_flm_pst_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_flm_e field, int index, uint32_t *value,\n+\t\t\t      int get)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_PST_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->flm.v17.pst[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct flm_v17_pst_s));\n+\t\t\tbreak;\n+\t\tcase HW_FLM_PST_BP:\n+\t\t\tget_set(&be->flm.v17.pst[index].bp, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_PST_PP:\n+\t\t\tget_set(&be->flm.v17.pst[index].pp, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_PST_TP:\n+\t\t\tget_set(&be->flm.v17.pst[index].tp, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_pst_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t       int index, uint32_t value)\n+{\n+\treturn hw_mod_flm_pst_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_flm_pst_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t       int index, uint32_t *value)\n+{\n+\treturn hw_mod_flm_pst_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_flm_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->flm.nb_categories;\n+\tif ((unsigned int)(start_idx + count) > be->flm.nb_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->flm_rcp_flush(be->be_dev, &be->flm, start_idx, count);\n+}\n+\n+static int hw_mod_flm_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_flm_e field, int index, uint32_t *value,\n+\t\t\t      int get)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_RCP_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->flm.v17.rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct flm_v17_rcp_s));\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_LOOKUP:\n+\t\t\tget_set(&be->flm.v17.rcp[index].lookup, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_QW0_DYN:\n+\t\t\tget_set(&be->flm.v17.rcp[index].qw0_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_QW0_OFS:\n+\t\t\tget_set(&be->flm.v17.rcp[index].qw0_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_QW0_SEL:\n+\t\t\tget_set(&be->flm.v17.rcp[index].qw0_sel, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_QW4_DYN:\n+\t\t\tget_set(&be->flm.v17.rcp[index].qw4_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_QW4_OFS:\n+\t\t\tget_set(&be->flm.v17.rcp[index].qw4_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_SW8_DYN:\n+\t\t\tget_set(&be->flm.v17.rcp[index].sw8_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_SW8_OFS:\n+\t\t\tget_set(&be->flm.v17.rcp[index].sw8_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_SW8_SEL:\n+\t\t\tget_set(&be->flm.v17.rcp[index].sw8_sel, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_SW9_DYN:\n+\t\t\tget_set(&be->flm.v17.rcp[index].sw9_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_SW9_OFS:\n+\t\t\tget_set(&be->flm.v17.rcp[index].sw9_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_MASK:\n+\t\t\tif (get) {\n+\t\t\t\tmemcpy(value, be->flm.v17.rcp[index].mask,\n+\t\t\t\t       sizeof(((struct flm_v17_rcp_s *)0)\n+\t\t\t\t\t      ->mask));\n+\t\t\t} else {\n+\t\t\t\tmemcpy(be->flm.v17.rcp[index].mask, value,\n+\t\t\t\t       sizeof(((struct flm_v17_rcp_s *)0)\n+\t\t\t\t\t      ->mask));\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_KID:\n+\t\t\tget_set(&be->flm.v17.rcp[index].kid, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_OPN:\n+\t\t\tget_set(&be->flm.v17.rcp[index].opn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_IPN:\n+\t\t\tget_set(&be->flm.v17.rcp[index].ipn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_BYT_DYN:\n+\t\t\tget_set(&be->flm.v17.rcp[index].byt_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_BYT_OFS:\n+\t\t\tget_set(&be->flm.v17.rcp[index].byt_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_TXPLM:\n+\t\t\tget_set(&be->flm.v17.rcp[index].txplm, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_RCP_AUTO_IPV4_MASK:\n+\t\t\tget_set(&be->flm.v17.rcp[index].auto_ipv4_mask, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_rcp_set_mask(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    int index, uint32_t *value)\n+{\n+\tif (field != HW_FLM_RCP_MASK)\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\treturn hw_mod_flm_rcp_mod(be, field, index, value, 0);\n+}\n+\n+int hw_mod_flm_rcp_set(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t       int index, uint32_t value)\n+{\n+\tif (field == HW_FLM_RCP_MASK)\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\treturn hw_mod_flm_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_flm_rcp_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t       int index, uint32_t *value)\n+{\n+\treturn hw_mod_flm_rcp_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_flm_buf_ctrl_update(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->flm_buf_ctrl_update(be->be_dev, &be->flm);\n+}\n+\n+static int hw_mod_flm_buf_ctrl_mod_get(struct flow_api_backend_s *be,\n+\t\t\t\t       enum hw_flm_e field, uint32_t *value)\n+{\n+\tint get = 1; /* Only get supported */\n+\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_BUF_CTRL_LRN_FREE:\n+\t\t\tget_set(&be->flm.v17.buf_ctrl->lrn_free, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_BUF_CTRL_INF_AVAIL:\n+\t\t\tget_set(&be->flm.v17.buf_ctrl->inf_avail, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_FLM_BUF_CTRL_STA_AVAIL:\n+\t\t\tget_set(&be->flm.v17.buf_ctrl->sta_avail, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_buf_ctrl_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\t    uint32_t *value)\n+{\n+\treturn hw_mod_flm_buf_ctrl_mod_get(be, field, value);\n+}\n+\n+int hw_mod_flm_stat_update(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->flm_stat_update(be->be_dev, &be->flm);\n+}\n+\n+int hw_mod_flm_stat_get(struct flow_api_backend_s *be, enum hw_flm_e field,\n+\t\t\tuint32_t *value)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_STAT_LRN_DONE:\n+\t\t\t*value = be->flm.v17.lrn_done->cnt;\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STAT_LRN_IGNORE:\n+\t\t\t*value = be->flm.v17.lrn_ignore->cnt;\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STAT_LRN_FAIL:\n+\t\t\t*value = be->flm.v17.lrn_fail->cnt;\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STAT_UNL_DONE:\n+\t\t\t*value = be->flm.v17.unl_done->cnt;\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STAT_UNL_IGNORE:\n+\t\t\t*value = be->flm.v17.unl_ignore->cnt;\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STAT_REL_DONE:\n+\t\t\t*value = be->flm.v17.rel_done->cnt;\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STAT_REL_IGNORE:\n+\t\t\t*value = be->flm.v17.rel_ignore->cnt;\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STAT_PRB_DONE:\n+\t\t\t*value = be->flm.v17.prb_done->cnt;\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STAT_PRB_IGNORE:\n+\t\t\t*value = be->flm.v17.prb_ignore->cnt;\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STAT_AUL_DONE:\n+\t\t\t*value = be->flm.v17.aul_done->cnt;\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STAT_AUL_IGNORE:\n+\t\t\t*value = be->flm.v17.aul_ignore->cnt;\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STAT_AUL_FAIL:\n+\t\t\t*value = be->flm.v17.aul_fail->cnt;\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STAT_TUL_DONE:\n+\t\t\t*value = be->flm.v17.tul_done->cnt;\n+\t\t\tbreak;\n+\t\tcase HW_FLM_STAT_FLOWS:\n+\t\t\t*value = be->flm.v17.flows->cnt;\n+\t\t\tbreak;\n+\n+\t\tdefault: {\n+\t\t\tif (_VER_ < 18)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\n+\t\t\tswitch (field) {\n+\t\t\tcase HW_FLM_STAT_STA_DONE:\n+\t\t\t\t*value = be->flm.v20.sta_done->cnt;\n+\t\t\t\tbreak;\n+\t\t\tcase HW_FLM_STAT_INF_DONE:\n+\t\t\t\t*value = be->flm.v20.inf_done->cnt;\n+\t\t\t\tbreak;\n+\t\t\tcase HW_FLM_STAT_INF_SKIP:\n+\t\t\t\t*value = be->flm.v20.inf_skip->cnt;\n+\t\t\t\tbreak;\n+\t\t\tcase HW_FLM_STAT_PCK_HIT:\n+\t\t\t\t*value = be->flm.v20.pck_hit->cnt;\n+\t\t\t\tbreak;\n+\t\t\tcase HW_FLM_STAT_PCK_MISS:\n+\t\t\t\t*value = be->flm.v20.pck_miss->cnt;\n+\t\t\t\tbreak;\n+\t\t\tcase HW_FLM_STAT_PCK_UNH:\n+\t\t\t\t*value = be->flm.v20.pck_unh->cnt;\n+\t\t\t\tbreak;\n+\t\t\tcase HW_FLM_STAT_PCK_DIS:\n+\t\t\t\t*value = be->flm.v20.pck_dis->cnt;\n+\t\t\t\tbreak;\n+\t\t\tcase HW_FLM_STAT_CSH_HIT:\n+\t\t\t\t*value = be->flm.v20.csh_hit->cnt;\n+\t\t\t\tbreak;\n+\t\t\tcase HW_FLM_STAT_CSH_MISS:\n+\t\t\t\t*value = be->flm.v20.csh_miss->cnt;\n+\t\t\t\tbreak;\n+\t\t\tcase HW_FLM_STAT_CSH_UNH:\n+\t\t\t\t*value = be->flm.v20.csh_unh->cnt;\n+\t\t\t\tbreak;\n+\t\t\tcase HW_FLM_STAT_CUC_START:\n+\t\t\t\t*value = be->flm.v20.cuc_start->cnt;\n+\t\t\t\tbreak;\n+\t\t\tcase HW_FLM_STAT_CUC_MOVE:\n+\t\t\t\t*value = be->flm.v20.cuc_move->cnt;\n+\t\t\t\tbreak;\n+\n+\t\t\tdefault:\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\t}\n+\t\t}\n+\t\tbreak;\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_lrn_data_set_flush(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_flm_e field, const uint32_t *value)\n+{\n+\tint ret = 0;\n+\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_FLOW_LRN_DATA_V17:\n+\t\t\tret = be->iface->flm_lrn_data_flush(be->be_dev,\n+\t\t\t\t&be->flm, value,\n+\t\t\t\tsizeof(struct flm_v17_lrn_data_s) /\n+\t\t\t\tsizeof(uint32_t));\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn ret;\n+}\n+\n+int hw_mod_flm_inf_data_update_get(struct flow_api_backend_s *be,\n+\t\t\t\t   enum hw_flm_e field, uint32_t *value,\n+\t\t\t\t   uint32_t word_cnt)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_FLOW_INF_DATA_V17:\n+\t\t\tbe->iface->flm_inf_data_update(be->be_dev, &be->flm,\n+\t\t\t\t\t\t       value, word_cnt);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_flm_sta_data_update_get(struct flow_api_backend_s *be,\n+\t\t\t\t   enum hw_flm_e field, uint32_t *value)\n+{\n+\tswitch (_VER_) {\n+\tcase 17:\n+\tcase 20:\n+\t\tswitch (field) {\n+\t\tcase HW_FLM_FLOW_STA_DATA_V17:\n+\t\t\tbe->iface->flm_sta_data_update(be->be_dev,\n+\t\t\t\t&be->flm, value,\n+\t\t\t\tsizeof(struct flm_v17_sta_data_s) /\n+\t\t\t\tsizeof(uint32_t));\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h\nnew file mode 100644\nindex 0000000000..9b4ee1991e\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h\n@@ -0,0 +1,265 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_FLM_V17_H_\n+#define _HW_MOD_FLM_V17_H_\n+\n+struct flm_v17_mbr_idx_overlay {\n+\tuint64_t a : 28;\n+\tuint64_t b : 28;\n+\tuint64_t pad : 4;\n+};\n+\n+struct flm_v17_control_s {\n+\tuint32_t enable;\n+\tuint32_t init;\n+\tuint32_t lds;\n+\tuint32_t lfs;\n+\tuint32_t lis;\n+\tuint32_t uds;\n+\tuint32_t uis;\n+\tuint32_t rds;\n+\tuint32_t ris;\n+\tuint32_t pds;\n+\tuint32_t pis;\n+\tuint32_t crcwr;\n+\tuint32_t crcrd;\n+\tuint32_t rbl;\n+\tuint32_t eab;\n+\tuint32_t split_sdram_usage;\n+};\n+\n+struct flm_v17_status_s {\n+\tuint32_t calibdone;\n+\tuint32_t initdone;\n+\tuint32_t idle;\n+\tuint32_t critical;\n+\tuint32_t panic;\n+\tuint32_t crcerr;\n+\tuint32_t eft_bp;\n+};\n+\n+struct flm_v17_timeout_s {\n+\tuint32_t t;\n+};\n+\n+struct flm_v17_scrub_s {\n+\tuint32_t i;\n+};\n+\n+struct flm_v17_load_bin_s {\n+\tuint32_t bin;\n+};\n+\n+struct flm_v17_load_pps_s {\n+\tuint32_t pps;\n+};\n+\n+struct flm_v17_load_lps_s {\n+\tuint32_t lps;\n+};\n+\n+struct flm_v17_load_aps_s {\n+\tuint32_t aps;\n+};\n+\n+struct flm_v17_prio_s {\n+\tuint32_t limit0;\n+\tuint32_t ft0;\n+\tuint32_t limit1;\n+\tuint32_t ft1;\n+\tuint32_t limit2;\n+\tuint32_t ft2;\n+\tuint32_t limit3;\n+\tuint32_t ft3;\n+};\n+\n+struct flm_v17_pst_s {\n+\tuint32_t bp;\n+\tuint32_t pp;\n+\tuint32_t tp;\n+};\n+\n+struct flm_v17_rcp_s {\n+\tuint32_t lookup;\n+\tuint32_t qw0_dyn;\n+\tuint32_t qw0_ofs;\n+\tuint32_t qw0_sel;\n+\tuint32_t qw4_dyn;\n+\tuint32_t qw4_ofs;\n+\tuint32_t sw8_dyn;\n+\tuint32_t sw8_ofs;\n+\tuint32_t sw8_sel;\n+\tuint32_t sw9_dyn;\n+\tuint32_t sw9_ofs;\n+\tuint32_t mask[10];\n+\tuint32_t kid;\n+\tuint32_t opn;\n+\tuint32_t ipn;\n+\tuint32_t byt_dyn;\n+\tuint32_t byt_ofs;\n+\tuint32_t txplm;\n+\tuint32_t auto_ipv4_mask;\n+};\n+\n+struct flm_v17_buf_ctrl_s {\n+\tuint32_t lrn_free;\n+\tuint32_t inf_avail;\n+\tuint32_t sta_avail;\n+};\n+\n+#pragma pack(1)\n+struct flm_v17_lrn_data_s {\n+\tuint32_t sw9; /* 31:0 (32) */\n+\tuint32_t sw8; /* 63:32 (32) */\n+\tuint32_t qw4[4]; /* 191:64 (128) */\n+\tuint32_t qw0[4]; /* 319:192 (128) */\n+\tuint8_t prot; /* 327:320 (8) */\n+\tuint8_t kid; /* 335:328 (8) */\n+\tuint32_t nat_ip; /* 367:336 (32) */\n+\tuint32_t teid; /* 399:368 (32) */\n+\tuint16_t nat_port; /* 415:400 (16) */\n+\tuint16_t rate; /* 431:416 (16) */\n+\tuint16_t size; /* 447:432 (16) */\n+\tuint32_t color; /* 479:448 (32) */\n+\tuint32_t adj; /* 511:480 (32) */\n+\tuint8_t id[9]; /* 583:512 (72) */\n+\tuint16_t fill : 12; /* 595:584 (12) */\n+\tuint16_t ft : 4; /* 599:596 (4) */\n+\tuint8_t ft_mbr : 4; /* 603:600 (4) */\n+\tuint8_t ft_miss : 4; /* 607:604 (5) */\n+\n+\t/* 635:608, 663:636, 691:664, 719:692 (4 x 28) Get/set with macros FLM_V17_MBR_IDx */\n+\tuint8_t mbr_idx[14];\n+\tuint32_t vol_idx : 3; /* 722:720 (3) */\n+\tuint32_t stat_prof : 4; /* 726:723 (4) */\n+\tuint32_t prio : 2; /* 728:727 (2) */\n+\tuint32_t ent : 1; /* 729:729 (1) */\n+\tuint32_t op : 4; /* 733:730 (4) */\n+\tuint32_t dscp : 6; /* 739:734 (6) */\n+\tuint32_t qfi : 6; /* 745:740 (6) */\n+\tuint32_t rqi : 1; /* 746:746 (1) */\n+\tuint32_t nat_en : 1; /* 747:747 (1) */\n+\tuint32_t pad0 : 4; /* 751:748 (4) */\n+\tuint16_t pad1 : 15; /* 752:766 (15) */\n+\tuint16_t eor : 1; /* 767:767 (1) */\n+};\n+\n+struct flm_v17_inf_data_s {\n+\tuint64_t bytes;\n+\tuint64_t packets;\n+\tuint64_t ts;\n+\tuint64_t id0; /* id0 and id1 results in a 72-bit int */\n+\tuint32_t id1 : 8;\n+\tuint32_t cause : 3;\n+\tuint32_t pad : 20;\n+\tuint32_t eor : 1;\n+};\n+\n+struct flm_v17_sta_data_s {\n+\tuint64_t id0; /* id0 and id1 results in a 72-bit int */\n+\tuint32_t id1 : 8;\n+\tuint32_t lds : 1;\n+\tuint32_t lfs : 1;\n+\tuint32_t lis : 1;\n+\tuint32_t uds : 1;\n+\tuint32_t uis : 1;\n+\tuint32_t rds : 1;\n+\tuint32_t ris : 1;\n+\tuint32_t pds : 1;\n+\tuint32_t pis : 1;\n+\tuint32_t pad : 14;\n+\tuint32_t eor : 1;\n+};\n+\n+#pragma pack()\n+struct flm_v17_stat_lrn_done_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v17_stat_lrn_ignore_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v17_stat_lrn_fail_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v17_stat_unl_done_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v17_stat_unl_ignore_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v17_stat_rel_done_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v17_stat_rel_ignore_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v17_stat_aul_done_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v17_stat_aul_ignore_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v17_stat_aul_fail_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v17_stat_tul_done_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v17_stat_flows_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v17_stat_prb_done_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v17_stat_prb_ignore_s {\n+\tuint32_t cnt;\n+};\n+\n+struct hw_mod_flm_v17_s {\n+\tstruct flm_v17_control_s *control;\n+\tstruct flm_v17_status_s *status;\n+\tstruct flm_v17_timeout_s *timeout;\n+\tstruct flm_v17_scrub_s *scrub;\n+\tstruct flm_v17_load_bin_s *load_bin;\n+\tstruct flm_v17_load_pps_s *load_pps;\n+\tstruct flm_v17_load_lps_s *load_lps;\n+\tstruct flm_v17_load_aps_s *load_aps;\n+\tstruct flm_v17_prio_s *prio;\n+\tstruct flm_v17_pst_s *pst;\n+\tstruct flm_v17_rcp_s *rcp;\n+\tstruct flm_v17_buf_ctrl_s *buf_ctrl;\n+\t/* lrn_data is not handled by struct */\n+\t/* inf_data is not handled by struct */\n+\t/* sta_data is not handled by struct */\n+\tstruct flm_v17_stat_lrn_done_s *lrn_done;\n+\tstruct flm_v17_stat_lrn_ignore_s *lrn_ignore;\n+\tstruct flm_v17_stat_lrn_fail_s *lrn_fail;\n+\tstruct flm_v17_stat_unl_done_s *unl_done;\n+\tstruct flm_v17_stat_unl_ignore_s *unl_ignore;\n+\tstruct flm_v17_stat_rel_done_s *rel_done;\n+\tstruct flm_v17_stat_rel_ignore_s *rel_ignore;\n+\tstruct flm_v17_stat_aul_done_s *aul_done;\n+\tstruct flm_v17_stat_aul_ignore_s *aul_ignore;\n+\tstruct flm_v17_stat_aul_fail_s *aul_fail;\n+\tstruct flm_v17_stat_tul_done_s *tul_done;\n+\tstruct flm_v17_stat_flows_s *flows;\n+\tstruct flm_v17_stat_prb_done_s *prb_done;\n+\tstruct flm_v17_stat_prb_ignore_s *prb_ignore;\n+};\n+\n+#endif /* _HW_MOD_FLM_V17_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h\nnew file mode 100644\nindex 0000000000..e33d4353c3\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h\n@@ -0,0 +1,102 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_FLM_V20_H_\n+#define _HW_MOD_FLM_V20_H_\n+\n+struct flm_v20_stat_sta_done_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v20_stat_inf_done_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v20_stat_inf_skip_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v20_stat_pck_hit_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v20_stat_pck_miss_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v20_stat_pck_unh_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v20_stat_pck_dis_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v20_stat_csh_hit_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v20_stat_csh_miss_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v20_stat_csh_unh_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v20_stat_cuc_start_s {\n+\tuint32_t cnt;\n+};\n+\n+struct flm_v20_stat_cuc_move_s {\n+\tuint32_t cnt;\n+};\n+\n+struct hw_mod_flm_v20_s {\n+\tstruct flm_v17_control_s *control;\n+\tstruct flm_v17_status_s *status;\n+\tstruct flm_v17_timeout_s *timeout;\n+\tstruct flm_v17_scrub_s *scrub;\n+\tstruct flm_v17_load_bin_s *load_bin;\n+\tstruct flm_v17_load_pps_s *load_pps;\n+\tstruct flm_v17_load_lps_s *load_lps;\n+\tstruct flm_v17_load_aps_s *load_aps;\n+\tstruct flm_v17_prio_s *prio;\n+\tstruct flm_v17_pst_s *pst;\n+\tstruct flm_v17_rcp_s *rcp;\n+\tstruct flm_v17_buf_ctrl_s *buf_ctrl;\n+\t/*\n+\t * lrn_data is not handled by struct\n+\t * inf_data is not handled by struct\n+\t * sta_data is not handled by struct\n+\t */\n+\tstruct flm_v17_stat_lrn_done_s *lrn_done;\n+\tstruct flm_v17_stat_lrn_ignore_s *lrn_ignore;\n+\tstruct flm_v17_stat_lrn_fail_s *lrn_fail;\n+\tstruct flm_v17_stat_unl_done_s *unl_done;\n+\tstruct flm_v17_stat_unl_ignore_s *unl_ignore;\n+\tstruct flm_v17_stat_rel_done_s *rel_done;\n+\tstruct flm_v17_stat_rel_ignore_s *rel_ignore;\n+\tstruct flm_v17_stat_aul_done_s *aul_done;\n+\tstruct flm_v17_stat_aul_ignore_s *aul_ignore;\n+\tstruct flm_v17_stat_aul_fail_s *aul_fail;\n+\tstruct flm_v17_stat_tul_done_s *tul_done;\n+\tstruct flm_v17_stat_flows_s *flows;\n+\tstruct flm_v17_stat_prb_done_s *prb_done;\n+\tstruct flm_v17_stat_prb_ignore_s *prb_ignore;\n+\tstruct flm_v20_stat_sta_done_s *sta_done;\n+\tstruct flm_v20_stat_inf_done_s *inf_done;\n+\tstruct flm_v20_stat_inf_skip_s *inf_skip;\n+\tstruct flm_v20_stat_pck_hit_s *pck_hit;\n+\tstruct flm_v20_stat_pck_miss_s *pck_miss;\n+\tstruct flm_v20_stat_pck_unh_s *pck_unh;\n+\tstruct flm_v20_stat_pck_dis_s *pck_dis;\n+\tstruct flm_v20_stat_csh_hit_s *csh_hit;\n+\tstruct flm_v20_stat_csh_miss_s *csh_miss;\n+\tstruct flm_v20_stat_csh_unh_s *csh_unh;\n+\tstruct flm_v20_stat_cuc_start_s *cuc_start;\n+\tstruct flm_v20_stat_cuc_move_s *cuc_move;\n+};\n+\n+#endif /* _HW_MOD_FLM_V20_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c\nnew file mode 100644\nindex 0000000000..1b8896d5c2\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c\n@@ -0,0 +1,195 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <string.h>\n+#include \"flow_api_backend.h\"\n+\n+#define _MOD_ \"HSH\"\n+#define _VER_ be->hsh.ver\n+\n+#define HSH_RCP_ENTRIES_V4 16\n+#define HSH_RCP_ENTRIES_V5 32\n+#define HSH_RCP_MAC_PORT_MASK_SIZE 4\n+#define HSH_RCP_WORD_MASK_SIZE 10\n+\n+bool hw_mod_hsh_present(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->get_hsh_present(be->be_dev);\n+}\n+\n+int hw_mod_hsh_alloc(struct flow_api_backend_s *be)\n+{\n+\t_VER_ = be->iface->get_hsh_version(be->be_dev);\n+\tNT_LOG(DBG, FILTER, \"HSH MODULE VERSION  %i.%i\\n\", VER_MAJOR(_VER_),\n+\t       VER_MINOR(_VER_));\n+\n+\tswitch (_VER_) {\n+\tcase 5:\n+\t\tbe->hsh.nb_rcp = HSH_RCP_ENTRIES_V5;\n+\t\tif (!callocate_mod(CAST_COMMON(&be->hsh), 1,\n+\t\t\t&be->hsh.v5.rcp,\n+\t\t\tbe->hsh.nb_rcp,\n+\t\t\tsizeof(struct hsh_v5_rcp_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\t/* end case 5 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\treturn 0;\n+}\n+\n+void hw_mod_hsh_free(struct flow_api_backend_s *be)\n+{\n+\tif (be->hsh.base) {\n+\t\tfree(be->hsh.base);\n+\t\tbe->hsh.base = NULL;\n+\t}\n+}\n+\n+int hw_mod_hsh_reset(struct flow_api_backend_s *be)\n+{\n+\t/* Zero entire cache area */\n+\tZERO_MOD_CACHE(&be->hsh);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT HSH RCP\\n\");\n+\treturn hw_mod_hsh_rcp_flush(be, 0, be->hsh.nb_rcp);\n+}\n+\n+int hw_mod_hsh_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->hsh.nb_rcp;\n+\tif ((start_idx + count) > (int)be->hsh.nb_rcp)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->hsh_rcp_flush(be->be_dev, &be->hsh, start_idx, count);\n+}\n+\n+static int hw_mod_hsh_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_hsh_e field, uint32_t index,\n+\t\t\t      uint32_t word_off, uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->hsh.nb_rcp)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 5:\n+\t\tswitch (field) {\n+\t\tcase HW_HSH_RCP_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->hsh.v5.rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct hsh_v5_rcp_s));\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_COMPARE:\n+\t\t\trv = do_compare_indexes(be->hsh.v5.rcp,\n+\t\t\t\tsizeof(struct hsh_v5_rcp_s), index, word_off,\n+\t\t\t\tbe->hsh.nb_rcp, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_FIND:\n+\t\t\trv = find_equal_index(be->hsh.v5.rcp,\n+\t\t\t\tsizeof(struct hsh_v5_rcp_s), index, word_off,\n+\t\t\t\tbe->hsh.nb_rcp, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_LOAD_DIST_TYPE:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].load_dist_type, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_MAC_PORT_MASK:\n+\t\t\tif (word_off > HSH_RCP_MAC_PORT_MASK_SIZE)\n+\t\t\t\treturn error_word_off_too_large(__func__);\n+\t\t\tget_set(&be->hsh.v5.rcp[index].mac_port_mask[word_off],\n+\t\t\t\tvalue, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_SORT:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].sort, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_QW0_PE:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].qw0_pe, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_QW0_OFS:\n+\t\t\tget_set_signed(&be->hsh.v5.rcp[index].qw0_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_QW4_PE:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].qw4_pe, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_QW4_OFS:\n+\t\t\tget_set_signed(&be->hsh.v5.rcp[index].qw4_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_W8_PE:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].w8_pe, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_W8_OFS:\n+\t\t\tget_set_signed(&be->hsh.v5.rcp[index].w8_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_W8_SORT:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].w8_sort, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_W9_PE:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].w9_pe, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_W9_OFS:\n+\t\t\tget_set_signed(&be->hsh.v5.rcp[index].w9_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_W9_SORT:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].w9_sort, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_W9_P:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].w9_p, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_P_MASK:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].p_mask, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_WORD_MASK:\n+\t\t\tif (word_off > HSH_RCP_WORD_MASK_SIZE)\n+\t\t\t\treturn error_word_off_too_large(__func__);\n+\t\t\tget_set(&be->hsh.v5.rcp[index].word_mask[word_off],\n+\t\t\t\tvalue, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_SEED:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].seed, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_TNL_P:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].tnl_p, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_HSH_VALID:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].hsh_valid, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_HSH_TYPE:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].hsh_type, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HSH_RCP_AUTO_IPV4_MASK:\n+\t\t\tget_set(&be->hsh.v5.rcp[index].auto_ipv4_mask, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 5 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_hsh_rcp_set(struct flow_api_backend_s *be, enum hw_hsh_e field,\n+\t\t       uint32_t index, uint32_t word_off, uint32_t value)\n+{\n+\treturn hw_mod_hsh_rcp_mod(be, field, index, word_off, &value, 0);\n+}\n+\n+int hw_mod_hsh_rcp_get(struct flow_api_backend_s *be, enum hw_hsh_e field,\n+\t\t       uint32_t index, uint32_t word_off, uint32_t *value)\n+{\n+\treturn hw_mod_hsh_rcp_mod(be, field, index, word_off, value, 1);\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h\nnew file mode 100644\nindex 0000000000..8588750ff0\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h\n@@ -0,0 +1,36 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_HSH_V5_H_\n+#define _HW_MOD_HSH_V5_H_\n+\n+struct hsh_v5_rcp_s {\n+\tuint32_t load_dist_type;\n+\tuint32_t mac_port_mask[4];\n+\tuint32_t sort;\n+\tuint32_t qw0_pe;\n+\tint32_t qw0_ofs;\n+\tuint32_t qw4_pe;\n+\tint32_t qw4_ofs;\n+\tuint32_t w8_pe;\n+\tint32_t w8_ofs;\n+\tuint32_t w8_sort;\n+\tuint32_t w9_pe;\n+\tint32_t w9_ofs;\n+\tuint32_t w9_sort;\n+\tuint32_t w9_p;\n+\tuint32_t p_mask;\n+\tuint32_t word_mask[10];\n+\tuint32_t seed;\n+\tuint32_t tnl_p;\n+\tuint32_t hsh_valid;\n+\tuint32_t hsh_type;\n+\tuint32_t auto_ipv4_mask;\n+};\n+\n+struct hw_mod_hsh_v5_s {\n+\tstruct hsh_v5_rcp_s *rcp;\n+};\n+\n+#endif /* _HW_MOD_HSH_V5_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c\nnew file mode 100644\nindex 0000000000..751c7b3ffe\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c\n@@ -0,0 +1,178 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include \"flow_api_backend.h\"\n+\n+#define _MOD_ \"HST\"\n+#define _VER_ be->hst.ver\n+\n+bool hw_mod_hst_present(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->get_hst_present(be->be_dev);\n+}\n+\n+int hw_mod_hst_alloc(struct flow_api_backend_s *be)\n+{\n+\tint nb;\n+\n+\t_VER_ = be->iface->get_hst_version(be->be_dev);\n+\tNT_LOG(DBG, FILTER, \"HST MODULE VERSION %i.%i\\n\", VER_MAJOR(_VER_),\n+\t       VER_MINOR(_VER_));\n+\n+\tnb = be->iface->get_nb_hst_categories(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"hst_categories\", _MOD_, _VER_);\n+\tbe->hst.nb_hst_rcp_categories = (uint32_t)nb;\n+\n+\tswitch (_VER_) {\n+\tcase 2:\n+\t\tif (!callocate_mod(CAST_COMMON(&be->hst), 1,\n+\t\t\t&be->hst.v2.rcp,\n+\t\t\tbe->hst.nb_hst_rcp_categories,\n+\t\t\tsizeof(struct hst_v2_rcp_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\t/* end case 2 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void hw_mod_hst_free(struct flow_api_backend_s *be)\n+{\n+\tif (be->hst.base) {\n+\t\tfree(be->hst.base);\n+\t\tbe->hst.base = NULL;\n+\t}\n+}\n+\n+int hw_mod_hst_reset(struct flow_api_backend_s *be)\n+{\n+\t/* Zero entire cache area */\n+\tZERO_MOD_CACHE(&be->hst);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT HST RCP\\n\");\n+\treturn hw_mod_hst_rcp_flush(be, 0, ALL_ENTRIES);\n+}\n+\n+int hw_mod_hst_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->hst.nb_hst_rcp_categories;\n+\tif ((unsigned int)(start_idx + count) > be->hst.nb_hst_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->hst_rcp_flush(be->be_dev, &be->hst, start_idx, count);\n+}\n+\n+static int hw_mod_hst_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_hst_e field, uint32_t index,\n+\t\t\t      uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->hst.nb_hst_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 2:\n+\t\tswitch (field) {\n+\t\tcase HW_HST_RCP_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->hst.v2.rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct hst_v2_rcp_s));\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_FIND:\n+\t\t\tfind_equal_index(be->hst.v2.rcp,\n+\t\t\t\tsizeof(struct hst_v2_rcp_s), index, *value,\n+\t\t\t\tbe->hst.nb_hst_rcp_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_COMPARE:\n+\t\t\trv = do_compare_indexes(be->hst.v2.rcp,\n+\t\t\t\tsizeof(struct hst_v2_rcp_s), index, *value,\n+\t\t\t\tbe->hst.nb_hst_rcp_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_STRIP_MODE:\n+\t\t\tget_set(&be->hst.v2.rcp[index].strip_mode, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_START_DYN:\n+\t\t\tget_set(&be->hst.v2.rcp[index].start_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_START_OFS:\n+\t\t\tget_set(&be->hst.v2.rcp[index].start_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_END_DYN:\n+\t\t\tget_set(&be->hst.v2.rcp[index].end_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_END_OFS:\n+\t\t\tget_set(&be->hst.v2.rcp[index].end_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_MODIF0_CMD:\n+\t\t\tget_set(&be->hst.v2.rcp[index].modif0_cmd, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_MODIF0_DYN:\n+\t\t\tget_set(&be->hst.v2.rcp[index].modif0_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_MODIF0_OFS:\n+\t\t\tget_set(&be->hst.v2.rcp[index].modif0_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_MODIF0_VALUE:\n+\t\t\tget_set(&be->hst.v2.rcp[index].modif0_value, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_MODIF1_CMD:\n+\t\t\tget_set(&be->hst.v2.rcp[index].modif1_cmd, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_MODIF1_DYN:\n+\t\t\tget_set(&be->hst.v2.rcp[index].modif1_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_MODIF1_OFS:\n+\t\t\tget_set(&be->hst.v2.rcp[index].modif1_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_MODIF1_VALUE:\n+\t\t\tget_set(&be->hst.v2.rcp[index].modif1_value, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_MODIF2_CMD:\n+\t\t\tget_set(&be->hst.v2.rcp[index].modif2_cmd, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_MODIF2_DYN:\n+\t\t\tget_set(&be->hst.v2.rcp[index].modif2_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_MODIF2_OFS:\n+\t\t\tget_set(&be->hst.v2.rcp[index].modif2_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_HST_RCP_MODIF2_VALUE:\n+\t\t\tget_set(&be->hst.v2.rcp[index].modif2_value, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 2 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_hst_rcp_set(struct flow_api_backend_s *be, enum hw_hst_e field,\n+\t\t       int index, uint32_t value)\n+{\n+\treturn hw_mod_hst_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_hst_rcp_get(struct flow_api_backend_s *be, enum hw_hst_e field,\n+\t\t       int index, uint32_t *value)\n+{\n+\treturn hw_mod_hst_rcp_mod(be, field, index, value, 1);\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h\nnew file mode 100644\nindex 0000000000..230c70b56d\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h\n@@ -0,0 +1,32 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_HST_V2_H_\n+#define _HW_MOD_HST_V2_H_\n+\n+struct hst_v2_rcp_s {\n+\tuint32_t strip_mode;\n+\tuint32_t start_dyn;\n+\tuint32_t start_ofs;\n+\tuint32_t end_dyn;\n+\tuint32_t end_ofs;\n+\tuint32_t modif0_cmd;\n+\tuint32_t modif0_dyn;\n+\tuint32_t modif0_ofs;\n+\tuint32_t modif0_value;\n+\tuint32_t modif1_cmd;\n+\tuint32_t modif1_dyn;\n+\tuint32_t modif1_ofs;\n+\tuint32_t modif1_value;\n+\tuint32_t modif2_cmd;\n+\tuint32_t modif2_dyn;\n+\tuint32_t modif2_ofs;\n+\tuint32_t modif2_value;\n+};\n+\n+struct hw_mod_hst_v2_s {\n+\tstruct hst_v2_rcp_s *rcp;\n+};\n+\n+#endif /* _HW_MOD_HST_V2_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c\nnew file mode 100644\nindex 0000000000..c8e3593637\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c\n@@ -0,0 +1,271 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <string.h>\n+#include \"flow_api_backend.h\"\n+\n+#define _MOD_ \"IOA\"\n+#define _VER_ be->ioa.ver\n+\n+bool hw_mod_ioa_present(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->get_ioa_present(be->be_dev);\n+}\n+\n+int hw_mod_ioa_alloc(struct flow_api_backend_s *be)\n+{\n+\t_VER_ = be->iface->get_ioa_version(be->be_dev);\n+\tNT_LOG(DBG, FILTER, \"IOA MODULE VERSION  %i.%i\\n\", VER_MAJOR(_VER_),\n+\t       VER_MINOR(_VER_));\n+\n+\tint nb = be->iface->get_nb_ioa_categories(be->be_dev);\n+\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"ioa_categories\", _MOD_, _VER_);\n+\tbe->ioa.nb_rcp_categories = (uint32_t)nb;\n+\n+\t/* NOTE: ROA number of categories are called here. FPGA uses a cross-indexing here - bad! */\n+\tnb = be->iface->get_nb_roa_categories(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"roa_epp_entries\", _MOD_, _VER_);\n+\tbe->ioa.nb_roa_epp_entries = (uint32_t)nb;\n+\n+\tswitch (_VER_) {\n+\tcase 4:\n+\t\tif (!callocate_mod(CAST_COMMON(&be->ioa), 3,\n+\t\t\t&be->ioa.v4.rcp, be->ioa.nb_rcp_categories,\n+\t\t\tsizeof(struct ioa_v4_rcp_s),\n+\t\t\t&be->ioa.v4.tpid, 1,\n+\t\t\tsizeof(struct ioa_v4_special_tpid_s),\n+\t\t\t&be->ioa.v4.roa_epp, be->ioa.nb_roa_epp_entries,\n+\t\t\tsizeof(struct ioa_v4_roa_epp_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\t/* end case 4 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\treturn 0;\n+}\n+\n+void hw_mod_ioa_free(struct flow_api_backend_s *be)\n+{\n+\tif (be->ioa.base) {\n+\t\tfree(be->ioa.base);\n+\t\tbe->ioa.base = NULL;\n+\t}\n+}\n+\n+int hw_mod_ioa_reset(struct flow_api_backend_s *be)\n+{\n+\t/* Zero entire cache area */\n+\tZERO_MOD_CACHE(&be->ioa);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT IOA RCP\\n\");\n+\thw_mod_ioa_rcp_flush(be, 0, ALL_ENTRIES);\n+\tNT_LOG(DBG, FILTER, \"INIT IOA SPECIAL TPID\\n\");\n+\thw_mod_ioa_config_set(be, HW_IOA_CONFIG_CUST_TPID_0, 0x8200);\n+\thw_mod_ioa_config_set(be, HW_IOA_CONFIG_CUST_TPID_1, 0x8300);\n+\thw_mod_ioa_config_flush(be);\n+\tNT_LOG(DBG, FILTER, \"INIT IOA ROA EPP\\n\");\n+\thw_mod_ioa_roa_epp_flush(be, 0, ALL_ENTRIES);\n+\treturn 0;\n+}\n+\n+int hw_mod_ioa_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->ioa.nb_rcp_categories;\n+\tif ((unsigned int)(start_idx + count) > be->ioa.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->ioa_rcp_flush(be->be_dev, &be->ioa, start_idx, count);\n+}\n+\n+static int hw_mod_ioa_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_ioa_e field, uint32_t index,\n+\t\t\t      uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->ioa.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 4:\n+\t\tswitch (field) {\n+\t\tcase HW_IOA_RCP_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->ioa.v4.rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct ioa_v4_rcp_s));\n+\t\t\tbreak;\n+\t\tcase HW_IOA_RCP_FIND:\n+\t\t\trv = find_equal_index(be->ioa.v4.rcp,\n+\t\t\t\tsizeof(struct ioa_v4_rcp_s), index, *value,\n+\t\t\t\tbe->ioa.nb_rcp_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_IOA_RCP_COMPARE:\n+\t\t\trv = do_compare_indexes(be->ioa.v4.rcp,\n+\t\t\t\tsizeof(struct ioa_v4_rcp_s), index, *value,\n+\t\t\t\tbe->ioa.nb_rcp_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_IOA_RCP_TUNNEL_POP:\n+\t\t\tget_set(&be->ioa.v4.rcp[index].tunnel_pop, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_IOA_RCP_VLAN_POP:\n+\t\t\tget_set(&be->ioa.v4.rcp[index].vlan_pop, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_IOA_RCP_VLAN_PUSH:\n+\t\t\tget_set(&be->ioa.v4.rcp[index].vlan_push, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_IOA_RCP_VLAN_VID:\n+\t\t\tget_set(&be->ioa.v4.rcp[index].vlan_vid, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_IOA_RCP_VLAN_DEI:\n+\t\t\tget_set(&be->ioa.v4.rcp[index].vlan_dei, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_IOA_RCP_VLAN_PCP:\n+\t\t\tget_set(&be->ioa.v4.rcp[index].vlan_pcp, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_IOA_RCP_VLAN_TPID_SEL:\n+\t\t\tget_set(&be->ioa.v4.rcp[index].vlan_tpid_sel, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_IOA_RCP_QUEUE_OVERRIDE_EN:\n+\t\t\tget_set(&be->ioa.v4.rcp[index].queue_override_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_IOA_RCP_QUEUE_ID:\n+\t\t\tget_set(&be->ioa.v4.rcp[index].queue_id, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 4 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_ioa_rcp_set(struct flow_api_backend_s *be, enum hw_ioa_e field,\n+\t\t       uint32_t index, uint32_t value)\n+{\n+\treturn hw_mod_ioa_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_ioa_rcp_get(struct flow_api_backend_s *be, enum hw_ioa_e field,\n+\t\t       uint32_t index, uint32_t *value)\n+{\n+\treturn hw_mod_ioa_rcp_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_ioa_config_flush(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->ioa_special_tpid_flush(be->be_dev, &be->ioa);\n+}\n+\n+int hw_mod_ioa_config_set(struct flow_api_backend_s *be, enum hw_ioa_e field,\n+\t\t\t  uint32_t value)\n+{\n+\tswitch (_VER_) {\n+\tcase 4:\n+\t\tswitch (field) {\n+\t\tcase HW_IOA_CONFIG_CUST_TPID_0:\n+\t\t\tbe->ioa.v4.tpid->cust_tpid_0 = value;\n+\t\t\tbreak;\n+\t\tcase HW_IOA_CONFIG_CUST_TPID_1:\n+\t\t\tbe->ioa.v4.tpid->cust_tpid_1 = value;\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 4 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_ioa_roa_epp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->ioa.nb_roa_epp_entries;\n+\tif ((unsigned int)(start_idx + count) > be->ioa.nb_roa_epp_entries)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->ioa_roa_epp_flush(be->be_dev, &be->ioa, start_idx,\n+\t\t\t\t\t    count);\n+}\n+\n+static int hw_mod_ioa_roa_epp_mod(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_ioa_e field, uint32_t index,\n+\t\t\t\t  uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->ioa.nb_roa_epp_entries)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 4:\n+\t\tswitch (field) {\n+\t\tcase HW_IOA_ROA_EPP_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->ioa.v4.roa_epp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct ioa_v4_roa_epp_s));\n+\t\t\tbreak;\n+\t\tcase HW_IOA_ROA_EPP_FIND:\n+\t\t\trv = find_equal_index(be->ioa.v4.roa_epp,\n+\t\t\t\tsizeof(struct ioa_v4_roa_epp_s), index, *value,\n+\t\t\t\tbe->ioa.nb_roa_epp_entries, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_IOA_ROA_EPP_COMPARE:\n+\t\t\trv = do_compare_indexes(be->ioa.v4.roa_epp,\n+\t\t\t\tsizeof(struct ioa_v4_roa_epp_s), index, *value,\n+\t\t\t\tbe->ioa.nb_roa_epp_entries, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_IOA_ROA_EPP_PUSH_TUNNEL:\n+\t\t\tget_set(&be->ioa.v4.roa_epp[index].push_tunnel, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_IOA_ROA_EPP_TX_PORT:\n+\t\t\tget_set(&be->ioa.v4.roa_epp[index].tx_port, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 4 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_ioa_roa_epp_set(struct flow_api_backend_s *be, enum hw_ioa_e field,\n+\t\t\t   uint32_t index, uint32_t value)\n+{\n+\treturn hw_mod_ioa_roa_epp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_ioa_roa_epp_get(struct flow_api_backend_s *be, enum hw_ioa_e field,\n+\t\t\t   uint32_t index, uint32_t *value)\n+{\n+\treturn hw_mod_ioa_roa_epp_mod(be, field, index, value, 1);\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h\nnew file mode 100644\nindex 0000000000..309b53ff76\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h\n@@ -0,0 +1,36 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_IOA_V4_H_\n+#define _HW_MOD_IOA_V4_H_\n+\n+struct ioa_v4_rcp_s {\n+\tuint32_t tunnel_pop;\n+\tuint32_t vlan_pop;\n+\tuint32_t vlan_push;\n+\tuint32_t vlan_vid;\n+\tuint32_t vlan_dei;\n+\tuint32_t vlan_pcp;\n+\tuint32_t vlan_tpid_sel;\n+\tuint32_t queue_override_en;\n+\tuint32_t queue_id;\n+};\n+\n+struct ioa_v4_special_tpid_s {\n+\tuint32_t cust_tpid_0;\n+\tuint32_t cust_tpid_1;\n+};\n+\n+struct ioa_v4_roa_epp_s {\n+\tuint32_t push_tunnel;\n+\tuint32_t tx_port;\n+};\n+\n+struct hw_mod_ioa_v4_s {\n+\tstruct ioa_v4_rcp_s *rcp;\n+\tstruct ioa_v4_special_tpid_s *tpid;\n+\tstruct ioa_v4_roa_epp_s *roa_epp;\n+};\n+\n+#endif /* _HW_MOD_IOA_V4_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c\nnew file mode 100644\nindex 0000000000..a91f0e0a7d\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c\n@@ -0,0 +1,629 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <string.h>\n+#include \"flow_api_backend.h\"\n+\n+#define _MOD_ \"KM\"\n+#define _VER_ be->km.ver\n+\n+#define KM_TCQ_ENTRIES 2048\n+#define KM_RCP_MASK_A_SIZE 11\n+#define KM_RCP_MASK_D_A_SIZE \\\n+\t12 /* Mask for double size word extractors for DW8/DW10 */\n+#define KM_RCP_MASK_B_SIZE 6\n+\n+bool hw_mod_km_present(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->get_km_present(be->be_dev);\n+}\n+\n+int hw_mod_km_alloc(struct flow_api_backend_s *be)\n+{\n+\tint nb;\n+\n+\t_VER_ = be->iface->get_km_version(be->be_dev);\n+\tNT_LOG(DBG, FILTER, \"KM  MODULE VERSION  %i.%i\\n\", VER_MAJOR(_VER_),\n+\t       VER_MINOR(_VER_));\n+\n+\tnb = be->iface->get_nb_km_categories(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"km_categories\", _MOD_, _VER_);\n+\tbe->km.nb_categories = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_km_cam_banks(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"cam_banks\", _MOD_, _VER_);\n+\tbe->km.nb_cam_banks = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_km_cam_records(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"cam_records\", _MOD_, _VER_);\n+\tbe->km.nb_cam_records = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_km_cam_record_words(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"cam_record_words\", _MOD_, _VER_);\n+\tbe->km.nb_cam_record_words = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_km_tcam_banks(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"tcam_banks\", _MOD_, _VER_);\n+\tbe->km.nb_tcam_banks = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_km_tcam_bank_width(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"tcam_bank_width\", _MOD_, _VER_);\n+\tbe->km.nb_tcam_bank_width = (uint32_t)nb;\n+\n+\tswitch (_VER_) {\n+\tcase 7:\n+\t\tbe->km.nb_km_rcp_mask_a_word_size = 12;\n+\t\tbe->km.nb_km_rcp_mask_b_word_size = 6;\n+\t\tif (!callocate_mod(CAST_COMMON(&be->km), 5,\n+\t\t\t&be->km.v7.rcp,\n+\t\t\tbe->km.nb_categories,\n+\t\t\tsizeof(struct km_v7_rcp_s),\n+\t\t\t&be->km.v7.cam,\n+\t\t\tbe->km.nb_cam_banks * be->km.nb_cam_records,\n+\t\t\tsizeof(struct km_v7_cam_s),\n+\t\t\t&be->km.v7.tcam,\n+\t\t\tbe->km.nb_tcam_banks * 4 * 256,\n+\t\t\tsizeof(struct km_v7_tcam_s),\n+\t\t\t&be->km.v7.tci,\n+\t\t\tbe->km.nb_tcam_banks * be->km.nb_tcam_bank_width,\n+\t\t\tsizeof(struct km_v7_tci_s),\n+\t\t\t&be->km.v7.tcq,\n+\t\t\tKM_TCQ_ENTRIES,\n+\t\t\tsizeof(struct km_v7_tcq_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\t/* end case 7 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void hw_mod_km_free(struct flow_api_backend_s *be)\n+{\n+\tif (be->km.base) {\n+\t\tfree(be->km.base);\n+\t\tbe->km.base = NULL;\n+\t}\n+}\n+\n+int hw_mod_km_reset(struct flow_api_backend_s *be)\n+{\n+\tuint32_t tcam_v_set[3] = { 0x00000000, 0x00000000, 0x00000000 };\n+\t/*  int err = 0; */\n+\n+\t/* Zero entire cache area */\n+\tZERO_MOD_CACHE(&be->km);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT KM RCP\\n\");\n+\thw_mod_km_rcp_flush(be, 0, ALL_ENTRIES);\n+\n+\t/* init CAM - all zero */\n+\tNT_LOG(DBG, FILTER, \"INIT KM CAM\\n\");\n+\thw_mod_km_cam_flush(be, 0, 0, ALL_ENTRIES);\n+\n+\t/* init TCAM - all zero */\n+\tNT_LOG(DBG, FILTER, \"INIT KM TCAM\\n\");\n+\tfor (unsigned int i = 0; i < be->km.nb_tcam_banks; i++) {\n+\t\t/*\n+\t\t * TCAM entries are cache controlled, thus need to hard reset initially to sync\n+\t\t * cache with HW\n+\t\t */\n+\t\thw_mod_km_tcam_set(be, HW_KM_TCAM_BANK_RESET, i, 0, 0,\n+\t\t\t\t   tcam_v_set);\n+\t}\n+\thw_mod_km_tcam_flush(be, 0, ALL_ENTRIES);\n+\n+\t/* init TCI - all zero */\n+\tNT_LOG(DBG, FILTER, \"INIT KM TCI\\n\");\n+\thw_mod_km_tci_flush(be, 0, 0, ALL_ENTRIES);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT KM TCQ\\n\");\n+\tfor (unsigned int i = 0; i < be->km.nb_tcam_bank_width; i++)\n+\t\thw_mod_km_tcq_flush(be, 0, i, be->km.nb_tcam_banks);\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_km_rcp_flush(struct flow_api_backend_s *be, int start_idx, int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->km.nb_categories;\n+\tif ((unsigned int)(start_idx + count) > be->km.nb_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->km_rcp_flush(be->be_dev, &be->km, start_idx, count);\n+}\n+\n+static int hw_mod_km_rcp_mod(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t\t     int index, int word_off, uint32_t *value, int get)\n+{\n+\tif ((unsigned int)index >= be->km.nb_categories)\n+\t\treturn error_index_too_large(__func__);\n+\n+\tswitch (_VER_) {\n+\tcase 7:\n+\t\tswitch (field) {\n+\t\tcase HW_KM_RCP_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->km.v7.rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct km_v7_rcp_s));\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_QW0_DYN:\n+\t\t\tget_set(&be->km.v7.rcp[index].qw0_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_QW0_OFS:\n+\t\t\tget_set_signed(&be->km.v7.rcp[index].qw0_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_QW0_SEL_A:\n+\t\t\tget_set(&be->km.v7.rcp[index].qw0_sel_a, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_QW0_SEL_B:\n+\t\t\tget_set(&be->km.v7.rcp[index].qw0_sel_b, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_QW4_DYN:\n+\t\t\tget_set(&be->km.v7.rcp[index].qw4_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_QW4_OFS:\n+\t\t\tget_set_signed(&be->km.v7.rcp[index].qw4_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_QW4_SEL_A:\n+\t\t\tget_set(&be->km.v7.rcp[index].qw4_sel_a, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_QW4_SEL_B:\n+\t\t\tget_set(&be->km.v7.rcp[index].qw4_sel_b, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_DW8_DYN:\n+\t\t\tget_set(&be->km.v7.rcp[index].dw8_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_DW8_OFS:\n+\t\t\tget_set_signed(&be->km.v7.rcp[index].dw8_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_DW8_SEL_A:\n+\t\t\tget_set(&be->km.v7.rcp[index].dw8_sel_a, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_DW8_SEL_B:\n+\t\t\tget_set(&be->km.v7.rcp[index].dw8_sel_b, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_DW10_DYN:\n+\t\t\tget_set(&be->km.v7.rcp[index].dw10_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_DW10_OFS:\n+\t\t\tget_set_signed(&be->km.v7.rcp[index].dw10_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_DW10_SEL_A:\n+\t\t\tget_set(&be->km.v7.rcp[index].dw10_sel_a, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_DW10_SEL_B:\n+\t\t\tget_set(&be->km.v7.rcp[index].dw10_sel_b, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_SWX_CCH:\n+\t\t\tget_set(&be->km.v7.rcp[index].swx_cch, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_SWX_SEL_A:\n+\t\t\tget_set(&be->km.v7.rcp[index].swx_sel_a, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_SWX_SEL_B:\n+\t\t\tget_set(&be->km.v7.rcp[index].swx_sel_b, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_MASK_A:\n+\t\t\tif (word_off > KM_RCP_MASK_D_A_SIZE)\n+\t\t\t\treturn error_word_off_too_large(__func__);\n+\t\t\tget_set(&be->km.v7.rcp[index].mask_d_a[word_off], value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_MASK_B:\n+\t\t\tif (word_off > KM_RCP_MASK_B_SIZE)\n+\t\t\t\treturn error_word_off_too_large(__func__);\n+\t\t\tget_set(&be->km.v7.rcp[index].mask_b[word_off], value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_DUAL:\n+\t\t\tget_set(&be->km.v7.rcp[index].dual, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_PAIRED:\n+\t\t\tget_set(&be->km.v7.rcp[index].paired, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_EL_A:\n+\t\t\tget_set(&be->km.v7.rcp[index].el_a, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_EL_B:\n+\t\t\tget_set(&be->km.v7.rcp[index].el_b, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_INFO_A:\n+\t\t\tget_set(&be->km.v7.rcp[index].info_a, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_INFO_B:\n+\t\t\tget_set(&be->km.v7.rcp[index].info_b, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_FTM_A:\n+\t\t\tget_set(&be->km.v7.rcp[index].ftm_a, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_FTM_B:\n+\t\t\tget_set(&be->km.v7.rcp[index].ftm_b, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_BANK_A:\n+\t\t\tget_set(&be->km.v7.rcp[index].bank_a, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_BANK_B:\n+\t\t\tget_set(&be->km.v7.rcp[index].bank_b, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_KL_A:\n+\t\t\tget_set(&be->km.v7.rcp[index].kl_a, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_KL_B:\n+\t\t\tget_set(&be->km.v7.rcp[index].kl_b, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_KEYWAY_A:\n+\t\t\tget_set(&be->km.v7.rcp[index].keyway_a, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_KEYWAY_B:\n+\t\t\tget_set(&be->km.v7.rcp[index].keyway_b, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_SYNERGY_MODE:\n+\t\t\tget_set(&be->km.v7.rcp[index].synergy_mode, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_DW0_B_DYN:\n+\t\t\tget_set(&be->km.v7.rcp[index].dw0_b_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_DW0_B_OFS:\n+\t\t\tget_set_signed(&be->km.v7.rcp[index].dw0_b_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_DW2_B_DYN:\n+\t\t\tget_set(&be->km.v7.rcp[index].dw2_b_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_DW2_B_OFS:\n+\t\t\tget_set_signed(&be->km.v7.rcp[index].dw2_b_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_SW4_B_DYN:\n+\t\t\tget_set(&be->km.v7.rcp[index].sw4_b_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_SW4_B_OFS:\n+\t\t\tget_set_signed(&be->km.v7.rcp[index].sw4_b_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_SW5_B_DYN:\n+\t\t\tget_set(&be->km.v7.rcp[index].sw5_b_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_RCP_SW5_B_OFS:\n+\t\t\tget_set_signed(&be->km.v7.rcp[index].sw5_b_ofs, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 7 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_km_rcp_set(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int index, int word_off, uint32_t value)\n+{\n+\treturn hw_mod_km_rcp_mod(be, field, index, word_off, &value, 0);\n+}\n+\n+int hw_mod_km_rcp_get(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int index, int word_off, uint32_t *value)\n+{\n+\treturn hw_mod_km_rcp_mod(be, field, index, word_off, value, 1);\n+}\n+\n+int hw_mod_km_cam_flush(struct flow_api_backend_s *be, int start_bank,\n+\t\t\tint start_record, int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->km.nb_cam_records * be->km.nb_cam_banks;\n+\n+\tunsigned int end =\n+\t\tstart_bank * be->km.nb_cam_records + start_record + count;\n+\tif (end > (be->km.nb_cam_banks * be->km.nb_cam_records))\n+\t\treturn error_index_too_large(__func__);\n+\n+\treturn be->iface->km_cam_flush(be->be_dev, &be->km, start_bank,\n+\t\t\t\t       start_record, count);\n+}\n+\n+static int hw_mod_km_cam_mod(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t\t     int bank, int record, uint32_t *value, int get)\n+{\n+\tif ((unsigned int)bank >= be->km.nb_cam_banks)\n+\t\treturn error_index_too_large(__func__);\n+\tif ((unsigned int)record >= be->km.nb_cam_records)\n+\t\treturn error_index_too_large(__func__);\n+\n+\tunsigned int index = bank * be->km.nb_cam_records + record;\n+\n+\tswitch (_VER_) {\n+\tcase 7:\n+\t\tswitch (field) {\n+\t\tcase HW_KM_CAM_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->km.v7.cam[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct km_v7_cam_s));\n+\t\t\tbreak;\n+\t\tcase HW_KM_CAM_W0:\n+\t\t\tget_set(&be->km.v7.cam[index].w0, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_CAM_W1:\n+\t\t\tget_set(&be->km.v7.cam[index].w1, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_CAM_W2:\n+\t\t\tget_set(&be->km.v7.cam[index].w2, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_CAM_W3:\n+\t\t\tget_set(&be->km.v7.cam[index].w3, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_CAM_W4:\n+\t\t\tget_set(&be->km.v7.cam[index].w4, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_CAM_W5:\n+\t\t\tget_set(&be->km.v7.cam[index].w5, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_CAM_FT0:\n+\t\t\tget_set(&be->km.v7.cam[index].ft0, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_CAM_FT1:\n+\t\t\tget_set(&be->km.v7.cam[index].ft1, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_CAM_FT2:\n+\t\t\tget_set(&be->km.v7.cam[index].ft2, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_CAM_FT3:\n+\t\t\tget_set(&be->km.v7.cam[index].ft3, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_CAM_FT4:\n+\t\t\tget_set(&be->km.v7.cam[index].ft4, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_CAM_FT5:\n+\t\t\tget_set(&be->km.v7.cam[index].ft5, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 7 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\treturn 0;\n+}\n+\n+int hw_mod_km_cam_set(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int bank, int record, uint32_t value)\n+{\n+\treturn hw_mod_km_cam_mod(be, field, bank, record, &value, 0);\n+}\n+\n+int hw_mod_km_cam_get(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int bank, int record, uint32_t *value)\n+{\n+\treturn hw_mod_km_cam_mod(be, field, bank, record, value, 1);\n+}\n+\n+int hw_mod_km_tcam_flush(struct flow_api_backend_s *be, int start_bank,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->km.nb_tcam_banks * 4 * 256;\n+\telse if (count == ALL_BANK_ENTRIES)\n+\t\tcount = 4 * 256;\n+\n+\tunsigned int end = start_bank * 4 * 256 + count;\n+\n+\tif (end > (be->km.nb_tcam_banks * 4 * 256))\n+\t\treturn error_index_too_large(__func__);\n+\n+\treturn be->iface->km_tcam_flush(be->be_dev, &be->km, start_bank, 0, 0,\n+\t\t\t\t\tcount);\n+}\n+\n+static int hw_mod_km_tcam_mod(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t\t      int bank, int byte, int byte_val,\n+\t\t\t      uint32_t *value_set, int get)\n+{\n+\tunsigned int start_index = bank * 4 * 256 + (int)byte * 256 + byte_val;\n+\n+\tif (start_index >= (be->km.nb_tcam_banks * 4 * 256))\n+\t\treturn error_index_too_large(__func__);\n+\n+\tswitch (_VER_) {\n+\tcase 7:\n+\t\tswitch (field) {\n+\t\tcase HW_KM_TCAM_BANK_RESET:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\t{\n+\t\t\t\tint start_idx = bank * 4 * 256;\n+\n+\t\t\t\tfor (int i = 0; i < 4 * 256; i++) {\n+\t\t\t\t\tbe->km.v7.tcam[start_idx + i].t[0] =\n+\t\t\t\t\t\tvalue_set[0];\n+\t\t\t\t\tbe->km.v7.tcam[start_idx + i].t[1] =\n+\t\t\t\t\t\tvalue_set[1];\n+\t\t\t\t\tbe->km.v7.tcam[start_idx + i].t[2] =\n+\t\t\t\t\t\tvalue_set[2];\n+\t\t\t\t\tbe->km.v7.tcam[start_idx + i].dirty = 1;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase HW_KM_TCAM_T: {\n+\t\t\tint index = bank * 4 * 256 + byte * 256 + byte_val;\n+\n+\t\t\tif (get) {\n+\t\t\t\tvalue_set[0] = be->km.v7.tcam[index].t[0];\n+\t\t\t\tvalue_set[1] = be->km.v7.tcam[index].t[1];\n+\t\t\t\tvalue_set[2] = be->km.v7.tcam[index].t[2];\n+\t\t\t} else {\n+\t\t\t\t/* only change if any bits has to be changed */\n+\t\t\t\tif (be->km.v7.tcam[index].t[0] !=\n+\t\t\t\t\t\tvalue_set[0] ||\n+\t\t\t\t\t\tbe->km.v7.tcam[index].t[1] !=\n+\t\t\t\t\t\tvalue_set[1] ||\n+\t\t\t\t\t\tbe->km.v7.tcam[index].t[2] !=\n+\t\t\t\t\t\tvalue_set[2]) {\n+\t\t\t\t\tbe->km.v7.tcam[index].t[0] =\n+\t\t\t\t\t\tvalue_set[0];\n+\t\t\t\t\tbe->km.v7.tcam[index].t[1] =\n+\t\t\t\t\t\tvalue_set[1];\n+\t\t\t\t\tbe->km.v7.tcam[index].t[2] =\n+\t\t\t\t\t\tvalue_set[2];\n+\t\t\t\t\tbe->km.v7.tcam[index].dirty = 1;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 7 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\treturn 0;\n+}\n+\n+int hw_mod_km_tcam_set(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t       int bank, int byte, int byte_val, uint32_t *value_set)\n+{\n+\treturn hw_mod_km_tcam_mod(be, field, bank, byte, byte_val, value_set,\n+\t\t\t\t  0);\n+}\n+\n+int hw_mod_km_tcam_get(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t       int bank, int byte, int byte_val, uint32_t *value_set)\n+{\n+\treturn hw_mod_km_tcam_mod(be, field, bank, byte, byte_val, value_set,\n+\t\t\t\t  1);\n+}\n+\n+int hw_mod_km_tci_flush(struct flow_api_backend_s *be, int start_bank,\n+\t\t\tint start_record, int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->km.nb_tcam_banks * be->km.nb_tcam_bank_width;\n+\n+\tunsigned int end = (int)start_bank * be->km.nb_tcam_bank_width +\n+\t\t\t   start_record + count;\n+\n+\tif (end > (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width))\n+\t\treturn error_index_too_large(__func__);\n+\n+\treturn be->iface->km_tci_flush(be->be_dev, &be->km, start_bank,\n+\t\t\t\t       start_record, count);\n+}\n+\n+static int hw_mod_km_tci_mod(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t\t     int bank, int record, uint32_t *value, int get)\n+{\n+\tunsigned int index = bank * be->km.nb_tcam_bank_width + record;\n+\n+\tif (index >= (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width))\n+\t\treturn error_index_too_large(__func__);\n+\n+\tswitch (_VER_) {\n+\tcase 7:\n+\t\tswitch (field) {\n+\t\tcase HW_KM_TCI_COLOR:\n+\t\t\tget_set(&be->km.v7.tci[index].color, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_TCI_FT:\n+\t\t\tget_set(&be->km.v7.tci[index].ft, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 7 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\treturn 0;\n+}\n+\n+int hw_mod_km_tci_set(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int bank, int record, uint32_t value)\n+{\n+\treturn hw_mod_km_tci_mod(be, field, bank, record, &value, 0);\n+}\n+\n+int hw_mod_km_tci_get(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int bank, int record, uint32_t *value)\n+{\n+\treturn hw_mod_km_tci_mod(be, field, bank, record, value, 1);\n+}\n+\n+int hw_mod_km_tcq_flush(struct flow_api_backend_s *be, int start_bank,\n+\t\t\tint start_record, int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->km.nb_tcam_banks * be->km.nb_tcam_bank_width;\n+\n+\tunsigned int end = (int)start_bank * be->km.nb_tcam_bank_width +\n+\t\t\t   start_record + count;\n+\n+\tif (end > (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width))\n+\t\treturn error_index_too_large(__func__);\n+\n+\treturn be->iface->km_tcq_flush(be->be_dev, &be->km, start_bank,\n+\t\t\t\t       start_record, count);\n+}\n+\n+static int hw_mod_km_tcq_mod(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t\t     int bank, int record, uint32_t *value, int get)\n+{\n+\tunsigned int index = bank * be->km.nb_tcam_bank_width + record;\n+\n+\tif (index >= (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width))\n+\t\treturn error_index_too_large(__func__);\n+\n+\tswitch (_VER_) {\n+\tcase 7:\n+\t\tswitch (field) {\n+\t\tcase HW_KM_TCQ_BANK_MASK:\n+\t\t\tget_set(&be->km.v7.tcq[index].bank_mask, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_KM_TCQ_QUAL:\n+\t\t\tget_set(&be->km.v7.tcq[index].qual, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 7 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\treturn 0;\n+}\n+\n+int hw_mod_km_tcq_set(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int bank, int record, uint32_t *value)\n+{\n+\treturn hw_mod_km_tcq_mod(be, field, bank, record, value, 0);\n+}\n+\n+int hw_mod_km_tcq_get(struct flow_api_backend_s *be, enum hw_km_e field,\n+\t\t      int bank, int record, uint32_t *value)\n+{\n+\treturn hw_mod_km_tcq_mod(be, field, bank, record, value, 1);\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h\nnew file mode 100644\nindex 0000000000..798a175609\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h\n@@ -0,0 +1,93 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_KM_V7_H_\n+#define _HW_MOD_KM_V7_H_\n+\n+struct km_v7_rcp_s {\n+\tuint32_t qw0_dyn;\n+\tint32_t qw0_ofs;\n+\tuint32_t qw0_sel_a;\n+\tuint32_t qw0_sel_b;\n+\tuint32_t qw4_dyn;\n+\tint32_t qw4_ofs;\n+\tuint32_t qw4_sel_a;\n+\tuint32_t qw4_sel_b;\n+\tuint32_t dw8_dyn;\n+\tint32_t dw8_ofs;\n+\tuint32_t dw8_sel_a;\n+\tuint32_t dw8_sel_b;\n+\tuint32_t dw10_dyn;\n+\tint32_t dw10_ofs;\n+\tuint32_t dw10_sel_a;\n+\tuint32_t dw10_sel_b;\n+\tuint32_t swx_cch;\n+\tuint32_t swx_sel_a;\n+\tuint32_t swx_sel_b;\n+\tuint32_t mask_d_a[12];\n+\tuint32_t mask_b[6];\n+\tuint32_t dual;\n+\tuint32_t paired;\n+\tuint32_t el_a;\n+\tuint32_t el_b;\n+\tuint32_t info_a;\n+\tuint32_t info_b;\n+\tuint32_t ftm_a;\n+\tuint32_t ftm_b;\n+\tuint32_t bank_a;\n+\tuint32_t bank_b;\n+\tuint32_t kl_a;\n+\tuint32_t kl_b;\n+\tuint32_t keyway_a;\n+\tuint32_t keyway_b;\n+\tuint32_t synergy_mode;\n+\tuint32_t dw0_b_dyn;\n+\tint32_t dw0_b_ofs;\n+\tuint32_t dw2_b_dyn;\n+\tint32_t dw2_b_ofs;\n+\tuint32_t sw4_b_dyn;\n+\tint32_t sw4_b_ofs;\n+\tuint32_t sw5_b_dyn;\n+\tint32_t sw5_b_ofs;\n+};\n+\n+struct km_v7_cam_s {\n+\tuint32_t w0;\n+\tuint32_t w1;\n+\tuint32_t w2;\n+\tuint32_t w3;\n+\tuint32_t w4;\n+\tuint32_t w5;\n+\tuint32_t ft0;\n+\tuint32_t ft1;\n+\tuint32_t ft2;\n+\tuint32_t ft3;\n+\tuint32_t ft4;\n+\tuint32_t ft5;\n+};\n+\n+struct km_v7_tcam_s {\n+\tuint32_t t[3];\n+\tuint32_t dirty;\n+};\n+\n+struct km_v7_tci_s {\n+\tuint32_t color;\n+\tuint32_t ft;\n+};\n+\n+struct km_v7_tcq_s {\n+\tuint32_t bank_mask;\n+\tuint32_t qual;\n+};\n+\n+struct hw_mod_km_v7_s {\n+\tstruct km_v7_rcp_s *rcp;\n+\tstruct km_v7_cam_s *cam;\n+\tstruct km_v7_tcam_s *tcam;\n+\tstruct km_v7_tci_s *tci;\n+\tstruct km_v7_tcq_s *tcq;\n+};\n+\n+#endif /* _HW_MOD_KM_V7_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c\nnew file mode 100644\nindex 0000000000..8d0d70cae2\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c\n@@ -0,0 +1,219 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <string.h>\n+#include \"flow_api_backend.h\"\n+\n+#define _MOD_ \"PDB\"\n+#define _VER_ be->pdb.ver\n+\n+bool hw_mod_pdb_present(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->get_pdb_present(be->be_dev);\n+}\n+\n+int hw_mod_pdb_alloc(struct flow_api_backend_s *be)\n+{\n+\tint nb;\n+\n+\t_VER_ = be->iface->get_pdb_version(be->be_dev);\n+\tNT_LOG(DBG, FILTER, \"PDB MODULE VERSION  %i.%i\\n\", VER_MAJOR(_VER_),\n+\t       VER_MINOR(_VER_));\n+\n+\tnb = be->iface->get_nb_pdb_categories(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"pdb_categories\", _MOD_, _VER_);\n+\tbe->pdb.nb_pdb_rcp_categories = (uint32_t)nb;\n+\n+\tswitch (_VER_) {\n+\tcase 9:\n+\t\tif (!callocate_mod(CAST_COMMON(&be->pdb), 2,\n+\t\t\t&be->pdb.v9.rcp,\n+\t\t\tbe->pdb.nb_pdb_rcp_categories,\n+\t\t\tsizeof(struct pdb_v9_rcp_s),\n+\t\t\t&be->pdb.v9.config,\n+\t\t\t1,\n+\t\t\tsizeof(struct pdb_v9_config_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\t/* end case 9 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\treturn 0;\n+}\n+\n+void hw_mod_pdb_free(struct flow_api_backend_s *be)\n+{\n+\tif (be->pdb.base) {\n+\t\tfree(be->pdb.base);\n+\t\tbe->pdb.base = NULL;\n+\t}\n+}\n+\n+int hw_mod_pdb_reset(struct flow_api_backend_s *be)\n+{\n+\tint err = 0;\n+\t/* Zero entire cache area */\n+\tZERO_MOD_CACHE(&be->pdb);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT PDB RCP\\n\");\n+\terr |= hw_mod_pdb_rcp_flush(be, 0, ALL_ENTRIES);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT PDB CONFIG\\n\");\n+\terr |= hw_mod_pdb_config_flush(be);\n+\treturn err;\n+}\n+\n+int hw_mod_pdb_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->pdb.nb_pdb_rcp_categories;\n+\tif ((unsigned int)(start_idx + count) > be->pdb.nb_pdb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->pdb_rcp_flush(be->be_dev, &be->pdb, start_idx, count);\n+}\n+\n+static int hw_mod_pdb_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_pdb_e field, uint32_t index,\n+\t\t\t      uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->pdb.nb_pdb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 9:\n+\t\tswitch (field) {\n+\t\tcase HW_PDB_RCP_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->pdb.v9.rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct pdb_v9_rcp_s));\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_FIND:\n+\t\t\trv = find_equal_index(be->pdb.v9.rcp,\n+\t\t\t\tsizeof(struct pdb_v9_rcp_s), index, *value,\n+\t\t\t\tbe->pdb.nb_pdb_rcp_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_COMPARE:\n+\t\t\trv = do_compare_indexes(be->pdb.v9.rcp,\n+\t\t\t\tsizeof(struct pdb_v9_rcp_s), index, *value,\n+\t\t\t\tbe->pdb.nb_pdb_rcp_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_DESCRIPTOR:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].descriptor, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_DESC_LEN:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].desc_len, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_TX_PORT:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].tx_port, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_TX_IGNORE:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].tx_ignore, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_TX_NOW:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].tx_now, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_CRC_OVERWRITE:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].crc_overwrite, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_ALIGN:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].align, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_OFS0_DYN:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].ofs0_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_OFS0_REL:\n+\t\t\tget_set_signed(&be->pdb.v9.rcp[index].ofs0_rel, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_OFS1_DYN:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].ofs1_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_OFS1_REL:\n+\t\t\tget_set_signed(&be->pdb.v9.rcp[index].ofs1_rel, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_OFS2_DYN:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].ofs2_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_OFS2_REL:\n+\t\t\tget_set_signed(&be->pdb.v9.rcp[index].ofs2_rel, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_IP_PROT_TNL:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].ip_prot_tnl, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_PPC_HSH:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].ppc_hsh, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_DUPLICATE_EN:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].duplicate_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_DUPLICATE_BIT:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].duplicate_bit, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_PDB_RCP_PCAP_KEEP_FCS:\n+\t\t\tget_set(&be->pdb.v9.rcp[index].pcap_keep_fcs, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 9 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_pdb_rcp_set(struct flow_api_backend_s *be, enum hw_pdb_e field,\n+\t\t       uint32_t index, uint32_t value)\n+{\n+\treturn hw_mod_pdb_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_pdb_rcp_get(struct flow_api_backend_s *be, enum hw_pdb_e field,\n+\t\t       uint32_t index, uint32_t *value)\n+{\n+\treturn hw_mod_pdb_rcp_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_pdb_config_flush(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->pdb_config_flush(be->be_dev, &be->pdb);\n+}\n+\n+int hw_mod_pdb_config_set(struct flow_api_backend_s *be, enum hw_pdb_e field,\n+\t\t\t  uint32_t value)\n+{\n+\tswitch (_VER_) {\n+\tcase 9:\n+\t\tswitch (field) {\n+\t\tcase HW_PDB_CONFIG_TS_FORMAT:\n+\t\t\tbe->pdb.v9.config->ts_format = value;\n+\t\t\tbreak;\n+\t\tcase HW_PDB_CONFIG_PORT_OFS:\n+\t\t\tbe->pdb.v9.config->port_ofs = value;\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 9 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h\nnew file mode 100644\nindex 0000000000..b14c10bc53\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h\n@@ -0,0 +1,39 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_PDB_V9_H_\n+#define _HW_MOD_PDB_V9_H_\n+\n+struct pdb_v9_rcp_s {\n+\tuint32_t descriptor;\n+\tuint32_t desc_len;\n+\tuint32_t tx_port;\n+\tuint32_t tx_ignore;\n+\tuint32_t tx_now;\n+\tuint32_t crc_overwrite;\n+\tuint32_t align;\n+\tuint32_t ofs0_dyn;\n+\tint32_t ofs0_rel;\n+\tuint32_t ofs1_dyn;\n+\tint32_t ofs1_rel;\n+\tuint32_t ofs2_dyn;\n+\tint32_t ofs2_rel;\n+\tuint32_t ip_prot_tnl;\n+\tuint32_t ppc_hsh;\n+\tuint32_t duplicate_en;\n+\tuint32_t duplicate_bit;\n+\tuint32_t pcap_keep_fcs; /* only field added to v9 cmp to v7/8 */\n+};\n+\n+struct pdb_v9_config_s {\n+\tuint32_t ts_format;\n+\tuint32_t port_ofs;\n+};\n+\n+struct hw_mod_pdb_v9_s {\n+\tstruct pdb_v9_rcp_s *rcp;\n+\tstruct pdb_v9_config_s *config;\n+};\n+\n+#endif /* _HW_MOD_PDB_V9_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c\nnew file mode 100644\nindex 0000000000..86d23ea683\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c\n@@ -0,0 +1,348 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <string.h>\n+#include \"flow_api_backend.h\"\n+\n+#define _MOD_ \"QSL\"\n+#define _VER_ be->qsl.ver\n+\n+#define QSL_QEN_ENTRIES 32\n+#define QSL_QNMQ_ENTRIES 256\n+\n+bool hw_mod_qsl_present(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->get_qsl_present(be->be_dev);\n+}\n+\n+int hw_mod_qsl_alloc(struct flow_api_backend_s *be)\n+{\n+\tint nb;\n+\n+\t_VER_ = be->iface->get_qsl_version(be->be_dev);\n+\tNT_LOG(DBG, FILTER, \"QSL MODULE VERSION  %i.%i\\n\", VER_MAJOR(_VER_),\n+\t       VER_MINOR(_VER_));\n+\n+\tnb = be->iface->get_nb_qsl_categories(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"qsl_categories\", _MOD_, _VER_);\n+\tbe->qsl.nb_rcp_categories = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_qsl_qst_entries(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"qsl_qst_entries\", _MOD_, _VER_);\n+\tbe->qsl.nb_qst_entries = (uint32_t)nb;\n+\n+\tswitch (_VER_) {\n+\tcase 7:\n+\t\tif (!callocate_mod(CAST_COMMON(&be->qsl), 4,\n+\t\t\t&be->qsl.v7.rcp,\n+\t\t\tbe->qsl.nb_rcp_categories,\n+\t\t\tsizeof(struct qsl_v7_rcp_s),\n+\t\t\t&be->qsl.v7.qst,\n+\t\t\tbe->qsl.nb_qst_entries,\n+\t\t\tsizeof(struct qsl_v7_qst_s),\n+\t\t\t&be->qsl.v7.qen,\n+\t\t\tQSL_QEN_ENTRIES,\n+\t\t\tsizeof(struct qsl_v7_qen_s),\n+\t\t\t&be->qsl.v7.unmq,\n+\t\t\tQSL_QNMQ_ENTRIES,\n+\t\t\tsizeof(struct qsl_v7_unmq_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\t/* end case 7 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\treturn 0;\n+}\n+\n+void hw_mod_qsl_free(struct flow_api_backend_s *be)\n+{\n+\tif (be->qsl.base) {\n+\t\tfree(be->qsl.base);\n+\t\tbe->qsl.base = NULL;\n+\t}\n+}\n+\n+int hw_mod_qsl_reset(struct flow_api_backend_s *be)\n+{\n+\t/* Zero entire cache area */\n+\tZERO_MOD_CACHE(&be->qsl);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT QSL RCP\\n\");\n+\thw_mod_qsl_rcp_flush(be, 0, ALL_ENTRIES);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT QSL QST\\n\");\n+\thw_mod_qsl_qst_flush(be, 0, ALL_ENTRIES);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT QSL QEN\\n\");\n+\thw_mod_qsl_qen_flush(be, 0, ALL_ENTRIES);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT QSL UNMQ\\n\");\n+\tbe->iface->qsl_unmq_flush(be->be_dev, &be->qsl, 0, 256);\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_qsl_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->qsl.nb_rcp_categories;\n+\tif ((unsigned int)(start_idx + count) > be->qsl.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->qsl_rcp_flush(be->be_dev, &be->qsl, start_idx, count);\n+}\n+\n+static int hw_mod_qsl_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_qsl_e field, uint32_t index,\n+\t\t\t      uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->qsl.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 7:\n+\t\tswitch (field) {\n+\t\tcase HW_QSL_RCP_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->qsl.v7.rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct qsl_v7_rcp_s));\n+\t\t\tbreak;\n+\t\tcase HW_QSL_RCP_FIND:\n+\t\t\trv = find_equal_index(be->qsl.v7.rcp,\n+\t\t\t\tsizeof(struct qsl_v7_rcp_s), index, *value,\n+\t\t\t\tbe->qsl.nb_rcp_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_QSL_RCP_COMPARE:\n+\t\t\trv = do_compare_indexes(be->qsl.v7.rcp,\n+\t\t\t\tsizeof(struct qsl_v7_rcp_s), index, *value,\n+\t\t\t\tbe->qsl.nb_rcp_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_QSL_RCP_DISCARD:\n+\t\t\tget_set(&be->qsl.v7.rcp[index].discard, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_RCP_DROP:\n+\t\t\tget_set(&be->qsl.v7.rcp[index].drop, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_RCP_TBL_LO:\n+\t\t\tget_set(&be->qsl.v7.rcp[index].tbl_lo, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_RCP_TBL_HI:\n+\t\t\tget_set(&be->qsl.v7.rcp[index].tbl_hi, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_RCP_TBL_IDX:\n+\t\t\tget_set(&be->qsl.v7.rcp[index].tbl_idx, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_RCP_TBL_MSK:\n+\t\t\tget_set(&be->qsl.v7.rcp[index].tbl_msk, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_RCP_LR:\n+\t\t\tget_set(&be->qsl.v7.rcp[index].lr, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_RCP_TSA:\n+\t\t\tget_set(&be->qsl.v7.rcp[index].tsa, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_RCP_VLI:\n+\t\t\tget_set(&be->qsl.v7.rcp[index].vli, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 7 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_qsl_rcp_set(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t       uint32_t index, uint32_t value)\n+{\n+\treturn hw_mod_qsl_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_qsl_rcp_get(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t       uint32_t index, uint32_t *value)\n+{\n+\treturn hw_mod_qsl_rcp_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_qsl_qst_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->qsl.nb_qst_entries;\n+\tif ((unsigned int)(start_idx + count) > be->qsl.nb_qst_entries)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->qsl_qst_flush(be->be_dev, &be->qsl, start_idx, count);\n+}\n+\n+static int hw_mod_qsl_qst_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_qsl_e field, uint32_t index,\n+\t\t\t      uint32_t *value, int get)\n+{\n+\tif (index >= be->qsl.nb_qst_entries)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 7:\n+\t\tswitch (field) {\n+\t\tcase HW_QSL_QST_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->qsl.v7.qst[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct qsl_v7_qst_s));\n+\t\t\tbreak;\n+\t\tcase HW_QSL_QST_QUEUE:\n+\t\t\tget_set(&be->qsl.v7.qst[index].queue, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_QST_EN:\n+\t\t\tget_set(&be->qsl.v7.qst[index].en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_QST_TX_PORT:\n+\t\t\tget_set(&be->qsl.v7.qst[index].tx_port, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_QST_LRE:\n+\t\t\tget_set(&be->qsl.v7.qst[index].lre, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_QST_TCI:\n+\t\t\tget_set(&be->qsl.v7.qst[index].tci, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_QST_VEN:\n+\t\t\tget_set(&be->qsl.v7.qst[index].ven, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 7 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_qsl_qst_set(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t       uint32_t index, uint32_t value)\n+{\n+\treturn hw_mod_qsl_qst_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_qsl_qst_get(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t       uint32_t index, uint32_t *value)\n+{\n+\treturn hw_mod_qsl_qst_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_qsl_qen_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = QSL_QEN_ENTRIES;\n+\tif ((start_idx + count) > QSL_QEN_ENTRIES)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->qsl_qen_flush(be->be_dev, &be->qsl, start_idx, count);\n+}\n+\n+static int hw_mod_qsl_qen_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_qsl_e field, uint32_t index,\n+\t\t\t      uint32_t *value, int get)\n+{\n+\tif (index >= QSL_QEN_ENTRIES)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 7:\n+\t\tswitch (field) {\n+\t\tcase HW_QSL_QEN_EN:\n+\t\t\tget_set(&be->qsl.v7.qen[index].en, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 7 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_qsl_qen_set(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t       uint32_t index, uint32_t value)\n+{\n+\treturn hw_mod_qsl_qen_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_qsl_qen_get(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t       uint32_t index, uint32_t *value)\n+{\n+\treturn hw_mod_qsl_qen_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_qsl_unmq_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t  int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = QSL_QNMQ_ENTRIES;\n+\tif ((start_idx + count) > QSL_QNMQ_ENTRIES)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->qsl_unmq_flush(be->be_dev, &be->qsl, start_idx,\n+\t\t\t\t\t count);\n+}\n+\n+static int hw_mod_qsl_unmq_mod(struct flow_api_backend_s *be,\n+\t\t\t       enum hw_qsl_e field, uint32_t index,\n+\t\t\t       uint32_t *value, int get)\n+{\n+\tif (index >= QSL_QNMQ_ENTRIES)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 7:\n+\t\tswitch (field) {\n+\t\tcase HW_QSL_UNMQ_DEST_QUEUE:\n+\t\t\tget_set(&be->qsl.v7.unmq[index].dest_queue, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_QSL_UNMQ_EN:\n+\t\t\tget_set(&be->qsl.v7.unmq[index].en, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 7 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_qsl_unmq_set(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t\tuint32_t index, uint32_t value)\n+{\n+\treturn hw_mod_qsl_unmq_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_qsl_unmq_get(struct flow_api_backend_s *be, enum hw_qsl_e field,\n+\t\t\tuint32_t index, uint32_t *value)\n+{\n+\treturn hw_mod_qsl_unmq_mod(be, field, index, value, 1);\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h\nnew file mode 100644\nindex 0000000000..747da4bc43\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h\n@@ -0,0 +1,45 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_QSL_V7_H_\n+#define _HW_MOD_QSL_V7_H_\n+\n+struct qsl_v7_rcp_s {\n+\tuint32_t discard;\n+\tuint32_t drop;\n+\tuint32_t tbl_lo;\n+\tuint32_t tbl_hi;\n+\tuint32_t tbl_idx;\n+\tuint32_t tbl_msk;\n+\tuint32_t lr;\n+\tuint32_t tsa;\n+\tuint32_t vli;\n+};\n+\n+struct qsl_v7_qst_s {\n+\tuint32_t queue;\n+\tuint32_t en;\n+\tuint32_t tx_port;\n+\tuint32_t lre;\n+\tuint32_t tci;\n+\tuint32_t ven;\n+};\n+\n+struct qsl_v7_qen_s {\n+\tuint32_t en;\n+};\n+\n+struct qsl_v7_unmq_s {\n+\tuint32_t dest_queue;\n+\tuint32_t en;\n+};\n+\n+struct hw_mod_qsl_v7_s {\n+\tstruct qsl_v7_rcp_s *rcp;\n+\tstruct qsl_v7_qst_s *qst;\n+\tstruct qsl_v7_qen_s *qen;\n+\tstruct qsl_v7_unmq_s *unmq;\n+};\n+\n+#endif /* _HW_MOD_QSL_V7_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c\nnew file mode 100644\nindex 0000000000..7f1d695a90\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c\n@@ -0,0 +1,112 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include \"flow_api_backend.h\"\n+\n+#define _MOD_ \"RMC\"\n+#define _VER_ be->rmc.ver\n+\n+bool hw_mod_rmc_present(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->get_rmc_present(be->be_dev);\n+}\n+\n+int hw_mod_rmc_alloc(struct flow_api_backend_s *be)\n+{\n+\t_VER_ = be->iface->get_rmc_version(be->be_dev);\n+\tNT_LOG(DBG, FILTER, \"RMC MODULE VERSION  %i.%i\\n\", VER_MAJOR(_VER_),\n+\t       VER_MINOR(_VER_));\n+\n+\tswitch (_VER_) {\n+\tcase 0x10003:\n+\t\tif (!callocate_mod(CAST_COMMON(&be->rmc), 1,\n+\t\t\t&be->rmc.v1_3.ctrl, 1, sizeof(struct rmc_v1_3_ctrl_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\t/* end case 1_3 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void hw_mod_rmc_free(struct flow_api_backend_s *be)\n+{\n+\tif (be->rmc.base) {\n+\t\tfree(be->rmc.base);\n+\t\tbe->rmc.base = NULL;\n+\t}\n+}\n+\n+int hw_mod_rmc_reset(struct flow_api_backend_s *be)\n+{\n+\t/* Zero entire cache area */\n+\tZERO_MOD_CACHE(&be->rmc);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT RMC CTRL\\n\");\n+\t/* disable block stat, block keep alive */\n+\thw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_STATT, 1);\n+\thw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_KEEPA, 1);\n+\thw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_MAC_PORT,\n+\t\t\t    0xff); /* initially block all ports */\n+\thw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_STATT, 1);\n+\thw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_RPP_SLICE, 0xf);\n+\treturn hw_mod_rmc_ctrl_flush(be);\n+}\n+\n+int hw_mod_rmc_ctrl_flush(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->rmc_ctrl_flush(be->be_dev, &be->rmc);\n+}\n+\n+static int hw_mod_rmc_ctrl_mod(struct flow_api_backend_s *be,\n+\t\t\t       enum hw_rmc_e field, uint32_t *value, int get)\n+{\n+\tswitch (_VER_) {\n+\tcase 0x10003:\n+\t\tswitch (field) {\n+\t\tcase HW_RMC_BLOCK_STATT:\n+\t\t\tget_set(&be->rmc.v1_3.ctrl->block_statt, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_RMC_BLOCK_KEEPA:\n+\t\t\tget_set(&be->rmc.v1_3.ctrl->block_keepa, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_RMC_BLOCK_RPP_SLICE:\n+\t\t\tget_set(&be->rmc.v1_3.ctrl->block_rpp_slice, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_RMC_BLOCK_MAC_PORT:\n+\t\t\tget_set(&be->rmc.v1_3.ctrl->block_mac_port, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_RMC_LAG_PHY_ODD_EVEN:\n+\t\t\tget_set(&be->rmc.v1_3.ctrl->lag_phy_odd_even, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 1.3 */\n+\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_rmc_ctrl_set(struct flow_api_backend_s *be, enum hw_rmc_e field,\n+\t\t\tuint32_t value)\n+{\n+\treturn hw_mod_rmc_ctrl_mod(be, field, &value, 0);\n+}\n+\n+int hw_mod_rmc_ctrl_get(struct flow_api_backend_s *be, enum hw_rmc_e field,\n+\t\t\tuint32_t *value)\n+{\n+\treturn hw_mod_rmc_ctrl_mod(be, field, value, 1);\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h\nnew file mode 100644\nindex 0000000000..8f90695821\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h\n@@ -0,0 +1,20 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_RMC_V1_3_H_\n+#define _HW_MOD_RMC_V1_3_H_\n+\n+struct rmc_v1_3_ctrl_s {\n+\tuint32_t block_statt;\n+\tuint32_t block_keepa;\n+\tuint32_t block_rpp_slice;\n+\tuint32_t block_mac_port;\n+\tuint32_t lag_phy_odd_even;\n+};\n+\n+struct hw_mod_rmc_v1_3_s {\n+\tstruct rmc_v1_3_ctrl_s *ctrl;\n+};\n+\n+#endif /* _HW_MOD_RMC_V1_3_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c\nnew file mode 100644\nindex 0000000000..933caf9fd5\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c\n@@ -0,0 +1,358 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <string.h>\n+#include \"flow_api_backend.h\"\n+\n+#define _MOD_ \"ROA\"\n+#define _VER_ be->roa.ver\n+\n+#define ROA_LAGCFG_ENTRIES 512\n+\n+bool hw_mod_roa_present(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->get_roa_present(be->be_dev);\n+}\n+\n+int hw_mod_roa_alloc(struct flow_api_backend_s *be)\n+{\n+\tint nb;\n+\n+\t_VER_ = be->iface->get_roa_version(be->be_dev);\n+\tNT_LOG(DBG, FILTER, \"ROA MODULE VERSION  %i.%i\\n\", VER_MAJOR(_VER_),\n+\t       VER_MINOR(_VER_));\n+\n+\tnb = be->iface->get_nb_roa_categories(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"roa_categories\", _MOD_, _VER_);\n+\tbe->roa.nb_tun_categories = (uint32_t)nb;\n+\n+\tbe->roa.nb_tun_categories /= 4;\n+\n+\tswitch (_VER_) {\n+\tcase 6:\n+\t\tbe->roa.nb_lag_entries = ROA_LAGCFG_ENTRIES;\n+\t\tif (!callocate_mod(CAST_COMMON(&be->roa), 4,\n+\t\t\t&be->roa.v6.tunhdr,\n+\t\t\tbe->roa.nb_tun_categories,\n+\t\t\tsizeof(struct roa_v6_tunhdr_s),\n+\t\t\t&be->roa.v6.tuncfg,\n+\t\t\tbe->roa.nb_tun_categories,\n+\t\t\tsizeof(struct roa_v6_tuncfg_s),\n+\t\t\t&be->roa.v6.config,\n+\t\t\t1,\n+\t\t\tsizeof(struct roa_v6_config_s),\n+\t\t\t&be->roa.v6.lagcfg,\n+\t\t\tbe->roa.nb_lag_entries,\n+\t\t\tsizeof(struct roa_v6_lagcfg_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\t/* end case 6 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\treturn 0;\n+}\n+\n+void hw_mod_roa_free(struct flow_api_backend_s *be)\n+{\n+\tif (be->roa.base) {\n+\t\tfree(be->roa.base);\n+\t\tbe->roa.base = NULL;\n+\t}\n+}\n+\n+int hw_mod_roa_reset(struct flow_api_backend_s *be)\n+{\n+\tint err = 0;\n+\n+\t/* Zero entire cache area */\n+\tZERO_MOD_CACHE(&be->roa);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT ROA TUNHDR\\n\");\n+\terr = hw_mod_roa_tunhdr_flush(be, 0, ALL_ENTRIES);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT ROA TUNCFG\\n\");\n+\thw_mod_roa_tuncfg_flush(be, 0, ALL_ENTRIES);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT ROA CONFIG\\n\");\n+\thw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_RECIRCULATE, 1);\n+\thw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_NORMAL_PCKS, 1);\n+\thw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_TXPORT0, 1);\n+\thw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_TXPORT1, 1);\n+\thw_mod_roa_config_flush(be);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT ROA LAGCFG\\n\");\n+\thw_mod_roa_lagcfg_flush(be, 0, ALL_ENTRIES);\n+\n+\treturn err;\n+}\n+\n+int hw_mod_roa_tunhdr_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t    int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->roa.nb_tun_categories;\n+\tif ((unsigned int)(start_idx + count) > be->roa.nb_tun_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->roa_tunhdr_flush(be->be_dev, &be->roa, start_idx,\n+\t\t\t\t\t   count);\n+}\n+\n+static int hw_mod_roa_tunhdr_mod(struct flow_api_backend_s *be,\n+\t\t\t\t enum hw_roa_e field, uint32_t index,\n+\t\t\t\t uint32_t word_off, uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->roa.nb_tun_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 6:\n+\t\tswitch (field) {\n+\t\tcase HW_ROA_TUNHDR_COMPARE:\n+\t\t\trv = do_compare_indexes(be->roa.v6.tunhdr,\n+\t\t\t\tsizeof(struct roa_v6_tunhdr_s), index, word_off,\n+\t\t\t\tbe->roa.nb_tun_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNHDR:\n+\t\t\tget_set(&be->roa.v6.tunhdr[index].tunnel_hdr[word_off],\n+\t\t\t\tvalue, get);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 6 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_roa_tunhdr_set(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t index, uint32_t word_off, uint32_t value)\n+{\n+\treturn hw_mod_roa_tunhdr_mod(be, field, index, word_off, &value, 0);\n+}\n+\n+int hw_mod_roa_tunhdr_get(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t index, uint32_t word_off, uint32_t *value)\n+{\n+\treturn hw_mod_roa_tunhdr_mod(be, field, index, word_off, value, 1);\n+}\n+\n+int hw_mod_roa_tuncfg_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t    int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->roa.nb_tun_categories;\n+\tif ((unsigned int)(start_idx + count) > be->roa.nb_tun_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->roa_tuncfg_flush(be->be_dev, &be->roa, start_idx,\n+\t\t\t\t\t   count);\n+}\n+\n+static int hw_mod_roa_tuncfg_mod(struct flow_api_backend_s *be,\n+\t\t\t\t enum hw_roa_e field, uint32_t index,\n+\t\t\t\t uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->roa.nb_tun_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 6:\n+\t\tswitch (field) {\n+\t\tcase HW_ROA_TUNCFG_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->roa.v6.tuncfg[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct roa_v6_tuncfg_s));\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_FIND:\n+\t\t\trv = find_equal_index(be->roa.v6.tuncfg,\n+\t\t\t\tsizeof(struct roa_v6_tuncfg_s), index, *value,\n+\t\t\t\tbe->roa.nb_tun_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_COMPARE:\n+\t\t\trv = do_compare_indexes(be->roa.v6.tuncfg,\n+\t\t\t\tsizeof(struct roa_v6_tuncfg_s), index, *value,\n+\t\t\t\tbe->roa.nb_tun_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_TUN_LEN:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].tun_len, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_TUN_TYPE:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].tun_type, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_TUN_VLAN:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].tun_vlan, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_IP_TYPE:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].ip_type, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_IPCS_UPD:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].ipcs_upd, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_IPCS_PRECALC:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].ipcs_precalc, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_IPTL_UPD:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].iptl_upd, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_IPTL_PRECALC:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].iptl_precalc, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_VXLAN_UDP_LEN_UPD:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].vxlan_udp_len_upd,\n+\t\t\t\tvalue, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_TX_LAG_IX:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].tx_lag_ix, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_RECIRCULATE:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].recirculate, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_PUSH_TUNNEL:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].push_tunnel, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_RECIRC_PORT:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].recirc_port, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_TUNCFG_RECIRC_BYPASS:\n+\t\t\tget_set(&be->roa.v6.tuncfg[index].recirc_bypass, value, get);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 6 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_roa_tuncfg_set(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t index, uint32_t value)\n+{\n+\treturn hw_mod_roa_tuncfg_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_roa_tuncfg_get(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t index, uint32_t *value)\n+{\n+\treturn hw_mod_roa_tuncfg_mod(be, field, index, value, 1);\n+}\n+\n+int hw_mod_roa_config_flush(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->roa_config_flush(be->be_dev, &be->roa);\n+}\n+\n+static int hw_mod_roa_config_mod(struct flow_api_backend_s *be,\n+\t\t\t\t enum hw_roa_e field, uint32_t *value, int get)\n+{\n+\tswitch (_VER_) {\n+\tcase 6:\n+\t\tswitch (field) {\n+\t\tcase HW_ROA_CONFIG_FWD_RECIRCULATE:\n+\t\t\tget_set(&be->roa.v6.config->fwd_recirculate, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_CONFIG_FWD_NORMAL_PCKS:\n+\t\t\tget_set(&be->roa.v6.config->fwd_normal_pcks, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_CONFIG_FWD_TXPORT0:\n+\t\t\tget_set(&be->roa.v6.config->fwd_txport0, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_CONFIG_FWD_TXPORT1:\n+\t\t\tget_set(&be->roa.v6.config->fwd_txport1, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_CONFIG_FWD_CELLBUILDER_PCKS:\n+\t\t\tget_set(&be->roa.v6.config->fwd_cellbuilder_pcks, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_ROA_CONFIG_FWD_NON_NORMAL_PCKS:\n+\t\t\tget_set(&be->roa.v6.config->fwd_non_normal_pcks, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 6 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_roa_config_set(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t value)\n+{\n+\treturn hw_mod_roa_config_mod(be, field, &value, 0);\n+}\n+\n+int hw_mod_roa_config_get(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t *value)\n+{\n+\treturn hw_mod_roa_config_mod(be, field, value, 1);\n+}\n+\n+int hw_mod_roa_lagcfg_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t    int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->roa.nb_lag_entries;\n+\tif ((unsigned int)(start_idx + count) > be->roa.nb_lag_entries)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->roa_lagcfg_flush(be->be_dev, &be->roa, start_idx,\n+\t\t\t\t\t   count);\n+}\n+\n+static int hw_mod_roa_lagcfg_mod(struct flow_api_backend_s *be,\n+\t\t\t\t enum hw_roa_e field, uint32_t index,\n+\t\t\t\t uint32_t *value, int get)\n+{\n+\tif (index >= be->roa.nb_lag_entries)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 6:\n+\t\tswitch (field) {\n+\t\tcase HW_ROA_LAGCFG_TXPHY_PORT:\n+\t\t\tget_set(&be->roa.v6.lagcfg[index].txphy_port, value, get);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 6 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_roa_lagcfg_set(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t index, uint32_t value)\n+{\n+\treturn hw_mod_roa_lagcfg_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_roa_lagcfg_get(struct flow_api_backend_s *be, enum hw_roa_e field,\n+\t\t\t  uint32_t index, uint32_t *value)\n+{\n+\treturn hw_mod_roa_lagcfg_mod(be, field, index, value, 1);\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h\nnew file mode 100644\nindex 0000000000..9930c52428\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h\n@@ -0,0 +1,49 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_ROA_V6_H_\n+#define _HW_MOD_ROA_V6_H_\n+\n+struct roa_v6_tunhdr_s {\n+\tuint32_t tunnel_hdr[4 * 4];\n+};\n+\n+struct roa_v6_tuncfg_s {\n+\tuint32_t tun_len;\n+\tuint32_t tun_type;\n+\tuint32_t tun_vlan;\n+\tuint32_t ip_type;\n+\tuint32_t ipcs_upd;\n+\tuint32_t ipcs_precalc;\n+\tuint32_t iptl_upd;\n+\tuint32_t iptl_precalc;\n+\tuint32_t vxlan_udp_len_upd;\n+\tuint32_t tx_lag_ix;\n+\tuint32_t recirculate;\n+\tuint32_t push_tunnel;\n+\tuint32_t recirc_port;\n+\tuint32_t recirc_bypass;\n+};\n+\n+struct roa_v6_config_s {\n+\tuint32_t fwd_recirculate;\n+\tuint32_t fwd_normal_pcks;\n+\tuint32_t fwd_txport0;\n+\tuint32_t fwd_txport1;\n+\tuint32_t fwd_cellbuilder_pcks;\n+\tuint32_t fwd_non_normal_pcks;\n+};\n+\n+struct roa_v6_lagcfg_s {\n+\tuint32_t txphy_port;\n+};\n+\n+struct hw_mod_roa_v6_s {\n+\tstruct roa_v6_tunhdr_s *tunhdr;\n+\tstruct roa_v6_tuncfg_s *tuncfg;\n+\tstruct roa_v6_config_s *config;\n+\tstruct roa_v6_lagcfg_s *lagcfg;\n+};\n+\n+#endif /* _HW_MOD_ROA_V6_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c\nnew file mode 100644\nindex 0000000000..ca65db7232\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c\n@@ -0,0 +1,132 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include \"flow_api_backend.h\"\n+\n+#define _MOD_ \"SLC\"\n+#define _VER_ be->slc.ver\n+\n+bool hw_mod_slc_present(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->get_slc_present(be->be_dev);\n+}\n+\n+int hw_mod_slc_alloc(struct flow_api_backend_s *be)\n+{\n+\t_VER_ = be->iface->get_slc_version(be->be_dev);\n+\tNT_LOG(DBG, FILTER, \"SLC MODULE VERSION  %i.%i\\n\", VER_MAJOR(_VER_),\n+\t       VER_MINOR(_VER_));\n+\n+\tswitch (_VER_) {\n+\tcase 1:\n+\t\tif (!callocate_mod(CAST_COMMON(&be->slc), 1,\n+\t\t\t&be->slc.v1.rcp,\n+\t\t\tbe->max_categories,\n+\t\t\tsizeof(struct slc_v1_rcp_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\t/* end case 1 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void hw_mod_slc_free(struct flow_api_backend_s *be)\n+{\n+\tif (be->slc.base) {\n+\t\tfree(be->slc.base);\n+\t\tbe->slc.base = NULL;\n+\t}\n+}\n+\n+int hw_mod_slc_reset(struct flow_api_backend_s *be)\n+{\n+\t/* Zero entire cache area */\n+\tZERO_MOD_CACHE(&be->slc);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT SLC RCP\\n\");\n+\treturn hw_mod_slc_rcp_flush(be, 0, be->max_categories);\n+}\n+\n+int hw_mod_slc_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->max_categories;\n+\tif ((unsigned int)(start_idx + count) > be->max_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->slc_rcp_flush(be->be_dev, &be->slc, start_idx, count);\n+}\n+\n+static int hw_mod_slc_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t      enum hw_slc_e field, uint32_t index,\n+\t\t\t      uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->max_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 1:\n+\t\tswitch (field) {\n+\t\tcase HW_SLC_RCP_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->slc.v1.rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct hw_mod_slc_v1_s));\n+\t\t\tbreak;\n+\t\tcase HW_SLC_RCP_FIND:\n+\t\t\trv = find_equal_index(be->slc.v1.rcp,\n+\t\t\t\tsizeof(struct hw_mod_slc_v1_s), index, *value,\n+\t\t\t\tbe->max_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_SLC_RCP_COMPARE:\n+\t\t\trv = do_compare_indexes(be->slc.v1.rcp,\n+\t\t\t\tsizeof(struct hw_mod_slc_v1_s), index, *value,\n+\t\t\t\tbe->max_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_SLC_RCP_SLC_EN:\n+\t\t\tget_set(&be->slc.v1.rcp[index].tail_slc_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_SLC_RCP_DYN:\n+\t\t\tget_set(&be->slc.v1.rcp[index].tail_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_SLC_RCP_OFS:\n+\t\t\tget_set_signed(&be->slc.v1.rcp[index].tail_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_SLC_RCP_PCAP:\n+\t\t\tget_set(&be->slc.v1.rcp[index].pcap, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 1 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_slc_rcp_set(struct flow_api_backend_s *be, enum hw_slc_e field,\n+\t\t       uint32_t index, uint32_t value)\n+{\n+\treturn hw_mod_slc_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_slc_rcp_get(struct flow_api_backend_s *be, enum hw_slc_e field,\n+\t\t       uint32_t index, uint32_t *value)\n+{\n+\treturn hw_mod_slc_rcp_mod(be, field, index, value, 1);\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c\nnew file mode 100644\nindex 0000000000..9f40563e8a\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c\n@@ -0,0 +1,132 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include \"flow_api_backend.h\"\n+\n+#define _MOD_ \"SLC_LR\"\n+#define _VER_ be->slc_lr.ver\n+\n+bool hw_mod_slc_lr_present(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->get_slc_lr_present(be->be_dev);\n+}\n+\n+int hw_mod_slc_lr_alloc(struct flow_api_backend_s *be)\n+{\n+\t_VER_ = be->iface->get_slc_lr_version(be->be_dev);\n+\tNT_LOG(DBG, FILTER, \"SLC LR MODULE VERSION  %i.%i\\n\", VER_MAJOR(_VER_),\n+\t       VER_MINOR(_VER_));\n+\n+\tswitch (_VER_) {\n+\tcase 2:\n+\t\tif (!callocate_mod(CAST_COMMON(&be->slc_lr), 1,\n+\t\t\t&be->slc_lr.v2.rcp,\n+\t\t\tbe->max_categories,\n+\t\t\tsizeof(struct slc_lr_v2_rcp_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void hw_mod_slc_lr_free(struct flow_api_backend_s *be)\n+{\n+\tif (be->slc_lr.base) {\n+\t\tfree(be->slc_lr.base);\n+\t\tbe->slc_lr.base = NULL;\n+\t}\n+}\n+\n+int hw_mod_slc_lr_reset(struct flow_api_backend_s *be)\n+{\n+\t/* Zero entire cache area */\n+\tZERO_MOD_CACHE(&be->slc_lr);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT SLC LR RCP\\n\");\n+\treturn hw_mod_slc_lr_rcp_flush(be, 0, be->max_categories);\n+}\n+\n+int hw_mod_slc_lr_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t    int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->max_categories;\n+\tif ((unsigned int)(start_idx + count) > be->max_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->slc_lr_rcp_flush(be->be_dev, &be->slc_lr, start_idx,\n+\t\t\t\t\t   count);\n+}\n+\n+static int hw_mod_slc_lr_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t\t enum hw_slc_lr_e field, uint32_t index,\n+\t\t\t\t uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->max_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 2:\n+\t\tswitch (field) {\n+\t\tcase HW_SLC_LR_RCP_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->slc_lr.v2.rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct hw_mod_slc_lr_v2_s));\n+\t\t\tbreak;\n+\t\tcase HW_SLC_LR_RCP_FIND:\n+\t\t\trv = find_equal_index(be->slc_lr.v2.rcp,\n+\t\t\t\tsizeof(struct hw_mod_slc_lr_v2_s), index, *value,\n+\t\t\t\tbe->max_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_SLC_LR_RCP_COMPARE:\n+\t\t\trv = do_compare_indexes(be->slc_lr.v2.rcp,\n+\t\t\t\tsizeof(struct hw_mod_slc_lr_v2_s), index, *value,\n+\t\t\t\tbe->max_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_SLC_LR_RCP_SLC_EN:\n+\t\t\tget_set(&be->slc_lr.v2.rcp[index].tail_slc_en, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_SLC_LR_RCP_DYN:\n+\t\t\tget_set(&be->slc_lr.v2.rcp[index].tail_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_SLC_LR_RCP_OFS:\n+\t\t\tget_set_signed(&be->slc_lr.v2.rcp[index].tail_ofs,\n+\t\t\t\t       value, get);\n+\t\t\tbreak;\n+\t\tcase HW_SLC_LR_RCP_PCAP:\n+\t\t\tget_set(&be->slc_lr.v2.rcp[index].pcap, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_slc_lr_rcp_set(struct flow_api_backend_s *be, enum hw_slc_lr_e field,\n+\t\t\t  uint32_t index, uint32_t value)\n+{\n+\treturn hw_mod_slc_lr_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_slc_lr_rcp_get(struct flow_api_backend_s *be, enum hw_slc_lr_e field,\n+\t\t\t  uint32_t index, uint32_t *value)\n+{\n+\treturn hw_mod_slc_lr_rcp_mod(be, field, index, value, 1);\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h\nnew file mode 100644\nindex 0000000000..d03b206e6d\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h\n@@ -0,0 +1,19 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_SLC_LR_V2_H_\n+#define _HW_MOD_SLC_LR_V2_H_\n+\n+struct slc_lr_v2_rcp_s {\n+\tuint32_t tail_slc_en;\n+\tuint32_t tail_dyn;\n+\tint32_t tail_ofs;\n+\tuint32_t pcap;\n+};\n+\n+struct hw_mod_slc_lr_v2_s {\n+\tstruct slc_lr_v2_rcp_s *rcp;\n+};\n+\n+#endif /* _HW_MOD_SLC_V2_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h\nnew file mode 100644\nindex 0000000000..01f60bfb18\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h\n@@ -0,0 +1,19 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_SLC_V1_H_\n+#define _HW_MOD_SLC_V1_H_\n+\n+struct slc_v1_rcp_s {\n+\tuint32_t tail_slc_en;\n+\tuint32_t tail_dyn;\n+\tint32_t tail_ofs;\n+\tuint32_t pcap;\n+};\n+\n+struct hw_mod_slc_v1_s {\n+\tstruct slc_v1_rcp_s *rcp;\n+};\n+\n+#endif /* _HW_MOD_SLC_V1_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c\nnew file mode 100644\nindex 0000000000..dd6f06b2c4\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c\n@@ -0,0 +1,983 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include \"flow_api_backend.h\"\n+\n+#define _MOD_ \"TPE\"\n+#define _VER_ be->tpe.ver\n+\n+bool hw_mod_tpe_present(struct flow_api_backend_s *be)\n+{\n+\treturn be->iface->get_tpe_present(be->be_dev);\n+}\n+\n+int hw_mod_tpe_alloc(struct flow_api_backend_s *be)\n+{\n+\tint nb;\n+\n+\t_VER_ = be->iface->get_tpe_version(be->be_dev);\n+\tNT_LOG(DBG, FILTER, _MOD_ \" MODULE VERSION %i.%i\\n\", VER_MAJOR(_VER_),\n+\t       VER_MINOR(_VER_));\n+\n+\tnb = be->iface->get_nb_tpe_categories(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"tpe_categories\", _MOD_, _VER_);\n+\tbe->tpe.nb_rcp_categories = (uint32_t)nb;\n+\n+\tbe->tpe.nb_ifr_categories = 0;\n+\tif (_VER_ > 1) {\n+\t\tnb = be->iface->get_nb_tpe_ifr_categories(be->be_dev);\n+\t\tif (nb <= 0)\n+\t\t\treturn error_resource_count(__func__, \"tpe_ifr_categories\", _MOD_, _VER_);\n+\t\tbe->tpe.nb_ifr_categories = (uint32_t)nb;\n+\t}\n+\n+\tnb = be->iface->get_nb_tx_cpy_writers(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"tx_cpy_writers\", _MOD_, _VER_);\n+\tbe->tpe.nb_cpy_writers = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_tx_rpl_depth(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"tx_rpl_depth\", _MOD_, _VER_);\n+\tbe->tpe.nb_rpl_depth = (uint32_t)nb;\n+\n+\tnb = be->iface->get_nb_tx_rpl_ext_categories(be->be_dev);\n+\tif (nb <= 0)\n+\t\treturn error_resource_count(__func__, \"tx_rpl_ext_categories\", _MOD_, _VER_);\n+\tbe->tpe.nb_rpl_ext_categories = (uint32_t)nb;\n+\n+\tswitch (_VER_) {\n+\tcase 1:\n+\t\tif (!callocate_mod(CAST_COMMON(&be->tpe), 8,\n+\t\t\t&be->tpe.v1.rpp_rcp, be->tpe.nb_rcp_categories,\n+\t\t\tsizeof(struct tpe_v1_rpp_v0_rcp_s),\n+\t\t\t&be->tpe.v1.ins_rcp, be->tpe.nb_rcp_categories,\n+\t\t\tsizeof(struct tpe_v1_ins_v1_rcp_s),\n+\t\t\t&be->tpe.v1.rpl_rcp, be->tpe.nb_rcp_categories,\n+\t\t\tsizeof(struct tpe_v1_rpl_v2_rcp_s),\n+\t\t\t&be->tpe.v1.rpl_ext, be->tpe.nb_rpl_ext_categories,\n+\t\t\tsizeof(struct tpe_v1_rpl_v2_ext_s),\n+\t\t\t&be->tpe.v1.rpl_rpl, be->tpe.nb_rpl_depth,\n+\t\t\tsizeof(struct tpe_v1_rpl_v2_rpl_s),\n+\t\t\t&be->tpe.v1.cpy_rcp,\n+\t\t\tbe->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories,\n+\t\t\tsizeof(struct tpe_v1_cpy_v1_rcp_s),\n+\t\t\t&be->tpe.v1.hfu_rcp, be->tpe.nb_rcp_categories,\n+\t\t\tsizeof(struct tpe_v1_hfu_v1_rcp_s),\n+\t\t\t&be->tpe.v1.csu_rcp, be->tpe.nb_rcp_categories,\n+\t\t\tsizeof(struct tpe_v1_csu_v0_rcp_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\tcase 2:\n+\t\tif (!callocate_mod(CAST_COMMON(&be->tpe), 10,\n+\t\t\t&be->tpe.v2.rpp_rcp, be->tpe.nb_rcp_categories,\n+\t\t\tsizeof(struct tpe_v1_rpp_v0_rcp_s),\n+\t\t\t&be->tpe.v2.rpp_ifr_rcp, be->tpe.nb_ifr_categories,\n+\t\t\tsizeof(struct tpe_v2_rpp_v1_ifr_rcp_s),\n+\t\t\t&be->tpe.v2.ifr_rcp, be->tpe.nb_ifr_categories,\n+\t\t\tsizeof(struct tpe_v2_ifr_v1_rcp_s),\n+\t\t\t&be->tpe.v2.ins_rcp, be->tpe.nb_rcp_categories,\n+\t\t\tsizeof(struct tpe_v1_ins_v1_rcp_s),\n+\t\t\t&be->tpe.v2.rpl_rcp, be->tpe.nb_rcp_categories,\n+\t\t\tsizeof(struct tpe_v1_rpl_v2_rcp_s),\n+\t\t\t&be->tpe.v2.rpl_ext, be->tpe.nb_rpl_ext_categories,\n+\t\t\tsizeof(struct tpe_v1_rpl_v2_ext_s),\n+\t\t\t&be->tpe.v2.rpl_rpl, be->tpe.nb_rpl_depth,\n+\t\t\tsizeof(struct tpe_v1_rpl_v2_rpl_s),\n+\t\t\t&be->tpe.v2.cpy_rcp,\n+\t\t\tbe->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories,\n+\t\t\tsizeof(struct tpe_v1_cpy_v1_rcp_s),\n+\t\t\t&be->tpe.v2.hfu_rcp, be->tpe.nb_rcp_categories,\n+\t\t\tsizeof(struct tpe_v1_hfu_v1_rcp_s),\n+\t\t\t&be->tpe.v2.csu_rcp, be->tpe.nb_rcp_categories,\n+\t\t\tsizeof(struct tpe_v1_csu_v0_rcp_s)))\n+\t\t\treturn -1;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void hw_mod_tpe_free(struct flow_api_backend_s *be)\n+{\n+\tif (be->tpe.base) {\n+\t\tfree(be->tpe.base);\n+\t\tbe->tpe.base = NULL;\n+\t}\n+}\n+\n+int hw_mod_tpe_reset(struct flow_api_backend_s *be)\n+{\n+\tint err = 0;\n+\n+\t/* Zero entire cache area */\n+\tZERO_MOD_CACHE(&be->tpe);\n+\n+\tNT_LOG(DBG, FILTER, \"INIT TPE\\n\");\n+\terr |= hw_mod_tpe_rpp_rcp_flush(be, 0, ALL_ENTRIES);\n+\terr |= hw_mod_tpe_ins_rcp_flush(be, 0, ALL_ENTRIES);\n+\terr |= hw_mod_tpe_rpl_rcp_flush(be, 0, ALL_ENTRIES);\n+\terr |= hw_mod_tpe_rpl_ext_flush(be, 0, ALL_ENTRIES);\n+\terr |= hw_mod_tpe_rpl_rpl_flush(be, 0, ALL_ENTRIES);\n+\terr |= hw_mod_tpe_cpy_rcp_flush(be, 0, ALL_ENTRIES);\n+\terr |= hw_mod_tpe_hfu_rcp_flush(be, 0, ALL_ENTRIES);\n+\terr |= hw_mod_tpe_csu_rcp_flush(be, 0, ALL_ENTRIES);\n+\n+\tif (_VER_ == 2) {\n+\t\terr |= hw_mod_tpe_rpp_ifr_rcp_flush(be, 0, ALL_ENTRIES);\n+\t\terr |= hw_mod_tpe_ifr_rcp_flush(be, 0, ALL_ENTRIES);\n+\t}\n+\n+\treturn err;\n+}\n+\n+/*\n+ * RPP_IFR_RCP\n+ */\n+\n+int hw_mod_tpe_rpp_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t\t int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->tpe.nb_ifr_categories;\n+\tif ((unsigned int)(start_idx + count) > be->tpe.nb_ifr_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->tpe_rpp_ifr_rcp_flush(be->be_dev, &be->tpe, start_idx,\n+\t\t\t\t\t\tcount);\n+}\n+\n+static int hw_mod_tpe_rpp_ifr_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t\t      enum hw_tpe_e field, uint32_t index,\n+\t\t\t\t      uint32_t *value, int get)\n+{\n+\tif (index >= be->tpe.nb_ifr_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 2:\n+\t\tswitch (field) {\n+\t\tcase HW_TPE_IFR_RCP_EN:\n+\t\t\tget_set(&be->tpe.v2.rpp_ifr_rcp[index].en, value, get);\n+\t\t\tbreak;\n+\n+\t\tcase HW_TPE_IFR_RCP_MTU:\n+\t\t\tget_set(&be->tpe.v2.rpp_ifr_rcp[index].mtu, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_tpe_rpp_ifr_rcp_set(struct flow_api_backend_s *be,\n+\t\t\t       enum hw_tpe_e field, int index, uint32_t value)\n+{\n+\treturn hw_mod_tpe_rpp_ifr_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_tpe_rpp_ifr_rcp_get(struct flow_api_backend_s *be,\n+\t\t\t       enum hw_tpe_e field, int index, uint32_t *value)\n+{\n+\treturn hw_mod_tpe_rpp_ifr_rcp_mod(be, field, index, value, 1);\n+}\n+\n+/*\n+ * RPP_RCP\n+ */\n+\n+int hw_mod_tpe_rpp_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->tpe.nb_rcp_categories;\n+\tif ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->tpe_rpp_rcp_flush(be->be_dev, &be->tpe, start_idx,\n+\t\t\t\t\t    count);\n+}\n+\n+static int hw_mod_tpe_rpp_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_tpe_e field, uint32_t index,\n+\t\t\t\t  uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->tpe.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 1:\n+\tcase 2:\n+\t\tswitch (field) {\n+\t\tcase HW_TPE_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->tpe.v1.rpp_rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct tpe_v1_rpp_v0_rcp_s));\n+\t\t\tbreak;\n+\t\tcase HW_TPE_FIND:\n+\t\t\trv = find_equal_index(be->tpe.v1.rpp_rcp,\n+\t\t\t\tsizeof(struct tpe_v1_rpp_v0_rcp_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rcp_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_COMPARE:\n+\t\t\trv = do_compare_indexes(be->tpe.v1.rpp_rcp,\n+\t\t\t\tsizeof(struct tpe_v1_rpp_v0_rcp_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rcp_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_RPP_RCP_EXP:\n+\t\t\tget_set(&be->tpe.v1.rpp_rcp[index].exp, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_tpe_rpp_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value)\n+{\n+\treturn hw_mod_tpe_rpp_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_tpe_rpp_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value)\n+{\n+\treturn hw_mod_tpe_rpp_rcp_mod(be, field, index, value, 1);\n+}\n+\n+/*\n+ * IFR_RCP\n+ */\n+\n+int hw_mod_tpe_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->tpe.nb_ifr_categories;\n+\tif ((unsigned int)(start_idx + count) > be->tpe.nb_ifr_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->tpe_ifr_rcp_flush(be->be_dev, &be->tpe, start_idx,\n+\t\t\t\t\t    count);\n+}\n+\n+static int hw_mod_tpe_ifr_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_tpe_e field, uint32_t index,\n+\t\t\t\t  uint32_t *value, int get)\n+{\n+\tif (index >= be->tpe.nb_ifr_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 2:\n+\t\tswitch (field) {\n+\t\tcase HW_TPE_IFR_RCP_EN:\n+\t\t\tget_set(&be->tpe.v2.ifr_rcp[index].en, value, get);\n+\t\t\tbreak;\n+\n+\t\tcase HW_TPE_IFR_RCP_MTU:\n+\t\t\tget_set(&be->tpe.v2.ifr_rcp[index].mtu, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_tpe_ifr_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value)\n+{\n+\treturn hw_mod_tpe_ifr_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_tpe_ifr_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value)\n+{\n+\treturn hw_mod_tpe_ifr_rcp_mod(be, field, index, value, 1);\n+}\n+\n+/*\n+ * INS_RCP\n+ */\n+\n+int hw_mod_tpe_ins_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->tpe.nb_rcp_categories;\n+\tif ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->tpe_ins_rcp_flush(be->be_dev, &be->tpe, start_idx,\n+\t\t\t\t\t    count);\n+}\n+\n+static int hw_mod_tpe_ins_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_tpe_e field, uint32_t index,\n+\t\t\t\t  uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->tpe.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 1:\n+\tcase 2:\n+\t\tswitch (field) {\n+\t\tcase HW_TPE_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->tpe.v1.ins_rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct tpe_v1_ins_v1_rcp_s));\n+\t\t\tbreak;\n+\t\tcase HW_TPE_FIND:\n+\t\t\trv = find_equal_index(be->tpe.v1.ins_rcp,\n+\t\t\t\tsizeof(struct tpe_v1_ins_v1_rcp_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rcp_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_COMPARE:\n+\t\t\trv = do_compare_indexes(be->tpe.v1.ins_rcp,\n+\t\t\t\tsizeof(struct tpe_v1_ins_v1_rcp_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rcp_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_INS_RCP_DYN:\n+\t\t\tget_set(&be->tpe.v1.ins_rcp[index].dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_INS_RCP_OFS:\n+\t\t\tget_set(&be->tpe.v1.ins_rcp[index].ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_INS_RCP_LEN:\n+\t\t\tget_set(&be->tpe.v1.ins_rcp[index].len, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 1 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_tpe_ins_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value)\n+{\n+\treturn hw_mod_tpe_ins_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_tpe_ins_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value)\n+{\n+\treturn hw_mod_tpe_ins_rcp_mod(be, field, index, value, 1);\n+}\n+\n+/*\n+ * RPL_RCP\n+ */\n+\n+int hw_mod_tpe_rpl_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->tpe.nb_rcp_categories;\n+\tif ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->tpe_rpl_rcp_flush(be->be_dev, &be->tpe, start_idx,\n+\t\t\t\t\t    count);\n+}\n+\n+static int hw_mod_tpe_rpl_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_tpe_e field, uint32_t index,\n+\t\t\t\t  uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->tpe.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 1:\n+\tcase 2:\n+\t\tswitch (field) {\n+\t\tcase HW_TPE_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->tpe.v1.rpl_rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct tpe_v1_rpl_v2_rcp_s));\n+\t\t\tbreak;\n+\t\tcase HW_TPE_FIND:\n+\t\t\trv = find_equal_index(be->tpe.v1.rpl_rcp,\n+\t\t\t\tsizeof(struct tpe_v1_rpl_v2_rcp_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rcp_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_COMPARE:\n+\t\t\trv = do_compare_indexes(be->tpe.v1.rpl_rcp,\n+\t\t\t\tsizeof(struct tpe_v1_rpl_v2_rcp_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rcp_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_RPL_RCP_DYN:\n+\t\t\tget_set(&be->tpe.v1.rpl_rcp[index].dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_RPL_RCP_OFS:\n+\t\t\tget_set(&be->tpe.v1.rpl_rcp[index].ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_RPL_RCP_LEN:\n+\t\t\tget_set(&be->tpe.v1.rpl_rcp[index].len, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_RPL_RCP_RPL_PTR:\n+\t\t\tget_set(&be->tpe.v1.rpl_rcp[index].rpl_ptr, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_RPL_RCP_EXT_PRIO:\n+\t\t\tget_set(&be->tpe.v1.rpl_rcp[index].ext_prio, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 1 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_tpe_rpl_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value)\n+{\n+\treturn hw_mod_tpe_rpl_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_tpe_rpl_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value)\n+{\n+\treturn hw_mod_tpe_rpl_rcp_mod(be, field, index, value, 1);\n+}\n+\n+/*\n+ * RPL_EXT\n+ */\n+\n+int hw_mod_tpe_rpl_ext_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->tpe.nb_rpl_ext_categories;\n+\tif ((unsigned int)(start_idx + count) > be->tpe.nb_rpl_ext_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->tpe_rpl_ext_flush(be->be_dev, &be->tpe, start_idx,\n+\t\t\t\t\t    count);\n+}\n+\n+static int hw_mod_tpe_rpl_ext_mod(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_tpe_e field, uint32_t index,\n+\t\t\t\t  uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->tpe.nb_rpl_ext_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 1:\n+\tcase 2:\n+\t\tswitch (field) {\n+\t\tcase HW_TPE_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->tpe.v1.rpl_ext[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct tpe_v1_rpl_v2_ext_s));\n+\t\t\tbreak;\n+\t\tcase HW_TPE_FIND:\n+\t\t\trv = find_equal_index(be->tpe.v1.rpl_ext,\n+\t\t\t\tsizeof(struct tpe_v1_rpl_v2_ext_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rpl_ext_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_COMPARE:\n+\t\t\trv = do_compare_indexes(be->tpe.v1.rpl_ext,\n+\t\t\t\tsizeof(struct tpe_v1_rpl_v2_ext_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rpl_ext_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_RPL_EXT_RPL_PTR:\n+\t\t\tget_set(&be->tpe.v1.rpl_ext[index].rpl_ptr, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_RPL_EXT_META_RPL_LEN:\n+\t\t\tget_set(&be->tpe.v1.rpl_ext[index].meta_rpl_len, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 1 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_tpe_rpl_ext_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value)\n+{\n+\treturn hw_mod_tpe_rpl_ext_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_tpe_rpl_ext_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value)\n+{\n+\treturn hw_mod_tpe_rpl_ext_mod(be, field, index, value, 1);\n+}\n+\n+/*\n+ * RPL_RPL\n+ */\n+\n+int hw_mod_tpe_rpl_rpl_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->tpe.nb_rpl_depth;\n+\tif ((unsigned int)(start_idx + count) > be->tpe.nb_rpl_depth)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->tpe_rpl_rpl_flush(be->be_dev, &be->tpe, start_idx,\n+\t\t\t\t\t    count);\n+}\n+\n+static int hw_mod_tpe_rpl_rpl_mod(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_tpe_e field, uint32_t index,\n+\t\t\t\t  uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->tpe.nb_rpl_depth)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 1:\n+\tcase 2:\n+\t\tswitch (field) {\n+\t\tcase HW_TPE_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->tpe.v1.rpl_rpl[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct tpe_v1_rpl_v2_rpl_s));\n+\t\t\tbreak;\n+\t\tcase HW_TPE_FIND:\n+\t\t\trv = find_equal_index(be->tpe.v1.rpl_rpl,\n+\t\t\t\tsizeof(struct tpe_v1_rpl_v2_rpl_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rpl_depth, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_COMPARE:\n+\t\t\trv = do_compare_indexes(be->tpe.v1.rpl_rpl,\n+\t\t\t\tsizeof(struct tpe_v1_rpl_v2_rpl_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rpl_depth, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_RPL_RPL_VALUE:\n+\t\t\tif (get)\n+\t\t\t\tmemcpy(value, be->tpe.v1.rpl_rpl[index].value,\n+\t\t\t\t       sizeof(uint32_t) * 4);\n+\t\t\telse\n+\t\t\t\tmemcpy(be->tpe.v1.rpl_rpl[index].value, value,\n+\t\t\t\t       sizeof(uint32_t) * 4);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 1 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_tpe_rpl_rpl_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value)\n+{\n+\treturn hw_mod_tpe_rpl_rpl_mod(be, field, index, value, 0);\n+}\n+\n+int hw_mod_tpe_rpl_rpl_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value)\n+{\n+\treturn hw_mod_tpe_rpl_rpl_mod(be, field, index, value, 1);\n+}\n+\n+/*\n+ * CPY_RCP\n+ */\n+\n+int hw_mod_tpe_cpy_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count)\n+{\n+\tconst uint32_t cpy_size =\n+\t\tbe->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories;\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = cpy_size;\n+\tif ((unsigned int)(start_idx + count) > cpy_size)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->tpe_cpy_rcp_flush(be->be_dev, &be->tpe, start_idx,\n+\t\t\t\t\t    count);\n+}\n+\n+static int hw_mod_tpe_cpy_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_tpe_e field, uint32_t index,\n+\t\t\t\t  uint32_t *value, int get)\n+{\n+\tconst uint32_t cpy_size =\n+\t\tbe->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories;\n+\tint rv = 0;\n+\tif (index >= cpy_size)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 1:\n+\tcase 2:\n+\t\tswitch (field) {\n+\t\tcase HW_TPE_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->tpe.v1.cpy_rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct tpe_v1_cpy_v1_rcp_s));\n+\t\t\tbreak;\n+\t\tcase HW_TPE_FIND:\n+\t\t\trv = find_equal_index(be->tpe.v1.cpy_rcp,\n+\t\t\t\tsizeof(struct tpe_v1_cpy_v1_rcp_s), index, *value,\n+\t\t\t\tcpy_size, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_COMPARE:\n+\t\t\trv = do_compare_indexes(be->tpe.v1.cpy_rcp,\n+\t\t\t\tsizeof(struct tpe_v1_cpy_v1_rcp_s), index, *value,\n+\t\t\t\tcpy_size, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_CPY_RCP_READER_SELECT:\n+\t\t\tget_set(&be->tpe.v1.cpy_rcp[index].reader_select, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_CPY_RCP_DYN:\n+\t\t\tget_set(&be->tpe.v1.cpy_rcp[index].dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_CPY_RCP_OFS:\n+\t\t\tget_set(&be->tpe.v1.cpy_rcp[index].ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_CPY_RCP_LEN:\n+\t\t\tget_set(&be->tpe.v1.cpy_rcp[index].len, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 1 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_tpe_cpy_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value)\n+{\n+\treturn hw_mod_tpe_cpy_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_tpe_cpy_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value)\n+{\n+\treturn hw_mod_tpe_cpy_rcp_mod(be, field, index, value, 1);\n+}\n+\n+/*\n+ * HFU_RCP\n+ */\n+\n+int hw_mod_tpe_hfu_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->tpe.nb_rcp_categories;\n+\tif ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->tpe_hfu_rcp_flush(be->be_dev, &be->tpe, start_idx,\n+\t\t\t\t\t    count);\n+}\n+\n+static int hw_mod_tpe_hfu_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_tpe_e field, uint32_t index,\n+\t\t\t\t  uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->tpe.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 1:\n+\tcase 2:\n+\t\tswitch (field) {\n+\t\tcase HW_TPE_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->tpe.v1.hfu_rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct tpe_v1_hfu_v1_rcp_s));\n+\t\t\tbreak;\n+\t\tcase HW_TPE_FIND:\n+\t\t\trv = find_equal_index(be->tpe.v1.hfu_rcp,\n+\t\t\t\tsizeof(struct tpe_v1_hfu_v1_rcp_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rcp_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_COMPARE:\n+\t\t\trv = do_compare_indexes(be->tpe.v1.hfu_rcp,\n+\t\t\t\tsizeof(struct tpe_v1_hfu_v1_rcp_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rcp_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_A_WR:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_a_wr, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_A_OUTER_L4_LEN:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_a_outer_l4_len,\n+\t\t\t\tvalue, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_A_POS_DYN:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_a_pos_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_A_POS_OFS:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_a_pos_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_A_ADD_DYN:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_a_add_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_A_ADD_OFS:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_a_add_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_A_SUB_DYN:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_a_sub_dyn, value, get);\n+\t\t\tbreak;\n+\n+\t\tcase HW_TPE_HFU_RCP_LEN_B_WR:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_b_wr, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_B_POS_DYN:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_b_pos_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_B_POS_OFS:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_b_pos_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_B_ADD_DYN:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_b_add_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_B_ADD_OFS:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_b_add_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_B_SUB_DYN:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_b_sub_dyn, value, get);\n+\t\t\tbreak;\n+\n+\t\tcase HW_TPE_HFU_RCP_LEN_C_WR:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_c_wr, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_C_POS_DYN:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_c_pos_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_C_POS_OFS:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_c_pos_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_C_ADD_DYN:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_c_add_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_C_ADD_OFS:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_c_add_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_LEN_C_SUB_DYN:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].len_c_sub_dyn, value, get);\n+\t\t\tbreak;\n+\n+\t\tcase HW_TPE_HFU_RCP_TTL_WR:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].ttl_wr, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_TTL_POS_DYN:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].ttl_pos_dyn, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_TTL_POS_OFS:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].ttl_pos_ofs, value, get);\n+\t\t\tbreak;\n+\n+\t\tcase HW_TPE_HFU_RCP_CS_INF:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].cs_inf, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_L3_PRT:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].l3_prt, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_L3_FRAG:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].l3_frag, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_TUNNEL:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].tunnel, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_L4_PRT:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].l4_prt, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_OUTER_L3_OFS:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].outer_l3_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_OUTER_L4_OFS:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].outer_l4_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_INNER_L3_OFS:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].inner_l3_ofs, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_HFU_RCP_INNER_L4_OFS:\n+\t\t\tget_set(&be->tpe.v1.hfu_rcp[index].inner_l4_ofs, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 1 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_tpe_hfu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value)\n+{\n+\treturn hw_mod_tpe_hfu_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_tpe_hfu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value)\n+{\n+\treturn hw_mod_tpe_hfu_rcp_mod(be, field, index, value, 1);\n+}\n+\n+/*\n+ * CSU_RCP\n+ */\n+\n+int hw_mod_tpe_csu_rcp_flush(struct flow_api_backend_s *be, int start_idx,\n+\t\t\t     int count)\n+{\n+\tif (count == ALL_ENTRIES)\n+\t\tcount = be->tpe.nb_rcp_categories;\n+\tif ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\treturn be->iface->tpe_csu_rcp_flush(be->be_dev, &be->tpe, start_idx,\n+\t\t\t\t\t    count);\n+}\n+\n+static int hw_mod_tpe_csu_rcp_mod(struct flow_api_backend_s *be,\n+\t\t\t\t  enum hw_tpe_e field, uint32_t index,\n+\t\t\t\t  uint32_t *value, int get)\n+{\n+\tint rv = 0;\n+\tif (index >= be->tpe.nb_rcp_categories)\n+\t\treturn error_index_too_large(__func__);\n+\tswitch (_VER_) {\n+\tcase 1:\n+\tcase 2:\n+\t\tswitch (field) {\n+\t\tcase HW_TPE_PRESET_ALL:\n+\t\t\tif (get)\n+\t\t\t\treturn error_unsup_field(__func__);\n+\t\t\tmemset(&be->tpe.v1.csu_rcp[index], (uint8_t)*value,\n+\t\t\t       sizeof(struct tpe_v1_csu_v0_rcp_s));\n+\t\t\tbreak;\n+\t\tcase HW_TPE_FIND:\n+\t\t\trv = find_equal_index(be->tpe.v1.csu_rcp,\n+\t\t\t\tsizeof(struct tpe_v1_csu_v0_rcp_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rcp_categories, value, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_COMPARE:\n+\t\t\trv = do_compare_indexes(be->tpe.v1.csu_rcp,\n+\t\t\t\tsizeof(struct tpe_v1_csu_v0_rcp_s), index, *value,\n+\t\t\t\tbe->tpe.nb_rcp_categories, get, __func__);\n+\t\t\tif (rv != 0)\n+\t\t\t\treturn rv;\n+\t\t\tbreak;\n+\t\tcase HW_TPE_CSU_RCP_OUTER_L3_CMD:\n+\t\t\tget_set(&be->tpe.v1.csu_rcp[index].ol3_cmd, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_CSU_RCP_OUTER_L4_CMD:\n+\t\t\tget_set(&be->tpe.v1.csu_rcp[index].ol4_cmd, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_CSU_RCP_INNER_L3_CMD:\n+\t\t\tget_set(&be->tpe.v1.csu_rcp[index].il3_cmd, value, get);\n+\t\t\tbreak;\n+\t\tcase HW_TPE_CSU_RCP_INNER_L4_CMD:\n+\t\t\tget_set(&be->tpe.v1.csu_rcp[index].il4_cmd, value, get);\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\treturn error_unsup_field(__func__);\n+\t\t}\n+\t\tbreak;\n+\t/* end case 1 */\n+\tdefault:\n+\t\treturn error_unsup_ver(__func__, _MOD_, _VER_);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int hw_mod_tpe_csu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t value)\n+{\n+\treturn hw_mod_tpe_csu_rcp_mod(be, field, index, &value, 0);\n+}\n+\n+int hw_mod_tpe_csu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,\n+\t\t\t   int index, uint32_t *value)\n+{\n+\treturn hw_mod_tpe_csu_rcp_mod(be, field, index, value, 1);\n+}\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h\nnew file mode 100644\nindex 0000000000..dacd819659\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h\n@@ -0,0 +1,103 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_TPE_V1_H_\n+#define _HW_MOD_TPE_V1_H_\n+\n+struct tpe_v1_rpp_v0_rcp_s {\n+\tuint32_t exp;\n+};\n+\n+struct tpe_v1_ins_v1_rcp_s {\n+\tuint32_t dyn;\n+\tuint32_t ofs;\n+\tuint32_t len;\n+};\n+\n+struct tpe_v1_rpl_v2_rcp_s {\n+\tuint32_t dyn;\n+\tuint32_t ofs;\n+\tuint32_t len;\n+\tuint32_t rpl_ptr;\n+\tuint32_t ext_prio;\n+};\n+\n+struct tpe_v1_rpl_v2_ext_s {\n+\tuint32_t rpl_ptr;\n+\tuint32_t meta_rpl_len; /* SW only */\n+};\n+\n+struct tpe_v1_rpl_v2_rpl_s {\n+\tuint32_t value[4];\n+};\n+\n+struct tpe_v1_cpy_v1_rcp_s {\n+\tuint32_t reader_select;\n+\tuint32_t dyn;\n+\tuint32_t ofs;\n+\tuint32_t len;\n+};\n+\n+struct tpe_v1_hfu_v1_rcp_s {\n+\tuint32_t len_a_wr;\n+\tuint32_t len_a_outer_l4_len;\n+\tuint32_t len_a_pos_dyn;\n+\tuint32_t len_a_pos_ofs;\n+\tuint32_t len_a_add_dyn;\n+\tuint32_t len_a_add_ofs;\n+\tuint32_t len_a_sub_dyn;\n+\n+\tuint32_t len_b_wr;\n+\tuint32_t len_b_pos_dyn;\n+\tuint32_t len_b_pos_ofs;\n+\tuint32_t len_b_add_dyn;\n+\tuint32_t len_b_add_ofs;\n+\tuint32_t len_b_sub_dyn;\n+\n+\tuint32_t len_c_wr;\n+\tuint32_t len_c_pos_dyn;\n+\tuint32_t len_c_pos_ofs;\n+\tuint32_t len_c_add_dyn;\n+\tuint32_t len_c_add_ofs;\n+\tuint32_t len_c_sub_dyn;\n+\n+\tuint32_t ttl_wr;\n+\tuint32_t ttl_pos_dyn;\n+\tuint32_t ttl_pos_ofs;\n+\n+\tuint32_t cs_inf;\n+\tuint32_t l3_prt;\n+\tuint32_t l3_frag;\n+\tuint32_t tunnel;\n+\tuint32_t l4_prt;\n+\tuint32_t outer_l3_ofs;\n+\tuint32_t outer_l4_ofs;\n+\tuint32_t inner_l3_ofs;\n+\tuint32_t inner_l4_ofs;\n+};\n+\n+struct tpe_v1_csu_v0_rcp_s {\n+\tuint32_t ol3_cmd;\n+\tuint32_t ol4_cmd;\n+\tuint32_t il3_cmd;\n+\tuint32_t il4_cmd;\n+};\n+\n+struct hw_mod_tpe_v1_s {\n+\tstruct tpe_v1_rpp_v0_rcp_s *rpp_rcp;\n+\n+\tstruct tpe_v1_ins_v1_rcp_s *ins_rcp;\n+\n+\tstruct tpe_v1_rpl_v2_rcp_s *rpl_rcp;\n+\tstruct tpe_v1_rpl_v2_ext_s *rpl_ext;\n+\tstruct tpe_v1_rpl_v2_rpl_s *rpl_rpl;\n+\n+\tstruct tpe_v1_cpy_v1_rcp_s *cpy_rcp;\n+\n+\tstruct tpe_v1_hfu_v1_rcp_s *hfu_rcp;\n+\n+\tstruct tpe_v1_csu_v0_rcp_s *csu_rcp;\n+};\n+\n+#endif /* _HW_MOD_TPE_V1_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h\nnew file mode 100644\nindex 0000000000..c56cad8d89\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h\n@@ -0,0 +1,37 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _HW_MOD_TPE_V2_H_\n+#define _HW_MOD_TPE_V2_H_\n+\n+struct tpe_v2_rpp_v1_ifr_rcp_s {\n+\tuint32_t en;\n+\tuint32_t mtu;\n+};\n+\n+struct tpe_v2_ifr_v1_rcp_s {\n+\tuint32_t en;\n+\tuint32_t mtu;\n+};\n+\n+struct hw_mod_tpe_v2_s {\n+\tstruct tpe_v1_rpp_v0_rcp_s *rpp_rcp;\n+\n+\tstruct tpe_v1_ins_v1_rcp_s *ins_rcp;\n+\n+\tstruct tpe_v1_rpl_v2_rcp_s *rpl_rcp;\n+\tstruct tpe_v1_rpl_v2_ext_s *rpl_ext;\n+\tstruct tpe_v1_rpl_v2_rpl_s *rpl_rpl;\n+\n+\tstruct tpe_v1_cpy_v1_rcp_s *cpy_rcp;\n+\n+\tstruct tpe_v1_hfu_v1_rcp_s *hfu_rcp;\n+\n+\tstruct tpe_v1_csu_v0_rcp_s *csu_rcp;\n+\n+\tstruct tpe_v2_rpp_v1_ifr_rcp_s *rpp_ifr_rcp;\n+\tstruct tpe_v2_ifr_v1_rcp_s *ifr_rcp;\n+};\n+\n+#endif /* _HW_MOD_TPE_V2_H_ */\ndiff --git a/drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h b/drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h\nnew file mode 100644\nindex 0000000000..eae8f176a8\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h\n@@ -0,0 +1,697 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef _STREAM_BINARY_FLOW_API_H_\n+#define _STREAM_BINARY_FLOW_API_H_\n+\n+#include <stdint.h> /* uint16_t, uint32_t, uint64_t */\n+#include <stdio.h> /* snprintf */\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+typedef uint16_t be16_t; /* 16-bit big-endian */\n+typedef uint32_t be32_t; /* 32-bit big-endian */\n+typedef uint64_t be64_t; /* 64-bit big-endian */\n+\n+/*\n+ * Flow frontend for binary programming interface\n+ */\n+\n+#define FLOW_MAX_QUEUES 128\n+\n+#define RAW_ENCAP_DECAP_ELEMS_MAX 16\n+\n+/*\n+ * Partial flow mark and special flow marks\n+ */\n+#define FLOW_MARK_LACP 0x7fffffff\n+#define FLOW_MARK_MAX 0x7ffffffe\n+/*\n+ * Flow eth dev profile determines how the FPGA module resources are\n+ * managed and what features are available\n+ */\n+enum flow_eth_dev_profile {\n+\tFLOW_ETH_DEV_PROFILE_VSWITCH = 0,\n+\tFLOW_ETH_DEV_PROFILE_INLINE = 1,\n+};\n+\n+/*\n+ * Flow rule attributes\n+ */\n+struct flow_attr {\n+\tuint32_t group; /* Priority group. */\n+\tuint32_t priority; /* Rule priority level within group. */\n+\tuint16_t forced_vlan_vid; /* Forced VLAN VID that filter must match. Ignored if 0. */\n+\tuint8_t caller_id; /* Unique ID of caller application. */\n+};\n+\n+struct flow_queue_id_s {\n+\tint id;\n+\tint hw_id;\n+};\n+\n+/* NT Private rte flow items. */\n+\n+/* NT Private rte flow actions. */\n+\n+enum flow_elem_type {\n+\tFLOW_ELEM_TYPE_END,\n+\tFLOW_ELEM_TYPE_ANY,\n+\tFLOW_ELEM_TYPE_ETH,\n+\tFLOW_ELEM_TYPE_VLAN,\n+\tFLOW_ELEM_TYPE_IPV4,\n+\tFLOW_ELEM_TYPE_IPV6,\n+\tFLOW_ELEM_TYPE_SCTP,\n+\tFLOW_ELEM_TYPE_TCP,\n+\tFLOW_ELEM_TYPE_UDP,\n+\tFLOW_ELEM_TYPE_ICMP,\n+\tFLOW_ELEM_TYPE_VXLAN,\n+\tFLOW_ELEM_TYPE_GTP,\n+\tFLOW_ELEM_TYPE_PORT_ID,\n+\tFLOW_ELEM_TYPE_TAG,\n+\tFLOW_ELEM_TYPE_VOID,\n+\n+\t/*\n+\t * Not associated with a RTE_ITEM..., but rather an restoration API device specific\n+\t * extension\n+\t */\n+\tFLOW_ELEM_TYPE_TUNNEL\n+};\n+\n+enum flow_action_type { /* conf structure */\n+\tFLOW_ACTION_TYPE_END, /* -none- : End tag for action list */\n+\tFLOW_ACTION_TYPE_POP_VLAN, /* -none- : Pops outer vlan tag */\n+\tFLOW_ACTION_TYPE_PUSH_VLAN, /* struct flow_action_push_vlan : Push VLAN TAG */\n+\tFLOW_ACTION_TYPE_SET_VLAN_VID, /* struct flow_action_set_vlan_vid : Set VLAN VID */\n+\tFLOW_ACTION_TYPE_SET_VLAN_PCP, /* struct flow_action_set_vlan_pcp : Set VLAN PCP */\n+\t/* -none- : Decapsulate outer most VXLAN tunnel from matched flow */\n+\tFLOW_ACTION_TYPE_VXLAN_DECAP,\n+\tFLOW_ACTION_TYPE_VXLAN_ENCAP, /* struct flow_action_vxlan_encap */\n+\tFLOW_ACTION_TYPE_DROP, /* -none- : Drop packets of this flow */\n+\tFLOW_ACTION_TYPE_COUNT, /* struct flow_action_count : Used for \"query\" flow function */\n+\tFLOW_ACTION_TYPE_MARK, /* struct flow_action_mark : Used to tag a flow in HW with a MARK */\n+\tFLOW_ACTION_TYPE_SET_TAG, /* struct flow_action_tag : Used to tag a flow in HW with a TAG */\n+\t/* struct flow_action_port_id : Destination port ID - HW port ID */\n+\tFLOW_ACTION_TYPE_PORT_ID,\n+\tFLOW_ACTION_TYPE_RSS, /* struct flow_action_rss : */\n+\tFLOW_ACTION_TYPE_QUEUE, /* struct flow_action_queue : */\n+\tFLOW_ACTION_TYPE_JUMP, /* struct flow_action_jump : */\n+\t/* struct flow_action_meter : Used to set MBR record ids in FLM learn records */\n+\tFLOW_ACTION_TYPE_METER,\n+\tFLOW_ACTION_TYPE_RAW_ENCAP, /* struct flow_action_raw_encap : */\n+\tFLOW_ACTION_TYPE_RAW_DECAP, /* struct flow_action_raw_decap : */\n+\tFLOW_ACTION_TYPE_MODIFY_FIELD, /* struct flow_action_modify_field : */\n+\n+\t/*\n+\t * -none- : not associated with a RTE_ACTION..., but rather an restoration API device\n+\t * specific extension\n+\t */\n+\tFLOW_ACTION_TYPE_TUNNEL_SET\n+};\n+\n+#pragma pack(1)\n+struct ether_addr_s {\n+\tuint8_t addr_b[6];\n+};\n+\n+#pragma pack()\n+\n+static inline void flow_ether_format_addr(char *buf, uint16_t size,\n+\t\tconst struct ether_addr_s *eth_addr)\n+{\n+\tsnprintf(buf, size, \"%02X:%02X:%02X:%02X:%02X:%02X\",\n+\t\t eth_addr->addr_b[0], eth_addr->addr_b[1], eth_addr->addr_b[2],\n+\t\t eth_addr->addr_b[3], eth_addr->addr_b[4], eth_addr->addr_b[5]);\n+}\n+\n+/*\n+ * IPv4 Header\n+ */\n+#pragma pack(1)\n+struct ipv4_hdr_s {\n+\tuint8_t version_ihl;\n+\tuint8_t tos;\n+\tbe16_t length;\n+\tbe16_t id;\n+\tbe16_t frag_offset;\n+\tuint8_t ttl;\n+\tuint8_t next_proto_id;\n+\tbe16_t hdr_csum;\n+\tbe32_t src_ip;\n+\tbe32_t dst_ip;\n+};\n+\n+#pragma pack()\n+/*\n+ * IPv6 Header\n+ */\n+#pragma pack(1)\n+struct ipv6_hdr_s {\n+\tbe32_t vtc_flow; /* IP version, traffic class & flow label */\n+\tbe16_t payload_len; /* IP packet length - includes ip header */\n+\tuint8_t proto;\n+\tuint8_t hop_limits;\n+\tuint8_t src_addr[16];\n+\tuint8_t dst_addr[16];\n+};\n+\n+#pragma pack()\n+\n+/*\n+ * SCTP Header\n+ */\n+#pragma pack(1)\n+struct sctp_hdr_s {\n+\tbe16_t src_port;\n+\tbe16_t dst_port;\n+\tbe32_t tag; /* Validation tag */\n+\tbe32_t cksum;\n+};\n+\n+#pragma pack()\n+\n+/*\n+ * TCP Header\n+ */\n+#pragma pack(1)\n+struct tcp_hdr_s {\n+\tbe16_t src_port;\n+\tbe16_t dst_port;\n+\tbe32_t sent_seq;\n+\tbe32_t recv_ack;\n+\tuint8_t data_off;\n+\tuint8_t tcp_flags;\n+\tbe16_t rx_win;\n+\tbe16_t cksum;\n+\tbe16_t tcp_urp;\n+};\n+\n+#pragma pack()\n+\n+/*\n+ * UDP Header\n+ */\n+#pragma pack(1)\n+struct udp_hdr_s {\n+\tbe16_t src_port;\n+\tbe16_t dst_port;\n+\tbe16_t len;\n+\tbe16_t cksum;\n+};\n+\n+#pragma pack()\n+\n+/*\n+ * ICMP Header\n+ */\n+#pragma pack(1)\n+struct icmp_hdr_s {\n+\tuint8_t type;\n+\tuint8_t code;\n+\tbe16_t cksum;\n+\tbe16_t ident;\n+\tbe16_t seq_nb;\n+};\n+\n+#pragma pack()\n+/*\n+ * FLOW_ELEM_TYPE_ETH specification\n+ */\n+#pragma pack(1)\n+struct flow_elem_eth {\n+\tstruct ether_addr_s d_addr; /* DMAC */\n+\tstruct ether_addr_s s_addr; /* SMAC */\n+\tbe16_t ether_type; /* Frame type */\n+};\n+\n+#pragma pack()\n+\n+/*\n+ * FLOW_ELEM_TYPE_VLAN specification\n+ */\n+#pragma pack(1)\n+struct flow_elem_vlan {\n+\tbe16_t tci; /* Tag control information */\n+\tbe16_t inner_type; /* Inner EtherType or TPID */\n+};\n+\n+#pragma pack()\n+\n+/*\n+ * FLOW_ELEM_TYPE_IPV4 specification\n+ */\n+struct flow_elem_ipv4 {\n+\tstruct ipv4_hdr_s hdr;\n+};\n+\n+/*\n+ * FLOW_ELEM_TYPE_IPV6 specification\n+ */\n+struct flow_elem_ipv6 {\n+\tstruct ipv6_hdr_s hdr;\n+};\n+\n+/*\n+ * FLOW_ELEM_TYPE_SCTP specification\n+ */\n+struct flow_elem_sctp {\n+\tstruct sctp_hdr_s hdr;\n+};\n+\n+/*\n+ * FLOW_ELEM_TYPE_TCP specification\n+ */\n+struct flow_elem_tcp {\n+\tstruct tcp_hdr_s hdr;\n+};\n+\n+/*\n+ * FLOW_ELEM_TYPE_UDP specification\n+ */\n+struct flow_elem_udp {\n+\tstruct udp_hdr_s hdr;\n+};\n+\n+/*\n+ * FLOW_ELEM_TYPE_ICMP specification\n+ */\n+struct flow_elem_icmp {\n+\tstruct icmp_hdr_s hdr;\n+};\n+\n+/*\n+ * FLOW_ELEM_TYPE_GTP specification\n+ */\n+#pragma pack(1)\n+struct flow_elem_gtp {\n+\tuint8_t v_pt_rsv_flags;\n+\tuint8_t msg_type;\n+\tbe16_t msg_len;\n+\tbe32_t teid;\n+};\n+\n+#pragma pack()\n+\n+/*\n+ * FLOW_ELEM_TYPE_VXLAN specification (RFC 7348)\n+ */\n+#pragma pack(1)\n+struct flow_elem_vxlan {\n+\tuint8_t flags; /* Normally 0x08 (I flag) */\n+\tuint8_t rsvd0[3];\n+\tuint8_t vni[3];\n+\tuint8_t rsvd1;\n+};\n+\n+#pragma pack()\n+/*\n+ * FLOW_ELEM_TYPE_PORT_ID specification\n+ */\n+struct flow_elem_port_id {\n+\tuint32_t id; /* HW port no */\n+};\n+\n+/*\n+ * FLOW_ELEM_TYPE_TAG specification\n+ */\n+struct flow_elem_tag {\n+\tuint32_t data;\n+\tuint8_t index;\n+};\n+\n+/*\n+ * FLOW_ELEM_TYPE_ANY specification\n+ */\n+struct flow_elem_any {\n+\tuint32_t num; /**< Number of layers covered. */\n+};\n+\n+struct flow_elem {\n+\tenum flow_elem_type type; /* element type */\n+\tconst void *spec; /* Pointer to element specification structure */\n+\tconst void *mask; /* Bitmask applied to spec - same type */\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_RSS\n+ */\n+enum flow_hash_function {\n+\tFLOW_HASH_FUNCTION_DEFAULT = 0,\n+\tFLOW_HASH_FUNCTION_TOEPLITZ, /* Unsupported in current supported FPGA */\n+\tFLOW_HASH_FUNCTION_SIMPLE_XOR /* Simple XOR - not supported */\n+};\n+\n+struct flow_action_rss {\n+\tenum flow_hash_function func;\n+\tuint32_t level; /* only level 0 supported */\n+\t/* Specific RSS hash types (see like DPDK ETH_RSS_*) */\n+\tuint64_t types;\n+\tuint32_t key_len; /* Not supported yet - Hash key length in bytes */\n+\tuint32_t queue_num; /* Number of entries in queue */\n+\tconst uint8_t *key; /* Not supported yet - Hash key */\n+\tconst uint16_t *queue; /* Queue indices to use */\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_PUSH_VLAN\n+ * Push a new vlan TAG\n+ */\n+struct flow_action_push_vlan {\n+\tbe16_t ethertype;\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_SET_VLAN_VID\n+ */\n+struct flow_action_set_vlan_vid {\n+\tbe16_t vlan_vid;\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_SET_VLAN_PCP\n+ */\n+struct flow_action_set_vlan_pcp {\n+\tuint8_t vlan_pcp; /* < VLAN priority. */\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_VXLAN_ENCAP specification\n+ * Valid flow definition:\n+ *\n+ * - ETH / IPV4 / UDP / VXLAN / END\n+ * - ETH / IPV6 / UDP / VXLAN / END\n+ * - ETH / VLAN / IPV4 / UDP / VXLAN / END\n+ *\n+ */\n+struct flow_action_vxlan_encap {\n+\t/* Encapsulating vxlan tunnel definition */\n+\tstruct flow_elem *vxlan_tunnel;\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_COUNT specification\n+ */\n+struct flow_action_count {\n+\tuint32_t id; /* HW port no */\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_COUNT specification (query)\n+ */\n+struct flow_query_count {\n+\tuint32_t reset : 1;\n+\tuint32_t hits_set : 1;\n+\tuint32_t bytes_set : 1;\n+\n+\tuint32_t tcp_flags : 9;\n+\n+\tuint32_t reserved : 20;\n+\tuint64_t hits;\n+\tuint64_t bytes;\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_MARK specification\n+ */\n+struct flow_action_mark {\n+\tuint32_t id; /* mark flow with this ID */\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_TAG specification\n+ */\n+struct flow_action_tag {\n+\tuint32_t data; /* tag flow with this value */\n+\tuint32_t mask; /* bit-mask applied to \"data\" */\n+\tuint8_t index; /* index of tag to set */\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_PORT_ID specification\n+ */\n+struct flow_action_port_id {\n+\tuint32_t rte_flags; /* not used but to be binary compatible with rte flow */\n+\tuint32_t id;\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_QUEUE\n+ */\n+struct flow_action_queue {\n+\tuint16_t index;\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_JUMP\n+ */\n+struct flow_action_jump {\n+\tuint32_t group;\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_METER\n+ */\n+struct flow_action_meter {\n+\tuint32_t mtr_id;\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_RAW_ENCAP\n+ */\n+struct flow_action_raw_encap {\n+\tuint8_t *data;\n+\tuint8_t *preserve;\n+\tsize_t size;\n+\tstruct flow_elem items[RAW_ENCAP_DECAP_ELEMS_MAX];\n+\tint item_count;\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_RAW_DECAP\n+ */\n+struct flow_action_raw_decap {\n+\tuint8_t *data;\n+\tsize_t size;\n+\tstruct flow_elem items[RAW_ENCAP_DECAP_ELEMS_MAX];\n+\tint item_count;\n+};\n+\n+/*\n+ * Field IDs for MODIFY_FIELD action.\n+ */\n+enum flow_field_id {\n+\tFLOW_FIELD_START = 0, /* Start of a packet. */\n+\tFLOW_FIELD_MAC_DST, /* Destination MAC Address. */\n+\tFLOW_FIELD_MAC_SRC, /* Source MAC Address. */\n+\tFLOW_FIELD_VLAN_TYPE, /* 802.1Q Tag Identifier. */\n+\tFLOW_FIELD_VLAN_ID, /* 802.1Q VLAN Identifier. */\n+\tFLOW_FIELD_MAC_TYPE, /* EtherType. */\n+\tFLOW_FIELD_IPV4_DSCP, /* IPv4 DSCP. */\n+\tFLOW_FIELD_IPV4_TTL, /* IPv4 Time To Live. */\n+\tFLOW_FIELD_IPV4_SRC, /* IPv4 Source Address. */\n+\tFLOW_FIELD_IPV4_DST, /* IPv4 Destination Address. */\n+\tFLOW_FIELD_IPV6_DSCP, /* IPv6 DSCP. */\n+\tFLOW_FIELD_IPV6_HOPLIMIT, /* IPv6 Hop Limit. */\n+\tFLOW_FIELD_IPV6_SRC, /* IPv6 Source Address. */\n+\tFLOW_FIELD_IPV6_DST, /* IPv6 Destination Address. */\n+\tFLOW_FIELD_TCP_PORT_SRC, /* TCP Source Port Number. */\n+\tFLOW_FIELD_TCP_PORT_DST, /* TCP Destination Port Number. */\n+\tFLOW_FIELD_TCP_SEQ_NUM, /* TCP Sequence Number. */\n+\tFLOW_FIELD_TCP_ACK_NUM, /* TCP Acknowledgment Number. */\n+\tFLOW_FIELD_TCP_FLAGS, /* TCP Flags. */\n+\tFLOW_FIELD_UDP_PORT_SRC, /* UDP Source Port Number. */\n+\tFLOW_FIELD_UDP_PORT_DST, /* UDP Destination Port Number. */\n+\tFLOW_FIELD_VXLAN_VNI, /* VXLAN Network Identifier. */\n+\tFLOW_FIELD_GENEVE_VNI, /* GENEVE Network Identifier. */\n+\tFLOW_FIELD_GTP_TEID, /* GTP Tunnel Endpoint Identifier. */\n+\tFLOW_FIELD_TAG, /* Tag value. */\n+\tFLOW_FIELD_MARK, /* Mark value. */\n+\tFLOW_FIELD_META, /* Metadata value. */\n+\tFLOW_FIELD_POINTER, /* Memory pointer. */\n+\tFLOW_FIELD_VALUE, /* Immediate value. */\n+\tFLOW_FIELD_IPV4_ECN, /* IPv4 ECN. */\n+\tFLOW_FIELD_IPV6_ECN, /* IPv6 ECN. */\n+\tFLOW_FIELD_GTP_PSC_QFI, /* GTP QFI. */\n+\tFLOW_FIELD_METER_COLOR, /* Meter color marker. */\n+};\n+\n+/*\n+ * Field description for MODIFY_FIELD action.\n+ */\n+struct flow_action_modify_data {\n+\tenum flow_field_id field; /* Field or memory type ID. */\n+\tunion {\n+\t\tstruct {\n+\t\t\t/* Encapsulation level or tag index. */\n+\t\t\tuint32_t level;\n+\t\t\t/* Number of bits to skip from a field. */\n+\t\t\tuint32_t offset;\n+\t\t};\n+\t\t/*\n+\t\t * Immediate value for FLOW_FIELD_VALUE, presented in the\n+\t\t * same byte order and length as in relevant rte_flow_item_xxx.\n+\t\t */\n+\t\tuint8_t value[16];\n+\t\t/*\n+\t\t * Memory address for FLOW_FIELD_POINTER, memory layout\n+\t\t * should be the same as for relevant field in the\n+\t\t * rte_flow_item_xxx structure.\n+\t\t */\n+\t\tvoid *pvalue;\n+\t};\n+};\n+\n+/*\n+ * Operation types for MODIFY_FIELD action.\n+ */\n+enum flow_modify_op {\n+\tFLOW_MODIFY_SET = 0,\n+\tFLOW_MODIFY_ADD,\n+\tFLOW_MODIFY_SUB,\n+};\n+\n+/*\n+ * FLOW_ACTION_TYPE_MODIFY_FIELD\n+ */\n+struct flow_action_modify_field {\n+\tenum flow_modify_op operation;\n+\tstruct flow_action_modify_data dst;\n+\tstruct flow_action_modify_data src;\n+\tuint32_t width;\n+};\n+\n+struct flow_action {\n+\tenum flow_action_type type;\n+\tconst void *conf;\n+};\n+\n+enum flow_error_e { FLOW_ERROR_NONE, FLOW_ERROR_SUCCESS, FLOW_ERROR_GENERAL };\n+\n+struct flow_error {\n+\tenum flow_error_e type;\n+\tconst char *message;\n+};\n+\n+enum flow_lag_cmd {\n+\tFLOW_LAG_SET_ENTRY,\n+\tFLOW_LAG_SET_ALL,\n+\tFLOW_LAG_SET_BALANCE,\n+};\n+\n+/*\n+ * Tunnel definition for DPDK RTE tunnel helper function support\n+ */\n+struct tunnel_cfg_s {\n+\tunion {\n+\t\tstruct {\n+\t\t\tuint32_t src_ip; /* BE */\n+\t\t\tuint32_t dst_ip; /* BE */\n+\t\t} v4;\n+\t\tstruct {\n+\t\t\tuint8_t src_ip[16];\n+\t\t\tuint8_t dst_ip[16];\n+\t\t} v6;\n+\t\tstruct {\n+\t\t\tuint64_t src_ip[2];\n+\t\t\tuint64_t dst_ip[2];\n+\t\t} v6_long;\n+\t};\n+\tint ipversion;\n+\tuint16_t s_port; /* BE */\n+\tuint16_t d_port; /* BE */\n+\tint tun_type;\n+};\n+\n+struct flow_eth_dev; /* port device */\n+struct flow_handle;\n+\n+/*\n+ * Device Management API\n+ */\n+int flow_reset_nic_dev(uint8_t adapter_no);\n+\n+struct flow_eth_dev *flow_get_eth_dev(uint8_t adapter_no, uint8_t hw_port_no,\n+\t\t\t\t      uint32_t port_id, int alloc_queues,\n+\t\t\t\t      struct flow_queue_id_s queue_ids[],\n+\t\t\t\t      int *rss_target_id,\n+\t\t\t\t      enum flow_eth_dev_profile flow_profile,\n+\t\t\t\t      uint32_t exception_path);\n+\n+int flow_eth_dev_add_queue(struct flow_eth_dev *eth_dev,\n+\t\t\t   struct flow_queue_id_s *queue_id);\n+\n+int flow_delete_eth_dev(struct flow_eth_dev *eth_dev);\n+\n+int flow_get_tunnel_definition(struct tunnel_cfg_s *tun, uint32_t flow_stat_id,\n+\t\t\t       uint8_t vport);\n+\n+/*\n+ * NT Flow API\n+ */\n+int flow_validate(struct flow_eth_dev *dev, const struct flow_elem item[],\n+\t\t  const struct flow_action action[], struct flow_error *error);\n+\n+struct flow_handle *flow_create(struct flow_eth_dev *dev,\n+\t\t\t\tconst struct flow_attr *attr,\n+\t\t\t\tconst struct flow_elem item[],\n+\t\t\t\tconst struct flow_action action[],\n+\t\t\t\tstruct flow_error *error);\n+\n+int flow_destroy(struct flow_eth_dev *dev, struct flow_handle *flow,\n+\t\t struct flow_error *error);\n+\n+int flow_flush(struct flow_eth_dev *dev, struct flow_error *error);\n+\n+int flow_query(struct flow_eth_dev *dev, struct flow_handle *flow,\n+\t       const struct flow_action *action, void **data, uint32_t *length,\n+\t       struct flow_error *error);\n+\n+/*\n+ * NT Flow FLM Meter API\n+ */\n+int flow_mtr_supported(struct flow_eth_dev *dev);\n+\n+uint64_t flow_mtr_meter_policy_n_max(void);\n+\n+int flow_mtr_set_profile(struct flow_eth_dev *dev, uint32_t profile_id,\n+\t\t\t uint64_t bucket_rate_a, uint64_t bucket_size_a,\n+\t\t\t uint64_t bucket_rate_b, uint64_t bucket_size_b);\n+\n+int flow_mtr_set_policy(struct flow_eth_dev *dev, uint32_t policy_id, int drop);\n+\n+int flow_mtr_create_meter(struct flow_eth_dev *dev, uint32_t mtr_id,\n+\t\t\t  uint32_t profile_id, uint32_t policy_id,\n+\t\t\t  uint64_t stats_mask);\n+\n+int flow_mtr_destroy_meter(struct flow_eth_dev *dev, uint32_t mtr_id);\n+\n+int flm_mtr_adjust_stats(struct flow_eth_dev *dev, uint32_t mtr_id,\n+\t\t\t uint32_t adjust_value);\n+\n+uint32_t flow_mtr_meters_supported(void);\n+\n+uint32_t flm_mtr_update_stats(struct flow_eth_dev *dev);\n+void flm_mtr_read_stats(struct flow_eth_dev *dev, uint32_t id,\n+\t\t\tuint64_t *stats_mask, uint64_t *green_pkt,\n+\t\t\tuint64_t *green_bytes, int clear);\n+\n+/*\n+ * Config API\n+ */\n+int lag_set_port_group(uint8_t adapter_no, uint32_t port_mask);\n+\n+int lag_set_port_block(uint8_t adapter_no, uint32_t port_mask);\n+\n+int lag_set_config(uint8_t adapter_no, enum flow_lag_cmd cmd, uint32_t index,\n+\t\t   uint32_t value);\n+\n+int flow_set_mtu_inline(struct flow_eth_dev *dev, uint32_t port, uint16_t mtu);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* _STREAM_BINARY_FLOW_API_H_ */\n",
    "prefixes": [
        "v13",
        "5/8"
    ]
}