Commit 6e765a00 authored by Florian Westphal's avatar Florian Westphal Committed by David S. Miller

net_sched: drr: warn when qdisc is not work conserving

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 b00355db
('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: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f3591fd4
...@@ -96,7 +96,7 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, ...@@ -96,7 +96,7 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
struct nlattr *tab); struct nlattr *tab);
void qdisc_put_rtab(struct qdisc_rate_table *tab); void qdisc_put_rtab(struct qdisc_rate_table *tab);
void qdisc_put_stab(struct qdisc_size_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, int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
struct net_device *dev, struct netdev_queue *txq, struct net_device *dev, struct netdev_queue *txq,
spinlock_t *root_lock); spinlock_t *root_lock);
......
...@@ -563,7 +563,7 @@ void __qdisc_calculate_pkt_len(struct sk_buff *skb, const struct qdisc_size_tabl ...@@ -563,7 +563,7 @@ void __qdisc_calculate_pkt_len(struct sk_buff *skb, const struct qdisc_size_tabl
} }
EXPORT_SYMBOL(__qdisc_calculate_pkt_len); 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)) { if (!(qdisc->flags & TCQ_F_WARN_NONWC)) {
pr_warn("%s: %s qdisc %X: is non-work-conserving?\n", pr_warn("%s: %s qdisc %X: is non-work-conserving?\n",
......
...@@ -391,8 +391,10 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch) ...@@ -391,8 +391,10 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch)
while (1) { while (1) {
cl = list_first_entry(&q->active, struct drr_class, alist); cl = list_first_entry(&q->active, struct drr_class, alist);
skb = cl->qdisc->ops->peek(cl->qdisc); skb = cl->qdisc->ops->peek(cl->qdisc);
if (skb == NULL) if (skb == NULL) {
qdisc_warn_nonwc(__func__, cl->qdisc);
goto out; goto out;
}
len = qdisc_pkt_len(skb); len = qdisc_pkt_len(skb);
if (len <= cl->deficit) { if (len <= cl->deficit) {
......
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