Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/810962/?format=api
{ "id": 810962, "url": "http://patchwork.ozlabs.org/api/patches/810962/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/150478200636.24662.17572491925361676670.stgit@anamdev.jf.intel.com/", "project": { "id": 46, "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api", "name": "Intel Wired Ethernet development", "link_name": "intel-wired-lan", "list_id": "intel-wired-lan.osuosl.org", "list_email": "intel-wired-lan@osuosl.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<150478200636.24662.17572491925361676670.stgit@anamdev.jf.intel.com>", "list_archive_url": null, "date": "2017-09-07T11:00:06", "name": "[RFC,v3,1/6] mqprio: Introduce new hardware offload mode and shaper in mqprio", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "f1f58040bc66162ebf7fbc0e5cc2d020fea8edb4", "submitter": { "id": 68504, "url": "http://patchwork.ozlabs.org/api/people/68504/?format=api", "name": "Nambiar, Amritha", "email": "amritha.nambiar@intel.com" }, "delegate": { "id": 68, "url": "http://patchwork.ozlabs.org/api/users/68/?format=api", "username": "jtkirshe", "first_name": "Jeff", "last_name": "Kirsher", "email": "jeffrey.t.kirsher@intel.com" }, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/150478200636.24662.17572491925361676670.stgit@anamdev.jf.intel.com/mbox/", "series": [ { "id": 1979, "url": "http://patchwork.ozlabs.org/api/series/1979/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=1979", "date": "2017-09-07T11:00:01", "name": "Configuring traffic classes via new hardware offload mechanism in tc/mqprio", "version": 3, "mbox": "http://patchwork.ozlabs.org/series/1979/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/810962/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/810962/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@osuosl.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Authentication-Results": "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=osuosl.org\n\t(client-ip=140.211.166.133; helo=hemlock.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)", "Received": [ "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xnyDv3qBpz9s7C\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 7 Sep 2017 21:01:19 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id BA30489A61;\n\tThu, 7 Sep 2017 11:01:17 +0000 (UTC)", "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id atchGGbYVC3j; Thu, 7 Sep 2017 11:01:15 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 9A15289612;\n\tThu, 7 Sep 2017 11:01:15 +0000 (UTC)", "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\tby ash.osuosl.org (Postfix) with ESMTP id EE78F1C2121\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 7 Sep 2017 11:01:13 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id E6FF82F807\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 7 Sep 2017 11:01:13 +0000 (UTC)", "from silver.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id qLDue7ztMLdZ for <intel-wired-lan@lists.osuosl.org>;\n\tThu, 7 Sep 2017 11:01:12 +0000 (UTC)", "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n\tby silver.osuosl.org (Postfix) with ESMTPS id 7AE14239B5\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 7 Sep 2017 11:01:12 +0000 (UTC)", "from fmsmga002.fm.intel.com ([10.253.24.26])\n\tby fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t07 Sep 2017 04:01:11 -0700", "from anamdev.jf.intel.com ([10.166.29.110])\n\tby fmsmga002.fm.intel.com with ESMTP; 07 Sep 2017 04:01:10 -0700" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6", "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos; i=\"5.42,357,1500966000\"; d=\"scan'208\";\n\ta=\"1215872677\"", "From": "Amritha Nambiar <amritha.nambiar@intel.com>", "To": "intel-wired-lan@lists.osuosl.org, jeffrey.t.kirsher@intel.com", "Date": "Thu, 07 Sep 2017 04:00:06 -0700", "Message-ID": "<150478200636.24662.17572491925361676670.stgit@anamdev.jf.intel.com>", "In-Reply-To": "<150478158684.24662.17975701233699487888.stgit@anamdev.jf.intel.com>", "References": "<150478158684.24662.17975701233699487888.stgit@anamdev.jf.intel.com>", "User-Agent": "StGit/0.17.1-dirty", "MIME-Version": "1.0", "Cc": "netdev@vger.kernel.org", "Subject": "[Intel-wired-lan] [RFC PATCH v3 1/6] mqprio: Introduce new hardware\n\toffload mode and shaper in mqprio", "X-BeenThere": "intel-wired-lan@osuosl.org", "X-Mailman-Version": "2.1.18-1", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.osuosl.org>", "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>", "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "intel-wired-lan-bounces@osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>" }, "content": "The offload types currently supported in mqprio are 0 (no offload) and\n1 (offload only TCs) by setting these values for the 'hw' option. If\noffloads are supported by setting the 'hw' option to 1, the default\noffload mode is 'dcb' where only the TC values are offloaded to the\ndevice. This patch introduces a new hardware offload mode called\n'channel' with 'hw' set to 1 in mqprio which makes full use of the\nmqprio options, the TCs, the queue configurations and the QoS parameters\nfor the TCs. This is achieved through a new netlink attribute for the\n'mode' option which takes values such as 'dcb' (default) and 'channel'.\nThe 'channel' mode also supports QoS attributes for traffic class such as\nminimum and maximum values for bandwidth rate limits.\n\nThis patch enables configuring additional HW shaper attributes associated\nwith a traffic class. Currently the shaper for bandwidth rate limiting is\nsupported which takes options such as minimum and maximum bandwidth rates\nand are offloaded to the hardware in the 'channel' mode. The min and max\nlimits for bandwidth rates are provided by the user along with the the TCs\nand the queue configurations when creating the mqprio qdisc. The interface\ncan be extended to support new HW shapers in future through the 'shaper'\nattribute.\n\nIntroduces a new datastructure 'tc_mqprio_qopt_offload' for offloading\nmqprio queue options and use this to be shared between the kernel and\ndevice driver. This contains a copy of the exisiting datastructure\nfor mqprio queue options. This new datastructure can be extended when\nadding new attributes for traffic class such as mode, shaper, shaper\nparameters (bandwidth rate limits). The existing datastructure for mqprio\nqueue options will be shared between the kernel and userspace.\n\nExample:\n# tc qdisc add dev eth0 root mqprio num_tc 2 map 0 0 0 0 1 1 1 1\\\n queues 4@0 4@4 hw 1 mode channel shaper bw_rlimit\\\n min_rate 1Gbit 2Gbit max_rate 4Gbit 5Gbit\n\nTo dump the bandwidth rates:\n\n# tc qdisc show dev eth0\n\nqdisc mqprio 804a: root tc 2 map 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0\n queues:(0:3) (4:7)\n mode:channel\n shaper:bw_rlimit min_rate:1Gbit 2Gbit max_rate:4Gbit 5Gbit\n\nv3 : Removed supporting new offloads through value 2 for 'hw' option,\nintroduced new netlink based options for offload mode and HW shaper.\nv2 : Jiri's changes accepted upstream removes the struct\ntc_to_netdev. Clean up the full offload related changes added to\nmqprio_init() and mqprio_destroy() to rebase on these changes.\n\nSigned-off-by: Amritha Nambiar <amritha.nambiar@intel.com>\n---\n include/net/pkt_cls.h | 9 ++\n include/uapi/linux/pkt_sched.h | 32 +++++++\n net/sched/sch_mqprio.c | 183 ++++++++++++++++++++++++++++++++++++++--\n 3 files changed, 215 insertions(+), 9 deletions(-)", "diff": "diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h\nindex e80edd8..456017a 100644\n--- a/include/net/pkt_cls.h\n+++ b/include/net/pkt_cls.h\n@@ -546,6 +546,15 @@ struct tc_cls_bpf_offload {\n \tu32 gen_flags;\n };\n \n+struct tc_mqprio_qopt_offload {\n+\t/* struct tc_mqprio_qopt must always be the first element */\n+\tstruct tc_mqprio_qopt qopt;\n+\tu16 mode;\n+\tu16 shaper;\n+\tu32 flags;\n+\tu64 min_rate[TC_QOPT_MAX_QUEUE];\n+\tu64 max_rate[TC_QOPT_MAX_QUEUE];\n+};\n \n /* This structure holds cookie structure that is passed from user\n * to the kernel for actions and classifiers\ndiff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h\nindex 099bf55..e95b5c9 100644\n--- a/include/uapi/linux/pkt_sched.h\n+++ b/include/uapi/linux/pkt_sched.h\n@@ -625,6 +625,22 @@ enum {\n \n #define TC_MQPRIO_HW_OFFLOAD_MAX (__TC_MQPRIO_HW_OFFLOAD_MAX - 1)\n \n+enum {\n+\tTC_MQPRIO_MODE_DCB,\n+\tTC_MQPRIO_MODE_CHANNEL,\n+\t__TC_MQPRIO_MODE_MAX\n+};\n+\n+#define __TC_MQPRIO_MODE_MAX (__TC_MQPRIO_MODE_MAX - 1)\n+\n+enum {\n+\tTC_MQPRIO_SHAPER_DCB,\n+\tTC_MQPRIO_SHAPER_BW_RATE,\t/* Add new shapers below */\n+\t__TC_MQPRIO_SHAPER_MAX\n+};\n+\n+#define __TC_MQPRIO_SHAPER_MAX (__TC_MQPRIO_SHAPER_MAX - 1)\n+\n struct tc_mqprio_qopt {\n \t__u8\tnum_tc;\n \t__u8\tprio_tc_map[TC_QOPT_BITMASK + 1];\n@@ -633,6 +649,22 @@ struct tc_mqprio_qopt {\n \t__u16\toffset[TC_QOPT_MAX_QUEUE];\n };\n \n+#define TC_MQPRIO_F_MODE\t\t0x1\n+#define TC_MQPRIO_F_SHAPER\t\t0x2\n+#define TC_MQPRIO_F_MIN_RATE\t\t0x4\n+#define TC_MQPRIO_F_MAX_RATE\t\t0x8\n+\n+enum {\n+\tTCA_MQPRIO_UNSPEC,\n+\tTCA_MQPRIO_MODE,\n+\tTCA_MQPRIO_SHAPER,\n+\tTCA_MQPRIO_MIN_RATE64,\n+\tTCA_MQPRIO_MAX_RATE64,\n+\t__TCA_MQPRIO_MAX,\n+};\n+\n+#define TCA_MQPRIO_MAX (__TCA_MQPRIO_MAX - 1)\n+\n /* SFB */\n \n enum {\ndiff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c\nindex 6bcdfe6..e5e7724 100644\n--- a/net/sched/sch_mqprio.c\n+++ b/net/sched/sch_mqprio.c\n@@ -18,10 +18,16 @@\n #include <net/netlink.h>\n #include <net/pkt_sched.h>\n #include <net/sch_generic.h>\n+#include <net/pkt_cls.h>\n \n struct mqprio_sched {\n \tstruct Qdisc\t\t**qdiscs;\n+\tu16 mode;\n+\tu16 shaper;\n \tint hw_offload;\n+\tu32 flags;\n+\tu64 min_rate[TC_QOPT_MAX_QUEUE];\n+\tu64 max_rate[TC_QOPT_MAX_QUEUE];\n };\n \n static void mqprio_destroy(struct Qdisc *sch)\n@@ -39,9 +45,17 @@ static void mqprio_destroy(struct Qdisc *sch)\n \t}\n \n \tif (priv->hw_offload && dev->netdev_ops->ndo_setup_tc) {\n-\t\tstruct tc_mqprio_qopt mqprio = {};\n+\t\tstruct tc_mqprio_qopt_offload mqprio = { { 0 } };\n \n-\t\tdev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_MQPRIO, &mqprio);\n+\t\tswitch (priv->mode) {\n+\t\tcase TC_MQPRIO_MODE_DCB:\n+\t\tcase TC_MQPRIO_MODE_CHANNEL:\n+\t\t\tdev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_MQPRIO,\n+\t\t\t\t\t\t &mqprio);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn;\n+\t\t}\n \t} else {\n \t\tnetdev_set_num_tc(dev, 0);\n \t}\n@@ -97,6 +111,26 @@ static int mqprio_parse_opt(struct net_device *dev, struct tc_mqprio_qopt *qopt)\n \treturn 0;\n }\n \n+static const struct nla_policy mqprio_policy[TCA_MQPRIO_MAX + 1] = {\n+\t[TCA_MQPRIO_MODE]\t= { .len = sizeof(u16) },\n+\t[TCA_MQPRIO_SHAPER]\t= { .len = sizeof(u16) },\n+\t[TCA_MQPRIO_MIN_RATE64] = { .type = NLA_NESTED },\n+\t[TCA_MQPRIO_MAX_RATE64] = { .type = NLA_NESTED },\n+};\n+\n+static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,\n+\t\t const struct nla_policy *policy, int len)\n+{\n+\tint nested_len = nla_len(nla) - NLA_ALIGN(len);\n+\n+\tif (nested_len >= nla_attr_size(0))\n+\t\treturn nla_parse(tb, maxtype, nla_data(nla) + NLA_ALIGN(len),\n+\t\t\t\t nested_len, policy, NULL);\n+\n+\tmemset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));\n+\treturn 0;\n+}\n+\n static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)\n {\n \tstruct net_device *dev = qdisc_dev(sch);\n@@ -105,6 +139,10 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)\n \tstruct Qdisc *qdisc;\n \tint i, err = -EOPNOTSUPP;\n \tstruct tc_mqprio_qopt *qopt = NULL;\n+\tstruct nlattr *tb[TCA_MQPRIO_MAX + 1];\n+\tstruct nlattr *attr;\n+\tint rem;\n+\tint len = nla_len(opt) - NLA_ALIGN(sizeof(*qopt));\n \n \tBUILD_BUG_ON(TC_MAX_QUEUE != TC_QOPT_MAX_QUEUE);\n \tBUILD_BUG_ON(TC_BITMASK != TC_QOPT_BITMASK);\n@@ -122,6 +160,58 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)\n \tif (mqprio_parse_opt(dev, qopt))\n \t\treturn -EINVAL;\n \n+\tif (len > 0) {\n+\t\terr = parse_attr(tb, TCA_MQPRIO_MAX, opt, mqprio_policy,\n+\t\t\t\t sizeof(*qopt));\n+\t\tif (err < 0)\n+\t\t\treturn err;\n+\n+\t\tif (!qopt->hw)\n+\t\t\treturn -EINVAL;\n+\n+\t\tif (tb[TCA_MQPRIO_MODE]) {\n+\t\t\tpriv->flags |= TC_MQPRIO_F_MODE;\n+\t\t\tpriv->mode = *(u16 *)nla_data(tb[TCA_MQPRIO_MODE]);\n+\t\t}\n+\n+\t\tif (tb[TCA_MQPRIO_SHAPER]) {\n+\t\t\tpriv->flags |= TC_MQPRIO_F_SHAPER;\n+\t\t\tpriv->shaper = *(u16 *)nla_data(tb[TCA_MQPRIO_SHAPER]);\n+\t\t}\n+\n+\t\tif (tb[TCA_MQPRIO_MIN_RATE64]) {\n+\t\t\tif (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE)\n+\t\t\t\treturn -EINVAL;\n+\t\t\ti = 0;\n+\t\t\tnla_for_each_nested(attr, tb[TCA_MQPRIO_MIN_RATE64],\n+\t\t\t\t\t rem) {\n+\t\t\t\tif (nla_type(attr) != TCA_MQPRIO_MIN_RATE64)\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\tif (i >= qopt->num_tc)\n+\t\t\t\t\tbreak;\n+\t\t\t\tpriv->min_rate[i] = *(u64 *)nla_data(attr);\n+\t\t\t\ti++;\n+\t\t\t}\n+\t\t\tpriv->flags |= TC_MQPRIO_F_MIN_RATE;\n+\t\t}\n+\n+\t\tif (tb[TCA_MQPRIO_MAX_RATE64]) {\n+\t\t\tif (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE)\n+\t\t\t\treturn -EINVAL;\n+\t\t\ti = 0;\n+\t\t\tnla_for_each_nested(attr, tb[TCA_MQPRIO_MAX_RATE64],\n+\t\t\t\t\t rem) {\n+\t\t\t\tif (nla_type(attr) != TCA_MQPRIO_MAX_RATE64)\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\tif (i >= qopt->num_tc)\n+\t\t\t\t\tbreak;\n+\t\t\t\tpriv->max_rate[i] = *(u64 *)nla_data(attr);\n+\t\t\t\ti++;\n+\t\t\t}\n+\t\t\tpriv->flags |= TC_MQPRIO_F_MAX_RATE;\n+\t\t}\n+\t}\n+\n \t/* pre-allocate qdisc, attachment can't fail */\n \tpriv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]),\n \t\t\t GFP_KERNEL);\n@@ -146,14 +236,36 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)\n \t * supplied and verified mapping\n \t */\n \tif (qopt->hw) {\n-\t\tstruct tc_mqprio_qopt mqprio = *qopt;\n+\t\tstruct tc_mqprio_qopt_offload mqprio = {.qopt = *qopt};\n \n-\t\terr = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_MQPRIO,\n+\t\tswitch (priv->mode) {\n+\t\tcase TC_MQPRIO_MODE_DCB:\n+\t\t\tif (priv->shaper != TC_MQPRIO_SHAPER_DCB)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tbreak;\n+\t\tcase TC_MQPRIO_MODE_CHANNEL:\n+\t\t\tmqprio.flags = priv->flags;\n+\t\t\tif (priv->flags & TC_MQPRIO_F_MODE)\n+\t\t\t\tmqprio.mode = priv->mode;\n+\t\t\tif (priv->flags & TC_MQPRIO_F_SHAPER)\n+\t\t\t\tmqprio.shaper = priv->shaper;\n+\t\t\tif (priv->flags & TC_MQPRIO_F_MIN_RATE)\n+\t\t\t\tfor (i = 0; i < mqprio.qopt.num_tc; i++)\n+\t\t\t\t\tmqprio.min_rate[i] = priv->min_rate[i];\n+\t\t\tif (priv->flags & TC_MQPRIO_F_MAX_RATE)\n+\t\t\t\tfor (i = 0; i < mqprio.qopt.num_tc; i++)\n+\t\t\t\t\tmqprio.max_rate[i] = priv->max_rate[i];\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\terr = dev->netdev_ops->ndo_setup_tc(dev,\n+\t\t\t\t\t\t TC_SETUP_MQPRIO,\n \t\t\t\t\t\t &mqprio);\n \t\tif (err)\n \t\t\treturn err;\n \n-\t\tpriv->hw_offload = mqprio.hw;\n+\t\tpriv->hw_offload = mqprio.qopt.hw;\n \t} else {\n \t\tnetdev_set_num_tc(dev, qopt->num_tc);\n \t\tfor (i = 0; i < qopt->num_tc; i++)\n@@ -223,11 +335,51 @@ static int mqprio_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new,\n \treturn 0;\n }\n \n+static int dump_rates(struct mqprio_sched *priv,\n+\t\t struct tc_mqprio_qopt *opt, struct sk_buff *skb)\n+{\n+\tstruct nlattr *nest;\n+\tint i;\n+\n+\tif (priv->flags & TC_MQPRIO_F_MIN_RATE) {\n+\t\tnest = nla_nest_start(skb, TCA_MQPRIO_MIN_RATE64);\n+\t\tif (!nest)\n+\t\t\tgoto nla_put_failure;\n+\n+\t\tfor (i = 0; i < opt->num_tc; i++) {\n+\t\t\tif (nla_put(skb, TCA_MQPRIO_MIN_RATE64,\n+\t\t\t\t sizeof(priv->min_rate[i]),\n+\t\t\t\t &priv->min_rate[i]))\n+\t\t\t\tgoto nla_put_failure;\n+\t\t}\n+\t\tnla_nest_end(skb, nest);\n+\t}\n+\n+\tif (priv->flags & TC_MQPRIO_F_MAX_RATE) {\n+\t\tnest = nla_nest_start(skb, TCA_MQPRIO_MAX_RATE64);\n+\t\tif (!nest)\n+\t\t\tgoto nla_put_failure;\n+\n+\t\tfor (i = 0; i < opt->num_tc; i++) {\n+\t\t\tif (nla_put(skb, TCA_MQPRIO_MAX_RATE64,\n+\t\t\t\t sizeof(priv->max_rate[i]),\n+\t\t\t\t &priv->max_rate[i]))\n+\t\t\t\tgoto nla_put_failure;\n+\t\t}\n+\t\tnla_nest_end(skb, nest);\n+\t}\n+\treturn 0;\n+\n+nla_put_failure:\n+\tnla_nest_cancel(skb, nest);\n+\treturn -1;\n+}\n+\n static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb)\n {\n \tstruct net_device *dev = qdisc_dev(sch);\n \tstruct mqprio_sched *priv = qdisc_priv(sch);\n-\tunsigned char *b = skb_tail_pointer(skb);\n+\tstruct nlattr *nla = (struct nlattr *)skb_tail_pointer(skb);\n \tstruct tc_mqprio_qopt opt = { 0 };\n \tstruct Qdisc *qdisc;\n \tunsigned int i;\n@@ -258,12 +410,25 @@ static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb)\n \t\topt.offset[i] = dev->tc_to_txq[i].offset;\n \t}\n \n-\tif (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt))\n+\tif (nla_put(skb, TCA_OPTIONS, NLA_ALIGN(sizeof(opt)), &opt))\n+\t\tgoto nla_put_failure;\n+\n+\tif ((priv->flags & TC_MQPRIO_F_MODE) &&\n+\t nla_put_u16(skb, TCA_MQPRIO_MODE, priv->mode))\n+\t\tgoto nla_put_failure;\n+\n+\tif ((priv->flags & TC_MQPRIO_F_SHAPER) &&\n+\t nla_put_u16(skb, TCA_MQPRIO_SHAPER, priv->shaper))\n+\t\tgoto nla_put_failure;\n+\n+\tif ((priv->flags & TC_MQPRIO_F_MIN_RATE ||\n+\t priv->flags & TC_MQPRIO_F_MAX_RATE) &&\n+\t (dump_rates(priv, &opt, skb) != 0))\n \t\tgoto nla_put_failure;\n \n-\treturn skb->len;\n+\treturn nla_nest_end(skb, nla);\n nla_put_failure:\n-\tnlmsg_trim(skb, b);\n+\tnlmsg_trim(skb, nla);\n \treturn -1;\n }\n \n", "prefixes": [ "RFC", "v3", "1/6" ] }