Skip to content

Commit 49b4997

Browse files
Jiri Kosinadavem330
authored andcommitted
net: sched: make default fifo qdiscs appear in the dump
The original reason [1] for having hidden qdiscs (potential scalability issues in qdisc_match_from_root() with single linked list in case of large amount of qdiscs) has been invalidated by 59cc1f6 ("net: sched: convert qdisc linked list to hashtable"). This allows us for bringing more clarity and determinism into the dump by making default pfifo qdiscs visible. We're not turning this on by default though, at it was deemed [2] too intrusive / unnecessary change of default behavior towards userspace. Instead, TCA_DUMP_INVISIBLE netlink attribute is introduced, which allows applications to request complete qdisc hierarchy dump, including the ones that have always been implicit/invisible. Singleton noop_qdisc stays invisible, as teaching the whole infrastructure about singletons would require quite some surgery with very little gain (seeing no qdisc or seeing noop qdisc in the dump is probably setting the same user expectation). [1] http://lkml.kernel.org/r/1460732328.10638.74.camel@edumazet-glaptop3.roam.corp.google.com [2] http://lkml.kernel.org/r/20161021.105935.1907696543877061916.davem@davemloft.net Signed-off-by: Jiri Kosina <jkosina@suse.cz> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 5e8456f commit 49b4997

18 files changed

+65
-17
lines changed

include/net/pkt_sched.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ int unregister_qdisc(struct Qdisc_ops *qops);
9292
void qdisc_get_default(char *id, size_t len);
9393
int qdisc_set_default(const char *id);
9494

95-
void qdisc_hash_add(struct Qdisc *q);
95+
void qdisc_hash_add(struct Qdisc *q, bool invisible);
9696
void qdisc_hash_del(struct Qdisc *q);
9797
struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
9898
struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);

include/net/sch_generic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ struct Qdisc {
6666
#define TCQ_F_NOPARENT 0x40 /* root of its hierarchy :
6767
* qdisc_tree_decrease_qlen() should stop.
6868
*/
69+
#define TCQ_F_INVISIBLE 0x80 /* invisible by default in dump */
6970
u32 limit;
7071
const struct Qdisc_ops *ops;
7172
struct qdisc_size_table __rcu *stab;

include/uapi/linux/rtnetlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ enum {
545545
TCA_STATS2,
546546
TCA_STAB,
547547
TCA_PAD,
548+
TCA_DUMP_INVISIBLE,
548549
__TCA_MAX
549550
};
550551

net/sched/sch_api.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -274,14 +274,16 @@ static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle)
274274
return NULL;
275275
}
276276

277-
void qdisc_hash_add(struct Qdisc *q)
277+
void qdisc_hash_add(struct Qdisc *q, bool invisible)
278278
{
279279
if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) {
280280
struct Qdisc *root = qdisc_dev(q)->qdisc;
281281

282282
WARN_ON_ONCE(root == &noop_qdisc);
283283
ASSERT_RTNL();
284284
hash_add_rcu(qdisc_dev(q)->qdisc_hash, &q->hash, q->handle);
285+
if (invisible)
286+
q->flags |= TCQ_F_INVISIBLE;
285287
}
286288
}
287289
EXPORT_SYMBOL(qdisc_hash_add);
@@ -1003,7 +1005,7 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
10031005
goto err_out4;
10041006
}
10051007

1006-
qdisc_hash_add(sch);
1008+
qdisc_hash_add(sch, false);
10071009

10081010
return sch;
10091011
}
@@ -1401,9 +1403,14 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
14011403
return -1;
14021404
}
14031405

1404-
static bool tc_qdisc_dump_ignore(struct Qdisc *q)
1406+
static bool tc_qdisc_dump_ignore(struct Qdisc *q, bool dump_invisible)
14051407
{
1406-
return (q->flags & TCQ_F_BUILTIN) ? true : false;
1408+
if (q->flags & TCQ_F_BUILTIN)
1409+
return true;
1410+
if ((q->flags & TCQ_F_INVISIBLE) && !dump_invisible)
1411+
return true;
1412+
1413+
return false;
14071414
}
14081415

