* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
+ * 2 of the License.
*
* Many of the algorithms and ideas for this came from
- * NIST Net which is not copyrighted.
+ * NIST Net which is not copyrighted.
*
* Authors: Stephen Hemminger <shemminger@osdl.org>
* Catalin(ux aka Dino) BOIE <catab at umbrella dot ro>
* std deviation sigma. Uses table lookup to approximate the desired
* distribution, and a uniformly-distributed pseudo-random source.
*/
-static long tabledist(unsigned long mu, long sigma,
+static long tabledist(unsigned long mu, long sigma,
struct crndstate *state, const struct disttable *dist)
{
long t, x;
rnd = get_crandom(state);
/* default uniform distribution */
- if (dist == NULL)
+ if (dist == NULL)
return (rnd % (2*sigma)) - sigma + mu;
t = dist->table[rnd % dist->size];
return NET_XMIT_BYPASS;
}
+ skb_orphan(skb);
+
/*
* If we need to duplicate packet, then re-insert at top of the
* qdisc tree, since parent queuer expects that only one
++q->counter;
ret = q->qdisc->enqueue(skb, q->qdisc);
} else {
- /*
+ /*
* Do re-ordering by putting one out of N packets at the front
* of the queue.
*/
psched_tdiff_t delay = PSCHED_TDIFF(cb->time_to_send, now);
if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
+ qdisc_tree_decrease_qlen(q->qdisc, 1);
sch->qstats.drops++;
-
- /* After this qlen is confused */
printk(KERN_ERR "netem: queue discpline %s could not requeue\n",
q->qdisc->ops->id);
-
- sch->q.qlen--;
}
mod_timer(&q->timer, jiffies + PSCHED_US2JIFFIE(delay));
/* Pass size change message down to embedded FIFO */
static int set_fifo_limit(struct Qdisc *q, int limit)
{
- struct rtattr *rta;
+ struct rtattr *rta;
int ret = -ENOMEM;
/* Hack to avoid sending change message to non-FIFO */
rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
if (rta) {
rta->rta_type = RTM_NEWQDISC;
- rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt));
+ rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt));
((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit;
-
+
ret = q->ops->change(q, rta);
kfree(rta);
}
d->size = n;
for (i = 0; i < n; i++)
d->table[i] = data[i];
-
+
spin_lock_bh(&sch->dev->queue_lock);
d = xchg(&q->delay_dist, d);
spin_unlock_bh(&sch->dev->queue_lock);
struct netem_sched_data *q = qdisc_priv(sch);
struct tc_netem_qopt *qopt;
int ret;
-
+
if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
return -EINVAL;
pr_debug("netem: can't set fifo limit\n");
return ret;
}
-
+
q->latency = qopt->latency;
q->jitter = qopt->jitter;
q->limit = qopt->limit;
/* Handle nested options after initial queue options.
* Should have put all options in nested format but too late now.
- */
+ */
if (RTA_PAYLOAD(opt) > sizeof(*qopt)) {
struct rtattr *tb[TCA_NETEM_MAX];
- if (rtattr_parse(tb, TCA_NETEM_MAX,
+ if (rtattr_parse(tb, TCA_NETEM_MAX,
RTA_DATA(opt) + sizeof(*qopt),
RTA_PAYLOAD(opt) - sizeof(*qopt)))
return -EINVAL;
q->timer.function = netem_watchdog;
q->timer.data = (unsigned long) sch;
- q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops);
+ q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops,
+ TC_H_MAKE(sch->handle, 1));
if (!q->qdisc) {
pr_debug("netem: qdisc create failed\n");
return -ENOMEM;
sch_tree_lock(sch);
*old = xchg(&q->qdisc, new);
+ qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
qdisc_reset(*old);
- sch->q.qlen = 0;
sch_tree_unlock(sch);
return 0;
{
}
-static int netem_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
+static int netem_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
struct rtattr **tca, unsigned long *arg)
{
return -ENOSYS;