get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 5235,
    "url": "http://patchwork.dpdk.org/api/1.0/patches/5235/?format=api",
    "project": {
        "id": 1,
        "url": "http://patchwork.dpdk.org/api/1.0/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"
    },
    "msgid": "<1433546120-2254-16-git-send-email-adrien.mazarguil@6wind.com>",
    "date": "2015-06-05T23:15:19",
    "name": "[dpdk-dev,15/16] mlx4: fix support for multiple VLAN filters",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "40c503924317853b6ac1a4c6d90c650a33c39df9",
    "submitter": {
        "id": 165,
        "url": "http://patchwork.dpdk.org/api/1.0/people/165/?format=api",
        "name": "Adrien Mazarguil",
        "email": "adrien.mazarguil@6wind.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/1433546120-2254-16-git-send-email-adrien.mazarguil@6wind.com/mbox/",
    "series": [],
    "check": "pending",
    "checks": "http://patchwork.dpdk.org/api/patches/5235/checks/",
    "tags": {},
    "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 DDD1AC430;\n\tSat,  6 Jun 2015 01:16:29 +0200 (CEST)",
            "from mail-wi0-f169.google.com (mail-wi0-f169.google.com\n\t[209.85.212.169]) by dpdk.org (Postfix) with ESMTP id E49DDC40A\n\tfor <dev@dpdk.org>; Sat,  6 Jun 2015 01:16:28 +0200 (CEST)",
            "by wibut5 with SMTP id ut5so34659357wib.1\n\tfor <dev@dpdk.org>; Fri, 05 Jun 2015 16:16:28 -0700 (PDT)",
            "from 6wind.com (guy78-3-82-239-227-177.fbx.proxad.net.\n\t[82.239.227.177]) by mx.google.com with ESMTPSA id\n\td3sm3992011wjs.21.2015.06.05.16.16.27\n\t(version=TLSv1.2 cipher=RC4-SHA bits=128/128);\n\tFri, 05 Jun 2015 16:16:28 -0700 (PDT)"
        ],
        "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=JcBynnduIm7zt2tH+4byh+BSUw4fr1pCCVgIDhjchMI=;\n\tb=dK2S3LtQTr6MBJsJvok9g3sz6YEBeZe4VALpSKlsVauEjHInJAM4yHB6vY+VcR3S4N\n\tVAm2wYkgg225SNn2MFlpcmv+2D7Od5sbd+hIMnk+pGr9PEqF3PcfBgf4F1VWwSiCro/G\n\tu8KZmcMJDq8ZnYhOmM8Q6erSYt4RHfhPTVgYU/fvUJ+VXROSV6FpVCK0WA3EwjVuvkjS\n\tfwOVljA3m+p2G/nUbXSaOvaUa6mFUMZ4phAJPuzSO6qzsts/9OwbStXv1ODbOLnLDY4o\n\tZrm5uEu1Hwrrex55jaF8fWGpSc8q6/MVhm/A3a/9bj2nBnVTPYFanPbuHrBQtUr3a0+H\n\tLvYg==",
        "X-Gm-Message-State": "ALoCoQn9HjViq/ZwVs4JTIHgWPX6UqrL7RKbHkGLSy0cxLrysZEEuQ8MBsB2+qJlBV7zJ0/UYGzU",
        "X-Received": "by 10.194.176.201 with SMTP id\n\tck9mr10405361wjc.108.1433546188831; \n\tFri, 05 Jun 2015 16:16:28 -0700 (PDT)",
        "From": "Adrien Mazarguil <adrien.mazarguil@6wind.com>",
        "To": "dev@dpdk.org",
        "Date": "Sat,  6 Jun 2015 01:15:19 +0200",
        "Message-Id": "<1433546120-2254-16-git-send-email-adrien.mazarguil@6wind.com>",
        "X-Mailer": "git-send-email 2.1.0",
        "In-Reply-To": "<1433546120-2254-1-git-send-email-adrien.mazarguil@6wind.com>",
        "References": "<1433546120-2254-1-git-send-email-adrien.mazarguil@6wind.com>",
        "Subject": "[dpdk-dev] [PATCH 15/16] mlx4: fix support for multiple VLAN filters",
        "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: Olga Shern <olgas@mellanox.com>\n\nThis commit fixes the \"Multiple RX VLAN filters can be configured, but only\nthe first one works\" bug. Since a single flow specification cannot contain\nseveral VLAN definitions, the flows table is extended with MLX4_MAX_VLAN_IDS\npossible specifications per configured MAC address.\n\nSigned-off-by: Olga Shern <olgas@mellanox.com>\nSigned-off-by: Or Ami <ora@mellanox.com>\nSigned-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>\n---\n drivers/net/mlx4/mlx4.c | 174 ++++++++++++++++++++++++++++++++----------------\n 1 file changed, 115 insertions(+), 59 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c\nindex 4c0294a..4c4f693 100644\n--- a/drivers/net/mlx4/mlx4.c\n+++ b/drivers/net/mlx4/mlx4.c\n@@ -33,8 +33,6 @@\n \n /*\n  * Known limitations:\n- * - Multiple RX VLAN filters can be configured, but only the first one\n- *   works properly.\n  * - RSS hash key and options cannot be modified.\n  * - Hardware counters aren't implemented.\n  */\n@@ -227,11 +225,10 @@ struct rxq {\n \t/* Faster callbacks that bypass Verbs. */\n \tdrv_exp_poll_cq_func ibv_exp_poll_cq;\n \t/*\n-\t * There is exactly one flow configured per MAC address. Each flow\n-\t * may contain several specifications, one per configured VLAN ID.\n+\t * Each VLAN ID requires a separate flow steering rule.\n \t */\n \tBITFIELD_DECLARE(mac_configured, uint32_t, MLX4_MAX_MAC_ADDRESSES);\n-\tstruct mlx_flow *mac_flow[MLX4_MAX_MAC_ADDRESSES];\n+\tstruct mlx_flow *mac_flow[MLX4_MAX_MAC_ADDRESSES][MLX4_MAX_VLAN_IDS];\n \tstruct mlx_flow *promisc_flow; /* Promiscuous flow. */\n \tstruct mlx_flow *allmulti_flow; /* Multicast flow. */\n \tunsigned int port_id; /* Port ID for incoming packets. */\n@@ -1880,15 +1877,17 @@ rxq_free_elts(struct rxq *rxq)\n }\n \n /**\n- * Unregister a MAC address from a RX queue.\n+ * Delete flow steering rule.\n  *\n  * @param rxq\n  *   Pointer to RX queue structure.\n  * @param mac_index\n  *   MAC address index.\n+ * @param vlan_index\n+ *   VLAN index.\n  */\n static void\n-rxq_mac_addr_del(struct rxq *rxq, unsigned int mac_index)\n+rxq_del_flow(struct rxq *rxq, unsigned int mac_index, unsigned int vlan_index)\n {\n #ifndef NDEBUG\n \tstruct priv *priv = rxq->priv;\n@@ -1896,20 +1895,43 @@ rxq_mac_addr_del(struct rxq *rxq, unsigned int mac_index)\n \t\t(const uint8_t (*)[ETHER_ADDR_LEN])\n \t\tpriv->mac[mac_index].addr_bytes;\n #endif\n+\tassert(rxq->mac_flow[mac_index][vlan_index] != NULL);\n+\tDEBUG(\"%p: removing MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u\"\n+\t      \" (VLAN ID %\" PRIu16 \")\",\n+\t      (void *)rxq,\n+\t      (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],\n+\t      mac_index, priv->vlan_filter[vlan_index].id);\n+\tclaim_zero(mlx_destroy_flow(rxq->mac_flow[mac_index][vlan_index]));\n+\trxq->mac_flow[mac_index][vlan_index] = NULL;\n+}\n+\n+/**\n+ * Unregister a MAC address from a RX queue.\n+ *\n+ * @param rxq\n+ *   Pointer to RX queue structure.\n+ * @param mac_index\n+ *   MAC address index.\n+ */\n+static void\n+rxq_mac_addr_del(struct rxq *rxq, unsigned int mac_index)\n+{\n+\tstruct priv *priv = rxq->priv;\n+\tunsigned int i;\n+\tunsigned int vlans = 0;\n \n \tassert(mac_index < elemof(priv->mac));\n-\tif (!BITFIELD_ISSET(rxq->mac_configured, mac_index)) {\n-\t\tassert(rxq->mac_flow[mac_index] == NULL);\n+\tif (!BITFIELD_ISSET(rxq->mac_configured, mac_index))\n \t\treturn;\n+\tfor (i = 0; (i != elemof(priv->vlan_filter)); ++i) {\n+\t\tif (!priv->vlan_filter[i].enabled)\n+\t\t\tcontinue;\n+\t\trxq_del_flow(rxq, mac_index, i);\n+\t\tvlans++;\n+\t}\n+\tif (!vlans) {\n+\t\trxq_del_flow(rxq, mac_index, 0);\n \t}\n-\tDEBUG(\"%p: removing MAC address %02x:%02x:%02x:%02x:%02x:%02x\"\n-\t      \" index %u\",\n-\t      (void *)rxq,\n-\t      (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],\n-\t      mac_index);\n-\tassert(rxq->mac_flow[mac_index] != NULL);\n-\tclaim_zero(mlx_destroy_flow(rxq->mac_flow[mac_index]));\n-\trxq->mac_flow[mac_index] = NULL;\n \tBITFIELD_RESET(rxq->mac_configured, mac_index);\n }\n \n@@ -1933,47 +1955,37 @@ static int rxq_promiscuous_enable(struct rxq *);\n static void rxq_promiscuous_disable(struct rxq *);\n \n /**\n- * Register a MAC address in a RX queue.\n+ * Add single flow steering rule.\n  *\n  * @param rxq\n  *   Pointer to RX queue structure.\n  * @param mac_index\n  *   MAC address index to register.\n+ * @param vlan_index\n+ *   VLAN index. Use -1 for a flow without VLAN.\n  *\n  * @return\n  *   0 on success, errno value on failure.\n  */\n static int\n-rxq_mac_addr_add(struct rxq *rxq, unsigned int mac_index)\n+rxq_add_flow(struct rxq *rxq, unsigned int mac_index, unsigned int vlan_index)\n {\n+\tstruct mlx_flow *flow;\n \tstruct priv *priv = rxq->priv;\n \tconst uint8_t (*mac)[ETHER_ADDR_LEN] =\n-\t\t(const uint8_t (*)[ETHER_ADDR_LEN])\n-\t\tpriv->mac[mac_index].addr_bytes;\n-\tunsigned int vlans = 0;\n-\tunsigned int specs = 0;\n-\tunsigned int i, j;\n-\tstruct mlx_flow *flow;\n-\n-\tassert(mac_index < elemof(priv->mac));\n-\tif (BITFIELD_ISSET(rxq->mac_configured, mac_index))\n-\t\trxq_mac_addr_del(rxq, mac_index);\n-\t/* Number of configured VLANs. */\n-\tfor (i = 0; (i != elemof(priv->vlan_filter)); ++i)\n-\t\tif (priv->vlan_filter[i].enabled)\n-\t\t\t++vlans;\n-\tspecs = (vlans ? vlans : 1);\n+\t\t\t(const uint8_t (*)[ETHER_ADDR_LEN])\n+\t\t\tpriv->mac[mac_index].addr_bytes;\n \n \t/* Allocate flow specification on the stack. */\n-\tstruct mlx_flow_attr data\n-\t\t[1 +\n-\t\t (sizeof(struct mlx_flow_spec_eth[specs]) /\n-\t\t  sizeof(struct mlx_flow_attr)) +\n-\t\t !!(sizeof(struct mlx_flow_spec_eth[specs]) %\n-\t\t    sizeof(struct mlx_flow_attr))];\n-\tstruct mlx_flow_attr *attr = (void *)&data[0];\n-\tstruct mlx_flow_spec_eth *spec = (void *)&data[1];\n+\tstruct __attribute__((packed)) {\n+\t\tstruct mlx_flow_attr attr;\n+\t\tstruct mlx_flow_spec_eth spec;\n+\t} data;\n+\tstruct mlx_flow_attr *attr = &data.attr;\n+\tstruct mlx_flow_spec_eth *spec = &data.spec;\n \n+\tassert(mac_index < elemof(priv->mac));\n+\tassert((vlan_index < elemof(priv->vlan_filter)) || (vlan_index == -1u));\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@@ -1981,7 +1993,7 @@ rxq_mac_addr_add(struct rxq *rxq, unsigned int mac_index)\n \tassert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec);\n \t*attr = (struct mlx_flow_attr) {\n \t\t.type = MLX_FLOW_ATTR_NORMAL,\n-\t\t.num_of_specs = specs,\n+\t\t.num_of_specs = 1,\n \t\t.port = priv->port,\n \t\t.flags = 0\n \t};\n@@ -1992,29 +2004,23 @@ rxq_mac_addr_add(struct rxq *rxq, unsigned int mac_index)\n \t\t\t.dst_mac = {\n \t\t\t\t(*mac)[0], (*mac)[1], (*mac)[2],\n \t\t\t\t(*mac)[3], (*mac)[4], (*mac)[5]\n-\t\t\t}\n+\t\t\t},\n+\t\t\t.vlan_tag = ((vlan_index != -1u) ?\n+\t\t\t\t     htons(priv->vlan_filter[vlan_index].id) :\n+\t\t\t\t     0),\n \t\t},\n \t\t.mask = {\n \t\t\t.dst_mac = \"\\xff\\xff\\xff\\xff\\xff\\xff\",\n-\t\t\t.vlan_tag = (vlans ? htons(0xfff) : 0)\n+\t\t\t.vlan_tag = ((vlan_index != -1u) ? htons(0xfff) : 0),\n \t\t}\n \t};\n-\t/* Fill VLAN specifications. */\n-\tfor (i = 0, j = 0; (i != elemof(priv->vlan_filter)); ++i) {\n-\t\tif (!priv->vlan_filter[i].enabled)\n-\t\t\tcontinue;\n-\t\tassert(j != vlans);\n-\t\tif (j)\n-\t\t\tspec[j] = spec[0];\n-\t\tspec[j].val.vlan_tag = htons(priv->vlan_filter[i].id);\n-\t\t++j;\n-\t}\n \tDEBUG(\"%p: adding MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u\"\n-\t      \" (%u VLAN(s) configured)\",\n+\t      \" (VLAN %s %\" PRIu16 \")\",\n \t      (void *)rxq,\n \t      (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],\n \t      mac_index,\n-\t      vlans);\n+\t      ((vlan_index != -1u) ? \"ID\" : \"index\"),\n+\t      ((vlan_index != -1u) ? priv->vlan_filter[vlan_index].id : -1u));\n \t/* Create related flow. */\n \terrno = 0;\n \tflow = mlx_create_flow(rxq->qp, attr);\n@@ -2027,8 +2033,58 @@ rxq_mac_addr_add(struct rxq *rxq, unsigned int mac_index)\n \t\t\treturn errno;\n \t\treturn EINVAL;\n \t}\n-\tassert(rxq->mac_flow[mac_index] == NULL);\n-\trxq->mac_flow[mac_index] = flow;\n+\tif (vlan_index == -1u)\n+\t\tvlan_index = 0;\n+\tassert(rxq->mac_flow[mac_index][vlan_index] == NULL);\n+\trxq->mac_flow[mac_index][vlan_index] = flow;\n+\treturn 0;\n+}\n+\n+/**\n+ * Register a MAC address in a RX queue.\n+ *\n+ * @param rxq\n+ *   Pointer to RX queue structure.\n+ * @param mac_index\n+ *   MAC address index to register.\n+ *\n+ * @return\n+ *   0 on success, errno value on failure.\n+ */\n+static int\n+rxq_mac_addr_add(struct rxq *rxq, unsigned int mac_index)\n+{\n+\tstruct priv *priv = rxq->priv;\n+\tunsigned int i;\n+\tunsigned int vlans = 0;\n+\tint ret;\n+\n+\tassert(mac_index < elemof(priv->mac));\n+\tif (BITFIELD_ISSET(rxq->mac_configured, mac_index))\n+\t\trxq_mac_addr_del(rxq, mac_index);\n+\t/* Fill VLAN specifications. */\n+\tfor (i = 0; (i != elemof(priv->vlan_filter)); ++i) {\n+\t\tif (!priv->vlan_filter[i].enabled)\n+\t\t\tcontinue;\n+\t\t/* Create related flow. */\n+\t\tret = rxq_add_flow(rxq, mac_index, i);\n+\t\tif (!ret) {\n+\t\t\tvlans++;\n+\t\t\tcontinue;\n+\t\t}\n+\t\t/* Failure, rollback. */\n+\t\twhile (i != 0)\n+\t\t\tif (priv->vlan_filter[--i].enabled)\n+\t\t\t\trxq_del_flow(rxq, mac_index, i);\n+\t\tassert(ret > 0);\n+\t\treturn ret;\n+\t}\n+\t/* In case there is no VLAN filter. */\n+\tif (!vlans) {\n+\t\tret = rxq_add_flow(rxq, mac_index, -1);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n \tBITFIELD_SET(rxq->mac_configured, mac_index);\n \treturn 0;\n }\n",
    "prefixes": [
        "dpdk-dev",
        "15/16"
    ]
}