get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 81936,
    "url": "http://patches.dpdk.org/api/patches/81936/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20201023102410.20317-5-andreyv@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": "<20201023102410.20317-5-andreyv@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20201023102410.20317-5-andreyv@nvidia.com",
    "date": "2020-10-23T10:24:10",
    "name": "[v2,4/4] net/mlx5: driver support for shared action",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "05cb597c7da26fe29c04ee147154a7775cb59a38",
    "submitter": {
        "id": 1969,
        "url": "http://patches.dpdk.org/api/people/1969/?format=api",
        "name": "Andrey Vesnovaty",
        "email": "andreyv@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/20201023102410.20317-5-andreyv@nvidia.com/mbox/",
    "series": [
        {
            "id": 13264,
            "url": "http://patches.dpdk.org/api/series/13264/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=13264",
            "date": "2020-10-23T10:24:06",
            "name": "Shared action RSS PMD impl",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/13264/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/81936/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/81936/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 A942AA04DE;\n\tFri, 23 Oct 2020 12:25:36 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 1313BA965;\n\tFri, 23 Oct 2020 12:24:38 +0200 (CEST)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by dpdk.org (Postfix) with ESMTP id A6900A950\n for <dev@dpdk.org>; Fri, 23 Oct 2020 12:24:25 +0200 (CEST)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n andreyv@nvidia.com) with SMTP; 23 Oct 2020 13:24:23 +0300",
            "from nvidia.com (r-arch-host11.mtr.labs.mlnx [10.213.43.60])\n by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 09NAOGD0009185;\n Fri, 23 Oct 2020 13:24:23 +0300"
        ],
        "From": "Andrey Vesnovaty <andreyv@nvidia.com>",
        "To": "dev@dpdk.org",
        "Cc": "jer@marvell.com, jerinjacobk@gmail.com, thomas@monjalon.net,\n ferruh.yigit@intel.com, stephen@networkplumber.org,\n bruce.richardson@intel.com, orika@nvidia.com, viacheslavo@nvidia.com,\n andrey.vesnovaty@gmail.com, mdr@ashroe.eu, nhorman@tuxdriver.com,\n ajit.khaparde@broadcom.com, samik.gupta@broadcom.com,\n Matan Azrad <matan@nvidia.com>, Shahaf Shuler <shahafs@nvidia.com>",
        "Date": "Fri, 23 Oct 2020 13:24:10 +0300",
        "Message-Id": "<20201023102410.20317-5-andreyv@nvidia.com>",
        "X-Mailer": "git-send-email 2.26.2",
        "In-Reply-To": "<20201023102410.20317-1-andreyv@nvidia.com>",
        "References": "<20201008121848.15330-1-andreyv@nvidia.com>\n <20201023102410.20317-1-andreyv@nvidia.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v2 4/4] net/mlx5: driver support for shared 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": "Implement shared action create/destroy/update/query. The current\nimplementation support is limited to shared RSS action only. The shared\nRSS action create operation prepares hash RX queue objects for all\nsupported permutations of the hash.  The shared RSS action update\noperation relies on functionality to modify hash RX queue introduced in\none of the previous commits in this patch series.\n\nImplement RSS shared action and handle shared RSS on flow apply and\nrelease. The lookup for hash RX queue object for RSS action is limited\nto the set of objects stored in the shared action itself and when\nhandling shared RSS action. The lookup for hash RX queue object inside\nshared action is performed by hash only.\n\nCurrent implementation limited to DV flow driver operations i.e. verbs\nflow driver operations doesn't support shared action.\n\nSigned-off-by: Andrey Vesnovaty <andreyv@nvidia.com>\n---\n drivers/net/mlx5/mlx5_flow_dv.c | 690 ++++++++++++++++++++++++++++++--\n 1 file changed, 666 insertions(+), 24 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex 2bac7dac9b..66d81e9598 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -9943,6 +9943,158 @@ __flow_dv_translate(struct rte_eth_dev *dev,\n \treturn 0;\n }\n \n+/**\n+ * Set hash RX queue by hash fields (see enum ibv_rx_hash_fields)\n+ * and tunnel.\n+ *\n+ * @param[in, out] action\n+ *   Shred RSS action holding hash RX queue objects.\n+ * @param[in] hash_fields\n+ *   Defines combination of packet fields to participate in RX hash.\n+ * @param[in] tunnel\n+ *   Tunnel type\n+ * @param[in] hrxq_idx\n+ *   Hash RX queue index to set.\n+ *\n+ * @return\n+ *   0 on success, otherwise negative errno value.\n+ */\n+static int\n+__flow_dv_action_rss_hrxq_set(struct mlx5_shared_action_rss *action,\n+\t\t\t      const uint64_t hash_fields,\n+\t\t\t      const int tunnel,\n+\t\t\t      uint32_t hrxq_idx)\n+{\n+\tuint32_t *hrxqs = tunnel ? action->hrxq : action->hrxq_tunnel;\n+\n+\tswitch (hash_fields & ~IBV_RX_HASH_INNER) {\n+\tcase MLX5_RSS_HASH_IPV4:\n+\t\thrxqs[0] = hrxq_idx;\n+\t\treturn 0;\n+\tcase MLX5_RSS_HASH_IPV4_TCP:\n+\t\thrxqs[1] = hrxq_idx;\n+\t\treturn 0;\n+\tcase MLX5_RSS_HASH_IPV4_UDP:\n+\t\thrxqs[2] = hrxq_idx;\n+\t\treturn 0;\n+\tcase MLX5_RSS_HASH_IPV6:\n+\t\thrxqs[3] = hrxq_idx;\n+\t\treturn 0;\n+\tcase MLX5_RSS_HASH_IPV6_TCP:\n+\t\thrxqs[4] = hrxq_idx;\n+\t\treturn 0;\n+\tcase MLX5_RSS_HASH_IPV6_UDP:\n+\t\thrxqs[5] = hrxq_idx;\n+\t\treturn 0;\n+\tcase MLX5_RSS_HASH_NONE:\n+\t\thrxqs[6] = hrxq_idx;\n+\t\treturn 0;\n+\tdefault:\n+\t\treturn -1;\n+\t}\n+}\n+\n+/**\n+ * Look up for hash RX queue by hash fields (see enum ibv_rx_hash_fields)\n+ * and tunnel.\n+ *\n+ * @param[in] action\n+ *   Shred RSS action holding hash RX queue objects.\n+ * @param[in] hash_fields\n+ *   Defines combination of packet fields to participate in RX hash.\n+ * @param[in] tunnel\n+ *   Tunnel type\n+ *\n+ * @return\n+ *   Valid hash RX queue index, otherwise 0.\n+ */\n+static uint32_t\n+__flow_dv_action_rss_hrxq_lookup(const struct mlx5_shared_action_rss *action,\n+\t\t\t\t const uint64_t hash_fields,\n+\t\t\t\t const int tunnel)\n+{\n+\tconst uint32_t *hrxqs = tunnel ? action->hrxq : action->hrxq_tunnel;\n+\n+\tswitch (hash_fields & ~IBV_RX_HASH_INNER) {\n+\tcase MLX5_RSS_HASH_IPV4:\n+\t\treturn hrxqs[0];\n+\tcase MLX5_RSS_HASH_IPV4_TCP:\n+\t\treturn hrxqs[1];\n+\tcase MLX5_RSS_HASH_IPV4_UDP:\n+\t\treturn hrxqs[2];\n+\tcase MLX5_RSS_HASH_IPV6:\n+\t\treturn hrxqs[3];\n+\tcase MLX5_RSS_HASH_IPV6_TCP:\n+\t\treturn hrxqs[4];\n+\tcase MLX5_RSS_HASH_IPV6_UDP:\n+\t\treturn hrxqs[5];\n+\tcase MLX5_RSS_HASH_NONE:\n+\t\treturn hrxqs[6];\n+\tdefault:\n+\t\treturn 0;\n+\t}\n+}\n+\n+/**\n+ * Retrieves hash RX queue suitable for the *flow*.\n+ * If shared action configured for *flow* suitable hash RX queue will be\n+ * retrieved from attached shared action.\n+ *\n+ * @param[in] flow\n+ *   Shred RSS action holding hash RX queue objects.\n+ * @param[in] dev_flow\n+ *   Pointer to the sub flow.\n+ * @param[out] hrxq\n+ *   Pointer to retrieved hash RX queue object.\n+ *\n+ * @return\n+ *   Valid hash RX queue index, otherwise 0 and rte_errno is set.\n+ */\n+static uint32_t\n+__flow_dv_rss_get_hrxq(struct rte_eth_dev *dev, struct rte_flow *flow,\n+\t\t\t   struct mlx5_flow *dev_flow,\n+\t\t\t   struct mlx5_hrxq **hrxq)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tuint32_t hrxq_idx;\n+\n+\tif (flow->shared_rss) {\n+\t\thrxq_idx = __flow_dv_action_rss_hrxq_lookup\n+\t\t\t\t(flow->shared_rss, dev_flow->hash_fields,\n+\t\t\t\t !!(dev_flow->handle->layers &\n+\t\t\t\t    MLX5_FLOW_LAYER_TUNNEL));\n+\t\tif (hrxq_idx) {\n+\t\t\t*hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],\n+\t\t\t\t\t       hrxq_idx);\n+\t\t\trte_atomic32_inc(&(*hrxq)->refcnt);\n+\t\t}\n+\t} else {\n+\t\tstruct mlx5_flow_rss_desc *rss_desc =\n+\t\t\t\t&((struct mlx5_flow_rss_desc *)priv->rss_desc)\n+\t\t\t\t[!!priv->flow_nested_idx];\n+\n+\t\tMLX5_ASSERT(rss_desc->queue_num);\n+\t\thrxq_idx = mlx5_hrxq_get(dev, rss_desc->key,\n+\t\t\t\t\t MLX5_RSS_HASH_KEY_LEN,\n+\t\t\t\t\t dev_flow->hash_fields,\n+\t\t\t\t\t rss_desc->queue, rss_desc->queue_num);\n+\t\tif (!hrxq_idx) {\n+\t\t\thrxq_idx = mlx5_hrxq_new(dev,\n+\t\t\t\t\t\t rss_desc->key,\n+\t\t\t\t\t\t MLX5_RSS_HASH_KEY_LEN,\n+\t\t\t\t\t\t dev_flow->hash_fields,\n+\t\t\t\t\t\t rss_desc->queue,\n+\t\t\t\t\t\t rss_desc->queue_num,\n+\t\t\t\t\t\t !!(dev_flow->handle->layers &\n+\t\t\t\t\t\t MLX5_FLOW_LAYER_TUNNEL),\n+\t\t\t\t\t\t false);\n+\t\t}\n+\t\t*hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],\n+\t\t\t\t       hrxq_idx);\n+\t}\n+\treturn hrxq_idx;\n+}\n+\n /**\n  * Apply the flow to the NIC, lock free,\n  * (mutex should be acquired by caller).\n@@ -10002,31 +10154,10 @@ __flow_dv_apply(struct rte_eth_dev *dev, struct rte_flow *flow,\n \t\t\t}\n \t\t} else if (dh->fate_action == MLX5_FLOW_FATE_QUEUE &&\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-\t\t\t\t&((struct mlx5_flow_rss_desc *)priv->rss_desc)\n-\t\t\t\t[!!priv->flow_nested_idx];\n+\t\t\tstruct mlx5_hrxq *hrxq = NULL;\n+\t\t\tuint32_t hrxq_idx = __flow_dv_rss_get_hrxq\n+\t\t\t\t\t\t(dev, flow, dev_flow, &hrxq);\n \n-\t\t\tMLX5_ASSERT(rss_desc->queue_num);\n-\t\t\thrxq_idx = mlx5_hrxq_get(dev, rss_desc->key,\n-\t\t\t\t\t\t MLX5_RSS_HASH_KEY_LEN,\n-\t\t\t\t\t\t dev_flow->hash_fields,\n-\t\t\t\t\t\t rss_desc->queue,\n-\t\t\t\t\t\t rss_desc->queue_num);\n-\t\t\tif (!hrxq_idx) {\n-\t\t\t\thrxq_idx = mlx5_hrxq_new\n-\t\t\t\t\t\t(dev, rss_desc->key,\n-\t\t\t\t\t\t MLX5_RSS_HASH_KEY_LEN,\n-\t\t\t\t\t\t dev_flow->hash_fields,\n-\t\t\t\t\t\t rss_desc->queue,\n-\t\t\t\t\t\t rss_desc->queue_num,\n-\t\t\t\t\t\t !!(dh->layers &\n-\t\t\t\t\t\t MLX5_FLOW_LAYER_TUNNEL),\n-\t\t\t\t\t\t false);\n-\t\t\t}\n-\t\t\thrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],\n-\t\t\t\t\t      hrxq_idx);\n \t\t\tif (!hrxq) {\n \t\t\t\trte_flow_error_set\n \t\t\t\t\t(error, rte_errno,\n@@ -10579,12 +10710,16 @@ __flow_dv_remove(struct rte_eth_dev *dev, struct rte_flow *flow)\n static void\n __flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)\n {\n+\tstruct rte_flow_shared_action *shared;\n \tstruct mlx5_flow_handle *dev_handle;\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \n \tif (!flow)\n \t\treturn;\n \t__flow_dv_remove(dev, flow);\n+\tshared = mlx5_flow_get_shared_rss(flow);\n+\tif (shared)\n+\t\t__atomic_sub_fetch(&shared->refcnt, 1, __ATOMIC_RELAXED);\n \tif (flow->counter) {\n \t\tflow_dv_counter_release(dev, flow->counter);\n \t\tflow->counter = 0;\n@@ -10629,6 +10764,423 @@ __flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)\n \t}\n }\n \n+/**\n+ * Release array of hash RX queue objects.\n+ * Helper function.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the Ethernet device structure.\n+ * @param[in, out] hrxqs\n+ *   Array of hash RX queue objects.\n+ *\n+ * @return\n+ *   Total number of references to hash RX queue objects in *hrxqs* array\n+ *   after this operation.\n+ */\n+static int\n+__flow_dv_hrxqs_release(struct rte_eth_dev *dev,\n+\t\t\tuint32_t (*hrxqs)[MLX5_RSS_HASH_FIELDS_LEN])\n+{\n+\tsize_t i;\n+\tint remaining = 0;\n+\n+\tfor (i = 0; i < RTE_DIM(*hrxqs); i++) {\n+\t\tint ret = mlx5_hrxq_release(dev, (*hrxqs)[i]);\n+\n+\t\tif (!ret)\n+\t\t\t(*hrxqs)[i] = 0;\n+\t\tremaining += ret;\n+\t}\n+\treturn remaining;\n+}\n+\n+/**\n+ * Release all hash RX queue objects representing shared RSS action.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the Ethernet device structure.\n+ * @param[in, out] action\n+ *   Shared RSS action to remove hash RX queue objects from.\n+ *\n+ * @return\n+ *   Total number of references to hash RX queue objects stored in *action*\n+ *   after this operation.\n+ *   Expected to be 0 if no external references held.\n+ */\n+static int\n+__flow_dv_action_rss_hrxqs_release(struct rte_eth_dev *dev,\n+\t\t\t\t struct mlx5_shared_action_rss *action)\n+{\n+\treturn __flow_dv_hrxqs_release(dev, &action->hrxq) +\n+\t\t__flow_dv_hrxqs_release(dev, &action->hrxq_tunnel);\n+}\n+\n+/**\n+ * Setup shared RSS action.\n+ * Prepare set of hash RX queue objects sufficient to handle all valid\n+ * hash_fields combinations (see enum ibv_rx_hash_fields).\n+ *\n+ * @param[in] dev\n+ *   Pointer to the Ethernet device structure.\n+ * @param[in, out] action\n+ *   Partially initialized shared RSS action.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL. Initialized in case of\n+ *   error only.\n+ *\n+ * @return\n+ *   0 on success, otherwise negative errno value.\n+ */\n+static int\n+__flow_dv_action_rss_setup(struct rte_eth_dev *dev,\n+\t\t\tstruct mlx5_shared_action_rss *action,\n+\t\t\tstruct rte_flow_error *error)\n+{\n+\tsize_t i;\n+\tint err;\n+\n+\tfor (i = 0; i < MLX5_RSS_HASH_FIELDS_LEN; i++) {\n+\t\tuint32_t hrxq_idx;\n+\t\tuint64_t hash_fields = mlx5_rss_hash_fields[i];\n+\t\tint tunnel;\n+\n+\t\tfor (tunnel = 0; tunnel < 2; tunnel++) {\n+\t\t\thrxq_idx = mlx5_hrxq_new(dev, action->origin.key,\n+\t\t\t\t\tMLX5_RSS_HASH_KEY_LEN,\n+\t\t\t\t\thash_fields,\n+\t\t\t\t\taction->origin.queue,\n+\t\t\t\t\taction->origin.queue_num,\n+\t\t\t\t\ttunnel, true);\n+\t\t\tif (!hrxq_idx) {\n+\t\t\t\trte_flow_error_set\n+\t\t\t\t\t(error, rte_errno,\n+\t\t\t\t\t RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\t \"cannot get hash queue\");\n+\t\t\t\tgoto error_hrxq_new;\n+\t\t\t}\n+\t\t\terr = __flow_dv_action_rss_hrxq_set\n+\t\t\t\t(action, hash_fields, tunnel, hrxq_idx);\n+\t\t\tMLX5_ASSERT(!err);\n+\t\t}\n+\t}\n+\treturn 0;\n+error_hrxq_new:\n+\terr = rte_errno;\n+\t__flow_dv_action_rss_hrxqs_release(dev, action);\n+\trte_errno = err;\n+\treturn -rte_errno;\n+}\n+\n+/**\n+ * Create shared RSS action.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the Ethernet device structure.\n+ * @param[in] conf\n+ *   Shared action configuration.\n+ * @param[in] rss\n+ *   RSS action specification used to create shared action.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL. Initialized in case of\n+ *   error only.\n+ *\n+ * @return\n+ *   A valid shared action handle in case of success, NULL otherwise and\n+ *   rte_errno is set.\n+ */\n+static struct rte_flow_shared_action *\n+__flow_dv_action_rss_create(struct rte_eth_dev *dev,\n+\t\t\t    const struct rte_flow_shared_action_conf *conf,\n+\t\t\t    const struct rte_flow_action_rss *rss,\n+\t\t\t    struct rte_flow_error *error)\n+{\n+\tstruct rte_flow_shared_action *shared_action = NULL;\n+\tvoid *queue = NULL;\n+\tstruct mlx5_shared_action_rss *shared_rss;\n+\tstruct rte_flow_action_rss *origin;\n+\tconst uint8_t *rss_key;\n+\tuint32_t queue_size = rss->queue_num * sizeof(uint16_t);\n+\n+\tRTE_SET_USED(conf);\n+\tqueue = mlx5_malloc(0, RTE_ALIGN_CEIL(queue_size, sizeof(void *)),\n+\t\t\t    0, SOCKET_ID_ANY);\n+\tshared_action = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*shared_action), 0,\n+\t\t\t\t    SOCKET_ID_ANY);\n+\tif (!shared_action || !queue) {\n+\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t   \"cannot allocate resource memory\");\n+\t\tgoto error_rss_init;\n+\t}\n+\tshared_rss = &shared_action->rss;\n+\tshared_rss->queue = queue;\n+\torigin = &shared_rss->origin;\n+\torigin->func = rss->func;\n+\torigin->level = rss->level;\n+\t/* RSS type 0 indicates default RSS type (ETH_RSS_IP). */\n+\torigin->types = !rss->types ? ETH_RSS_IP : rss->types;\n+\t/* NULL RSS key indicates default RSS key. */\n+\trss_key = !rss->key ? rss_hash_default_key : rss->key;\n+\tmemcpy(shared_rss->key, rss_key, MLX5_RSS_HASH_KEY_LEN);\n+\torigin->key = &shared_rss->key[0];\n+\torigin->key_len = MLX5_RSS_HASH_KEY_LEN;\n+\tmemcpy(shared_rss->queue, rss->queue, queue_size);\n+\torigin->queue = shared_rss->queue;\n+\torigin->queue_num = rss->queue_num;\n+\tif (__flow_dv_action_rss_setup(dev, shared_rss, error))\n+\t\tgoto error_rss_init;\n+\tshared_action->type = MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS;\n+\treturn shared_action;\n+error_rss_init:\n+\tmlx5_free(shared_action);\n+\tmlx5_free(queue);\n+\treturn NULL;\n+}\n+\n+/**\n+ * Destroy the shared RSS action.\n+ * Release related hash RX queue objects.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the Ethernet device structure.\n+ * @param[in] shared_rss\n+ *   The shared RSS action object to be removed.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL. Initialized in case of\n+ *   error only.\n+ *\n+ * @return\n+ *   0 on success, otherwise negative errno value.\n+ */\n+static int\n+__flow_dv_action_rss_release(struct rte_eth_dev *dev,\n+\t\t\t struct mlx5_shared_action_rss *shared_rss,\n+\t\t\t struct rte_flow_error *error)\n+{\n+\tstruct rte_flow_shared_action *shared_action = NULL;\n+\tuint32_t old_refcnt = 1;\n+\tint remaining = __flow_dv_action_rss_hrxqs_release(dev, shared_rss);\n+\n+\tif (remaining) {\n+\t\treturn rte_flow_error_set(error, ETOOMANYREFS,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"shared rss hrxq has references\");\n+\t}\n+\tshared_action = container_of(shared_rss,\n+\t\t\t\t     struct rte_flow_shared_action, rss);\n+\tif (!__atomic_compare_exchange_n(&shared_action->refcnt, &old_refcnt,\n+\t\t\t\t\t 0, 0,\n+\t\t\t\t\t __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {\n+\t\treturn rte_flow_error_set(error, ETOOMANYREFS,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"shared rss has references\");\n+\t}\n+\trte_free(shared_rss->queue);\n+\treturn 0;\n+}\n+\n+/**\n+ * Create shared action, lock free,\n+ * (mutex should be acquired by caller).\n+ * Dispatcher for action type specific call.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the Ethernet device structure.\n+ * @param[in] conf\n+ *   Shared action configuration.\n+ * @param[in] action\n+ *   Action specification used to create shared action.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL. Initialized in case of\n+ *   error only.\n+ *\n+ * @return\n+ *   A valid shared action handle in case of success, NULL otherwise and\n+ *   rte_errno is set.\n+ */\n+static struct rte_flow_shared_action *\n+__flow_dv_action_create(struct rte_eth_dev *dev,\n+\t\t\tconst struct rte_flow_shared_action_conf *conf,\n+\t\t\tconst struct rte_flow_action *action,\n+\t\t\tstruct rte_flow_error *error)\n+{\n+\tstruct rte_flow_shared_action *shared_action = NULL;\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\n+\tswitch (action->type) {\n+\tcase RTE_FLOW_ACTION_TYPE_RSS:\n+\t\tshared_action = __flow_dv_action_rss_create(dev, conf,\n+\t\t\t\t\t\t\t    action->conf,\n+\t\t\t\t\t\t\t    error);\n+\t\tbreak;\n+\tdefault:\n+\t\trte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t   NULL, \"action type not supported\");\n+\t\tbreak;\n+\t}\n+\tif (shared_action) {\n+\t\t__atomic_add_fetch(&shared_action->refcnt, 1,\n+\t\t\t\t   __ATOMIC_RELAXED);\n+\t\tLIST_INSERT_HEAD(&priv->shared_actions, shared_action, next);\n+\t}\n+\treturn shared_action;\n+}\n+\n+/**\n+ * Destroy the shared action.\n+ * Release action related resources on the NIC and the memory.\n+ * Lock free, (mutex should be acquired by caller).\n+ * Dispatcher for action type specific call.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the Ethernet device structure.\n+ * @param[in] action\n+ *   The shared action object to be removed.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL. Initialized in case of\n+ *   error only.\n+ *\n+ * @return\n+ *   0 on success, otherwise negative errno value.\n+ */\n+static int\n+__flow_dv_action_destroy(struct rte_eth_dev *dev,\n+\t\t\t struct rte_flow_shared_action *action,\n+\t\t\t struct rte_flow_error *error)\n+{\n+\tint ret;\n+\n+\tswitch (action->type) {\n+\tcase MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:\n+\t\tret = __flow_dv_action_rss_release(dev, &action->rss, error);\n+\t\tbreak;\n+\tdefault:\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"action type not supported\");\n+\t}\n+\tif (ret)\n+\t\treturn ret;\n+\tLIST_REMOVE(action, next);\n+\trte_free(action);\n+\treturn 0;\n+}\n+\n+/**\n+ * Updates in place shared RSS action configuration.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the Ethernet device structure.\n+ * @param[in] shared_rss\n+ *   The shared RSS action object to be updated.\n+ * @param[in] action_conf\n+ *   RSS action specification used to modify *shared_rss*.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL. Initialized in case of\n+ *   error only.\n+ *\n+ * @return\n+ *   0 on success, otherwise negative errno value.\n+ * @note: currently only support update of RSS queues.\n+ */\n+static int\n+__flow_dv_action_rss_update(struct rte_eth_dev *dev,\n+\t\t\t    struct mlx5_shared_action_rss *shared_rss,\n+\t\t\t    const struct rte_flow_action_rss *action_conf,\n+\t\t\t    struct rte_flow_error *error)\n+{\n+\tsize_t i;\n+\tint ret;\n+\tvoid *queue = NULL;\n+\tconst uint8_t *rss_key;\n+\tuint32_t rss_key_len;\n+\tuint32_t queue_size = action_conf->queue_num * sizeof(uint16_t);\n+\n+\tqueue = mlx5_malloc(MLX5_MEM_ZERO,\n+\t\t\t    RTE_ALIGN_CEIL(queue_size, sizeof(void *)),\n+\t\t\t    0, SOCKET_ID_ANY);\n+\tif (!queue)\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+\tif (action_conf->key) {\n+\t\trss_key = action_conf->key;\n+\t\trss_key_len = action_conf->key_len;\n+\t} else {\n+\t\trss_key = rss_hash_default_key;\n+\t\trss_key_len = MLX5_RSS_HASH_KEY_LEN;\n+\t}\n+\tfor (i = 0; i < MLX5_RSS_HASH_FIELDS_LEN; i++) {\n+\t\tuint32_t hrxq_idx;\n+\t\tuint64_t hash_fields = mlx5_rss_hash_fields[i];\n+\t\tint tunnel;\n+\n+\t\tfor (tunnel = 0; tunnel < 2; tunnel++) {\n+\t\t\thrxq_idx = __flow_dv_action_rss_hrxq_lookup\n+\t\t\t\t\t(shared_rss, hash_fields, tunnel);\n+\t\t\tMLX5_ASSERT(hrxq_idx);\n+\t\t\tret = mlx5_hrxq_modify\n+\t\t\t\t(dev, hrxq_idx,\n+\t\t\t\t rss_key, rss_key_len,\n+\t\t\t\t hash_fields,\n+\t\t\t\t action_conf->queue, action_conf->queue_num);\n+\t\t\tif (ret) {\n+\t\t\t\tmlx5_free(queue);\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, NULL,\n+\t\t\t\t\t \"cannot update hash queue\");\n+\t\t\t}\n+\t\t}\n+\t}\n+\tmlx5_free(shared_rss->queue);\n+\tshared_rss->queue = queue;\n+\tmemcpy(shared_rss->queue, action_conf->queue, queue_size);\n+\tshared_rss->origin.queue = shared_rss->queue;\n+\tshared_rss->origin.queue_num = action_conf->queue_num;\n+\treturn 0;\n+}\n+\n+/**\n+ * Updates in place shared action configuration, lock free,\n+ * (mutex should be acquired by caller).\n+ *\n+ * @param[in] dev\n+ *   Pointer to the Ethernet device structure.\n+ * @param[in] action\n+ *   The shared action object to be updated.\n+ * @param[in] action_conf\n+ *   Action specification used to modify *action*.\n+ *   *action_conf* should be of type correlating with type of the *action*,\n+ *   otherwise considered as invalid.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL. Initialized in case of\n+ *   error only.\n+ *\n+ * @return\n+ *   0 on success, otherwise negative errno value.\n+ */\n+static int\n+__flow_dv_action_update(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_flow_shared_action *action,\n+\t\t\tconst void *action_conf,\n+\t\t\tstruct rte_flow_error *error)\n+{\n+\tswitch (action->type) {\n+\tcase MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:\n+\t\treturn __flow_dv_action_rss_update(dev, &action->rss,\n+\t\t\t\t\t\t   action_conf, error);\n+\tdefault:\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"action type not supported\");\n+\t}\n+}\n /**\n  * Query a dv flow  rule for its statistics via devx.\n  *\n@@ -11453,6 +12005,92 @@ flow_dv_counter_free(struct rte_eth_dev *dev, uint32_t cnt)\n \tflow_dv_shared_unlock(dev);\n }\n \n+/**\n+ * Validate shared action.\n+ * Dispatcher for action type specific validation.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the Ethernet device structure.\n+ * @param[in] conf\n+ *   Shared action configuration.\n+ * @param[in] action\n+ *   The shared action object to validate.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL. Initialized in case of\n+ *   error only.\n+ *\n+ * @return\n+ *   0 on success, otherwise negative errno value.\n+ */\n+static int\n+flow_dv_action_validate(struct rte_eth_dev *dev,\n+\t\t\tconst struct rte_flow_shared_action_conf *conf,\n+\t\t\tconst struct rte_flow_action *action,\n+\t\t\tstruct rte_flow_error *error)\n+{\n+\tRTE_SET_USED(conf);\n+\tswitch (action->type) {\n+\tcase RTE_FLOW_ACTION_TYPE_RSS:\n+\t\treturn mlx5_validate_action_rss(dev, action, error);\n+\tdefault:\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"action type not supported\");\n+\t}\n+}\n+\n+/*\n+ * Mutex-protected thunk to lock-free  __flow_dv_action_create().\n+ */\n+static struct rte_flow_shared_action *\n+flow_dv_action_create(struct rte_eth_dev *dev,\n+\t\t      const struct rte_flow_shared_action_conf *conf,\n+\t\t      const struct rte_flow_action *action,\n+\t\t      struct rte_flow_error *error)\n+{\n+\tstruct rte_flow_shared_action *shared_action = NULL;\n+\n+\tflow_dv_shared_lock(dev);\n+\tshared_action = __flow_dv_action_create(dev, conf, action, error);\n+\tflow_dv_shared_unlock(dev);\n+\treturn shared_action;\n+}\n+\n+/*\n+ * Mutex-protected thunk to lock-free  __flow_dv_action_destroy().\n+ */\n+static int\n+flow_dv_action_destroy(struct rte_eth_dev *dev,\n+\t\t       struct rte_flow_shared_action *action,\n+\t\t       struct rte_flow_error *error)\n+{\n+\tint ret;\n+\n+\tflow_dv_shared_lock(dev);\n+\tret = __flow_dv_action_destroy(dev, action, error);\n+\tflow_dv_shared_unlock(dev);\n+\treturn ret;\n+}\n+\n+/*\n+ * Mutex-protected thunk to lock-free  __flow_dv_action_update().\n+ */\n+static int\n+flow_dv_action_update(struct rte_eth_dev *dev,\n+\t\t      struct rte_flow_shared_action *action,\n+\t\t      const void *action_conf,\n+\t\t      struct rte_flow_error *error)\n+{\n+\tint ret;\n+\n+\tflow_dv_shared_lock(dev);\n+\tret = __flow_dv_action_update(dev, action, action_conf,\n+\t\t\t\t      error);\n+\tflow_dv_shared_unlock(dev);\n+\treturn ret;\n+}\n+\n const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {\n \t.validate = flow_dv_validate,\n \t.prepare = flow_dv_prepare,\n@@ -11469,6 +12107,10 @@ const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {\n \t.counter_free = flow_dv_counter_free,\n \t.counter_query = flow_dv_counter_query,\n \t.get_aged_flows = flow_get_aged_flows,\n+\t.action_validate = flow_dv_action_validate,\n+\t.action_create = flow_dv_action_create,\n+\t.action_destroy = flow_dv_action_destroy,\n+\t.action_update = flow_dv_action_update,\n };\n \n #endif /* HAVE_IBV_FLOW_DV_SUPPORT */\n",
    "prefixes": [
        "v2",
        "4/4"
    ]
}