14091416
static int qdisc_notify(struct net *net, struct sk_buff *oskb,
@@ -1417,12 +1424,12 @@ static int qdisc_notify(struct net *net, struct sk_buff *oskb,
14171424
if (!skb)
14181425
return -ENOBUFS;
14191426

1420-
if (old && !tc_qdisc_dump_ignore(old)) {
1427+
if (old && !tc_qdisc_dump_ignore(old, false)) {
14211428
if (tc_fill_qdisc(skb, old, clid, portid, n->nlmsg_seq,
14221429
0, RTM_DELQDISC) < 0)
14231430
goto err_out;
14241431
}
1425-
if (new && !tc_qdisc_dump_ignore(new)) {
1432+
if (new && !tc_qdisc_dump_ignore(new, false)) {
14261433
if (tc_fill_qdisc(skb, new, clid, portid, n->nlmsg_seq,
14271434
old ? NLM_F_REPLACE : 0, RTM_NEWQDISC) < 0)
14281435
goto err_out;
@@ -1439,7 +1446,8 @@ static int qdisc_notify(struct net *net, struct sk_buff *oskb,
14391446

14401447
static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb,
14411448
struct netlink_callback *cb,
1442-
int *q_idx_p, int s_q_idx, bool recur)
1449+
int *q_idx_p, int s_q_idx, bool recur,
1450+
bool dump_invisible)
14431451
{
14441452
int ret = 0, q_idx = *q_idx_p;
14451453
struct Qdisc *q;
@@ -1452,7 +1460,7 @@ static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb,
14521460
if (q_idx < s_q_idx) {
14531461
q_idx++;
14541462
} else {
1455-
if (!tc_qdisc_dump_ignore(q) &&
1463+
if (!tc_qdisc_dump_ignore(q, dump_invisible) &&
14561464
tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).portid,
14571465
cb->nlh->nlmsg_seq, NLM_F_MULTI,
14581466
RTM_NEWQDISC) <= 0)
@@ -1474,7 +1482,7 @@ static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb,
14741482
q_idx++;
14751483
continue;
14761484
}
1477-
if (!tc_qdisc_dump_ignore(q) &&
1485+
if (!tc_qdisc_dump_ignore(q, dump_invisible) &&
14781486
tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).portid,
14791487
cb->nlh->nlmsg_seq, NLM_F_MULTI,
14801488
RTM_NEWQDISC) <= 0)
@@ -1496,12 +1504,21 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
14961504
int idx, q_idx;
14971505
int s_idx, s_q_idx;
14981506
struct net_device *dev;
1507+
const struct nlmsghdr *nlh = cb->nlh;
1508+
struct tcmsg *tcm = nlmsg_data(nlh);
1509+
struct nlattr *tca[TCA_MAX + 1];
1510+
int err;
14991511

15001512
s_idx = cb->args[0];
15011513
s_q_idx = q_idx = cb->args[1];
15021514

15031515
idx = 0;
15041516
ASSERT_RTNL();
1517+
1518+
err = nlmsg_parse(nlh, sizeof(*tcm), tca, TCA_MAX, NULL);
1519+
if (err < 0)
1520+
return err;
1521+
15051522
for_each_netdev(net, dev) {
15061523
struct netdev_queue *dev_queue;
15071524

@@ -1512,13 +1529,14 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
15121529
q_idx = 0;
15131530

15141531
if (tc_dump_qdisc_root(dev->qdisc, skb, cb, &q_idx, s_q_idx,
1515-
true) < 0)
1532+
true, tca[TCA_DUMP_INVISIBLE]) < 0)
15161533
goto done;
15171534

15181535
dev_queue = dev_ingress_queue(dev);
15191536
if (dev_queue &&
15201537
tc_dump_qdisc_root(dev_queue->qdisc_sleeping, skb, cb,
1521-
&q_idx, s_q_idx, false) < 0)
1538+
&q_idx, s_q_idx, false,
1539+
tca[TCA_DUMP_INVISIBLE]) < 0)
15221540
goto done;
15231541

15241542
cont:
@@ -1762,7 +1780,7 @@ static int tc_dump_tclass_qdisc(struct Qdisc *q, struct sk_buff *skb,
17621780
{
17631781
struct qdisc_dump_args arg;
17641782

1765-
if (tc_qdisc_dump_ignore(q) ||
1783+
if (tc_qdisc_dump_ignore(q, false) ||
17661784
*t_p < s_t || !q->ops->cl_ops ||
17671785
(tcm->tcm_parent &&
17681786
TC_H_MAJ(tcm->tcm_parent) != q->handle)) {

net/sched/sch_cbq.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,6 +1161,8 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
11611161
sch->handle);
11621162
if (!q->link.q)
11631163
q->link.q = &noop_qdisc;
1164+
else
1165+
qdisc_hash_add(q->link.q, true);
11641166

11651167
q->link.priority = TC_CBQ_MAXPRIO - 1;
11661168
q->link.priority2 = TC_CBQ_MAXPRIO - 1;
@@ -1600,6 +1602,9 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
16001602
cl->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid);
16011603
if (!cl->q)
16021604
cl->q = &noop_qdisc;
1605+
else
1606+
qdisc_hash_add(cl->q, true);
1607+
16031608
cl->common.classid = classid;
16041609
cl->tparent = parent;
16051610
cl->qdisc = sch;

net/sched/sch_drr.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
117117
&pfifo_qdisc_ops, classid);
118118
if (cl->qdisc == NULL)
119119
cl->qdisc = &noop_qdisc;
120+
else
121+
qdisc_hash_add(cl->qdisc, true);
120122

121123
if (tca[TCA_RATE]) {
122124
err = gen_replace_estimator(&cl->bstats, NULL, &cl->rate_est,

net/sched/sch_dsmark.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,8 @@ static int dsmark_init(struct Qdisc *sch, struct nlattr *opt)
368368
p->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, sch->handle);
369369
if (p->q == NULL)
370370
p->q = &noop_qdisc;
371+
else
372+
qdisc_hash_add(p->q, true);
371373

372374
pr_debug("%s: qdisc %p\n", __func__, p->q);
373375

net/sched/sch_generic.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ static void attach_default_qdiscs(struct net_device *dev)
795795
}
796796
#ifdef CONFIG_NET_SCHED
797797
if (dev->qdisc)
798-
qdisc_hash_add(dev->qdisc);
798+
qdisc_hash_add(dev->qdisc, false);
799799
#endif
800800
}
801801

