Commit 8123b421 authored by David S. Miller's avatar David S. Miller

pkt_sched: Fix ingress deletion and filter attachment.

Based upon bug reports by Stephen Hemminger.

We still had some cases using ->qdisc instead of ->qdisc_sleeping.

Also, qdisc_lookup() should return ingress qdiscs.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 76aab2c1
...@@ -183,6 +183,21 @@ EXPORT_SYMBOL(unregister_qdisc); ...@@ -183,6 +183,21 @@ EXPORT_SYMBOL(unregister_qdisc);
(root qdisc, all its children, children of children etc.) (root qdisc, all its children, children of children etc.)
*/ */
struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle)
{
struct Qdisc *q;
if (!(root->flags & TCQ_F_BUILTIN) &&
root->handle == handle)
return root;
list_for_each_entry(q, &root->list, list) {
if (q->handle == handle)
return q;
}
return NULL;
}
struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
{ {
unsigned int i; unsigned int i;
...@@ -191,16 +206,11 @@ struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) ...@@ -191,16 +206,11 @@ struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
struct netdev_queue *txq = netdev_get_tx_queue(dev, i); struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
struct Qdisc *q, *txq_root = txq->qdisc_sleeping; struct Qdisc *q, *txq_root = txq->qdisc_sleeping;
if (!(txq_root->flags & TCQ_F_BUILTIN) && q = qdisc_match_from_root(txq_root, handle);
txq_root->handle == handle) if (q)
return txq_root;
list_for_each_entry(q, &txq_root->list, list) {
if (q->handle == handle)
return q; return q;
} }
} return qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle);
return NULL;
} }
static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid)
...@@ -908,7 +918,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -908,7 +918,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
return -ENOENT; return -ENOENT;
q = qdisc_leaf(p, clid); q = qdisc_leaf(p, clid);
} else { /* ingress */ } else { /* ingress */
q = dev->rx_queue.qdisc; q = dev->rx_queue.qdisc_sleeping;
} }
} else { } else {
struct netdev_queue *dev_queue; struct netdev_queue *dev_queue;
...@@ -978,7 +988,7 @@ replay: ...@@ -978,7 +988,7 @@ replay:
return -ENOENT; return -ENOENT;
q = qdisc_leaf(p, clid); q = qdisc_leaf(p, clid);
} else { /*ingress */ } else { /*ingress */
q = dev->rx_queue.qdisc; q = dev->rx_queue.qdisc_sleeping;
} }
} else { } else {
struct netdev_queue *dev_queue; struct netdev_queue *dev_queue;
...@@ -1529,11 +1539,11 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1529,11 +1539,11 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
t = 0; t = 0;
dev_queue = netdev_get_tx_queue(dev, 0); dev_queue = netdev_get_tx_queue(dev, 0);
if (tc_dump_tclass_root(dev_queue->qdisc, skb, tcm, cb, &t, s_t) < 0) if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t) < 0)
goto done; goto done;
dev_queue = &dev->rx_queue; dev_queue = &dev->rx_queue;
if (tc_dump_tclass_root(dev_queue->qdisc, skb, tcm, cb, &t, s_t) < 0) if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t) < 0)
goto done; goto done;
done: done:
......
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