aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-08-09 02:23:39 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-09 02:23:39 -0400
commit8123b421e8ed944671d7241323ed3198cccb4041 (patch)
treefb9e5634b36cce181781e764e71406c972dd2e8c
parent76aab2c1eae491a5d73ac83deec97dd28ebac584 (diff)
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: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sched/sch_api.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index ba1d121f3127..bbf149dd7818 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -183,6 +183,21 @@ EXPORT_SYMBOL(unregister_qdisc);
183 (root qdisc, all its children, children of children etc.) 183 (root qdisc, all its children, children of children etc.)
184 */ 184 */
185 185
186struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle)
187{
188 struct Qdisc *q;
189
190 if (!(root->flags & TCQ_F_BUILTIN) &&
191 root->handle == handle)
192 return root;
193
194 list_for_each_entry(q, &root->list, list) {
195 if (q->handle == handle)
196 return q;
197 }
198 return NULL;
199}
200
186struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) 201struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
187{ 202{
188 unsigned int i; 203 unsigned int i;
@@ -191,16 +206,11 @@ struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
191 struct netdev_queue *txq = netdev_get_tx_queue(dev, i); 206 struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
192 struct Qdisc *q, *txq_root = txq->qdisc_sleeping; 207 struct Qdisc *q, *txq_root = txq->qdisc_sleeping;
193 208
194 if (!(txq_root->flags & TCQ_F_BUILTIN) && 209 q = qdisc_match_from_root(txq_root, handle);
195 txq_root->handle == handle) 210 if (q)
196 return txq_root; 211 return q;
197
198 list_for_each_entry(q, &txq_root->list, list) {
199 if (q->handle == handle)
200 return q;
201 }
202 } 212 }
203 return NULL; 213 return qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle);
204} 214}
205 215
206static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) 216static 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 return -ENOENT; 918 return -ENOENT;
909 q = qdisc_leaf(p, clid); 919 q = qdisc_leaf(p, clid);
910 } else { /* ingress */ 920 } else { /* ingress */
911 q = dev->rx_queue.qdisc; 921 q = dev->rx_queue.qdisc_sleeping;
912 } 922 }
913 } else { 923 } else {
914 struct netdev_queue *dev_queue; 924 struct netdev_queue *dev_queue;
@@ -978,7 +988,7 @@ replay:
978 return -ENOENT; 988 return -ENOENT;
979 q = qdisc_leaf(p, clid); 989 q = qdisc_leaf(p, clid);
980 } else { /*ingress */ 990 } else { /*ingress */
981 q = dev->rx_queue.qdisc; 991 q = dev->rx_queue.qdisc_sleeping;
982 } 992 }
983 } else { 993 } else {
984 struct netdev_queue *dev_queue; 994 struct netdev_queue *dev_queue;
@@ -1529,11 +1539,11 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
1529 t = 0; 1539 t = 0;
1530 1540
1531 dev_queue = netdev_get_tx_queue(dev, 0); 1541 dev_queue = netdev_get_tx_queue(dev, 0);
1532 if (tc_dump_tclass_root(dev_queue->qdisc, skb, tcm, cb, &t, s_t) < 0) 1542 if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t) < 0)
1533 goto done; 1543 goto done;
1534 1544
1535 dev_queue = &dev->rx_queue; 1545 dev_queue = &dev->rx_queue;
1536 if (tc_dump_tclass_root(dev_queue->qdisc, skb, tcm, cb, &t, s_t) < 0) 1546 if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t) < 0)
1537 goto done; 1547 goto done;
1538 1548
1539done: 1549done: