From: Patrick McHardy Date: Fri, 1 Feb 2008 02:37:16 +0000 (-0800) Subject: [NET_SCHED]: sch_sfq: make internal queues visible as classes X-Git-Tag: v2.6.25-rc1~1089^2~8 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=94de78d19580143c407ff2492edf2410d0e7d48c;p=linux-2.6 [NET_SCHED]: sch_sfq: make internal queues visible as classes Add support for dumping statistics and make internal queues visible as classes. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 32761352e8..dbb7ac3796 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -150,6 +150,11 @@ struct tc_sfq_qopt unsigned flows; /* Maximal number of flows */ }; +struct tc_sfq_xstats +{ + __s32 allot; +}; + /* * NOTE: limit, divisor and flows are hardwired to code at the moment. * diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index d818d1985c..a20e2ef770 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -566,15 +566,54 @@ static struct tcf_proto **sfq_find_tcf(struct Qdisc *sch, unsigned long cl) return &q->filter_list; } +static int sfq_dump_class(struct Qdisc *sch, unsigned long cl, + struct sk_buff *skb, struct tcmsg *tcm) +{ + tcm->tcm_handle |= TC_H_MIN(cl); + return 0; +} + +static int sfq_dump_class_stats(struct Qdisc *sch, unsigned long cl, + struct gnet_dump *d) +{ + struct sfq_sched_data *q = qdisc_priv(sch); + sfq_index idx = q->ht[cl-1]; + struct gnet_stats_queue qs = { .qlen = q->qs[idx].qlen }; + struct tc_sfq_xstats xstats = { .allot = q->allot[idx] }; + + if (gnet_stats_copy_queue(d, &qs) < 0) + return -1; + return gnet_stats_copy_app(d, &xstats, sizeof(xstats)); +} + static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg) { - return; + struct sfq_sched_data *q = qdisc_priv(sch); + unsigned int i; + + if (arg->stop) + return; + + for (i = 0; i < SFQ_HASH_DIVISOR; i++) { + if (q->ht[i] == SFQ_DEPTH || + arg->count < arg->skip) { + arg->count++; + continue; + } + if (arg->fn(sch, i + 1, arg) < 0) { + arg->stop = 1; + break; + } + arg->count++; + } } static const struct Qdisc_class_ops sfq_class_ops = { .get = sfq_get, .change = sfq_change_class, .tcf_chain = sfq_find_tcf, + .dump = sfq_dump_class, + .dump_stats = sfq_dump_class_stats, .walk = sfq_walk, };