get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 117218,
    "url": "http://patches.dpdk.org/api/patches/117218/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20220930125315.5079-10-suanmingm@nvidia.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20220930125315.5079-10-suanmingm@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220930125315.5079-10-suanmingm@nvidia.com",
    "date": "2022-09-30T12:53:07",
    "name": "[v3,09/17] net/mlx5: support DR action template API",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "5f593b11c8b9db85b8b46584aca4b41eb86f36bd",
    "submitter": {
        "id": 1887,
        "url": "http://patches.dpdk.org/api/people/1887/?format=api",
        "name": "Suanming Mou",
        "email": "suanmingm@nvidia.com"
    },
    "delegate": {
        "id": 3268,
        "url": "http://patches.dpdk.org/api/users/3268/?format=api",
        "username": "rasland",
        "first_name": "Raslan",
        "last_name": "Darawsheh",
        "email": "rasland@nvidia.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20220930125315.5079-10-suanmingm@nvidia.com/mbox/",
    "series": [
        {
            "id": 24935,
            "url": "http://patches.dpdk.org/api/series/24935/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=24935",
            "date": "2022-09-30T12:52:58",
            "name": "net/mlx5: HW steering PMD update",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/24935/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/117218/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/117218/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 404F7A00C4;\n\tFri, 30 Sep 2022 14:54:43 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 7AF0B42B85;\n\tFri, 30 Sep 2022 14:54:03 +0200 (CEST)",
            "from NAM04-DM6-obe.outbound.protection.outlook.com\n (mail-dm6nam04on2063.outbound.protection.outlook.com [40.107.102.63])\n by mails.dpdk.org (Postfix) with ESMTP id 2A8C842B85\n for <dev@dpdk.org>; Fri, 30 Sep 2022 14:54:01 +0200 (CEST)",
            "from DS7PR03CA0149.namprd03.prod.outlook.com (2603:10b6:5:3b4::34)\n by DM4PR12MB5818.namprd12.prod.outlook.com (2603:10b6:8:62::15) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5676.20; Fri, 30 Sep\n 2022 12:53:59 +0000",
            "from DM6NAM11FT102.eop-nam11.prod.protection.outlook.com\n (2603:10b6:5:3b4:cafe::a6) by DS7PR03CA0149.outlook.office365.com\n (2603:10b6:5:3b4::34) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5676.20 via Frontend\n Transport; Fri, 30 Sep 2022 12:53:59 +0000",
            "from mail.nvidia.com (216.228.117.161) by\n DM6NAM11FT102.mail.protection.outlook.com (10.13.173.172) with Microsoft SMTP\n Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.20.5676.17 via Frontend Transport; Fri, 30 Sep 2022 12:53:58 +0000",
            "from rnnvmail201.nvidia.com (10.129.68.8) by mail.nvidia.com\n (10.129.200.67) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.26; Fri, 30 Sep\n 2022 05:53:54 -0700",
            "from nvidia.com (10.126.230.35) by rnnvmail201.nvidia.com\n (10.129.68.8) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.29; Fri, 30 Sep\n 2022 05:53:51 -0700"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=Vk4WFTtyu0WvFFQ8Fsmt0YrAjiy4IJH+3cbKX76blezg3OmfMfOVCTuLW4VA2cUoDUN9asjLXfKe/pw0ivtczlV+GQSvrKhNVDGaxYsl7h0cJIWCqdCWJKi2q91Z3tY8HTwXwyGiOxZC6nv2F8Zr5HnNsO9rFNqusRlsAccrPrlK607qcAxpmvGIS+cwpXixlyyiuJvL/HEm2buwvl/34YepLLXpVneJET8zxHyHs3COrY4NHBOoyWrdIO7f+2G0nLHTi0AX445AfPu+9ZcDuzhl5iJToB529sWFN4j+yIOH2GXrmOEHgWnqttbKJaWYankwz1W8XqOPFdmeomVgTg==",
        "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=vqdYZdY7NtaPTC3NXzJ+K4s3k0EinjlgB0rxc9pSKNk=;\n b=QuRTnj7C30+j+33prds1pZkaKPdTRH3sPOI65UEdRShCrQ6axPhpHDXwvyQtJUo4qznuJNeHa2WRDzeQWesEMCDuXXgSfr29YtGARFm0yJyED0/w5MfmUkY/+LNNLh5kLm/DZ8R5gvXiukX9j09WokR9In80dIFQLMBIYzNXV8T9EgtNKR8FNZF7M5x2aVWUl9q659hH7zqMuv3OZkVjICCZmuJEy5P+TTyv2zcOokKNdWJNJcKEBbhhDKAIwcGNrCdLTu0j/DXRyRRkmv6IJX1RSm7IcpobkKyGYjh+07TD4zDoWknjqx65Lk05h/y9oA2ICbmpYoUIoa+w6j0Qlw==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass (sender ip is\n 216.228.117.161) smtp.rcpttodomain=dpdk.org smtp.mailfrom=nvidia.com;\n dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com;\n dkim=none (message not signed); arc=none",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com;\n s=selector2;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=vqdYZdY7NtaPTC3NXzJ+K4s3k0EinjlgB0rxc9pSKNk=;\n b=DLjyjKIKZosTBz09hHvh/EO1DOyzMJ7xlwE/BHJPg/xd6qidSx+Us8Z39965GCqX+Me1FsQzrJMlBqrGJ1i81KQFaVQuBm8KTyk6lg0CPgtmuu6Cu3VW+lOSujHZYpQmchgxm6pbgs8Z+9r/JeoJjUMfoSzUzpUaM65p2t01TjPQdbPzQlzK14FAZco9k3tE6TCCHnasBcUveaMMEXSRdHhSoqCOrIrmKcAeE8OvIxIfW4XauB0bT5n0gWL4zoF5Fgbso+IFIBt2b8p9sXoJILpzWxvl+P+e+gkwweDdoSQbqLTNlU+1Ut/clHkBPrU0L91s4dPdz/eh+UnhY+3Ing==",
        "X-MS-Exchange-Authentication-Results": "spf=pass (sender IP is 216.228.117.161)\n smtp.mailfrom=nvidia.com;\n dkim=none (message not signed)\n header.d=none;dmarc=pass action=none header.from=nvidia.com;",
        "Received-SPF": "Pass (protection.outlook.com: domain of nvidia.com designates\n 216.228.117.161 as permitted sender) receiver=protection.outlook.com;\n client-ip=216.228.117.161; helo=mail.nvidia.com; pr=C",
        "From": "Suanming Mou <suanmingm@nvidia.com>",
        "To": "Matan Azrad <matan@nvidia.com>, Viacheslav Ovsiienko\n <viacheslavo@nvidia.com>",
        "CC": "<dev@dpdk.org>, <rasland@nvidia.com>, <orika@nvidia.com>, \"Dariusz\n Sosnowski\" <dsosnowski@nvidia.com>",
        "Subject": "[PATCH v3 09/17] net/mlx5: support DR action template API",
        "Date": "Fri, 30 Sep 2022 15:53:07 +0300",
        "Message-ID": "<20220930125315.5079-10-suanmingm@nvidia.com>",
        "X-Mailer": "git-send-email 2.18.1",
        "In-Reply-To": "<20220930125315.5079-1-suanmingm@nvidia.com>",
        "References": "<20220923144334.27736-1-suanmingm@nvidia.com>\n <20220930125315.5079-1-suanmingm@nvidia.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[10.126.230.35]",
        "X-ClientProxiedBy": "rnnvmail201.nvidia.com (10.129.68.8) To\n rnnvmail201.nvidia.com (10.129.68.8)",
        "X-EOPAttributedMessage": "0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "DM6NAM11FT102:EE_|DM4PR12MB5818:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "49c437d0-d2cf-4fc7-ae99-08daa2e2d7ac",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n zh59wCTgwk+tS0rAceG1xFLv+o7/zRB81KGezFL0JKt0PZJIrAKAjy4YN0RU421/0f/grNSJgyhn7/IQV3KsoSCnkcNe7IQzGW7odjFg8T0hsLz5BuggpijmNXlqKmVvga08NBVrfSgPp6T3sf+vMWwwNvPqJBdeg5eYjvB/grCC/Wq1Z2f4+mEemCyfGD/44l1DsuwtyDuL/5EU0njkwTILvxwei5ytHFn2xzyaJ+pPCoJcY/6H0NvxLAvI3cW8qkhzQHs+LNSlXqZ5rIL0777AtFYYOF4WBMiEJrZkEY44VkzqcE3ZIotBvJOnWS6gfgQryj7qlFJ6mKGUDsrQHfwdneu/6n7n2MIX73ltQ3LYx/IiEUdVOd4tRi3qpmyzfsmIvxmHNUe0nlBy4xcVipKvXy4WWyj+C7uU0im7Ci1darNbgP9adMKTPGfM1D11141RlJRfNNfKzek7aO3rGfWrDe1kP+BP2fBb+AQL4NxHl9hi4bfrc2DT6d3Hx3acM71x2Nv+R28Nij2tiQeokSD94CNoGzvNgMQs9Gt1Bpuk7pUdHVxaAPNptfp+ityHXb30kdQVxrKWV99Ly8tHc+bv5Q70RP9f0domT+RvaX77kLpE2McC2bs5yTisiuO/RT2U00ri8b6yCUNzGzCyITzxHzkYHlsm5ohuSBuExBOku+2N/yHrMbzF4DNIaY0Fysq8h9G5vHyHgOScnhca5zpUhyNRvjHaU7zDumTYJbl2GVTgAAPfXWfM2QAF9cvNwyA1CqD6y+xiVctr6aELPBM/IlibmVOcnBn5KhIbBdcKIfs2lV30+eFmb7eAiKCt",
        "X-Forefront-Antispam-Report": "CIP:216.228.117.161; CTRY:US; LANG:en; SCL:1;\n SRV:;\n IPV:NLI; SFV:NSPM; H:mail.nvidia.com; PTR:dc6edge2.nvidia.com; CAT:NONE;\n SFS:(13230022)(4636009)(39860400002)(346002)(376002)(396003)(136003)(451199015)(46966006)(36840700001)(40470700004)(2616005)(30864003)(26005)(6286002)(40460700003)(82740400003)(4326008)(356005)(8676002)(110136005)(316002)(36756003)(7636003)(55016003)(36860700001)(54906003)(86362001)(40480700001)(47076005)(1076003)(186003)(336012)(82310400005)(8936002)(83380400001)(478600001)(6666004)(107886003)(426003)(16526019)(7696005)(6636002)(5660300002)(70586007)(2906002)(41300700001)(70206006)(21314003)(579004)(309714004);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "Nvidia.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "30 Sep 2022 12:53:58.9511 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 49c437d0-d2cf-4fc7-ae99-08daa2e2d7ac",
        "X-MS-Exchange-CrossTenant-Id": "43083d15-7273-40c1-b7db-39efd9ccc17a",
        "X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp": "\n TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[216.228.117.161];\n Helo=[mail.nvidia.com]",
        "X-MS-Exchange-CrossTenant-AuthSource": "\n DM6NAM11FT102.eop-nam11.prod.protection.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "DM4PR12MB5818",
        "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: Dariusz Sosnowski <dsosnowski@nvidia.com>\n\nThis patch adapts mlx5 PMD to changes in mlx5dr API regarding action\ntemplates. It changes the following:\n\n1. Actions template creation:\n\n    - Flow actions types are translated to mlx5dr action types in order\n      to create mlx5dr_action_template object.\n    - An offset is assigned to each flow action. This offset is used to\n      predetermine action's location in rule_acts array passed on rule\n      creation.\n\n2. Template table creation:\n\n    - Fixed actions are created and put in rule_acts cache using\n      predetermined offsets\n    - mlx5dr matcher is parametrized by action templates bound to\n      template table.\n    - mlx5dr matcher is configured to optimize rule creation based on\n      passed rule indices.\n\n3. Flow rule creation:\n\n    - mlx5dr rule is parametrized by action template on which these\n      rule's actions are based.\n    - Rule index hint is provided to mlx5dr.\n\nSigned-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>\n---\n drivers/net/mlx5/linux/mlx5_os.c |   1 +\n drivers/net/mlx5/mlx5.c          |   4 +-\n drivers/net/mlx5/mlx5.h          |   2 +\n drivers/net/mlx5/mlx5_flow.h     |  30 +-\n drivers/net/mlx5/mlx5_flow_hw.c  | 617 +++++++++++++++++++++++++------\n drivers/net/mlx5/mlx5_trigger.c  |  10 +\n 6 files changed, 541 insertions(+), 123 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c\nindex 061b825e7b..65795da516 100644\n--- a/drivers/net/mlx5/linux/mlx5_os.c\n+++ b/drivers/net/mlx5/linux/mlx5_os.c\n@@ -1565,6 +1565,7 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n \t\t}\n \t\t/* Only HWS requires this information. */\n \t\tflow_hw_init_tags_set(eth_dev);\n+\t\tflow_hw_init_flow_metadata_config(eth_dev);\n \t\tif (priv->sh->config.dv_esw_en &&\n \t\t    flow_hw_create_vport_action(eth_dev)) {\n \t\t\tDRV_LOG(ERR, \"port %u failed to create vport action\",\ndiff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex b6a66f12ee..cf7b7b7158 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -1969,8 +1969,10 @@ mlx5_dev_close(struct rte_eth_dev *dev)\n \tflow_hw_destroy_vport_action(dev);\n \tflow_hw_resource_release(dev);\n \tflow_hw_clear_port_info(dev);\n-\tif (priv->sh->config.dv_flow_en == 2)\n+\tif (priv->sh->config.dv_flow_en == 2) {\n+\t\tflow_hw_clear_flow_metadata_config();\n \t\tflow_hw_clear_tags_set(dev);\n+\t}\n #endif\n \tif (priv->rxq_privs != NULL) {\n \t\t/* XXX race condition if mlx5_rx_burst() is still running. */\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 4859f5a509..c0835e725f 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -1644,6 +1644,8 @@ struct mlx5_priv {\n \tstruct mlx5dr_action *hw_drop[2];\n \t/* HW steering global tag action. */\n \tstruct mlx5dr_action *hw_tag[2];\n+\t/* HW steering create ongoing rte flow table list header. */\n+\tLIST_HEAD(flow_hw_tbl_ongo, rte_flow_template_table) flow_hw_tbl_ongo;\n \tstruct mlx5_indexed_pool *acts_ipool; /* Action data indexed pool. */\n #endif\n };\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex 8f1b66eaac..ae1417f10e 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -1175,6 +1175,11 @@ struct rte_flow_actions_template {\n \tstruct rte_flow_actions_template_attr attr;\n \tstruct rte_flow_action *actions; /* Cached flow actions. */\n \tstruct rte_flow_action *masks; /* Cached action masks.*/\n+\tstruct mlx5dr_action_template *tmpl; /* mlx5dr action template. */\n+\tuint16_t dr_actions_num; /* Amount of DR rules actions. */\n+\tuint16_t actions_num; /* Amount of flow actions */\n+\tuint16_t *actions_off; /* DR action offset for given rte action offset. */\n+\tuint16_t reformat_off; /* Offset of DR reformat action. */\n \tuint16_t mhdr_off; /* Offset of DR modify header action. */\n \tuint32_t refcnt; /* Reference counter. */\n \tuint16_t rx_cpy_pos; /* Action position of Rx metadata to be copied. */\n@@ -1226,7 +1231,6 @@ struct mlx5_hw_actions {\n \t/* Encap/Decap action. */\n \tstruct mlx5_hw_encap_decap_action *encap_decap;\n \tuint16_t encap_decap_pos; /* Encap/Decap action position. */\n-\tuint32_t acts_num:4; /* Total action number. */\n \tuint32_t mark:1; /* Indicate the mark action. */\n \tuint32_t cnt_id; /* Counter id. */\n \t/* Translated DR action array from action template. */\n@@ -1482,6 +1486,13 @@ flow_hw_get_wire_port(struct ibv_context *ibctx)\n }\n #endif\n \n+extern uint32_t mlx5_flow_hw_flow_metadata_config_refcnt;\n+extern uint8_t mlx5_flow_hw_flow_metadata_esw_en;\n+extern uint8_t mlx5_flow_hw_flow_metadata_xmeta_en;\n+\n+void flow_hw_init_flow_metadata_config(struct rte_eth_dev *dev);\n+void flow_hw_clear_flow_metadata_config(void);\n+\n /*\n  * Convert metadata or tag to the actual register.\n  * META: Can only be used to match in the FDB in this stage, fixed C_1.\n@@ -1493,7 +1504,20 @@ flow_hw_get_reg_id(enum rte_flow_item_type type, uint32_t id)\n {\n \tswitch (type) {\n \tcase RTE_FLOW_ITEM_TYPE_META:\n-\t\treturn REG_C_1;\n+\t\tif (mlx5_flow_hw_flow_metadata_esw_en &&\n+\t\t    mlx5_flow_hw_flow_metadata_xmeta_en == MLX5_XMETA_MODE_META32_HWS) {\n+\t\t\treturn REG_C_1;\n+\t\t}\n+\t\t/*\n+\t\t * On root table - PMD allows only egress META matching, thus\n+\t\t * REG_A matching is sufficient.\n+\t\t *\n+\t\t * On non-root tables - REG_A corresponds to general_purpose_lookup_field,\n+\t\t * which translates to REG_A in NIC TX and to REG_B in NIC RX.\n+\t\t * However, current FW does not implement REG_B case right now, so\n+\t\t * REG_B case should be rejected on pattern template validation.\n+\t\t */\n+\t\treturn REG_A;\n \tcase RTE_FLOW_ITEM_TYPE_TAG:\n \t\tMLX5_ASSERT(id < MLX5_FLOW_HW_TAGS_MAX);\n \t\treturn mlx5_flow_hw_avl_tags[id];\n@@ -2402,4 +2426,6 @@ int mlx5_flow_pattern_validate(struct rte_eth_dev *dev,\n \t\tconst struct rte_flow_pattern_template_attr *attr,\n \t\tconst struct rte_flow_item items[],\n \t\tstruct rte_flow_error *error);\n+int flow_hw_table_update(struct rte_eth_dev *dev,\n+\t\t\t struct rte_flow_error *error);\n #endif /* RTE_PMD_MLX5_FLOW_H_ */\ndiff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c\nindex 507abb54e4..91835cd024 100644\n--- a/drivers/net/mlx5/mlx5_flow_hw.c\n+++ b/drivers/net/mlx5/mlx5_flow_hw.c\n@@ -340,6 +340,13 @@ __flow_hw_action_template_destroy(struct rte_eth_dev *dev,\n \t\t\t\t struct mlx5_hw_actions *acts)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_action_construct_data *data;\n+\n+\twhile (!LIST_EMPTY(&acts->act_list)) {\n+\t\tdata = LIST_FIRST(&acts->act_list);\n+\t\tLIST_REMOVE(data, next);\n+\t\tmlx5_ipool_free(priv->acts_ipool, data->idx);\n+\t}\n \n \tif (acts->jump) {\n \t\tstruct mlx5_flow_group *grp;\n@@ -349,6 +356,16 @@ __flow_hw_action_template_destroy(struct rte_eth_dev *dev,\n \t\tmlx5_hlist_unregister(priv->sh->flow_tbls, &grp->entry);\n \t\tacts->jump = NULL;\n \t}\n+\tif (acts->tir) {\n+\t\tmlx5_hrxq_release(dev, acts->tir->idx);\n+\t\tacts->tir = NULL;\n+\t}\n+\tif (acts->encap_decap) {\n+\t\tif (acts->encap_decap->action)\n+\t\t\tmlx5dr_action_destroy(acts->encap_decap->action);\n+\t\tmlx5_free(acts->encap_decap);\n+\t\tacts->encap_decap = NULL;\n+\t}\n \tif (acts->mhdr) {\n \t\tif (acts->mhdr->action)\n \t\t\tmlx5dr_action_destroy(acts->mhdr->action);\n@@ -967,33 +984,29 @@ flow_hw_represented_port_compile(struct rte_eth_dev *dev,\n static __rte_always_inline int\n flow_hw_meter_compile(struct rte_eth_dev *dev,\n \t\t      const struct mlx5_flow_template_table_cfg *cfg,\n-\t\t      uint32_t  start_pos, const struct rte_flow_action *action,\n-\t\t      struct mlx5_hw_actions *acts, uint32_t *end_pos,\n+\t\t      uint16_t aso_mtr_pos,\n+\t\t      uint16_t jump_pos,\n+\t\t      const struct rte_flow_action *action,\n+\t\t      struct mlx5_hw_actions *acts,\n \t\t      struct rte_flow_error *error)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_aso_mtr *aso_mtr;\n \tconst struct rte_flow_action_meter *meter = action->conf;\n-\tuint32_t pos = start_pos;\n \tuint32_t group = cfg->attr.flow_attr.group;\n \n \taso_mtr = mlx5_aso_meter_by_idx(priv, meter->mtr_id);\n-\tacts->rule_acts[pos].action = priv->mtr_bulk.action;\n-\tacts->rule_acts[pos].aso_meter.offset = aso_mtr->offset;\n-\t\tacts->jump = flow_hw_jump_action_register\n+\tacts->rule_acts[aso_mtr_pos].action = priv->mtr_bulk.action;\n+\tacts->rule_acts[aso_mtr_pos].aso_meter.offset = aso_mtr->offset;\n+\tacts->jump = flow_hw_jump_action_register\n \t\t(dev, cfg, aso_mtr->fm.group, error);\n-\tif (!acts->jump) {\n-\t\t*end_pos = start_pos;\n+\tif (!acts->jump)\n \t\treturn -ENOMEM;\n-\t}\n-\tacts->rule_acts[++pos].action = (!!group) ?\n+\tacts->rule_acts[jump_pos].action = (!!group) ?\n \t\t\t\t    acts->jump->hws_action :\n \t\t\t\t    acts->jump->root_action;\n-\t*end_pos = pos;\n-\tif (mlx5_aso_mtr_wait(priv->sh, aso_mtr)) {\n-\t\t*end_pos = start_pos;\n+\tif (mlx5_aso_mtr_wait(priv->sh, aso_mtr))\n \t\treturn -ENOMEM;\n-\t}\n \treturn 0;\n }\n \n@@ -1046,11 +1059,11 @@ flow_hw_cnt_compile(struct rte_eth_dev *dev, uint32_t  start_pos,\n  *    Table on success, NULL otherwise and rte_errno is set.\n  */\n static int\n-flow_hw_actions_translate(struct rte_eth_dev *dev,\n-\t\t\t  const struct mlx5_flow_template_table_cfg *cfg,\n-\t\t\t  struct mlx5_hw_actions *acts,\n-\t\t\t  struct rte_flow_actions_template *at,\n-\t\t\t  struct rte_flow_error *error)\n+__flow_hw_actions_translate(struct rte_eth_dev *dev,\n+\t\t\t    const struct mlx5_flow_template_table_cfg *cfg,\n+\t\t\t    struct mlx5_hw_actions *acts,\n+\t\t\t    struct rte_flow_actions_template *at,\n+\t\t\t    struct rte_flow_error *error)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tconst struct rte_flow_template_table_attr *table_attr = &cfg->attr;\n@@ -1061,12 +1074,15 @@ flow_hw_actions_translate(struct rte_eth_dev *dev,\n \tenum mlx5dr_action_reformat_type refmt_type = 0;\n \tconst struct rte_flow_action_raw_encap *raw_encap_data;\n \tconst struct rte_flow_item *enc_item = NULL, *enc_item_m = NULL;\n-\tuint16_t reformat_pos = MLX5_HW_MAX_ACTS, reformat_src = 0;\n+\tuint16_t reformat_src = 0;\n \tuint8_t *encap_data = NULL, *encap_data_m = NULL;\n \tsize_t data_size = 0;\n \tstruct mlx5_hw_modify_header_action mhdr = { 0 };\n \tbool actions_end = false;\n-\tuint32_t type, i;\n+\tuint32_t type;\n+\tbool reformat_used = false;\n+\tuint16_t action_pos;\n+\tuint16_t jump_pos;\n \tint err;\n \n \tflow_hw_modify_field_init(&mhdr, at);\n@@ -1076,46 +1092,53 @@ flow_hw_actions_translate(struct rte_eth_dev *dev,\n \t\ttype = MLX5DR_TABLE_TYPE_NIC_TX;\n \telse\n \t\ttype = MLX5DR_TABLE_TYPE_NIC_RX;\n-\tfor (i = 0; !actions_end; actions++, masks++) {\n+\tfor (; !actions_end; actions++, masks++) {\n \t\tswitch (actions->type) {\n \t\tcase RTE_FLOW_ACTION_TYPE_INDIRECT:\n+\t\t\taction_pos = at->actions_off[actions - at->actions];\n \t\t\tif (!attr->group) {\n \t\t\t\tDRV_LOG(ERR, \"Indirect action is not supported in root table.\");\n \t\t\t\tgoto err;\n \t\t\t}\n \t\t\tif (actions->conf && masks->conf) {\n \t\t\t\tif (flow_hw_shared_action_translate\n-\t\t\t\t(dev, actions, acts, actions - action_start, i))\n+\t\t\t\t(dev, actions, acts, actions - action_start, action_pos))\n \t\t\t\t\tgoto err;\n \t\t\t} else if (__flow_hw_act_data_general_append\n \t\t\t\t\t(priv, acts, actions->type,\n-\t\t\t\t\t actions - action_start, i)){\n+\t\t\t\t\t actions - action_start, action_pos)){\n \t\t\t\tgoto err;\n \t\t\t}\n-\t\t\ti++;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_VOID:\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_DROP:\n-\t\t\tacts->rule_acts[i++].action =\n+\t\t\taction_pos = at->actions_off[actions - at->actions];\n+\t\t\tacts->rule_acts[action_pos].action =\n \t\t\t\tpriv->hw_drop[!!attr->group];\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_MARK:\n+\t\t\taction_pos = at->actions_off[actions - at->actions];\n \t\t\tacts->mark = true;\n-\t\t\tif (masks->conf)\n-\t\t\t\tacts->rule_acts[i].tag.value =\n+\t\t\tif (masks->conf &&\n+\t\t\t    ((const struct rte_flow_action_mark *)\n+\t\t\t     masks->conf)->id)\n+\t\t\t\tacts->rule_acts[action_pos].tag.value =\n \t\t\t\t\tmlx5_flow_mark_set\n \t\t\t\t\t(((const struct rte_flow_action_mark *)\n-\t\t\t\t\t(masks->conf))->id);\n+\t\t\t\t\t(actions->conf))->id);\n \t\t\telse if (__flow_hw_act_data_general_append(priv, acts,\n-\t\t\t\tactions->type, actions - action_start, i))\n+\t\t\t\tactions->type, actions - action_start, action_pos))\n \t\t\t\tgoto err;\n-\t\t\tacts->rule_acts[i++].action =\n+\t\t\tacts->rule_acts[action_pos].action =\n \t\t\t\tpriv->hw_tag[!!attr->group];\n \t\t\tflow_hw_rxq_flag_set(dev, true);\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_JUMP:\n-\t\t\tif (masks->conf) {\n+\t\t\taction_pos = at->actions_off[actions - at->actions];\n+\t\t\tif (masks->conf &&\n+\t\t\t    ((const struct rte_flow_action_jump *)\n+\t\t\t     masks->conf)->group) {\n \t\t\t\tuint32_t jump_group =\n \t\t\t\t\t((const struct rte_flow_action_jump *)\n \t\t\t\t\tactions->conf)->group;\n@@ -1123,76 +1146,77 @@ flow_hw_actions_translate(struct rte_eth_dev *dev,\n \t\t\t\t\t\t(dev, cfg, jump_group, error);\n \t\t\t\tif (!acts->jump)\n \t\t\t\t\tgoto err;\n-\t\t\t\tacts->rule_acts[i].action = (!!attr->group) ?\n+\t\t\t\tacts->rule_acts[action_pos].action = (!!attr->group) ?\n \t\t\t\t\t\tacts->jump->hws_action :\n \t\t\t\t\t\tacts->jump->root_action;\n \t\t\t} else if (__flow_hw_act_data_general_append\n \t\t\t\t\t(priv, acts, actions->type,\n-\t\t\t\t\t actions - action_start, i)){\n+\t\t\t\t\t actions - action_start, action_pos)){\n \t\t\t\tgoto err;\n \t\t\t}\n-\t\t\ti++;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_QUEUE:\n-\t\t\tif (masks->conf) {\n+\t\t\taction_pos = at->actions_off[actions - at->actions];\n+\t\t\tif (masks->conf &&\n+\t\t\t    ((const struct rte_flow_action_queue *)\n+\t\t\t     masks->conf)->index) {\n \t\t\t\tacts->tir = flow_hw_tir_action_register\n \t\t\t\t(dev,\n \t\t\t\t mlx5_hw_act_flag[!!attr->group][type],\n \t\t\t\t actions);\n \t\t\t\tif (!acts->tir)\n \t\t\t\t\tgoto err;\n-\t\t\t\tacts->rule_acts[i].action =\n+\t\t\t\tacts->rule_acts[action_pos].action =\n \t\t\t\t\tacts->tir->action;\n \t\t\t} else if (__flow_hw_act_data_general_append\n \t\t\t\t\t(priv, acts, actions->type,\n-\t\t\t\t\t actions - action_start, i)) {\n+\t\t\t\t\t actions - action_start, action_pos)) {\n \t\t\t\tgoto err;\n \t\t\t}\n-\t\t\ti++;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_RSS:\n-\t\t\tif (masks->conf) {\n+\t\t\taction_pos = at->actions_off[actions - at->actions];\n+\t\t\tif (actions->conf && masks->conf) {\n \t\t\t\tacts->tir = flow_hw_tir_action_register\n \t\t\t\t(dev,\n \t\t\t\t mlx5_hw_act_flag[!!attr->group][type],\n \t\t\t\t actions);\n \t\t\t\tif (!acts->tir)\n \t\t\t\t\tgoto err;\n-\t\t\t\tacts->rule_acts[i].action =\n+\t\t\t\tacts->rule_acts[action_pos].action =\n \t\t\t\t\tacts->tir->action;\n \t\t\t} else if (__flow_hw_act_data_general_append\n \t\t\t\t\t(priv, acts, actions->type,\n-\t\t\t\t\t actions - action_start, i)) {\n+\t\t\t\t\t actions - action_start, action_pos)) {\n \t\t\t\tgoto err;\n \t\t\t}\n-\t\t\ti++;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:\n-\t\t\tMLX5_ASSERT(reformat_pos == MLX5_HW_MAX_ACTS);\n+\t\t\tMLX5_ASSERT(!reformat_used);\n \t\t\tenc_item = ((const struct rte_flow_action_vxlan_encap *)\n \t\t\t\t   actions->conf)->definition;\n \t\t\tif (masks->conf)\n \t\t\t\tenc_item_m = ((const struct rte_flow_action_vxlan_encap *)\n \t\t\t\t\t     masks->conf)->definition;\n-\t\t\treformat_pos = i++;\n+\t\t\treformat_used = true;\n \t\t\treformat_src = actions - action_start;\n \t\t\trefmt_type = MLX5DR_ACTION_REFORMAT_TYPE_L2_TO_TNL_L2;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:\n-\t\t\tMLX5_ASSERT(reformat_pos == MLX5_HW_MAX_ACTS);\n+\t\t\tMLX5_ASSERT(!reformat_used);\n \t\t\tenc_item = ((const struct rte_flow_action_nvgre_encap *)\n \t\t\t\t   actions->conf)->definition;\n \t\t\tif (masks->conf)\n \t\t\t\tenc_item_m = ((const struct rte_flow_action_nvgre_encap *)\n \t\t\t\t\t     masks->conf)->definition;\n-\t\t\treformat_pos = i++;\n+\t\t\treformat_used = true;\n \t\t\treformat_src = actions - action_start;\n \t\t\trefmt_type = MLX5DR_ACTION_REFORMAT_TYPE_L2_TO_TNL_L2;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:\n \t\tcase RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:\n-\t\t\tMLX5_ASSERT(reformat_pos == MLX5_HW_MAX_ACTS);\n-\t\t\treformat_pos = i++;\n+\t\t\tMLX5_ASSERT(!reformat_used);\n+\t\t\treformat_used = true;\n \t\t\trefmt_type = MLX5DR_ACTION_REFORMAT_TYPE_TNL_L2_TO_L2;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_RAW_ENCAP:\n@@ -1206,25 +1230,23 @@ flow_hw_actions_translate(struct rte_eth_dev *dev,\n \t\t\t\t actions->conf;\n \t\t\tencap_data = raw_encap_data->data;\n \t\t\tdata_size = raw_encap_data->size;\n-\t\t\tif (reformat_pos != MLX5_HW_MAX_ACTS) {\n+\t\t\tif (reformat_used) {\n \t\t\t\trefmt_type = data_size <\n \t\t\t\tMLX5_ENCAPSULATION_DECISION_SIZE ?\n \t\t\t\tMLX5DR_ACTION_REFORMAT_TYPE_TNL_L3_TO_L2 :\n \t\t\t\tMLX5DR_ACTION_REFORMAT_TYPE_L2_TO_TNL_L3;\n \t\t\t} else {\n-\t\t\t\treformat_pos = i++;\n+\t\t\t\treformat_used = true;\n \t\t\t\trefmt_type =\n \t\t\t\tMLX5DR_ACTION_REFORMAT_TYPE_L2_TO_TNL_L2;\n \t\t\t}\n \t\t\treformat_src = actions - action_start;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_RAW_DECAP:\n-\t\t\treformat_pos = i++;\n+\t\t\treformat_used = true;\n \t\t\trefmt_type = MLX5DR_ACTION_REFORMAT_TYPE_TNL_L2_TO_L2;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:\n-\t\t\tif (mhdr.pos == UINT16_MAX)\n-\t\t\t\tmhdr.pos = i++;\n \t\t\terr = flow_hw_modify_field_compile(dev, attr, action_start,\n \t\t\t\t\t\t\t   actions, masks, acts, &mhdr,\n \t\t\t\t\t\t\t   error);\n@@ -1242,40 +1264,46 @@ flow_hw_actions_translate(struct rte_eth_dev *dev,\n \t\t\t\taction_start += 1;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:\n+\t\t\taction_pos = at->actions_off[actions - at->actions];\n \t\t\tif (flow_hw_represented_port_compile\n \t\t\t\t\t(dev, attr, action_start, actions,\n-\t\t\t\t\t masks, acts, i, error))\n+\t\t\t\t\t masks, acts, action_pos, error))\n \t\t\t\tgoto err;\n-\t\t\ti++;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_METER:\n+\t\t\t/*\n+\t\t\t * METER action is compiled to 2 DR actions - ASO_METER and FT.\n+\t\t\t * Calculated DR offset is stored only for ASO_METER and FT\n+\t\t\t * is assumed to be the next action.\n+\t\t\t */\n+\t\t\taction_pos = at->actions_off[actions - at->actions];\n+\t\t\tjump_pos = action_pos + 1;\n \t\t\tif (actions->conf && masks->conf &&\n \t\t\t    ((const struct rte_flow_action_meter *)\n \t\t\t     masks->conf)->mtr_id) {\n \t\t\t\terr = flow_hw_meter_compile(dev, cfg,\n-\t\t\t\t\t\ti, actions, acts, &i, error);\n+\t\t\t\t\t\taction_pos, jump_pos, actions, acts, error);\n \t\t\t\tif (err)\n \t\t\t\t\tgoto err;\n \t\t\t} else if (__flow_hw_act_data_general_append(priv, acts,\n \t\t\t\t\t\t\tactions->type,\n \t\t\t\t\t\t\tactions - action_start,\n-\t\t\t\t\t\t\ti))\n+\t\t\t\t\t\t\taction_pos))\n \t\t\t\tgoto err;\n-\t\t\ti++;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n+\t\t\taction_pos = at->actions_off[actions - action_start];\n \t\t\tif (masks->conf &&\n \t\t\t    ((const struct rte_flow_action_count *)\n \t\t\t     masks->conf)->id) {\n-\t\t\t\terr = flow_hw_cnt_compile(dev, i, acts);\n+\t\t\t\terr = flow_hw_cnt_compile(dev, action_pos, acts);\n \t\t\t\tif (err)\n \t\t\t\t\tgoto err;\n \t\t\t} else if (__flow_hw_act_data_general_append\n \t\t\t\t\t(priv, acts, actions->type,\n-\t\t\t\t\t actions - action_start, i)) {\n+\t\t\t\t\t actions - action_start, action_pos)) {\n \t\t\t\tgoto err;\n \t\t\t}\n-\t\t\ti++;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_END:\n \t\t\tactions_end = true;\n@@ -1309,10 +1337,11 @@ flow_hw_actions_translate(struct rte_eth_dev *dev,\n \t\t\tgoto err;\n \t\tacts->rule_acts[acts->mhdr->pos].action = acts->mhdr->action;\n \t}\n-\tif (reformat_pos != MLX5_HW_MAX_ACTS) {\n+\tif (reformat_used) {\n \t\tuint8_t buf[MLX5_ENCAP_MAX_LEN];\n \t\tbool shared_rfmt = true;\n \n+\t\tMLX5_ASSERT(at->reformat_off != UINT16_MAX);\n \t\tif (enc_item) {\n \t\t\tMLX5_ASSERT(!encap_data);\n \t\t\tif (flow_dv_convert_encap_data(enc_item, buf, &data_size, error))\n@@ -1340,20 +1369,17 @@ flow_hw_actions_translate(struct rte_eth_dev *dev,\n \t\t\t\t (shared_rfmt ? MLX5DR_ACTION_FLAG_SHARED : 0));\n \t\tif (!acts->encap_decap->action)\n \t\t\tgoto err;\n-\t\tacts->rule_acts[reformat_pos].action =\n-\t\t\t\t\t\tacts->encap_decap->action;\n-\t\tacts->rule_acts[reformat_pos].reformat.data =\n-\t\t\t\t\t\tacts->encap_decap->data;\n+\t\tacts->rule_acts[at->reformat_off].action = acts->encap_decap->action;\n+\t\tacts->rule_acts[at->reformat_off].reformat.data = acts->encap_decap->data;\n \t\tif (shared_rfmt)\n-\t\t\tacts->rule_acts[reformat_pos].reformat.offset = 0;\n+\t\t\tacts->rule_acts[at->reformat_off].reformat.offset = 0;\n \t\telse if (__flow_hw_act_data_encap_append(priv, acts,\n \t\t\t\t (action_start + reformat_src)->type,\n-\t\t\t\t reformat_src, reformat_pos, data_size))\n+\t\t\t\t reformat_src, at->reformat_off, data_size))\n \t\t\tgoto err;\n \t\tacts->encap_decap->shared = shared_rfmt;\n-\t\tacts->encap_decap_pos = reformat_pos;\n+\t\tacts->encap_decap_pos = at->reformat_off;\n \t}\n-\tacts->acts_num = i;\n \treturn 0;\n err:\n \terr = rte_errno;\n@@ -1363,6 +1389,40 @@ flow_hw_actions_translate(struct rte_eth_dev *dev,\n \t\t\t\t  \"fail to create rte table\");\n }\n \n+/**\n+ * Translate rte_flow actions to DR action.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the rte_eth_dev structure.\n+ * @param[in] tbl\n+ *   Pointer to the flow template table.\n+ * @param[out] error\n+ *   Pointer to error structure.\n+ *\n+ * @return\n+ *    0 on success, negative value otherwise and rte_errno is set.\n+ */\n+static int\n+flow_hw_actions_translate(struct rte_eth_dev *dev,\n+\t\t\t  struct rte_flow_template_table *tbl,\n+\t\t\t  struct rte_flow_error *error)\n+{\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < tbl->nb_action_templates; i++) {\n+\t\tif (__flow_hw_actions_translate(dev, &tbl->cfg,\n+\t\t\t\t\t\t&tbl->ats[i].acts,\n+\t\t\t\t\t\ttbl->ats[i].action_template,\n+\t\t\t\t\t\terror))\n+\t\t\tgoto err;\n+\t}\n+\treturn 0;\n+err:\n+\twhile (i--)\n+\t\t__flow_hw_action_template_destroy(dev, &tbl->ats[i].acts);\n+\treturn -1;\n+}\n+\n /**\n  * Get shared indirect action.\n  *\n@@ -1611,16 +1671,17 @@ flow_hw_modify_field_construct(struct mlx5_hw_q_job *job,\n static __rte_always_inline int\n flow_hw_actions_construct(struct rte_eth_dev *dev,\n \t\t\t  struct mlx5_hw_q_job *job,\n-\t\t\t  const struct mlx5_hw_actions *hw_acts,\n+\t\t\t  const struct mlx5_hw_action_template *hw_at,\n \t\t\t  const uint8_t it_idx,\n \t\t\t  const struct rte_flow_action actions[],\n \t\t\t  struct mlx5dr_rule_action *rule_acts,\n-\t\t\t  uint32_t *acts_num,\n \t\t\t  uint32_t queue)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct rte_flow_template_table *table = job->flow->table;\n \tstruct mlx5_action_construct_data *act_data;\n+\tconst struct rte_flow_actions_template *at = hw_at->action_template;\n+\tconst struct mlx5_hw_actions *hw_acts = &hw_at->acts;\n \tconst struct rte_flow_action *action;\n \tconst struct rte_flow_action_raw_encap *raw_encap_data;\n \tconst struct rte_flow_item *enc_item = NULL;\n@@ -1636,11 +1697,7 @@ flow_hw_actions_construct(struct rte_eth_dev *dev,\n \tstruct mlx5_aso_mtr *mtr;\n \tuint32_t mtr_id;\n \n-\tmemcpy(rule_acts, hw_acts->rule_acts,\n-\t       sizeof(*rule_acts) * hw_acts->acts_num);\n-\t*acts_num = hw_acts->acts_num;\n-\tif (LIST_EMPTY(&hw_acts->act_list))\n-\t\treturn 0;\n+\trte_memcpy(rule_acts, hw_acts->rule_acts, sizeof(*rule_acts) * at->dr_actions_num);\n \tattr.group = table->grp->group_id;\n \tft_flag = mlx5_hw_act_flag[!!table->grp->group_id][table->type];\n \tif (table->type == MLX5DR_TABLE_TYPE_FDB) {\n@@ -1774,7 +1831,6 @@ flow_hw_actions_construct(struct rte_eth_dev *dev,\n \t\t\t\t\t\t\t jump->root_action;\n \t\t\tjob->flow->jump = jump;\n \t\t\tjob->flow->fate_type = MLX5_FLOW_FATE_JUMP;\n-\t\t\t(*acts_num)++;\n \t\t\tif (mlx5_aso_mtr_wait(priv->sh, mtr))\n \t\t\t\treturn -1;\n \t\t\tbreak;\n@@ -1912,13 +1968,16 @@ flow_hw_async_flow_create(struct rte_eth_dev *dev,\n \t\t.burst = attr->postpone,\n \t};\n \tstruct mlx5dr_rule_action rule_acts[MLX5_HW_MAX_ACTS];\n-\tstruct mlx5_hw_actions *hw_acts;\n \tstruct rte_flow_hw *flow;\n \tstruct mlx5_hw_q_job *job;\n \tconst struct rte_flow_item *rule_items;\n-\tuint32_t acts_num, flow_idx;\n+\tuint32_t flow_idx;\n \tint ret;\n \n+\tif (unlikely((!dev->data->dev_started))) {\n+\t\trte_errno = EINVAL;\n+\t\tgoto error;\n+\t}\n \tif (unlikely(!priv->hw_q[queue].job_idx)) {\n \t\trte_errno = ENOMEM;\n \t\tgoto error;\n@@ -1941,7 +2000,12 @@ flow_hw_async_flow_create(struct rte_eth_dev *dev,\n \tjob->flow = flow;\n \tjob->user_data = user_data;\n \trule_attr.user_data = job;\n-\thw_acts = &table->ats[action_template_index].acts;\n+\t/*\n+\t * Indexed pool returns 1-based indices, but mlx5dr expects 0-based indices for rule\n+\t * insertion hints.\n+\t */\n+\tMLX5_ASSERT(flow_idx > 0);\n+\trule_attr.rule_idx = flow_idx - 1;\n \t/*\n \t * Construct the flow actions based on the input actions.\n \t * The implicitly appended action is always fixed, like metadata\n@@ -1949,8 +2013,8 @@ flow_hw_async_flow_create(struct rte_eth_dev *dev,\n \t * No need to copy and contrust a new \"actions\" list based on the\n \t * user's input, in order to save the cost.\n \t */\n-\tif (flow_hw_actions_construct(dev, job, hw_acts, pattern_template_index,\n-\t\t\t\t  actions, rule_acts, &acts_num, queue)) {\n+\tif (flow_hw_actions_construct(dev, job, &table->ats[action_template_index],\n+\t\t\t\t      pattern_template_index, actions, rule_acts, queue)) {\n \t\trte_errno = EINVAL;\n \t\tgoto free;\n \t}\n@@ -1959,7 +2023,7 @@ flow_hw_async_flow_create(struct rte_eth_dev *dev,\n \tif (!rule_items)\n \t\tgoto free;\n \tret = mlx5dr_rule_create(table->matcher,\n-\t\t\t\t pattern_template_index, items,\n+\t\t\t\t pattern_template_index, rule_items,\n \t\t\t\t action_template_index, rule_acts,\n \t\t\t\t &rule_attr, &flow->rule);\n \tif (likely(!ret))\n@@ -2295,6 +2359,7 @@ flow_hw_table_create(struct rte_eth_dev *dev,\n \tstruct rte_flow_template_table *tbl = NULL;\n \tstruct mlx5_flow_group *grp;\n \tstruct mlx5dr_match_template *mt[MLX5_HW_TBL_MAX_ITEM_TEMPLATE];\n+\tstruct mlx5dr_action_template *at[MLX5_HW_TBL_MAX_ACTION_TEMPLATE];\n \tconst struct rte_flow_template_table_attr *attr = &table_cfg->attr;\n \tstruct rte_flow_attr flow_attr = attr->flow_attr;\n \tstruct mlx5_flow_cb_ctx ctx = {\n@@ -2315,6 +2380,7 @@ flow_hw_table_create(struct rte_eth_dev *dev,\n \tstruct mlx5_list_entry *ge;\n \tuint32_t i, max_tpl = MLX5_HW_TBL_MAX_ITEM_TEMPLATE;\n \tuint32_t nb_flows = rte_align32pow2(attr->nb_flows);\n+\tbool port_started = !!dev->data->dev_started;\n \tint err;\n \n \t/* HWS layer accepts only 1 item template with root table. */\n@@ -2349,12 +2415,20 @@ flow_hw_table_create(struct rte_eth_dev *dev,\n \ttbl->grp = grp;\n \t/* Prepare matcher information. */\n \tmatcher_attr.priority = attr->flow_attr.priority;\n+\tmatcher_attr.optimize_using_rule_idx = true;\n \tmatcher_attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_RULE;\n \tmatcher_attr.rule.num_log = rte_log2_u32(nb_flows);\n \t/* Build the item template. */\n \tfor (i = 0; i < nb_item_templates; i++) {\n \t\tuint32_t ret;\n \n+\t\tif ((flow_attr.ingress && !item_templates[i]->attr.ingress) ||\n+\t\t    (flow_attr.egress && !item_templates[i]->attr.egress) ||\n+\t\t    (flow_attr.transfer && !item_templates[i]->attr.transfer)) {\n+\t\t\tDRV_LOG(ERR, \"pattern template and template table attribute mismatch\");\n+\t\t\trte_errno = EINVAL;\n+\t\t\tgoto it_error;\n+\t\t}\n \t\tret = __atomic_add_fetch(&item_templates[i]->refcnt, 1,\n \t\t\t\t\t __ATOMIC_RELAXED);\n \t\tif (ret <= 1) {\n@@ -2364,10 +2438,6 @@ flow_hw_table_create(struct rte_eth_dev *dev,\n \t\tmt[i] = item_templates[i]->mt;\n \t\ttbl->its[i] = item_templates[i];\n \t}\n-\ttbl->matcher = mlx5dr_matcher_create\n-\t\t(tbl->grp->tbl, mt, nb_item_templates, NULL, 0, &matcher_attr);\n-\tif (!tbl->matcher)\n-\t\tgoto it_error;\n \ttbl->nb_item_templates = nb_item_templates;\n \t/* Build the action template. */\n \tfor (i = 0; i < nb_action_templates; i++) {\n@@ -2379,21 +2449,31 @@ flow_hw_table_create(struct rte_eth_dev *dev,\n \t\t\trte_errno = EINVAL;\n \t\t\tgoto at_error;\n \t\t}\n+\t\tat[i] = action_templates[i]->tmpl;\n+\t\ttbl->ats[i].action_template = action_templates[i];\n \t\tLIST_INIT(&tbl->ats[i].acts.act_list);\n-\t\terr = flow_hw_actions_translate(dev, &tbl->cfg,\n-\t\t\t\t\t\t&tbl->ats[i].acts,\n-\t\t\t\t\t\taction_templates[i], error);\n+\t\tif (!port_started)\n+\t\t\tcontinue;\n+\t\terr = __flow_hw_actions_translate(dev, &tbl->cfg,\n+\t\t\t\t\t\t  &tbl->ats[i].acts,\n+\t\t\t\t\t\t  action_templates[i], error);\n \t\tif (err) {\n \t\t\ti++;\n \t\t\tgoto at_error;\n \t\t}\n-\t\ttbl->ats[i].action_template = action_templates[i];\n \t}\n \ttbl->nb_action_templates = nb_action_templates;\n+\ttbl->matcher = mlx5dr_matcher_create\n+\t\t(tbl->grp->tbl, mt, nb_item_templates, at, nb_action_templates, &matcher_attr);\n+\tif (!tbl->matcher)\n+\t\tgoto at_error;\n \ttbl->type = attr->flow_attr.transfer ? MLX5DR_TABLE_TYPE_FDB :\n \t\t    (attr->flow_attr.egress ? MLX5DR_TABLE_TYPE_NIC_TX :\n \t\t    MLX5DR_TABLE_TYPE_NIC_RX);\n-\tLIST_INSERT_HEAD(&priv->flow_hw_tbl, tbl, next);\n+\tif (port_started)\n+\t\tLIST_INSERT_HEAD(&priv->flow_hw_tbl, tbl, next);\n+\telse\n+\t\tLIST_INSERT_HEAD(&priv->flow_hw_tbl_ongo, tbl, next);\n \treturn tbl;\n at_error:\n \twhile (i--) {\n@@ -2406,7 +2486,6 @@ flow_hw_table_create(struct rte_eth_dev *dev,\n \twhile (i--)\n \t\t__atomic_sub_fetch(&item_templates[i]->refcnt,\n \t\t\t\t   1, __ATOMIC_RELAXED);\n-\tmlx5dr_matcher_destroy(tbl->matcher);\n error:\n \terr = rte_errno;\n \tif (tbl) {\n@@ -2423,6 +2502,33 @@ flow_hw_table_create(struct rte_eth_dev *dev,\n \treturn NULL;\n }\n \n+/**\n+ * Update flow template table.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the rte_eth_dev structure.\n+ * @param[out] error\n+ *   Pointer to error structure.\n+ *\n+ * @return\n+ *    0 on success, negative value otherwise and rte_errno is set.\n+ */\n+int\n+flow_hw_table_update(struct rte_eth_dev *dev,\n+\t\t     struct rte_flow_error *error)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct rte_flow_template_table *tbl;\n+\n+\twhile ((tbl = LIST_FIRST(&priv->flow_hw_tbl_ongo)) != NULL) {\n+\t\tif (flow_hw_actions_translate(dev, tbl, error))\n+\t\t\treturn -1;\n+\t\tLIST_REMOVE(tbl, next);\n+\t\tLIST_INSERT_HEAD(&priv->flow_hw_tbl, tbl, next);\n+\t}\n+\treturn 0;\n+}\n+\n /**\n  * Translates group index specified by the user in @p attr to internal\n  * group index.\n@@ -2501,6 +2607,7 @@ flow_hw_template_table_create(struct rte_eth_dev *dev,\n \t\t\t      uint8_t nb_action_templates,\n \t\t\t      struct rte_flow_error *error)\n {\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_flow_template_table_cfg cfg = {\n \t\t.attr = *attr,\n \t\t.external = true,\n@@ -2509,6 +2616,12 @@ flow_hw_template_table_create(struct rte_eth_dev *dev,\n \n \tif (flow_hw_translate_group(dev, &cfg, group, &cfg.attr.flow_attr.group, error))\n \t\treturn NULL;\n+\tif (priv->sh->config.dv_esw_en && cfg.attr.flow_attr.egress) {\n+\t\trte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, NULL,\n+\t\t\t\t  \"egress flows are not supported with HW Steering\"\n+\t\t\t\t  \" when E-Switch is enabled\");\n+\t\treturn NULL;\n+\t}\n \treturn flow_hw_table_create(dev, &cfg, item_templates, nb_item_templates,\n \t\t\t\t    action_templates, nb_action_templates, error);\n }\n@@ -2750,7 +2863,8 @@ flow_hw_actions_validate(struct rte_eth_dev *dev,\n \t\tconst struct rte_flow_action *mask = &masks[i];\n \n \t\tMLX5_ASSERT(i < MLX5_HW_MAX_ACTS);\n-\t\tif (action->type != mask->type)\n+\t\tif (action->type != RTE_FLOW_ACTION_TYPE_INDIRECT &&\n+\t\t    action->type != mask->type)\n \t\t\treturn rte_flow_error_set(error, ENOTSUP,\n \t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n \t\t\t\t\t\t  action,\n@@ -2826,6 +2940,157 @@ flow_hw_actions_validate(struct rte_eth_dev *dev,\n \treturn 0;\n }\n \n+static enum mlx5dr_action_type mlx5_hw_dr_action_types[] = {\n+\t[RTE_FLOW_ACTION_TYPE_MARK] = MLX5DR_ACTION_TYP_TAG,\n+\t[RTE_FLOW_ACTION_TYPE_DROP] = MLX5DR_ACTION_TYP_DROP,\n+\t[RTE_FLOW_ACTION_TYPE_JUMP] = MLX5DR_ACTION_TYP_FT,\n+\t[RTE_FLOW_ACTION_TYPE_QUEUE] = MLX5DR_ACTION_TYP_TIR,\n+\t[RTE_FLOW_ACTION_TYPE_RSS] = MLX5DR_ACTION_TYP_TIR,\n+\t[RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] = MLX5DR_ACTION_TYP_L2_TO_TNL_L2,\n+\t[RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP] = MLX5DR_ACTION_TYP_L2_TO_TNL_L2,\n+\t[RTE_FLOW_ACTION_TYPE_VXLAN_DECAP] = MLX5DR_ACTION_TYP_TNL_L2_TO_L2,\n+\t[RTE_FLOW_ACTION_TYPE_NVGRE_DECAP] = MLX5DR_ACTION_TYP_TNL_L2_TO_L2,\n+\t[RTE_FLOW_ACTION_TYPE_MODIFY_FIELD] = MLX5DR_ACTION_TYP_MODIFY_HDR,\n+\t[RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT] = MLX5DR_ACTION_TYP_VPORT,\n+\t[RTE_FLOW_ACTION_TYPE_COUNT] = MLX5DR_ACTION_TYP_CTR,\n+};\n+\n+static int\n+flow_hw_dr_actions_template_handle_shared(const struct rte_flow_action *mask,\n+\t\t\t\t\t  unsigned int action_src,\n+\t\t\t\t\t  enum mlx5dr_action_type *action_types,\n+\t\t\t\t\t  uint16_t *curr_off,\n+\t\t\t\t\t  struct rte_flow_actions_template *at)\n+{\n+\tuint32_t type;\n+\n+\tif (!mask) {\n+\t\tDRV_LOG(WARNING, \"Unable to determine indirect action type \"\n+\t\t\t\"without a mask specified\");\n+\t\treturn -EINVAL;\n+\t}\n+\ttype = mask->type;\n+\tswitch (type) {\n+\tcase RTE_FLOW_ACTION_TYPE_RSS:\n+\t\tat->actions_off[action_src] = *curr_off;\n+\t\taction_types[*curr_off] = MLX5DR_ACTION_TYP_TIR;\n+\t\t*curr_off = *curr_off + 1;\n+\t\tbreak;\n+\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n+\t\tat->actions_off[action_src] = *curr_off;\n+\t\taction_types[*curr_off] = MLX5DR_ACTION_TYP_CTR;\n+\t\t*curr_off = *curr_off + 1;\n+\t\tbreak;\n+\tdefault:\n+\t\tDRV_LOG(WARNING, \"Unsupported shared action type: %d\", type);\n+\t\treturn -EINVAL;\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n+ * Create DR action template based on a provided sequence of flow actions.\n+ *\n+ * @param[in] at\n+ *   Pointer to flow actions template to be updated.\n+ *\n+ * @return\n+ *   DR action template pointer on success and action offsets in @p at are updated.\n+ *   NULL otherwise.\n+ */\n+static struct mlx5dr_action_template *\n+flow_hw_dr_actions_template_create(struct rte_flow_actions_template *at)\n+{\n+\tstruct mlx5dr_action_template *dr_template;\n+\tenum mlx5dr_action_type action_types[MLX5_HW_MAX_ACTS] = { MLX5DR_ACTION_TYP_LAST };\n+\tunsigned int i;\n+\tuint16_t curr_off;\n+\tenum mlx5dr_action_type reformat_act_type = MLX5DR_ACTION_TYP_TNL_L2_TO_L2;\n+\tuint16_t reformat_off = UINT16_MAX;\n+\tuint16_t mhdr_off = UINT16_MAX;\n+\tint ret;\n+\tfor (i = 0, curr_off = 0; at->actions[i].type != RTE_FLOW_ACTION_TYPE_END; ++i) {\n+\t\tconst struct rte_flow_action_raw_encap *raw_encap_data;\n+\t\tsize_t data_size;\n+\t\tenum mlx5dr_action_type type;\n+\n+\t\tif (curr_off >= MLX5_HW_MAX_ACTS)\n+\t\t\tgoto err_actions_num;\n+\t\tswitch (at->actions[i].type) {\n+\t\tcase RTE_FLOW_ACTION_TYPE_VOID:\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_INDIRECT:\n+\t\t\tret = flow_hw_dr_actions_template_handle_shared(&at->masks[i], i,\n+\t\t\t\t\t\t\t\t\taction_types,\n+\t\t\t\t\t\t\t\t\t&curr_off, at);\n+\t\t\tif (ret)\n+\t\t\t\treturn NULL;\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:\n+\t\tcase RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:\n+\t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:\n+\t\tcase RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:\n+\t\t\tMLX5_ASSERT(reformat_off == UINT16_MAX);\n+\t\t\treformat_off = curr_off++;\n+\t\t\treformat_act_type = mlx5_hw_dr_action_types[at->actions[i].type];\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_RAW_ENCAP:\n+\t\t\traw_encap_data = at->actions[i].conf;\n+\t\t\tdata_size = raw_encap_data->size;\n+\t\t\tif (reformat_off != UINT16_MAX) {\n+\t\t\t\treformat_act_type = data_size < MLX5_ENCAPSULATION_DECISION_SIZE ?\n+\t\t\t\t\tMLX5DR_ACTION_TYP_TNL_L3_TO_L2 :\n+\t\t\t\t\tMLX5DR_ACTION_TYP_L2_TO_TNL_L3;\n+\t\t\t} else {\n+\t\t\t\treformat_off = curr_off++;\n+\t\t\t\treformat_act_type = MLX5DR_ACTION_TYP_L2_TO_TNL_L2;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_RAW_DECAP:\n+\t\t\treformat_off = curr_off++;\n+\t\t\treformat_act_type = MLX5DR_ACTION_TYP_TNL_L2_TO_L2;\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:\n+\t\t\tif (mhdr_off == UINT16_MAX) {\n+\t\t\t\tmhdr_off = curr_off++;\n+\t\t\t\ttype = mlx5_hw_dr_action_types[at->actions[i].type];\n+\t\t\t\taction_types[mhdr_off] = type;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_METER:\n+\t\t\tat->actions_off[i] = curr_off;\n+\t\t\taction_types[curr_off++] = MLX5DR_ACTION_TYP_ASO_METER;\n+\t\t\tif (curr_off >= MLX5_HW_MAX_ACTS)\n+\t\t\t\tgoto err_actions_num;\n+\t\t\taction_types[curr_off++] = MLX5DR_ACTION_TYP_FT;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\ttype = mlx5_hw_dr_action_types[at->actions[i].type];\n+\t\t\tat->actions_off[i] = curr_off;\n+\t\t\taction_types[curr_off++] = type;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tif (curr_off >= MLX5_HW_MAX_ACTS)\n+\t\tgoto err_actions_num;\n+\tif (mhdr_off != UINT16_MAX)\n+\t\tat->mhdr_off = mhdr_off;\n+\tif (reformat_off != UINT16_MAX) {\n+\t\tat->reformat_off = reformat_off;\n+\t\taction_types[reformat_off] = reformat_act_type;\n+\t}\n+\tdr_template = mlx5dr_action_template_create(action_types);\n+\tif (dr_template)\n+\t\tat->dr_actions_num = curr_off;\n+\telse\n+\t\tDRV_LOG(ERR, \"Failed to create DR action template: %d\", rte_errno);\n+\treturn dr_template;\n+err_actions_num:\n+\tDRV_LOG(ERR, \"Number of HW actions (%u) exceeded maximum (%u) allowed in template\",\n+\t\tcurr_off, MLX5_HW_MAX_ACTS);\n+\treturn NULL;\n+}\n+\n /**\n  * Create flow action template.\n  *\n@@ -2851,7 +3116,8 @@ flow_hw_actions_template_create(struct rte_eth_dev *dev,\n \t\t\tstruct rte_flow_error *error)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tint len, act_len, mask_len, i;\n+\tint len, act_num, act_len, mask_len;\n+\tunsigned int i;\n \tstruct rte_flow_actions_template *at = NULL;\n \tuint16_t pos = MLX5_HW_MAX_ACTS;\n \tstruct rte_flow_action tmp_action[MLX5_HW_MAX_ACTS];\n@@ -2921,6 +3187,11 @@ flow_hw_actions_template_create(struct rte_eth_dev *dev,\n \tif (mask_len <= 0)\n \t\treturn NULL;\n \tlen += RTE_ALIGN(mask_len, 16);\n+\t/* Count flow actions to allocate required space for storing DR offsets. */\n+\tact_num = 0;\n+\tfor (i = 0; ra[i].type != RTE_FLOW_ACTION_TYPE_END; ++i)\n+\t\tact_num++;\n+\tlen += RTE_ALIGN(act_num * sizeof(*at->actions_off), 16);\n \tat = mlx5_malloc(MLX5_MEM_ZERO, len + sizeof(*at),\n \t\t\t RTE_CACHE_LINE_SIZE, rte_socket_id());\n \tif (!at) {\n@@ -2930,19 +3201,26 @@ flow_hw_actions_template_create(struct rte_eth_dev *dev,\n \t\t\t\t   \"cannot allocate action template\");\n \t\treturn NULL;\n \t}\n-\t/* Actions part is in the first half. */\n+\t/* Actions part is in the first part. */\n \tat->attr = *attr;\n \tat->actions = (struct rte_flow_action *)(at + 1);\n \tact_len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, at->actions,\n \t\t\t\tlen, ra, error);\n \tif (act_len <= 0)\n \t\tgoto error;\n-\t/* Masks part is in the second half. */\n+\t/* Masks part is in the second part. */\n \tat->masks = (struct rte_flow_action *)(((uint8_t *)at->actions) + act_len);\n \tmask_len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, at->masks,\n \t\t\t\t len - act_len, rm, error);\n \tif (mask_len <= 0)\n \t\tgoto error;\n+\t/* DR actions offsets in the third part. */\n+\tat->actions_off = (uint16_t *)((uint8_t *)at->masks + mask_len);\n+\tat->actions_num = act_num;\n+\tfor (i = 0; i < at->actions_num; ++i)\n+\t\tat->actions_off[i] = UINT16_MAX;\n+\tat->reformat_off = UINT16_MAX;\n+\tat->mhdr_off = UINT16_MAX;\n \tat->rx_cpy_pos = pos;\n \t/*\n \t * mlx5 PMD hacks indirect action index directly to the action conf.\n@@ -2956,12 +3234,18 @@ flow_hw_actions_template_create(struct rte_eth_dev *dev,\n \t\t\tat->masks[i].conf = masks->conf;\n \t\t}\n \t}\n+\tat->tmpl = flow_hw_dr_actions_template_create(at);\n+\tif (!at->tmpl)\n+\t\tgoto error;\n \t__atomic_fetch_add(&at->refcnt, 1, __ATOMIC_RELAXED);\n \tLIST_INSERT_HEAD(&priv->flow_hw_at, at, next);\n \treturn at;\n error:\n-\tif (at)\n+\tif (at) {\n+\t\tif (at->tmpl)\n+\t\t\tmlx5dr_action_template_destroy(at->tmpl);\n \t\tmlx5_free(at);\n+\t}\n \treturn NULL;\n }\n \n@@ -2992,6 +3276,8 @@ flow_hw_actions_template_destroy(struct rte_eth_dev *dev __rte_unused,\n \t\t\t\t   \"action template in using\");\n \t}\n \tLIST_REMOVE(template, next);\n+\tif (template->tmpl)\n+\t\tmlx5dr_action_template_destroy(template->tmpl);\n \tmlx5_free(template);\n \treturn 0;\n }\n@@ -3042,11 +3328,48 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,\n \t\t\t const struct rte_flow_item items[],\n \t\t\t struct rte_flow_error *error)\n {\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n \tint i;\n \tbool items_end = false;\n-\tRTE_SET_USED(dev);\n-\tRTE_SET_USED(attr);\n \n+\tif (!attr->ingress && !attr->egress && !attr->transfer)\n+\t\treturn rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, NULL,\n+\t\t\t\t\t  \"at least one of the direction attributes\"\n+\t\t\t\t\t  \" must be specified\");\n+\tif (priv->sh->config.dv_esw_en) {\n+\t\tMLX5_ASSERT(priv->master || priv->representor);\n+\t\tif (priv->master) {\n+\t\t\t/*\n+\t\t\t * It is allowed to specify ingress, egress and transfer attributes\n+\t\t\t * at the same time, in order to construct flows catching all missed\n+\t\t\t * FDB traffic and forwarding it to the master port.\n+\t\t\t */\n+\t\t\tif (!(attr->ingress ^ attr->egress ^ attr->transfer))\n+\t\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR, NULL,\n+\t\t\t\t\t\t\t  \"only one or all direction attributes\"\n+\t\t\t\t\t\t\t  \" at once can be used on transfer proxy\"\n+\t\t\t\t\t\t\t  \" port\");\n+\t\t} else {\n+\t\t\tif (attr->transfer)\n+\t\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, NULL,\n+\t\t\t\t\t\t\t  \"transfer attribute cannot be used with\"\n+\t\t\t\t\t\t\t  \" port representors\");\n+\t\t\tif (attr->ingress && attr->egress)\n+\t\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR, NULL,\n+\t\t\t\t\t\t\t  \"ingress and egress direction attributes\"\n+\t\t\t\t\t\t\t  \" cannot be used at the same time on\"\n+\t\t\t\t\t\t\t  \" port representors\");\n+\t\t}\n+\t} else {\n+\t\tif (attr->transfer)\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, NULL,\n+\t\t\t\t\t\t  \"transfer attribute cannot be used when\"\n+\t\t\t\t\t\t  \" E-Switch is disabled\");\n+\t}\n \tfor (i = 0; !items_end; i++) {\n \t\tint type = items[i].type;\n \n@@ -3069,7 +3392,6 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,\n \t\t{\n \t\t\tconst struct rte_flow_item_tag *tag =\n \t\t\t\t(const struct rte_flow_item_tag *)items[i].spec;\n-\t\t\tstruct mlx5_priv *priv = dev->data->dev_private;\n \t\t\tuint8_t regcs = (uint8_t)priv->sh->cdev->config.hca_attr.set_reg_c;\n \n \t\t\tif (!((1 << (tag->index - REG_C_0)) & regcs))\n@@ -3077,7 +3399,26 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,\n \t\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n \t\t\t\t\t\t\t  NULL,\n \t\t\t\t\t\t\t  \"Unsupported internal tag index\");\n+\t\t\tbreak;\n \t\t}\n+\t\tcase RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:\n+\t\t\tif (attr->ingress || attr->egress)\n+\t\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, NULL,\n+\t\t\t\t\t\t  \"represented port item cannot be used\"\n+\t\t\t\t\t\t  \" when transfer attribute is set\");\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ITEM_TYPE_META:\n+\t\t\tif (!priv->sh->config.dv_esw_en ||\n+\t\t\t    priv->sh->config.dv_xmeta_en != MLX5_XMETA_MODE_META32_HWS) {\n+\t\t\t\tif (attr->ingress)\n+\t\t\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, NULL,\n+\t\t\t\t\t\t\t\t  \"META item is not supported\"\n+\t\t\t\t\t\t\t\t  \" on current FW with ingress\"\n+\t\t\t\t\t\t\t\t  \" attribute\");\n+\t\t\t}\n+\t\t\tbreak;\n \t\tcase RTE_FLOW_ITEM_TYPE_VOID:\n \t\tcase RTE_FLOW_ITEM_TYPE_ETH:\n \t\tcase RTE_FLOW_ITEM_TYPE_VLAN:\n@@ -3087,10 +3428,8 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,\n \t\tcase RTE_FLOW_ITEM_TYPE_TCP:\n \t\tcase RTE_FLOW_ITEM_TYPE_GTP:\n \t\tcase RTE_FLOW_ITEM_TYPE_GTP_PSC:\n-\t\tcase RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:\n \t\tcase RTE_FLOW_ITEM_TYPE_VXLAN:\n \t\tcase MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE:\n-\t\tcase RTE_FLOW_ITEM_TYPE_META:\n \t\tcase RTE_FLOW_ITEM_TYPE_GRE:\n \t\tcase RTE_FLOW_ITEM_TYPE_GRE_KEY:\n \t\tcase RTE_FLOW_ITEM_TYPE_GRE_OPTION:\n@@ -3138,21 +3477,7 @@ flow_hw_pattern_template_create(struct rte_eth_dev *dev,\n \n \tif (flow_hw_pattern_validate(dev, attr, items, error))\n \t\treturn NULL;\n-\tif (priv->sh->config.dv_esw_en && attr->ingress) {\n-\t\t/*\n-\t\t * Disallow pattern template with ingress and egress/transfer\n-\t\t * attributes in order to forbid implicit port matching\n-\t\t * on egress and transfer traffic.\n-\t\t */\n-\t\tif (attr->egress || attr->transfer) {\n-\t\t\trte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\t   NULL,\n-\t\t\t\t\t   \"item template for ingress traffic\"\n-\t\t\t\t\t   \" cannot be used for egress/transfer\"\n-\t\t\t\t\t   \" traffic when E-Switch is enabled\");\n-\t\t\treturn NULL;\n-\t\t}\n+\tif (priv->sh->config.dv_esw_en && attr->ingress && !attr->egress && !attr->transfer) {\n \t\tcopied_items = flow_hw_copy_prepend_port_item(items, error);\n \t\tif (!copied_items)\n \t\t\treturn NULL;\n@@ -4542,6 +4867,10 @@ flow_hw_resource_release(struct rte_eth_dev *dev)\n \t\treturn;\n \tflow_hw_rxq_flag_set(dev, false);\n \tflow_hw_flush_all_ctrl_flows(dev);\n+\twhile (!LIST_EMPTY(&priv->flow_hw_tbl_ongo)) {\n+\t\ttbl = LIST_FIRST(&priv->flow_hw_tbl_ongo);\n+\t\tflow_hw_table_destroy(dev, tbl, NULL);\n+\t}\n \twhile (!LIST_EMPTY(&priv->flow_hw_tbl)) {\n \t\ttbl = LIST_FIRST(&priv->flow_hw_tbl);\n \t\tflow_hw_table_destroy(dev, tbl, NULL);\n@@ -4679,6 +5008,54 @@ void flow_hw_clear_tags_set(struct rte_eth_dev *dev)\n \t\t       sizeof(enum modify_reg) * MLX5_FLOW_HW_TAGS_MAX);\n }\n \n+uint32_t mlx5_flow_hw_flow_metadata_config_refcnt;\n+uint8_t mlx5_flow_hw_flow_metadata_esw_en;\n+uint8_t mlx5_flow_hw_flow_metadata_xmeta_en;\n+\n+/**\n+ * Initializes static configuration of META flow items.\n+ *\n+ * As a temporary workaround, META flow item is translated to a register,\n+ * based on statically saved dv_esw_en and dv_xmeta_en device arguments.\n+ * It is a workaround for flow_hw_get_reg_id() where port specific information\n+ * is not available at runtime.\n+ *\n+ * Values of dv_esw_en and dv_xmeta_en device arguments are taken from the first opened port.\n+ * This means that each mlx5 port will use the same configuration for translation\n+ * of META flow items.\n+ *\n+ * @param[in] dev\n+ *    Pointer to Ethernet device.\n+ */\n+void\n+flow_hw_init_flow_metadata_config(struct rte_eth_dev *dev)\n+{\n+\tuint32_t refcnt;\n+\n+\trefcnt = __atomic_fetch_add(&mlx5_flow_hw_flow_metadata_config_refcnt, 1,\n+\t\t\t\t    __ATOMIC_RELAXED);\n+\tif (refcnt > 0)\n+\t\treturn;\n+\tmlx5_flow_hw_flow_metadata_esw_en = MLX5_SH(dev)->config.dv_esw_en;\n+\tmlx5_flow_hw_flow_metadata_xmeta_en = MLX5_SH(dev)->config.dv_xmeta_en;\n+}\n+\n+/**\n+ * Clears statically stored configuration related to META flow items.\n+ */\n+void\n+flow_hw_clear_flow_metadata_config(void)\n+{\n+\tuint32_t refcnt;\n+\n+\trefcnt = __atomic_sub_fetch(&mlx5_flow_hw_flow_metadata_config_refcnt, 1,\n+\t\t\t\t    __ATOMIC_RELAXED);\n+\tif (refcnt > 0)\n+\t\treturn;\n+\tmlx5_flow_hw_flow_metadata_esw_en = 0;\n+\tmlx5_flow_hw_flow_metadata_xmeta_en = 0;\n+}\n+\n /**\n  * Create shared action.\n  *\ndiff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c\nindex ccefebefc9..2603196933 100644\n--- a/drivers/net/mlx5/mlx5_trigger.c\n+++ b/drivers/net/mlx5/mlx5_trigger.c\n@@ -1170,6 +1170,16 @@ mlx5_dev_start(struct rte_eth_dev *dev)\n \t\t\tdev->data->port_id, rte_strerror(rte_errno));\n \t\tgoto error;\n \t}\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\tif (priv->sh->config.dv_flow_en == 2) {\n+\t\tret = flow_hw_table_update(dev, NULL);\n+\t\tif (ret) {\n+\t\t\tDRV_LOG(ERR, \"port %u failed to update HWS tables\",\n+\t\t\t\tdev->data->port_id);\n+\t\t\tgoto error;\n+\t\t}\n+\t}\n+#endif\n \tret = mlx5_traffic_enable(dev);\n \tif (ret) {\n \t\tDRV_LOG(ERR, \"port %u failed to set defaults flows\",\n",
    "prefixes": [
        "v3",
        "09/17"
    ]
}