]> err.no Git - linux-2.6/blobdiff - net/sched/sch_sfq.c
pkt_sched: ERR_PTR() ususally encodes an negative errno, not positive.
[linux-2.6] / net / sched / sch_sfq.c
index d818d1985cca4cfb7ee69235ce4aed9372f2ad31..f0463d757a98489f5b12138c0026d1b91742fd9d 100644 (file)
@@ -521,7 +521,8 @@ static void sfq_destroy(struct Qdisc *sch)
        struct sfq_sched_data *q = qdisc_priv(sch);
 
        tcf_destroy_chain(q->filter_list);
-       del_timer(&q->perturb_timer);
+       q->perturb_period = 0;
+       del_timer_sync(&q->perturb_timer);
 }
 
 static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
@@ -566,15 +567,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,
 };