get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 76091,
    "url": "http://patches.dpdk.org/api/patches/76091/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1598540492-406340-7-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": "<1598540492-406340-7-git-send-email-jiaweiw@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1598540492-406340-7-git-send-email-jiaweiw@nvidia.com",
    "date": "2020-08-27T15:01:31",
    "name": "[v5,6/7] net/mlx5: update translate function for sample action",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "db713b429f9c566ec55353107ba05f2a160cb81f",
    "submitter": {
        "id": 1939,
        "url": "http://patches.dpdk.org/api/people/1939/?format=api",
        "name": "Jiawei Wang",
        "email": "jiaweiw@nvidia.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1598540492-406340-7-git-send-email-jiaweiw@nvidia.com/mbox/",
    "series": [
        {
            "id": 11829,
            "url": "http://patches.dpdk.org/api/series/11829/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=11829",
            "date": "2020-08-27T15:01:30",
            "name": "support the flow-based traffic sampling",
            "version": 5,
            "mbox": "http://patches.dpdk.org/series/11829/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/76091/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/76091/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 CE583A04B1;\n\tThu, 27 Aug 2020 17:23:39 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 02B871C0BC;\n\tThu, 27 Aug 2020 17:22:53 +0200 (CEST)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by dpdk.org (Postfix) with ESMTP id 08D0E1BFE1\n for <dev@dpdk.org>; Thu, 27 Aug 2020 17:22:41 +0200 (CEST)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n jiaweiw@nvidia.com) with SMTP; 27 Aug 2020 18:22:37 +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 07RF1W7r029794;\n Thu, 27 Aug 2020 18:01:32 +0300"
        ],
        "From": "Jiawei Wang <jiaweiw@nvidia.com>",
        "To": "orika@nvidia.com, viacheslavo@nvidia.com, matan@nvidia.com",
        "Cc": "dev@dpdk.org, thomas@monjalon.net, rasland@nvidia.com,\n ian.stokes@intel.com, fbl@redhat.com, jiaweiw@nvidia.com, asafp@nvidia.com",
        "Date": "Thu, 27 Aug 2020 18:01:31 +0300",
        "Message-Id": "<1598540492-406340-7-git-send-email-jiaweiw@nvidia.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1598540492-406340-1-git-send-email-jiaweiw@nvidia.com>",
        "References": "<1598457725-396788-1-git-send-email-jiaweiw@nvidia.com>\n <1598540492-406340-1-git-send-email-jiaweiw@nvidia.com>",
        "Subject": "[dpdk-dev] [PATCH v5 6/7] net/mlx5: update translate function for\n\tsample action",
        "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, then create the sample DR action.\n\nSigned-off-by: Jiawei Wang <jiaweiw@nvidia.com>\nAcked-by: Ori Kam <orika@nvidia.com>\n---\n drivers/net/mlx5/mlx5_flow.c    |  16 +-\n drivers/net/mlx5/mlx5_flow.h    |  14 +-\n drivers/net/mlx5/mlx5_flow_dv.c | 494 +++++++++++++++++++++++++++++++++++++++-\n 3 files changed, 502 insertions(+), 22 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex 49f49e7..d2b79f0 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -4606,10 +4606,14 @@ struct mlx5_flow_tunnel_info {\n \tint hairpin_flow;\n \tuint32_t hairpin_id = 0;\n \tstruct rte_flow_attr attr_tx = { .priority = 0 };\n+\tstruct rte_flow_attr attr_factor = {0};\n \tint ret;\n \n-\thairpin_flow = flow_check_hairpin_split(dev, attr, actions);\n-\tret = flow_drv_validate(dev, attr, items, p_actions_rx,\n+\tmemcpy((void *)&attr_factor, (const void *)attr, sizeof(*attr));\n+\tif (external)\n+\t\tattr_factor.group *= MLX5_FLOW_TABLE_FACTOR;\n+\thairpin_flow = flow_check_hairpin_split(dev, &attr_factor, actions);\n+\tret = flow_drv_validate(dev, &attr_factor, items, p_actions_rx,\n \t\t\t\texternal, hairpin_flow, error);\n \tif (ret < 0)\n \t\treturn 0;\n@@ -4628,7 +4632,7 @@ struct mlx5_flow_tunnel_info {\n \t\trte_errno = ENOMEM;\n \t\tgoto error_before_flow;\n \t}\n-\tflow->drv_type = flow_get_drv_type(dev, attr);\n+\tflow->drv_type = flow_get_drv_type(dev, &attr_factor);\n \tif (hairpin_id != 0)\n \t\tflow->hairpin_flow_id = hairpin_id;\n \tMLX5_ASSERT(flow->drv_type > MLX5_FLOW_TYPE_MIN &&\n@@ -4674,7 +4678,7 @@ struct mlx5_flow_tunnel_info {\n \t\t * depending on configuration. In the simplest\n \t\t * case it just creates unmodified original flow.\n \t\t */\n-\t\tret = flow_create_split_outer(dev, flow, attr,\n+\t\tret = flow_create_split_outer(dev, flow, &attr_factor,\n \t\t\t\t\t      buf->entry[i].pattern,\n \t\t\t\t\t      p_actions_rx, external, idx,\n \t\t\t\t\t      error);\n@@ -4711,8 +4715,8 @@ struct mlx5_flow_tunnel_info {\n \t * the egress Flows belong to the different device and\n \t * copy table should be updated in peer NIC Rx domain.\n \t */\n-\tif (attr->ingress &&\n-\t    (external || attr->group != MLX5_FLOW_MREG_CP_TABLE_GROUP)) {\n+\tif (attr_factor.ingress &&\n+\t    (external || attr_factor.group != MLX5_FLOW_MREG_CP_TABLE_GROUP)) {\n \t\tret = flow_mreg_update_copy_table(dev, flow, actions, error);\n \t\tif (ret)\n \t\t\tgoto error;\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex 9d2493a..f3c0406 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -366,6 +366,13 @@ enum mlx5_flow_fate_type {\n \tMLX5_FLOW_FATE_MAX,\n };\n \n+/*\n+ * Max number of actions per DV flow.\n+ * See CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED\n+ * in rdma-core file providers/mlx5/verbs.c.\n+ */\n+#define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8\n+\n /* Matcher PRM representation */\n struct mlx5_flow_dv_match_params {\n \tsize_t size;\n@@ -613,13 +620,6 @@ struct mlx5_flow_handle {\n #define MLX5_FLOW_HANDLE_VERBS_SIZE (sizeof(struct mlx5_flow_handle))\n #endif\n \n-/*\n- * Max number of actions per DV flow.\n- * See CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED\n- * in rdma-core file providers/mlx5/verbs.c.\n- */\n-#define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8\n-\n /** Device flow structure only for DV flow creation. */\n struct mlx5_flow_dv_workspace {\n \tuint32_t group; /**< The group index. */\ndiff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex a8db8ab..3d85140 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -76,6 +76,10 @@\n static int\n flow_dv_default_miss_resource_release(struct rte_eth_dev *dev);\n \n+static int\n+flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev,\n+\t\t\t\t      uint32_t encap_decap_idx);\n+\n /**\n  * Initialize flow attributes structure according to flow items' types.\n  *\n@@ -8233,6 +8237,373 @@ struct field_modify_info modify_tcp[] = {\n }\n \n /**\n+ * Create an Rx Hash queue.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device.\n+ * @param[in] dev_flow\n+ *   Pointer to the mlx5_flow.\n+ * @param[in] rss_desc\n+ *   Pointer to the mlx5_flow_rss_desc.\n+ * @param[out] hrxq_idx\n+ *   Hash Rx queue index.\n+ *\n+ * @return\n+ *   The Verbs/DevX object initialised, NULL otherwise and rte_errno is set.\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+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_flow_handle *dh = dev_flow->handle;\n+\tstruct mlx5_hrxq *hrxq;\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+\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\tif (!*hrxq_idx)\n+\t\t\treturn NULL;\n+\t}\n+\thrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],\n+\t\t\t      *hrxq_idx);\n+\treturn hrxq;\n+}\n+\n+/**\n+ * Find existing sample 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 sample resource.\n+ * @parm[in, out] dev_flow\n+ *   Pointer to the dev_flow.\n+ * @param[in, out] sample_dv_actions\n+ *   Pointer to sample actions list.\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_sample_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_sample_resource *resource,\n+\t\t\t struct mlx5_flow *dev_flow,\n+\t\t\t void **sample_dv_actions,\n+\t\t\t struct rte_flow_error *error)\n+{\n+\tstruct mlx5_flow_dv_sample_resource *cache_resource;\n+\tstruct mlx5dv_dr_flow_sampler_attr sampler_attr;\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_dev_ctx_shared *sh = priv->sh;\n+\tstruct mlx5_flow_tbl_resource *tbl;\n+\tuint32_t idx = 0;\n+\tconst uint32_t next_ft_step = 1;\n+\tuint32_t next_ft_id = resource->ft_id +\tnext_ft_step;\n+\n+\t/* Lookup a matching resource from cache. */\n+\tILIST_FOREACH(sh->ipool[MLX5_IPOOL_SAMPLE], sh->sample_action_list,\n+\t\t      idx, cache_resource, next) {\n+\t\tif (resource->ratio == cache_resource->ratio &&\n+\t\t    resource->ft_type == cache_resource->ft_type &&\n+\t\t    resource->ft_id == cache_resource->ft_id &&\n+\t\t    !memcmp((void *)&resource->sample_act,\n+\t\t\t    (void *)&cache_resource->sample_act,\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_sample = idx;\n+\t\t\tdev_flow->dv.sample_res = cache_resource;\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\t/* Register new sample resource. */\n+\tcache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_SAMPLE],\n+\t\t\t\t       &dev_flow->handle->dvh.rix_sample);\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+\t/* Create normal path table level */\n+\ttbl = flow_dv_tbl_resource_get(dev, next_ft_id,\n+\t\t\t\t\tattr->egress, attr->transfer, error);\n+\tif (!tbl) {\n+\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  \"fail to create normal path table \"\n+\t\t\t\t\t  \"for sample\");\n+\t\tgoto error;\n+\t}\n+\tcache_resource->normal_path_tbl = tbl;\n+\tif (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {\n+\t\tcache_resource->default_miss =\n+\t\t\t\tmlx5_glue->dr_create_flow_action_default_miss();\n+\t\tif (!cache_resource->default_miss) {\n+\t\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t\t\tNULL,\n+\t\t\t\t\t\t\"cannot create default miss \"\n+\t\t\t\t\t\t\"action\");\n+\t\t\tgoto error;\n+\t\t}\n+\t\tsample_dv_actions[resource->sample_act.actions_num++] =\n+\t\t\t\t\t\tcache_resource->default_miss;\n+\t}\n+\t/* Create a DR sample action */\n+\tsampler_attr.sample_ratio = cache_resource->ratio;\n+\tsampler_attr.default_next_table = tbl->obj;\n+\tsampler_attr.num_sample_actions = resource->sample_act.actions_num;\n+\tsampler_attr.sample_actions = (struct mlx5dv_dr_action **)\n+\t\t\t\t\t\t\t&sample_dv_actions[0];\n+\tcache_resource->verbs_action =\n+\t\tmlx5_glue->dr_create_flow_action_sampler(&sampler_attr);\n+\tif (!cache_resource->verbs_action) {\n+\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t\tNULL, \"cannot create sample 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_SAMPLE], &sh->sample_action_list,\n+\t\t     dev_flow->handle->dvh.rix_sample, cache_resource,\n+\t\t     next);\n+\tdev_flow->dv.sample_res = cache_resource;\n+\tDRV_LOG(DEBUG, \"new sample resource %p: refcnt %d++\",\n+\t\t(void *)cache_resource,\n+\t\trte_atomic32_read(&cache_resource->refcnt));\n+\treturn 0;\n+error:\n+\tif (cache_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {\n+\t\tif (cache_resource->default_miss)\n+\t\t\tclaim_zero(mlx5_glue->destroy_flow_action\n+\t\t\t\t(cache_resource->default_miss));\n+\t} else {\n+\t\tif (cache_resource->sample_idx.rix_hrxq &&\n+\t\t    !mlx5_hrxq_release(dev,\n+\t\t\t\tcache_resource->sample_idx.rix_hrxq))\n+\t\t\tcache_resource->sample_idx.rix_hrxq = 0;\n+\t\tif (cache_resource->sample_idx.rix_tag &&\n+\t\t    !flow_dv_tag_release(dev,\n+\t\t\t\tcache_resource->sample_idx.rix_tag))\n+\t\t\tcache_resource->sample_idx.rix_tag = 0;\n+\t\tif (cache_resource->sample_idx.cnt) {\n+\t\t\tflow_dv_counter_release(dev,\n+\t\t\t\tcache_resource->sample_idx.cnt);\n+\t\t\tcache_resource->sample_idx.cnt = 0;\n+\t\t}\n+\t}\n+\tif (cache_resource->normal_path_tbl)\n+\t\tflow_dv_tbl_resource_release(dev,\n+\t\t\t\tcache_resource->normal_path_tbl);\n+\tmlx5_ipool_free(sh->ipool[MLX5_IPOOL_SAMPLE],\n+\t\t\t\tdev_flow->handle->dvh.rix_sample);\n+\tdev_flow->handle->dvh.rix_sample = 0;\n+\treturn -rte_errno;\n+}\n+\n+/**\n+ * Convert Sample action to DV specification.\n+ *\n+ * @param[in] dev\n+ *   Pointer to rte_eth_dev structure.\n+ * @param[in] action\n+ *   Pointer to action structure.\n+ * @param[in, out] dev_flow\n+ *   Pointer to the mlx5_flow.\n+ * @param[in] attr\n+ *   Pointer to the flow attributes.\n+ * @param[in, out] sample_actions\n+ *   Pointer to sample actions list.\n+ * @param[in, out] res\n+ *   Pointer to sample resource.\n+ * @param[out] error\n+ *   Pointer to the error structure.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+flow_dv_translate_action_sample(struct rte_eth_dev *dev,\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\tvoid **sample_actions,\n+\t\t\t\tstruct mlx5_flow_dv_sample_resource *res,\n+\t\t\t\tstruct rte_flow_error *error)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tconst struct rte_flow_action_sample *sample_action;\n+\tconst struct rte_flow_action *sub_actions;\n+\tconst struct rte_flow_action_queue *queue;\n+\tstruct mlx5_flow_sub_actions_list *sample_act;\n+\tstruct mlx5_flow_sub_actions_idx *sample_idx;\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+\tuint64_t action_flags = 0;\n+\n+\tsample_act = &res->sample_act;\n+\tsample_idx = &res->sample_idx;\n+\tsample_action = (const struct rte_flow_action_sample *)action->conf;\n+\tres->ratio = sample_action->ratio;\n+\tsub_actions = sample_action->actions;\n+\tfor (; sub_actions->type != RTE_FLOW_ACTION_TYPE_END; sub_actions++) {\n+\t\tint type = sub_actions->type;\n+\t\tuint32_t pre_rix = 0;\n+\t\tvoid *pre_r;\n+\t\tswitch (type) {\n+\t\tcase RTE_FLOW_ACTION_TYPE_QUEUE:\n+\t\t{\n+\t\t\tstruct mlx5_hrxq *hrxq;\n+\t\t\tuint32_t hrxq_idx;\n+\n+\t\t\tqueue = sub_actions->conf;\n+\t\t\trss_desc->queue_num = 1;\n+\t\t\trss_desc->queue[0] = queue->index;\n+\t\t\thrxq = flow_dv_handle_rx_queue(dev, dev_flow,\n+\t\t\t\t\trss_desc, &hrxq_idx);\n+\t\t\tif (!hrxq)\n+\t\t\t\treturn rte_flow_error_set\n+\t\t\t\t\t(error, rte_errno,\n+\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t NULL,\n+\t\t\t\t\t \"cannot create fate queue\");\n+\t\t\tsample_act->dr_queue_action = hrxq->action;\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\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+\t\t\tdev_flow->handle->fate_action =\n+\t\t\t\t\tMLX5_FLOW_FATE_QUEUE;\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase RTE_FLOW_ACTION_TYPE_MARK:\n+\t\t{\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+\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+\t\t\tpre_r = dev_flow->dv.tag_resource;\n+\t\t\tif (flow_dv_tag_resource_register(dev, tag_be,\n+\t\t\t\t\t\t  dev_flow, error))\n+\t\t\t\treturn -rte_errno;\n+\t\t\tMLX5_ASSERT(dev_flow->dv.tag_resource);\n+\t\t\tsample_act->dr_tag_action =\n+\t\t\t\tdev_flow->dv.tag_resource->action;\n+\t\t\tsample_idx->rix_tag =\n+\t\t\t\tdev_flow->handle->dvh.rix_tag;\n+\t\t\tsample_actions[sample_act->actions_num++] =\n+\t\t\t\t\t\tsample_act->dr_tag_action;\n+\t\t\t/* Recover the mark resource after sample */\n+\t\t\tdev_flow->dv.tag_resource = pre_r;\n+\t\t\tdev_flow->handle->dvh.rix_tag = pre_rix;\n+\t\t\taction_flags |= MLX5_FLOW_ACTION_MARK;\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n+\t\t{\n+\t\t\tuint32_t counter;\n+\n+\t\t\tcounter = flow_dv_translate_create_counter(dev,\n+\t\t\t\t\tdev_flow, sub_actions->conf, 0);\n+\t\t\tif (!counter)\n+\t\t\t\treturn rte_flow_error_set\n+\t\t\t\t\t\t(error, rte_errno,\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 \"cannot create counter\"\n+\t\t\t\t\t\t \" object.\");\n+\t\t\tsample_idx->cnt = counter;\n+\t\t\tsample_act->dr_cnt_action =\n+\t\t\t\t  (flow_dv_counter_get_by_idx(dev,\n+\t\t\t\t  counter, NULL))->action;\n+\t\t\tsample_actions[sample_act->actions_num++] =\n+\t\t\t\t\t\tsample_act->dr_cnt_action;\n+\t\t\taction_flags |= MLX5_FLOW_ACTION_COUNT;\n+\t\t\tbreak;\n+\t\t}\n+\t\tdefault:\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\tNULL,\n+\t\t\t\t\"Not support for sampler action\");\n+\t\t}\n+\t}\n+\tsample_act->action_flags = action_flags;\n+\tres->ft_id = dev_flow->dv.group;\n+\tif (attr->transfer)\n+\t\tres->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;\n+\telse if (attr->ingress)\n+\t\tres->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * Convert Sample action to DV specification.\n+ *\n+ * @param[in] dev\n+ *   Pointer to rte_eth_dev structure.\n+ * @param[in, out] dev_flow\n+ *   Pointer to the mlx5_flow.\n+ * @param[in] attr\n+ *   Pointer to the flow attributes.\n+ * @param[in, out] res\n+ *   Pointer to sample resource.\n+ * @param[in] sample_actions\n+ *   Pointer to sample path actions list.\n+ * @param[out] error\n+ *   Pointer to the error structure.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\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+{\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+\treturn 0;\n+}\n+\n+/**\n  * Fill the flow with DV spec, lock free\n  * (mutex should be acquired by caller).\n  *\n@@ -8296,9 +8667,13 @@ 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_sample_resource sample_res;\n+\tvoid *sample_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};\n+\tuint32_t sample_act_pos = UINT32_MAX;\n \tuint32_t table;\n \tint ret = 0;\n \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 \tret = mlx5_flow_group_to_table(attr, dev_flow->external, attr->group,\n@@ -8317,7 +8692,6 @@ struct field_modify_info modify_tcp[] = {\n \t\tconst struct rte_flow_action_rss *rss;\n \t\tconst struct rte_flow_action *action = actions;\n \t\tconst uint8_t *rss_key;\n-\t\tconst struct rte_flow_action_jump *jump_data;\n \t\tconst struct rte_flow_action_meter *mtr;\n \t\tstruct mlx5_flow_tbl_resource *tbl;\n \t\tuint32_t port_id = 0;\n@@ -8325,6 +8699,7 @@ struct field_modify_info modify_tcp[] = {\n \t\tint action_type = actions->type;\n \t\tconst struct rte_flow_action *found_action = NULL;\n \t\tstruct mlx5_flow_meter *fm = NULL;\n+\t\tuint32_t jump_group = 0;\n \n \t\tif (!mlx5_flow_os_action_supported(action_type))\n \t\t\treturn rte_flow_error_set(error, ENOTSUP,\n@@ -8563,9 +8938,13 @@ struct field_modify_info modify_tcp[] = {\n \t\t\taction_flags |= MLX5_FLOW_ACTION_DECAP;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_JUMP:\n-\t\t\tjump_data = action->conf;\n+\t\t\tjump_group = ((const struct rte_flow_action_jump *)\n+\t\t\t\t\t\t\taction->conf)->group;\n+\t\t\tif (dev_flow->external && jump_group <\n+\t\t\t\t\tMLX5_MAX_TABLES_EXTERNAL)\n+\t\t\t\tjump_group *= MLX5_FLOW_TABLE_FACTOR;\n \t\t\tret = mlx5_flow_group_to_table(attr, dev_flow->external,\n-\t\t\t\t\t\t       jump_data->group,\n+\t\t\t\t\t\t       jump_group,\n \t\t\t\t\t\t       !!priv->fdb_def_rule,\n \t\t\t\t\t\t       &table, error);\n \t\t\tif (ret)\n@@ -8731,6 +9110,19 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\treturn -rte_errno;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_SET_IPV6_DSCP;\n \t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_SAMPLE:\n+\t\t\tsample_act_pos = actions_n;\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      sample_actions,\n+\t\t\t\t\t\t\t      &sample_res,\n+\t\t\t\t\t\t\t      error);\n+\t\t\tif (ret < 0)\n+\t\t\t\treturn ret;\n+\t\t\tactions_n++;\n+\t\t\taction_flags |= MLX5_FLOW_ACTION_SAMPLE;\n+\t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_END:\n \t\t\tactions_end = true;\n \t\t\tif (mhdr_res->actions_num) {\n@@ -8757,6 +9149,21 @@ struct field_modify_info modify_tcp[] = {\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}\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  &sample_res,\n+\t\t\t\t\t\t\t  sample_actions,\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+\t\t\t\t\t\t(error, rte_errno,\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\t\tdev_flow->dv.sample_res->verbs_action;\n+\t\t\t}\n \t\t\tbreak;\n \t\tdefault:\n \t\t\tbreak;\n@@ -9068,7 +9475,8 @@ struct field_modify_info modify_tcp[] = {\n \t\t\t\tdh->rix_hrxq = UINT32_MAX;\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} else if (dh->fate_action == MLX5_FLOW_FATE_QUEUE &&\n+\t\t\t   !dv_h->rix_sample) {\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@@ -9200,18 +9608,18 @@ struct field_modify_info modify_tcp[] = {\n  *\n  * @param dev\n  *   Pointer to Ethernet device.\n- * @param handle\n- *   Pointer to mlx5_flow_handle.\n+ * @param encap_decap_idx\n+ *   Index of encap decap resource.\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 rte_eth_dev *dev,\n-\t\t\t\t     struct mlx5_flow_handle *handle)\n+\t\t\t\t     uint32_t encap_decap_idx)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tuint32_t idx = handle->dvh.rix_encap_decap;\n+\tuint32_t idx = encap_decap_idx;\n \tstruct mlx5_flow_dv_encap_decap_resource *cache_resource;\n \n \tcache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DECAP_ENCAP],\n@@ -9462,6 +9870,71 @@ struct field_modify_info modify_tcp[] = {\n }\n \n /**\n+ * Release an sample 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_sample_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+\tuint32_t idx = handle->dvh.rix_sample;\n+\tstruct mlx5_flow_dv_sample_resource *cache_resource;\n+\n+\tcache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_SAMPLE],\n+\t\t\t idx);\n+\tif (!cache_resource)\n+\t\treturn 0;\n+\tMLX5_ASSERT(cache_resource->verbs_action);\n+\tDRV_LOG(DEBUG, \"sample 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->verbs_action)\n+\t\t\tclaim_zero(mlx5_glue->destroy_flow_action\n+\t\t\t\t\t(cache_resource->verbs_action));\n+\t\tif (cache_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {\n+\t\t\tif (cache_resource->default_miss)\n+\t\t\t\tclaim_zero(mlx5_glue->destroy_flow_action\n+\t\t\t\t  (cache_resource->default_miss));\n+\t\t}\n+\t\tif (cache_resource->normal_path_tbl)\n+\t\t\tflow_dv_tbl_resource_release(dev,\n+\t\t\t\tcache_resource->normal_path_tbl);\n+\t}\n+\tif (cache_resource->sample_idx.rix_hrxq &&\n+\t\t!mlx5_hrxq_release(dev,\n+\t\t\tcache_resource->sample_idx.rix_hrxq))\n+\t\tcache_resource->sample_idx.rix_hrxq = 0;\n+\tif (cache_resource->sample_idx.rix_tag &&\n+\t\t!flow_dv_tag_release(dev,\n+\t\t\tcache_resource->sample_idx.rix_tag))\n+\t\tcache_resource->sample_idx.rix_tag = 0;\n+\tif (cache_resource->sample_idx.cnt) {\n+\t\tflow_dv_counter_release(dev,\n+\t\t\tcache_resource->sample_idx.cnt);\n+\t\tcache_resource->sample_idx.cnt = 0;\n+\t}\n+\tif (!rte_atomic32_read(&cache_resource->refcnt)) {\n+\t\tILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_SAMPLE],\n+\t\t\t     &priv->sh->sample_action_list, idx,\n+\t\t\t     cache_resource, next);\n+\t\tmlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_SAMPLE], idx);\n+\t\tDRV_LOG(DEBUG, \"sample 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@@ -9540,8 +10013,11 @@ struct field_modify_info modify_tcp[] = {\n \t\tflow->dev_handles = dev_handle->next.next;\n \t\tif (dev_handle->dvh.matcher)\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_encap_decap)\n-\t\t\tflow_dv_encap_decap_resource_release(dev, dev_handle);\n+\t\t\tflow_dv_encap_decap_resource_release(dev,\n+\t\t\t\tdev_handle->dvh.rix_encap_decap);\n \t\tif (dev_handle->dvh.modify_hdr)\n \t\t\tflow_dv_modify_hdr_resource_release(dev, dev_handle);\n \t\tif (dev_handle->dvh.rix_push_vlan)\n",
    "prefixes": [
        "v5",
        "6/7"
    ]
}