Skip to content

Commit 10f6dfc

Browse files
stephen hemmingerdavem330
authored andcommitted
Revert "sch_netem: Remove classful functionality"
Many users have wanted the old functionality that was lost to be able to use pfifo as inner qdisc for netem. The reason that netem could not be classful with the older API was because of the limitations of the old dequeue/requeue interface; now that qdisc API has a peek function, there is no longer a problem with using any inner qdisc's. This reverts commit 0220146. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent df173bd commit 10f6dfc

File tree

1 file changed

+79
-8
lines changed

1 file changed

+79
-8
lines changed

net/sched/sch_netem.c

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -238,14 +238,15 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
238238
ret = NET_XMIT_SUCCESS;
239239
}
240240

241-
if (likely(ret == NET_XMIT_SUCCESS)) {
242-
sch->q.qlen++;
243-
} else if (net_xmit_drop_count(ret)) {
244-
sch->qstats.drops++;
241+
if (ret != NET_XMIT_SUCCESS) {
242+
if (net_xmit_drop_count(ret)) {
243+
sch->qstats.drops++;
244+
return ret;
245+
}
245246
}
246247

247-
pr_debug("netem: enqueue ret %d\n", ret);
248-
return ret;
248+
sch->q.qlen++;
249+
return NET_XMIT_SUCCESS;
249250
}
250251

251252
static unsigned int netem_drop(struct Qdisc *sch)
@@ -287,9 +288,10 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
287288
if (G_TC_FROM(skb->tc_verd) & AT_INGRESS)
288289
skb->tstamp.tv64 = 0;
289290
#endif
290-
pr_debug("netem_dequeue: return skb=%p\n", skb);
291-
qdisc_bstats_update(sch, skb);
291+
292292
sch->q.qlen--;
293+
qdisc_unthrottled(sch);
294+
qdisc_bstats_update(sch, skb);
293295
return skb;
294296
}
295297

@@ -610,8 +612,77 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
610612
return -1;
611613
}
612614

615+
static int netem_dump_class(struct Qdisc *sch, unsigned long cl,
616+
struct sk_buff *skb, struct tcmsg *tcm)
617+
{
618+
struct netem_sched_data *q = qdisc_priv(sch);
619+
620+
if (cl != 1) /* only one class */
621+
return -ENOENT;
622+
623+
tcm->tcm_handle |= TC_H_MIN(1);
624+
tcm->tcm_info = q->qdisc->handle;
625+
626+
return 0;
627+
}
628+
629+
static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
630+
struct Qdisc **old)
631+
{
632+
struct netem_sched_data *q = qdisc_priv(sch);
633+
634+
if (new == NULL)
635+
new = &noop_qdisc;
636+
637+
sch_tree_lock(sch);
638+
*old = q->qdisc;
639+
q->qdisc = new;
640+
qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
641+
qdisc_reset(*old);
642+
sch_tree_unlock(sch);
643+
644+
return 0;
645+
}
646+
647+
static struct Qdisc *netem_leaf(struct Qdisc *sch, unsigned long arg)
648+
{
649+
struct netem_sched_data *q = qdisc_priv(sch);
650+
return q->qdisc;
651+
}
652+
653+
static unsigned long netem_get(struct Qdisc *sch, u32 classid)
654+
{
655+
return 1;
656+
}
657+
658+
static void netem_put(struct Qdisc *sch, unsigned long arg)
659+
{
660+
}
661+
662+
static void netem_walk(struct Qdisc *sch, struct qdisc_walker *walker)
663+
{
664+
if (!walker->stop) {
665+
if (walker->count >= walker->skip)
666+
if (walker->fn(sch, 1, walker) < 0) {
667+
walker->stop = 1;
668+
return;
669+
}
670+
walker->count++;
671+
}
672+
}
673+
674+
static const struct Qdisc_class_ops netem_class_ops = {
675+
.graft = netem_graft,
676+
.leaf = netem_leaf,
677+
.get = netem_get,
678+
.put = netem_put,
679+
.walk = netem_walk,
680+
.dump = netem_dump_class,
681+
};
682+
613683
static struct Qdisc_ops netem_qdisc_ops __read_mostly = {
614684
.id = "netem",
685+
.cl_ops = &netem_class_ops,
615686
.priv_size = sizeof(struct netem_sched_data),
616687
.enqueue = netem_enqueue,
617688
.dequeue = netem_dequeue,

0 commit comments

Comments
 (0)