net_sched: drr: warn when qdisc is not work conserving
authorFlorian Westphal <fw@strlen.de>
Wed, 11 Jun 2014 18:35:18 +0000 (20:35 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 11 Jun 2014 22:50:59 +0000 (15:50 -0700)
The DRR scheduler requires that items on the active list are work
conserving, i.e. do not hold on to skbs for throttling purposes, etc.
Attaching e.g. tbf renders DRR useless because all other classes on the
active list are delayed as well.

So, warn users that this configuration won't work as expected; we
already do this in couple of other qdiscs, see e.g.

commit b00355db3f88d96810a60011a30cfb2c3469409d
('pkt_sched: sch_hfsc: sch_htb: Add non-work-conserving warning handler')

The 'const' change is needed to avoid compiler warning ("discards 'const'
qualifier from pointer target type").

tested with:
drr_hier() {
        parent=$1
        classes=$2
        for i in  $(seq 1 $classes); do
                classid=$parent$(printf %x $i)
                tc class add dev eth0 parent $parent classid $classid drr
tc qdisc add dev eth0 parent $classid tbf rate 64kbit burst 256kbit limit 64kbit
        done
}
tc qdisc add dev eth0 root handle 1: drr
drr_hier 1: 32
tc filter add dev eth0 protocol all pref 1 parent 1: handle 1 flow hash keys dst perturb 1 divisor 32

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/pkt_sched.h
net/sched/sch_api.c
net/sched/sch_drr.c

index 891d80d2c4d2a98cfdad75deee1c28bdce9c9f9f..ec030cd7661693d3812035d350e242f9b271edc4 100644 (file)
@@ -96,7 +96,7 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
                                        struct nlattr *tab);
 void qdisc_put_rtab(struct qdisc_rate_table *tab);
 void qdisc_put_stab(struct qdisc_size_table *tab);
-void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc);
+void qdisc_warn_nonwc(const char *txt, struct Qdisc *qdisc);
 int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
                    struct net_device *dev, struct netdev_queue *txq,
                    spinlock_t *root_lock);
index fd14df56e5ffdc2d96d61abbe55b2607c95179c5..58bed7599db7d9f5538f01ff5057e7aa79d0a915 100644 (file)
@@ -563,7 +563,7 @@ out:
 }
 EXPORT_SYMBOL(__qdisc_calculate_pkt_len);
 
-void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc)
+void qdisc_warn_nonwc(const char *txt, struct Qdisc *qdisc)
 {
        if (!(qdisc->flags & TCQ_F_WARN_NONWC)) {
                pr_warn("%s: %s qdisc %X: is non-work-conserving?\n",
index 8302717ea3034247bc27597e067ac8771dc973b5..7bbbfe1121920a126537d43a0443ab4b98e340fa 100644 (file)
@@ -391,8 +391,10 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch)
        while (1) {
                cl = list_first_entry(&q->active, struct drr_class, alist);
                skb = cl->qdisc->ops->peek(cl->qdisc);
-               if (skb == NULL)
+               if (skb == NULL) {
+                       qdisc_warn_nonwc(__func__, cl->qdisc);
                        goto out;
+               }
 
                len = qdisc_pkt_len(skb);
                if (len <= cl->deficit) {