#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>
#endif
/* general class parameters */
u32 classid;
- struct gnet_stats_basic bstats;
- struct gnet_stats_queue qstats;
- struct gnet_stats_rate_est rate_est;
+ struct tc_stats stats; /* generic stats */
+ spinlock_t *stats_lock;
struct tc_htb_xstats xstats;/* our special stats */
int refcnt; /* usage count of this class */
}
} else if (!cl) {
if (NET_XMIT_DROP == ret) {
- sch->qstats.drops++;
+ sch->stats.drops++;
}
return ret;
}
q->direct_pkts++;
} else {
kfree_skb (skb);
- sch->qstats.drops++;
+ sch->stats.drops++;
return NET_XMIT_DROP;
}
}
#endif
else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) {
- sch->qstats.drops++;
- cl->qstats.drops++;
+ sch->stats.drops++;
+ cl->stats.drops++;
return NET_XMIT_DROP;
} else {
- cl->bstats.packets++; cl->bstats.bytes += skb->len;
+ cl->stats.packets++; cl->stats.bytes += skb->len;
htb_activate (q,cl);
}
sch->q.qlen++;
- sch->bstats.packets++; sch->bstats.bytes += skb->len;
+ sch->stats.packets++; sch->stats.bytes += skb->len;
HTB_DBG(1,1,"htb_enq_ok cl=%X skb=%p\n",(cl && cl != HTB_DIRECT)?cl->classid:0,skb);
return NET_XMIT_SUCCESS;
}
__skb_queue_head(&q->direct_queue, skb);
tskb = __skb_dequeue_tail(&q->direct_queue);
kfree_skb (tskb);
- sch->qstats.drops++;
+ sch->stats.drops++;
return NET_XMIT_CN;
}
} else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) {
- sch->qstats.drops++;
- cl->qstats.drops++;
+ sch->stats.drops++;
+ cl->stats.drops++;
return NET_XMIT_DROP;
} else
htb_activate (q,cl);
sch->q.qlen++;
- sch->qstats.requeues++;
HTB_DBG(1,1,"htb_req_ok cl=%X skb=%p\n",(cl && cl != HTB_DIRECT)?cl->classid:0,skb);
return NET_XMIT_SUCCESS;
}
/* update byte stats except for leaves which are already updated */
if (cl->level) {
- cl->bstats.bytes += bytes;
- cl->bstats.packets++;
+ cl->stats.bytes += bytes;
+ cl->stats.packets++;
}
cl = cl->parent;
}
/* why don't use jiffies here ? because expires can be in past */
mod_timer(&q->timer, q->jiffies + delay);
sch->flags |= TCQ_F_THROTTLED;
- sch->qstats.overlimits++;
+ sch->stats.overlimits++;
HTB_DBG(3,1,"htb_deq t_delay=%ld\n",delay);
}
struct rtattr *rta;
struct tc_htb_glob gopt;
HTB_DBG(0,1,"htb_dump sch=%p, handle=%X\n",sch,sch->handle);
+ /* stats */
HTB_QLOCK(sch);
gopt.direct_pkts = q->direct_pkts;
RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
RTA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
rta->rta_len = skb->tail - b;
+ sch->stats.qlen = sch->q.qlen;
+ RTA_PUT(skb, TCA_STATS, sizeof(sch->stats), &sch->stats);
HTB_QUNLOCK(sch);
return skb->len;
rtattr_failure:
HTB_QLOCK(sch);
tcm->tcm_parent = cl->parent ? cl->parent->classid : TC_H_ROOT;
tcm->tcm_handle = cl->classid;
- if (!cl->level && cl->un.leaf.q)
+ if (!cl->level && cl->un.leaf.q) {
tcm->tcm_info = cl->un.leaf.q->handle;
+ cl->stats.qlen = cl->un.leaf.q->q.qlen;
+ }
rta = (struct rtattr*)b;
RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
opt.level = cl->level;
RTA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
rta->rta_len = skb->tail - b;
- HTB_QUNLOCK(sch);
- return skb->len;
-rtattr_failure:
- HTB_QUNLOCK(sch);
- skb_trim(skb, b - skb->data);
- return -1;
-}
-
-static int
-htb_dump_class_stats(struct Qdisc *sch, unsigned long arg,
- struct gnet_dump *d)
-{
- struct htb_class *cl = (struct htb_class*)arg;
#ifdef HTB_RATECM
- cl->rate_est.bps = cl->rate_bytes/(HTB_EWMAC*HTB_HSIZE);
- cl->rate_est.pps = cl->rate_packets/(HTB_EWMAC*HTB_HSIZE);
+ cl->stats.bps = cl->rate_bytes/(HTB_EWMAC*HTB_HSIZE);
+ cl->stats.pps = cl->rate_packets/(HTB_EWMAC*HTB_HSIZE);
#endif
- if (!cl->level && cl->un.leaf.q)
- cl->qstats.qlen = cl->un.leaf.q->q.qlen;
cl->xstats.tokens = cl->tokens;
cl->xstats.ctokens = cl->ctokens;
-
- if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
- gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
- gnet_stats_copy_queue(d, &cl->qstats) < 0)
- return -1;
-
- return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
+ RTA_PUT(skb, TCA_STATS, sizeof(cl->stats), &cl->stats);
+ RTA_PUT(skb, TCA_XSTATS, sizeof(cl->xstats), &cl->xstats);
+ HTB_QUNLOCK(sch);
+ return skb->len;
+rtattr_failure:
+ HTB_QUNLOCK(sch);
+ skb_trim(skb, b - skb->data);
+ return -1;
}
static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
qdisc_put_rtab(cl->rate);
qdisc_put_rtab(cl->ceil);
+#ifdef CONFIG_NET_ESTIMATOR
+ qdisc_kill_estimator(&cl->stats);
+#endif
htb_destroy_filters (&cl->filter_list);
while (!list_empty(&cl->children))
.bind_tcf = htb_bind_filter,
.unbind_tcf = htb_unbind_filter,
.dump = htb_dump_class,
- .dump_stats = htb_dump_class_stats,
};
static struct Qdisc_ops htb_qdisc_ops = {