get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 117227,
    "url": "http://patches.dpdk.org/api/patches/117227/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20220930125315.5079-18-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-18-suanmingm@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220930125315.5079-18-suanmingm@nvidia.com",
    "date": "2022-09-30T12:53:15",
    "name": "[v3,17/17] net/mlx5: support device control of representor matching",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "fd953c0bf83a767e8fa1f6179abbc1a5d8d3d521",
    "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-18-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/117227/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/117227/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 5C838A00C4;\n\tFri, 30 Sep 2022 14:56:11 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id AF2A242BD3;\n\tFri, 30 Sep 2022 14:54:29 +0200 (CEST)",
            "from NAM11-BN8-obe.outbound.protection.outlook.com\n (mail-bn8nam11on2040.outbound.protection.outlook.com [40.107.236.40])\n by mails.dpdk.org (Postfix) with ESMTP id D6FF442BC9\n for <dev@dpdk.org>; Fri, 30 Sep 2022 14:54:25 +0200 (CEST)",
            "from DM6PR07CA0043.namprd07.prod.outlook.com (2603:10b6:5:74::20) by\n CY5PR12MB6347.namprd12.prod.outlook.com (2603:10b6:930:20::10) with\n Microsoft\n SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.20.5676.20; Fri, 30 Sep 2022 12:54:23 +0000",
            "from DM6NAM11FT081.eop-nam11.prod.protection.outlook.com\n (2603:10b6:5:74:cafe::c4) by DM6PR07CA0043.outlook.office365.com\n (2603:10b6:5:74::20) 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:54:23 +0000",
            "from mail.nvidia.com (216.228.117.160) by\n DM6NAM11FT081.mail.protection.outlook.com (10.13.172.136) 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:54:23 +0000",
            "from rnnvmail201.nvidia.com (10.129.68.8) by mail.nvidia.com\n (10.129.200.66) 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:54:14 -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:54:11 -0700"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=HGHIASqoyN67eIWpLBUSctfevzpklOEE1XqpeyiBfPnKJ7LIg0lOVPtfWpKCtTX7qJXo8uo8XZkspkKskeGAvjTvT1bVYSKLXFcF28z0sUR6uHWPI2ZWLqD/3zq5uiiBkwZVYPDnO33KCUVQlXRoKSVzTinIjFbYlfbC1mEvdmKkF0CZtfhMzJ5vUwp5Y7PMZkNBEwSjiRVhvwJj2c/ftx2Sch4zftxlYzIqyDuoBTIq5yfNfAvO+i2gj+/LpKiv6P4ITNOT3UVBUz5ktG1+bVDKGIqJVFRLo9xkGML6I+bAz3IwYIOVny1MSUub4lTAQXc11feYq96peidWVo8Qbg==",
        "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=8iylnYThu5ufnhL5oYP4orRGo3Zxmai7KDRxPqmrQIE=;\n b=mML8gSER47pfEOOeu2g1+c3J+JOU+RqC+T10TAJcxvwv0dgJOs3TZqB4j8hhOWXLs9h4hn3tyV2xyQS8DKEIjn3lLOkhtol3c8hZoOia4sJYMRUMs1P5Xh8xHs//ZehpVWTUVuwgd2bAOaY4PQRWtn9TpT2B1DEmN7FIByJ0l5sjJp272IRCuBcRV/X2p3C7bc4eXH+jyLBTIV/1Jq5vjYpVBy6OgNKs6QyKYV20zSkbca+fZ+aqsrCujhkC+XODoWnJtkIOPmTVZZIa2ExtCSy3jshbmJhy0lD00tXhut6WvsXAt7yaPB3/yBt+EUqFlX4XMsIvHhQHmJoyIu1kOg==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass (sender ip is\n 216.228.117.160) 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=8iylnYThu5ufnhL5oYP4orRGo3Zxmai7KDRxPqmrQIE=;\n b=qD8U/3c9GiaTcBhOaGkktjzKRthRxFqRHrR+H6L+rNz29mK11m7sKmsGTJwjL9RmlRBscwLZEga95Y6lsgXLUTl6CLJYA+CiL2LpGbPutr7/svuII/ElHObxX4rI0m0EJh8wPbf2+kLJJHFa1cU/WkBhOoavWFhHHG4XtsBzhp0h3s4S0rfrCQVGsTKaWIwHmsl4NIoaepIDQBQmbjTJG+UTvhty42twM9LueDpixf88GE406MrhoFrpcXKOLoX2S+OfoJnnJ+eRsEZY23TgDYKRS8aNbFov8dzODkAtOURL+p5349GGjmy/tXBHbXfSUtKdcYseY7MStETrEV0SZQ==",
        "X-MS-Exchange-Authentication-Results": "spf=pass (sender IP is 216.228.117.160)\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.160 as permitted sender) receiver=protection.outlook.com;\n client-ip=216.228.117.160; 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 17/17] net/mlx5: support device control of representor\n matching",
        "Date": "Fri, 30 Sep 2022 15:53:15 +0300",
        "Message-ID": "<20220930125315.5079-18-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": "DM6NAM11FT081:EE_|CY5PR12MB6347:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "726aaff4-c497-4b04-4d47-08daa2e2e605",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n 80um1MHEI21knOpdRZqZaKkILDLB2hbpt6mCPiBVc2rkFBkS3zKnEnQ8Jt1HoWP+2Urxl8jqr3RDrr4RkSdsGLNDqYS0rPY2UuQItBosk92xzYFVUTqv42surM4Jnqa2fKOVd+yVXDXbelkdDpidmNSb0yVeZ0XTNa6dmkQ98PfYVRaYLhO468ADQAySoqLPDjlLRYKAMmccpOTCQ+2K0mxgr/3MgqB9vbzlXF1y864MwuUaixqVH81noiy05MCbxkaiqjaG5jsXIdxLRmCyh1oWyv/pPT3EGBuk1LU6U9PalBtJruCo1v2JR1ifejAzmgT8fuVg9qYgdSWm9LWV0arDmQZN28ugKFtqLnaoiBakpDnzo/Y2oKzcP9+171Id5BYZ6wAOmNak3dH08R80ouLjh8h3NNIaPeUY3xcwet3v5d34RHsR2xyXErL+V6v45gyTiErU8N3M7h4xpN17C3uIltBwNE9w0kZPPHUOQMZDsRtLNh8ikaX2azca1dwme2J7SSGxhguhba7sZ1jKQPdFUC6YpkANB7eP4qtvvIjqbuqiu63WcvQmTpPQf+/s8GfNXUCNK4X7LROaSB+l6bYjB5qdGlZN4/XPkST+6WoW6GS4ztjINxGoPcsW/NRsT1ZeiW1XTl1S9IgifmJNGHMUCgiDprU2lwOvxlMdAT30S/IuujCBGcZGzLrmYge8qL6WR337ZMZTC/p8rXMuDrPaTSkGpmwqgATd7lsL4hhv9RLtlz2DXhcSAUhQZev8JHsulCS5PDUzKoEHBMBVGymeB8+fk4qk8ZBomhFBM7I=",
        "X-Forefront-Antispam-Report": "CIP:216.228.117.160; CTRY:US; LANG:en; SCL:1;\n SRV:;\n IPV:NLI; SFV:NSPM; H:mail.nvidia.com; PTR:dc6edge1.nvidia.com; CAT:NONE;\n SFS:(13230022)(4636009)(346002)(376002)(396003)(39860400002)(136003)(451199015)(46966006)(36840700001)(40470700004)(55016003)(110136005)(54906003)(316002)(6636002)(86362001)(40460700003)(40480700001)(478600001)(70586007)(70206006)(4326008)(8676002)(5660300002)(8936002)(356005)(30864003)(82740400003)(41300700001)(82310400005)(36860700001)(107886003)(2906002)(2616005)(336012)(7636003)(186003)(1076003)(426003)(36756003)(16526019)(83380400001)(26005)(47076005)(6286002)(7696005)(579004)(559001)(309714004);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "Nvidia.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "30 Sep 2022 12:54:23.0199 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 726aaff4-c497-4b04-4d47-08daa2e2e605",
        "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.160];\n Helo=[mail.nvidia.com]",
        "X-MS-Exchange-CrossTenant-AuthSource": "\n DM6NAM11FT081.eop-nam11.prod.protection.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "CY5PR12MB6347",
        "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\nIn some E-Switch use cases applications want to receive all traffic\non a single port. Since currently flow API does not provide a way to\nmatch traffic forwarded to any port representor, this patch adds\nsupport for controlling representor matching on ingress flow rules.\n\nRepresentor matching is controlled through new device argument\nrepr_matching_en.\n\n- If representor matching is enabled (default setting),\n  then each ingress pattern template has an implicit REPRESENTED_PORT\n  item added. Flow rules based on this pattern template will match\n  the vport associated with port on which rule is created.\n- If representor matching is disabled, then there will be no implicit\n  item added. As a result ingress flow rules will match traffic\n  coming to any port, not only the port on which flow rule is created.\n\nRepresentor matching is enabled by default, to provide an expected\ndefault behavior.\n\nThis patch enables egress flow rules on representors when E-Switch is\nenabled in the following configurations:\n\n- repr_matching_en=1 and dv_xmeta_en=4\n- repr_matching_en=1 and dv_xmeta_en=0\n- repr_matching_en=0 and dv_xmeta_en=0\n\nWhen representor matching is enabled, the following logic is\nimplemented:\n\n1. Creating an egress template table in group 0 for each port. These\n   tables will hold default flow rules defined as follows:\n\n      pattern SQ\n      actions MODIFY_FIELD (set available bits in REG_C_0 to\n                            vport_meta_tag)\n              MODIFY_FIELD (copy REG_A to REG_C_1, only when\n                            dv_xmeta_en == 4)\n              JUMP (group 1)\n\n2. Egress pattern templates created by an application have an implicit\n   MLX5_RTE_FLOW_ITEM_TYPE_TAG item prepended to pattern, which matches\n   available bits of REG_C_0.\n\n3. Egress flow rules created by an application have an implicit\n   MLX5_RTE_FLOW_ITEM_TYPE_TAG item prepended to pattern, which matches\n   vport_meta_tag placed in available bits of REG_C_0.\n\n4. Egress template tables created by an application, which are in\n   group n, are placed in group n + 1.\n\n5. Items and actions related to META are operating on REG_A when\n   dv_xmeta_en == 0 or REG_C_1 when dv_xmeta_en == 4.\n\nWhen representor matching is disabled and extended metadata is disabled,\nno changes to current logic are required.\n\nSigned-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>\n---\n drivers/net/mlx5/linux/mlx5_os.c |  11 +\n drivers/net/mlx5/mlx5.c          |  13 +\n drivers/net/mlx5/mlx5.h          |   5 +\n drivers/net/mlx5/mlx5_flow.c     |   8 +-\n drivers/net/mlx5/mlx5_flow.h     |   7 +\n drivers/net/mlx5/mlx5_flow_hw.c  | 738 ++++++++++++++++++++++++-------\n drivers/net/mlx5/mlx5_trigger.c  | 167 ++++++-\n 7 files changed, 783 insertions(+), 166 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c\nindex de8c003d02..50d34b152a 100644\n--- a/drivers/net/mlx5/linux/mlx5_os.c\n+++ b/drivers/net/mlx5/linux/mlx5_os.c\n@@ -1555,6 +1555,9 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n \tif (priv->sh->config.dv_flow_en == 2) {\n #ifdef HAVE_IBV_FLOW_DV_SUPPORT\n \t\tif (priv->sh->config.dv_esw_en) {\n+\t\t\tuint32_t usable_bits;\n+\t\t\tuint32_t required_bits;\n+\n \t\t\tif (priv->sh->dv_regc0_mask == UINT32_MAX) {\n \t\t\t\tDRV_LOG(ERR, \"E-Switch port metadata is required when using HWS \"\n \t\t\t\t\t     \"but it is disabled (configure it through devlink)\");\n@@ -1567,6 +1570,14 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n \t\t\t\terr = ENOTSUP;\n \t\t\t\tgoto error;\n \t\t\t}\n+\t\t\tusable_bits = __builtin_popcount(priv->sh->dv_regc0_mask);\n+\t\t\trequired_bits = __builtin_popcount(priv->vport_meta_mask);\n+\t\t\tif (usable_bits < required_bits) {\n+\t\t\t\tDRV_LOG(ERR, \"Not enough bits available in reg_c[0] to provide \"\n+\t\t\t\t\t     \"representor matching.\");\n+\t\t\t\terr = ENOTSUP;\n+\t\t\t\tgoto error;\n+\t\t\t}\n \t\t}\n \t\tif (priv->vport_meta_mask)\n \t\t\tflow_hw_set_port_info(eth_dev);\ndiff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex 742607509b..c249619a60 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -181,6 +181,9 @@\n /* HW steering counter's query interval. */\n #define MLX5_HWS_CNT_CYCLE_TIME \"svc_cycle_time\"\n \n+/* Device parameter to control representor matching in ingress/egress flows with HWS. */\n+#define MLX5_REPR_MATCHING_EN \"repr_matching_en\"\n+\n /* Shared memory between primary and secondary processes. */\n struct mlx5_shared_data *mlx5_shared_data;\n \n@@ -1283,6 +1286,8 @@ mlx5_dev_args_check_handler(const char *key, const char *val, void *opaque)\n \t\tconfig->cnt_svc.service_core = tmp;\n \t} else if (strcmp(MLX5_HWS_CNT_CYCLE_TIME, key) == 0) {\n \t\tconfig->cnt_svc.cycle_time = tmp;\n+\t} else if (strcmp(MLX5_REPR_MATCHING_EN, key) == 0) {\n+\t\tconfig->repr_matching = !!tmp;\n \t}\n \treturn 0;\n }\n@@ -1321,6 +1326,7 @@ mlx5_shared_dev_ctx_args_config(struct mlx5_dev_ctx_shared *sh,\n \t\tMLX5_FDB_DEFAULT_RULE_EN,\n \t\tMLX5_HWS_CNT_SERVICE_CORE,\n \t\tMLX5_HWS_CNT_CYCLE_TIME,\n+\t\tMLX5_REPR_MATCHING_EN,\n \t\tNULL,\n \t};\n \tint ret = 0;\n@@ -1335,6 +1341,7 @@ mlx5_shared_dev_ctx_args_config(struct mlx5_dev_ctx_shared *sh,\n \tconfig->fdb_def_rule = 1;\n \tconfig->cnt_svc.cycle_time = MLX5_CNT_SVC_CYCLE_TIME_DEFAULT;\n \tconfig->cnt_svc.service_core = rte_get_main_lcore();\n+\tconfig->repr_matching = 1;\n \tif (mkvlist != NULL) {\n \t\t/* Process parameters. */\n \t\tret = mlx5_kvargs_process(mkvlist, params,\n@@ -1368,6 +1375,11 @@ mlx5_shared_dev_ctx_args_config(struct mlx5_dev_ctx_shared *sh,\n \t\t\tconfig->dv_xmeta_en);\n \t\tconfig->dv_xmeta_en = MLX5_XMETA_MODE_LEGACY;\n \t}\n+\tif (config->dv_flow_en != 2 && !config->repr_matching) {\n+\t\tDRV_LOG(DEBUG, \"Disabling representor matching is valid only \"\n+\t\t\t       \"when HW Steering is enabled.\");\n+\t\tconfig->repr_matching = 1;\n+\t}\n \tif (config->tx_pp && !sh->dev_cap.txpp_en) {\n \t\tDRV_LOG(ERR, \"Packet pacing is not supported.\");\n \t\trte_errno = ENODEV;\n@@ -1411,6 +1423,7 @@ mlx5_shared_dev_ctx_args_config(struct mlx5_dev_ctx_shared *sh,\n \tDRV_LOG(DEBUG, \"\\\"allow_duplicate_pattern\\\" is %u.\",\n \t\tconfig->allow_duplicate_pattern);\n \tDRV_LOG(DEBUG, \"\\\"fdb_def_rule_en\\\" is %u.\", config->fdb_def_rule);\n+\tDRV_LOG(DEBUG, \"\\\"repr_matching_en\\\" is %u.\", config->repr_matching);\n \treturn 0;\n }\n \ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 419b5a18ca..a0fb6d04d8 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -316,6 +316,7 @@ struct mlx5_sh_config {\n \t} cnt_svc; /* configure for HW steering's counter's service. */\n \t/* Allow/Prevent the duplicate rules pattern. */\n \tuint32_t fdb_def_rule:1; /* Create FDB default jump rule */\n+\tuint32_t repr_matching:1; /* Enable implicit vport matching in HWS FDB. */\n };\n \n /* Structure for VF VLAN workaround. */\n@@ -366,6 +367,7 @@ struct mlx5_hw_q_job {\n \t\t\tvoid *out_data;\n \t\t} __rte_packed;\n \t\tstruct rte_flow_item_ethdev port_spec;\n+\t\tstruct rte_flow_item_tag tag_spec;\n \t} __rte_packed;\n };\n \n@@ -1673,6 +1675,9 @@ struct mlx5_priv {\n \tstruct rte_flow_template_table *hw_esw_sq_miss_tbl;\n \tstruct rte_flow_template_table *hw_esw_zero_tbl;\n \tstruct rte_flow_template_table *hw_tx_meta_cpy_tbl;\n+\tstruct rte_flow_pattern_template *hw_tx_repr_tagging_pt;\n+\tstruct rte_flow_actions_template *hw_tx_repr_tagging_at;\n+\tstruct rte_flow_template_table *hw_tx_repr_tagging_tbl;\n \tstruct mlx5_indexed_pool *flows[MLX5_FLOW_TYPE_MAXI];\n \t/* RTE Flow rules. */\n \tuint32_t ctrl_flows; /* Control flow rules. */\ndiff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex 2142cd828a..026d4eb9c0 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -1123,7 +1123,11 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev,\n \t\t}\n \t\tbreak;\n \tcase MLX5_METADATA_TX:\n-\t\treturn REG_A;\n+\t\tif (config->dv_flow_en == 2 && config->dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS) {\n+\t\t\treturn REG_C_1;\n+\t\t} else {\n+\t\t\treturn REG_A;\n+\t\t}\n \tcase MLX5_METADATA_FDB:\n \t\tswitch (config->dv_xmeta_en) {\n \t\tcase MLX5_XMETA_MODE_LEGACY:\n@@ -11319,7 +11323,7 @@ mlx5_flow_pick_transfer_proxy(struct rte_eth_dev *dev,\n \t\t\treturn 0;\n \t\t}\n \t}\n-\treturn rte_flow_error_set(error, EINVAL,\n+\treturn rte_flow_error_set(error, ENODEV,\n \t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n \t\t\t\t  NULL, \"unable to find a proxy port\");\n }\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex 63f946473d..a497dac474 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -1199,12 +1199,18 @@ struct rte_flow_pattern_template {\n \tstruct rte_flow_pattern_template_attr attr;\n \tstruct mlx5dr_match_template *mt; /* mlx5 match template. */\n \tuint64_t item_flags; /* Item layer flags. */\n+\tuint64_t orig_item_nb; /* Number of pattern items provided by the user (with END item). */\n \tuint32_t refcnt;  /* Reference counter. */\n \t/*\n \t * If true, then rule pattern should be prepended with\n \t * represented_port pattern item.\n \t */\n \tbool implicit_port;\n+\t/*\n+\t * If true, then rule pattern should be prepended with\n+\t * tag pattern item for representor matching.\n+\t */\n+\tbool implicit_tag;\n };\n \n /* Flow action template struct. */\n@@ -2479,6 +2485,7 @@ int mlx5_flow_hw_esw_create_sq_miss_flow(struct rte_eth_dev *dev,\n \t\t\t\t\t uint32_t sqn);\n int mlx5_flow_hw_esw_create_default_jump_flow(struct rte_eth_dev *dev);\n int mlx5_flow_hw_create_tx_default_mreg_copy_flow(struct rte_eth_dev *dev);\n+int mlx5_flow_hw_tx_repr_matching_flow(struct rte_eth_dev *dev, uint32_t sqn);\n int mlx5_flow_actions_validate(struct rte_eth_dev *dev,\n \t\tconst struct rte_flow_actions_template_attr *attr,\n \t\tconst struct rte_flow_action actions[],\ndiff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c\nindex b2824ad8fe..461d344700 100644\n--- a/drivers/net/mlx5/mlx5_flow_hw.c\n+++ b/drivers/net/mlx5/mlx5_flow_hw.c\n@@ -32,12 +32,15 @@\n /* Maximum number of rules in control flow tables. */\n #define MLX5_HW_CTRL_FLOW_NB_RULES (4096)\n \n-/* Lowest flow group usable by an application. */\n+/* Lowest flow group usable by an application if group translation is done. */\n #define MLX5_HW_LOWEST_USABLE_GROUP (1)\n \n /* Maximum group index usable by user applications for transfer flows. */\n #define MLX5_HW_MAX_TRANSFER_GROUP (UINT32_MAX - 1)\n \n+/* Maximum group index usable by user applications for egress flows. */\n+#define MLX5_HW_MAX_EGRESS_GROUP (UINT32_MAX - 1)\n+\n /* Lowest priority for HW root table. */\n #define MLX5_HW_LOWEST_PRIO_ROOT 15\n \n@@ -61,6 +64,9 @@ flow_hw_set_vlan_vid_construct(struct rte_eth_dev *dev,\n \t\t\t       const struct mlx5_hw_actions *hw_acts,\n \t\t\t       const struct rte_flow_action *action);\n \n+static __rte_always_inline uint32_t flow_hw_tx_tag_regc_mask(struct rte_eth_dev *dev);\n+static __rte_always_inline uint32_t flow_hw_tx_tag_regc_value(struct rte_eth_dev *dev);\n+\n const struct mlx5_flow_driver_ops mlx5_flow_hw_drv_ops;\n \n /* DR action flags with different table. */\n@@ -2346,21 +2352,18 @@ flow_hw_get_rule_items(struct rte_eth_dev *dev,\n \t\t       uint8_t pattern_template_index,\n \t\t       struct mlx5_hw_q_job *job)\n {\n-\tif (table->its[pattern_template_index]->implicit_port) {\n-\t\tconst struct rte_flow_item *curr_item;\n-\t\tunsigned int nb_items;\n-\t\tbool found_end;\n-\t\tunsigned int i;\n-\n-\t\t/* Count number of pattern items. */\n-\t\tnb_items = 0;\n-\t\tfound_end = false;\n-\t\tfor (curr_item = items; !found_end; ++curr_item) {\n-\t\t\t++nb_items;\n-\t\t\tif (curr_item->type == RTE_FLOW_ITEM_TYPE_END)\n-\t\t\t\tfound_end = true;\n+\tstruct rte_flow_pattern_template *pt = table->its[pattern_template_index];\n+\n+\t/* Only one implicit item can be added to flow rule pattern. */\n+\tMLX5_ASSERT(!pt->implicit_port || !pt->implicit_tag);\n+\t/* At least one item was allocated in job descriptor for items. */\n+\tMLX5_ASSERT(MLX5_HW_MAX_ITEMS >= 1);\n+\tif (pt->implicit_port) {\n+\t\tif (pt->orig_item_nb + 1 > MLX5_HW_MAX_ITEMS) {\n+\t\t\trte_errno = ENOMEM;\n+\t\t\treturn NULL;\n \t\t}\n-\t\t/* Prepend represented port item. */\n+\t\t/* Set up represented port item in job descriptor. */\n \t\tjob->port_spec = (struct rte_flow_item_ethdev){\n \t\t\t.port_id = dev->data->port_id,\n \t\t};\n@@ -2368,21 +2371,26 @@ flow_hw_get_rule_items(struct rte_eth_dev *dev,\n \t\t\t.type = RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT,\n \t\t\t.spec = &job->port_spec,\n \t\t};\n-\t\tfound_end = false;\n-\t\tfor (i = 1; i < MLX5_HW_MAX_ITEMS && i - 1 < nb_items; ++i) {\n-\t\t\tjob->items[i] = items[i - 1];\n-\t\t\tif (items[i - 1].type == RTE_FLOW_ITEM_TYPE_END) {\n-\t\t\t\tfound_end = true;\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t}\n-\t\tif (i >= MLX5_HW_MAX_ITEMS && !found_end) {\n+\t\trte_memcpy(&job->items[1], items, sizeof(*items) * pt->orig_item_nb);\n+\t\treturn job->items;\n+\t} else if (pt->implicit_tag) {\n+\t\tif (pt->orig_item_nb + 1 > MLX5_HW_MAX_ITEMS) {\n \t\t\trte_errno = ENOMEM;\n \t\t\treturn NULL;\n \t\t}\n+\t\t/* Set up tag item in job descriptor. */\n+\t\tjob->tag_spec = (struct rte_flow_item_tag){\n+\t\t\t.data = flow_hw_tx_tag_regc_value(dev),\n+\t\t};\n+\t\tjob->items[0] = (struct rte_flow_item){\n+\t\t\t.type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_TAG,\n+\t\t\t.spec = &job->tag_spec,\n+\t\t};\n+\t\trte_memcpy(&job->items[1], items, sizeof(*items) * pt->orig_item_nb);\n \t\treturn job->items;\n+\t} else {\n+\t\treturn items;\n \t}\n-\treturn items;\n }\n \n /**\n@@ -2960,6 +2968,11 @@ flow_hw_table_create(struct rte_eth_dev *dev,\n \t\t     uint8_t nb_action_templates,\n \t\t     struct rte_flow_error *error)\n {\n+\tstruct rte_flow_error sub_error = {\n+\t\t.type = RTE_FLOW_ERROR_TYPE_NONE,\n+\t\t.cause = NULL,\n+\t\t.message = NULL,\n+\t};\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5dr_matcher_attr matcher_attr = {0};\n \tstruct rte_flow_template_table *tbl = NULL;\n@@ -2970,7 +2983,7 @@ flow_hw_table_create(struct rte_eth_dev *dev,\n \tstruct rte_flow_attr flow_attr = attr->flow_attr;\n \tstruct mlx5_flow_cb_ctx ctx = {\n \t\t.dev = dev,\n-\t\t.error = error,\n+\t\t.error = &sub_error,\n \t\t.data = &flow_attr,\n \t};\n \tstruct mlx5_indexed_pool_config cfg = {\n@@ -3064,7 +3077,7 @@ flow_hw_table_create(struct rte_eth_dev *dev,\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\t\t\t\t\t  action_templates[i], &sub_error);\n \t\tif (err) {\n \t\t\ti++;\n \t\t\tgoto at_error;\n@@ -3105,12 +3118,11 @@ flow_hw_table_create(struct rte_eth_dev *dev,\n \t\tmlx5_free(tbl);\n \t}\n \tif (error != NULL) {\n-\t\trte_flow_error_set(error, err,\n-\t\t\t\terror->type == RTE_FLOW_ERROR_TYPE_NONE ?\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED : error->type,\n-\t\t\t\tNULL,\n-\t\t\t\terror->message == NULL ?\n-\t\t\t\t\"fail to create rte table\" : error->message);\n+\t\tif (sub_error.type == RTE_FLOW_ERROR_TYPE_NONE)\n+\t\t\trte_flow_error_set(error, err, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\t   \"Failed to create template table\");\n+\t\telse\n+\t\t\trte_memcpy(error, &sub_error, sizeof(sub_error));\n \t}\n \treturn NULL;\n }\n@@ -3171,9 +3183,10 @@ flow_hw_translate_group(struct rte_eth_dev *dev,\n \t\t\tstruct rte_flow_error *error)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_sh_config *config = &priv->sh->config;\n \tconst struct rte_flow_attr *flow_attr = &cfg->attr.flow_attr;\n \n-\tif (priv->sh->config.dv_esw_en &&\n+\tif (config->dv_esw_en &&\n \t    priv->fdb_def_rule &&\n \t    cfg->external &&\n \t    flow_attr->transfer) {\n@@ -3183,6 +3196,22 @@ flow_hw_translate_group(struct rte_eth_dev *dev,\n \t\t\t\t\t\t  NULL,\n \t\t\t\t\t\t  \"group index not supported\");\n \t\t*table_group = group + 1;\n+\t} else if (config->dv_esw_en &&\n+\t\t   !(config->repr_matching && config->dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS) &&\n+\t\t   cfg->external &&\n+\t\t   flow_attr->egress) {\n+\t\t/*\n+\t\t * On E-Switch setups, egress group translation is not done if and only if\n+\t\t * representor matching is disabled and legacy metadata mode is selected.\n+\t\t * In all other cases, egree group 0 is reserved for representor tagging flows\n+\t\t * and metadata copy flows.\n+\t\t */\n+\t\tif (group > MLX5_HW_MAX_EGRESS_GROUP)\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_GROUP,\n+\t\t\t\t\t\t  NULL,\n+\t\t\t\t\t\t  \"group index not supported\");\n+\t\t*table_group = group + 1;\n \t} else {\n \t\t*table_group = group;\n \t}\n@@ -3223,7 +3252,6 @@ 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@@ -3232,12 +3260,6 @@ 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@@ -4494,26 +4516,28 @@ flow_hw_actions_template_destroy(struct rte_eth_dev *dev __rte_unused,\n \treturn 0;\n }\n \n-static struct rte_flow_item *\n-flow_hw_copy_prepend_port_item(const struct rte_flow_item *items,\n-\t\t\t       struct rte_flow_error *error)\n+static uint32_t\n+flow_hw_count_items(const struct rte_flow_item *items)\n {\n \tconst struct rte_flow_item *curr_item;\n-\tstruct rte_flow_item *copied_items;\n-\tbool found_end;\n-\tunsigned int nb_items;\n-\tunsigned int i;\n-\tsize_t size;\n+\tuint32_t nb_items;\n \n-\t/* Count number of pattern items. */\n \tnb_items = 0;\n-\tfound_end = false;\n-\tfor (curr_item = items; !found_end; ++curr_item) {\n+\tfor (curr_item = items; curr_item->type != RTE_FLOW_ITEM_TYPE_END; ++curr_item)\n \t\t++nb_items;\n-\t\tif (curr_item->type == RTE_FLOW_ITEM_TYPE_END)\n-\t\t\tfound_end = true;\n-\t}\n-\t/* Allocate new array of items and prepend REPRESENTED_PORT item. */\n+\treturn ++nb_items;\n+}\n+\n+static struct rte_flow_item *\n+flow_hw_prepend_item(const struct rte_flow_item *items,\n+\t\t     const uint32_t nb_items,\n+\t\t     const struct rte_flow_item *new_item,\n+\t\t     struct rte_flow_error *error)\n+{\n+\tstruct rte_flow_item *copied_items;\n+\tsize_t size;\n+\n+\t/* Allocate new array of items. */\n \tsize = sizeof(*copied_items) * (nb_items + 1);\n \tcopied_items = mlx5_malloc(MLX5_MEM_ZERO, size, 0, rte_socket_id());\n \tif (!copied_items) {\n@@ -4523,14 +4547,9 @@ flow_hw_copy_prepend_port_item(const struct rte_flow_item *items,\n \t\t\t\t   \"cannot allocate item template\");\n \t\treturn NULL;\n \t}\n-\tcopied_items[0] = (struct rte_flow_item){\n-\t\t.type = RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT,\n-\t\t.spec = NULL,\n-\t\t.last = NULL,\n-\t\t.mask = &rte_flow_item_ethdev_mask,\n-\t};\n-\tfor (i = 1; i < nb_items + 1; ++i)\n-\t\tcopied_items[i] = items[i - 1];\n+\t/* Put new item at the beginning and copy the rest. */\n+\tcopied_items[0] = *new_item;\n+\trte_memcpy(&copied_items[1], items, sizeof(*items) * nb_items);\n \treturn copied_items;\n }\n \n@@ -4551,17 +4570,13 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,\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\tif ((attr->ingress && attr->egress) ||\n+\t\t\t    (attr->ingress && attr->transfer) ||\n+\t\t\t    (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\t\t\t\t\t  \"only one direction attribute at once\"\n+\t\t\t\t\t\t\t  \" can be used on transfer proxy port\");\n \t\t} else {\n \t\t\tif (attr->transfer)\n \t\t\t\treturn rte_flow_error_set(error, EINVAL,\n@@ -4614,11 +4629,16 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,\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\tif (attr->ingress && priv->sh->config.repr_matching)\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 ingress attribute is set\");\n+\t\t\tif (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\t\t\t\t  \" when egress 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@@ -4680,6 +4700,17 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,\n \treturn 0;\n }\n \n+static bool\n+flow_hw_pattern_has_sq_match(const struct rte_flow_item *items)\n+{\n+\tunsigned int i;\n+\n+\tfor (i = 0; items[i].type != RTE_FLOW_ITEM_TYPE_END; ++i)\n+\t\tif (items[i].type == (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_SQ)\n+\t\t\treturn true;\n+\treturn false;\n+}\n+\n /**\n  * Create flow item template.\n  *\n@@ -4705,17 +4736,53 @@ flow_hw_pattern_template_create(struct rte_eth_dev *dev,\n \tstruct rte_flow_pattern_template *it;\n \tstruct rte_flow_item *copied_items = NULL;\n \tconst struct rte_flow_item *tmpl_items;\n+\tuint64_t orig_item_nb;\n+\tstruct rte_flow_item port = {\n+\t\t.type = RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT,\n+\t\t.mask = &rte_flow_item_ethdev_mask,\n+\t};\n+\tstruct rte_flow_item_tag tag_v = {\n+\t\t.data = 0,\n+\t\t.index = REG_C_0,\n+\t};\n+\tstruct rte_flow_item_tag tag_m = {\n+\t\t.data = flow_hw_tx_tag_regc_mask(dev),\n+\t\t.index = 0xff,\n+\t};\n+\tstruct rte_flow_item tag = {\n+\t\t.type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_TAG,\n+\t\t.spec = &tag_v,\n+\t\t.mask = &tag_m,\n+\t\t.last = NULL\n+\t};\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 && !attr->egress && !attr->transfer) {\n-\t\tcopied_items = flow_hw_copy_prepend_port_item(items, error);\n+\torig_item_nb = flow_hw_count_items(items);\n+\tif (priv->sh->config.dv_esw_en &&\n+\t    priv->sh->config.repr_matching &&\n+\t    attr->ingress && !attr->egress && !attr->transfer) {\n+\t\tcopied_items = flow_hw_prepend_item(items, orig_item_nb, &port, error);\n+\t\tif (!copied_items)\n+\t\t\treturn NULL;\n+\t\ttmpl_items = copied_items;\n+\t} else if (priv->sh->config.dv_esw_en &&\n+\t\t   priv->sh->config.repr_matching &&\n+\t\t   !attr->ingress && attr->egress && !attr->transfer) {\n+\t\tif (flow_hw_pattern_has_sq_match(items)) {\n+\t\t\tDRV_LOG(DEBUG, \"Port %u omitting implicit REG_C_0 match for egress \"\n+\t\t\t\t       \"pattern template\", dev->data->port_id);\n+\t\t\ttmpl_items = items;\n+\t\t\tgoto setup_pattern_template;\n+\t\t}\n+\t\tcopied_items = flow_hw_prepend_item(items, orig_item_nb, &tag, error);\n \t\tif (!copied_items)\n \t\t\treturn NULL;\n \t\ttmpl_items = copied_items;\n \t} else {\n \t\ttmpl_items = items;\n \t}\n+setup_pattern_template:\n \tit = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*it), 0, rte_socket_id());\n \tif (!it) {\n \t\tif (copied_items)\n@@ -4727,6 +4794,7 @@ flow_hw_pattern_template_create(struct rte_eth_dev *dev,\n \t\treturn NULL;\n \t}\n \tit->attr = *attr;\n+\tit->orig_item_nb = orig_item_nb;\n \tit->mt = mlx5dr_match_template_create(tmpl_items, attr->relaxed_matching);\n \tif (!it->mt) {\n \t\tif (copied_items)\n@@ -4739,11 +4807,15 @@ flow_hw_pattern_template_create(struct rte_eth_dev *dev,\n \t\treturn NULL;\n \t}\n \tit->item_flags = flow_hw_rss_item_flags_get(tmpl_items);\n-\tit->implicit_port = !!copied_items;\n+\tif (copied_items) {\n+\t\tif (attr->ingress)\n+\t\t\tit->implicit_port = true;\n+\t\telse if (attr->egress)\n+\t\t\tit->implicit_tag = true;\n+\t\tmlx5_free(copied_items);\n+\t}\n \t__atomic_fetch_add(&it->refcnt, 1, __ATOMIC_RELAXED);\n \tLIST_INSERT_HEAD(&priv->flow_hw_itt, it, next);\n-\tif (copied_items)\n-\t\tmlx5_free(copied_items);\n \treturn it;\n }\n \n@@ -5143,6 +5215,254 @@ flow_hw_free_vport_actions(struct mlx5_priv *priv)\n \tpriv->hw_vport = NULL;\n }\n \n+/**\n+ * Create an egress pattern template matching on source SQ.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device.\n+ *\n+ * @return\n+ *   Pointer to pattern template on success. NULL otherwise, and rte_errno is set.\n+ */\n+static struct rte_flow_pattern_template *\n+flow_hw_create_tx_repr_sq_pattern_tmpl(struct rte_eth_dev *dev)\n+{\n+\tstruct rte_flow_pattern_template_attr attr = {\n+\t\t.relaxed_matching = 0,\n+\t\t.egress = 1,\n+\t};\n+\tstruct mlx5_rte_flow_item_sq sq_mask = {\n+\t\t.queue = UINT32_MAX,\n+\t};\n+\tstruct rte_flow_item items[] = {\n+\t\t{\n+\t\t\t.type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_SQ,\n+\t\t\t.mask = &sq_mask,\n+\t\t},\n+\t\t{\n+\t\t\t.type = RTE_FLOW_ITEM_TYPE_END,\n+\t\t},\n+\t};\n+\n+\treturn flow_hw_pattern_template_create(dev, &attr, items, NULL);\n+}\n+\n+static __rte_always_inline uint32_t\n+flow_hw_tx_tag_regc_mask(struct rte_eth_dev *dev)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tuint32_t mask = priv->sh->dv_regc0_mask;\n+\n+\t/* Mask is verified during device initialization. Sanity checking here. */\n+\tMLX5_ASSERT(mask != 0);\n+\t/*\n+\t * Availability of sufficient number of bits in REG_C_0 is verified on initialization.\n+\t * Sanity checking here.\n+\t */\n+\tMLX5_ASSERT(__builtin_popcount(mask) >= __builtin_popcount(priv->vport_meta_mask));\n+\treturn mask;\n+}\n+\n+static __rte_always_inline uint32_t\n+flow_hw_tx_tag_regc_value(struct rte_eth_dev *dev)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tuint32_t tag;\n+\n+\t/* Mask is verified during device initialization. Sanity checking here. */\n+\tMLX5_ASSERT(priv->vport_meta_mask != 0);\n+\ttag = priv->vport_meta_tag >> (rte_bsf32(priv->vport_meta_mask));\n+\t/*\n+\t * Availability of sufficient number of bits in REG_C_0 is verified on initialization.\n+\t * Sanity checking here.\n+\t */\n+\tMLX5_ASSERT((tag & priv->sh->dv_regc0_mask) == tag);\n+\treturn tag;\n+}\n+\n+static void\n+flow_hw_update_action_mask(struct rte_flow_action *action,\n+\t\t\t   struct rte_flow_action *mask,\n+\t\t\t   enum rte_flow_action_type type,\n+\t\t\t   void *conf_v,\n+\t\t\t   void *conf_m)\n+{\n+\taction->type = type;\n+\taction->conf = conf_v;\n+\tmask->type = type;\n+\tmask->conf = conf_m;\n+}\n+\n+/**\n+ * Create an egress actions template with MODIFY_FIELD action for setting unused REG_C_0 bits\n+ * to vport tag and JUMP action to group 1.\n+ *\n+ * If extended metadata mode is enabled, then MODIFY_FIELD action for copying software metadata\n+ * to REG_C_1 is added as well.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device.\n+ *\n+ * @return\n+ *   Pointer to actions template on success. NULL otherwise, and rte_errno is set.\n+ */\n+static struct rte_flow_actions_template *\n+flow_hw_create_tx_repr_tag_jump_acts_tmpl(struct rte_eth_dev *dev)\n+{\n+\tuint32_t tag_mask = flow_hw_tx_tag_regc_mask(dev);\n+\tuint32_t tag_value = flow_hw_tx_tag_regc_value(dev);\n+\tstruct rte_flow_actions_template_attr attr = {\n+\t\t.egress = 1,\n+\t};\n+\tstruct rte_flow_action_modify_field set_tag_v = {\n+\t\t.operation = RTE_FLOW_MODIFY_SET,\n+\t\t.dst = {\n+\t\t\t.field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,\n+\t\t\t.level = REG_C_0,\n+\t\t\t.offset = rte_bsf32(tag_mask),\n+\t\t},\n+\t\t.src = {\n+\t\t\t.field = RTE_FLOW_FIELD_VALUE,\n+\t\t},\n+\t\t.width = __builtin_popcount(tag_mask),\n+\t};\n+\tstruct rte_flow_action_modify_field set_tag_m = {\n+\t\t.operation = RTE_FLOW_MODIFY_SET,\n+\t\t.dst = {\n+\t\t\t.field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,\n+\t\t\t.level = UINT32_MAX,\n+\t\t\t.offset = UINT32_MAX,\n+\t\t},\n+\t\t.src = {\n+\t\t\t.field = RTE_FLOW_FIELD_VALUE,\n+\t\t},\n+\t\t.width = UINT32_MAX,\n+\t};\n+\tstruct rte_flow_action_modify_field copy_metadata_v = {\n+\t\t.operation = RTE_FLOW_MODIFY_SET,\n+\t\t.dst = {\n+\t\t\t.field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,\n+\t\t\t.level = REG_C_1,\n+\t\t},\n+\t\t.src = {\n+\t\t\t.field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,\n+\t\t\t.level = REG_A,\n+\t\t},\n+\t\t.width = 32,\n+\t};\n+\tstruct rte_flow_action_modify_field copy_metadata_m = {\n+\t\t.operation = RTE_FLOW_MODIFY_SET,\n+\t\t.dst = {\n+\t\t\t.field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,\n+\t\t\t.level = UINT32_MAX,\n+\t\t\t.offset = UINT32_MAX,\n+\t\t},\n+\t\t.src = {\n+\t\t\t.field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,\n+\t\t\t.level = UINT32_MAX,\n+\t\t\t.offset = UINT32_MAX,\n+\t\t},\n+\t\t.width = UINT32_MAX,\n+\t};\n+\tstruct rte_flow_action_jump jump_v = {\n+\t\t.group = MLX5_HW_LOWEST_USABLE_GROUP,\n+\t};\n+\tstruct rte_flow_action_jump jump_m = {\n+\t\t.group = UINT32_MAX,\n+\t};\n+\tstruct rte_flow_action actions_v[4] = { { 0 } };\n+\tstruct rte_flow_action actions_m[4] = { { 0 } };\n+\tunsigned int idx = 0;\n+\n+\trte_memcpy(set_tag_v.src.value, &tag_value, sizeof(tag_value));\n+\trte_memcpy(set_tag_m.src.value, &tag_mask, sizeof(tag_mask));\n+\tflow_hw_update_action_mask(&actions_v[idx], &actions_m[idx],\n+\t\t\t\t   RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,\n+\t\t\t\t   &set_tag_v, &set_tag_m);\n+\tidx++;\n+\tif (MLX5_SH(dev)->config.dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS) {\n+\t\tflow_hw_update_action_mask(&actions_v[idx], &actions_m[idx],\n+\t\t\t\t\t   RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,\n+\t\t\t\t\t   &copy_metadata_v, &copy_metadata_m);\n+\t\tidx++;\n+\t}\n+\tflow_hw_update_action_mask(&actions_v[idx], &actions_m[idx], RTE_FLOW_ACTION_TYPE_JUMP,\n+\t\t\t\t   &jump_v, &jump_m);\n+\tidx++;\n+\tflow_hw_update_action_mask(&actions_v[idx], &actions_m[idx], RTE_FLOW_ACTION_TYPE_END,\n+\t\t\t\t   NULL, NULL);\n+\tidx++;\n+\tMLX5_ASSERT(idx <= RTE_DIM(actions_v));\n+\treturn flow_hw_actions_template_create(dev, &attr, actions_v, actions_m, NULL);\n+}\n+\n+static void\n+flow_hw_cleanup_tx_repr_tagging(struct rte_eth_dev *dev)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\n+\tif (priv->hw_tx_repr_tagging_tbl) {\n+\t\tflow_hw_table_destroy(dev, priv->hw_tx_repr_tagging_tbl, NULL);\n+\t\tpriv->hw_tx_repr_tagging_tbl = NULL;\n+\t}\n+\tif (priv->hw_tx_repr_tagging_at) {\n+\t\tflow_hw_actions_template_destroy(dev, priv->hw_tx_repr_tagging_at, NULL);\n+\t\tpriv->hw_tx_repr_tagging_at = NULL;\n+\t}\n+\tif (priv->hw_tx_repr_tagging_pt) {\n+\t\tflow_hw_pattern_template_destroy(dev, priv->hw_tx_repr_tagging_pt, NULL);\n+\t\tpriv->hw_tx_repr_tagging_pt = NULL;\n+\t}\n+}\n+\n+/**\n+ * Setup templates and table used to create default Tx flow rules. These default rules\n+ * allow for matching Tx representor traffic using a vport tag placed in unused bits of\n+ * REG_C_0 register.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device.\n+ *\n+ * @return\n+ *   0 on success, negative errno value otherwise.\n+ */\n+static int\n+flow_hw_setup_tx_repr_tagging(struct rte_eth_dev *dev)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct rte_flow_template_table_attr attr = {\n+\t\t.flow_attr = {\n+\t\t\t.group = 0,\n+\t\t\t.priority = MLX5_HW_LOWEST_PRIO_ROOT,\n+\t\t\t.egress = 1,\n+\t\t},\n+\t\t.nb_flows = MLX5_HW_CTRL_FLOW_NB_RULES,\n+\t};\n+\tstruct mlx5_flow_template_table_cfg cfg = {\n+\t\t.attr = attr,\n+\t\t.external = false,\n+\t};\n+\n+\tMLX5_ASSERT(priv->sh->config.dv_esw_en);\n+\tMLX5_ASSERT(priv->sh->config.repr_matching);\n+\tpriv->hw_tx_repr_tagging_pt = flow_hw_create_tx_repr_sq_pattern_tmpl(dev);\n+\tif (!priv->hw_tx_repr_tagging_pt)\n+\t\tgoto error;\n+\tpriv->hw_tx_repr_tagging_at = flow_hw_create_tx_repr_tag_jump_acts_tmpl(dev);\n+\tif (!priv->hw_tx_repr_tagging_at)\n+\t\tgoto error;\n+\tpriv->hw_tx_repr_tagging_tbl = flow_hw_table_create(dev, &cfg,\n+\t\t\t\t\t\t\t    &priv->hw_tx_repr_tagging_pt, 1,\n+\t\t\t\t\t\t\t    &priv->hw_tx_repr_tagging_at, 1,\n+\t\t\t\t\t\t\t    NULL);\n+\tif (!priv->hw_tx_repr_tagging_tbl)\n+\t\tgoto error;\n+\treturn 0;\n+error:\n+\tflow_hw_cleanup_tx_repr_tagging(dev);\n+\treturn -rte_errno;\n+}\n+\n static uint32_t\n flow_hw_esw_mgr_regc_marker_mask(struct rte_eth_dev *dev)\n {\n@@ -5549,29 +5869,43 @@ flow_hw_create_tx_default_mreg_copy_actions_template(struct rte_eth_dev *dev)\n \t\t},\n \t\t.width = UINT32_MAX,\n \t};\n-\tconst struct rte_flow_action copy_reg_action[] = {\n+\tconst struct rte_flow_action_jump jump_action = {\n+\t\t.group = 1,\n+\t};\n+\tconst struct rte_flow_action_jump jump_mask = {\n+\t\t.group = UINT32_MAX,\n+\t};\n+\tconst struct rte_flow_action actions[] = {\n \t\t[0] = {\n \t\t\t.type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,\n \t\t\t.conf = &mreg_action,\n \t\t},\n \t\t[1] = {\n+\t\t\t.type = RTE_FLOW_ACTION_TYPE_JUMP,\n+\t\t\t.conf = &jump_action,\n+\t\t},\n+\t\t[2] = {\n \t\t\t.type = RTE_FLOW_ACTION_TYPE_END,\n \t\t},\n \t};\n-\tconst struct rte_flow_action copy_reg_mask[] = {\n+\tconst struct rte_flow_action masks[] = {\n \t\t[0] = {\n \t\t\t.type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,\n \t\t\t.conf = &mreg_mask,\n \t\t},\n \t\t[1] = {\n+\t\t\t.type = RTE_FLOW_ACTION_TYPE_JUMP,\n+\t\t\t.conf = &jump_mask,\n+\t\t},\n+\t\t[2] = {\n \t\t\t.type = RTE_FLOW_ACTION_TYPE_END,\n \t\t},\n \t};\n \tstruct rte_flow_error drop_err;\n \n \tRTE_SET_USED(drop_err);\n-\treturn flow_hw_actions_template_create(dev, &tx_act_attr, copy_reg_action,\n-\t\t\t\t\t       copy_reg_mask, &drop_err);\n+\treturn flow_hw_actions_template_create(dev, &tx_act_attr, actions,\n+\t\t\t\t\t       masks, &drop_err);\n }\n \n /**\n@@ -5749,63 +6083,21 @@ flow_hw_create_ctrl_tables(struct rte_eth_dev *dev)\n \tstruct rte_flow_actions_template *jump_one_actions_tmpl = NULL;\n \tstruct rte_flow_actions_template *tx_meta_actions_tmpl = NULL;\n \tuint32_t xmeta = priv->sh->config.dv_xmeta_en;\n+\tuint32_t repr_matching = priv->sh->config.repr_matching;\n \n-\t/* Item templates */\n+\t/* Create templates and table for default SQ miss flow rules - root table. */\n \tesw_mgr_items_tmpl = flow_hw_create_ctrl_esw_mgr_pattern_template(dev);\n \tif (!esw_mgr_items_tmpl) {\n \t\tDRV_LOG(ERR, \"port %u failed to create E-Switch Manager item\"\n \t\t\t\" template for control flows\", dev->data->port_id);\n \t\tgoto error;\n \t}\n-\tregc_sq_items_tmpl = flow_hw_create_ctrl_regc_sq_pattern_template(dev);\n-\tif (!regc_sq_items_tmpl) {\n-\t\tDRV_LOG(ERR, \"port %u failed to create SQ item template for\"\n-\t\t\t\" control flows\", dev->data->port_id);\n-\t\tgoto error;\n-\t}\n-\tport_items_tmpl = flow_hw_create_ctrl_port_pattern_template(dev);\n-\tif (!port_items_tmpl) {\n-\t\tDRV_LOG(ERR, \"port %u failed to create SQ item template for\"\n-\t\t\t\" control flows\", dev->data->port_id);\n-\t\tgoto error;\n-\t}\n-\tif (xmeta == MLX5_XMETA_MODE_META32_HWS) {\n-\t\ttx_meta_items_tmpl = flow_hw_create_tx_default_mreg_copy_pattern_template(dev);\n-\t\tif (!tx_meta_items_tmpl) {\n-\t\t\tDRV_LOG(ERR, \"port %u failed to Tx metadata copy pattern\"\n-\t\t\t\t\" template for control flows\", dev->data->port_id);\n-\t\t\tgoto error;\n-\t\t}\n-\t}\n-\t/* Action templates */\n \tregc_jump_actions_tmpl = flow_hw_create_ctrl_regc_jump_actions_template(dev);\n \tif (!regc_jump_actions_tmpl) {\n \t\tDRV_LOG(ERR, \"port %u failed to create REG_C set and jump action template\"\n \t\t\t\" for control flows\", dev->data->port_id);\n \t\tgoto error;\n \t}\n-\tport_actions_tmpl = flow_hw_create_ctrl_port_actions_template(dev);\n-\tif (!port_actions_tmpl) {\n-\t\tDRV_LOG(ERR, \"port %u failed to create port action template\"\n-\t\t\t\" for control flows\", dev->data->port_id);\n-\t\tgoto error;\n-\t}\n-\tjump_one_actions_tmpl = flow_hw_create_ctrl_jump_actions_template\n-\t\t\t(dev, MLX5_HW_LOWEST_USABLE_GROUP);\n-\tif (!jump_one_actions_tmpl) {\n-\t\tDRV_LOG(ERR, \"port %u failed to create jump action template\"\n-\t\t\t\" for control flows\", dev->data->port_id);\n-\t\tgoto error;\n-\t}\n-\tif (xmeta == MLX5_XMETA_MODE_META32_HWS) {\n-\t\ttx_meta_actions_tmpl = flow_hw_create_tx_default_mreg_copy_actions_template(dev);\n-\t\tif (!tx_meta_actions_tmpl) {\n-\t\t\tDRV_LOG(ERR, \"port %u failed to Tx metadata copy actions\"\n-\t\t\t\t\" template for control flows\", dev->data->port_id);\n-\t\t\tgoto error;\n-\t\t}\n-\t}\n-\t/* Tables */\n \tMLX5_ASSERT(priv->hw_esw_sq_miss_root_tbl == NULL);\n \tpriv->hw_esw_sq_miss_root_tbl = flow_hw_create_ctrl_sq_miss_root_table\n \t\t\t(dev, esw_mgr_items_tmpl, regc_jump_actions_tmpl);\n@@ -5814,6 +6106,19 @@ flow_hw_create_ctrl_tables(struct rte_eth_dev *dev)\n \t\t\t\" for control flows\", dev->data->port_id);\n \t\tgoto error;\n \t}\n+\t/* Create templates and table for default SQ miss flow rules - non-root table. */\n+\tregc_sq_items_tmpl = flow_hw_create_ctrl_regc_sq_pattern_template(dev);\n+\tif (!regc_sq_items_tmpl) {\n+\t\tDRV_LOG(ERR, \"port %u failed to create SQ item template for\"\n+\t\t\t\" control flows\", dev->data->port_id);\n+\t\tgoto error;\n+\t}\n+\tport_actions_tmpl = flow_hw_create_ctrl_port_actions_template(dev);\n+\tif (!port_actions_tmpl) {\n+\t\tDRV_LOG(ERR, \"port %u failed to create port action template\"\n+\t\t\t\" for control flows\", dev->data->port_id);\n+\t\tgoto error;\n+\t}\n \tMLX5_ASSERT(priv->hw_esw_sq_miss_tbl == NULL);\n \tpriv->hw_esw_sq_miss_tbl = flow_hw_create_ctrl_sq_miss_table(dev, regc_sq_items_tmpl,\n \t\t\t\t\t\t\t\t     port_actions_tmpl);\n@@ -5822,6 +6127,20 @@ flow_hw_create_ctrl_tables(struct rte_eth_dev *dev)\n \t\t\t\" for control flows\", dev->data->port_id);\n \t\tgoto error;\n \t}\n+\t/* Create templates and table for default FDB jump flow rules. */\n+\tport_items_tmpl = flow_hw_create_ctrl_port_pattern_template(dev);\n+\tif (!port_items_tmpl) {\n+\t\tDRV_LOG(ERR, \"port %u failed to create SQ item template for\"\n+\t\t\t\" control flows\", dev->data->port_id);\n+\t\tgoto error;\n+\t}\n+\tjump_one_actions_tmpl = flow_hw_create_ctrl_jump_actions_template\n+\t\t\t(dev, MLX5_HW_LOWEST_USABLE_GROUP);\n+\tif (!jump_one_actions_tmpl) {\n+\t\tDRV_LOG(ERR, \"port %u failed to create jump action template\"\n+\t\t\t\" for control flows\", dev->data->port_id);\n+\t\tgoto error;\n+\t}\n \tMLX5_ASSERT(priv->hw_esw_zero_tbl == NULL);\n \tpriv->hw_esw_zero_tbl = flow_hw_create_ctrl_jump_table(dev, port_items_tmpl,\n \t\t\t\t\t\t\t       jump_one_actions_tmpl);\n@@ -5830,7 +6149,20 @@ flow_hw_create_ctrl_tables(struct rte_eth_dev *dev)\n \t\t\t\" for control flows\", dev->data->port_id);\n \t\tgoto error;\n \t}\n-\tif (xmeta == MLX5_XMETA_MODE_META32_HWS) {\n+\t/* Create templates and table for default Tx metadata copy flow rule. */\n+\tif (!repr_matching && xmeta == MLX5_XMETA_MODE_META32_HWS) {\n+\t\ttx_meta_items_tmpl = flow_hw_create_tx_default_mreg_copy_pattern_template(dev);\n+\t\tif (!tx_meta_items_tmpl) {\n+\t\t\tDRV_LOG(ERR, \"port %u failed to Tx metadata copy pattern\"\n+\t\t\t\t\" template for control flows\", dev->data->port_id);\n+\t\t\tgoto error;\n+\t\t}\n+\t\ttx_meta_actions_tmpl = flow_hw_create_tx_default_mreg_copy_actions_template(dev);\n+\t\tif (!tx_meta_actions_tmpl) {\n+\t\t\tDRV_LOG(ERR, \"port %u failed to Tx metadata copy actions\"\n+\t\t\t\t\" template for control flows\", dev->data->port_id);\n+\t\t\tgoto error;\n+\t\t}\n \t\tMLX5_ASSERT(priv->hw_tx_meta_cpy_tbl == NULL);\n \t\tpriv->hw_tx_meta_cpy_tbl = flow_hw_create_tx_default_mreg_copy_table(dev,\n \t\t\t\t\ttx_meta_items_tmpl, tx_meta_actions_tmpl);\n@@ -5854,7 +6186,7 @@ flow_hw_create_ctrl_tables(struct rte_eth_dev *dev)\n \t\tflow_hw_table_destroy(dev, priv->hw_esw_sq_miss_root_tbl, NULL);\n \t\tpriv->hw_esw_sq_miss_root_tbl = NULL;\n \t}\n-\tif (xmeta == MLX5_XMETA_MODE_META32_HWS && tx_meta_actions_tmpl)\n+\tif (tx_meta_actions_tmpl)\n \t\tflow_hw_actions_template_destroy(dev, tx_meta_actions_tmpl, NULL);\n \tif (jump_one_actions_tmpl)\n \t\tflow_hw_actions_template_destroy(dev, jump_one_actions_tmpl, NULL);\n@@ -5862,7 +6194,7 @@ flow_hw_create_ctrl_tables(struct rte_eth_dev *dev)\n \t\tflow_hw_actions_template_destroy(dev, port_actions_tmpl, NULL);\n \tif (regc_jump_actions_tmpl)\n \t\tflow_hw_actions_template_destroy(dev, regc_jump_actions_tmpl, NULL);\n-\tif (xmeta == MLX5_XMETA_MODE_META32_HWS && tx_meta_items_tmpl)\n+\tif (tx_meta_items_tmpl)\n \t\tflow_hw_pattern_template_destroy(dev, tx_meta_items_tmpl, NULL);\n \tif (port_items_tmpl)\n \t\tflow_hw_pattern_template_destroy(dev, port_items_tmpl, NULL);\n@@ -6207,6 +6539,13 @@ flow_hw_configure(struct rte_eth_dev *dev,\n \t\tif (!priv->hw_tag[i])\n \t\t\tgoto err;\n \t}\n+\tif (priv->sh->config.dv_esw_en && priv->sh->config.repr_matching) {\n+\t\tret = flow_hw_setup_tx_repr_tagging(dev);\n+\t\tif (ret) {\n+\t\t\trte_errno = -ret;\n+\t\t\tgoto err;\n+\t\t}\n+\t}\n \tif (is_proxy) {\n \t\tret = flow_hw_create_vport_actions(priv);\n \t\tif (ret) {\n@@ -6329,6 +6668,7 @@ 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+\tflow_hw_cleanup_tx_repr_tagging(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@@ -7688,45 +8028,30 @@ flow_hw_destroy_ctrl_flow(struct rte_eth_dev *dev, struct rte_flow *flow)\n }\n \n /**\n- * Destroys control flows created on behalf of @p owner_dev device.\n+ * Destroys control flows created on behalf of @p owner device on @p dev device.\n  *\n- * @param owner_dev\n+ * @param dev\n+ *   Pointer to Ethernet device on which control flows were created.\n+ * @param owner\n  *   Pointer to Ethernet device owning control flows.\n  *\n  * @return\n  *   0 on success, otherwise negative error code is returned and\n  *   rte_errno is set.\n  */\n-int\n-mlx5_flow_hw_flush_ctrl_flows(struct rte_eth_dev *owner_dev)\n+static int\n+flow_hw_flush_ctrl_flows_owned_by(struct rte_eth_dev *dev, struct rte_eth_dev *owner)\n {\n-\tstruct mlx5_priv *owner_priv = owner_dev->data->dev_private;\n-\tstruct rte_eth_dev *proxy_dev;\n-\tstruct mlx5_priv *proxy_priv;\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_hw_ctrl_flow *cf;\n \tstruct mlx5_hw_ctrl_flow *cf_next;\n-\tuint16_t owner_port_id = owner_dev->data->port_id;\n-\tuint16_t proxy_port_id = owner_dev->data->port_id;\n \tint ret;\n \n-\tif (owner_priv->sh->config.dv_esw_en) {\n-\t\tif (rte_flow_pick_transfer_proxy(owner_port_id, &proxy_port_id, NULL)) {\n-\t\t\tDRV_LOG(ERR, \"Unable to find proxy port for port %u\",\n-\t\t\t\towner_port_id);\n-\t\t\trte_errno = EINVAL;\n-\t\t\treturn -rte_errno;\n-\t\t}\n-\t\tproxy_dev = &rte_eth_devices[proxy_port_id];\n-\t\tproxy_priv = proxy_dev->data->dev_private;\n-\t} else {\n-\t\tproxy_dev = owner_dev;\n-\t\tproxy_priv = owner_priv;\n-\t}\n-\tcf = LIST_FIRST(&proxy_priv->hw_ctrl_flows);\n+\tcf = LIST_FIRST(&priv->hw_ctrl_flows);\n \twhile (cf != NULL) {\n \t\tcf_next = LIST_NEXT(cf, next);\n-\t\tif (cf->owner_dev == owner_dev) {\n-\t\t\tret = flow_hw_destroy_ctrl_flow(proxy_dev, cf->flow);\n+\t\tif (cf->owner_dev == owner) {\n+\t\t\tret = flow_hw_destroy_ctrl_flow(dev, cf->flow);\n \t\t\tif (ret) {\n \t\t\t\trte_errno = ret;\n \t\t\t\treturn -ret;\n@@ -7739,6 +8064,50 @@ mlx5_flow_hw_flush_ctrl_flows(struct rte_eth_dev *owner_dev)\n \treturn 0;\n }\n \n+/**\n+ * Destroys control flows created for @p owner_dev device.\n+ *\n+ * @param owner_dev\n+ *   Pointer to Ethernet device owning control flows.\n+ *\n+ * @return\n+ *   0 on success, otherwise negative error code is returned and\n+ *   rte_errno is set.\n+ */\n+int\n+mlx5_flow_hw_flush_ctrl_flows(struct rte_eth_dev *owner_dev)\n+{\n+\tstruct mlx5_priv *owner_priv = owner_dev->data->dev_private;\n+\tstruct rte_eth_dev *proxy_dev;\n+\tuint16_t owner_port_id = owner_dev->data->port_id;\n+\tuint16_t proxy_port_id = owner_dev->data->port_id;\n+\tint ret;\n+\n+\t/* Flush all flows created by this port for itself. */\n+\tret = flow_hw_flush_ctrl_flows_owned_by(owner_dev, owner_dev);\n+\tif (ret)\n+\t\treturn ret;\n+\t/* Flush all flows created for this port on proxy port. */\n+\tif (owner_priv->sh->config.dv_esw_en) {\n+\t\tret = rte_flow_pick_transfer_proxy(owner_port_id, &proxy_port_id, NULL);\n+\t\tif (ret == -ENODEV) {\n+\t\t\tDRV_LOG(DEBUG, \"Unable to find transfer proxy port for port %u. It was \"\n+\t\t\t\t       \"probably closed. Control flows were cleared.\",\n+\t\t\t\t       owner_port_id);\n+\t\t\trte_errno = 0;\n+\t\t\treturn 0;\n+\t\t} else if (ret) {\n+\t\t\tDRV_LOG(ERR, \"Unable to find proxy port for port %u (ret = %d)\",\n+\t\t\t\towner_port_id, ret);\n+\t\t\treturn ret;\n+\t\t}\n+\t\tproxy_dev = &rte_eth_devices[proxy_port_id];\n+\t} else {\n+\t\tproxy_dev = owner_dev;\n+\t}\n+\treturn flow_hw_flush_ctrl_flows_owned_by(proxy_dev, owner_dev);\n+}\n+\n /**\n  * Destroys all control flows created on @p dev device.\n  *\n@@ -7990,6 +8359,9 @@ mlx5_flow_hw_create_tx_default_mreg_copy_flow(struct rte_eth_dev *dev)\n \t\t\t.conf = &mreg_action,\n \t\t},\n \t\t[1] = {\n+\t\t\t.type = RTE_FLOW_ACTION_TYPE_JUMP,\n+\t\t},\n+\t\t[2] = {\n \t\t\t.type = RTE_FLOW_ACTION_TYPE_END,\n \t\t},\n \t};\n@@ -8002,6 +8374,60 @@ mlx5_flow_hw_create_tx_default_mreg_copy_flow(struct rte_eth_dev *dev)\n \t\t\t\t\teth_all, 0, copy_reg_action, 0);\n }\n \n+int\n+mlx5_flow_hw_tx_repr_matching_flow(struct rte_eth_dev *dev, uint32_t sqn)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_rte_flow_item_sq sq_spec = {\n+\t\t.queue = sqn,\n+\t};\n+\tstruct rte_flow_item items[] = {\n+\t\t{\n+\t\t\t.type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_SQ,\n+\t\t\t.spec = &sq_spec,\n+\t\t},\n+\t\t{\n+\t\t\t.type = RTE_FLOW_ITEM_TYPE_END,\n+\t\t},\n+\t};\n+\t/*\n+\t * Allocate actions array suitable for all cases - extended metadata enabled or not.\n+\t * With extended metadata there will be an additional MODIFY_FIELD action before JUMP.\n+\t */\n+\tstruct rte_flow_action actions[] = {\n+\t\t{ .type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD },\n+\t\t{ .type = RTE_FLOW_ACTION_TYPE_JUMP },\n+\t\t{ .type = RTE_FLOW_ACTION_TYPE_END },\n+\t\t{ .type = RTE_FLOW_ACTION_TYPE_END },\n+\t};\n+\n+\t/* It is assumed that caller checked for representor matching. */\n+\tMLX5_ASSERT(priv->sh->config.repr_matching);\n+\tif (!priv->dr_ctx) {\n+\t\tDRV_LOG(DEBUG, \"Port %u must be configured for HWS, before creating \"\n+\t\t\t       \"default egress flow rules. Omitting creation.\",\n+\t\t\t       dev->data->port_id);\n+\t\treturn 0;\n+\t}\n+\tif (!priv->hw_tx_repr_tagging_tbl) {\n+\t\tDRV_LOG(ERR, \"Port %u is configured for HWS, but table for default \"\n+\t\t\t     \"egress flow rules does not exist.\",\n+\t\t\t     dev->data->port_id);\n+\t\trte_errno = EINVAL;\n+\t\treturn -rte_errno;\n+\t}\n+\t/*\n+\t * If extended metadata mode is enabled, then an additional MODIFY_FIELD action must be\n+\t * placed before terminating JUMP action.\n+\t */\n+\tif (priv->sh->config.dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS) {\n+\t\tactions[1].type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD;\n+\t\tactions[2].type = RTE_FLOW_ACTION_TYPE_JUMP;\n+\t}\n+\treturn flow_hw_create_ctrl_flow(dev, dev, priv->hw_tx_repr_tagging_tbl,\n+\t\t\t\t\titems, 0, actions, 0);\n+}\n+\n void\n mlx5_flow_meter_uninit(struct rte_eth_dev *dev)\n {\ndiff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c\nindex a973cbc5e3..dcb02f2a7f 100644\n--- a/drivers/net/mlx5/mlx5_trigger.c\n+++ b/drivers/net/mlx5/mlx5_trigger.c\n@@ -1065,6 +1065,69 @@ mlx5_hairpin_get_peer_ports(struct rte_eth_dev *dev, uint16_t *peer_ports,\n \treturn ret;\n }\n \n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\n+/**\n+ * Check if starting representor port is allowed.\n+ *\n+ * If transfer proxy port is configured for HWS, then starting representor port\n+ * is allowed if and only if transfer proxy port is started as well.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device structure.\n+ *\n+ * @return\n+ *   If stopping representor port is allowed, then 0 is returned.\n+ *   Otherwise rte_errno is set, and negative errno value is returned.\n+ */\n+static int\n+mlx5_hw_representor_port_allowed_start(struct rte_eth_dev *dev)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct rte_eth_dev *proxy_dev;\n+\tstruct mlx5_priv *proxy_priv;\n+\tuint16_t proxy_port_id = UINT16_MAX;\n+\tint ret;\n+\n+\tMLX5_ASSERT(priv->sh->config.dv_flow_en == 2);\n+\tMLX5_ASSERT(priv->sh->config.dv_esw_en);\n+\tMLX5_ASSERT(priv->representor);\n+\tret = rte_flow_pick_transfer_proxy(dev->data->port_id, &proxy_port_id, NULL);\n+\tif (ret) {\n+\t\tif (ret == -ENODEV)\n+\t\t\tDRV_LOG(ERR, \"Starting representor port %u is not allowed. Transfer \"\n+\t\t\t\t     \"proxy port is not available.\", dev->data->port_id);\n+\t\telse\n+\t\t\tDRV_LOG(ERR, \"Failed to pick transfer proxy for port %u (ret = %d)\",\n+\t\t\t\tdev->data->port_id, ret);\n+\t\treturn ret;\n+\t}\n+\tproxy_dev = &rte_eth_devices[proxy_port_id];\n+\tproxy_priv = proxy_dev->data->dev_private;\n+\tif (proxy_priv->dr_ctx == NULL) {\n+\t\tDRV_LOG(DEBUG, \"Starting representor port %u is allowed, but default traffic flows\"\n+\t\t\t       \" will not be created. Transfer proxy port must be configured\"\n+\t\t\t       \" for HWS and started.\",\n+\t\t\t       dev->data->port_id);\n+\t\treturn 0;\n+\t}\n+\tif (!proxy_dev->data->dev_started) {\n+\t\tDRV_LOG(ERR, \"Failed to start port %u: transfer proxy (port %u) must be started\",\n+\t\t\t     dev->data->port_id, proxy_port_id);\n+\t\trte_errno = EAGAIN;\n+\t\treturn -rte_errno;\n+\t}\n+\tif (priv->sh->config.repr_matching && !priv->dr_ctx) {\n+\t\tDRV_LOG(ERR, \"Failed to start port %u: with representor matching enabled, port \"\n+\t\t\t     \"must be configured for HWS\", dev->data->port_id);\n+\t\trte_errno = EINVAL;\n+\t\treturn -rte_errno;\n+\t}\n+\treturn 0;\n+}\n+\n+#endif\n+\n /**\n  * DPDK callback to start the device.\n  *\n@@ -1084,6 +1147,19 @@ mlx5_dev_start(struct rte_eth_dev *dev)\n \tint fine_inline;\n \n \tDRV_LOG(DEBUG, \"port %u starting device\", dev->data->port_id);\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\tif (priv->sh->config.dv_flow_en == 2) {\n+\t\t/* If there is no E-Switch, then there are no start/stop order limitations. */\n+\t\tif (!priv->sh->config.dv_esw_en)\n+\t\t\tgoto continue_dev_start;\n+\t\t/* If master is being started, then it is always allowed. */\n+\t\tif (priv->master)\n+\t\t\tgoto continue_dev_start;\n+\t\tif (mlx5_hw_representor_port_allowed_start(dev))\n+\t\t\treturn -rte_errno;\n+\t}\n+continue_dev_start:\n+#endif\n \tfine_inline = rte_mbuf_dynflag_lookup\n \t\t(RTE_PMD_MLX5_FINE_GRANULARITY_INLINE, NULL);\n \tif (fine_inline >= 0)\n@@ -1248,6 +1324,53 @@ mlx5_dev_start(struct rte_eth_dev *dev)\n \treturn -rte_errno;\n }\n \n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+/**\n+ * Check if stopping transfer proxy port is allowed.\n+ *\n+ * If transfer proxy port is configured for HWS, then it is allowed to stop it\n+ * if and only if all other representor ports are stopped.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device structure.\n+ *\n+ * @return\n+ *   If stopping transfer proxy port is allowed, then 0 is returned.\n+ *   Otherwise rte_errno is set, and negative errno value is returned.\n+ */\n+static int\n+mlx5_hw_proxy_port_allowed_stop(struct rte_eth_dev *dev)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tbool representor_started = false;\n+\tuint16_t port_id;\n+\n+\tMLX5_ASSERT(priv->sh->config.dv_flow_en == 2);\n+\tMLX5_ASSERT(priv->sh->config.dv_esw_en);\n+\tMLX5_ASSERT(priv->master);\n+\t/* If transfer proxy port was not configured for HWS, then stopping it is allowed. */\n+\tif (!priv->dr_ctx)\n+\t\treturn 0;\n+\tMLX5_ETH_FOREACH_DEV(port_id, dev->device) {\n+\t\tconst struct rte_eth_dev *port_dev = &rte_eth_devices[port_id];\n+\t\tconst struct mlx5_priv *port_priv = port_dev->data->dev_private;\n+\n+\t\tif (port_id != dev->data->port_id &&\n+\t\t    port_priv->domain_id == priv->domain_id &&\n+\t\t    port_dev->data->dev_started)\n+\t\t\trepresentor_started = true;\n+\t}\n+\tif (representor_started) {\n+\t\tDRV_LOG(INFO, \"Failed to stop port %u: attached representor ports\"\n+\t\t\t      \" must be stopped before stopping transfer proxy port\",\n+\t\t\t      dev->data->port_id);\n+\t\trte_errno = EBUSY;\n+\t\treturn -rte_errno;\n+\t}\n+\treturn 0;\n+}\n+#endif\n+\n /**\n  * DPDK callback to stop the device.\n  *\n@@ -1261,6 +1384,21 @@ mlx5_dev_stop(struct rte_eth_dev *dev)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\tif (priv->sh->config.dv_flow_en == 2) {\n+\t\t/* If there is no E-Switch, then there are no start/stop order limitations. */\n+\t\tif (!priv->sh->config.dv_esw_en)\n+\t\t\tgoto continue_dev_stop;\n+\t\t/* If representor is being stopped, then it is always allowed. */\n+\t\tif (priv->representor)\n+\t\t\tgoto continue_dev_stop;\n+\t\tif (mlx5_hw_proxy_port_allowed_stop(dev)) {\n+\t\t\tdev->data->dev_started = 1;\n+\t\t\treturn -rte_errno;\n+\t\t}\n+\t}\n+continue_dev_stop:\n+#endif\n \tdev->data->dev_started = 0;\n \t/* Prevent crashes when queues are still in use. */\n \tdev->rx_pkt_burst = rte_eth_pkt_burst_dummy;\n@@ -1296,13 +1434,21 @@ static int\n mlx5_traffic_enable_hws(struct rte_eth_dev *dev)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_sh_config *config = &priv->sh->config;\n \tunsigned int i;\n \tint ret;\n \n-\tif (priv->sh->config.dv_esw_en && priv->master) {\n-\t\tif (priv->sh->config.dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS)\n-\t\t\tif (mlx5_flow_hw_create_tx_default_mreg_copy_flow(dev))\n-\t\t\t\tgoto error;\n+\t/*\n+\t * With extended metadata enabled, the Tx metadata copy is handled by default\n+\t * Tx tagging flow rules, so default Tx flow rule is not needed. It is only\n+\t * required when representor matching is disabled.\n+\t */\n+\tif (config->dv_esw_en &&\n+\t    !config->repr_matching &&\n+\t    config->dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS &&\n+\t    priv->master) {\n+\t\tif (mlx5_flow_hw_create_tx_default_mreg_copy_flow(dev))\n+\t\t\tgoto error;\n \t}\n \tfor (i = 0; i < priv->txqs_n; ++i) {\n \t\tstruct mlx5_txq_ctrl *txq = mlx5_txq_get(dev, i);\n@@ -1311,17 +1457,22 @@ mlx5_traffic_enable_hws(struct rte_eth_dev *dev)\n \t\tif (!txq)\n \t\t\tcontinue;\n \t\tqueue = mlx5_txq_get_sqn(txq);\n-\t\tif ((priv->representor || priv->master) &&\n-\t\t    priv->sh->config.dv_esw_en) {\n+\t\tif ((priv->representor || priv->master) && config->dv_esw_en) {\n \t\t\tif (mlx5_flow_hw_esw_create_sq_miss_flow(dev, queue)) {\n \t\t\t\tmlx5_txq_release(dev, i);\n \t\t\t\tgoto error;\n \t\t\t}\n \t\t}\n+\t\tif (config->dv_esw_en && config->repr_matching) {\n+\t\t\tif (mlx5_flow_hw_tx_repr_matching_flow(dev, queue)) {\n+\t\t\t\tmlx5_txq_release(dev, i);\n+\t\t\t\tgoto error;\n+\t\t\t}\n+\t\t}\n \t\tmlx5_txq_release(dev, i);\n \t}\n-\tif (priv->sh->config.fdb_def_rule) {\n-\t\tif ((priv->master || priv->representor) && priv->sh->config.dv_esw_en) {\n+\tif (config->fdb_def_rule) {\n+\t\tif ((priv->master || priv->representor) && config->dv_esw_en) {\n \t\t\tif (!mlx5_flow_hw_esw_create_default_jump_flow(dev))\n \t\t\t\tpriv->fdb_def_rule = 1;\n \t\t\telse\n",
    "prefixes": [
        "v3",
        "17/17"
    ]
}