Commit 3e7d2d45 authored by David S. Miller's avatar David S. Miller

Merge branch 'qdisc-hash-fixes'

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: default avatarDavid S. Miller <davem@davemloft.net>
parents e951f145 ea327469
......@@ -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;
......@@ -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;
......@@ -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++;
......@@ -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:
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment