#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
+#include <net/netlink.h>
#include <net/pkt_sched.h>
#define VERSION "1.2"
struct netem_sched_data {
struct Qdisc *qdisc;
- struct timer_list timer;
+ struct qdisc_watchdog watchdog;
u32 latency;
u32 loss;
sch->flags &= ~TCQ_F_THROTTLED;
return skb;
} else {
- psched_tdiff_t delay = PSCHED_TDIFF(cb->time_to_send, now);
+ qdisc_watchdog_schedule(&q->watchdog, cb->time_to_send);
if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
qdisc_tree_decrease_qlen(q->qdisc, 1);
printk(KERN_ERR "netem: queue discpline %s could not requeue\n",
q->qdisc->ops->id);
}
-
- mod_timer(&q->timer, jiffies + PSCHED_US2JIFFIE(delay));
- sch->flags |= TCQ_F_THROTTLED;
}
}
return NULL;
}
-static void netem_watchdog(unsigned long arg)
-{
- struct Qdisc *sch = (struct Qdisc *)arg;
-
- pr_debug("netem_watchdog qlen=%d\n", sch->q.qlen);
- sch->flags &= ~TCQ_F_THROTTLED;
- netif_schedule(sch->dev);
-}
-
static void netem_reset(struct Qdisc *sch)
{
struct netem_sched_data *q = qdisc_priv(sch);
qdisc_reset(q->qdisc);
sch->q.qlen = 0;
- sch->flags &= ~TCQ_F_THROTTLED;
- del_timer_sync(&q->timer);
+ qdisc_watchdog_cancel(&q->watchdog);
}
/* Pass size change message down to embedded FIFO */
/* for compatiablity with earlier versions.
* if gap is set, need to assume 100% probablity
*/
- q->reorder = ~0;
+ if (q->gap)
+ q->reorder = ~0;
/* Handle nested options after initial queue options.
* Should have put all options in nested format but too late now.
if (!opt)
return -EINVAL;
- init_timer(&q->timer);
- q->timer.function = netem_watchdog;
- q->timer.data = (unsigned long) sch;
+ qdisc_watchdog_init(&q->watchdog, sch);
q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops,
TC_H_MAKE(sch->handle, 1));
{
struct netem_sched_data *q = qdisc_priv(sch);
- del_timer_sync(&q->timer);
+ qdisc_watchdog_cancel(&q->watchdog);
qdisc_destroy(q->qdisc);
kfree(q->delay_dist);
}
static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
{
const struct netem_sched_data *q = qdisc_priv(sch);
- unsigned char *b = skb->tail;
+ unsigned char *b = skb_tail_pointer(skb);
struct rtattr *rta = (struct rtattr *) b;
struct tc_netem_qopt qopt;
struct tc_netem_corr cor;
corrupt.correlation = q->corrupt_cor.rho;
RTA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
- rta->rta_len = skb->tail - b;
+ rta->rta_len = skb_tail_pointer(skb) - b;
return skb->len;
rtattr_failure:
- skb_trim(skb, b - skb->data);
+ nlmsg_trim(skb, b);
return -1;
}