get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 65489,
    "url": "http://patches.dpdk.org/api/patches/65489/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1580736735-19472-5-git-send-email-bingz@mellanox.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": "<1580736735-19472-5-git-send-email-bingz@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1580736735-19472-5-git-send-email-bingz@mellanox.com",
    "date": "2020-02-03T13:32:13",
    "name": "[4/6] net/mlx5: introduce handle structure for DV flows",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "02f2e2e30f709c3218f6435023384c3cf9f32308",
    "submitter": {
        "id": 1357,
        "url": "http://patches.dpdk.org/api/people/1357/?format=api",
        "name": "Bing Zhao",
        "email": "bingz@mellanox.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/1580736735-19472-5-git-send-email-bingz@mellanox.com/mbox/",
    "series": [
        {
            "id": 8396,
            "url": "http://patches.dpdk.org/api/series/8396/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=8396",
            "date": "2020-02-03T13:32:09",
            "name": "net/mlx5: move to non-cached mode for flow rules",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/8396/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/65489/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/65489/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 dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 9E55EA052E;\n\tMon,  3 Feb 2020 14:33:05 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id DCD9F1C01F;\n\tMon,  3 Feb 2020 14:32:40 +0100 (CET)",
            "from git-send-mailer.rdmz.labs.mlnx (unknown [37.142.13.130])\n by dpdk.org (Postfix) with ESMTP id A402A1C00F\n for <dev@dpdk.org>; Mon,  3 Feb 2020 14:32:38 +0100 (CET)"
        ],
        "From": "Bing Zhao <bingz@mellanox.com>",
        "To": "orika@mellanox.com, viacheslavo@mellanox.com, rasland@mellanox.com,\n matan@mellanox.com",
        "Cc": "dev@dpdk.org",
        "Date": "Mon,  3 Feb 2020 15:32:13 +0200",
        "Message-Id": "<1580736735-19472-5-git-send-email-bingz@mellanox.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1580736735-19472-1-git-send-email-bingz@mellanox.com>",
        "References": "<1580736735-19472-1-git-send-email-bingz@mellanox.com>",
        "Subject": "[dpdk-dev] [PATCH 4/6] net/mlx5: introduce handle structure for DV\n\tflows",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "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",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Introduce a new structure \"mlx5_flow_dv_handle\" based on device flow\nstructures \"mlx5_flow\" and \"mlx5_flow_dv\", and in the meanwhile, the\n\"mlx5_flow\" is kept for Verbs flow.\nOnly the matchers and actions objects will be saved in order to free\nsuch resource when destroying a flow. The other information will be\nstored by using some intermediate global variables that can be reused\nfor all flows when being created.\nInbox OFED driver should also be taken into consideration.\n\nSigned-off-by: Bing Zhao <bingz@mellanox.com>\n---\n drivers/net/mlx5/mlx5_flow.c    | 184 +++++++++++++++++++-----\n drivers/net/mlx5/mlx5_flow.h    |  40 +++++-\n drivers/net/mlx5/mlx5_flow_dv.c | 310 +++++++++++++++++++++-------------------\n 3 files changed, 350 insertions(+), 184 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex 8fb973b..1121904 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -709,19 +709,42 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n  *\n  * @param[in] dev\n  *   Pointer to the Ethernet device structure.\n- * @param[in] dev_flow\n- *   Pointer to device flow structure.\n+ * @param[in] type\n+ *   Driver type of the RTE flow.\n+ * @param[in] sub_flow\n+ *   Pointer to device flow or flow handle structure.\n  */\n static void\n-flow_drv_rxq_flags_set(struct rte_eth_dev *dev, struct mlx5_flow *dev_flow)\n+flow_drv_rxq_flags_set(struct rte_eth_dev *dev,\n+\t\t       enum mlx5_flow_drv_type type __rte_unused,\n+\t\t       void *sub_flow)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct rte_flow *flow = dev_flow->flow;\n-\tconst int mark = !!(dev_flow->actions &\n-\t\t\t    (MLX5_FLOW_ACTION_FLAG | MLX5_FLOW_ACTION_MARK));\n-\tconst int tunnel = !!(dev_flow->layers & MLX5_FLOW_LAYER_TUNNEL);\n+\tstruct rte_flow *flow;\n+\tint mark;\n+\tint tunnel;\n+\tuint64_t layers;\n \tunsigned int i;\n \n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\tif (type == MLX5_FLOW_TYPE_DV) {\n+\t\tstruct mlx5_flow_dv_handle *handle = sub_flow;\n+\t\tmark = !!(handle->action_flags &\n+\t\t\t    (MLX5_FLOW_ACTION_FLAG | MLX5_FLOW_ACTION_MARK));\n+\t\tlayers = handle->layers;\n+\t\ttunnel = !!(layers & MLX5_FLOW_LAYER_TUNNEL);\n+\t\tflow = handle->m_flow;\n+\t} else {\n+#endif\n+\t\tstruct mlx5_flow *dev_flow = sub_flow;\n+\t\tmark = !!(dev_flow->actions &\n+\t\t\t    (MLX5_FLOW_ACTION_FLAG | MLX5_FLOW_ACTION_MARK));\n+\t\tlayers = dev_flow->layers;\n+\t\ttunnel = !!(dev_flow->layers & MLX5_FLOW_LAYER_TUNNEL);\n+\t\tflow = dev_flow->flow;\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\t}\n+#endif\n \tfor (i = 0; i != flow->rss.queue_num; ++i) {\n \t\tint idx = (*flow->rss.queue)[i];\n \t\tstruct mlx5_rxq_ctrl *rxq_ctrl =\n@@ -747,8 +770,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \n \t\t\t/* Increase the counter matching the flow. */\n \t\t\tfor (j = 0; j != MLX5_FLOW_TUNNEL; ++j) {\n-\t\t\t\tif ((tunnels_info[j].tunnel &\n-\t\t\t\t     dev_flow->layers) ==\n+\t\t\t\tif ((tunnels_info[j].tunnel & layers) ==\n \t\t\t\t    tunnels_info[j].tunnel) {\n \t\t\t\t\trxq_ctrl->flow_tunnels_n[j]++;\n \t\t\t\t\tbreak;\n@@ -771,9 +793,17 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n flow_rxq_flags_set(struct rte_eth_dev *dev, struct rte_flow *flow)\n {\n \tstruct mlx5_flow *dev_flow;\n+\tenum mlx5_flow_drv_type type = flow->drv_type;\n \n-\tLIST_FOREACH(dev_flow, &flow->dev_flows, next)\n-\t\tflow_drv_rxq_flags_set(dev, dev_flow);\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\tstruct mlx5_flow_dv_handle *handle;\n+\tif (type == MLX5_FLOW_TYPE_DV)\n+\t\tSLIST_FOREACH(handle, &flow->handles, next)\n+\t\t\tflow_drv_rxq_flags_set(dev, type, (void *)handle);\n+\telse\n+#endif\n+\t\tLIST_FOREACH(dev_flow, &flow->dev_flows, next)\n+\t\t\tflow_drv_rxq_flags_set(dev, type, (void *)dev_flow);\n }\n \n /**\n@@ -782,20 +812,44 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n  *\n  * @param dev\n  *   Pointer to Ethernet device.\n- * @param[in] dev_flow\n- *   Pointer to the device flow.\n+ * @param[in] type\n+ *   Driver type of the RTE flow.\n+ * @param[in] sub_flow\n+ *   Pointer to device flow or flow handle structure.\n+\n  */\n static void\n-flow_drv_rxq_flags_trim(struct rte_eth_dev *dev, struct mlx5_flow *dev_flow)\n+flow_drv_rxq_flags_trim(struct rte_eth_dev *dev,\n+\t\t\tenum mlx5_flow_drv_type type __rte_unused,\n+\t\t\tvoid *sub_flow)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct rte_flow *flow = dev_flow->flow;\n-\tconst int mark = !!(dev_flow->actions &\n-\t\t\t    (MLX5_FLOW_ACTION_FLAG | MLX5_FLOW_ACTION_MARK));\n-\tconst int tunnel = !!(dev_flow->layers & MLX5_FLOW_LAYER_TUNNEL);\n+\tstruct rte_flow *flow;\n+\tint mark;\n+\tint tunnel;\n+\tuint64_t layers;\n \tunsigned int i;\n \n \tMLX5_ASSERT(dev->data->dev_started);\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\tif (type == MLX5_FLOW_TYPE_DV) {\n+\t\tstruct mlx5_flow_dv_handle *handle = sub_flow;\n+\t\tmark = !!(handle->action_flags &\n+\t\t\t    (MLX5_FLOW_ACTION_FLAG | MLX5_FLOW_ACTION_MARK));\n+\t\tlayers = handle->layers;\n+\t\ttunnel = !!(layers & MLX5_FLOW_LAYER_TUNNEL);\n+\t\tflow = handle->m_flow;\n+\t} else {\n+#endif\n+\t\tstruct mlx5_flow *dev_flow = sub_flow;\n+\t\tmark = !!(dev_flow->actions &\n+\t\t\t    (MLX5_FLOW_ACTION_FLAG | MLX5_FLOW_ACTION_MARK));\n+\t\tlayers = dev_flow->layers;\n+\t\ttunnel = !!(layers & MLX5_FLOW_LAYER_TUNNEL);\n+\t\tflow = dev_flow->flow;\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\t}\n+#endif\n \tfor (i = 0; i != flow->rss.queue_num; ++i) {\n \t\tint idx = (*flow->rss.queue)[i];\n \t\tstruct mlx5_rxq_ctrl *rxq_ctrl =\n@@ -816,8 +870,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \n \t\t\t/* Decrease the counter matching the flow. */\n \t\t\tfor (j = 0; j != MLX5_FLOW_TUNNEL; ++j) {\n-\t\t\t\tif ((tunnels_info[j].tunnel &\n-\t\t\t\t     dev_flow->layers) ==\n+\t\t\t\tif ((tunnels_info[j].tunnel & layers) ==\n \t\t\t\t    tunnels_info[j].tunnel) {\n \t\t\t\t\trxq_ctrl->flow_tunnels_n[j]--;\n \t\t\t\t\tbreak;\n@@ -841,9 +894,17 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n flow_rxq_flags_trim(struct rte_eth_dev *dev, struct rte_flow *flow)\n {\n \tstruct mlx5_flow *dev_flow;\n+\tenum mlx5_flow_drv_type type = flow->drv_type;\n \n-\tLIST_FOREACH(dev_flow, &flow->dev_flows, next)\n-\t\tflow_drv_rxq_flags_trim(dev, dev_flow);\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\tstruct mlx5_flow_dv_handle *handle;\n+\tif (type == MLX5_FLOW_TYPE_DV)\n+\t\tSLIST_FOREACH(handle, &flow->handles, next)\n+\t\t\tflow_drv_rxq_flags_trim(dev, type, (void *)handle);\n+\telse\n+#endif\n+\t\tLIST_FOREACH(dev_flow, &flow->dev_flows, next)\n+\t\t\tflow_drv_rxq_flags_trim(dev, type, (void *)dev_flow);\n }\n \n /**\n@@ -2341,10 +2402,22 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \t\t\t     struct rte_flow *flow)\n {\n \tstruct mlx5_flow *dev_flow;\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\tstruct mlx5_flow_dv_handle *handle;\n+\tenum mlx5_flow_drv_type type = flow->drv_type;\n \n-\tLIST_FOREACH(dev_flow, &flow->dev_flows, next)\n-\t\tif (dev_flow->qrss_id)\n-\t\t\tflow_qrss_free_id(dev, dev_flow->qrss_id);\n+\tif (type == MLX5_FLOW_TYPE_DV) {\n+\t\tSLIST_FOREACH(handle, &flow->handles, next)\n+\t\t\tif (handle->qrss_id)\n+\t\t\t\tflow_qrss_free_id(dev, handle->qrss_id);\n+\t} else {\n+#endif\n+\t\tLIST_FOREACH(dev_flow, &flow->dev_flows, next)\n+\t\t\tif (dev_flow->qrss_id)\n+\t\t\t\tflow_qrss_free_id(dev, dev_flow->qrss_id);\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\t}\n+#endif\n }\n \n static int\n@@ -3434,10 +3507,20 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \tdev_flow = flow_drv_prepare(flow, attr, items, actions, error);\n \tif (!dev_flow)\n \t\treturn -rte_errno;\n-\tdev_flow->flow = flow;\n \tdev_flow->external = external;\n-\t/* Subflow object was created, we must include one in the list. */\n-\tLIST_INSERT_HEAD(&flow->dev_flows, dev_flow, next);\n+\tdev_flow->flow = flow;\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\tif (flow->drv_type == MLX5_FLOW_TYPE_DV) {\n+\t\tSLIST_INSERT_HEAD(&flow->handles, dev_flow->dv_handle, next);\n+\t\tdev_flow->dv_handle->sidx = flow->sub_flows++;\n+\t\tdev_flow->dv_handle->m_flow = flow;\n+\t} else {\n+#endif\n+\t\t/* Subflow obj was created, we must include one in the list. */\n+\t\tLIST_INSERT_HEAD(&flow->dev_flows, dev_flow, next);\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\t}\n+#endif\n \tif (sub_flow)\n \t\t*sub_flow = dev_flow;\n \treturn flow_drv_translate(dev, dev_flow, attr, items, actions, error);\n@@ -3900,6 +3983,10 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \t\t\t * other flows in other threads).\n \t\t\t */\n \t\t\tdev_flow->qrss_id = qrss_id;\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\t\t\tif (flow->drv_type == MLX5_FLOW_TYPE_DV)\n+\t\t\t\tdev_flow->dv_handle->qrss_id = qrss_id;\n+#endif\n \t\t\tqrss_id = 0;\n \t\t\tret = mlx5_flow_get_reg_id(dev, MLX5_COPY_MARK, 0,\n \t\t\t\t\t\t   error);\n@@ -4012,6 +4099,10 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \t\t\tgoto exit;\n \t\t}\n \t\tdev_flow->mtr_flow_id = mtr_tag_id;\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\t\tif (flow->drv_type == MLX5_FLOW_TYPE_DV)\n+\t\t\tdev_flow->dv_handle->mtr_flow_id = mtr_tag_id;\n+#endif\n \t\t/* Prepare the suffix flow match pattern. */\n \t\tsfx_items = (struct rte_flow_item *)((char *)sfx_actions +\n \t\t\t     act_size);\n@@ -4164,6 +4255,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \tuint32_t hairpin_id = 0;\n \tstruct rte_flow_attr attr_tx = { .priority = 0 };\n \n+\tMLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);\n \thairpin_flow = flow_check_hairpin_split(dev, attr, actions);\n \tif (hairpin_flow > 0) {\n \t\tif (hairpin_flow > MLX5_MAX_SPLIT_ACTIONS) {\n@@ -4192,10 +4284,9 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \t\tgoto error_before_flow;\n \t}\n \tflow->drv_type = type;\n+\tflow->sub_flows = 0;\n \tif (hairpin_id != 0)\n \t\tflow->hairpin_flow_id = hairpin_id;\n-\tMLX5_ASSERT(flow->drv_type > MLX5_FLOW_TYPE_MIN &&\n-\t\t    flow->drv_type < MLX5_FLOW_TYPE_MAX);\n \tflow->rss.queue = (void *)(flow + 1);\n \tif (rss) {\n \t\t/*\n@@ -4206,7 +4297,10 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \t\t/* RSS type 0 indicates default RSS type (ETH_RSS_IP). */\n \t\tflow->rss.types = !rss->types ? ETH_RSS_IP : rss->types;\n \t}\n-\tLIST_INIT(&flow->dev_flows);\n+\tif (flow->drv_type == MLX5_FLOW_TYPE_DV)\n+\t\tSLIST_INIT(&flow->handles);\n+\telse\n+\t\tLIST_INIT(&flow->dev_flows);\n \tif (rss && rss->types) {\n \t\tunsigned int graph_root;\n \n@@ -4243,9 +4337,20 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \t\t\t\t\t    actions_hairpin_tx.actions, error);\n \t\tif (!dev_flow)\n \t\t\tgoto error;\n-\t\tdev_flow->flow = flow;\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\t\tif (flow->drv_type == MLX5_FLOW_TYPE_DV) {\n+\t\t\tSLIST_INSERT_HEAD(&flow->handles,\n+\t\t\t\t\t  dev_flow->dv_handle, next);\n+\t\t\tdev_flow->dv_handle->sidx = flow->sub_flows++;\n+\t\t\tdev_flow->dv_handle->m_flow = flow;\n+\t\t} else {\n+#endif\n+\t\t\tdev_flow->flow = flow;\n+\t\t\tLIST_INSERT_HEAD(&flow->dev_flows, dev_flow, next);\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\t\t}\n+#endif\n \t\tdev_flow->external = 0;\n-\t\tLIST_INSERT_HEAD(&flow->dev_flows, dev_flow, next);\n \t\tret = flow_drv_translate(dev, dev_flow, &attr_tx,\n \t\t\t\t\t items_tx.items,\n \t\t\t\t\t actions_hairpin_tx.actions, error);\n@@ -4363,8 +4468,17 @@ struct rte_flow *\n \tstruct mlx5_flows *flow_list;\n \tenum mlx5_flow_drv_type type = flow_get_drv_type(dev, attr);\n \n-\tflow_list = (type == MLX5_FLOW_TYPE_DV) ? &priv->noncached_flows :\n-\t\t\t\t\t\t  &priv->cached_flows;\n+\tif (type == MLX5_FLOW_TYPE_DV) {\n+\t\tif (unlikely(!dev->data->dev_started)) {\n+\t\t\trte_errno = ENODEV;\n+\t\t\tDRV_LOG(DEBUG, \"port %u is not started when \"\n+\t\t\t\t\"inserting a flow\", dev->data->port_id);\n+\t\t\treturn NULL;\n+\t\t}\n+\t\tflow_list = &priv->noncached_flows;\n+\t} else {\n+\t\tflow_list = &priv->cached_flows;\n+\t}\n \treturn flow_list_create(dev, flow_list, attr,\n \t\t\t\titems, actions, true, type, error);\n }\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex 7c31bfe..10ac9c3 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -468,6 +468,39 @@ struct mlx5_flow_tbl_data_entry {\n \t/**< jump resource, at most one for each table created. */\n };\n \n+struct mlx5_flow_dv_handle {\n+\tSLIST_ENTRY(mlx5_flow_dv_handle) next;\n+\tstruct rte_flow *m_flow; /**< Pointer to the main flow. */\n+\tuint64_t layers;\n+\t/**< Bit-fields of present layers, see MLX5_FLOW_LAYER_*. */\n+\tuint64_t action_flags;\n+\t/**< Bit-fields of detected actions, see MLX5_FLOW_ACTION_*. */\n+\tstruct mlx5_hrxq *hrxq; /**< Hash Rx queues. */\n+\tstruct mlx5_flow_dv_matcher *matcher; /**< Cache to matcher. */\n+\tstruct mlx5_flow_dv_match_params value;\n+\t/**< Holds the value that the packet is compared to. */\n+\tstruct mlx5_flow_dv_encap_decap_resource *encap_decap;\n+\t/**< Pointer to encap/decap resource in cache. */\n+\tstruct mlx5_flow_dv_modify_hdr_resource *modify_hdr;\n+\t/**< Pointer to modify header resource in cache. */\n+\tstruct mlx5_flow_dv_jump_tbl_resource *jump;\n+\t/**< Pointer to the jump action resource. */\n+\tstruct mlx5_flow_dv_port_id_action_resource *port_id_action;\n+\t/**< Pointer to port ID action resource. */\n+\tstruct mlx5_vf_vlan vf_vlan;\n+\t/**< Structure for VF VLAN workaround. */\n+\tstruct mlx5_flow_dv_push_vlan_action_resource *push_vlan_res;\n+\t/**< Pointer to push VLAN action resource in cache. */\n+\tstruct mlx5_flow_dv_tag_resource *tag_resource;\n+\t/**< pointer to the tag action. */\n+\tstruct ibv_flow *flow; /**< Installed flow. */\n+\tunion {\n+\t\tuint32_t qrss_id; /**< Unique Q/RSS suffix subflow tag. */\n+\t\tuint32_t mtr_flow_id; /**< Unique meter match flow id. */\n+\t};\n+\tuint8_t sidx;\n+};\n+\n /*\n  * Max number of actions per DV flow.\n  * See CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED\n@@ -547,12 +580,12 @@ struct mlx5_flow {\n \tuint8_t transfer; /**< 1 if the flow is E-Switch flow. */\n \tunion {\n #ifdef HAVE_IBV_FLOW_DV_SUPPORT\n-\t\tstruct mlx5_flow_dv dv;\n+\t\tstruct mlx5_flow_dv_handle *dv_handle;\n #endif\n \t\tstruct mlx5_flow_verbs verbs;\n \t};\n \tunion {\n-\t\tuint32_t qrss_id; /**< Uniqie Q/RSS suffix subflow tag. */\n+\t\tuint32_t qrss_id; /**< Unique Q/RSS suffix subflow tag. */\n \t\tuint32_t mtr_flow_id; /**< Unique meter match flow id. */\n \t};\n \tbool external; /**< true if the flow is created external to PMD. */\n@@ -674,6 +707,9 @@ struct rte_flow {\n \tstruct mlx5_fdir *fdir; /**< Pointer to associated FDIR if any. */\n \tuint32_t hairpin_flow_id; /**< The flow id used for hairpin. */\n \tuint32_t copy_applied:1; /**< The MARK copy Flow os applied. */\n+\tSLIST_HEAD(, mlx5_flow_dv_handle) handles;\n+\t/**< The HEAD of DV handles. */\n+\tuint8_t sub_flows;\n };\n \n typedef int (*mlx5_flow_validate_t)(struct rte_eth_dev *dev,\ndiff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex 2878393..2013082 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -75,6 +75,16 @@\n \tuint32_t attr;\n };\n \n+/* Global temporary device flow. */\n+struct mlx5_flow sflow;\n+/* Global subsidiary device flows actions' list. */\n+struct {\n+\tvoid *actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];\n+\tuint64_t hash_fields;\n+\tint actions_n;\n+\tuint8_t transfer; /**< 1 if the flow is E-Switch flow. */\n+} sflow_act[8];\n+\n /**\n  * Initialize flow attributes structure according to flow items' types.\n  *\n@@ -2348,7 +2358,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t(void *)cache_resource,\n \t\t\t\trte_atomic32_read(&cache_resource->refcnt));\n \t\t\trte_atomic32_inc(&cache_resource->refcnt);\n-\t\t\tdev_flow->dv.encap_decap = cache_resource;\n+\t\t\tdev_flow->dv_handle->encap_decap = cache_resource;\n \t\t\treturn 0;\n \t\t}\n \t}\n@@ -2374,7 +2384,7 @@ struct field_modify_info modify_tcp[] = {\n \trte_atomic32_init(&cache_resource->refcnt);\n \trte_atomic32_inc(&cache_resource->refcnt);\n \tLIST_INSERT_HEAD(&sh->encaps_decaps, cache_resource, next);\n-\tdev_flow->dv.encap_decap = cache_resource;\n+\tdev_flow->dv_handle->encap_decap = cache_resource;\n \tDRV_LOG(DEBUG, \"new encap/decap resource %p: refcnt %d++\",\n \t\t(void *)cache_resource,\n \t\trte_atomic32_read(&cache_resource->refcnt));\n@@ -2425,7 +2435,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t(void *)&tbl_data->jump, cnt);\n \t}\n \trte_atomic32_inc(&tbl_data->jump.refcnt);\n-\tdev_flow->dv.jump = &tbl_data->jump;\n+\tdev_flow->dv_handle->jump = &tbl_data->jump;\n \treturn 0;\n }\n \n@@ -2463,7 +2473,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t(void *)cache_resource,\n \t\t\t\trte_atomic32_read(&cache_resource->refcnt));\n \t\t\trte_atomic32_inc(&cache_resource->refcnt);\n-\t\t\tdev_flow->dv.port_id_action = cache_resource;\n+\t\t\tdev_flow->dv_handle->port_id_action = cache_resource;\n \t\t\treturn 0;\n \t\t}\n \t}\n@@ -2491,7 +2501,7 @@ struct field_modify_info modify_tcp[] = {\n \trte_atomic32_init(&cache_resource->refcnt);\n \trte_atomic32_inc(&cache_resource->refcnt);\n \tLIST_INSERT_HEAD(&sh->port_id_action_list, cache_resource, next);\n-\tdev_flow->dv.port_id_action = cache_resource;\n+\tdev_flow->dv_handle->port_id_action = cache_resource;\n \tDRV_LOG(DEBUG, \"new port id action resource %p: refcnt %d++\",\n \t\t(void *)cache_resource,\n \t\trte_atomic32_read(&cache_resource->refcnt));\n@@ -2534,7 +2544,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t(void *)cache_resource,\n \t\t\t\trte_atomic32_read(&cache_resource->refcnt));\n \t\t\trte_atomic32_inc(&cache_resource->refcnt);\n-\t\t\tdev_flow->dv.push_vlan_res = cache_resource;\n+\t\t\tdev_flow->dv_handle->push_vlan_res = cache_resource;\n \t\t\treturn 0;\n \t\t}\n \t}\n@@ -2563,7 +2573,7 @@ struct field_modify_info modify_tcp[] = {\n \trte_atomic32_init(&cache_resource->refcnt);\n \trte_atomic32_inc(&cache_resource->refcnt);\n \tLIST_INSERT_HEAD(&sh->push_vlan_action_list, cache_resource, next);\n-\tdev_flow->dv.push_vlan_res = cache_resource;\n+\tdev_flow->dv_handle->push_vlan_res = cache_resource;\n \tDRV_LOG(DEBUG, \"new push vlan action resource %p: refcnt %d++\",\n \t\t(void *)cache_resource,\n \t\trte_atomic32_read(&cache_resource->refcnt));\n@@ -3652,7 +3662,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t(void *)cache_resource,\n \t\t\t\trte_atomic32_read(&cache_resource->refcnt));\n \t\t\trte_atomic32_inc(&cache_resource->refcnt);\n-\t\t\tdev_flow->dv.modify_hdr = cache_resource;\n+\t\t\tdev_flow->dv_handle->modify_hdr = cache_resource;\n \t\t\treturn 0;\n \t\t}\n \t}\n@@ -3679,7 +3689,7 @@ struct field_modify_info modify_tcp[] = {\n \trte_atomic32_init(&cache_resource->refcnt);\n \trte_atomic32_inc(&cache_resource->refcnt);\n \tLIST_INSERT_HEAD(&sh->modify_cmds, cache_resource, next);\n-\tdev_flow->dv.modify_hdr = cache_resource;\n+\tdev_flow->dv_handle->modify_hdr = cache_resource;\n \tDRV_LOG(DEBUG, \"new modify-header resource %p: refcnt %d++\",\n \t\t(void *)cache_resource,\n \t\trte_atomic32_read(&cache_resource->refcnt));\n@@ -5102,19 +5112,24 @@ struct field_modify_info modify_tcp[] = {\n \t\tconst struct rte_flow_action actions[] __rte_unused,\n \t\tstruct rte_flow_error *error)\n {\n-\tsize_t size = sizeof(struct mlx5_flow);\n+\tsize_t size = sizeof(struct mlx5_flow_dv_handle);\n \tstruct mlx5_flow *dev_flow;\n+\tstruct mlx5_flow_dv_handle *dv_handle;\n \n-\tdev_flow = rte_calloc(__func__, 1, size, 0);\n-\tif (!dev_flow) {\n+\t/* No need to clear to 0. */\n+\tdev_flow = &sflow;\n+\tdv_handle = rte_zmalloc(__func__, size, 0);\n+\tif (!dv_handle) {\n \t\trte_flow_error_set(error, ENOMEM,\n \t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t   \"not enough memory to create flow\");\n+\t\t\t\t   \"not enough memory to create flow handle\");\n \t\treturn NULL;\n \t}\n-\tdev_flow->dv.value.size = MLX5_ST_SZ_BYTES(fte_match_param);\n \tdev_flow->ingress = attr->ingress;\n \tdev_flow->transfer = attr->transfer;\n+\tdv_handle->value.size = MLX5_ST_SZ_BYTES(fte_match_param);\n+\t/* DV support already defined, compiler will happy for inbox driver. */\n+\tdev_flow->dv_handle = dv_handle;\n \treturn dev_flow;\n }\n \n@@ -5253,7 +5268,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t * This is workaround, masks are not supported,\n \t\t * and pre-validated.\n \t\t */\n-\t\tdev_flow->dv.vf_vlan.tag =\n+\t\tdev_flow->dv_handle->vf_vlan.tag =\n \t\t\trte_be_to_cpu_16(vlan_v->tci) & 0x0fff;\n \t}\n \ttci_m = rte_be_to_cpu_16(vlan_m->tci);\n@@ -6712,7 +6727,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t(void *)cache_matcher,\n \t\t\t\trte_atomic32_read(&cache_matcher->refcnt));\n \t\t\trte_atomic32_inc(&cache_matcher->refcnt);\n-\t\t\tdev_flow->dv.matcher = cache_matcher;\n+\t\t\tdev_flow->dv_handle->matcher = cache_matcher;\n \t\t\t/* old matcher should not make the table ref++. */\n \t\t\tflow_dv_tbl_resource_release(dev, tbl);\n \t\t\treturn 0;\n@@ -6749,7 +6764,7 @@ struct field_modify_info modify_tcp[] = {\n \t/* only matcher ref++, table ref++ already done above in get API. */\n \trte_atomic32_inc(&cache_matcher->refcnt);\n \tLIST_INSERT_HEAD(&tbl_data->matchers, cache_matcher, next);\n-\tdev_flow->dv.matcher = cache_matcher;\n+\tdev_flow->dv_handle->matcher = cache_matcher;\n \tDRV_LOG(DEBUG, \"%s group %u priority %hd new %s matcher %p: refcnt %d\",\n \t\tkey->domain ? \"FDB\" : \"NIC\", key->table_id,\n \t\tcache_matcher->priority,\n@@ -6791,7 +6806,7 @@ struct field_modify_info modify_tcp[] = {\n \t\tcache_resource = container_of\n \t\t\t(entry, struct mlx5_flow_dv_tag_resource, entry);\n \t\trte_atomic32_inc(&cache_resource->refcnt);\n-\t\tdev_flow->dv.tag_resource = cache_resource;\n+\t\tdev_flow->dv_handle->tag_resource = cache_resource;\n \t\tDRV_LOG(DEBUG, \"cached tag resource %p: refcnt now %d++\",\n \t\t\t(void *)cache_resource,\n \t\t\trte_atomic32_read(&cache_resource->refcnt));\n@@ -6820,7 +6835,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n \t\t\t\t\t  NULL, \"cannot insert tag\");\n \t}\n-\tdev_flow->dv.tag_resource = cache_resource;\n+\tdev_flow->dv_handle->tag_resource = cache_resource;\n \tDRV_LOG(DEBUG, \"new tag resource %p: refcnt now %d++\",\n \t\t(void *)cache_resource,\n \t\trte_atomic32_read(&cache_resource->refcnt));\n@@ -7022,6 +7037,9 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\tdev_flow->hash_fields |= MLX5_TCP_IBV_RX_HASH;\n \t\t}\n \t}\n+\t/* No need to save the hash fileds after creation. */\n+\tsflow_act[dev_flow->dv_handle->sidx].hash_fields =\n+\t\t\t\t\t\tdev_flow->hash_fields;\n }\n \n /**\n@@ -7065,6 +7083,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t},\n \t};\n \tint actions_n = 0;\n+\tuint8_t sidx = dev_flow->dv_handle->sidx;\n \tbool actions_end = false;\n \tunion {\n \t\tstruct mlx5_flow_dv_modify_hdr_resource res;\n@@ -7076,9 +7095,9 @@ struct field_modify_info modify_tcp[] = {\n \tunion flow_dv_attr flow_attr = { .attr = 0 };\n \tuint32_t tag_be;\n \tunion mlx5_flow_tbl_key tbl_key;\n-\tuint32_t modify_action_position = UINT32_MAX;\n+\tuint32_t modify_action_pos = UINT32_MAX;\n \tvoid *match_mask = matcher.mask.buf;\n-\tvoid *match_value = dev_flow->dv.value.buf;\n+\tvoid *match_value = dev_flow->dv_handle->value.buf;\n \tuint8_t next_protocol = 0xff;\n \tstruct rte_vlan_hdr vlan = { 0 };\n \tuint32_t table;\n@@ -7122,8 +7141,8 @@ struct field_modify_info modify_tcp[] = {\n \t\t\tif (flow_dv_port_id_action_resource_register\n \t\t\t    (dev, &port_id_resource, dev_flow, error))\n \t\t\t\treturn -rte_errno;\n-\t\t\tdev_flow->dv.actions[actions_n++] =\n-\t\t\t\tdev_flow->dv.port_id_action->action;\n+\t\t\tsflow_act[sidx].actions[actions_n++] =\n+\t\t\t\tdev_flow->dv_handle->port_id_action->action;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_PORT_ID;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_FLAG:\n@@ -7132,7 +7151,6 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\tstruct rte_flow_action_mark mark = {\n \t\t\t\t\t.id = MLX5_FLOW_MARK_DEFAULT,\n \t\t\t\t};\n-\n \t\t\t\tif (flow_dv_convert_action_mark(dev, &mark,\n \t\t\t\t\t\t\t\tmhdr_res,\n \t\t\t\t\t\t\t\terror))\n@@ -7141,12 +7159,12 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\tbreak;\n \t\t\t}\n \t\t\ttag_be = mlx5_flow_mark_set(MLX5_FLOW_MARK_DEFAULT);\n-\t\t\tif (!dev_flow->dv.tag_resource)\n+\t\t\tif (!dev_flow->dv_handle->tag_resource)\n \t\t\t\tif (flow_dv_tag_resource_register\n \t\t\t\t    (dev, tag_be, dev_flow, error))\n \t\t\t\t\treturn -rte_errno;\n-\t\t\tdev_flow->dv.actions[actions_n++] =\n-\t\t\t\tdev_flow->dv.tag_resource->action;\n+\t\t\tsflow_act[sidx].actions[actions_n++] =\n+\t\t\t\tdev_flow->dv_handle->tag_resource->action;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_MARK:\n \t\t\taction_flags |= MLX5_FLOW_ACTION_MARK;\n@@ -7168,12 +7186,12 @@ struct field_modify_info modify_tcp[] = {\n \t\t\ttag_be = mlx5_flow_mark_set\n \t\t\t      (((const struct rte_flow_action_mark *)\n \t\t\t       (actions->conf))->id);\n-\t\t\tif (!dev_flow->dv.tag_resource)\n+\t\t\tif (!dev_flow->dv_handle->tag_resource)\n \t\t\t\tif (flow_dv_tag_resource_register\n \t\t\t\t    (dev, tag_be, dev_flow, error))\n \t\t\t\t\treturn -rte_errno;\n-\t\t\tdev_flow->dv.actions[actions_n++] =\n-\t\t\t\tdev_flow->dv.tag_resource->action;\n+\t\t\tsflow_act[sidx].actions[actions_n++] =\n+\t\t\t\tdev_flow->dv_handle->tag_resource->action;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_SET_META:\n \t\t\tif (flow_dv_convert_action_set_meta\n@@ -7228,7 +7246,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t\t\t\t      dev_flow->group);\n \t\t\tif (flow->counter == NULL)\n \t\t\t\tgoto cnt_err;\n-\t\t\tdev_flow->dv.actions[actions_n++] =\n+\t\t\tsflow_act[sidx].actions[actions_n++] =\n \t\t\t\tflow->counter->action;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_COUNT;\n \t\t\tbreak;\n@@ -7248,7 +7266,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t\t\t  \" object.\");\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:\n-\t\t\tdev_flow->dv.actions[actions_n++] =\n+\t\t\tsflow_act[sidx].actions[actions_n++] =\n \t\t\t\t\t\tpriv->sh->pop_vlan_action;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;\n \t\t\tbreak;\n@@ -7270,8 +7288,8 @@ struct field_modify_info modify_tcp[] = {\n \t\t\tif (flow_dv_create_action_push_vlan\n \t\t\t\t\t    (dev, attr, &vlan, dev_flow, error))\n \t\t\t\treturn -rte_errno;\n-\t\t\tdev_flow->dv.actions[actions_n++] =\n-\t\t\t\t\t   dev_flow->dv.push_vlan_res->action;\n+\t\t\tsflow_act[sidx].actions[actions_n++] =\n+\t\t\t\tdev_flow->dv_handle->push_vlan_res->action;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:\n@@ -7297,8 +7315,8 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t\t\t\t   attr->transfer,\n \t\t\t\t\t\t\t   error))\n \t\t\t\treturn -rte_errno;\n-\t\t\tdev_flow->dv.actions[actions_n++] =\n-\t\t\t\tdev_flow->dv.encap_decap->verbs_action;\n+\t\t\tsflow_act[sidx].actions[actions_n++] =\n+\t\t\t\tdev_flow->dv_handle->encap_decap->verbs_action;\n \t\t\taction_flags |= actions->type ==\n \t\t\t\t\tRTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?\n \t\t\t\t\tMLX5_FLOW_ACTION_VXLAN_ENCAP :\n@@ -7310,8 +7328,8 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t\t\t\t   attr->transfer,\n \t\t\t\t\t\t\t   error))\n \t\t\t\treturn -rte_errno;\n-\t\t\tdev_flow->dv.actions[actions_n++] =\n-\t\t\t\tdev_flow->dv.encap_decap->verbs_action;\n+\t\t\tsflow_act[sidx].actions[actions_n++] =\n+\t\t\t\tdev_flow->dv_handle->encap_decap->verbs_action;\n \t\t\taction_flags |= actions->type ==\n \t\t\t\t\tRTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?\n \t\t\t\t\tMLX5_FLOW_ACTION_VXLAN_DECAP :\n@@ -7323,16 +7341,16 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\tif (flow_dv_create_action_raw_encap\n \t\t\t\t\t(dev, actions, dev_flow, attr, error))\n \t\t\t\t\treturn -rte_errno;\n-\t\t\t\tdev_flow->dv.actions[actions_n++] =\n-\t\t\t\t\tdev_flow->dv.encap_decap->verbs_action;\n+\t\t\t\tsflow_act[sidx].actions[actions_n++] =\n+\t\t\t\tdev_flow->dv_handle->encap_decap->verbs_action;\n \t\t\t} else {\n \t\t\t\t/* Handle encap without preceding decap. */\n \t\t\t\tif (flow_dv_create_action_l2_encap\n \t\t\t\t    (dev, actions, dev_flow, attr->transfer,\n \t\t\t\t     error))\n \t\t\t\t\treturn -rte_errno;\n-\t\t\t\tdev_flow->dv.actions[actions_n++] =\n-\t\t\t\t\tdev_flow->dv.encap_decap->verbs_action;\n+\t\t\t\tsflow_act[sidx].actions[actions_n++] =\n+\t\t\t\tdev_flow->dv_handle->encap_decap->verbs_action;\n \t\t\t}\n \t\t\taction_flags |= MLX5_FLOW_ACTION_RAW_ENCAP;\n \t\t\tbreak;\n@@ -7347,8 +7365,8 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\tif (flow_dv_create_action_l2_decap\n \t\t\t\t    (dev, dev_flow, attr->transfer, error))\n \t\t\t\t\treturn -rte_errno;\n-\t\t\t\tdev_flow->dv.actions[actions_n++] =\n-\t\t\t\t\tdev_flow->dv.encap_decap->verbs_action;\n+\t\t\t\tsflow_act[sidx].actions[actions_n++] =\n+\t\t\t\tdev_flow->dv_handle->encap_decap->verbs_action;\n \t\t\t}\n \t\t\t/* If decap is followed by encap, handle it at encap. */\n \t\t\taction_flags |= MLX5_FLOW_ACTION_RAW_DECAP;\n@@ -7379,8 +7397,8 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t\t\t NULL,\n \t\t\t\t\t\t \"cannot create jump action.\");\n \t\t\t}\n-\t\t\tdev_flow->dv.actions[actions_n++] =\n-\t\t\t\tdev_flow->dv.jump->action;\n+\t\t\tsflow_act[sidx].actions[actions_n++] =\n+\t\t\t\tdev_flow->dv_handle->jump->action;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_JUMP;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:\n@@ -7485,7 +7503,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t\t\t\"or invalid parameters\");\n \t\t\t}\n \t\t\t/* Set the meter action. */\n-\t\t\tdev_flow->dv.actions[actions_n++] =\n+\t\t\tsflow_act[sidx].actions[actions_n++] =\n \t\t\t\tflow->meter->mfts->meter_action;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_METER;\n \t\t\tbreak;\n@@ -7508,19 +7526,19 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\tif (flow_dv_modify_hdr_resource_register\n \t\t\t\t\t(dev, mhdr_res, dev_flow, error))\n \t\t\t\t\treturn -rte_errno;\n-\t\t\t\tdev_flow->dv.actions[modify_action_position] =\n-\t\t\t\t\tdev_flow->dv.modify_hdr->verbs_action;\n+\t\t\t\tsflow_act[sidx].actions[modify_action_pos] =\n+\t\t\t\tdev_flow->dv_handle->modify_hdr->verbs_action;\n \t\t\t}\n \t\t\tbreak;\n \t\tdefault:\n \t\t\tbreak;\n \t\t}\n-\t\tif (mhdr_res->actions_num &&\n-\t\t    modify_action_position == UINT32_MAX)\n-\t\t\tmodify_action_position = actions_n++;\n+\t\tif (mhdr_res->actions_num && modify_action_pos == UINT32_MAX)\n+\t\t\tmodify_action_pos = actions_n++;\n \t}\n-\tdev_flow->dv.actions_n = actions_n;\n-\tdev_flow->actions = action_flags;\n+\tsflow_act[sidx].actions_n = actions_n;\n+\tsflow_act[sidx].transfer = dev_flow->transfer;\n+\tdev_flow->dv_handle->action_flags = action_flags;\n \tfor (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {\n \t\tint tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);\n \t\tint item_type = items->type;\n@@ -7707,7 +7725,7 @@ struct field_modify_info modify_tcp[] = {\n \tMLX5_ASSERT(!flow_dv_check_valid_spec(matcher.mask.buf,\n \t\t\t\t\t      dev_flow->dv.value.buf));\n #endif\n-\tdev_flow->layers = item_flags;\n+\tdev_flow->dv_handle->layers = item_flags;\n \tif (action_flags & MLX5_FLOW_ACTION_RSS)\n \t\tflow_dv_hashfields_set(dev_flow);\n \t/* Register matcher. */\n@@ -7742,21 +7760,23 @@ struct field_modify_info modify_tcp[] = {\n __flow_dv_apply(struct rte_eth_dev *dev, struct rte_flow *flow,\n \t\tstruct rte_flow_error *error)\n {\n-\tstruct mlx5_flow_dv *dv;\n-\tstruct mlx5_flow *dev_flow;\n+\tstruct mlx5_flow_dv_handle *dv_handle;\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tvoid *matcher_obj;\n \tint n;\n \tint err;\n \n-\tLIST_FOREACH(dev_flow, &flow->dev_flows, next) {\n-\t\tdv = &dev_flow->dv;\n-\t\tn = dv->actions_n;\n-\t\tif (dev_flow->actions & MLX5_FLOW_ACTION_DROP) {\n-\t\t\tif (dev_flow->transfer) {\n-\t\t\t\tdv->actions[n++] = priv->sh->esw_drop_action;\n+\tSLIST_FOREACH(dv_handle, &flow->handles, next) {\n+\t\tuint8_t sidx = dv_handle->sidx;\n+\t\tn = sflow_act[sidx].actions_n;\n+\n+\t\tif (dv_handle->action_flags & MLX5_FLOW_ACTION_DROP) {\n+\t\t\tif (sflow_act[sidx].transfer) {\n+\t\t\t\tsflow_act[sidx].actions[n++] =\n+\t\t\t\t\t\tpriv->sh->esw_drop_action;\n \t\t\t} else {\n-\t\t\t\tdv->hrxq = mlx5_hrxq_drop_new(dev);\n-\t\t\t\tif (!dv->hrxq) {\n+\t\t\t\tdv_handle->hrxq = mlx5_hrxq_drop_new(dev);\n+\t\t\t\tif (!dv_handle->hrxq) {\n \t\t\t\t\trte_flow_error_set\n \t\t\t\t\t\t(error, errno,\n \t\t\t\t\t\t RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n@@ -7764,26 +7784,27 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t\t\t \"cannot get drop hash queue\");\n \t\t\t\t\tgoto error;\n \t\t\t\t}\n-\t\t\t\tdv->actions[n++] = dv->hrxq->action;\n+\t\t\t\tsflow_act[sidx].actions[n++] =\n+\t\t\t\t\t\tdv_handle->hrxq->action;\n \t\t\t}\n-\t\t} else if (dev_flow->actions &\n+\t\t} else if (dv_handle->action_flags &\n \t\t\t   (MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)) {\n \t\t\tstruct mlx5_hrxq *hrxq;\n \n \t\t\tMLX5_ASSERT(flow->rss.queue);\n \t\t\thrxq = mlx5_hrxq_get(dev, flow->rss.key,\n \t\t\t\t\t     MLX5_RSS_HASH_KEY_LEN,\n-\t\t\t\t\t     dev_flow->hash_fields,\n+\t\t\t\t\t     sflow_act[sidx].hash_fields,\n \t\t\t\t\t     (*flow->rss.queue),\n \t\t\t\t\t     flow->rss.queue_num);\n \t\t\tif (!hrxq) {\n \t\t\t\thrxq = mlx5_hrxq_new\n \t\t\t\t\t(dev, flow->rss.key,\n \t\t\t\t\t MLX5_RSS_HASH_KEY_LEN,\n-\t\t\t\t\t dev_flow->hash_fields,\n+\t\t\t\t\t sflow_act[sidx].hash_fields,\n \t\t\t\t\t (*flow->rss.queue),\n \t\t\t\t\t flow->rss.queue_num,\n-\t\t\t\t\t !!(dev_flow->layers &\n+\t\t\t\t\t !!(dv_handle->layers &\n \t\t\t\t\t    MLX5_FLOW_LAYER_TUNNEL));\n \t\t\t}\n \t\t\tif (!hrxq) {\n@@ -7793,47 +7814,45 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t\t \"cannot get hash queue\");\n \t\t\t\tgoto error;\n \t\t\t}\n-\t\t\tdv->hrxq = hrxq;\n-\t\t\tdv->actions[n++] = dv->hrxq->action;\n+\t\t\tdv_handle->hrxq = hrxq;\n+\t\t\tsflow_act[sidx].actions[n++] = hrxq->action;\n \t\t}\n-\t\tdv->flow =\n-\t\t\tmlx5_glue->dv_create_flow(dv->matcher->matcher_object,\n-\t\t\t\t\t\t  (void *)&dv->value, n,\n-\t\t\t\t\t\t  dv->actions);\n-\t\tif (!dv->flow) {\n+\t\tmatcher_obj = dv_handle->matcher->matcher_object;\n+\t\tdv_handle->flow =\n+\t\t\tmlx5_glue->dv_create_flow(matcher_obj,\n+\t\t\t\t\t\t  (void *)&dv_handle->value,\n+\t\t\t\t\t\t  n, sflow_act[sidx].actions);\n+\t\tif (!dv_handle->flow) {\n \t\t\trte_flow_error_set(error, errno,\n \t\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n \t\t\t\t\t   NULL,\n \t\t\t\t\t   \"hardware refuses to create flow\");\n \t\t\tgoto error;\n \t\t}\n-\t\tif (priv->vmwa_context &&\n-\t\t    dev_flow->dv.vf_vlan.tag &&\n-\t\t    !dev_flow->dv.vf_vlan.created) {\n+\t\tif (priv->vmwa_context && dv_handle->vf_vlan.tag &&\n+\t\t    !dv_handle->vf_vlan.created) {\n \t\t\t/*\n \t\t\t * The rule contains the VLAN pattern.\n \t\t\t * For VF we are going to create VLAN\n \t\t\t * interface to make hypervisor set correct\n \t\t\t * e-Switch vport context.\n \t\t\t */\n-\t\t\tmlx5_vlan_vmwa_acquire(dev, &dev_flow->dv.vf_vlan);\n+\t\t\tmlx5_vlan_vmwa_acquire(dev, &dv_handle->vf_vlan);\n \t\t}\n \t}\n \treturn 0;\n error:\n \terr = rte_errno; /* Save rte_errno before cleanup. */\n-\tLIST_FOREACH(dev_flow, &flow->dev_flows, next) {\n-\t\tstruct mlx5_flow_dv *dv = &dev_flow->dv;\n-\t\tif (dv->hrxq) {\n-\t\t\tif (dev_flow->actions & MLX5_FLOW_ACTION_DROP)\n+\tSLIST_FOREACH(dv_handle, &flow->handles, next) {\n+\t\tif (dv_handle->hrxq) {\n+\t\t\tif (dv_handle->action_flags & MLX5_FLOW_ACTION_DROP)\n \t\t\t\tmlx5_hrxq_drop_release(dev);\n \t\t\telse\n-\t\t\t\tmlx5_hrxq_release(dev, dv->hrxq);\n-\t\t\tdv->hrxq = NULL;\n+\t\t\t\tmlx5_hrxq_release(dev, dv_handle->hrxq);\n+\t\t\tdv_handle->hrxq = NULL;\n \t\t}\n-\t\tif (dev_flow->dv.vf_vlan.tag &&\n-\t\t    dev_flow->dv.vf_vlan.created)\n-\t\t\tmlx5_vlan_vmwa_release(dev, &dev_flow->dv.vf_vlan);\n+\t\tif (dv_handle->vf_vlan.tag && dv_handle->vf_vlan.created)\n+\t\t\tmlx5_vlan_vmwa_release(dev, &dv_handle->vf_vlan);\n \t}\n \trte_errno = err; /* Restore rte_errno. */\n \treturn -rte_errno;\n@@ -7844,17 +7863,17 @@ struct field_modify_info modify_tcp[] = {\n  *\n  * @param dev\n  *   Pointer to Ethernet device.\n- * @param flow\n- *   Pointer to mlx5_flow.\n+ * @param handle\n+ *   Pointer to mlx5_flow_dv_handle.\n  *\n  * @return\n  *   1 while a reference on it exists, 0 when freed.\n  */\n static int\n flow_dv_matcher_release(struct rte_eth_dev *dev,\n-\t\t\tstruct mlx5_flow *flow)\n+\t\t\tstruct mlx5_flow_dv_handle *handle)\n {\n-\tstruct mlx5_flow_dv_matcher *matcher = flow->dv.matcher;\n+\tstruct mlx5_flow_dv_matcher *matcher = handle->matcher;\n \n \tMLX5_ASSERT(matcher->matcher_object);\n \tDRV_LOG(DEBUG, \"port %u matcher %p: refcnt %d--\",\n@@ -7877,17 +7896,17 @@ struct field_modify_info modify_tcp[] = {\n /**\n  * Release an encap/decap resource.\n  *\n- * @param flow\n- *   Pointer to mlx5_flow.\n+ * @param handle\n+ *   Pointer to mlx5_flow_dv_handle.\n  *\n  * @return\n  *   1 while a reference on it exists, 0 when freed.\n  */\n static int\n-flow_dv_encap_decap_resource_release(struct mlx5_flow *flow)\n+flow_dv_encap_decap_resource_release(struct mlx5_flow_dv_handle *handle)\n {\n \tstruct mlx5_flow_dv_encap_decap_resource *cache_resource =\n-\t\t\t\t\t\tflow->dv.encap_decap;\n+\t\t\t\t\t\thandle->encap_decap;\n \n \tMLX5_ASSERT(cache_resource->verbs_action);\n \tDRV_LOG(DEBUG, \"encap/decap resource %p: refcnt %d--\",\n@@ -7910,17 +7929,17 @@ struct field_modify_info modify_tcp[] = {\n  *\n  * @param dev\n  *   Pointer to Ethernet device.\n- * @param flow\n- *   Pointer to mlx5_flow.\n+ * @param handle\n+ *   Pointer to mlx5_flow_dv_handle.\n  *\n  * @return\n  *   1 while a reference on it exists, 0 when freed.\n  */\n static int\n flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev,\n-\t\t\t\t  struct mlx5_flow *flow)\n+\t\t\t\t  struct mlx5_flow_dv_handle *handle)\n {\n-\tstruct mlx5_flow_dv_jump_tbl_resource *cache_resource = flow->dv.jump;\n+\tstruct mlx5_flow_dv_jump_tbl_resource *cache_resource = handle->jump;\n \tstruct mlx5_flow_tbl_data_entry *tbl_data =\n \t\t\tcontainer_of(cache_resource,\n \t\t\t\t     struct mlx5_flow_tbl_data_entry, jump);\n@@ -7944,17 +7963,17 @@ struct field_modify_info modify_tcp[] = {\n /**\n  * Release a modify-header resource.\n  *\n- * @param flow\n- *   Pointer to mlx5_flow.\n+ * @param handle\n+ *   Pointer to mlx5_flow_dv_handle.\n  *\n  * @return\n  *   1 while a reference on it exists, 0 when freed.\n  */\n static int\n-flow_dv_modify_hdr_resource_release(struct mlx5_flow *flow)\n+flow_dv_modify_hdr_resource_release(struct mlx5_flow_dv_handle *handle)\n {\n \tstruct mlx5_flow_dv_modify_hdr_resource *cache_resource =\n-\t\t\t\t\t\tflow->dv.modify_hdr;\n+\t\t\t\t\t\thandle->modify_hdr;\n \n \tMLX5_ASSERT(cache_resource->verbs_action);\n \tDRV_LOG(DEBUG, \"modify-header resource %p: refcnt %d--\",\n@@ -7975,17 +7994,17 @@ struct field_modify_info modify_tcp[] = {\n /**\n  * Release port ID action resource.\n  *\n- * @param flow\n- *   Pointer to mlx5_flow.\n+ * @param handle\n+ *   Pointer to mlx5_flow_dv_handle.\n  *\n  * @return\n  *   1 while a reference on it exists, 0 when freed.\n  */\n static int\n-flow_dv_port_id_action_resource_release(struct mlx5_flow *flow)\n+flow_dv_port_id_action_resource_release(struct mlx5_flow_dv_handle *handle)\n {\n \tstruct mlx5_flow_dv_port_id_action_resource *cache_resource =\n-\t\tflow->dv.port_id_action;\n+\t\t\t\t\t\thandle->port_id_action;\n \n \tMLX5_ASSERT(cache_resource->action);\n \tDRV_LOG(DEBUG, \"port ID action resource %p: refcnt %d--\",\n@@ -8006,17 +8025,17 @@ struct field_modify_info modify_tcp[] = {\n /**\n  * Release push vlan action resource.\n  *\n- * @param flow\n- *   Pointer to mlx5_flow.\n+ * @param handle\n+ *   Pointer to mlx5_flow_dv_handle.\n  *\n  * @return\n  *   1 while a reference on it exists, 0 when freed.\n  */\n static int\n-flow_dv_push_vlan_action_resource_release(struct mlx5_flow *flow)\n+flow_dv_push_vlan_action_resource_release(struct mlx5_flow_dv_handle *handle)\n {\n \tstruct mlx5_flow_dv_push_vlan_action_resource *cache_resource =\n-\t\tflow->dv.push_vlan_res;\n+\t\t\t\t\t\thandle->push_vlan_res;\n \n \tMLX5_ASSERT(cache_resource->action);\n \tDRV_LOG(DEBUG, \"push VLAN action resource %p: refcnt %d--\",\n@@ -8046,27 +8065,24 @@ struct field_modify_info modify_tcp[] = {\n static void\n __flow_dv_remove(struct rte_eth_dev *dev, struct rte_flow *flow)\n {\n-\tstruct mlx5_flow_dv *dv;\n-\tstruct mlx5_flow *dev_flow;\n+\tstruct mlx5_flow_dv_handle *dv_handle;\n \n \tif (!flow)\n \t\treturn;\n-\tLIST_FOREACH(dev_flow, &flow->dev_flows, next) {\n-\t\tdv = &dev_flow->dv;\n-\t\tif (dv->flow) {\n-\t\t\tclaim_zero(mlx5_glue->dv_destroy_flow(dv->flow));\n-\t\t\tdv->flow = NULL;\n+\tSLIST_FOREACH(dv_handle, &flow->handles, next) {\n+\t\tif (dv_handle->flow) {\n+\t\t\tclaim_zero(mlx5_glue->dv_destroy_flow(dv_handle->flow));\n+\t\t\tdv_handle->flow = NULL;\n \t\t}\n-\t\tif (dv->hrxq) {\n-\t\t\tif (dev_flow->actions & MLX5_FLOW_ACTION_DROP)\n+\t\tif (dv_handle->hrxq) {\n+\t\t\tif (dv_handle->action_flags & MLX5_FLOW_ACTION_DROP)\n \t\t\t\tmlx5_hrxq_drop_release(dev);\n \t\t\telse\n-\t\t\t\tmlx5_hrxq_release(dev, dv->hrxq);\n-\t\t\tdv->hrxq = NULL;\n+\t\t\t\tmlx5_hrxq_release(dev, dv_handle->hrxq);\n+\t\t\tdv_handle->hrxq = NULL;\n \t\t}\n-\t\tif (dev_flow->dv.vf_vlan.tag &&\n-\t\t    dev_flow->dv.vf_vlan.created)\n-\t\t\tmlx5_vlan_vmwa_release(dev, &dev_flow->dv.vf_vlan);\n+\t\tif (dv_handle->vf_vlan.tag && dv_handle->vf_vlan.created)\n+\t\t\tmlx5_vlan_vmwa_release(dev, &dv_handle->vf_vlan);\n \t}\n }\n \n@@ -8082,7 +8098,7 @@ struct field_modify_info modify_tcp[] = {\n static void\n __flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)\n {\n-\tstruct mlx5_flow *dev_flow;\n+\tstruct mlx5_flow_dv_handle *dv_handle;\n \n \tif (!flow)\n \t\treturn;\n@@ -8095,24 +8111,24 @@ struct field_modify_info modify_tcp[] = {\n \t\tmlx5_flow_meter_detach(flow->meter);\n \t\tflow->meter = NULL;\n \t}\n-\twhile (!LIST_EMPTY(&flow->dev_flows)) {\n-\t\tdev_flow = LIST_FIRST(&flow->dev_flows);\n-\t\tLIST_REMOVE(dev_flow, next);\n-\t\tif (dev_flow->dv.matcher)\n-\t\t\tflow_dv_matcher_release(dev, dev_flow);\n-\t\tif (dev_flow->dv.encap_decap)\n-\t\t\tflow_dv_encap_decap_resource_release(dev_flow);\n-\t\tif (dev_flow->dv.modify_hdr)\n-\t\t\tflow_dv_modify_hdr_resource_release(dev_flow);\n-\t\tif (dev_flow->dv.jump)\n-\t\t\tflow_dv_jump_tbl_resource_release(dev, dev_flow);\n-\t\tif (dev_flow->dv.port_id_action)\n-\t\t\tflow_dv_port_id_action_resource_release(dev_flow);\n-\t\tif (dev_flow->dv.push_vlan_res)\n-\t\t\tflow_dv_push_vlan_action_resource_release(dev_flow);\n-\t\tif (dev_flow->dv.tag_resource)\n-\t\t\tflow_dv_tag_release(dev, dev_flow->dv.tag_resource);\n-\t\trte_free(dev_flow);\n+\twhile (!SLIST_EMPTY(&flow->handles)) {\n+\t\tdv_handle = SLIST_FIRST(&flow->handles);\n+\t\tSLIST_REMOVE_HEAD(&flow->handles, next);\n+\t\tif (dv_handle->matcher)\n+\t\t\tflow_dv_matcher_release(dev, dv_handle);\n+\t\tif (dv_handle->encap_decap)\n+\t\t\tflow_dv_encap_decap_resource_release(dv_handle);\n+\t\tif (dv_handle->modify_hdr)\n+\t\t\tflow_dv_modify_hdr_resource_release(dv_handle);\n+\t\tif (dv_handle->jump)\n+\t\t\tflow_dv_jump_tbl_resource_release(dev, dv_handle);\n+\t\tif (dv_handle->port_id_action)\n+\t\t\tflow_dv_port_id_action_resource_release(dv_handle);\n+\t\tif (dv_handle->push_vlan_res)\n+\t\t\tflow_dv_push_vlan_action_resource_release(dv_handle);\n+\t\tif (dv_handle->tag_resource)\n+\t\t\tflow_dv_tag_release(dev, dv_handle->tag_resource);\n+\t\trte_free(dv_handle);\n \t}\n }\n \n",
    "prefixes": [
        "4/6"
    ]
}