Commit 10f6dfcf authored by stephen hemminger's avatar stephen hemminger Committed by David S. Miller

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 02201464.
Signed-off-by: default avatarStephen Hemminger <shemminger@vyatta.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent df173bda
...@@ -238,14 +238,15 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) ...@@ -238,14 +238,15 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
ret = NET_XMIT_SUCCESS; ret = NET_XMIT_SUCCESS;
} }
if (likely(ret == NET_XMIT_SUCCESS)) { if (ret != NET_XMIT_SUCCESS) {
sch->q.qlen++; if (net_xmit_drop_count(ret)) {
} else if (net_xmit_drop_count(ret)) {
sch->qstats.drops++; sch->qstats.drops++;
return ret;
}
} }
pr_debug("netem: enqueue ret %d\n", ret); sch->q.qlen++;
return ret; return NET_XMIT_SUCCESS;
} }
static unsigned int netem_drop(struct Qdisc *sch) static unsigned int netem_drop(struct Qdisc *sch)
...@@ -287,9 +288,10 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) ...@@ -287,9 +288,10 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
if (G_TC_FROM(skb->tc_verd) & AT_INGRESS) if (G_TC_FROM(skb->tc_verd) & AT_INGRESS)
skb->tstamp.tv64 = 0; skb->tstamp.tv64 = 0;
#endif #endif
pr_debug("netem_dequeue: return skb=%p\n", skb);
qdisc_bstats_update(sch, skb);
sch->q.qlen--; sch->q.qlen--;
qdisc_unthrottled(sch);
qdisc_bstats_update(sch, skb);
return skb; return skb;
} }
...@@ -610,8 +612,77 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) ...@@ -610,8 +612,77 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
return -1; return -1;
} }
static int netem_dump_class(struct Qdisc *sch, unsigned long cl,
struct sk_buff *skb, struct tcmsg *tcm)
{
struct netem_sched_data *q = qdisc_priv(sch);
if (cl != 1) /* only one class */
return -ENOENT;
tcm->tcm_handle |= TC_H_MIN(1);
tcm->tcm_info = q->qdisc->handle;
return 0;
}
static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
struct Qdisc **old)
{
struct netem_sched_data *q = qdisc_priv(sch);
if (new == NULL)
new = &noop_qdisc;
sch_tree_lock(sch);
*old = q->qdisc;
q->qdisc = new;
qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
qdisc_reset(*old);
sch_tree_unlock(sch);
return 0;
}
static struct Qdisc *netem_leaf(struct Qdisc *sch, unsigned long arg)
{
struct netem_sched_data *q = qdisc_priv(sch);
return q->qdisc;
}
static unsigned long netem_get(struct Qdisc *sch, u32 classid)
{
return 1;
}
static void netem_put(struct Qdisc *sch, unsigned long arg)
{
}
static void netem_walk(struct Qdisc *sch, struct qdisc_walker *walker)
{
if (!walker->stop) {
if (walker->count >= walker->skip)
if (walker->fn(sch, 1, walker) < 0) {
walker->stop = 1;
return;
}
walker->count++;
}
}
static const struct Qdisc_class_ops netem_class_ops = {
.graft = netem_graft,
.leaf = netem_leaf,
.get = netem_get,
.put = netem_put,
.walk = netem_walk,
.dump = netem_dump_class,
};
static struct Qdisc_ops netem_qdisc_ops __read_mostly = { static struct Qdisc_ops netem_qdisc_ops __read_mostly = {
.id = "netem", .id = "netem",
.cl_ops = &netem_class_ops,
.priv_size = sizeof(struct netem_sched_data), .priv_size = sizeof(struct netem_sched_data),
.enqueue = netem_enqueue, .enqueue = netem_enqueue,
.dequeue = netem_dequeue, .dequeue = netem_dequeue,
......
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