get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 80437,
    "url": "http://patches.dpdk.org/api/patches/80437/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1602577050-178398-9-git-send-email-jiaweiw@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": "<1602577050-178398-9-git-send-email-jiaweiw@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1602577050-178398-9-git-send-email-jiaweiw@nvidia.com",
    "date": "2020-10-13T08:17:28",
    "name": "[v2,08/10] net/mlx5: update translate function for mirror",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "cbb78ce74e2926df3dd30b0e5937242537714a09",
    "submitter": {
        "id": 1939,
        "url": "http://patches.dpdk.org/api/people/1939/?format=api",
        "name": "Jiawei Wang",
        "email": "jiaweiw@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/1602577050-178398-9-git-send-email-jiaweiw@nvidia.com/mbox/",
    "series": [
        {
            "id": 12904,
            "url": "http://patches.dpdk.org/api/series/12904/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=12904",
            "date": "2020-10-13T08:17:23",
            "name": "Add sampling and mirroring support in MLX5 PMD",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/12904/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/80437/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/80437/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 512EBA04B6;\n\tTue, 13 Oct 2020 10:19:30 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 276C41DA65;\n\tTue, 13 Oct 2020 10:17:46 +0200 (CEST)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by dpdk.org (Postfix) with ESMTP id 4A9DA1DA32\n for <dev@dpdk.org>; Tue, 13 Oct 2020 10:17:36 +0200 (CEST)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n jiaweiw@nvidia.com) with SMTP; 13 Oct 2020 11:17:30 +0300",
            "from nvidia.com (gen-l-vrt-280.mtl.labs.mlnx [10.237.45.1])\n by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 09D8HU0c022749;\n Tue, 13 Oct 2020 11:17:30 +0300"
        ],
        "From": "Jiawei Wang <jiaweiw@nvidia.com>",
        "To": "orika@nvidia.com, viacheslavo@nvidia.com, matan@nvidia.com,\n thomas@monjalon.net",
        "Cc": "dev@dpdk.org, rasland@nvidia.com, asafp@nvidia.com",
        "Date": "Tue, 13 Oct 2020 11:17:28 +0300",
        "Message-Id": "<1602577050-178398-9-git-send-email-jiaweiw@nvidia.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1602577050-178398-1-git-send-email-jiaweiw@nvidia.com>",
        "References": "<1602251436-269694-1-git-send-email-jiaweiw@nvidia.com>\n <1602577050-178398-1-git-send-email-jiaweiw@nvidia.com>",
        "Subject": "[dpdk-dev] [PATCH v2 08/10] net/mlx5: update translate function for\n\tmirror",
        "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": "Translate the attribute of sample action that include sample ratio\nand sub actions list.\nPMD will check the destination action number in current flow,\nif found multiple destination actions, then create the new destination\narray rdma action that group actions for each destination.\nCurrently only support port or queue for destination action, and only\nencap action can be attached into one port destination.\n\nSigned-off-by: Jiawei Wang <jiaweiw@nvidia.com>\nAcked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>\n---\n drivers/net/mlx5/mlx5.c         |  11 +\n drivers/net/mlx5/mlx5.h         |   2 +\n drivers/net/mlx5/mlx5_flow.h    |  23 ++\n drivers/net/mlx5/mlx5_flow_dv.c | 461 +++++++++++++++++++++++++++++++++++++---\n 4 files changed, 468 insertions(+), 29 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex 2613c78..44822ad 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -252,6 +252,17 @@ static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =\n \t\t.free = mlx5_free,\n \t\t.type = \"mlx5_sample_ipool\",\n \t},\n+\t{\n+\t\t.size = sizeof(struct mlx5_flow_dv_dest_array_resource),\n+\t\t.trunk_size = 64,\n+\t\t.grow_trunk = 3,\n+\t\t.grow_shift = 2,\n+\t\t.need_lock = 0,\n+\t\t.release_mem_en = 1,\n+\t\t.malloc = mlx5_malloc,\n+\t\t.free = mlx5_free,\n+\t\t.type = \"mlx5_dest_array_ipool\",\n+\t},\n #endif\n \t{\n \t\t.size = sizeof(struct mlx5_flow_meter),\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 391f6f3..e528833 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -40,6 +40,7 @@ enum mlx5_ipool_index {\n \tMLX5_IPOOL_PORT_ID, /* Pool for port id resource. */\n \tMLX5_IPOOL_JUMP, /* Pool for jump resource. */\n \tMLX5_IPOOL_SAMPLE, /* Pool for sample resource. */\n+\tMLX5_IPOOL_DEST_ARRAY, /* Pool for destination array resource. */\n #endif\n \tMLX5_IPOOL_MTR, /* Pool for meter resource. */\n \tMLX5_IPOOL_MCP, /* Pool for metadata resource. */\n@@ -643,6 +644,7 @@ struct mlx5_dev_ctx_shared {\n \tuint32_t port_id_action_list; /* List of port ID actions. */\n \tuint32_t push_vlan_action_list; /* List of push VLAN actions. */\n \tuint32_t sample_action_list; /* List of sample actions. */\n+\tuint32_t dest_array_list; /* List of destination array actions. */\n \tstruct mlx5_flow_counter_mng cmng; /* Counters management structure. */\n \tstruct mlx5_flow_default_miss_resource default_miss;\n \t/* Default miss action resource structure. */\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex 85f9f45..e6d165d 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -527,6 +527,8 @@ struct mlx5_flow_sub_actions_list {\n \tvoid *dr_queue_action;\n \tvoid *dr_tag_action;\n \tvoid *dr_cnt_action;\n+\tvoid *dr_port_id_action;\n+\tvoid *dr_encap_action;\n };\n \n /* Sample sub-actions resource list. */\n@@ -534,6 +536,8 @@ struct mlx5_flow_sub_actions_idx {\n \tuint32_t rix_hrxq; /**< Hash Rx queue object index. */\n \tuint32_t rix_tag; /**< Index to the tag action. */\n \tuint32_t cnt;\n+\tuint32_t rix_port_id_action; /**< Index to port ID action resource. */\n+\tuint32_t rix_encap_decap; /**< Index to encap/decap resource. */\n };\n \n /* Sample action resource structure. */\n@@ -553,6 +557,21 @@ struct mlx5_flow_dv_sample_resource {\n \t/**< Action resources. */\n };\n \n+#define MLX5_MAX_DEST_NUM\t2\n+\n+/* Destination array action resource structure. */\n+struct mlx5_flow_dv_dest_array_resource {\n+\tILIST_ENTRY(uint32_t)next; /**< Pointer to next element. */\n+\trte_atomic32_t refcnt; /**< Reference counter. */\n+\tuint8_t ft_type; /** Flow Table Type */\n+\tuint8_t num_of_dest; /**< Number of destination actions. */\n+\tvoid *action; /**< Pointer to the rdma core action. */\n+\tstruct mlx5_flow_sub_actions_idx sample_idx[MLX5_MAX_DEST_NUM];\n+\t/**< Action index resources. */\n+\tstruct mlx5_flow_sub_actions_list sample_act[MLX5_MAX_DEST_NUM];\n+\t/**< Action resources. */\n+};\n+\n /* Verbs specification header. */\n struct ibv_spec_header {\n \tenum ibv_flow_spec_type type;\n@@ -587,6 +606,8 @@ struct mlx5_flow_handle_dv {\n \t/**< Index to the tag action. */\n \tuint32_t rix_sample;\n \t/**< Index to sample action resource in cache. */\n+\tuint32_t rix_dest_array;\n+\t/**< Index to destination array resource in cache. */\n } __rte_packed;\n \n /** Device flow handle structure: used both for creating & destroying. */\n@@ -654,6 +675,8 @@ struct mlx5_flow_dv_workspace {\n \t/**< Holds the value that the packet is compared to. */\n \tstruct mlx5_flow_dv_sample_resource *sample_res;\n \t/**< Pointer to the sample action resource. */\n+\tstruct mlx5_flow_dv_dest_array_resource *dest_array_res;\n+\t/**< Pointer to the destination array resource. */\n };\n \n /*\ndiff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex 157c465..7c6504e 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -80,6 +80,10 @@\n flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev,\n \t\t\t\t      uint32_t encap_decap_idx);\n \n+static int\n+flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev,\n+\t\t\t\t\tuint32_t port_id);\n+\n /**\n  * Initialize flow attributes structure according to flow items' types.\n  *\n@@ -8377,9 +8381,9 @@ struct field_modify_info modify_tcp[] = {\n  */\n static struct mlx5_hrxq *\n flow_dv_handle_rx_queue(struct rte_eth_dev *dev,\n-\t\t\t  struct mlx5_flow *dev_flow,\n-\t\t\t  struct mlx5_flow_rss_desc *rss_desc,\n-\t\t\t  uint32_t *hrxq_idx)\n+\t\t\tstruct mlx5_flow *dev_flow,\n+\t\t\tstruct mlx5_flow_rss_desc *rss_desc,\n+\t\t\tuint32_t *hrxq_idx)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_flow_handle *dh = dev_flow->handle;\n@@ -8387,19 +8391,19 @@ struct field_modify_info modify_tcp[] = {\n \n \tMLX5_ASSERT(rss_desc->queue_num);\n \t*hrxq_idx = mlx5_hrxq_get(dev, rss_desc->key,\n-\t\t\t\t MLX5_RSS_HASH_KEY_LEN,\n-\t\t\t\t dev_flow->hash_fields,\n-\t\t\t\t rss_desc->queue,\n-\t\t\t\t rss_desc->queue_num);\n+\t\t\t\t  MLX5_RSS_HASH_KEY_LEN,\n+\t\t\t\t  dev_flow->hash_fields,\n+\t\t\t\t  rss_desc->queue,\n+\t\t\t\t  rss_desc->queue_num);\n \tif (!*hrxq_idx) {\n \t\t*hrxq_idx = mlx5_hrxq_new\n \t\t\t\t(dev, rss_desc->key,\n-\t\t\t\tMLX5_RSS_HASH_KEY_LEN,\n-\t\t\t\tdev_flow->hash_fields,\n-\t\t\t\trss_desc->queue,\n-\t\t\t\trss_desc->queue_num,\n-\t\t\t\t!!(dh->layers &\n-\t\t\t\tMLX5_FLOW_LAYER_TUNNEL));\n+\t\t\t\t MLX5_RSS_HASH_KEY_LEN,\n+\t\t\t\t dev_flow->hash_fields,\n+\t\t\t\t rss_desc->queue,\n+\t\t\t\t rss_desc->queue_num,\n+\t\t\t\t !!(dh->layers &\n+\t\t\t\t MLX5_FLOW_LAYER_TUNNEL));\n \t\tif (!*hrxq_idx)\n \t\t\treturn NULL;\n \t}\n@@ -8553,6 +8557,153 @@ struct field_modify_info modify_tcp[] = {\n }\n \n /**\n+ * Find existing destination array resource or create and register a new one.\n+ *\n+ * @param[in, out] dev\n+ *   Pointer to rte_eth_dev structure.\n+ * @param[in] attr\n+ *   Attributes of flow that includes this item.\n+ * @param[in] resource\n+ *   Pointer to destination array resource.\n+ * @parm[in, out] dev_flow\n+ *   Pointer to the dev_flow.\n+ * @param[out] error\n+ *   pointer to error structure.\n+ *\n+ * @return\n+ *   0 on success otherwise -errno and errno is set.\n+ */\n+static int\n+flow_dv_dest_array_resource_register(struct rte_eth_dev *dev,\n+\t\t\t const struct rte_flow_attr *attr,\n+\t\t\t struct mlx5_flow_dv_dest_array_resource *resource,\n+\t\t\t struct mlx5_flow *dev_flow,\n+\t\t\t struct rte_flow_error *error)\n+{\n+\tstruct mlx5_flow_dv_dest_array_resource *cache_resource;\n+\tstruct mlx5dv_dr_action_dest_attr *dest_attr[MLX5_MAX_DEST_NUM] = { 0 };\n+\tstruct mlx5dv_dr_action_dest_reformat dest_reformat[MLX5_MAX_DEST_NUM];\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_dev_ctx_shared *sh = priv->sh;\n+\tstruct mlx5_flow_sub_actions_list *sample_act;\n+\tstruct mlx5dv_dr_domain *domain;\n+\tuint32_t idx = 0;\n+\n+\t/* Lookup a matching resource from cache. */\n+\tILIST_FOREACH(sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n+\t\t      sh->dest_array_list,\n+\t\t      idx, cache_resource, next) {\n+\t\tif (resource->num_of_dest == cache_resource->num_of_dest &&\n+\t\t    resource->ft_type == cache_resource->ft_type &&\n+\t\t    !memcmp((void *)cache_resource->sample_act,\n+\t\t\t    (void *)resource->sample_act,\n+\t\t\t   (resource->num_of_dest *\n+\t\t\t   sizeof(struct mlx5_flow_sub_actions_list)))) {\n+\t\t\tDRV_LOG(DEBUG, \"sample resource %p: refcnt %d++\",\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->handle->dvh.rix_dest_array = idx;\n+\t\t\tdev_flow->dv.dest_array_res = cache_resource;\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\t/* Register new destination array resource. */\n+\tcache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n+\t\t\t\t       &dev_flow->handle->dvh.rix_dest_array);\n+\tif (!cache_resource)\n+\t\treturn rte_flow_error_set(error, ENOMEM,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"cannot allocate resource memory\");\n+\t*cache_resource = *resource;\n+\tif (attr->transfer)\n+\t\tdomain = sh->fdb_domain;\n+\telse if (attr->ingress)\n+\t\tdomain = sh->rx_domain;\n+\telse\n+\t\tdomain = sh->tx_domain;\n+\tfor (idx = 0; idx < resource->num_of_dest; idx++) {\n+\t\tdest_attr[idx] = (struct mlx5dv_dr_action_dest_attr *)\n+\t\t\t\t mlx5_malloc(MLX5_MEM_ZERO,\n+\t\t\t\t sizeof(struct mlx5dv_dr_action_dest_attr),\n+\t\t\t\t 0, SOCKET_ID_ANY);\n+\t\tif (!dest_attr[idx]) {\n+\t\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t\t   NULL,\n+\t\t\t\t\t   \"cannot allocate resource memory\");\n+\t\t\tgoto error;\n+\t\t}\n+\t\tdest_attr[idx]->type = MLX5DV_DR_ACTION_DEST;\n+\t\tsample_act = &resource->sample_act[idx];\n+\t\tif (sample_act->action_flags == MLX5_FLOW_ACTION_QUEUE) {\n+\t\t\tdest_attr[idx]->dest = sample_act->dr_queue_action;\n+\t\t} else if (sample_act->action_flags ==\n+\t\t\t  (MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_ENCAP)) {\n+\t\t\tdest_attr[idx]->type = MLX5DV_DR_ACTION_DEST_REFORMAT;\n+\t\t\tdest_attr[idx]->dest_reformat = &dest_reformat[idx];\n+\t\t\tdest_attr[idx]->dest_reformat->reformat =\n+\t\t\t\t\tsample_act->dr_encap_action;\n+\t\t\tdest_attr[idx]->dest_reformat->dest =\n+\t\t\t\t\tsample_act->dr_port_id_action;\n+\t\t} else if (sample_act->action_flags ==\n+\t\t\t   MLX5_FLOW_ACTION_PORT_ID) {\n+\t\t\tdest_attr[idx]->dest = sample_act->dr_port_id_action;\n+\t\t}\n+\t}\n+\t/* create a dest array actioin */\n+\tcache_resource->action = mlx5_glue->dr_create_flow_action_dest_array\n+\t\t\t\t\t\t(domain,\n+\t\t\t\t\t\t cache_resource->num_of_dest,\n+\t\t\t\t\t\t dest_attr);\n+\tif (!cache_resource->action) {\n+\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t   NULL,\n+\t\t\t\t   \"cannot create destination array action\");\n+\t\tgoto error;\n+\t}\n+\trte_atomic32_init(&cache_resource->refcnt);\n+\trte_atomic32_inc(&cache_resource->refcnt);\n+\tILIST_INSERT(sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n+\t\t     &sh->dest_array_list,\n+\t\t     dev_flow->handle->dvh.rix_dest_array, cache_resource,\n+\t\t     next);\n+\tdev_flow->dv.dest_array_res = cache_resource;\n+\tDRV_LOG(DEBUG, \"new destination array resource %p: refcnt %d++\",\n+\t\t(void *)cache_resource,\n+\t\trte_atomic32_read(&cache_resource->refcnt));\n+\tfor (idx = 0; idx < resource->num_of_dest; idx++)\n+\t\tmlx5_free(dest_attr[idx]);\n+\treturn 0;\n+error:\n+\tfor (idx = 0; idx < resource->num_of_dest; idx++) {\n+\t\tstruct mlx5_flow_sub_actions_idx *act_res =\n+\t\t\t\t\t&cache_resource->sample_idx[idx];\n+\t\tif (act_res->rix_hrxq &&\n+\t\t    !mlx5_hrxq_release(dev,\n+\t\t\t\tact_res->rix_hrxq))\n+\t\t\tact_res->rix_hrxq = 0;\n+\t\tif (act_res->rix_encap_decap &&\n+\t\t\t!flow_dv_encap_decap_resource_release(dev,\n+\t\t\t\tact_res->rix_encap_decap))\n+\t\t\tact_res->rix_encap_decap = 0;\n+\t\tif (act_res->rix_port_id_action &&\n+\t\t\t!flow_dv_port_id_action_resource_release(dev,\n+\t\t\t\tact_res->rix_port_id_action))\n+\t\t\tact_res->rix_port_id_action = 0;\n+\t\tif (dest_attr[idx])\n+\t\t\tmlx5_free(dest_attr[idx]);\n+\t}\n+\n+\tmlx5_ipool_free(sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n+\t\t\t\tdev_flow->handle->dvh.rix_dest_array);\n+\tdev_flow->handle->dvh.rix_dest_array = 0;\n+\treturn -rte_errno;\n+}\n+\n+/**\n  * Convert Sample action to DV specification.\n  *\n  * @param[in] dev\n@@ -8563,6 +8714,8 @@ struct field_modify_info modify_tcp[] = {\n  *   Pointer to the mlx5_flow.\n  * @param[in] attr\n  *   Pointer to the flow attributes.\n+ * @param[in, out] num_of_dest\n+ *   Pointer to the num of destination.\n  * @param[in, out] sample_actions\n  *   Pointer to sample actions list.\n  * @param[in, out] res\n@@ -8578,6 +8731,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\tconst struct rte_flow_action *action,\n \t\t\t\tstruct mlx5_flow *dev_flow,\n \t\t\t\tconst struct rte_flow_attr *attr,\n+\t\t\t\tuint32_t *num_of_dest,\n \t\t\t\tvoid **sample_actions,\n \t\t\t\tstruct mlx5_flow_dv_sample_resource *res,\n \t\t\t\tstruct rte_flow_error *error)\n@@ -8623,6 +8777,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\tsample_idx->rix_hrxq = hrxq_idx;\n \t\t\tsample_actions[sample_act->actions_num++] =\n \t\t\t\t\t\thrxq->action;\n+\t\t\t(*num_of_dest)++;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_QUEUE;\n \t\t\tif (action_flags & MLX5_FLOW_ACTION_MARK)\n \t\t\t\tdev_flow->handle->rix_hrxq = hrxq_idx;\n@@ -8635,6 +8790,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\tuint32_t tag_be = mlx5_flow_mark_set\n \t\t\t\t(((const struct rte_flow_action_mark *)\n \t\t\t\t(sub_actions->conf))->id);\n+\n \t\t\tdev_flow->handle->mark = 1;\n \t\t\tpre_rix = dev_flow->handle->dvh.rix_tag;\n \t\t\t/* Save the mark resource before sample */\n@@ -8677,6 +8833,56 @@ struct field_modify_info modify_tcp[] = {\n \t\t\taction_flags |= MLX5_FLOW_ACTION_COUNT;\n \t\t\tbreak;\n \t\t}\n+\t\tcase RTE_FLOW_ACTION_TYPE_PORT_ID:\n+\t\t{\n+\t\t\tstruct mlx5_flow_dv_port_id_action_resource\n+\t\t\t\t\tport_id_resource;\n+\t\t\tuint32_t port_id = 0;\n+\n+\t\t\tmemset(&port_id_resource, 0, sizeof(port_id_resource));\n+\t\t\t/* Save the port id resource before sample */\n+\t\t\tpre_rix = dev_flow->handle->rix_port_id_action;\n+\t\t\tpre_r = dev_flow->dv.port_id_action;\n+\t\t\tif (flow_dv_translate_action_port_id(dev, sub_actions,\n+\t\t\t\t\t\t\t     &port_id, error))\n+\t\t\t\treturn -rte_errno;\n+\t\t\tport_id_resource.port_id = port_id;\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\tsample_act->dr_port_id_action =\n+\t\t\t\tdev_flow->dv.port_id_action->action;\n+\t\t\tsample_idx->rix_port_id_action =\n+\t\t\t\tdev_flow->handle->rix_port_id_action;\n+\t\t\tsample_actions[sample_act->actions_num++] =\n+\t\t\t\t\t\tsample_act->dr_port_id_action;\n+\t\t\t/* Recover the port id resource after sample */\n+\t\t\tdev_flow->dv.port_id_action = pre_r;\n+\t\t\tdev_flow->handle->rix_port_id_action = pre_rix;\n+\t\t\t(*num_of_dest)++;\n+\t\t\taction_flags |= MLX5_FLOW_ACTION_PORT_ID;\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase RTE_FLOW_ACTION_TYPE_RAW_ENCAP:\n+\t\t\t/* Save the encap resource before sample */\n+\t\t\tpre_rix = dev_flow->handle->dvh.rix_encap_decap;\n+\t\t\tpre_r = dev_flow->dv.encap_decap;\n+\t\t\tif (flow_dv_create_action_l2_encap(dev, sub_actions,\n+\t\t\t\t\t\t\t   dev_flow,\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\tsample_act->dr_encap_action =\n+\t\t\t\tdev_flow->dv.encap_decap->action;\n+\t\t\tsample_idx->rix_encap_decap =\n+\t\t\t\tdev_flow->handle->dvh.rix_encap_decap;\n+\t\t\tsample_actions[sample_act->actions_num++] =\n+\t\t\t\t\t\tsample_act->dr_encap_action;\n+\t\t\t/* Recover the encap resource after sample */\n+\t\t\tdev_flow->dv.encap_decap = pre_r;\n+\t\t\tdev_flow->handle->dvh.rix_encap_decap = pre_rix;\n+\t\t\taction_flags |= MLX5_FLOW_ACTION_ENCAP;\n+\t\t\tbreak;\n \t\tdefault:\n \t\t\treturn rte_flow_error_set(error, EINVAL,\n \t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n@@ -8715,10 +8921,16 @@ struct field_modify_info modify_tcp[] = {\n  *   Pointer to the mlx5_flow.\n  * @param[in] attr\n  *   Pointer to the flow attributes.\n+ * @param[in] num_of_dest\n+ *   The num of destination.\n  * @param[in, out] res\n  *   Pointer to sample resource.\n+ * @param[in, out] mdest_res\n+ *   Pointer to destination array resource.\n  * @param[in] sample_actions\n  *   Pointer to sample path actions list.\n+ * @param[in] action_flags\n+ *   Holds the actions detected until now.\n  * @param[out] error\n  *   Pointer to the error structure.\n  *\n@@ -8727,17 +8939,81 @@ struct field_modify_info modify_tcp[] = {\n  */\n static int\n flow_dv_create_action_sample(struct rte_eth_dev *dev,\n-\t\t\t\tstruct mlx5_flow *dev_flow,\n-\t\t\t\tconst struct rte_flow_attr *attr,\n-\t\t\t\tstruct mlx5_flow_dv_sample_resource *res,\n-\t\t\t\tvoid **sample_actions,\n-\t\t\t\tstruct rte_flow_error *error)\n+\t\t\t     struct mlx5_flow *dev_flow,\n+\t\t\t     const struct rte_flow_attr *attr,\n+\t\t\t     uint32_t num_of_dest,\n+\t\t\t     struct mlx5_flow_dv_sample_resource *res,\n+\t\t\t     struct mlx5_flow_dv_dest_array_resource *mdest_res,\n+\t\t\t     void **sample_actions,\n+\t\t\t     uint64_t action_flags,\n+\t\t\t     struct rte_flow_error *error)\n {\n-\tif (flow_dv_sample_resource_register(dev, attr, res, dev_flow,\n-\t\t\t\t\t\tsample_actions, error))\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  NULL, \"can't create sample action\");\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\t/* update normal path action resource into last index of array */\n+\tuint32_t dest_index = MLX5_MAX_DEST_NUM - 1;\n+\tstruct mlx5_flow_sub_actions_list *sample_act =\n+\t\t\t\t\t&mdest_res->sample_act[dest_index];\n+\tstruct mlx5_flow_rss_desc *rss_desc = &((struct mlx5_flow_rss_desc *)\n+\t\t\t\t\t      priv->rss_desc)\n+\t\t\t\t\t      [!!priv->flow_nested_idx];\n+\tuint32_t normal_idx = 0;\n+\tstruct mlx5_hrxq *hrxq;\n+\tuint32_t hrxq_idx;\n+\n+\tif (num_of_dest > 1) {\n+\t\tif (sample_act->action_flags & MLX5_FLOW_ACTION_QUEUE) {\n+\t\t\t/* Handle QP action for mirroring */\n+\t\t\thrxq = flow_dv_handle_rx_queue(dev, dev_flow,\n+\t\t\t\t\t\t       rss_desc, &hrxq_idx);\n+\t\t\tif (!hrxq)\n+\t\t\t\treturn rte_flow_error_set\n+\t\t\t\t     (error, rte_errno,\n+\t\t\t\t      RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t      NULL,\n+\t\t\t\t      \"cannot create rx queue\");\n+\t\t\tnormal_idx++;\n+\t\t\tmdest_res->sample_idx[dest_index].rix_hrxq = hrxq_idx;\n+\t\t\tsample_act->dr_queue_action = hrxq->action;\n+\t\t\tif (action_flags & MLX5_FLOW_ACTION_MARK)\n+\t\t\t\tdev_flow->handle->rix_hrxq = hrxq_idx;\n+\t\t\tdev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;\n+\t\t}\n+\t\tif (sample_act->action_flags & MLX5_FLOW_ACTION_ENCAP) {\n+\t\t\tnormal_idx++;\n+\t\t\tmdest_res->sample_idx[dest_index].rix_encap_decap =\n+\t\t\t\tdev_flow->handle->dvh.rix_encap_decap;\n+\t\t\tsample_act->dr_encap_action =\n+\t\t\t\tdev_flow->dv.encap_decap->action;\n+\t\t}\n+\t\tif (sample_act->action_flags & MLX5_FLOW_ACTION_PORT_ID) {\n+\t\t\tnormal_idx++;\n+\t\t\tmdest_res->sample_idx[dest_index].rix_port_id_action =\n+\t\t\t\tdev_flow->handle->rix_port_id_action;\n+\t\t\tsample_act->dr_port_id_action =\n+\t\t\t\tdev_flow->dv.port_id_action->action;\n+\t\t}\n+\t\tsample_act->actions_num = normal_idx;\n+\t\t/* update sample action resource into first index of array */\n+\t\tmdest_res->ft_type = res->ft_type;\n+\t\tmemcpy(&mdest_res->sample_idx[0], &res->sample_idx,\n+\t\t\t\tsizeof(struct mlx5_flow_sub_actions_idx));\n+\t\tmemcpy(&mdest_res->sample_act[0], &res->sample_act,\n+\t\t\t\tsizeof(struct mlx5_flow_sub_actions_list));\n+\t\tmdest_res->num_of_dest = num_of_dest;\n+\t\tif (flow_dv_dest_array_resource_register(dev, attr, mdest_res,\n+\t\t\t\t\t\t\t dev_flow, error))\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  NULL, \"can't create sample \"\n+\t\t\t\t\t\t  \"action\");\n+\t} else {\n+\t\tif (flow_dv_sample_resource_register(dev, attr, res, dev_flow,\n+\t\t\t\t\t\t     sample_actions, error))\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  NULL,\n+\t\t\t\t\t\t  \"can't create sample action\");\n+\t}\n \treturn 0;\n }\n \n@@ -8805,15 +9081,22 @@ struct field_modify_info modify_tcp[] = {\n \tvoid *match_value = dev_flow->dv.value.buf;\n \tuint8_t next_protocol = 0xff;\n \tstruct rte_vlan_hdr vlan = { 0 };\n+\tstruct mlx5_flow_dv_dest_array_resource mdest_res;\n \tstruct mlx5_flow_dv_sample_resource sample_res;\n \tvoid *sample_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};\n+\tstruct mlx5_flow_sub_actions_list *sample_act;\n \tuint32_t sample_act_pos = UINT32_MAX;\n+\tuint32_t num_of_dest = 0;\n+\tint tmp_actions_n = 0;\n \tuint32_t table;\n \tint ret = 0;\n \n+\tmemset(&mdest_res, 0, sizeof(struct mlx5_flow_dv_dest_array_resource));\n \tmemset(&sample_res, 0, sizeof(struct mlx5_flow_dv_sample_resource));\n \tmhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :\n \t\t\t\t\t   MLX5DV_FLOW_TABLE_TYPE_NIC_RX;\n+\t/* update normal path action resource into last index of array */\n+\tsample_act = &mdest_res.sample_act[MLX5_MAX_DEST_NUM - 1];\n \tret = mlx5_flow_group_to_table(attr, dev_flow->external, attr->group,\n \t\t\t\t       !!priv->fdb_def_rule, &table, error);\n \tif (ret)\n@@ -8860,6 +9143,8 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t\tdev_flow->dv.port_id_action->action;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_PORT_ID;\n \t\t\tdev_flow->handle->fate_action = MLX5_FLOW_FATE_PORT_ID;\n+\t\t\tsample_act->action_flags |= MLX5_FLOW_ACTION_PORT_ID;\n+\t\t\tnum_of_dest++;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_FLAG:\n \t\t\taction_flags |= MLX5_FLOW_ACTION_FLAG;\n@@ -8945,6 +9230,8 @@ struct field_modify_info modify_tcp[] = {\n \t\t\trss_desc->queue[0] = queue->index;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_QUEUE;\n \t\t\tdev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;\n+\t\t\tsample_act->action_flags |= MLX5_FLOW_ACTION_QUEUE;\n+\t\t\tnum_of_dest++;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_RSS:\n \t\t\trss = actions->conf;\n@@ -9032,6 +9319,9 @@ struct field_modify_info modify_tcp[] = {\n \t\t\tdev_flow->dv.actions[actions_n++] =\n \t\t\t\t\tdev_flow->dv.encap_decap->action;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_ENCAP;\n+\t\t\tif (action_flags & MLX5_FLOW_ACTION_SAMPLE)\n+\t\t\t\tsample_act->action_flags |=\n+\t\t\t\t\t\t\tMLX5_FLOW_ACTION_ENCAP;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:\n \t\tcase RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:\n@@ -9061,6 +9351,9 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t\tdev_flow->dv.encap_decap->action;\n \t\t\t}\n \t\t\taction_flags |= MLX5_FLOW_ACTION_ENCAP;\n+\t\t\tif (action_flags & MLX5_FLOW_ACTION_SAMPLE)\n+\t\t\t\tsample_act->action_flags |=\n+\t\t\t\t\t\t\tMLX5_FLOW_ACTION_ENCAP;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_RAW_DECAP:\n \t\t\twhile ((++action)->type == RTE_FLOW_ACTION_TYPE_VOID)\n@@ -9253,6 +9546,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\tret = flow_dv_translate_action_sample(dev,\n \t\t\t\t\t\t\t      actions,\n \t\t\t\t\t\t\t      dev_flow, attr,\n+\t\t\t\t\t\t\t      &num_of_dest,\n \t\t\t\t\t\t\t      sample_actions,\n \t\t\t\t\t\t\t      &sample_res,\n \t\t\t\t\t\t\t      error);\n@@ -9260,6 +9554,11 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\treturn ret;\n \t\t\tactions_n++;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_SAMPLE;\n+\t\t\t/* put encap action into group if work with port id */\n+\t\t\tif ((action_flags & MLX5_FLOW_ACTION_ENCAP) &&\n+\t\t\t    (action_flags & MLX5_FLOW_ACTION_PORT_ID))\n+\t\t\t\tsample_act->action_flags |=\n+\t\t\t\t\t\t\tMLX5_FLOW_ACTION_ENCAP;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_END:\n \t\t\tactions_end = true;\n@@ -9283,15 +9582,19 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t\t\tNULL,\n \t\t\t\t\t\t\"cannot create counter\"\n \t\t\t\t\t\t\" object.\");\n-\t\t\t\tdev_flow->dv.actions[actions_n++] =\n+\t\t\t\tdev_flow->dv.actions[actions_n] =\n \t\t\t\t\t  (flow_dv_counter_get_by_idx(dev,\n \t\t\t\t\t  flow->counter, NULL))->action;\n+\t\t\t\tactions_n++;\n \t\t\t}\n \t\t\tif (action_flags & MLX5_FLOW_ACTION_SAMPLE) {\n \t\t\t\tret = flow_dv_create_action_sample(dev,\n \t\t\t\t\t\t\t  dev_flow, attr,\n+\t\t\t\t\t\t\t  num_of_dest,\n \t\t\t\t\t\t\t  &sample_res,\n+\t\t\t\t\t\t\t  &mdest_res,\n \t\t\t\t\t\t\t  sample_actions,\n+\t\t\t\t\t\t\t  action_flags,\n \t\t\t\t\t\t\t  error);\n \t\t\t\tif (ret < 0)\n \t\t\t\t\treturn rte_flow_error_set\n@@ -9299,8 +9602,13 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n \t\t\t\t\t\tNULL,\n \t\t\t\t\t\t\"cannot create sample action\");\n-\t\t\t\tdev_flow->dv.actions[sample_act_pos] =\n+\t\t\t\tif (num_of_dest > 1) {\n+\t\t\t\t\tdev_flow->dv.actions[sample_act_pos] =\n+\t\t\t\t\tdev_flow->dv.dest_array_res->action;\n+\t\t\t\t} else {\n+\t\t\t\t\tdev_flow->dv.actions[sample_act_pos] =\n \t\t\t\t\tdev_flow->dv.sample_res->verbs_action;\n+\t\t\t\t}\n \t\t\t}\n \t\t\tbreak;\n \t\tdefault:\n@@ -9310,6 +9618,31 @@ struct field_modify_info modify_tcp[] = {\n \t\t    modify_action_position == UINT32_MAX)\n \t\t\tmodify_action_position = actions_n++;\n \t}\n+\t/*\n+\t * For multiple destination (sample action with ratio=1), the encap\n+\t * action and port id action will be combined into group action.\n+\t * So need remove the original these actions in the flow and only\n+\t * use the sample action instead of.\n+\t */\n+\tif (num_of_dest > 1 && sample_act->dr_port_id_action) {\n+\t\tint i;\n+\t\tvoid *temp_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};\n+\n+\t\tfor (i = 0; i < actions_n; i++) {\n+\t\t\tif ((sample_act->dr_encap_action &&\n+\t\t\t\tsample_act->dr_encap_action ==\n+\t\t\t\tdev_flow->dv.actions[i]) ||\n+\t\t\t\t(sample_act->dr_port_id_action &&\n+\t\t\t\tsample_act->dr_port_id_action ==\n+\t\t\t\tdev_flow->dv.actions[i]))\n+\t\t\t\tcontinue;\n+\t\t\ttemp_actions[tmp_actions_n++] = dev_flow->dv.actions[i];\n+\t\t}\n+\t\tmemcpy((void *)dev_flow->dv.actions,\n+\t\t\t\t(void *)temp_actions,\n+\t\t\t\ttmp_actions_n * sizeof(void *));\n+\t\tactions_n = tmp_actions_n;\n+\t}\n \tdev_flow->dv.actions_n = actions_n;\n \tdev_flow->act_flags = action_flags;\n \tfor (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {\n@@ -9614,7 +9947,7 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\tdv->actions[n++] = drop_hrxq->action;\n \t\t\t}\n \t\t} else if (dh->fate_action == MLX5_FLOW_FATE_QUEUE &&\n-\t\t\t   !dv_h->rix_sample) {\n+\t\t\t   !dv_h->rix_sample && !dv_h->rix_dest_array) {\n \t\t\tstruct mlx5_hrxq *hrxq;\n \t\t\tuint32_t hrxq_idx;\n \t\t\tstruct mlx5_flow_rss_desc *rss_desc =\n@@ -9900,11 +10233,11 @@ struct field_modify_info modify_tcp[] = {\n  */\n static int\n flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev,\n-\t\t\t\t\tstruct mlx5_flow_handle *handle)\n+\t\t\t\t\tuint32_t port_id)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_flow_dv_port_id_action_resource *cache_resource;\n-\tuint32_t idx = handle->rix_port_id_action;\n+\tuint32_t idx = port_id;\n \n \tcache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PORT_ID],\n \t\t\t\t\tidx);\n@@ -9994,7 +10327,8 @@ struct field_modify_info modify_tcp[] = {\n \t\tflow_dv_jump_tbl_resource_release(dev, handle);\n \t\tbreak;\n \tcase MLX5_FLOW_FATE_PORT_ID:\n-\t\tflow_dv_port_id_action_resource_release(dev, handle);\n+\t\tflow_dv_port_id_action_resource_release(dev,\n+\t\t\t\thandle->rix_port_id_action);\n \t\tbreak;\n \tcase MLX5_FLOW_FATE_DEFAULT_MISS:\n \t\tflow_dv_default_miss_resource_release(dev);\n@@ -10072,6 +10406,73 @@ struct field_modify_info modify_tcp[] = {\n }\n \n /**\n+ * Release an destination array resource.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device.\n+ * @param handle\n+ *   Pointer to mlx5_flow_handle.\n+ *\n+ * @return\n+ *   1 while a reference on it exists, 0 when freed.\n+ */\n+static int\n+flow_dv_dest_array_resource_release(struct rte_eth_dev *dev,\n+\t\t\t\t     struct mlx5_flow_handle *handle)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_flow_dv_dest_array_resource *cache_resource;\n+\tstruct mlx5_flow_sub_actions_idx *mdest_act_res;\n+\tuint32_t idx = handle->dvh.rix_dest_array;\n+\tuint32_t i = 0;\n+\n+\tcache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n+\t\t\t idx);\n+\tif (!cache_resource)\n+\t\treturn 0;\n+\tMLX5_ASSERT(cache_resource->action);\n+\tDRV_LOG(DEBUG, \"destination array resource %p: refcnt %d--\",\n+\t\t(void *)cache_resource,\n+\t\trte_atomic32_read(&cache_resource->refcnt));\n+\tif (rte_atomic32_dec_and_test(&cache_resource->refcnt)) {\n+\t\tif (cache_resource->action)\n+\t\t\tclaim_zero(mlx5_glue->destroy_flow_action\n+\t\t\t\t\t\t(cache_resource->action));\n+\t\tfor (; i < cache_resource->num_of_dest; i++) {\n+\t\t\tmdest_act_res = &cache_resource->sample_idx[i];\n+\t\t\tif (mdest_act_res->rix_hrxq) {\n+\t\t\t\tmlx5_hrxq_release(dev,\n+\t\t\t\t\tmdest_act_res->rix_hrxq);\n+\t\t\t\tmdest_act_res->rix_hrxq = 0;\n+\t\t\t}\n+\t\t\tif (mdest_act_res->rix_encap_decap) {\n+\t\t\t\tflow_dv_encap_decap_resource_release(dev,\n+\t\t\t\t\tmdest_act_res->rix_encap_decap);\n+\t\t\t\tmdest_act_res->rix_encap_decap = 0;\n+\t\t\t}\n+\t\t\tif (mdest_act_res->rix_port_id_action) {\n+\t\t\t\tflow_dv_port_id_action_resource_release(dev,\n+\t\t\t\t\tmdest_act_res->rix_port_id_action);\n+\t\t\t\tmdest_act_res->rix_port_id_action = 0;\n+\t\t\t}\n+\t\t\tif (mdest_act_res->rix_tag) {\n+\t\t\t\tflow_dv_tag_release(dev,\n+\t\t\t\t\tmdest_act_res->rix_tag);\n+\t\t\t\tmdest_act_res->rix_tag = 0;\n+\t\t\t}\n+\t\t}\n+\t\tILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY],\n+\t\t\t     &priv->sh->dest_array_list, idx,\n+\t\t\t     cache_resource, next);\n+\t\tmlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY], idx);\n+\t\tDRV_LOG(DEBUG, \"destination array resource %p: removed\",\n+\t\t\t(void *)cache_resource);\n+\t\treturn 0;\n+\t}\n+\treturn 1;\n+}\n+\n+/**\n  * Remove the flow from the NIC but keeps it in memory.\n  * Lock free, (mutex should be acquired by caller).\n  *\n@@ -10152,6 +10553,8 @@ struct field_modify_info modify_tcp[] = {\n \t\t\tflow_dv_matcher_release(dev, dev_handle);\n \t\tif (dev_handle->dvh.rix_sample)\n \t\t\tflow_dv_sample_resource_release(dev, dev_handle);\n+\t\tif (dev_handle->dvh.rix_dest_array)\n+\t\t\tflow_dv_dest_array_resource_release(dev, dev_handle);\n \t\tif (dev_handle->dvh.rix_encap_decap)\n \t\t\tflow_dv_encap_decap_resource_release(dev,\n \t\t\t\tdev_handle->dvh.rix_encap_decap);\n",
    "prefixes": [
        "v2",
        "08/10"
    ]
}