1 diff -urN linux-2.4.20/net/sched/sch_htb.c linux-2.4.21/net/sched/sch_htb.c
2 --- linux-2.4.20/net/sched/sch_htb.c Fri Nov 29 00:53:16 2002
3 +++ linux-2.4.21/net/sched/sch_htb.c Fri Jun 13 16:51:39 2003
5 * created test case so that I was able to fix nasty bug
6 * and many others. thanks.
11 #include <linux/config.h>
12 #include <linux/module.h>
14 #define HTB_HYSTERESIS 1/* whether to use mode hysteresis for speedup */
15 #define HTB_QLOCK(S) spin_lock_bh(&(S)->dev->queue_lock)
16 #define HTB_QUNLOCK(S) spin_unlock_bh(&(S)->dev->queue_lock)
17 -#define HTB_VER 0x30007 /* major must be matched with number suplied by TC as version */
18 +#define HTB_VER 0x3000a /* major must be matched with number suplied by TC as version */
20 #if HTB_VER >> 16 != TC_HTB_PROTOVER
21 #error "Mismatched sch_htb.c and pkt_sch.h"
24 -/* temporary debug defines to be removed after beta stage */
25 -#define DEVIK_MEND(N)
26 -#define DEVIK_MSTART(N)
28 /* debugging support; S is subsystem, these are defined:
33 #define HTB_ARGQ struct htb_sched *q,
39 #define HTB_CMAGIC 0xFEFAFEF1
40 #define htb_safe_rb_erase(N,R) do { BUG_TRAP((N)->rb_color != -1); \
42 if ((delay <= 0 || delay > cl->mbuffer) && net_ratelimit())
43 printk(KERN_ERR "HTB: suspicious delay in wait_tree d=%ld cl=%X h=%d\n",delay,cl->classid,debug_hint);
46 cl->pq_key = jiffies + PSCHED_US2JIFFIE(delay);
47 if (cl->pq_key == jiffies)
51 rb_link_node(&cl->pq_node, parent, p);
52 rb_insert_color(&cl->pq_node, &q->wait_pq[cl->level]);
58 struct htb_sched *q = (struct htb_sched *)sch->data;
59 struct htb_class *cl = htb_classify(skb,sch);
62 if (cl == HTB_DIRECT || !cl) {
63 /* enqueue to helper queue */
64 if (q->direct_queue.qlen < q->direct_qlen && cl) {
72 } else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) {
78 cl->stats.packets++; cl->stats.bytes += skb->len;
85 sch->stats.packets++; sch->stats.bytes += skb->len;
86 HTB_DBG(1,1,"htb_enq_ok cl=%X skb=%p\n",cl?cl->classid:0,skb);
88 return NET_XMIT_SUCCESS;
92 //struct htb_sched *q = (struct htb_sched *)sch->data;
93 struct htb_class *cl,*start;
94 /* look initial class up in the row */
96 start = cl = htb_lookup_leaf (q->row[level]+prio,prio,q->ptr[level]+prio);
100 cl = htb_lookup_leaf (q->row[level]+prio,prio,q->ptr[level]+prio);
101 } while (cl != start);
105 if (likely(skb != NULL)) {
106 if ((cl->un.leaf.deficit[level] -= skb->len) < 0) {
107 HTB_DBG(4,2,"htb_next_cl oldptr=%p quant_add=%d\n",
109 gives us slightly better performance */
110 if (!cl->un.leaf.q->q.qlen)
111 htb_deactivate (q,cl);
113 htb_charge_class (q,cl,level,skb->len);
120 @@ -1016,6 +1000,9 @@
121 struct htb_sched *q = (struct htb_sched *)sch->data;
128 HTB_DBG(3,1,"htb_deq dircnt=%d qlen=%d\n",skb_queue_len(&q->direct_queue),
130 @@ -1027,27 +1014,26 @@
135 if (!sch->q.qlen) goto fin;
136 PSCHED_GET_TIME(q->now);
139 + min_delay = LONG_MAX;
141 for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
142 /* common case optimization - skip event handler quickly */
146 if (jiffies - q->near_ev_cache[level] < 0x80000000 || 0) {
147 delay = htb_do_events(q,level);
148 q->near_ev_cache[level] += delay ? delay : HZ;
153 delay = q->near_ev_cache[level] - jiffies;
155 if (delay && min_delay > delay)
159 m = ~q->row_mask[level];
160 while (m != (int)(-1)) {
162 @@ -1056,24 +1042,24 @@
163 if (likely(skb != NULL)) {
165 sch->flags &= ~TCQ_F_THROTTLED;
174 - if (!q->nwc_hit && min_delay >= 5*HZ && net_ratelimit()) {
175 - printk(KERN_ERR "HTB: mindelay=%ld, report it please !\n",min_delay);
177 + if (!q->nwc_hit && min_delay >= 10*HZ && net_ratelimit()) {
178 + if (min_delay == LONG_MAX) {
179 + printk(KERN_ERR "HTB: dequeue bug (%d), report it please !\n",
183 + printk(KERN_WARNING "HTB: mindelay=%ld, some class has "
184 + "too small rate\n",min_delay);
187 - htb_delay_by (sch,min_delay);
189 + htb_delay_by (sch,min_delay > 5*HZ ? 5*HZ : min_delay);
191 HTB_DBG(3,1,"htb_deq_end %s j=%lu skb=%p\n",sch->dev->name,jiffies,skb);
196 @@ -1444,6 +1430,7 @@
197 if (!rtab || !ctab) goto failure;
199 if (!cl) { /* new class */
200 + struct Qdisc *new_q;
201 /* check for valid classid */
202 if (!classid || TC_H_MAJ(classid^sch->handle) || htb_find(classid,sch))
204 @@ -1467,6 +1454,10 @@
205 cl->magic = HTB_CMAGIC;
208 + /* create leaf qdisc early because it uses kmalloc(GPF_KERNEL)
209 + so that can't be used inside of sch_tree_lock
210 + -- thanks to Karlis Peisenieks */
211 + new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
213 if (parent && !parent->level) {
214 /* turn parent into inner node */
215 @@ -1485,8 +1476,7 @@
216 memset (&parent->un.inner,0,sizeof(parent->un.inner));
218 /* leaf (we) needs elementary qdisc */
219 - if (!(cl->un.leaf.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops)))
220 - cl->un.leaf.q = &noop_qdisc;
221 + cl->un.leaf.q = new_q ? new_q : &noop_qdisc;
223 cl->classid = classid; cl->parent = parent;
225 @@ -1514,11 +1504,11 @@
227 cl->un.leaf.quantum = rtab->rate.rate / q->rate2quantum;
228 if (!hopt->quantum && cl->un.leaf.quantum < 1000) {
229 - printk(KERN_WARNING "HTB: quantum of class %X is small. Consider r2q change.", cl->classid);
230 + printk(KERN_WARNING "HTB: quantum of class %X is small. Consider r2q change.\n", cl->classid);
231 cl->un.leaf.quantum = 1000;
233 if (!hopt->quantum && cl->un.leaf.quantum > 200000) {
234 - printk(KERN_WARNING "HTB: quantum of class %X is big. Consider r2q change.", cl->classid);
235 + printk(KERN_WARNING "HTB: quantum of class %X is big. Consider r2q change.\n", cl->classid);
236 cl->un.leaf.quantum = 200000;