get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 62726,
    "url": "http://patches.dpdk.org/api/patches/62726/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1573184965-49691-18-git-send-email-suanmingm@mellanox.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1573184965-49691-18-git-send-email-suanmingm@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1573184965-49691-18-git-send-email-suanmingm@mellanox.com",
    "date": "2019-11-08T03:49:23",
    "name": "[v2,17/19] net/mlx5: split meter flow",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "069630ea127314a7f7713f22b1178c3614254cc9",
    "submitter": {
        "id": 1358,
        "url": "http://patches.dpdk.org/api/people/1358/?format=api",
        "name": "Suanming Mou",
        "email": "suanmingm@mellanox.com"
    },
    "delegate": {
        "id": 3268,
        "url": "http://patches.dpdk.org/api/users/3268/?format=api",
        "username": "rasland",
        "first_name": "Raslan",
        "last_name": "Darawsheh",
        "email": "rasland@nvidia.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1573184965-49691-18-git-send-email-suanmingm@mellanox.com/mbox/",
    "series": [
        {
            "id": 7343,
            "url": "http://patches.dpdk.org/api/series/7343/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=7343",
            "date": "2019-11-08T03:49:07",
            "name": "net/mlx5: support meter",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/7343/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/62726/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/62726/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 2EF61A04AB;\n\tFri,  8 Nov 2019 04:51:40 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id D85D41C01B;\n\tFri,  8 Nov 2019 04:50:01 +0100 (CET)",
            "from git-send-mailer.rdmz.labs.mlnx (unknown [37.142.13.130])\n by dpdk.org (Postfix) with ESMTP id 6D8F11BF5D\n for <dev@dpdk.org>; Fri,  8 Nov 2019 04:49:33 +0100 (CET)"
        ],
        "From": "Suanming Mou <suanmingm@mellanox.com>",
        "To": "viacheslavo@mellanox.com,\n\tmatan@mellanox.com",
        "Cc": "orika@mellanox.com,\n\trasland@mellanox.com,\n\tdev@dpdk.org",
        "Date": "Fri,  8 Nov 2019 05:49:23 +0200",
        "Message-Id": "<1573184965-49691-18-git-send-email-suanmingm@mellanox.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1573184965-49691-1-git-send-email-suanmingm@mellanox.com>",
        "References": "<1573053090-179521-1-git-send-email-suanmingm@mellanox.com>\n <1573184965-49691-1-git-send-email-suanmingm@mellanox.com>",
        "Subject": "[dpdk-dev] [PATCH v2 17/19] net/mlx5: split meter flow",
        "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": "The flow with meter action will be divided to three sub flows, the\nprefix flow, the meter flow and the suffix flow.\n\nFor these three sub flows, as the prefix flow and meter flow have the\nmeter color match. In order the make the packet from prefix flow to\nmatch with the suffix flow, an extra metadata register is allocated.\nThe prefix flow will add a unique id to the register and the suffix\nflow matches on that unique id.\n\nAs RSS will also divided the flow to several sub flows, flow with meter\nwill be divided as the sub flow of the RSS sub flows if have as below:\n\nOriginal flow ->\n\tRSS sub flow 1 ->\n\t\tMeter sub flow 1 (Contain three sub flows.)\n\tRSS sub flow 2 ->\n\t\tMeter sub flow 2 (Contain three sub flows.)\n\t......\n\tRSS sub flow n ->\n\t\tMeter sub flow n (Contain three sub flows.)\n\nThe metadata feature flow will be split as the sub flow of the meter\nsuffix flow.\n\nSigned-off-by: Suanming Mou <suanmingm@mellanox.com>\n---\n drivers/net/mlx5/mlx5_flow.c | 299 ++++++++++++++++++++++++++++++++++++++++++-\n drivers/net/mlx5/mlx5_flow.h |   1 +\n 2 files changed, 299 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex ee964b0..da3e47a 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -2328,6 +2328,27 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \t\t\tflow_qrss_free_id(dev, dev_flow->qrss_id);\n }\n \n+/**\n+ * Release meter prefix suffix flow match id.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device.\n+ * @param flow\n+ *   Flow to release id's from.\n+ */\n+static void\n+flow_meter_split_id_release(struct rte_eth_dev *dev,\n+\t\t\t    struct rte_flow *flow)\n+{\n+\tstruct mlx5_flow *dev_flow;\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\n+\tLIST_FOREACH(dev_flow, &flow->dev_flows, next)\n+\t\tif (dev_flow->qrss_id)\n+\t\t\tmlx5_flow_id_release(priv->sh->flow_id_pool,\n+\t\t\t\t\t     dev_flow->mtr_flow_id);\n+}\n+\n static int\n flow_null_validate(struct rte_eth_dev *dev __rte_unused,\n \t\t   const struct rte_flow_attr *attr __rte_unused,\n@@ -2618,6 +2639,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \tenum mlx5_flow_drv_type type = flow->drv_type;\n \n \tflow_mreg_split_qrss_release(dev, flow);\n+\tflow_meter_split_id_release(dev, flow);\n \tassert(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);\n \tfops = flow_get_drv_ops(type);\n \tfops->destroy(dev, flow);\n@@ -2645,6 +2667,26 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n }\n \n /**\n+ * Get port id item from the item list.\n+ *\n+ * @param[in] item\n+ *   Pointer to the list of items.\n+ *\n+ * @return\n+ *   Pointer to the port id item if exist, else return NULL.\n+ */\n+static const struct rte_flow_item *\n+find_port_id_item(const struct rte_flow_item *item)\n+{\n+\tassert(item);\n+\tfor (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {\n+\t\tif (item->type == RTE_FLOW_ITEM_TYPE_PORT_ID)\n+\t\t\treturn item;\n+\t}\n+\treturn NULL;\n+}\n+\n+/**\n  * Get RSS action from the action list.\n  *\n  * @param[in] actions\n@@ -2723,6 +2765,38 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n }\n \n /**\n+ * Check meter action from the action list.\n+ *\n+ * @param[in] actions\n+ *   Pointer to the list of actions.\n+ * @param[out] mtr\n+ *   Pointer to the meter exist flag.\n+ *\n+ * @return\n+ *   Total number of actions.\n+ */\n+static int\n+flow_check_meter_action(const struct rte_flow_action actions[], uint32_t *mtr)\n+{\n+\tint actions_n = 0;\n+\n+\tassert(mtr);\n+\t*mtr = 0;\n+\tfor (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {\n+\t\tswitch (actions->type) {\n+\t\tcase RTE_FLOW_ACTION_TYPE_METER:\n+\t\t\t*mtr = 1;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t\tactions_n++;\n+\t}\n+\t/* Count RTE_FLOW_ACTION_TYPE_END. */\n+\treturn actions_n + 1;\n+}\n+\n+/**\n  * Check if the flow should be splited due to hairpin.\n  * The reason for the split is that in current HW we can't\n  * support encap on Rx, so if a flow have encap we move it\n@@ -3366,6 +3440,111 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n }\n \n /**\n+ * Split the meter flow.\n+ *\n+ * As meter flow will split to three sub flow, other than meter\n+ * action, the other actions make sense to only meter accepts\n+ * the packet. If it need to be dropped, no other additional\n+ * actions should be take.\n+ *\n+ * One kind of special action which decapsulates the L3 tunnel\n+ * header will be in the prefix sub flow, as not to take the\n+ * L3 tunnel header into account.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device.\n+ * @param[in] actions\n+ *   Associated actions (list terminated by the END action).\n+ * @param[out] actions_sfx\n+ *   Suffix flow actions.\n+ * @param[out] actions_pre\n+ *   Prefix flow actions.\n+ * @param[out] pattern_sfx\n+ *   The pattern items for the suffix flow.\n+ * @param[out] tag_sfx\n+ *   Pointer to suffix flow tag.\n+ *\n+ * @return\n+ *   0 on success.\n+ */\n+static int\n+flow_meter_split_prep(struct rte_eth_dev *dev,\n+\t\t const struct rte_flow_action actions[],\n+\t\t struct rte_flow_action actions_sfx[],\n+\t\t struct rte_flow_action actions_pre[])\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct rte_flow_action *tag_action;\n+\tstruct mlx5_rte_flow_action_set_tag *set_tag;\n+\tstruct rte_flow_error error;\n+\tconst struct rte_flow_action_raw_encap *raw_encap;\n+\tconst struct rte_flow_action_raw_decap *raw_decap;\n+\tuint32_t tag_id;\n+\n+\t/* Add the extra tag action first. */\n+\ttag_action = actions_pre;\n+\ttag_action->type = MLX5_RTE_FLOW_ACTION_TYPE_TAG;\n+\tactions_pre++;\n+\t/* Prepare the actions for prefix and suffix flow. */\n+\tfor (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {\n+\t\tswitch (actions->type) {\n+\t\tcase RTE_FLOW_ACTION_TYPE_METER:\n+\t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:\n+\t\tcase RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:\n+\t\t\tmemcpy(actions_pre, actions,\n+\t\t\t       sizeof(struct rte_flow_action));\n+\t\t\tactions_pre++;\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_RAW_ENCAP:\n+\t\t\traw_encap = actions->conf;\n+\t\t\tif (raw_encap->size >\n+\t\t\t    (sizeof(struct rte_flow_item_eth) +\n+\t\t\t     sizeof(struct rte_flow_item_ipv4))) {\n+\t\t\t\tmemcpy(actions_sfx, actions,\n+\t\t\t\t       sizeof(struct rte_flow_action));\n+\t\t\t\tactions_sfx++;\n+\t\t\t} else {\n+\t\t\t\trte_memcpy(actions_pre, actions,\n+\t\t\t\t\t   sizeof(struct rte_flow_action));\n+\t\t\t\tactions_pre++;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_RAW_DECAP:\n+\t\t\traw_decap = actions->conf;\n+\t\t\t/* Size 0 decap means 50 bytes as vxlan decap. */\n+\t\t\tif (raw_decap->size && (raw_decap->size <\n+\t\t\t    (sizeof(struct rte_flow_item_eth) +\n+\t\t\t     sizeof(struct rte_flow_item_ipv4)))) {\n+\t\t\t\tmemcpy(actions_sfx, actions,\n+\t\t\t\t       sizeof(struct rte_flow_action));\n+\t\t\t\tactions_sfx++;\n+\t\t\t} else {\n+\t\t\t\trte_memcpy(actions_pre, actions,\n+\t\t\t\t\t   sizeof(struct rte_flow_action));\n+\t\t\t\tactions_pre++;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tmemcpy(actions_sfx, actions,\n+\t\t\t\tsizeof(struct rte_flow_action));\n+\t\t\tactions_sfx++;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\t/* Add end action to the actions. */\n+\tactions_sfx->type = RTE_FLOW_ACTION_TYPE_END;\n+\tactions_pre->type = RTE_FLOW_ACTION_TYPE_END;\n+\tactions_pre++;\n+\t/* Set the tag. */\n+\tset_tag = (void *)actions_pre;\n+\tset_tag->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0, &error);\n+\tmlx5_flow_id_get(priv->sh->flow_id_pool, &tag_id);\n+\tset_tag->data = rte_cpu_to_be_32(tag_id);\n+\ttag_action->conf = set_tag;\n+\treturn tag_id;\n+}\n+\n+/**\n  * Split action list having QUEUE/RSS for metadata register copy.\n  *\n  * Once Q/RSS action is detected in user's action list, the flow action\n@@ -3711,6 +3890,124 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n }\n \n /**\n+ * The splitting for meter feature.\n+ *\n+ * - The meter flow will be split to two flows as prefix and\n+ *   suffix flow. The packets make sense only it pass the prefix\n+ *   meter action.\n+ *\n+ * - Reg_C_5 is used for the packet to match betweend prefix and\n+ *   suffix flow.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device.\n+ * @param[in] flow\n+ *   Parent flow structure pointer.\n+ * @param[in] attr\n+ *   Flow rule attributes.\n+ * @param[in] items\n+ *   Pattern specification (list terminated by the END pattern item).\n+ * @param[in] actions\n+ *   Associated actions (list terminated by the END action).\n+ * @param[in] external\n+ *   This flow rule is created by request external to PMD.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL.\n+ * @return\n+ *   0 on success, negative value otherwise\n+ */\n+static int\n+flow_create_split_meter(struct rte_eth_dev *dev,\n+\t\t\t   struct rte_flow *flow,\n+\t\t\t   const struct rte_flow_attr *attr,\n+\t\t\t   const struct rte_flow_item items[],\n+\t\t\t   const struct rte_flow_action actions[],\n+\t\t\t   bool external, struct rte_flow_error *error)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct rte_flow_action *sfx_actions = NULL;\n+\tstruct rte_flow_action *pre_actions = NULL;\n+\tstruct rte_flow_item *sfx_items = NULL;\n+\tconst  struct rte_flow_item *sfx_port_id_item;\n+\tstruct mlx5_flow *dev_flow = NULL;\n+\tstruct rte_flow_attr sfx_attr = *attr;\n+\tuint32_t mtr = 0;\n+\tuint32_t mtr_tag_id = 0;\n+\tsize_t act_size;\n+\tsize_t item_size;\n+\tint actions_n = 0;\n+\tint ret;\n+\n+\tif (priv->mtr_en)\n+\t\tactions_n = flow_check_meter_action(actions, &mtr);\n+\tif (mtr) {\n+\t\tstruct mlx5_rte_flow_item_tag *tag_spec;\n+\t\t/* The five prefix actions: meter, decap, encap, tag, end. */\n+\t\tact_size = sizeof(struct rte_flow_action) * (actions_n + 5) +\n+\t\t\t   sizeof(struct rte_flow_action_set_tag);\n+\t\t/* tag, end. */\n+#define METER_SUFFIX_ITEM 3\n+\t\titem_size = sizeof(struct rte_flow_item) * METER_SUFFIX_ITEM +\n+\t\t\t    sizeof(struct mlx5_rte_flow_item_tag);\n+\t\tsfx_actions = rte_zmalloc(__func__, (act_size + item_size), 0);\n+\t\tif (!sfx_actions)\n+\t\t\treturn rte_flow_error_set(error, ENOMEM,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t\t  NULL, \"no memory to split \"\n+\t\t\t\t\t\t  \"meter flow\");\n+\t\tpre_actions = sfx_actions + actions_n;\n+\t\tmtr_tag_id = flow_meter_split_prep(dev, actions, sfx_actions,\n+\t\t\t\t\t\t     pre_actions);\n+\t\tif (!mtr_tag_id) {\n+\t\t\tret = -rte_errno;\n+\t\t\tgoto exit;\n+\t\t}\n+\t\t/* Add the prefix subflow. */\n+\t\tret = flow_create_split_inner(dev, flow, &dev_flow, attr, items,\n+\t\t\t\t\t\t  pre_actions, external, error);\n+\t\tif (ret) {\n+\t\t\tret = -rte_errno;\n+\t\t\tgoto exit;\n+\t\t}\n+\t\tdev_flow->mtr_flow_id = mtr_tag_id;\n+\t\t/* Prepare the suffix flow match pattern. */\n+\t\tsfx_items = (struct rte_flow_item *)((char *)sfx_actions +\n+\t\t\t     act_size);\n+\t\ttag_spec = (struct mlx5_rte_flow_item_tag *)(sfx_items +\n+\t\t\t    METER_SUFFIX_ITEM);\n+\t\ttag_spec->data = rte_cpu_to_be_32(dev_flow->mtr_flow_id);\n+\t\ttag_spec->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0,\n+\t\t\t\t\t\t    error);\n+\t\tsfx_items->type = MLX5_RTE_FLOW_ITEM_TYPE_TAG;\n+\t\tsfx_items->spec = tag_spec;\n+\t\tsfx_items->last = NULL;\n+\t\tsfx_items->mask = NULL;\n+\t\tsfx_items++;\n+\t\tsfx_port_id_item = find_port_id_item(items);\n+\t\tif (sfx_port_id_item) {\n+\t\t\tmemcpy(sfx_items, sfx_port_id_item,\n+\t\t\t       sizeof(*sfx_items));\n+\t\t\tsfx_items++;\n+\t\t}\n+\t\tsfx_items->type = RTE_FLOW_ITEM_TYPE_END;\n+\t\tsfx_items -= METER_SUFFIX_ITEM;\n+\t\t/* Setting the sfx group atrr. */\n+\t\tsfx_attr.group = sfx_attr.transfer ?\n+\t\t\t\t(MLX5_FLOW_TABLE_LEVEL_SUFFIX - 1) :\n+\t\t\t\t MLX5_FLOW_TABLE_LEVEL_SUFFIX;\n+\t}\n+\t/* Add the prefix subflow. */\n+\tret = flow_create_split_metadata(dev, flow, &sfx_attr,\n+\t\t\t\t\t sfx_items ? sfx_items : items,\n+\t\t\t\t\t sfx_actions ? sfx_actions : actions,\n+\t\t\t\t\t external, error);\n+exit:\n+\tif (sfx_actions)\n+\t\trte_free(sfx_actions);\n+\treturn ret;\n+}\n+\n+/**\n  * Split the flow to subflow set. The splitters might be linked\n  * in the chain, like this:\n  * flow_create_split_outer() calls:\n@@ -3755,7 +4052,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n {\n \tint ret;\n \n-\tret = flow_create_split_metadata(dev, flow, attr, items,\n+\tret = flow_create_split_meter(dev, flow, attr, items,\n \t\t\t\t\t actions, external, error);\n \tassert(ret <= 0);\n \treturn ret;\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex ffb6886..42b4c76 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -521,6 +521,7 @@ struct mlx5_flow {\n \t\tstruct mlx5_flow_verbs verbs;\n \t};\n \tuint32_t qrss_id; /**< Uniqie Q/RSS suffix subflow tag. */\n+\tuint32_t mtr_flow_id; /**< Unique meter match flow id. */\n \tbool external; /**< true if the flow is created external to PMD. */\n };\n \n",
    "prefixes": [
        "v2",
        "17/19"
    ]
}