Skip to content

Commit

Permalink
Merge branch 'qdisc-hash-fixes'
Browse files Browse the repository at this point in the history
Jiri Kosina says:

====================
qdisc-hashtable fixes

The following two patches fix all the issues that have been reported
against the conversion of qdisc linked list to hashtable (currently in
net-next) so far.

First patch adjusts handling of singleton qdiscs to the new semantics, and
is rather straightforward.

The second patch, which fixes "cosmetic" issue of duplicate entries in the
qdisc dump for ingress qdiscs, is a little bit more hairy; I personally
would love to see all the already existing "if (ingress)"-like hacks go
away (by, let's say, introducing a general TCQ_F_? flag), but that's way
out of scope of this patchset (but already on my todo).

Thanks a lot to Daniel Borkmann and David Ahern for reporting the issues
and testing the patches promptly.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 19, 2016
2 parents e951f14 + ea32746 commit 3e7d2d4
Showing 1 changed file with 19 additions and 3 deletions.
22 changes: 19 additions & 3 deletions net/sched/sch_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle)
{
struct Qdisc *q;

if (!qdisc_dev(root))
return (root->handle == handle ? root : NULL);

if (!(root->flags & TCQ_F_BUILTIN) &&
root->handle == handle)
return root;
Expand Down Expand Up @@ -1432,7 +1435,7 @@ static int qdisc_notify(struct net *net, struct sk_buff *oskb,

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, bool recur)
{
int ret = 0, q_idx = *q_idx_p;
struct Qdisc *q;
Expand All @@ -1451,6 +1454,16 @@ static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb,
goto done;
q_idx++;
}

/* If dumping singletons, there is no qdisc_dev(root) and the singleton
* itself has already been dumped.
*
* If we've already dumped the top-level (ingress) qdisc above and the global
* qdisc hashtable, we don't want to hit it again
*/
if (!qdisc_dev(root) || !recur)
goto out;

hash_for_each(qdisc_dev(root)->qdisc_hash, b, q, hash) {
if (q_idx < s_q_idx) {
q_idx++;
Expand Down Expand Up @@ -1492,13 +1505,13 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
s_q_idx = 0;
q_idx = 0;

if (tc_dump_qdisc_root(dev->qdisc, skb, cb, &q_idx, s_q_idx) < 0)
if (tc_dump_qdisc_root(dev->qdisc, skb, cb, &q_idx, s_q_idx, true) < 0)
goto done;

dev_queue = dev_ingress_queue(dev);
if (dev_queue &&
tc_dump_qdisc_root(dev_queue->qdisc_sleeping, skb, cb,
&q_idx, s_q_idx) < 0)
&q_idx, s_q_idx, false) < 0)
goto done;

cont:
Expand Down Expand Up @@ -1775,6 +1788,9 @@ static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb,
if (tc_dump_tclass_qdisc(root, skb, tcm, cb, t_p, s_t) < 0)
return -1;

if (!qdisc_dev(root))
return 0;

hash_for_each(qdisc_dev(root)->qdisc_hash, b, q, hash) {
if (tc_dump_tclass_qdisc(q, skb, tcm, cb, t_p, s_t) < 0)
return -1;
Expand Down

0 comments on commit 3e7d2d4

Please sign in to comment.