get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 20994,
    "url": "https://patches.dpdk.org/api/patches/20994/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/6b31de8e945a0028098c86b8636f88ad583bd661.1488372438.git.nelio.laranjeiro@6wind.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<6b31de8e945a0028098c86b8636f88ad583bd661.1488372438.git.nelio.laranjeiro@6wind.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/6b31de8e945a0028098c86b8636f88ad583bd661.1488372438.git.nelio.laranjeiro@6wind.com",
    "date": "2017-03-01T12:49:46",
    "name": "[dpdk-dev,v2,7/9] net/mlx5: prepare support for RSS action rule",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "92d06fc4fb2961d974cd9761b393156c8180b7fc",
    "submitter": {
        "id": 243,
        "url": "https://patches.dpdk.org/api/people/243/?format=api",
        "name": "Nélio Laranjeiro",
        "email": "nelio.laranjeiro@6wind.com"
    },
    "delegate": {
        "id": 319,
        "url": "https://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/6b31de8e945a0028098c86b8636f88ad583bd661.1488372438.git.nelio.laranjeiro@6wind.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/20994/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/20994/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 7077DF950;\n\tWed,  1 Mar 2017 13:50:41 +0100 (CET)",
            "from mail-wm0-f53.google.com (mail-wm0-f53.google.com\n\t[74.125.82.53]) by dpdk.org (Postfix) with ESMTP id 83B112B86\n\tfor <dev@dpdk.org>; Wed,  1 Mar 2017 13:50:18 +0100 (CET)",
            "by mail-wm0-f53.google.com with SMTP id v186so109332407wmd.0\n\tfor <dev@dpdk.org>; Wed, 01 Mar 2017 04:50:18 -0800 (PST)",
            "from ping.vm.6wind.com (host.78.145.23.62.rev.coltfrance.com.\n\t[62.23.145.78]) by smtp.gmail.com with ESMTPSA id\n\tl45sm6502268wrc.14.2017.03.01.04.50.17\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n\tWed, 01 Mar 2017 04:50:17 -0800 (PST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=6wind-com.20150623.gappssmtp.com; s=20150623;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references\n\t:in-reply-to:references;\n\tbh=E5qA8AO+5cyf/VkXHwajkPaF2M4mu6fJthe0ZyQveuU=;\n\tb=aA2RjVE9+ysDuNQ2CIGHGWiGmpSvqlPC7urnF8KsP/tcSGPt3rjDP+Ep3CywnTQwWx\n\tVrgIpfUaExwcEoJr5QiC2sQbNiICVAyOjZXSZ0ptgw5nB1F840j16xCJtOrlERNh2iFv\n\tYkaUiIbAFROxndF9zWygIcenwDVSAuvJ/VKUEHWfy5OoEDITSKB/rcsDEowIjyvbwGT+\n\t8E8ym7MPIUn+kX37boBn4rsKRgneaTgqyrNdXx76Zh2vSfQOnumUQAshQjjcKRVBYviA\n\t0BozrgPTfaNbe5DpgL3swTAuywfu5d/2HwaIhOvkCSdKKdJ7cQgPfBs8HGjOTzWZl1bz\n\tdhPA==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references:in-reply-to:references;\n\tbh=E5qA8AO+5cyf/VkXHwajkPaF2M4mu6fJthe0ZyQveuU=;\n\tb=evzys8NV4CZwQO/ATG43IeoJ3TBIHX64LO14ZxC5/GgnoaRmTvrSdFuwXkJ6QnNC8y\n\thR646iszk/r+E5TzrQrluBqx81fD5AyzGm15SOtRpfiEUN8ogNGsZSi4uzM9AWMETkDb\n\tG3wuA6yY1Fh/sgFIRJNrsDVjQ05zAVIR4N21fE2gUHC5I5c97wCXlGGZ4ZtEg0TaP2q+\n\tq2QMooV8JKtmfVL5h87Lqw7N1bTtdQvPhCOlyriuxXiTnWDgGVg3raQA/x8h9X7IXXmf\n\tePBz5azj3jhJp4jhKAfkR4sVvK540SvVQcOvrSlKj4L7uqwZC+fmmpMkVrKhAE3WqOBB\n\tzCtg==",
        "X-Gm-Message-State": "AMke39muM21YP02BLL0pH3qjp/eTc+qeGDXYBRvnw0HIlDmOqufSdIY7YaH9pafwOr4oSEir",
        "X-Received": "by 10.28.65.196 with SMTP id o187mr3281899wma.9.1488372617977;\n\tWed, 01 Mar 2017 04:50:17 -0800 (PST)",
        "From": "Nelio Laranjeiro <nelio.laranjeiro@6wind.com>",
        "To": "dev@dpdk.org",
        "Cc": "Adrien Mazarguil <adrien.mazarguil@6wind.com>",
        "Date": "Wed,  1 Mar 2017 13:49:46 +0100",
        "Message-Id": "<6b31de8e945a0028098c86b8636f88ad583bd661.1488372438.git.nelio.laranjeiro@6wind.com>",
        "X-Mailer": "git-send-email 2.1.4",
        "In-Reply-To": [
            "<cover.1488372438.git.nelio.laranjeiro@6wind.com>",
            "<cover.1488372438.git.nelio.laranjeiro@6wind.com>"
        ],
        "References": [
            "<cover.1488372438.git.nelio.laranjeiro@6wind.com>",
            "<cover.1488364873.git.nelio.laranjeiro@6wind.com>\n\t<cover.1488372438.git.nelio.laranjeiro@6wind.com>"
        ],
        "Subject": "[dpdk-dev] [PATCH v2 7/9] net/mlx5: prepare support for RSS action\n\trule",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "In mlx5 PMD handling a single queue of several destination queues ends in\ncreating the same Verbs attribute, the main difference resides in the\nindirection table and the RSS hash key.\n\nThis helps to prepare the supports to the RSS queues by first handling the\nqueue action has being an RSS queue with a single queue.  No RSS hash key\nwill be provided to the Verbs flow.\n\nSigned-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>\n---\n drivers/net/mlx5/mlx5_flow.c | 249 +++++++++++++++++++++++++++++++++----------\n 1 file changed, 190 insertions(+), 59 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex 39a96ea..a188aa3 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -95,8 +95,10 @@ struct rte_flow {\n \tstruct ibv_exp_flow *ibv_flow; /**< Verbs flow. */\n \tstruct ibv_exp_wq *wq; /**< Verbs work queue. */\n \tstruct ibv_cq *cq; /**< Verbs completion queue. */\n-\tstruct rxq *rxq; /**< Pointer to the queue, NULL if drop queue. */\n+\tstruct rxq *(*rxqs)[]; /**< Pointer to the queues array. */\n+\tuint16_t rxqs_n; /**< Number of queues in this flow, 0 if drop queue. */\n \tuint32_t mark:1; /**< Set if the flow is marked. */\n+\tuint32_t drop:1; /**< Drop queue. */\n };\n \n /** Static initializer for items. */\n@@ -279,8 +281,9 @@ struct mlx5_flow_action {\n \tuint32_t queue:1; /**< Target is a receive queue. */\n \tuint32_t drop:1; /**< Target is a drop queue. */\n \tuint32_t mark:1; /**< Mark is present in the flow. */\n-\tuint32_t queue_id; /**< Identifier of the queue. */\n \tuint32_t mark_id; /**< Mark identifier. */\n+\tuint16_t queues[RTE_MAX_QUEUES_PER_PORT]; /**< Queues indexes to use. */\n+\tuint16_t queues_n; /**< Number of entries in queue[]. */\n };\n \n /**\n@@ -861,12 +864,128 @@ mlx5_flow_create_flag_mark(struct mlx5_flow *flow, uint32_t mark_id)\n }\n \n /**\n+ * Complete flow rule creation with a drop queue.\n+ *\n+ * @param priv\n+ *   Pointer to private structure.\n+ * @param flow\n+ *   MLX5 flow attributes (filled by mlx5_flow_validate()).\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL.\n+ *\n+ * @return\n+ *   A flow if the rule could be created.\n+ */\n+static struct rte_flow *\n+priv_flow_create_action_queue_drop(struct priv *priv,\n+\t\t\t\t   struct mlx5_flow *flow,\n+\t\t\t\t   struct rte_flow_error *error)\n+{\n+\tstruct rte_flow *rte_flow;\n+\n+\tassert(priv->pd);\n+\tassert(priv->ctx);\n+\trte_flow = rte_calloc(__func__, 1, sizeof(*rte_flow), 0);\n+\tif (!rte_flow) {\n+\t\trte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,\n+\t\t\t\t   NULL, \"cannot allocate flow memory\");\n+\t\treturn NULL;\n+\t}\n+\trte_flow->cq =\n+\t\tibv_exp_create_cq(priv->ctx, 1, NULL, NULL, 0,\n+\t\t\t\t  &(struct ibv_exp_cq_init_attr){\n+\t\t\t\t\t  .comp_mask = 0,\n+\t\t\t\t  });\n+\tif (!rte_flow->cq) {\n+\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_HANDLE,\n+\t\t\t\t   NULL, \"cannot allocate CQ\");\n+\t\tgoto error;\n+\t}\n+\trte_flow->wq = ibv_exp_create_wq(priv->ctx,\n+\t\t\t\t\t &(struct ibv_exp_wq_init_attr){\n+\t\t\t\t\t .wq_type = IBV_EXP_WQT_RQ,\n+\t\t\t\t\t .max_recv_wr = 1,\n+\t\t\t\t\t .max_recv_sge = 1,\n+\t\t\t\t\t .pd = priv->pd,\n+\t\t\t\t\t .cq = rte_flow->cq,\n+\t\t\t\t\t });\n+\tif (!rte_flow->wq) {\n+\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_HANDLE,\n+\t\t\t\t   NULL, \"cannot allocate WQ\");\n+\t\tgoto error;\n+\t}\n+\trte_flow->drop = 1;\n+\trte_flow->ibv_attr = flow->ibv_attr;\n+\trte_flow->ind_table = ibv_exp_create_rwq_ind_table(\n+\t\tpriv->ctx,\n+\t\t&(struct ibv_exp_rwq_ind_table_init_attr){\n+\t\t\t.pd = priv->pd,\n+\t\t\t.log_ind_tbl_size = 0,\n+\t\t\t.ind_tbl = &rte_flow->wq,\n+\t\t\t.comp_mask = 0,\n+\t\t});\n+\tif (!rte_flow->ind_table) {\n+\t\trte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,\n+\t\t\t\t   NULL, \"cannot allocate indirection table\");\n+\t\tgoto error;\n+\t}\n+\trte_flow->qp = ibv_exp_create_qp(\n+\t\tpriv->ctx,\n+\t\t&(struct ibv_exp_qp_init_attr){\n+\t\t\t.qp_type = IBV_QPT_RAW_PACKET,\n+\t\t\t.comp_mask =\n+\t\t\t\tIBV_EXP_QP_INIT_ATTR_PD |\n+\t\t\t\tIBV_EXP_QP_INIT_ATTR_PORT |\n+\t\t\t\tIBV_EXP_QP_INIT_ATTR_RX_HASH,\n+\t\t\t.pd = priv->pd,\n+\t\t\t.rx_hash_conf = &(struct ibv_exp_rx_hash_conf){\n+\t\t\t\t.rx_hash_function =\n+\t\t\t\t\tIBV_EXP_RX_HASH_FUNC_TOEPLITZ,\n+\t\t\t\t.rx_hash_key_len = rss_hash_default_key_len,\n+\t\t\t\t.rx_hash_key = rss_hash_default_key,\n+\t\t\t\t.rx_hash_fields_mask = 0,\n+\t\t\t\t.rwq_ind_tbl = rte_flow->ind_table,\n+\t\t\t},\n+\t\t\t.port_num = priv->port,\n+\t\t});\n+\tif (!rte_flow->qp) {\n+\t\trte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,\n+\t\t\t\t   NULL, \"cannot allocate QP\");\n+\t\tgoto error;\n+\t}\n+\tif (!priv->started)\n+\t\treturn rte_flow;\n+\trte_flow->ibv_flow = ibv_exp_create_flow(rte_flow->qp,\n+\t\t\t\t\t\t rte_flow->ibv_attr);\n+\tif (!rte_flow->ibv_flow) {\n+\t\trte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,\n+\t\t\t\t   NULL, \"flow rule creation failure\");\n+\t\tgoto error;\n+\t}\n+\treturn rte_flow;\n+error:\n+\tassert(rte_flow);\n+\tif (rte_flow->qp)\n+\t\tibv_destroy_qp(rte_flow->qp);\n+\tif (rte_flow->ind_table)\n+\t\tibv_exp_destroy_rwq_ind_table(rte_flow->ind_table);\n+\tif (rte_flow->wq)\n+\t\tibv_exp_destroy_wq(rte_flow->wq);\n+\tif (rte_flow->cq)\n+\t\tibv_destroy_cq(rte_flow->cq);\n+\trte_free(rte_flow);\n+\treturn NULL;\n+}\n+\n+/**\n  * Complete flow rule creation.\n  *\n  * @param priv\n  *   Pointer to private structure.\n- * @param ibv_attr\n- *   Verbs flow attributes.\n+ * @param flow\n+ *   MLX5 flow attributes (filled by mlx5_flow_validate()).\n  * @param action\n  *   Target action structure.\n  * @param[out] error\n@@ -877,62 +996,46 @@ mlx5_flow_create_flag_mark(struct mlx5_flow *flow, uint32_t mark_id)\n  */\n static struct rte_flow *\n priv_flow_create_action_queue(struct priv *priv,\n-\t\t\t      struct ibv_exp_flow_attr *ibv_attr,\n+\t\t\t      struct mlx5_flow *flow,\n \t\t\t      struct mlx5_flow_action *action,\n \t\t\t      struct rte_flow_error *error)\n {\n-\tstruct rxq_ctrl *rxq;\n \tstruct rte_flow *rte_flow;\n+\tunsigned int i;\n+\tstruct ibv_exp_wq *wq[action->queues_n];\n \n \tassert(priv->pd);\n \tassert(priv->ctx);\n-\trte_flow = rte_calloc(__func__, 1, sizeof(*rte_flow), 0);\n+\tassert(!action->drop);\n+\trte_flow = rte_calloc(__func__, 1,\n+\t\t\t      sizeof(*rte_flow) + sizeof(struct rxq *) *\n+\t\t\t      action->queues_n, 0);\n \tif (!rte_flow) {\n \t\trte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,\n \t\t\t\t   NULL, \"cannot allocate flow memory\");\n \t\treturn NULL;\n \t}\n-\tif (action->drop) {\n-\t\trte_flow->cq =\n-\t\t\tibv_exp_create_cq(priv->ctx, 1, NULL, NULL, 0,\n-\t\t\t\t\t  &(struct ibv_exp_cq_init_attr){\n-\t\t\t\t\t\t  .comp_mask = 0,\n-\t\t\t\t\t  });\n-\t\tif (!rte_flow->cq) {\n-\t\t\trte_flow_error_set(error, ENOMEM,\n-\t\t\t\t\t   RTE_FLOW_ERROR_TYPE_HANDLE,\n-\t\t\t\t\t   NULL, \"cannot allocate CQ\");\n-\t\t\tgoto error;\n-\t\t}\n-\t\trte_flow->wq = ibv_exp_create_wq(priv->ctx,\n-\t\t\t\t\t\t &(struct ibv_exp_wq_init_attr){\n-\t\t\t\t\t\t .wq_type = IBV_EXP_WQT_RQ,\n-\t\t\t\t\t\t .max_recv_wr = 1,\n-\t\t\t\t\t\t .max_recv_sge = 1,\n-\t\t\t\t\t\t .pd = priv->pd,\n-\t\t\t\t\t\t .cq = rte_flow->cq,\n-\t\t\t\t\t\t });\n-\t\tif (!rte_flow->wq) {\n-\t\t\trte_flow_error_set(error, ENOMEM,\n-\t\t\t\t\t   RTE_FLOW_ERROR_TYPE_HANDLE,\n-\t\t\t\t\t   NULL, \"cannot allocate WQ\");\n-\t\t\tgoto error;\n-\t\t}\n-\t} else {\n-\t\trxq = container_of((*priv->rxqs)[action->queue_id],\n+\trte_flow->rxqs = (struct rxq *(*)[])((uintptr_t)rte_flow +\n+\t\t\t\t\t     sizeof(struct rxq *) *\n+\t\t\t\t\t     action->queues_n);\n+\tfor (i = 0; i < action->queues_n; ++i) {\n+\t\tstruct rxq_ctrl *rxq;\n+\n+\t\trxq = container_of((*priv->rxqs)[action->queues[i]],\n \t\t\t\t   struct rxq_ctrl, rxq);\n-\t\trte_flow->rxq = &rxq->rxq;\n+\t\twq[i] = rxq->wq;\n+\t\t(*rte_flow->rxqs)[i] = &rxq->rxq;\n+\t\t++rte_flow->rxqs_n;\n \t\trxq->rxq.mark |= action->mark;\n-\t\trte_flow->wq = rxq->wq;\n \t}\n \trte_flow->mark = action->mark;\n-\trte_flow->ibv_attr = ibv_attr;\n+\trte_flow->ibv_attr = flow->ibv_attr;\n \trte_flow->ind_table = ibv_exp_create_rwq_ind_table(\n \t\tpriv->ctx,\n \t\t&(struct ibv_exp_rwq_ind_table_init_attr){\n \t\t\t.pd = priv->pd,\n \t\t\t.log_ind_tbl_size = 0,\n-\t\t\t.ind_tbl = &rte_flow->wq,\n+\t\t\t.ind_tbl = wq,\n \t\t\t.comp_mask = 0,\n \t\t});\n \tif (!rte_flow->ind_table) {\n@@ -980,10 +1083,6 @@ priv_flow_create_action_queue(struct priv *priv,\n \t\tibv_destroy_qp(rte_flow->qp);\n \tif (rte_flow->ind_table)\n \t\tibv_exp_destroy_rwq_ind_table(rte_flow->ind_table);\n-\tif (!rte_flow->rxq && rte_flow->wq)\n-\t\tibv_exp_destroy_wq(rte_flow->wq);\n-\tif (!rte_flow->rxq && rte_flow->cq)\n-\t\tibv_destroy_cq(rte_flow->cq);\n \trte_free(rte_flow);\n \treturn NULL;\n }\n@@ -1050,7 +1149,7 @@ priv_flow_create(struct priv *priv,\n \t\t\tcontinue;\n \t\t} else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) {\n \t\t\taction.queue = 1;\n-\t\t\taction.queue_id =\n+\t\t\taction.queues[action.queues_n++] =\n \t\t\t\t((const struct rte_flow_action_queue *)\n \t\t\t\t actions->conf)->index;\n \t\t} else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) {\n@@ -1077,8 +1176,12 @@ priv_flow_create(struct priv *priv,\n \t\tmlx5_flow_create_flag_mark(&flow, action.mark_id);\n \t\tflow.offset += sizeof(struct ibv_exp_flow_spec_action_tag);\n \t}\n-\trte_flow = priv_flow_create_action_queue(priv, flow.ibv_attr,\n-\t\t\t\t\t\t &action, error);\n+\tif (action.drop)\n+\t\trte_flow =\n+\t\t\tpriv_flow_create_action_queue_drop(priv, &flow, error);\n+\telse\n+\t\trte_flow = priv_flow_create_action_queue(priv, &flow, &action,\n+\t\t\t\t\t\t\t error);\n \tif (!rte_flow)\n \t\tgoto exit;\n \treturn rte_flow;\n@@ -1133,21 +1236,41 @@ priv_flow_destroy(struct priv *priv,\n \t\tclaim_zero(ibv_destroy_qp(flow->qp));\n \tif (flow->ind_table)\n \t\tclaim_zero(ibv_exp_destroy_rwq_ind_table(flow->ind_table));\n-\tif (!flow->rxq && flow->wq)\n+\tif (flow->drop && flow->wq)\n \t\tclaim_zero(ibv_exp_destroy_wq(flow->wq));\n-\tif (!flow->rxq && flow->cq)\n+\tif (flow->drop && flow->cq)\n \t\tclaim_zero(ibv_destroy_cq(flow->cq));\n \tif (flow->mark) {\n \t\tstruct rte_flow *tmp;\n+\t\tstruct rxq *rxq;\n \t\tuint32_t mark_n = 0;\n-\n-\t\tfor (tmp = LIST_FIRST(&priv->flows);\n-\t\t     tmp;\n-\t\t     tmp = LIST_NEXT(tmp, next)) {\n-\t\t\tif ((flow->rxq == tmp->rxq) && tmp->mark)\n-\t\t\t\t++mark_n;\n+\t\tuint32_t queue_n;\n+\n+\t\t/*\n+\t\t * To remove the mark from the queue, the queue must not be\n+\t\t * present in any other marked flow (RSS or not).\n+\t\t */\n+\t\tfor (queue_n = 0; queue_n < flow->rxqs_n; ++queue_n) {\n+\t\t\trxq = (*flow->rxqs)[queue_n];\n+\t\t\tfor (tmp = LIST_FIRST(&priv->flows);\n+\t\t\t     tmp;\n+\t\t\t     tmp = LIST_NEXT(tmp, next)) {\n+\t\t\t\tuint32_t tqueue_n;\n+\n+\t\t\t\tif (tmp->drop)\n+\t\t\t\t\tcontinue;\n+\t\t\t\tfor (tqueue_n = 0;\n+\t\t\t\t     tqueue_n < tmp->rxqs_n;\n+\t\t\t\t     ++tqueue_n) {\n+\t\t\t\t\tstruct rxq *trxq;\n+\n+\t\t\t\t\ttrxq = (*tmp->rxqs)[tqueue_n];\n+\t\t\t\t\tif (rxq == trxq)\n+\t\t\t\t\t\t++mark_n;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\trxq->mark = !!mark_n;\n \t\t}\n-\t\tflow->rxq->mark = !!mark_n;\n \t}\n \trte_free(flow->ibv_attr);\n \tDEBUG(\"Flow destroyed %p\", (void *)flow);\n@@ -1228,8 +1351,12 @@ priv_flow_stop(struct priv *priv)\n \t     flow = LIST_NEXT(flow, next)) {\n \t\tclaim_zero(ibv_exp_destroy_flow(flow->ibv_flow));\n \t\tflow->ibv_flow = NULL;\n-\t\tif (flow->mark)\n-\t\t\tflow->rxq->mark = 0;\n+\t\tif (flow->mark) {\n+\t\t\tunsigned int n;\n+\n+\t\t\tfor (n = 0; n < flow->rxqs_n; ++n)\n+\t\t\t\t(*flow->rxqs)[n]->mark = 0;\n+\t\t}\n \t\tDEBUG(\"Flow %p removed\", (void *)flow);\n \t}\n }\n@@ -1259,8 +1386,12 @@ priv_flow_start(struct priv *priv)\n \t\t\treturn rte_errno;\n \t\t}\n \t\tDEBUG(\"Flow %p applied\", (void *)flow);\n-\t\tif (flow->rxq)\n-\t\t\tflow->rxq->mark |= flow->mark;\n+\t\tif (flow->mark) {\n+\t\t\tunsigned int n;\n+\n+\t\t\tfor (n = 0; n < flow->rxqs_n; ++n)\n+\t\t\t\t(*flow->rxqs)[n]->mark = 1;\n+\t\t}\n \t}\n \treturn 0;\n }\n",
    "prefixes": [
        "dpdk-dev",
        "v2",
        "7/9"
    ]
}