#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/socket.h>
=======================================
Sources: [1] Sally Floyd and Van Jacobson, "Link-sharing and Resource
- Management Models for Packet Networks",
+ Management Models for Packet Networks",
IEEE/ACM Transactions on Networking, Vol.3, No.4, 1995
- [2] Sally Floyd, "Notes on CBQ and Guaranteed Service", 1995
+ [2] Sally Floyd, "Notes on CBQ and Guaranteed Service", 1995
- [3] Sally Floyd, "Notes on Class-Based Queueing: Setting
+ [3] Sally Floyd, "Notes on Class-Based Queueing: Setting
Parameters", 1996
[4] Sally Floyd and Michael Speer, "Experimental Results
the implementation is different. Particularly:
--- The WRR algorithm is different. Our version looks more
- reasonable (I hope) and works when quanta are allowed to be
- less than MTU, which is always the case when real time classes
- have small rates. Note, that the statement of [3] is
- incomplete, delay may actually be estimated even if class
- per-round allotment is less than MTU. Namely, if per-round
- allotment is W*r_i, and r_1+...+r_k = r < 1
+ reasonable (I hope) and works when quanta are allowed to be
+ less than MTU, which is always the case when real time classes
+ have small rates. Note, that the statement of [3] is
+ incomplete, delay may actually be estimated even if class
+ per-round allotment is less than MTU. Namely, if per-round
+ allotment is W*r_i, and r_1+...+r_k = r < 1
delay_i <= ([MTU/(W*r_i)]*W*r + W*r + k*MTU)/B
unsigned pmask;
struct timer_list delay_timer;
- struct timer_list wd_timer; /* Watchdog timer,
+ struct qdisc_watchdog watchdog; /* Watchdog timer,
started when CBQ has
backlog, but cannot
transmit just now */
- long wd_expires;
+ psched_tdiff_t wd_expires;
int toplevel;
u32 hgenerator;
};
#ifdef CONFIG_NET_CLS_ACT
switch (result) {
case TC_ACT_QUEUED:
- case TC_ACT_STOLEN:
+ case TC_ACT_STOLEN:
*qerr = NET_XMIT_SUCCESS;
case TC_ACT_SHOT:
return NULL;
if (!cl->delayed) {
delay += cl->offtime;
- /*
+ /*
Class goes to sleep, so that it will have no
chance to work avgidle. Let's forgive it 8)
cbq_ovl_classic(cl);
}
-static void cbq_watchdog(unsigned long arg)
-{
- struct Qdisc *sch = (struct Qdisc*)arg;
-
- sch->flags &= ~TCQ_F_THROTTLED;
- netif_schedule(sch->dev);
-}
-
static unsigned long cbq_undelay_prio(struct cbq_sched_data *q, int prio)
{
struct cbq_class *cl;
unsigned long sched = now;
if (cl_prev == NULL)
- return now;
+ return 0;
do {
cl = cl_prev->next_alive;
}
#endif
-/*
+/*
It is mission critical procedure.
We "regenerate" toplevel cutoff, if transmitting class
}
} while ((borrowed=borrowed->borrow) != NULL);
}
-#if 0
+#if 0
/* It is not necessary now. Uncommenting it
will save CPU cycles, but decrease fairness.
*/
(now - last) is total time between packet right edges.
(last_pktlen/rate) is "virtual" busy time, so that
- idle = (now - last) - last_pktlen/rate
+ idle = (now - last) - last_pktlen/rate
*/
idle = PSCHED_TDIFF(q->now, cl->last);
skb = cl->q->dequeue(cl->q);
/* Class did not give us any skb :-(
- It could occur even if cl->q->q.qlen != 0
+ It could occur even if cl->q->q.qlen != 0
f.e. if cl->q == "tbf"
*/
if (skb == NULL)
if (sch->q.qlen) {
sch->qstats.overlimits++;
- if (q->wd_expires) {
- long delay = PSCHED_US2JIFFIE(q->wd_expires);
- if (delay <= 0)
- delay = 1;
- mod_timer(&q->wd_timer, jiffies + delay);
- sch->flags |= TCQ_F_THROTTLED;
- }
+ if (q->wd_expires)
+ qdisc_watchdog_schedule(&q->watchdog,
+ q->now + q->wd_expires);
}
return NULL;
}
q->pmask = 0;
q->tx_class = NULL;
q->tx_borrowed = NULL;
- del_timer(&q->wd_timer);
+ qdisc_watchdog_cancel(&q->watchdog);
del_timer(&q->delay_timer);
q->toplevel = TC_CBQ_MAXLEVEL;
PSCHED_GET_TIME(q->now);
q->link.minidle = -0x7FFFFFFF;
q->link.stats_lock = &sch->dev->queue_lock;
- init_timer(&q->wd_timer);
- q->wd_timer.data = (unsigned long)sch;
- q->wd_timer.function = cbq_watchdog;
+ qdisc_watchdog_init(&q->watchdog, sch);
init_timer(&q->delay_timer);
q->delay_timer.data = (unsigned long)sch;
q->delay_timer.function = cbq_undelay;
{
return register_qdisc(&cbq_qdisc_ops);
}
-static void __exit cbq_module_exit(void)
+static void __exit cbq_module_exit(void)
{
unregister_qdisc(&cbq_qdisc_ops);
}