Russell Stuart
2006-Jun-15 09:01 UTC
[PATCH 1/2] Runtime configuration of HTB''s HYSTERESIS option (kernel)
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 <russell-tcatm@stuart.id.au>
Signed-off-by: Jesper Dangaard Brouer <hawk@comx.dk>
---
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;
