The HTB qdisc has a compile time option, HTB_HYSTERESIS, 
that trades accuracy of traffic classification for CPU 
time.  These patches change hysteresis to be a runtime 
option under the control of "tc".

The effects of HYSTERESIS on HTB's accuracy are significant 
(see chapter 7, section 7.3.1, pp 69-70 in Jesper Brouer's
thesis: http://www.adsl-optimizer.dk/thesis/ ), whereas 
HTB's CPU usage on modern machines using broadband links 
is minimal.  Currently HYSTERESIS is on by default, and 
requires a kernel re-compile to change.  Altering it to 
be a runtime option will make life easier for the bulk of 
its users.

Further documentation on the patch and its usage can be
found here:
  http://www.stuart.id.au/russell/files/tc/tc-atm

Signed-off-by: Russell Stuart <[EMAIL PROTECTED]>
Signed-off-by: Jesper Dangaard Brouer <[EMAIL PROTECTED]>
---

diff -Nurp kernel-source-2.6.11.orig/include/linux/pkt_sched.h 
kernel-source-2.6.11/include/linux/pkt_sched.h
--- kernel-source-2.6.11.orig/include/linux/pkt_sched.h 2005-03-02 
17:38:13.000000000 +1000
+++ kernel-source-2.6.11/include/linux/pkt_sched.h      2006-06-13 
11:34:25.000000000 +1000
@@ -231,6 +231,10 @@ struct tc_gred_sopt
 #define TC_HTB_MAXDEPTH                8
 #define TC_HTB_PROTOVER                3 /* the same as HTB and TC's major */
 
+struct tc_htb_hopt
+{
+       __u32   nohyst;
+};
 struct tc_htb_opt
 {
        struct tc_ratespec      rate;
@@ -258,6 +262,7 @@ enum
        TCA_HTB_INIT,
        TCA_HTB_CTAB,
        TCA_HTB_RTAB,
+       TCA_HTB_NOHYST,
        __TCA_HTB_MAX,
 };
 
diff -Nurp kernel-source-2.6.11.orig/net/sched/sch_htb.c 
kernel-source-2.6.11/net/sched/sch_htb.c
--- kernel-source-2.6.11.orig/net/sched/sch_htb.c       2005-03-02 
17:38:12.000000000 +1000
+++ kernel-source-2.6.11/net/sched/sch_htb.c    2006-06-13 11:34:25.000000000 
+1000
@@ -73,7 +73,6 @@
 #define HTB_EWMAC 2    /* rate average over HTB_EWMAC*HTB_HSIZE sec */
 #undef HTB_DEBUG       /* compile debugging support (activated by tc tool) */
 #define HTB_RATECM 1    /* whether to use rate computer */
-#define HTB_HYSTERESIS 1/* whether to use mode hysteresis for speedup */
 #define HTB_QLOCK(S) spin_lock_bh(&(S)->dev->queue_lock)
 #define HTB_QUNLOCK(S) spin_unlock_bh(&(S)->dev->queue_lock)
 #define HTB_VER 0x30011        /* major must be matched with number suplied by 
TC as version */
@@ -190,6 +189,7 @@ struct htb_class
     /* class attached filters */
     struct tcf_proto *filter_list;
     int filter_cnt;
+    int nohyst;                /* Don't use hysteresis htb_class_mode */
 
     int warned;                /* only one warning about non work conserving 
.. */
 
@@ -622,20 +622,14 @@ static __inline__ enum htb_cmode 
 htb_class_mode(struct htb_class *cl,long *diff)
 {
     long toks;
+    long hysteresis =
+           (cl->nohyst || cl->cmode == HTB_CANT_SEND) ? 0 : -cl->cbuffer;
 
-    if ((toks = (cl->ctokens + *diff)) < (
-#if HTB_HYSTERESIS
-           cl->cmode != HTB_CANT_SEND ? -cl->cbuffer :
-#endif
-                   0)) {
+    if ((toks = (cl->ctokens + *diff)) < hysteresis) {
            *diff = -toks;
            return HTB_CANT_SEND;
     }
-    if ((toks = (cl->tokens + *diff)) >= (
-#if HTB_HYSTERESIS
-           cl->cmode == HTB_CAN_SEND ? -cl->buffer :
-#endif
-           0))
+    if ((toks = (cl->tokens + *diff)) >= hysteresis)
            return HTB_CAN_SEND;
 
     *diff = -toks;
@@ -1323,6 +1317,7 @@ static int htb_dump_class(struct Qdisc *
        unsigned char    *b = skb->tail;
        struct rtattr *rta;
        struct tc_htb_opt opt;
+       struct tc_htb_hopt hopt;
 
        HTB_DBG(0,1,"htb_dump_class handle=%X 
clid=%X\n",sch->handle,cl->classid);
 
@@ -1342,6 +1337,8 @@ static int htb_dump_class(struct Qdisc *
        opt.quantum = cl->un.leaf.quantum; opt.prio = cl->un.leaf.prio;
        opt.level = cl->level; 
        RTA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
+       hopt.nohyst = cl->nohyst;
+       RTA_PUT(skb, TCA_HTB_NOHYST, sizeof(hopt), &hopt);
        rta->rta_len = skb->tail - b;
        HTB_QUNLOCK(sch);
        return skb->len;
@@ -1527,11 +1524,12 @@ static int htb_change_class(struct Qdisc
        struct htb_class *cl = (struct htb_class*)*arg,*parent;
        struct rtattr *opt = tca[TCA_OPTIONS-1];
        struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
-       struct rtattr *tb[TCA_HTB_RTAB];
+       struct rtattr *tb[TCA_HTB_MAX];
        struct tc_htb_opt *hopt;
+       struct tc_htb_hopt *uhopt;
 
        /* extract all subattrs from opt attr */
-       if (!opt || rtattr_parse_nested(tb, TCA_HTB_RTAB, opt) ||
+       if (!opt || rtattr_parse_nested(tb, TCA_HTB_MAX, opt) ||
                        tb[TCA_HTB_PARMS-1] == NULL ||
                        RTA_PAYLOAD(tb[TCA_HTB_PARMS-1]) < sizeof(*hopt))
                goto failure;
@@ -1544,6 +1542,10 @@ static int htb_change_class(struct Qdisc
        ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB-1]);
        if (!rtab || !ctab) goto failure;
 
+       uhopt = RTA_DATA(tb[TCA_HTB_NOHYST-1]);
+       if (uhopt != NULL && RTA_PAYLOAD(tb[TCA_HTB_NOHYST-1]) < sizeof(*uhopt))
+               goto failure;
+
        if (!cl) { /* new class */
                struct Qdisc *new_q;
                /* check for valid classid */
@@ -1636,6 +1638,7 @@ static int htb_change_class(struct Qdisc
        cl->cbuffer = hopt->cbuffer;
        if (cl->rate) qdisc_put_rtab(cl->rate); cl->rate = rtab;
        if (cl->ceil) qdisc_put_rtab(cl->ceil); cl->ceil = ctab;
+       if (uhopt) cl->nohyst = uhopt->nohyst;
        sch_tree_unlock(sch);
 
        *arg = (unsigned long)cl;



Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to