net/sched/sch_hfsc.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,8 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
10661066
&pfifo_qdisc_ops, classid);
10671067
if (cl->qdisc == NULL)
10681068
cl->qdisc = &noop_qdisc;
1069+
else
1070+
qdisc_hash_add(cl->qdisc, true);
10691071
INIT_LIST_HEAD(&cl->children);
10701072
cl->vt_tree = RB_ROOT;
10711073
cl->cf_tree = RB_ROOT;
@@ -1425,6 +1427,8 @@ hfsc_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
14251427
sch->handle);
14261428
if (q->root.qdisc == NULL)
14271429
q->root.qdisc = &noop_qdisc;
1430+
else
1431+
qdisc_hash_add(q->root.qdisc, true);
14281432
INIT_LIST_HEAD(&q->root.children);
14291433
q->root.vt_tree = RB_ROOT;
14301434
q->root.cf_tree = RB_ROOT;

net/sched/sch_htb.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,6 +1460,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
14601460
qdisc_class_hash_insert(&q->clhash, &cl->common);
14611461
if (parent)
14621462
parent->children++;
1463+
if (cl->un.leaf.q != &noop_qdisc)
1464+
qdisc_hash_add(cl->un.leaf.q, true);
14631465
} else {
14641466
if (tca[TCA_RATE]) {
14651467
err = gen_replace_estimator(&cl->bstats, NULL,

net/sched/sch_mq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ static void mq_attach(struct Qdisc *sch)
8484
qdisc_destroy(old);
8585
#ifdef CONFIG_NET_SCHED
8686
if (ntx < dev->real_num_tx_queues)
87-
qdisc_hash_add(qdisc);
87+
qdisc_hash_add(qdisc, false);
8888
#endif
8989

9090
}

net/sched/sch_mqprio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ static void mqprio_attach(struct Qdisc *sch)
175175
if (old)
176176
qdisc_destroy(old);
177177
if (ntx < dev->real_num_tx_queues)
178-
qdisc_hash_add(qdisc);
178+
qdisc_hash_add(qdisc, false);
179179
}
180180
kfree(priv->qdiscs);
181181
priv->qdiscs = NULL;

net/sched/sch_multiq.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt)
217217
sch_tree_lock(sch);
218218
old = q->queues[i];
219219
q->queues[i] = child;
220+
if (child != &noop_qdisc)
221+
qdisc_hash_add(child, true);
220222

221223
if (old != &noop_qdisc) {
222224
qdisc_tree_reduce_backlog(old,

net/sched/sch_prio.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,11 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt)
192192
qdisc_destroy(child);
193193
}
194194

195-
for (i = oldbands; i < q->bands; i++)
195+
for (i = oldbands; i < q->bands; i++) {
196196
q->queues[i] = queues[i];
197+
if (q->queues[i] != &noop_qdisc)
198+
qdisc_hash_add(q->queues[i], true);
199+
}
197200

198201
sch_tree_unlock(sch);
199202
return 0;

net/sched/sch_qfq.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
494494
goto destroy_class;
495495
}
496496

497+
if (cl->qdisc != &noop_qdisc)
498+
qdisc_hash_add(cl->qdisc, true);
497499
sch_tree_lock(sch);
498500
qdisc_class_hash_insert(&q->clhash, &cl->common);
499501
sch_tree_unlock(sch);

net/sched/sch_red.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt)
191191
return PTR_ERR(child);
192192
}
193193

194+
if (child != &noop_qdisc)
195+
qdisc_hash_add(child, true);
194196
sch_tree_lock(sch);
195197
q->flags = ctl->flags;
196198
q->limit = ctl->limit;

net/sched/sch_sfb.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,8 @@ static int sfb_change(struct Qdisc *sch, struct nlattr *opt)
513513
if (IS_ERR(child))
514514
return PTR_ERR(child);
515515

516+
if (child != &noop_qdisc)
517+
qdisc_hash_add(child, true);
516518
sch_tree_lock(sch);
517519

518520
qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen,

net/sched/sch_tbf.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,8 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
396396
q->qdisc->qstats.backlog);
397397
qdisc_destroy(q->qdisc);
398398
q->qdisc = child;
399+
if (child != &noop_qdisc);
400+
qdisc_hash_add(child, true);
399401
}
400402
q->limit = qopt->limit;
401403
if (tb[TCA_TBF_PBURST])

0 commit comments

Comments
 (0)