get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 10743,
    "url": "http://patches.dpdk.org/api/patches/10743/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1456164127-28072-2-git-send-email-adrien.mazarguil@6wind.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": "<1456164127-28072-2-git-send-email-adrien.mazarguil@6wind.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1456164127-28072-2-git-send-email-adrien.mazarguil@6wind.com",
    "date": "2016-02-22T18:02:03",
    "name": "[dpdk-dev,v2,1/5] mlx5: refactor special flows handling",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "6182facc9f336c30f641668d8c658263d46649fa",
    "submitter": {
        "id": 165,
        "url": "http://patches.dpdk.org/api/people/165/?format=api",
        "name": "Adrien Mazarguil",
        "email": "adrien.mazarguil@6wind.com"
    },
    "delegate": {
        "id": 10,
        "url": "http://patches.dpdk.org/api/users/10/?format=api",
        "username": "bruce",
        "first_name": "Bruce",
        "last_name": "Richardson",
        "email": "bruce.richardson@intel.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1456164127-28072-2-git-send-email-adrien.mazarguil@6wind.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/10743/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/10743/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 995B42C53;\n\tMon, 22 Feb 2016 19:02:27 +0100 (CET)",
            "from mail-wm0-f47.google.com (mail-wm0-f47.google.com\n\t[74.125.82.47]) by dpdk.org (Postfix) with ESMTP id 4101F2C52\n\tfor <dev@dpdk.org>; Mon, 22 Feb 2016 19:02:26 +0100 (CET)",
            "by mail-wm0-f47.google.com with SMTP id a4so174761142wme.1\n\tfor <dev@dpdk.org>; Mon, 22 Feb 2016 10:02:26 -0800 (PST)",
            "from 6wind.com (guy78-3-82-239-227-177.fbx.proxad.net.\n\t[82.239.227.177]) by smtp.gmail.com with ESMTPSA id\n\ti12sm22135883wmf.10.2016.02.22.10.02.23\n\t(version=TLSv1/SSLv3 cipher=OTHER);\n\tMon, 22 Feb 2016 10:02:25 -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\tbh=2sE1vlVvSEZKysHXzo9SyDvqrAOM1ksXTOzAvSK0SS4=;\n\tb=FJf9ivFe2IY4XNGAGaUM0rIpZ9abP58ZJ7p8LfjMv+vAxLye32hltLmnu0i/VdXPC0\n\t7EqHCUpqh242NJOipXQniXDhgXBZ+89QXAOXWjSiWhb6KdIPWRVV/i2R6NruodZWfW72\n\tolyJySP2frclClLGPIW4PKnOWQOhARkcSa8W8c4XJ0tvRd++qP427xE6A5frbCD+e/VO\n\thY992JXuMD+gfclPdwuvZ5NiH2+8TJgPYnLyOKkuh+UATnfnJgeJprBFkU4CHqkd0oR+\n\tKlmC2zDXliqTQX8EGBc1GjeU58M2Fy9qTxSsgOaJNBq9CTdCCy4k9tnxSaBouj5MMlL7\n\tJ+Jw==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20130820;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=2sE1vlVvSEZKysHXzo9SyDvqrAOM1ksXTOzAvSK0SS4=;\n\tb=l8ihSc1fG4Gkf/jRYsSsMBgwHEvcaZjfhn/AvyCN4CnDn9hVze9YDkFcDCg9JmCefU\n\tu0YVaMRRWMzhaZEmrzK9anunITESZ6MRhx+lXpSQeg+jeFQ3fG/slaIyaWaQ+25/d/Ov\n\tWaSnoEUlJd6gq6O6nvtvFnrIq2+smmmVZ5Jeg3zYMhop84SBeEdOo3bHVkm1+y7HJmY8\n\tJAx/FBwLQWNfXk4mqTxAf6haXeGLj2jVj5IBvnXNovrR488Tl7dRhGvbpUDd+NN1LXbU\n\tJP84gGx/+qvV59GZaCfVxm456A3w+D1fk6MalTH2GYJPW1zhHdKWpoLNNLFtC20gZAyB\n\txO5A==",
        "X-Gm-Message-State": "AG10YOQs/zQkQ8jhbxCXCyAQcdyD6HgzsK3KQs/TMpRa9J99aQ8m65gUXDVPHGBhKKD8sPPy",
        "X-Received": "by 10.194.87.1 with SMTP id t1mr28725940wjz.170.1456164146100;\n\tMon, 22 Feb 2016 10:02:26 -0800 (PST)",
        "From": "Adrien Mazarguil <adrien.mazarguil@6wind.com>",
        "To": "dev@dpdk.org",
        "Date": "Mon, 22 Feb 2016 19:02:03 +0100",
        "Message-Id": "<1456164127-28072-2-git-send-email-adrien.mazarguil@6wind.com>",
        "X-Mailer": "git-send-email 2.1.4",
        "In-Reply-To": "<1456164127-28072-1-git-send-email-adrien.mazarguil@6wind.com>",
        "References": "<1454063522-1948-1-git-send-email-adrien.mazarguil@6wind.com>\n\t<1456164127-28072-1-git-send-email-adrien.mazarguil@6wind.com>",
        "Subject": "[dpdk-dev] [PATCH v2 1/5] mlx5: refactor special flows handling",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <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": "From: Yaacov Hazan <yaacovh@mellanox.com>\n\nMerge redundant code by adding a static initialization table to manage\npromiscuous and allmulticast (special) flows.\n\nNew function priv_rehash_flows() implements the logic to enable/disable\nrelevant flows in one place from any context.\n\nSigned-off-by: Yaacov Hazan <yaacovh@mellanox.com>\nSigned-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>\n---\n drivers/net/mlx5/mlx5.c         |   4 +-\n drivers/net/mlx5/mlx5.h         |   6 +-\n drivers/net/mlx5/mlx5_defs.h    |   3 +\n drivers/net/mlx5/mlx5_rxmode.c  | 321 ++++++++++++++++++----------------------\n drivers/net/mlx5/mlx5_rxq.c     |  33 ++++-\n drivers/net/mlx5/mlx5_rxtx.h    |  29 +++-\n drivers/net/mlx5/mlx5_trigger.c |  14 +-\n 7 files changed, 210 insertions(+), 200 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex 30d88b5..52bf4b2 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -88,8 +88,8 @@ mlx5_dev_close(struct rte_eth_dev *dev)\n \t      ((priv->ctx != NULL) ? priv->ctx->device->name : \"\"));\n \t/* In case mlx5_dev_stop() has not been called. */\n \tpriv_dev_interrupt_handler_uninstall(priv, dev);\n-\tpriv_allmulticast_disable(priv);\n-\tpriv_promiscuous_disable(priv);\n+\tpriv_special_flow_disable(priv, HASH_RXQ_FLOW_TYPE_ALLMULTI);\n+\tpriv_special_flow_disable(priv, HASH_RXQ_FLOW_TYPE_PROMISC);\n \tpriv_mac_addrs_disable(priv);\n \tpriv_destroy_hash_rxqs(priv);\n \t/* Prevent crashes when queues are still in use. */\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 2f9a594..1c69bfa 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -195,13 +195,11 @@ int mlx5_dev_rss_reta_update(struct rte_eth_dev *,\n \n /* mlx5_rxmode.c */\n \n-int priv_promiscuous_enable(struct priv *);\n+int priv_special_flow_enable(struct priv *, enum hash_rxq_flow_type);\n+void priv_special_flow_disable(struct priv *, enum hash_rxq_flow_type);\n void mlx5_promiscuous_enable(struct rte_eth_dev *);\n-void priv_promiscuous_disable(struct priv *);\n void mlx5_promiscuous_disable(struct rte_eth_dev *);\n-int priv_allmulticast_enable(struct priv *);\n void mlx5_allmulticast_enable(struct rte_eth_dev *);\n-void priv_allmulticast_disable(struct priv *);\n void mlx5_allmulticast_disable(struct rte_eth_dev *);\n \n /* mlx5_stats.c */\ndiff --git a/drivers/net/mlx5/mlx5_defs.h b/drivers/net/mlx5/mlx5_defs.h\nindex bb82c9a..1ec14ef 100644\n--- a/drivers/net/mlx5/mlx5_defs.h\n+++ b/drivers/net/mlx5/mlx5_defs.h\n@@ -43,6 +43,9 @@\n /* Maximum number of simultaneous VLAN filters. */\n #define MLX5_MAX_VLAN_IDS 128\n \n+/* Maximum number of special flows. */\n+#define MLX5_MAX_SPECIAL_FLOWS 2\n+\n /* Request send completion once in every 64 sends, might be less. */\n #define MLX5_PMD_TX_PER_COMP_REQ 64\n \ndiff --git a/drivers/net/mlx5/mlx5_rxmode.c b/drivers/net/mlx5/mlx5_rxmode.c\nindex 096fd18..b2ed17e 100644\n--- a/drivers/net/mlx5/mlx5_rxmode.c\n+++ b/drivers/net/mlx5/mlx5_rxmode.c\n@@ -58,31 +58,96 @@\n #include \"mlx5_rxtx.h\"\n #include \"mlx5_utils.h\"\n \n-static void hash_rxq_promiscuous_disable(struct hash_rxq *);\n-static void hash_rxq_allmulticast_disable(struct hash_rxq *);\n+/* Initialization data for special flows. */\n+static const struct special_flow_init special_flow_init[] = {\n+\t[HASH_RXQ_FLOW_TYPE_PROMISC] = {\n+\t\t.dst_mac_val = \"\\x00\\x00\\x00\\x00\\x00\\x00\",\n+\t\t.dst_mac_mask = \"\\x00\\x00\\x00\\x00\\x00\\x00\",\n+\t\t.hash_types =\n+\t\t\t1 << HASH_RXQ_TCPV4 |\n+\t\t\t1 << HASH_RXQ_UDPV4 |\n+\t\t\t1 << HASH_RXQ_IPV4 |\n+#ifdef HAVE_FLOW_SPEC_IPV6\n+\t\t\t1 << HASH_RXQ_TCPV6 |\n+\t\t\t1 << HASH_RXQ_UDPV6 |\n+\t\t\t1 << HASH_RXQ_IPV6 |\n+#endif /* HAVE_FLOW_SPEC_IPV6 */\n+\t\t\t1 << HASH_RXQ_ETH |\n+\t\t\t0,\n+\t},\n+\t[HASH_RXQ_FLOW_TYPE_ALLMULTI] = {\n+\t\t.dst_mac_val = \"\\x01\\x00\\x00\\x00\\x00\\x00\",\n+\t\t.dst_mac_mask = \"\\x01\\x00\\x00\\x00\\x00\\x00\",\n+\t\t.hash_types =\n+\t\t\t1 << HASH_RXQ_UDPV4 |\n+\t\t\t1 << HASH_RXQ_IPV4 |\n+#ifdef HAVE_FLOW_SPEC_IPV6\n+\t\t\t1 << HASH_RXQ_UDPV6 |\n+\t\t\t1 << HASH_RXQ_IPV6 |\n+#endif /* HAVE_FLOW_SPEC_IPV6 */\n+\t\t\t1 << HASH_RXQ_ETH |\n+\t\t\t0,\n+\t},\n+};\n \n /**\n- * Enable promiscuous mode in a hash RX queue.\n+ * Enable a special flow in a hash RX queue.\n  *\n  * @param hash_rxq\n  *   Pointer to hash RX queue structure.\n+ * @param flow_type\n+ *   Special flow type.\n  *\n  * @return\n  *   0 on success, errno value on failure.\n  */\n static int\n-hash_rxq_promiscuous_enable(struct hash_rxq *hash_rxq)\n+hash_rxq_special_flow_enable(struct hash_rxq *hash_rxq,\n+\t\t\t     enum hash_rxq_flow_type flow_type)\n {\n \tstruct ibv_exp_flow *flow;\n \tFLOW_ATTR_SPEC_ETH(data, hash_rxq_flow_attr(hash_rxq, NULL, 0));\n \tstruct ibv_exp_flow_attr *attr = &data->attr;\n+\tstruct ibv_exp_flow_spec_eth *spec = &data->spec;\n+\tconst uint8_t *mac;\n+\tconst uint8_t *mask;\n \n-\tif (hash_rxq->promisc_flow != NULL)\n+\t/* Check if flow is relevant for this hash_rxq. */\n+\tif (!(special_flow_init[flow_type].hash_types & (1 << hash_rxq->type)))\n+\t\treturn 0;\n+\t/* Check if flow already exists. */\n+\tif (hash_rxq->special_flow[flow_type] != NULL)\n \t\treturn 0;\n-\tDEBUG(\"%p: enabling promiscuous mode\", (void *)hash_rxq);\n-\t/* Promiscuous flows only differ from normal flows by not filtering\n-\t * on specific MAC addresses. */\n+\n+\t/*\n+\t * No padding must be inserted by the compiler between attr and spec.\n+\t * This layout is expected by libibverbs.\n+\t */\n+\tassert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec);\n \thash_rxq_flow_attr(hash_rxq, attr, sizeof(data));\n+\t/* The first specification must be Ethernet. */\n+\tassert(spec->type == IBV_EXP_FLOW_SPEC_ETH);\n+\tassert(spec->size == sizeof(*spec));\n+\n+\tmac = special_flow_init[flow_type].dst_mac_val;\n+\tmask = special_flow_init[flow_type].dst_mac_mask;\n+\t*spec = (struct ibv_exp_flow_spec_eth){\n+\t\t.type = IBV_EXP_FLOW_SPEC_ETH,\n+\t\t.size = sizeof(*spec),\n+\t\t.val = {\n+\t\t\t.dst_mac = {\n+\t\t\t\tmac[0], mac[1], mac[2],\n+\t\t\t\tmac[3], mac[4], mac[5],\n+\t\t\t},\n+\t\t},\n+\t\t.mask = {\n+\t\t\t.dst_mac = {\n+\t\t\t\tmask[0], mask[1], mask[2],\n+\t\t\t\tmask[3], mask[4], mask[5],\n+\t\t\t},\n+\t\t},\n+\t};\n+\n \terrno = 0;\n \tflow = ibv_exp_create_flow(hash_rxq->qp, attr);\n \tif (flow == NULL) {\n@@ -94,38 +159,63 @@ hash_rxq_promiscuous_enable(struct hash_rxq *hash_rxq)\n \t\t\treturn errno;\n \t\treturn EINVAL;\n \t}\n-\thash_rxq->promisc_flow = flow;\n-\tDEBUG(\"%p: promiscuous mode enabled\", (void *)hash_rxq);\n+\thash_rxq->special_flow[flow_type] = flow;\n+\tDEBUG(\"%p: enabling special flow %s (%d)\",\n+\t      (void *)hash_rxq, hash_rxq_flow_type_str(flow_type), flow_type);\n \treturn 0;\n }\n \n /**\n- * Enable promiscuous mode in all hash RX queues.\n+ * Disable a special flow in a hash RX queue.\n+ *\n+ * @param hash_rxq\n+ *   Pointer to hash RX queue structure.\n+ * @param flow_type\n+ *   Special flow type.\n+ */\n+static void\n+hash_rxq_special_flow_disable(struct hash_rxq *hash_rxq,\n+\t\t\t      enum hash_rxq_flow_type flow_type)\n+{\n+\tif (hash_rxq->special_flow[flow_type] == NULL)\n+\t\treturn;\n+\tDEBUG(\"%p: disabling special flow %s (%d)\",\n+\t      (void *)hash_rxq, hash_rxq_flow_type_str(flow_type), flow_type);\n+\tclaim_zero(ibv_exp_destroy_flow(hash_rxq->special_flow[flow_type]));\n+\thash_rxq->special_flow[flow_type] = NULL;\n+\tDEBUG(\"%p: special flow %s (%d) disabled\",\n+\t      (void *)hash_rxq, hash_rxq_flow_type_str(flow_type), flow_type);\n+}\n+\n+/**\n+ * Enable a special flow in all hash RX queues.\n  *\n  * @param priv\n  *   Private structure.\n+ * @param flow_type\n+ *   Special flow type.\n  *\n  * @return\n  *   0 on success, errno value on failure.\n  */\n int\n-priv_promiscuous_enable(struct priv *priv)\n+priv_special_flow_enable(struct priv *priv, enum hash_rxq_flow_type flow_type)\n {\n \tunsigned int i;\n \n-\tif (!priv_allow_flow_type(priv, HASH_RXQ_FLOW_TYPE_PROMISC))\n+\tif (!priv_allow_flow_type(priv, flow_type))\n \t\treturn 0;\n \tfor (i = 0; (i != priv->hash_rxqs_n); ++i) {\n \t\tstruct hash_rxq *hash_rxq = &(*priv->hash_rxqs)[i];\n \t\tint ret;\n \n-\t\tret = hash_rxq_promiscuous_enable(hash_rxq);\n+\t\tret = hash_rxq_special_flow_enable(hash_rxq, flow_type);\n \t\tif (!ret)\n \t\t\tcontinue;\n \t\t/* Failure, rollback. */\n \t\twhile (i != 0) {\n \t\t\thash_rxq = &(*priv->hash_rxqs)[--i];\n-\t\t\thash_rxq_promiscuous_disable(hash_rxq);\n+\t\t\thash_rxq_special_flow_disable(hash_rxq, flow_type);\n \t\t}\n \t\treturn ret;\n \t}\n@@ -133,6 +223,26 @@ priv_promiscuous_enable(struct priv *priv)\n }\n \n /**\n+ * Disable a special flow in all hash RX queues.\n+ *\n+ * @param priv\n+ *   Private structure.\n+ * @param flow_type\n+ *   Special flow type.\n+ */\n+void\n+priv_special_flow_disable(struct priv *priv, enum hash_rxq_flow_type flow_type)\n+{\n+\tunsigned int i;\n+\n+\tfor (i = 0; (i != priv->hash_rxqs_n); ++i) {\n+\t\tstruct hash_rxq *hash_rxq = &(*priv->hash_rxqs)[i];\n+\n+\t\thash_rxq_special_flow_disable(hash_rxq, flow_type);\n+\t}\n+}\n+\n+/**\n  * DPDK callback to enable promiscuous mode.\n  *\n  * @param dev\n@@ -146,49 +256,14 @@ mlx5_promiscuous_enable(struct rte_eth_dev *dev)\n \n \tpriv_lock(priv);\n \tpriv->promisc_req = 1;\n-\tret = priv_promiscuous_enable(priv);\n+\tret = priv_rehash_flows(priv);\n \tif (ret)\n-\t\tERROR(\"cannot enable promiscuous mode: %s\", strerror(ret));\n-\telse {\n-\t\tpriv_mac_addrs_disable(priv);\n-\t\tpriv_allmulticast_disable(priv);\n-\t}\n+\t\tERROR(\"error while enabling promiscuous mode: %s\",\n+\t\t      strerror(ret));\n \tpriv_unlock(priv);\n }\n \n /**\n- * Disable promiscuous mode in a hash RX queue.\n- *\n- * @param hash_rxq\n- *   Pointer to hash RX queue structure.\n- */\n-static void\n-hash_rxq_promiscuous_disable(struct hash_rxq *hash_rxq)\n-{\n-\tif (hash_rxq->promisc_flow == NULL)\n-\t\treturn;\n-\tDEBUG(\"%p: disabling promiscuous mode\", (void *)hash_rxq);\n-\tclaim_zero(ibv_exp_destroy_flow(hash_rxq->promisc_flow));\n-\thash_rxq->promisc_flow = NULL;\n-\tDEBUG(\"%p: promiscuous mode disabled\", (void *)hash_rxq);\n-}\n-\n-/**\n- * Disable promiscuous mode in all hash RX queues.\n- *\n- * @param priv\n- *   Private structure.\n- */\n-void\n-priv_promiscuous_disable(struct priv *priv)\n-{\n-\tunsigned int i;\n-\n-\tfor (i = 0; (i != priv->hash_rxqs_n); ++i)\n-\t\thash_rxq_promiscuous_disable(&(*priv->hash_rxqs)[i]);\n-}\n-\n-/**\n  * DPDK callback to disable promiscuous mode.\n  *\n  * @param dev\n@@ -198,105 +273,18 @@ void\n mlx5_promiscuous_disable(struct rte_eth_dev *dev)\n {\n \tstruct priv *priv = dev->data->dev_private;\n+\tint ret;\n \n \tpriv_lock(priv);\n \tpriv->promisc_req = 0;\n-\tpriv_promiscuous_disable(priv);\n-\tpriv_mac_addrs_enable(priv);\n-\tpriv_allmulticast_enable(priv);\n+\tret = priv_rehash_flows(priv);\n+\tif (ret)\n+\t\tERROR(\"error while disabling promiscuous mode: %s\",\n+\t\t      strerror(ret));\n \tpriv_unlock(priv);\n }\n \n /**\n- * Enable allmulti mode in a hash RX queue.\n- *\n- * @param hash_rxq\n- *   Pointer to hash RX queue structure.\n- *\n- * @return\n- *   0 on success, errno value on failure.\n- */\n-static int\n-hash_rxq_allmulticast_enable(struct hash_rxq *hash_rxq)\n-{\n-\tstruct ibv_exp_flow *flow;\n-\tFLOW_ATTR_SPEC_ETH(data, hash_rxq_flow_attr(hash_rxq, NULL, 0));\n-\tstruct ibv_exp_flow_attr *attr = &data->attr;\n-\tstruct ibv_exp_flow_spec_eth *spec = &data->spec;\n-\n-\tif (hash_rxq->allmulti_flow != NULL)\n-\t\treturn 0;\n-\tDEBUG(\"%p: enabling allmulticast mode\", (void *)hash_rxq);\n-\t/*\n-\t * No padding must be inserted by the compiler between attr and spec.\n-\t * This layout is expected by libibverbs.\n-\t */\n-\tassert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec);\n-\thash_rxq_flow_attr(hash_rxq, attr, sizeof(data));\n-\t*spec = (struct ibv_exp_flow_spec_eth){\n-\t\t.type = IBV_EXP_FLOW_SPEC_ETH,\n-\t\t.size = sizeof(*spec),\n-\t\t.val = {\n-\t\t\t.dst_mac = \"\\x01\\x00\\x00\\x00\\x00\\x00\",\n-\t\t},\n-\t\t.mask = {\n-\t\t\t.dst_mac = \"\\x01\\x00\\x00\\x00\\x00\\x00\",\n-\t\t},\n-\t};\n-\terrno = 0;\n-\tflow = ibv_exp_create_flow(hash_rxq->qp, attr);\n-\tif (flow == NULL) {\n-\t\t/* It's not clear whether errno is always set in this case. */\n-\t\tERROR(\"%p: flow configuration failed, errno=%d: %s\",\n-\t\t      (void *)hash_rxq, errno,\n-\t\t      (errno ? strerror(errno) : \"Unknown error\"));\n-\t\tif (errno)\n-\t\t\treturn errno;\n-\t\treturn EINVAL;\n-\t}\n-\thash_rxq->allmulti_flow = flow;\n-\tDEBUG(\"%p: allmulticast mode enabled\", (void *)hash_rxq);\n-\treturn 0;\n-}\n-\n-/**\n- * Enable allmulti mode in most hash RX queues.\n- * TCP queues are exempted to save resources.\n- *\n- * @param priv\n- *   Private structure.\n- *\n- * @return\n- *   0 on success, errno value on failure.\n- */\n-int\n-priv_allmulticast_enable(struct priv *priv)\n-{\n-\tunsigned int i;\n-\n-\tif (!priv_allow_flow_type(priv, HASH_RXQ_FLOW_TYPE_ALLMULTI))\n-\t\treturn 0;\n-\tfor (i = 0; (i != priv->hash_rxqs_n); ++i) {\n-\t\tstruct hash_rxq *hash_rxq = &(*priv->hash_rxqs)[i];\n-\t\tint ret;\n-\n-\t\t/* allmulticast not relevant for TCP. */\n-\t\tif (hash_rxq->type == HASH_RXQ_TCPV4)\n-\t\t\tcontinue;\n-\t\tret = hash_rxq_allmulticast_enable(hash_rxq);\n-\t\tif (!ret)\n-\t\t\tcontinue;\n-\t\t/* Failure, rollback. */\n-\t\twhile (i != 0) {\n-\t\t\thash_rxq = &(*priv->hash_rxqs)[--i];\n-\t\t\thash_rxq_allmulticast_disable(hash_rxq);\n-\t\t}\n-\t\treturn ret;\n-\t}\n-\treturn 0;\n-}\n-\n-/**\n  * DPDK callback to enable allmulti mode.\n  *\n  * @param dev\n@@ -310,45 +298,14 @@ mlx5_allmulticast_enable(struct rte_eth_dev *dev)\n \n \tpriv_lock(priv);\n \tpriv->allmulti_req = 1;\n-\tret = priv_allmulticast_enable(priv);\n+\tret = priv_rehash_flows(priv);\n \tif (ret)\n-\t\tERROR(\"cannot enable allmulticast mode: %s\", strerror(ret));\n+\t\tERROR(\"error while enabling allmulticast mode: %s\",\n+\t\t      strerror(ret));\n \tpriv_unlock(priv);\n }\n \n /**\n- * Disable allmulti mode in a hash RX queue.\n- *\n- * @param hash_rxq\n- *   Pointer to hash RX queue structure.\n- */\n-static void\n-hash_rxq_allmulticast_disable(struct hash_rxq *hash_rxq)\n-{\n-\tif (hash_rxq->allmulti_flow == NULL)\n-\t\treturn;\n-\tDEBUG(\"%p: disabling allmulticast mode\", (void *)hash_rxq);\n-\tclaim_zero(ibv_exp_destroy_flow(hash_rxq->allmulti_flow));\n-\thash_rxq->allmulti_flow = NULL;\n-\tDEBUG(\"%p: allmulticast mode disabled\", (void *)hash_rxq);\n-}\n-\n-/**\n- * Disable allmulti mode in all hash RX queues.\n- *\n- * @param priv\n- *   Private structure.\n- */\n-void\n-priv_allmulticast_disable(struct priv *priv)\n-{\n-\tunsigned int i;\n-\n-\tfor (i = 0; (i != priv->hash_rxqs_n); ++i)\n-\t\thash_rxq_allmulticast_disable(&(*priv->hash_rxqs)[i]);\n-}\n-\n-/**\n  * DPDK callback to disable allmulti mode.\n  *\n  * @param dev\n@@ -358,9 +315,13 @@ void\n mlx5_allmulticast_disable(struct rte_eth_dev *dev)\n {\n \tstruct priv *priv = dev->data->dev_private;\n+\tint ret;\n \n \tpriv_lock(priv);\n \tpriv->allmulti_req = 0;\n-\tpriv_allmulticast_disable(priv);\n+\tret = priv_rehash_flows(priv);\n+\tif (ret)\n+\t\tERROR(\"error while disabling allmulticast mode: %s\",\n+\t\t      strerror(ret));\n \tpriv_unlock(priv);\n }\ndiff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c\nindex ebbe186..166516a 100644\n--- a/drivers/net/mlx5/mlx5_rxq.c\n+++ b/drivers/net/mlx5/mlx5_rxq.c\n@@ -534,8 +534,8 @@ priv_destroy_hash_rxqs(struct priv *priv)\n \t\tassert(hash_rxq->priv == priv);\n \t\tassert(hash_rxq->qp != NULL);\n \t\t/* Also check that there are no remaining flows. */\n-\t\tassert(hash_rxq->allmulti_flow == NULL);\n-\t\tassert(hash_rxq->promisc_flow == NULL);\n+\t\tfor (j = 0; (j != RTE_DIM(hash_rxq->special_flow)); ++j)\n+\t\t\tassert(hash_rxq->special_flow[j] == NULL);\n \t\tfor (j = 0; (j != RTE_DIM(hash_rxq->mac_flow)); ++j)\n \t\t\tfor (k = 0; (k != RTE_DIM(hash_rxq->mac_flow[j])); ++k)\n \t\t\t\tassert(hash_rxq->mac_flow[j][k] == NULL);\n@@ -586,6 +586,35 @@ priv_allow_flow_type(struct priv *priv, enum hash_rxq_flow_type type)\n }\n \n /**\n+ * Automatically enable/disable flows according to configuration.\n+ *\n+ * @param priv\n+ *   Private structure.\n+ *\n+ * @return\n+ *   0 on success, errno value on failure.\n+ */\n+int\n+priv_rehash_flows(struct priv *priv)\n+{\n+\tunsigned int i;\n+\n+\tfor (i = 0; (i != RTE_DIM((*priv->hash_rxqs)[0].special_flow)); ++i)\n+\t\tif (!priv_allow_flow_type(priv, i)) {\n+\t\t\tpriv_special_flow_disable(priv, i);\n+\t\t} else {\n+\t\t\tint ret = priv_special_flow_enable(priv, i);\n+\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t}\n+\tif (priv_allow_flow_type(priv, HASH_RXQ_FLOW_TYPE_MAC))\n+\t\treturn priv_mac_addrs_enable(priv);\n+\tpriv_mac_addrs_disable(priv);\n+\treturn 0;\n+}\n+\n+/**\n  * Allocate RX queue elements with scattered packets support.\n  *\n  * @param rxq\ndiff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h\nindex e1e1925..983e6a4 100644\n--- a/drivers/net/mlx5/mlx5_rxtx.h\n+++ b/drivers/net/mlx5/mlx5_rxtx.h\n@@ -176,20 +176,42 @@ struct ind_table_init {\n \tunsigned int hash_types_n;\n };\n \n+/* Initialization data for special flows. */\n+struct special_flow_init {\n+\tuint8_t dst_mac_val[6];\n+\tuint8_t dst_mac_mask[6];\n+\tunsigned int hash_types;\n+};\n+\n enum hash_rxq_flow_type {\n-\tHASH_RXQ_FLOW_TYPE_MAC,\n \tHASH_RXQ_FLOW_TYPE_PROMISC,\n \tHASH_RXQ_FLOW_TYPE_ALLMULTI,\n+\tHASH_RXQ_FLOW_TYPE_MAC,\n };\n \n+#ifndef NDEBUG\n+static inline const char *\n+hash_rxq_flow_type_str(enum hash_rxq_flow_type flow_type)\n+{\n+\tswitch (flow_type) {\n+\tcase HASH_RXQ_FLOW_TYPE_PROMISC:\n+\t\treturn \"promiscuous\";\n+\tcase HASH_RXQ_FLOW_TYPE_ALLMULTI:\n+\t\treturn \"allmulticast\";\n+\tcase HASH_RXQ_FLOW_TYPE_MAC:\n+\t\treturn \"MAC\";\n+\t}\n+\treturn NULL;\n+}\n+#endif /* NDEBUG */\n+\n struct hash_rxq {\n \tstruct priv *priv; /* Back pointer to private data. */\n \tstruct ibv_qp *qp; /* Hash RX QP. */\n \tenum hash_rxq_type type; /* Hash RX queue type. */\n \t/* MAC flow steering rules, one per VLAN ID. */\n \tstruct ibv_exp_flow *mac_flow[MLX5_MAX_MAC_ADDRESSES][MLX5_MAX_VLAN_IDS];\n-\tstruct ibv_exp_flow *promisc_flow; /* Promiscuous flow. */\n-\tstruct ibv_exp_flow *allmulti_flow; /* Multicast flow. */\n+\tstruct ibv_exp_flow *special_flow[MLX5_MAX_SPECIAL_FLOWS];\n };\n \n /* TX element. */\n@@ -247,6 +269,7 @@ size_t hash_rxq_flow_attr(const struct hash_rxq *, struct ibv_exp_flow_attr *,\n int priv_create_hash_rxqs(struct priv *);\n void priv_destroy_hash_rxqs(struct priv *);\n int priv_allow_flow_type(struct priv *, enum hash_rxq_flow_type);\n+int priv_rehash_flows(struct priv *);\n void rxq_cleanup(struct rxq *);\n int rxq_rehash(struct rte_eth_dev *, struct rxq *);\n int rxq_setup(struct rte_eth_dev *, struct rxq *, uint16_t, unsigned int,\ndiff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c\nindex ff1203d..d9f7d00 100644\n--- a/drivers/net/mlx5/mlx5_trigger.c\n+++ b/drivers/net/mlx5/mlx5_trigger.c\n@@ -72,11 +72,7 @@ mlx5_dev_start(struct rte_eth_dev *dev)\n \tDEBUG(\"%p: allocating and configuring hash RX queues\", (void *)dev);\n \terr = priv_create_hash_rxqs(priv);\n \tif (!err)\n-\t\terr = priv_promiscuous_enable(priv);\n-\tif (!err)\n-\t\terr = priv_mac_addrs_enable(priv);\n-\tif (!err)\n-\t\terr = priv_allmulticast_enable(priv);\n+\t\terr = priv_rehash_flows(priv);\n \tif (!err)\n \t\tpriv->started = 1;\n \telse {\n@@ -84,8 +80,8 @@ mlx5_dev_start(struct rte_eth_dev *dev)\n \t\t      \" %s\",\n \t\t      (void *)priv, strerror(err));\n \t\t/* Rollback. */\n-\t\tpriv_allmulticast_disable(priv);\n-\t\tpriv_promiscuous_disable(priv);\n+\t\tpriv_special_flow_disable(priv, HASH_RXQ_FLOW_TYPE_ALLMULTI);\n+\t\tpriv_special_flow_disable(priv, HASH_RXQ_FLOW_TYPE_PROMISC);\n \t\tpriv_mac_addrs_disable(priv);\n \t\tpriv_destroy_hash_rxqs(priv);\n \t}\n@@ -113,8 +109,8 @@ mlx5_dev_stop(struct rte_eth_dev *dev)\n \t\treturn;\n \t}\n \tDEBUG(\"%p: cleaning up and destroying hash RX queues\", (void *)dev);\n-\tpriv_allmulticast_disable(priv);\n-\tpriv_promiscuous_disable(priv);\n+\tpriv_special_flow_disable(priv, HASH_RXQ_FLOW_TYPE_ALLMULTI);\n+\tpriv_special_flow_disable(priv, HASH_RXQ_FLOW_TYPE_PROMISC);\n \tpriv_mac_addrs_disable(priv);\n \tpriv_destroy_hash_rxqs(priv);\n \tpriv_dev_interrupt_handler_uninstall(priv, dev);\n",
    "prefixes": [
        "dpdk-dev",
        "v2",
        "1/5"
    ]
}