#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/system.h>
-#include <linux/bitops.h>
+#include <asm/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
long avgidle;
long deficit; /* Saved deficit for WRR */
unsigned long penalized;
- struct gnet_stats_basic bstats;
- struct gnet_stats_queue qstats;
- struct gnet_stats_rate_est rate_est;
+ struct tc_stats stats;
spinlock_t *stats_lock;
struct tc_cbq_xstats xstats;
#endif
if ((ret = cl->q->enqueue(skb, cl->q)) == NET_XMIT_SUCCESS) {
sch->q.qlen++;
- sch->bstats.packets++;
- sch->bstats.bytes+=len;
+ sch->stats.packets++;
+ sch->stats.bytes+=len;
cbq_mark_toplevel(q, cl);
if (!cl->next_alive)
cbq_activate_class(cl);
}
#ifndef CONFIG_NET_CLS_ACT
- sch->qstats.drops++;
+ sch->stats.drops++;
if (cl == NULL)
kfree_skb(skb);
else {
cbq_mark_toplevel(q, cl);
- cl->qstats.drops++;
+ cl->stats.drops++;
}
#else
if ( NET_XMIT_DROP == ret) {
- sch->qstats.drops++;
+ sch->stats.drops++;
}
if (cl != NULL) {
cbq_mark_toplevel(q, cl);
- cl->qstats.drops++;
+ cl->stats.drops++;
}
#endif
return ret;
if ((cl = q->tx_class) == NULL) {
kfree_skb(skb);
- sch->qstats.drops++;
+ sch->stats.drops++;
return NET_XMIT_CN;
}
q->tx_class = NULL;
#endif
if ((ret = cl->q->ops->requeue(skb, cl->q)) == 0) {
sch->q.qlen++;
- sch->qstats.requeues++;
if (!cl->next_alive)
cbq_activate_class(cl);
return 0;
}
- sch->qstats.drops++;
- cl->qstats.drops++;
+ sch->stats.drops++;
+ cl->stats.drops++;
return ret;
}
if (cl->q->enqueue(skb, cl->q) == 0) {
sch->q.qlen++;
- sch->bstats.packets++;
- sch->bstats.bytes+=len;
+ sch->stats.packets++;
+ sch->stats.bytes+=len;
if (!cl->next_alive)
cbq_activate_class(cl);
return 0;
}
- sch->qstats.drops++;
+ sch->stats.drops++;
return 0;
}
- sch->qstats.drops++;
+ sch->stats.drops++;
return -1;
}
#endif
long avgidle = cl->avgidle;
long idle;
- cl->bstats.packets++;
- cl->bstats.bytes += len;
+ cl->stats.packets++;
+ cl->stats.bytes += len;
/*
(now - last) is total time between packet right edges.
no another solution exists.
*/
if ((cl = cl->borrow) == NULL) {
- this_cl->qstats.overlimits++;
+ this_cl->stats.overlimits++;
this_cl->overlimit(this_cl);
return NULL;
}
Sigh... start watchdog timer in the last case. */
if (sch->q.qlen) {
- sch->qstats.overlimits++;
+ sch->stats.overlimits++;
if (q->wd_expires) {
long delay = PSCHED_US2JIFFIE(q->wd_expires);
if (delay <= 0)
return 0;
}
+int cbq_copy_xstats(struct sk_buff *skb, struct tc_cbq_xstats *st)
+{
+ RTA_PUT(skb, TCA_XSTATS, sizeof(*st), st);
+ return 0;
+
+rtattr_failure:
+ return -1;
+}
+
+
static int cbq_dump(struct Qdisc *sch, struct sk_buff *skb)
{
struct cbq_sched_data *q = qdisc_priv(sch);
if (cbq_dump_attr(skb, &q->link) < 0)
goto rtattr_failure;
rta->rta_len = skb->tail - b;
+ spin_lock_bh(&sch->dev->queue_lock);
+ q->link.xstats.avgidle = q->link.avgidle;
+ if (cbq_copy_xstats(skb, &q->link.xstats)) {
+ spin_unlock_bh(&sch->dev->queue_lock);
+ goto rtattr_failure;
+ }
+ spin_unlock_bh(&sch->dev->queue_lock);
return skb->len;
rtattr_failure:
return -1;
}
-static int
-cbq_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
-{
- struct cbq_sched_data *q = qdisc_priv(sch);
-
- q->link.xstats.avgidle = q->link.avgidle;
- return gnet_stats_copy_app(d, &q->link.xstats, sizeof(q->link.xstats));
-}
-
static int
cbq_dump_class(struct Qdisc *sch, unsigned long arg,
struct sk_buff *skb, struct tcmsg *tcm)
{
+ struct cbq_sched_data *q = qdisc_priv(sch);
struct cbq_class *cl = (struct cbq_class*)arg;
unsigned char *b = skb->tail;
struct rtattr *rta;
if (cbq_dump_attr(skb, cl) < 0)
goto rtattr_failure;
rta->rta_len = skb->tail - b;
- return skb->len;
-
-rtattr_failure:
- skb_trim(skb, b - skb->data);
- return -1;
-}
-
-static int
-cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
- struct gnet_dump *d)
-{
- struct cbq_sched_data *q = qdisc_priv(sch);
- struct cbq_class *cl = (struct cbq_class*)arg;
-
- cl->qstats.qlen = cl->q->q.qlen;
+ cl->stats.qlen = cl->q->q.qlen;
+ if (qdisc_copy_stats(skb, &cl->stats, cl->stats_lock))
+ goto rtattr_failure;
+ spin_lock_bh(&sch->dev->queue_lock);
cl->xstats.avgidle = cl->avgidle;
cl->xstats.undertime = 0;
-
if (!PSCHED_IS_PASTPERFECT(cl->undertime))
cl->xstats.undertime = PSCHED_TDIFF(cl->undertime, q->now);
+ if (cbq_copy_xstats(skb, &cl->xstats)) {
+ spin_unlock_bh(&sch->dev->queue_lock);
+ goto rtattr_failure;
+ }
+ spin_unlock_bh(&sch->dev->queue_lock);
- if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
- gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
-#endif
- gnet_stats_copy_queue(d, &cl->qstats) < 0)
- return -1;
+ return skb->len;
- return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
}
static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
{
struct cbq_sched_data *q = qdisc_priv(sch);
- BUG_TRAP(!cl->filters);
-
cbq_destroy_filters(cl);
qdisc_destroy(cl->q);
qdisc_put_rtab(cl->R_tab);
#ifdef CONFIG_NET_ESTIMATOR
- gen_kill_estimator(&cl->bstats, &cl->rate_est);
+ qdisc_kill_estimator(&cl->stats);
#endif
if (cl != &q->link)
kfree(cl);
#ifdef CONFIG_NET_CLS_POLICE
q->rx_class = NULL;
#endif
- /*
- * Filters must be destroyed first because we don't destroy the
- * classes from root to leafs which means that filters can still
- * be bound to classes which have been destroyed already. --TGR '04
- */
- for (h = 0; h < 16; h++)
- for (cl = q->classes[h]; cl; cl = cl->next)
- cbq_destroy_filters(cl);
for (h = 0; h < 16; h++) {
struct cbq_class *next;
sch_tree_unlock(sch);
#ifdef CONFIG_NET_ESTIMATOR
- if (tca[TCA_RATE-1])
- gen_replace_estimator(&cl->bstats, &cl->rate_est,
- cl->stats_lock, tca[TCA_RATE-1]);
+ if (tca[TCA_RATE-1]) {
+ qdisc_kill_estimator(&cl->stats);
+ qdisc_new_estimator(&cl->stats, cl->stats_lock,
+ tca[TCA_RATE-1]);
+ }
#endif
return 0;
}
#ifdef CONFIG_NET_ESTIMATOR
if (tca[TCA_RATE-1])
- gen_new_estimator(&cl->bstats, &cl->rate_est,
- cl->stats_lock, tca[TCA_RATE-1]);
+ qdisc_new_estimator(&cl->stats, cl->stats_lock,
+ tca[TCA_RATE-1]);
#endif
*arg = (unsigned long)cl;
.bind_tcf = cbq_bind_filter,
.unbind_tcf = cbq_unbind_filter,
.dump = cbq_dump_class,
- .dump_stats = cbq_dump_class_stats,
};
static struct Qdisc_ops cbq_qdisc_ops = {
.destroy = cbq_destroy,
.change = NULL,
.dump = cbq_dump,
- .dump_stats = cbq_dump_stats,
.owner = THIS_MODULE,
};