From patchwork Wed Sep 2 12:30:09 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Eric Dumazet X-Patchwork-Id: 32828 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@bilbo.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from ozlabs.org (ozlabs.org [203.10.76.45]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "mx.ozlabs.org", Issuer "CA Cert Signing Authority" (verified OK)) by bilbo.ozlabs.org (Postfix) with ESMTPS id 8D755B70B0 for ; Wed, 2 Sep 2009 22:30:29 +1000 (EST) Received: by ozlabs.org (Postfix) id 7DE36DDD0B; Wed, 2 Sep 2009 22:30:29 +1000 (EST) Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id 8372ADDD04 for ; Wed, 2 Sep 2009 22:30:28 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751405AbZIBMaR (ORCPT ); Wed, 2 Sep 2009 08:30:17 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751377AbZIBMaR (ORCPT ); Wed, 2 Sep 2009 08:30:17 -0400 Received: from gw1.cosmosbay.com ([212.99.114.194]:32787 "EHLO gw1.cosmosbay.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751050AbZIBMaP (ORCPT ); Wed, 2 Sep 2009 08:30:15 -0400 Received: from [127.0.0.1] (localhost [127.0.0.1]) by gw1.cosmosbay.com (8.13.7/8.13.7) with ESMTP id n82CU9UG020089; Wed, 2 Sep 2009 14:30:09 +0200 Message-ID: <4A9E6551.4030209@gmail.com> Date: Wed, 02 Sep 2009 14:30:09 +0200 From: Eric Dumazet User-Agent: Thunderbird 2.0.0.23 (Windows/20090812) MIME-Version: 1.0 To: David Miller CC: jarkao2@gmail.com, cl@linux-foundation.org, kaber@trash.net, netdev@vger.kernel.org Subject: [PATCH net-next-2.6] tc: report informations for multiqueue devices References: <20090902081429.GB4878@ff.dom.local> <4A9E2CC7.1010103@gmail.com> <20090902.013002.181288977.davem@davemloft.net> In-Reply-To: <20090902.013002.181288977.davem@davemloft.net> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-1.6 (gw1.cosmosbay.com [0.0.0.0]); Wed, 02 Sep 2009 14:30:09 +0200 (CEST) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org David Miller a écrit : > From: Eric Dumazet > Date: Wed, 02 Sep 2009 10:28:55 +0200 > >> What naming convention should we choose for multiqueue devices ? > > We could give an index field to multiple root qdiscs assigned > to a device. Here is a patch then :) Only point is that I am iterating from 0 to dev->real_num_tx_queues instead of dev->num_tx_queues. I hope it's fine, because there are allocated qdisc, but not really used. Next patches to allow selective qdisc change/fetch (providing a TCA_QINDEX selector value to kernel) Thanks [PATCH net-next-2.6] tc: report informations for multiqueue devices qdisc and classes are not yet displayed by "tc -s -d {qdisc|class} show" for multiqueue devices. We use a new TCA_QINDEX attribute, to report queue index to user space. iproute2 tc should be changed to eventually display this queue index as in : $ tc -s -d qdisc qdisc pfifo_fast 0: dev eth0 root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 Sent 52498 bytes 465 pkt (dropped 0, overlimits 0 requeues 0) rate 0bit 0pps backlog 0b 0p requeues 0 qdisc pfifo_fast 0: dev eth0 qindex 1 root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) rate 0bit 0pps backlog 0b 0p requeues 0 Signed-off-by: Eric Dumazet --- include/linux/rtnetlink.h | 1 net/sched/sch_api.c | 118 ++++++++++++++++++++---------------- 2 files changed, 67 insertions(+), 52 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index ba3254e..b80e0f6 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -490,6 +490,7 @@ enum TCA_FCNT, TCA_STATS2, TCA_STAB, + TCA_QINDEX, __TCA_MAX }; diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 24d17ce..74cde83 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -35,9 +35,9 @@ #include static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid, - struct Qdisc *old, struct Qdisc *new); + struct Qdisc *old, struct Qdisc *new, int qnum); static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, - struct Qdisc *q, unsigned long cl, int event); + struct Qdisc *q, unsigned long cl, int event, int qnum); /* @@ -671,10 +671,10 @@ void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) EXPORT_SYMBOL(qdisc_tree_decrease_qlen); static void notify_and_destroy(struct sk_buff *skb, struct nlmsghdr *n, u32 clid, - struct Qdisc *old, struct Qdisc *new) + struct Qdisc *old, struct Qdisc *new, int qnum) { if (new || old) - qdisc_notify(skb, n, clid, old, new); + qdisc_notify(skb, n, clid, old, new, qnum); if (old) qdisc_destroy(old); @@ -720,7 +720,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, if (new && i > 0) atomic_inc(&new->refcnt); - notify_and_destroy(skb, n, classid, old, new); + notify_and_destroy(skb, n, classid, old, new, i); } if (dev->flags & IFF_UP) @@ -738,7 +738,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, } } if (!err) - notify_and_destroy(skb, n, classid, old, new); + notify_and_destroy(skb, n, classid, old, new, 0); } return err; } @@ -999,7 +999,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) if ((err = qdisc_graft(dev, p, skb, n, clid, NULL, q)) != 0) return err; } else { - qdisc_notify(skb, n, clid, NULL, q); + qdisc_notify(skb, n, clid, NULL, q, 0); } return 0; } @@ -1116,7 +1116,7 @@ replay: return -EINVAL; err = qdisc_change(q, tca); if (err == 0) - qdisc_notify(skb, n, clid, NULL, q); + qdisc_notify(skb, n, clid, NULL, q, 0); return err; create_n_graft: @@ -1148,7 +1148,7 @@ graft: } static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, - u32 pid, u32 seq, u16 flags, int event) + u32 pid, u32 seq, u16 flags, int event, int qnum) { struct tcmsg *tcm; struct nlmsghdr *nlh; @@ -1187,6 +1187,9 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, if (gnet_stats_finish_copy(&d) < 0) goto nla_put_failure; + if (qnum) + NLA_PUT_U32(skb, TCA_QINDEX, qnum); + nlh->nlmsg_len = skb_tail_pointer(skb) - b; return skb->len; @@ -1197,7 +1200,8 @@ nla_put_failure: } static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, - u32 clid, struct Qdisc *old, struct Qdisc *new) + u32 clid, struct Qdisc *old, struct Qdisc *new, + int qnum) { struct sk_buff *skb; u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; @@ -1207,11 +1211,13 @@ static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, return -ENOBUFS; if (old && old->handle) { - if (tc_fill_qdisc(skb, old, clid, pid, n->nlmsg_seq, 0, RTM_DELQDISC) < 0) + if (tc_fill_qdisc(skb, old, clid, pid, n->nlmsg_seq, 0, + RTM_DELQDISC, qnum) < 0) goto err_out; } if (new) { - if (tc_fill_qdisc(skb, new, clid, pid, n->nlmsg_seq, old ? NLM_F_REPLACE : 0, RTM_NEWQDISC) < 0) + if (tc_fill_qdisc(skb, new, clid, pid, n->nlmsg_seq, + old ? NLM_F_REPLACE : 0, RTM_NEWQDISC, qnum) < 0) goto err_out; } @@ -1230,7 +1236,7 @@ static bool tc_qdisc_dump_ignore(struct Qdisc *q) static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb, struct netlink_callback *cb, - int *q_idx_p, int s_q_idx) + int *q_idx_p, int s_q_idx, int qnum) { int ret = 0, q_idx = *q_idx_p; struct Qdisc *q; @@ -1239,23 +1245,18 @@ static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb, return 0; q = root; - if (q_idx < s_q_idx) { - q_idx++; - } else { - if (!tc_qdisc_dump_ignore(q) && - tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) - goto done; - q_idx++; - } + if (q_idx >= s_q_idx && + !tc_qdisc_dump_ignore(q) && + tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC, qnum) <= 0) + goto done; + q_idx++; + list_for_each_entry(q, &root->list, list) { - if (q_idx < s_q_idx) { - q_idx++; - continue; - } - if (!tc_qdisc_dump_ignore(q) && + if (q_idx >= s_q_idx && + !tc_qdisc_dump_ignore(q) && tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) + cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC, qnum) <= 0) goto done; q_idx++; } @@ -1284,6 +1285,7 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) idx = 0; for_each_netdev(&init_net, dev) { struct netdev_queue *dev_queue; + int ntx; if (idx < s_idx) goto cont; @@ -1291,12 +1293,15 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) s_q_idx = 0; q_idx = 0; - dev_queue = netdev_get_tx_queue(dev, 0); - if (tc_dump_qdisc_root(dev_queue->qdisc_sleeping, skb, cb, &q_idx, s_q_idx) < 0) - goto done; - + for (ntx = 0 ; ntx < dev->real_num_tx_queues; ntx++) { + dev_queue = netdev_get_tx_queue(dev, ntx); + if (tc_dump_qdisc_root(dev_queue->qdisc_sleeping, skb, + cb, &q_idx, s_q_idx, ntx) < 0) + goto done; + } dev_queue = &dev->rx_queue; - if (tc_dump_qdisc_root(dev_queue->qdisc_sleeping, skb, cb, &q_idx, s_q_idx) < 0) + if (tc_dump_qdisc_root(dev_queue->qdisc_sleeping, skb, cb, + &q_idx, s_q_idx, 0) < 0) goto done; cont: @@ -1419,10 +1424,10 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) case RTM_DELTCLASS: err = cops->delete(q, cl); if (err == 0) - tclass_notify(skb, n, q, cl, RTM_DELTCLASS); + tclass_notify(skb, n, q, cl, RTM_DELTCLASS, 0); goto out; case RTM_GETTCLASS: - err = tclass_notify(skb, n, q, cl, RTM_NEWTCLASS); + err = tclass_notify(skb, n, q, cl, RTM_NEWTCLASS, 0); goto out; default: err = -EINVAL; @@ -1433,7 +1438,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) new_cl = cl; err = cops->change(q, clid, pid, tca, &new_cl); if (err == 0) - tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS); + tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS, 0); out: if (cl) @@ -1445,7 +1450,7 @@ out: static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q, unsigned long cl, - u32 pid, u32 seq, u16 flags, int event) + u32 pid, u32 seq, u16 flags, int event, int qnum) { struct tcmsg *tcm; struct nlmsghdr *nlh; @@ -1474,6 +1479,9 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q, if (gnet_stats_finish_copy(&d) < 0) goto nla_put_failure; + if (qnum) + NLA_PUT_U32(skb, TCA_QINDEX, qnum); + nlh->nlmsg_len = skb_tail_pointer(skb) - b; return skb->len; @@ -1484,7 +1492,8 @@ nla_put_failure: } static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, - struct Qdisc *q, unsigned long cl, int event) + struct Qdisc *q, unsigned long cl, int event, + int qnum) { struct sk_buff *skb; u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; @@ -1493,7 +1502,7 @@ static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, if (!skb) return -ENOBUFS; - if (tc_fill_tclass(skb, q, cl, pid, n->nlmsg_seq, 0, event) < 0) { + if (tc_fill_tclass(skb, q, cl, pid, n->nlmsg_seq, 0, event, qnum) < 0) { kfree_skb(skb); return -EINVAL; } @@ -1503,9 +1512,10 @@ static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, struct qdisc_dump_args { - struct qdisc_walker w; - struct sk_buff *skb; + struct qdisc_walker w; + struct sk_buff *skb; struct netlink_callback *cb; + int qnum; }; static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walker *arg) @@ -1513,12 +1523,13 @@ static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walk struct qdisc_dump_args *a = (struct qdisc_dump_args *)arg; return tc_fill_tclass(a->skb, q, cl, NETLINK_CB(a->cb->skb).pid, - a->cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWTCLASS); + a->cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWTCLASS, + a->qnum); } static int tc_dump_tclass_qdisc(struct Qdisc *q, struct sk_buff *skb, struct tcmsg *tcm, struct netlink_callback *cb, - int *t_p, int s_t) + int *t_p, int s_t, int qnum) { struct qdisc_dump_args arg; @@ -1537,6 +1548,7 @@ static int tc_dump_tclass_qdisc(struct Qdisc *q, struct sk_buff *skb, arg.w.stop = 0; arg.w.skip = cb->args[1]; arg.w.count = 0; + arg.qnum = qnum; q->ops->cl_ops->walk(q, &arg.w); cb->args[1] = arg.w.count; if (arg.w.stop) @@ -1547,18 +1559,18 @@ static int tc_dump_tclass_qdisc(struct Qdisc *q, struct sk_buff *skb, static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb, struct tcmsg *tcm, struct netlink_callback *cb, - int *t_p, int s_t) + int *t_p, int s_t, int qnum) { struct Qdisc *q; if (!root) return 0; - if (tc_dump_tclass_qdisc(root, skb, tcm, cb, t_p, s_t) < 0) + if (tc_dump_tclass_qdisc(root, skb, tcm, cb, t_p, s_t, qnum) < 0) return -1; list_for_each_entry(q, &root->list, list) { - if (tc_dump_tclass_qdisc(q, skb, tcm, cb, t_p, s_t) < 0) + if (tc_dump_tclass_qdisc(q, skb, tcm, cb, t_p, s_t, qnum) < 0) return -1; } @@ -1571,7 +1583,7 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) struct net *net = sock_net(skb->sk); struct netdev_queue *dev_queue; struct net_device *dev; - int t, s_t; + int t, s_t, ntx; if (net != &init_net) return 0; @@ -1584,12 +1596,14 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) s_t = cb->args[0]; t = 0; - dev_queue = netdev_get_tx_queue(dev, 0); - if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t) < 0) - goto done; - + for (ntx = 0 ; ntx < dev->real_num_tx_queues; ntx++) { + dev_queue = netdev_get_tx_queue(dev, ntx); + if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, + cb, &t, s_t, ntx) < 0) + goto done; + } dev_queue = &dev->rx_queue; - if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t) < 0) + if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t, 0) < 0) goto done; done: