get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 117008,
    "url": "http://patches.dpdk.org/api/patches/117008/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20220928033130.9106-12-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": "<20220928033130.9106-12-suanmingm@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220928033130.9106-12-suanmingm@nvidia.com",
    "date": "2022-09-28T03:31:24",
    "name": "[v2,11/17] net/mlx5: add HW steering VLAN push, pop and VID modify flow actions",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "3f97e0053338cf85977e3bdbee44b35082f63a93",
    "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/20220928033130.9106-12-suanmingm@nvidia.com/mbox/",
    "series": [
        {
            "id": 24870,
            "url": "http://patches.dpdk.org/api/series/24870/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=24870",
            "date": "2022-09-28T03:31:15",
            "name": "net/mlx5: HW steering PMD update",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/24870/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/117008/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/117008/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 42A2EA00C2;\n\tWed, 28 Sep 2022 05:33:33 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id DCB1C42BA7;\n\tWed, 28 Sep 2022 05:32:28 +0200 (CEST)",
            "from NAM10-DM6-obe.outbound.protection.outlook.com\n (mail-dm6nam10on2077.outbound.protection.outlook.com [40.107.93.77])\n by mails.dpdk.org (Postfix) with ESMTP id CC68642B90\n for <dev@dpdk.org>; Wed, 28 Sep 2022 05:32:27 +0200 (CEST)",
            "from DM6PR07CA0118.namprd07.prod.outlook.com (2603:10b6:5:330::31)\n by BY5PR12MB4854.namprd12.prod.outlook.com (2603:10b6:a03:1d1::9) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5654.26; Wed, 28 Sep\n 2022 03:32:24 +0000",
            "from DM6NAM11FT017.eop-nam11.prod.protection.outlook.com\n (2603:10b6:5:330:cafe::73) by DM6PR07CA0118.outlook.office365.com\n (2603:10b6:5:330::31) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5654.25 via Frontend\n Transport; Wed, 28 Sep 2022 03:32:24 +0000",
            "from mail.nvidia.com (216.228.117.160) by\n DM6NAM11FT017.mail.protection.outlook.com (10.13.172.145) 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; Wed, 28 Sep 2022 03:32:24 +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; Tue, 27 Sep\n 2022 20:32:12 -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; Tue, 27 Sep\n 2022 20:32:10 -0700"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=dmCOfa98gvnlfoZ0iqisJC6qakraeaN/CE/4FX0iB4yrUMM8PEKl8Y2eDAD+Lt/uzrD5ezvsehAw/lcLLyWoQrPaJ8bx7m8xMqaHekcV1eRyCyynBaczy/o8c3N5MZgYJQnOGUBpCx3j35ir2CmfccE5BkuyF7sPXsMPDKTzq/ncKzXNfNi1GtEqmV+GczYIj9Ycey8L/8cAXQ9Ul+0DItINVkRhi5CcbO7lthG2T0S4h1R2O2n8O2kb2efmnW5DK5BGxJZnpo66tandtioJ796zb3kTvCRHDXjj7GS0rNmcgqDcnfZtd+9NJd9M3E/wFSLwLO1xqWi0SD7GPUjimg==",
        "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=RYGYSwRfdLBPh0Brd2pXGo0C8wUEB3GM7Q6WZZWfTKk=;\n b=X3GqhIaenajppPa+6XYF132D8P94fOQGuvHq4/vu4B013yxgEk1YR1tcErMk/pRJFPO9SvtfEmuyYKd4Y1VQAlkv1/79YJjTGaLMS7QWTw76+46T9fnXfX6q4qpy0h4nKoxIP3T9KE/zatXwKL9WyRXvzOqLsRynPvOYkqdISHwxTAdAdYYboOuIVXjGKAvPPoNKgDH/20kWrkOrrfe1E1/Zj67ayUUgt76IKK+jN4naVCr7Qb49MxjDnUee5HDLnvaQU+gdlbfM/7JYg3+6BQ3aVPXGGpfk0F3Jf/j8gxiZuuImw8Fb5T9pY6pRhew7BrFIPJIp30xQdZeCyw7rbw==",
        "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=RYGYSwRfdLBPh0Brd2pXGo0C8wUEB3GM7Q6WZZWfTKk=;\n b=nZg7qS59A/Fn7tuNCH36/XUP9ISj99Zsfn7RrWhqeRy2vjZFaPuUQDt5jl8bySVs2i7sfwCvSkOYfDwBr1MFRde2y1DDJFEXryhHT2GHtMAcki/L749jJB+8xxhxKu/iQVDi2xoClCrFG1tz58rbgFVOD+XLKdj/+JRa+SQeT9ECh/POX5Gwmo5Sa1x+3YSZ1rVZugJlMqWsAHV0qA+H8IiACRL3WpRPuR8pmCnjHfV+zUJK3IkhwN6SpI2atf7Pur3seIWGQWpCUB/3/4dZqE3VknizOwiSDV3g8OLp04OklRf1HYiol5msoGbUgpubWw3PGQWXQSIZuT2gMyGRug==",
        "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>, Gregory Etelson\n <getelson@nvidia.com>",
        "Subject": "[PATCH v2 11/17] net/mlx5: add HW steering VLAN push,\n pop and VID modify flow actions",
        "Date": "Wed, 28 Sep 2022 06:31:24 +0300",
        "Message-ID": "<20220928033130.9106-12-suanmingm@nvidia.com>",
        "X-Mailer": "git-send-email 2.18.1",
        "In-Reply-To": "<20220928033130.9106-1-suanmingm@nvidia.com>",
        "References": "<20220923144334.27736-1-suanmingm@nvidia.com>\n <20220928033130.9106-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": "DM6NAM11FT017:EE_|BY5PR12MB4854:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "20c155c4-e8e6-43e4-d6a4-08daa1020f3d",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n paUNzF9UI0Ka0FdmLAFv+bwNjIv7yNCl4DMVBanOZJ7xs9vd0o5gzJhUGGShM2f7s+KOcAwQ3wWBXG1OuUc9VzWkiGHhUY1nnVCjrrjr8FXijIzP2G7CYTD9oLcpq3cv0S29LPVCdqAi8dkMsa+mLX2Ae845rVLXeYX8AJ7giXLS1dhwOVPzDSO7I2oqg66IXX381YnWEyhUmPw2od6j1mgofYDS3gj86EAh9s66wItLh1vpJEASCRIWkcRU9iLgYPZdKLMxiY+L/metXKyfpeEIk+jN/kbRjSDkZ98yw+SN/zUWbKHgk8qkCCZsWCpUibMz+wRCpMMoQS9hY/qHPBeVciJih2R1+f5hBwEe6g+gwrP0k9aXXRwOaFlOVYlIKei+cRv4xImY6TLmCG3uoYR9W6+6EptsvV8Zee2VyT1CWE0ppprVeeirhigmnp3g8yVOV7zADViF9LKjCAmsDX9jLJqrO4azKvdzHuHDkdiN8yw1J6n2vvvyViBUpWCgO73IQ73A7moGMeCBm6Q2Of3geETLUx+eqIDkeNqqMhOUqz2FFoDsDI5Ko6JWrwvKoM8KQOA60oAoawsr52nYR5hjF7oZNVYMRk3L/HntqI0XXdpcMEqySAa8c5OeXu62/O+vsUcaybtz3VoMraeD68ak9wiK+1polP8SzzPR5MRZwjnEBgxsspipNI2kHbkDicy8c9yo/RVjgrOxkyV5Dn+P6q7z5lL20qGhJ6V4qsnF+1bDdULyEXzOTYLu6kG350rr9c/gFa6tXWLPswMpgQ==",
        "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)(396003)(346002)(376002)(39860400002)(136003)(451199015)(40470700004)(46966006)(36840700001)(70586007)(8676002)(356005)(70206006)(186003)(5660300002)(4326008)(7636003)(2906002)(8936002)(30864003)(6286002)(1076003)(16526019)(2616005)(86362001)(83380400001)(7696005)(316002)(426003)(336012)(26005)(40460700003)(107886003)(6666004)(478600001)(6636002)(54906003)(41300700001)(82740400003)(110136005)(47076005)(36860700001)(36756003)(55016003)(40480700001)(82310400005);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "Nvidia.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "28 Sep 2022 03:32:24.2501 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 20c155c4-e8e6-43e4-d6a4-08daa1020f3d",
        "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 DM6NAM11FT017.eop-nam11.prod.protection.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "BY5PR12MB4854",
        "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: Gregory Etelson <getelson@nvidia.com>\n\nAdd PMD implementation for HW steering VLAN push, pop and modify flow\nactions.\n\nHWS VLAN push flow action is triggered by a sequence of mandatory\nOF_PUSH_VLAN, OF_SET_VLAN_VID and optional OF_SET_VLAN_PCP\nflow actions commands.\nThe commands must be arranged in the exact order:\nOF_PUSH_VLAN / OF_SET_VLAN_VID [ / OF_SET_VLAN_PCP ].\nIn masked HWS VLAN push flow action template *ALL* the above flow\nactions must be masked.\nIn non-masked HWS VLAN push flow action template *ALL* the above flow\nactions must not be masked.\n\nExample:\n\nflow actions_template <port id> create \\\nactions_template_id <action id> \\\ntemplate \\\n  of_push_vlan / \\\n  of_set_vlan_vid \\\n  [ / of_set_vlan_pcp  ] / end \\\nmask \\\n  of_push_vlan ethertype 0 / \\\n  of_set_vlan_vid vlan_vid 0 \\\n  [ / of_set_vlan_pcp vlan_pcp 0 ] / end\\\n\nflow actions_template <port id> create \\\nactions_template_id <action id> \\\ntemplate \\\n  of_push_vlan ethertype <E>/ \\\n  of_set_vlan_vid vlan_vid <VID>\\\n  [ / of_set_vlan_pcp  <PCP>] / end \\\nmask \\\n  of_push_vlan ethertype <type != 0> / \\\n  of_set_vlan_vid vlan_vid <vid_mask != 0>\\\n  [ / of_set_vlan_pcp vlan_pcp <pcp_mask != 0> ] / end\\\n\nHWS VLAN pop flow action is triggered by OF_POP_VLAN\nflow action command.\nHWS VLAN pop action template is always non-masked.\n\nExample:\n\nflow actions_template <port id> create \\\nactions_template_id <action id> \\\ntemplate of_pop_vlan / end mask of_pop_vlan / end\n\nHWS VLAN VID modify flow action is triggered by a standalone\nOF_SET_VLAN_VID flow action command.\nHWS VLAN VID modify action template can be ether masked or non-masked.\n\nExample:\n\nflow actions_template <port id> create \\\nactions_template_id <action id> \\\ntemplate of_set_vlan_vid / end mask of_set_vlan_vid vlan_vid 0 / end\n\nflow actions_template <port id> create \\\nactions_template_id <action id> \\\ntemplate of_set_vlan_vid vlan_vid 0x101 / end \\\nmask of_set_vlan_vid vlan_vid 0xffff / end\n\nSigned-off-by: Gregory Etelson <getelson@nvidia.com>\n---\n drivers/net/mlx5/mlx5.h         |   2 +\n drivers/net/mlx5/mlx5_flow.h    |   4 +\n drivers/net/mlx5/mlx5_flow_dv.c |   2 +-\n drivers/net/mlx5/mlx5_flow_hw.c | 492 +++++++++++++++++++++++++++++---\n 4 files changed, 463 insertions(+), 37 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex df962a1fc0..16cd261942 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -1665,6 +1665,8 @@ struct mlx5_priv {\n \tstruct mlx5_hw_q *hw_q;\n \t/* HW steering rte flow table list header. */\n \tLIST_HEAD(flow_hw_tbl, rte_flow_template_table) flow_hw_tbl;\n+\tstruct mlx5dr_action *hw_push_vlan[MLX5DR_TABLE_TYPE_MAX];\n+\tstruct mlx5dr_action *hw_pop_vlan[MLX5DR_TABLE_TYPE_MAX];\n \tstruct mlx5dr_action **hw_vport;\n \t/* HW steering global drop action. */\n \tstruct mlx5dr_action *hw_drop[2];\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex f75a56a57b..6d928b477e 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -2435,4 +2435,8 @@ int mlx5_flow_pattern_validate(struct rte_eth_dev *dev,\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+int mlx5_flow_item_field_width(struct rte_eth_dev *dev,\n+\t\t\t   enum rte_flow_field_id field, int inherit,\n+\t\t\t   const struct rte_flow_attr *attr,\n+\t\t\t   struct rte_flow_error *error);\n #endif /* RTE_PMD_MLX5_FLOW_H_ */\ndiff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex 9721c5c311..7e0829d1fd 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -1326,7 +1326,7 @@ flow_dv_convert_action_modify_ipv6_dscp\n \t\t\t\t\t     MLX5_MODIFICATION_TYPE_SET, error);\n }\n \n-static int\n+int\n mlx5_flow_item_field_width(struct rte_eth_dev *dev,\n \t\t\t   enum rte_flow_field_id field, int inherit,\n \t\t\t   const struct rte_flow_attr *attr,\ndiff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c\nindex 9f575786f7..af06659052 100644\n--- a/drivers/net/mlx5/mlx5_flow_hw.c\n+++ b/drivers/net/mlx5/mlx5_flow_hw.c\n@@ -44,12 +44,22 @@\n /* Lowest priority for HW non-root table. */\n #define MLX5_HW_LOWEST_PRIO_NON_ROOT (UINT32_MAX)\n \n+#define MLX5_HW_VLAN_PUSH_TYPE_IDX 0\n+#define MLX5_HW_VLAN_PUSH_VID_IDX 1\n+#define MLX5_HW_VLAN_PUSH_PCP_IDX 2\n+\n static int flow_hw_flush_all_ctrl_flows(struct rte_eth_dev *dev);\n static int flow_hw_translate_group(struct rte_eth_dev *dev,\n \t\t\t\t   const struct mlx5_flow_template_table_cfg *cfg,\n \t\t\t\t   uint32_t group,\n \t\t\t\t   uint32_t *table_group,\n \t\t\t\t   struct rte_flow_error *error);\n+static __rte_always_inline int\n+flow_hw_set_vlan_vid_construct(struct rte_eth_dev *dev,\n+\t\t\t       struct mlx5_hw_q_job *job,\n+\t\t\t       struct mlx5_action_construct_data *act_data,\n+\t\t\t       const struct mlx5_hw_actions *hw_acts,\n+\t\t\t       const struct rte_flow_action *action);\n \n const struct mlx5_flow_driver_ops mlx5_flow_hw_drv_ops;\n \n@@ -1048,6 +1058,52 @@ flow_hw_cnt_compile(struct rte_eth_dev *dev, uint32_t  start_pos,\n \treturn 0;\n }\n \n+static __rte_always_inline bool\n+is_of_vlan_pcp_present(const struct rte_flow_action *actions)\n+{\n+\t/*\n+\t * Order of RTE VLAN push actions is\n+\t * OF_PUSH_VLAN / OF_SET_VLAN_VID [ / OF_SET_VLAN_PCP ]\n+\t */\n+\treturn actions[MLX5_HW_VLAN_PUSH_PCP_IDX].type ==\n+\t\tRTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP;\n+}\n+\n+static __rte_always_inline bool\n+is_template_masked_push_vlan(const struct rte_flow_action_of_push_vlan *mask)\n+{\n+\t/*\n+\t * In masked push VLAN template all RTE push actions are masked.\n+\t */\n+\treturn mask && mask->ethertype != 0;\n+}\n+\n+static rte_be32_t vlan_hdr_to_be32(const struct rte_flow_action *actions)\n+{\n+/*\n+ * OpenFlow Switch Specification defines 801.1q VID as 12+1 bits.\n+ */\n+\trte_be32_t type, vid, pcp;\n+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN\n+\trte_be32_t vid_lo, vid_hi;\n+#endif\n+\n+\ttype = ((const struct rte_flow_action_of_push_vlan *)\n+\t\tactions[MLX5_HW_VLAN_PUSH_TYPE_IDX].conf)->ethertype;\n+\tvid = ((const struct rte_flow_action_of_set_vlan_vid *)\n+\t\tactions[MLX5_HW_VLAN_PUSH_VID_IDX].conf)->vlan_vid;\n+\tpcp = is_of_vlan_pcp_present(actions) ?\n+\t      ((const struct rte_flow_action_of_set_vlan_pcp *)\n+\t\t      actions[MLX5_HW_VLAN_PUSH_PCP_IDX].conf)->vlan_pcp : 0;\n+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN\n+\tvid_hi = vid & 0xff;\n+\tvid_lo = vid >> 8;\n+\treturn (((vid_lo << 8) | (pcp << 5) | vid_hi) << 16) | type;\n+#else\n+\treturn (type << 16) | (pcp << 13) | vid;\n+#endif\n+}\n+\n /**\n  * Translate rte_flow actions to DR action.\n  *\n@@ -1150,6 +1206,26 @@ __flow_hw_actions_translate(struct rte_eth_dev *dev,\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_OF_PUSH_VLAN:\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_push_vlan[type];\n+\t\t\tif (is_template_masked_push_vlan(masks->conf))\n+\t\t\t\tacts->rule_acts[action_pos].push_vlan.vlan_hdr =\n+\t\t\t\t\tvlan_hdr_to_be32(actions);\n+\t\t\telse 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, action_pos))\n+\t\t\t\tgoto err;\n+\t\t\tactions += is_of_vlan_pcp_present(actions) ?\n+\t\t\t\t\tMLX5_HW_VLAN_PUSH_PCP_IDX :\n+\t\t\t\t\tMLX5_HW_VLAN_PUSH_VID_IDX;\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:\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_pop_vlan[type];\n+\t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_JUMP:\n \t\t\taction_pos = at->actions_off[actions - action_start];\n \t\t\tif (masks->conf &&\n@@ -1767,8 +1843,17 @@ flow_hw_actions_construct(struct rte_eth_dev *dev,\n \t\tcnt_id_t cnt_id;\n \n \t\taction = &actions[act_data->action_src];\n-\t\tMLX5_ASSERT(action->type == RTE_FLOW_ACTION_TYPE_INDIRECT ||\n-\t\t\t    (int)action->type == act_data->type);\n+\t\t/*\n+\t\t * action template construction replaces\n+\t\t * OF_SET_VLAN_VID with MODIFY_FIELD\n+\t\t */\n+\t\tif (action->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID)\n+\t\t\tMLX5_ASSERT(act_data->type ==\n+\t\t\t\t    RTE_FLOW_ACTION_TYPE_MODIFY_FIELD);\n+\t\telse\n+\t\t\tMLX5_ASSERT(action->type ==\n+\t\t\t\t    RTE_FLOW_ACTION_TYPE_INDIRECT ||\n+\t\t\t\t    (int)action->type == act_data->type);\n \t\tswitch (act_data->type) {\n \t\tcase RTE_FLOW_ACTION_TYPE_INDIRECT:\n \t\t\tif (flow_hw_shared_action_construct\n@@ -1784,6 +1869,10 @@ flow_hw_actions_construct(struct rte_eth_dev *dev,\n \t\t\t      (action->conf))->id);\n \t\t\trule_acts[act_data->action_dst].tag.value = tag;\n \t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:\n+\t\t\trule_acts[act_data->action_dst].push_vlan.vlan_hdr =\n+\t\t\t\tvlan_hdr_to_be32(action);\n+\t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_JUMP:\n \t\t\tjump_group = ((const struct rte_flow_action_jump *)\n \t\t\t\t\t\taction->conf)->group;\n@@ -1835,10 +1924,16 @@ flow_hw_actions_construct(struct rte_eth_dev *dev,\n \t\t\t\t    act_data->encap.len);\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:\n-\t\t\tret = flow_hw_modify_field_construct(job,\n-\t\t\t\t\t\t\t     act_data,\n-\t\t\t\t\t\t\t     hw_acts,\n-\t\t\t\t\t\t\t     action);\n+\t\t\tif (action->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID)\n+\t\t\t\tret = flow_hw_set_vlan_vid_construct(dev, job,\n+\t\t\t\t\t\t\t\t     act_data,\n+\t\t\t\t\t\t\t\t     hw_acts,\n+\t\t\t\t\t\t\t\t     action);\n+\t\t\telse\n+\t\t\t\tret = flow_hw_modify_field_construct(job,\n+\t\t\t\t\t\t\t\t     act_data,\n+\t\t\t\t\t\t\t\t     hw_acts,\n+\t\t\t\t\t\t\t\t     action);\n \t\t\tif (ret)\n \t\t\t\treturn -1;\n \t\t\tbreak;\n@@ -2540,9 +2635,14 @@ flow_hw_table_create(struct rte_eth_dev *dev,\n \t\t\tmlx5_ipool_destroy(tbl->flow);\n \t\tmlx5_free(tbl);\n \t}\n-\trte_flow_error_set(error, err,\n-\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t  \"fail to create rte table\");\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}\n \treturn NULL;\n }\n \n@@ -2827,28 +2927,76 @@ flow_hw_action_meta_copy_insert(const struct rte_flow_action actions[],\n \t\t\t\tuint16_t *ins_pos)\n {\n \tuint16_t idx, total = 0;\n-\tbool ins = false;\n+\tuint16_t end_idx = UINT16_MAX;\n \tbool act_end = false;\n+\tbool modify_field = false;\n+\tbool rss_or_queue = false;\n \n \tMLX5_ASSERT(actions && masks);\n \tMLX5_ASSERT(new_actions && new_masks);\n \tMLX5_ASSERT(ins_actions && ins_masks);\n \tfor (idx = 0; !act_end; idx++) {\n-\t\tif (idx >= MLX5_HW_MAX_ACTS)\n-\t\t\treturn -1;\n-\t\tif (actions[idx].type == RTE_FLOW_ACTION_TYPE_RSS ||\n-\t\t    actions[idx].type == RTE_FLOW_ACTION_TYPE_QUEUE) {\n-\t\t\tins = true;\n-\t\t\t*ins_pos = idx;\n-\t\t}\n-\t\tif (actions[idx].type == RTE_FLOW_ACTION_TYPE_END)\n+\t\tswitch (actions[idx].type) {\n+\t\tcase RTE_FLOW_ACTION_TYPE_RSS:\n+\t\tcase RTE_FLOW_ACTION_TYPE_QUEUE:\n+\t\t\t/* It is assumed that application provided only single RSS/QUEUE action. */\n+\t\t\tMLX5_ASSERT(!rss_or_queue);\n+\t\t\trss_or_queue = true;\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:\n+\t\t\tmodify_field = true;\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_END:\n+\t\t\tend_idx = idx;\n \t\t\tact_end = true;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n \t}\n-\tif (!ins)\n+\tif (!rss_or_queue)\n \t\treturn 0;\n-\telse if (idx == MLX5_HW_MAX_ACTS)\n+\telse if (idx >= MLX5_HW_MAX_ACTS)\n \t\treturn -1; /* No more space. */\n \ttotal = idx;\n+\t/*\n+\t * If actions template contains MODIFY_FIELD action, then meta copy action can be inserted\n+\t * at the template's end. Position of MODIFY_HDR action is based on the position of the\n+\t * first MODIFY_FIELD flow action.\n+\t */\n+\tif (modify_field) {\n+\t\t*ins_pos = end_idx;\n+\t\tgoto insert_meta_copy;\n+\t}\n+\t/*\n+\t * If actions template does not contain MODIFY_FIELD action, then meta copy action must be\n+\t * inserted at aplace conforming with action order defined in steering/mlx5dr_action.c.\n+\t */\n+\tact_end = false;\n+\tfor (idx = 0; !act_end; idx++) {\n+\t\tswitch (actions[idx].type) {\n+\t\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n+\t\tcase RTE_FLOW_ACTION_TYPE_METER:\n+\t\tcase RTE_FLOW_ACTION_TYPE_METER_MARK:\n+\t\tcase RTE_FLOW_ACTION_TYPE_CONNTRACK:\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_RAW_ENCAP:\n+\t\tcase RTE_FLOW_ACTION_TYPE_RSS:\n+\t\tcase RTE_FLOW_ACTION_TYPE_QUEUE:\n+\t\t\t*ins_pos = idx;\n+\t\t\tact_end = true;\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_END:\n+\t\t\tact_end = true;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+insert_meta_copy:\n+\tMLX5_ASSERT(*ins_pos != UINT16_MAX);\n+\tMLX5_ASSERT(*ins_pos < total);\n \t/* Before the position, no change for the actions. */\n \tfor (idx = 0; idx < *ins_pos; idx++) {\n \t\tnew_actions[idx] = actions[idx];\n@@ -2865,6 +3013,73 @@ flow_hw_action_meta_copy_insert(const struct rte_flow_action actions[],\n \treturn 0;\n }\n \n+static int\n+flow_hw_validate_action_push_vlan(struct rte_eth_dev *dev,\n+\t\t\t\t  const\n+\t\t\t\t  struct rte_flow_actions_template_attr *attr,\n+\t\t\t\t  const struct rte_flow_action *action,\n+\t\t\t\t  const struct rte_flow_action *mask,\n+\t\t\t\t  struct rte_flow_error *error)\n+{\n+#define X_FIELD(ptr, t, f) (((ptr)->conf) && ((t *)((ptr)->conf))->f)\n+\n+\tconst bool masked_push =\n+\t\tX_FIELD(mask + MLX5_HW_VLAN_PUSH_TYPE_IDX,\n+\t\t\tconst struct rte_flow_action_of_push_vlan, ethertype);\n+\tbool masked_param;\n+\n+\t/*\n+\t * Mandatory actions order:\n+\t * OF_PUSH_VLAN / OF_SET_VLAN_VID [ / OF_SET_VLAN_PCP ]\n+\t */\n+\tRTE_SET_USED(dev);\n+\tRTE_SET_USED(attr);\n+\t/* Check that mark matches OF_PUSH_VLAN */\n+\tif (mask[MLX5_HW_VLAN_PUSH_TYPE_IDX].type !=\n+\t    RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t  action, \"OF_PUSH_VLAN: mask does not match\");\n+\t/* Check that the second template and mask items are SET_VLAN_VID */\n+\tif (action[MLX5_HW_VLAN_PUSH_VID_IDX].type !=\n+\t    RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID ||\n+\t    mask[MLX5_HW_VLAN_PUSH_VID_IDX].type !=\n+\t    RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t  action, \"OF_PUSH_VLAN: invalid actions order\");\n+\tmasked_param = X_FIELD(mask + MLX5_HW_VLAN_PUSH_VID_IDX,\n+\t\t\t       const struct rte_flow_action_of_set_vlan_vid,\n+\t\t\t       vlan_vid);\n+\t/*\n+\t * PMD requires OF_SET_VLAN_VID mask to must match OF_PUSH_VLAN\n+\t */\n+\tif (masked_push ^ masked_param)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, action,\n+\t\t\t\t\t  \"OF_SET_VLAN_VID: mask does not match OF_PUSH_VLAN\");\n+\tif (is_of_vlan_pcp_present(action)) {\n+\t\tif (mask[MLX5_HW_VLAN_PUSH_PCP_IDX].type !=\n+\t\t     RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP)\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t\t  action, \"OF_SET_VLAN_PCP: missing mask configuration\");\n+\t\tmasked_param = X_FIELD(mask + MLX5_HW_VLAN_PUSH_PCP_IDX,\n+\t\t\t\t       const struct\n+\t\t\t\t       rte_flow_action_of_set_vlan_pcp,\n+\t\t\t\t       vlan_pcp);\n+\t\t/*\n+\t\t * PMD requires OF_SET_VLAN_PCP mask to must match OF_PUSH_VLAN\n+\t\t */\n+\t\tif (masked_push ^ masked_param)\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, action,\n+\t\t\t\t\t\t  \"OF_SET_VLAN_PCP: mask does not match OF_PUSH_VLAN\");\n+\t}\n+\treturn 0;\n+#undef X_FIELD\n+}\n+\n static int\n flow_hw_actions_validate(struct rte_eth_dev *dev,\n \t\t\tconst struct rte_flow_actions_template_attr *attr,\n@@ -2955,6 +3170,18 @@ flow_hw_actions_validate(struct rte_eth_dev *dev,\n \t\tcase RTE_FLOW_ACTION_TYPE_CONNTRACK:\n \t\t\t/* TODO: Validation logic */\n \t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:\n+\t\tcase RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:\n+\t\t\tret = flow_hw_validate_action_push_vlan\n+\t\t\t\t\t(dev, attr, action, mask, error);\n+\t\t\tif (ret != 0)\n+\t\t\t\treturn ret;\n+\t\t\ti += is_of_vlan_pcp_present(action) ?\n+\t\t\t\tMLX5_HW_VLAN_PUSH_PCP_IDX :\n+\t\t\t\tMLX5_HW_VLAN_PUSH_VID_IDX;\n+\t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_END:\n \t\t\tactions_end = true;\n \t\t\tbreak;\n@@ -2982,6 +3209,8 @@ static enum mlx5dr_action_type mlx5_hw_dr_action_types[] = {\n \t[RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT] = MLX5DR_ACTION_TYP_VPORT,\n \t[RTE_FLOW_ACTION_TYPE_COUNT] = MLX5DR_ACTION_TYP_CTR,\n \t[RTE_FLOW_ACTION_TYPE_CONNTRACK] = MLX5DR_ACTION_TYP_ASO_CT,\n+\t[RTE_FLOW_ACTION_TYPE_OF_POP_VLAN] = MLX5DR_ACTION_TYP_POP_VLAN,\n+\t[RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = MLX5DR_ACTION_TYP_PUSH_VLAN,\n };\n \n static int\n@@ -3098,6 +3327,14 @@ flow_hw_dr_actions_template_create(struct rte_flow_actions_template *at)\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\tcase RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:\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\ti += is_of_vlan_pcp_present(at->actions + i) ?\n+\t\t\t\tMLX5_HW_VLAN_PUSH_PCP_IDX :\n+\t\t\t\tMLX5_HW_VLAN_PUSH_VID_IDX;\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@@ -3125,6 +3362,89 @@ flow_hw_dr_actions_template_create(struct rte_flow_actions_template *at)\n \treturn NULL;\n }\n \n+static void\n+flow_hw_set_vlan_vid(struct rte_eth_dev *dev,\n+\t\t     struct rte_flow_action *ra,\n+\t\t     struct rte_flow_action *rm,\n+\t\t     struct rte_flow_action_modify_field *spec,\n+\t\t     struct rte_flow_action_modify_field *mask,\n+\t\t     int set_vlan_vid_ix)\n+{\n+\tstruct rte_flow_error error;\n+\tconst bool masked = rm[set_vlan_vid_ix].conf &&\n+\t\t(((const struct rte_flow_action_of_set_vlan_vid *)\n+\t\t\trm[set_vlan_vid_ix].conf)->vlan_vid != 0);\n+\tconst struct rte_flow_action_of_set_vlan_vid *conf =\n+\t\tra[set_vlan_vid_ix].conf;\n+\trte_be16_t vid = masked ? conf->vlan_vid : 0;\n+\tint width = mlx5_flow_item_field_width(dev, RTE_FLOW_FIELD_VLAN_ID, 0,\n+\t\t\t\t\t       NULL, &error);\n+\t*spec = (typeof(*spec)) {\n+\t\t.operation = RTE_FLOW_MODIFY_SET,\n+\t\t.dst = {\n+\t\t\t.field = RTE_FLOW_FIELD_VLAN_ID,\n+\t\t\t.level = 0, .offset = 0,\n+\t\t},\n+\t\t.src = {\n+\t\t\t.field = RTE_FLOW_FIELD_VALUE,\n+\t\t\t.level = vid,\n+\t\t\t.offset = 0,\n+\t\t},\n+\t\t.width = width,\n+\t};\n+\t*mask = (typeof(*mask)) {\n+\t\t.operation = RTE_FLOW_MODIFY_SET,\n+\t\t.dst = {\n+\t\t\t.field = RTE_FLOW_FIELD_VLAN_ID,\n+\t\t\t.level = 0xffffffff, .offset = 0xffffffff,\n+\t\t},\n+\t\t.src = {\n+\t\t\t.field = RTE_FLOW_FIELD_VALUE,\n+\t\t\t.level = masked ? (1U << width) - 1 : 0,\n+\t\t\t.offset = 0,\n+\t\t},\n+\t\t.width = 0xffffffff,\n+\t};\n+\tra[set_vlan_vid_ix].type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD;\n+\tra[set_vlan_vid_ix].conf = spec;\n+\trm[set_vlan_vid_ix].type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD;\n+\trm[set_vlan_vid_ix].conf = mask;\n+}\n+\n+static __rte_always_inline int\n+flow_hw_set_vlan_vid_construct(struct rte_eth_dev *dev,\n+\t\t\t       struct mlx5_hw_q_job *job,\n+\t\t\t       struct mlx5_action_construct_data *act_data,\n+\t\t\t       const struct mlx5_hw_actions *hw_acts,\n+\t\t\t       const struct rte_flow_action *action)\n+{\n+\tstruct rte_flow_error error;\n+\trte_be16_t vid = ((const struct rte_flow_action_of_set_vlan_vid *)\n+\t\t\t   action->conf)->vlan_vid;\n+\tint width = mlx5_flow_item_field_width(dev, RTE_FLOW_FIELD_VLAN_ID, 0,\n+\t\t\t\t\t       NULL, &error);\n+\tstruct rte_flow_action_modify_field conf = {\n+\t\t.operation = RTE_FLOW_MODIFY_SET,\n+\t\t.dst = {\n+\t\t\t.field = RTE_FLOW_FIELD_VLAN_ID,\n+\t\t\t.level = 0, .offset = 0,\n+\t\t},\n+\t\t.src = {\n+\t\t\t.field = RTE_FLOW_FIELD_VALUE,\n+\t\t\t.level = vid,\n+\t\t\t.offset = 0,\n+\t\t},\n+\t\t.width = width,\n+\t};\n+\tstruct rte_flow_action modify_action = {\n+\t\t.type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,\n+\t\t.conf = &conf\n+\t};\n+\n+\treturn flow_hw_modify_field_construct(job, act_data, hw_acts,\n+\t\t\t\t\t      &modify_action);\n+}\n+\n /**\n  * Create flow action template.\n  *\n@@ -3150,14 +3470,18 @@ 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_num, act_len, mask_len;\n+\tint len, act_len, mask_len;\n+\tunsigned int act_num;\n \tunsigned int i;\n \tstruct rte_flow_actions_template *at = NULL;\n-\tuint16_t pos = MLX5_HW_MAX_ACTS;\n+\tuint16_t pos = UINT16_MAX;\n \tstruct rte_flow_action tmp_action[MLX5_HW_MAX_ACTS];\n \tstruct rte_flow_action tmp_mask[MLX5_HW_MAX_ACTS];\n-\tconst struct rte_flow_action *ra;\n-\tconst struct rte_flow_action *rm;\n+\tstruct rte_flow_action *ra = (void *)(uintptr_t)actions;\n+\tstruct rte_flow_action *rm = (void *)(uintptr_t)masks;\n+\tint set_vlan_vid_ix = -1;\n+\tstruct rte_flow_action_modify_field set_vlan_vid_spec = {0, };\n+\tstruct rte_flow_action_modify_field set_vlan_vid_mask = {0, };\n \tconst struct rte_flow_action_modify_field rx_mreg = {\n \t\t.operation = RTE_FLOW_MODIFY_SET,\n \t\t.dst = {\n@@ -3197,21 +3521,58 @@ flow_hw_actions_template_create(struct rte_eth_dev *dev,\n \t\treturn NULL;\n \tif (priv->sh->config.dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS &&\n \t    priv->sh->config.dv_esw_en) {\n+\t\t/* Application should make sure only one Q/RSS exist in one rule. */\n \t\tif (flow_hw_action_meta_copy_insert(actions, masks, &rx_cpy, &rx_cpy_mask,\n \t\t\t\t\t\t    tmp_action, tmp_mask, &pos)) {\n \t\t\trte_flow_error_set(error, EINVAL,\n \t\t\t\t\t   RTE_FLOW_ERROR_TYPE_ACTION, NULL,\n \t\t\t\t\t   \"Failed to concatenate new action/mask\");\n \t\t\treturn NULL;\n+\t\t} else if (pos != UINT16_MAX) {\n+\t\t\tra = tmp_action;\n+\t\t\trm = tmp_mask;\n \t\t}\n \t}\n-\t/* Application should make sure only one Q/RSS exist in one rule. */\n-\tif (pos == MLX5_HW_MAX_ACTS) {\n-\t\tra = actions;\n-\t\trm = masks;\n-\t} else {\n-\t\tra = tmp_action;\n-\t\trm = tmp_mask;\n+\tfor (i = 0; ra[i].type != RTE_FLOW_ACTION_TYPE_END; ++i) {\n+\t\tswitch (ra[i].type) {\n+\t\t/* OF_PUSH_VLAN *MUST* come before OF_SET_VLAN_VID */\n+\t\tcase RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:\n+\t\t\ti += is_of_vlan_pcp_present(ra + i) ?\n+\t\t\t\tMLX5_HW_VLAN_PUSH_PCP_IDX :\n+\t\t\t\tMLX5_HW_VLAN_PUSH_VID_IDX;\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:\n+\t\t\tset_vlan_vid_ix = i;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\t/*\n+\t * Count flow actions to allocate required space for storing DR offsets and to check\n+\t * if temporary buffer would not be overrun.\n+\t */\n+\tact_num = i + 1;\n+\tif (act_num >= MLX5_HW_MAX_ACTS) {\n+\t\trte_flow_error_set(error, EINVAL,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_ACTION, NULL, \"Too many actions\");\n+\t\treturn NULL;\n+\t}\n+\tif (set_vlan_vid_ix != -1) {\n+\t\t/* If temporary action buffer was not used, copy template actions to it */\n+\t\tif (ra == actions && rm == masks) {\n+\t\t\tfor (i = 0; i < act_num; ++i) {\n+\t\t\t\ttmp_action[i] = actions[i];\n+\t\t\t\ttmp_mask[i] = masks[i];\n+\t\t\t\tif (actions[i].type == RTE_FLOW_ACTION_TYPE_END)\n+\t\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tra = tmp_action;\n+\t\t\trm = tmp_mask;\n+\t\t}\n+\t\tflow_hw_set_vlan_vid(dev, ra, rm,\n+\t\t\t\t     &set_vlan_vid_spec, &set_vlan_vid_mask,\n+\t\t\t\t     set_vlan_vid_ix);\n \t}\n \tact_len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, ra, error);\n \tif (act_len <= 0)\n@@ -3221,10 +3582,6 @@ 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@@ -4475,7 +4832,11 @@ flow_hw_create_tx_default_mreg_copy_table(struct rte_eth_dev *dev,\n \t\t.attr = tx_tbl_attr,\n \t\t.external = false,\n \t};\n-\tstruct rte_flow_error drop_err;\n+\tstruct rte_flow_error drop_err = {\n+\t\t.type = RTE_FLOW_ERROR_TYPE_NONE,\n+\t\t.cause = NULL,\n+\t\t.message = NULL,\n+\t};\n \n \tRTE_SET_USED(drop_err);\n \treturn flow_hw_table_create(dev, &tx_tbl_cfg, &pt, 1, &at, 1, &drop_err);\n@@ -4756,6 +5117,60 @@ flow_hw_ct_pool_create(struct rte_eth_dev *dev,\n \treturn NULL;\n }\n \n+static void\n+flow_hw_destroy_vlan(struct rte_eth_dev *dev)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tenum mlx5dr_table_type i;\n+\n+\tfor (i = MLX5DR_TABLE_TYPE_NIC_RX; i < MLX5DR_TABLE_TYPE_MAX; i++) {\n+\t\tif (priv->hw_pop_vlan[i]) {\n+\t\t\tmlx5dr_action_destroy(priv->hw_pop_vlan[i]);\n+\t\t\tpriv->hw_pop_vlan[i] = NULL;\n+\t\t}\n+\t\tif (priv->hw_push_vlan[i]) {\n+\t\t\tmlx5dr_action_destroy(priv->hw_push_vlan[i]);\n+\t\t\tpriv->hw_push_vlan[i] = NULL;\n+\t\t}\n+\t}\n+}\n+\n+static int\n+flow_hw_create_vlan(struct rte_eth_dev *dev)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tenum mlx5dr_table_type i;\n+\tconst enum mlx5dr_action_flags flags[MLX5DR_TABLE_TYPE_MAX] = {\n+\t\tMLX5DR_ACTION_FLAG_HWS_RX,\n+\t\tMLX5DR_ACTION_FLAG_HWS_TX,\n+\t\tMLX5DR_ACTION_FLAG_HWS_FDB\n+\t};\n+\n+\tfor (i = MLX5DR_TABLE_TYPE_NIC_RX; i <= MLX5DR_TABLE_TYPE_NIC_TX; i++) {\n+\t\tpriv->hw_pop_vlan[i] =\n+\t\t\tmlx5dr_action_create_pop_vlan(priv->dr_ctx, flags[i]);\n+\t\tif (!priv->hw_pop_vlan[i])\n+\t\t\treturn -ENOENT;\n+\t\tpriv->hw_push_vlan[i] =\n+\t\t\tmlx5dr_action_create_push_vlan(priv->dr_ctx, flags[i]);\n+\t\tif (!priv->hw_pop_vlan[i])\n+\t\t\treturn -ENOENT;\n+\t}\n+\tif (priv->sh->config.dv_esw_en && priv->master) {\n+\t\tpriv->hw_pop_vlan[MLX5DR_TABLE_TYPE_FDB] =\n+\t\t\tmlx5dr_action_create_pop_vlan\n+\t\t\t\t(priv->dr_ctx, MLX5DR_ACTION_FLAG_HWS_FDB);\n+\t\tif (!priv->hw_pop_vlan[MLX5DR_TABLE_TYPE_FDB])\n+\t\t\treturn -ENOENT;\n+\t\tpriv->hw_push_vlan[MLX5DR_TABLE_TYPE_FDB] =\n+\t\t\tmlx5dr_action_create_push_vlan\n+\t\t\t\t(priv->dr_ctx, MLX5DR_ACTION_FLAG_HWS_FDB);\n+\t\tif (!priv->hw_pop_vlan[MLX5DR_TABLE_TYPE_FDB])\n+\t\t\treturn -ENOENT;\n+\t}\n+\treturn 0;\n+}\n+\n /**\n  * Configure port HWS resources.\n  *\n@@ -4961,6 +5376,9 @@ flow_hw_configure(struct rte_eth_dev *dev,\n \t\tif (priv->hws_cpool == NULL)\n \t\t\tgoto err;\n \t}\n+\tret = flow_hw_create_vlan(dev);\n+\tif (ret)\n+\t\tgoto err;\n \treturn 0;\n err:\n \tif (priv->hws_ctpool) {\n@@ -4978,6 +5396,7 @@ flow_hw_configure(struct rte_eth_dev *dev,\n \t\tif (priv->hw_tag[i])\n \t\t\tmlx5dr_action_destroy(priv->hw_tag[i]);\n \t}\n+\tflow_hw_destroy_vlan(dev);\n \tif (dr_ctx)\n \t\tclaim_zero(mlx5dr_context_close(dr_ctx));\n \tmlx5_free(priv->hw_q);\n@@ -5037,6 +5456,7 @@ flow_hw_resource_release(struct rte_eth_dev *dev)\n \t\tif (priv->hw_tag[i])\n \t\t\tmlx5dr_action_destroy(priv->hw_tag[i]);\n \t}\n+\tflow_hw_destroy_vlan(dev);\n \tflow_hw_free_vport_actions(priv);\n \tif (priv->acts_ipool) {\n \t\tmlx5_ipool_destroy(priv->acts_ipool);\n",
    "prefixes": [
        "v2",
        "11/17"
    ]
}