Re: qdisc and down links (regression)

Previous thread: [PATCH -next] bnx2x: fix logical op by Randy Dunlap on Thursday, August 7, 2008 - 4:53 pm. (2 messages)

Next thread: [PATCH] sch_prio: Use return value from inner qdisc requeue by Jussi Kivilinna on Thursday, August 7, 2008 - 6:10 pm. (2 messages)
To: David Miller <davem@...>
Cc: <netdev@...>, <linux-kernel@...>
Date: Thursday, August 7, 2008 - 5:30 pm

Before the mulitqueue changes in 2.6.27-rc it was possible to setup
queueing disciplines before the link came up (carrier active). This
no longer works. If link is down, the qdisc is the noop_qdisc and
any configuration changes don't seem to be shown.

This probably will break ISP's (and other users whose links aren't always
on) that use traffic shaping.

For example, try wondershaper or similar script before boot; all the
tc commands will fail.
--

To: <stephen.hemminger@...>
Cc: <netdev@...>, <linux-kernel@...>
Date: Thursday, August 7, 2008 - 6:47 pm

From: Stephen Hemminger <stephen.hemminger@vyatta.com>

I'll see why this happens, it wasn't an intentional change.

Before the link comes up, we don't activate the qdisc. We just
remember it in ->qdisc_sleeping. I bet if you bring the link up the
configuration will become visible, or that is the area where the
unintentional error is occuring.
--

To: <stephen.hemminger@...>
Cc: <netdev@...>, <linux-kernel@...>
Date: Thursday, August 7, 2008 - 9:50 pm

From: David Miller <davem@davemloft.net>

This should fix it, let me know if it doesn't:

diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 83b23b5..ba1d121 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -189,7 +189,7 @@ struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)

for (i = 0; i < dev->num_tx_queues; i++) {
struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
- struct Qdisc *q, *txq_root = txq->qdisc;
+ struct Qdisc *q, *txq_root = txq->qdisc_sleeping;

if (!(txq_root->flags & TCQ_F_BUILTIN) &&
txq_root->handle == handle)
@@ -793,7 +793,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
}
}
if ((parent != TC_H_ROOT) && !(sch->flags & TCQ_F_INGRESS))
- list_add_tail(&sch->list, &dev_queue->qdisc->list);
+ list_add_tail(&sch->list, &dev_queue->qdisc_sleeping->list);

return sch;
}
@@ -1236,11 +1236,11 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
q_idx = 0;

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

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

cont:
--

To: David Miller <davem@...>
Cc: <netdev@...>, <linux-kernel@...>
Date: Friday, August 8, 2008 - 5:32 pm

On Thu, 07 Aug 2008 18:50:24 -0700 (PDT)

It fixes it for qdisc but not for ingress filters

# tc qdisc add dev eth0 handle ffff: ingress
# tc filter add dev eth0 parent ffff: protocol ip \
prio 50 u32 match ip src 0.0.0.0/0 police rate 800kbit burst 10k drop flowid :1
RTNETLINK answers: Invalid argument
We have an error talking to the kernel

Another problem is that the ingress qdisc can no longer be deleted
successfully.
--

To: <stephen.hemminger@...>
Cc: <netdev@...>, <linux-kernel@...>
Date: Saturday, August 9, 2008 - 2:24 am

From: Stephen Hemminger <stephen.hemminger@vyatta.com>

These problems should be fixed by the following patch which
I've just pushed to net-2.6:

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>
---
net/sched/sch_api.c | 36 +++++++++++++++++++++++-------------
1 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index ba1d121..bbf149d 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -183,6 +183,21 @@ EXPORT_SYMBOL(unregister_qdisc);
(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)
{
unsigned int i;
@@ -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 Qdisc *q, *txq_root = txq->qdisc_sleeping;

- if (!(txq_root->flags & TCQ_F_BUILTIN) &&
- txq_root->handle == handle)
- return txq_root;
-
- list_for_each_entry(q, &txq_root->list, list) {
- if (q->handle == handle)
- return q;
- }
+ q = qdisc_match_from_root(txq_root, handle);
+ if (q)
+ return q;
}
- return NULL;
+ return qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle);
}

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 *...

To: David Miller <davem@...>
Cc: <netdev@...>, <linux-kernel@...>
Date: Monday, August 11, 2008 - 1:34 pm

On Fri, 08 Aug 2008 23:24:27 -0700 (PDT)

Thanks, all fixed.
--

To: <stephen.hemminger@...>
Cc: <netdev@...>, <linux-kernel@...>
Date: Friday, August 8, 2008 - 7:11 pm

From: Stephen Hemminger <stephen.hemminger@vyatta.com>

Thanks, I'll take a look at this.
--

To: David Miller <davem@...>
Cc: <netdev@...>
Date: Friday, August 8, 2008 - 7:12 pm

[Empty message]
Previous thread: [PATCH -next] bnx2x: fix logical op by Randy Dunlap on Thursday, August 7, 2008 - 4:53 pm. (2 messages)

Next thread: [PATCH] sch_prio: Use return value from inner qdisc requeue by Jussi Kivilinna on Thursday, August 7, 2008 - 6:10 pm. (2 messages)