*/
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
do { \
struct timeval tv; \
do_gettimeofday(&tv); \
- (stamp) = 1000000ULL * tv.tv_sec + tv.tv_usec; \
+ (stamp) = 1ULL * USEC_PER_SEC * tv.tv_sec + tv.tv_usec; \
} while (0)
#endif
u64 dx;
dx = ((u64)d * PSCHED_JIFFIE2US(HZ));
- dx += 1000000 - 1;
- do_div(dx, 1000000);
+ dx += USEC_PER_SEC - 1;
+ do_div(dx, USEC_PER_SEC);
return dx;
}
{
u64 d;
- d = dx * 1000000;
+ d = dx * USEC_PER_SEC;
do_div(d, PSCHED_JIFFIE2US(HZ));
return (u32)d;
}
if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) {
if (net_ratelimit())
printk("qdisc_peek_len: failed to requeue\n");
+ qdisc_tree_decrease_qlen(sch, 1);
return 0;
}
return len;
unsigned int len = cl->qdisc->q.qlen;
qdisc_reset(cl->qdisc);
- if (len > 0) {
- update_vf(cl, 0, 0);
- set_passive(cl);
- sch->q.qlen -= len;
- }
+ qdisc_tree_decrease_qlen(cl->qdisc, len);
}
static void
do {
level = 0;
list_for_each_entry(p, &cl->children, siblings) {
- if (p->level > level)
- level = p->level;
+ if (p->level >= level)
+ level = p->level + 1;
}
- cl->level = level + 1;
+ cl->level = level;
} while ((cl = cl->cl_parent) != NULL);
}
struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL;
u64 cur_time;
- if (opt == NULL ||
- rtattr_parse(tb, TCA_HFSC_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)))
+ if (opt == NULL || rtattr_parse_nested(tb, TCA_HFSC_MAX, opt))
return -EINVAL;
if (tb[TCA_HFSC_RSC-1]) {
if (rsc == NULL && fsc == NULL)
return -EINVAL;
- cl = kmalloc(sizeof(struct hfsc_class), GFP_KERNEL);
+ cl = kzalloc(sizeof(struct hfsc_class), GFP_KERNEL);
if (cl == NULL)
return -ENOBUFS;
- memset(cl, 0, sizeof(struct hfsc_class));
if (rsc != NULL)
hfsc_change_rsc(cl, rsc, 0);
cl->classid = classid;
cl->sched = q;
cl->cl_parent = parent;
- cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
if (cl->qdisc == NULL)
cl->qdisc = &noop_qdisc;
cl->stats_lock = &sch->dev->queue_lock;
}
static struct hfsc_class *
-hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qres)
+hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
{
struct hfsc_sched *q = qdisc_priv(sch);
struct hfsc_class *cl;
if (cl->level == 0)
return cl;
+ *qerr = NET_XMIT_BYPASS;
tcf = q->root.filter_list;
while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
#ifdef CONFIG_NET_CLS_ACT
- int terminal = 0;
switch (result) {
- case TC_ACT_SHOT:
- *qres = NET_XMIT_DROP;
- terminal = 1;
- break;
case TC_ACT_QUEUED:
case TC_ACT_STOLEN:
- terminal = 1;
- break;
- case TC_ACT_RECLASSIFY:
- case TC_ACT_OK:
- case TC_ACT_UNSPEC:
- default:
- break;
- }
-
- if (terminal) {
- kfree_skb(skb);
+ *qerr = NET_XMIT_SUCCESS;
+ case TC_ACT_SHOT:
return NULL;
}
-#else
-#ifdef CONFIG_NET_CLS_POLICE
+#elif defined(CONFIG_NET_CLS_POLICE)
if (result == TC_POLICE_SHOT)
return NULL;
-#endif
#endif
if ((cl = (struct hfsc_class *)res.class) == NULL) {
if ((cl = hfsc_find_class(res.classid, sch)) == NULL)
if (cl->level > 0)
return -EINVAL;
if (new == NULL) {
- new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+ cl->classid);
if (new == NULL)
new = &noop_qdisc;
}
return NULL;
}
+static void
+hfsc_qlen_notify(struct Qdisc *sch, unsigned long arg)
+{
+ struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+ if (cl->qdisc->q.qlen == 0) {
+ update_vf(cl, 0, 0);
+ set_passive(cl);
+ }
+}
+
static unsigned long
hfsc_get_class(struct Qdisc *sch, u32 classid)
{
q->root.refcnt = 1;
q->root.classid = sch->handle;
q->root.sched = q;
- q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+ sch->handle);
if (q->root.qdisc == NULL)
q->root.qdisc = &noop_qdisc;
q->root.stats_lock = &sch->dev->queue_lock;
static int
hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
- int ret = NET_XMIT_SUCCESS;
- struct hfsc_class *cl = hfsc_classify(skb, sch, &ret);
- unsigned int len = skb->len;
+ struct hfsc_class *cl;
+ unsigned int len;
int err;
-
-#ifdef CONFIG_NET_CLS_ACT
+ cl = hfsc_classify(skb, sch, &err);
if (cl == NULL) {
- if (NET_XMIT_DROP == ret) {
+ if (err == NET_XMIT_BYPASS)
sch->qstats.drops++;
- }
- return ret;
- }
-#else
- if (cl == NULL) {
kfree_skb(skb);
- sch->qstats.drops++;
- return NET_XMIT_DROP;
+ return err;
}
-#endif
+ len = skb->len;
err = cl->qdisc->enqueue(skb, cl->qdisc);
if (unlikely(err != NET_XMIT_SUCCESS)) {
cl->qstats.drops++;
.delete = hfsc_delete_class,
.graft = hfsc_graft_class,
.leaf = hfsc_class_leaf,
+ .qlen_notify = hfsc_qlen_notify,
.get = hfsc_get_class,
.put = hfsc_put_class,
.bind_tcf = hfsc_bind_tcf,