get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 77003,
    "url": "http://patches.dpdk.org/api/patches/77003/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1599634114-148013-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": "<1599634114-148013-7-git-send-email-jiaweiw@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1599634114-148013-7-git-send-email-jiaweiw@nvidia.com",
    "date": "2020-09-09T06:48:28",
    "name": "[v6,06/12] net/mlx5: update translate function for sample action",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "471614928e7aeb9bc164b7755501bb26871eb716",
    "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/1599634114-148013-7-git-send-email-jiaweiw@nvidia.com/mbox/",
    "series": [
        {
            "id": 12045,
            "url": "http://patches.dpdk.org/api/series/12045/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=12045",
            "date": "2020-09-09T06:48:29",
            "name": "support the flow-based traffic sampling",
            "version": 6,
            "mbox": "http://patches.dpdk.org/series/12045/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/77003/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/77003/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 58DAAA04B1;\n\tWed,  9 Sep 2020 08:49:22 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 070F01C116;\n\tWed,  9 Sep 2020 08:48:45 +0200 (CEST)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by dpdk.org (Postfix) with ESMTP id 8E3811C0C9\n for <dev@dpdk.org>; Wed,  9 Sep 2020 08:48:36 +0200 (CEST)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n jiaweiw@nvidia.com) with SMTP; 9 Sep 2020 09:48:34 +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 0896mYG1029471;\n Wed, 9 Sep 2020 09:48:34 +0300"
        ],
        "From": "Jiawei Wang <jiaweiw@nvidia.com>",
        "To": "orika@nvidia.com, viacheslavo@nvidia.com, matan@nvidia.com,\n thomas@monjalon.net, ferruh.yigit@intel.com, marko.kovacevic@intel.com,\n arybchenko@solarflare.com",
        "Cc": "dev@dpdk.org, rasland@nvidia.com, ian.stokes@intel.com, fbl@redhat.com,\n asafp@nvidia.com",
        "Date": "Wed,  9 Sep 2020 09:48:28 +0300",
        "Message-Id": "<1599634114-148013-7-git-send-email-jiaweiw@nvidia.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1599634114-148013-1-git-send-email-jiaweiw@nvidia.com>",
        "References": "<1598540492-406340-1-git-send-email-jiaweiw@nvidia.com>\n <1599634114-148013-1-git-send-email-jiaweiw@nvidia.com>",
        "Subject": "[dpdk-dev] [PATCH v6 06/12] 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.\nThe metadata register value will be lost in the default path after\nSampler in FDB due to CX5 HW limitation.\nSince source vport also be shared with metadata register c0, MLX5\nPMD would set the source vport to rdma-core and rdma-core will\nrestore the regc0 value after sampler.\n\nSigned-off-by: Jiawei Wang <jiaweiw@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 | 507 +++++++++++++++++++++++++++++++++++++++-\n 3 files changed, 515 insertions(+), 22 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex b5eec48..ce03210 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -4637,10 +4637,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@@ -4659,7 +4663,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@@ -4705,7 +4709,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@@ -4742,8 +4746,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 9c609cb..50e230f 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@@ -614,13 +621,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 3df875d..2241e36 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@@ -8230,6 +8234,386 @@ 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    resource->set_action == cache_resource->set_action &&\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+\tsampler_attr.action = cache_resource->set_action;\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+\tunion {\n+\t\tuint32_t action_in[MLX5_ST_SZ_DW(set_action_in)];\n+\t\tuint64_t set_action;\n+\t} action_ctx = { .set_action = 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+\t\tMLX5_SET(set_action_in, action_ctx.action_in, action_type,\n+\t\t\t MLX5_MODIFICATION_TYPE_SET);\n+\t\tMLX5_SET(set_action_in, action_ctx.action_in, field,\n+\t\t\t MLX5_MODI_META_REG_C_0);\n+\t\tMLX5_SET(set_action_in, action_ctx.action_in, data,\n+\t\t\t priv->vport_meta_tag);\n+\t\tres->set_action = action_ctx.set_action;\n+\t} else if (attr->ingress) {\n+\t\tres->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX;\n+\t}\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@@ -8293,9 +8677,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@@ -8314,7 +8702,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@@ -8322,6 +8709,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@@ -8560,9 +8948,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@@ -8728,6 +9120,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@@ -8754,6 +9159,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@@ -9065,7 +9485,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@@ -9197,18 +9618,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@@ -9459,6 +9880,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@@ -9537,8 +10023,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": [
        "v6",
        "06/12"
    ]
}