When letting htb calculate the burst sizes, it chooses too small burst sizes, resulting in degraded performance. This is especially true for high rates.
Hello Thomas!
This is something you probably want to bring directly to upstream and discuss
it there....
Some examples would be useful where you can both see which options you used,
what the result was and some additional comments on what you expected to get!
This is from q_htb.c and should hopefully be the relevant code:
/* compute minimal allowed burst from rate; mtu is added here to make
sute that buffer is larger than mtu and to have some safeguard space */
if (!buffer) buffer = opt.rate.rate / get_hz() + mtu;
100mbit, 1:2 below that with a rate and ceil of 90mbit. For this I used the commands: tc qdisc add dev eth0 root handle 1 htb default 2 tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit ceil 100mbit tc class add dev eth0 parent 1:1 classid 1:2 htb rate 90mbit ceil 90mbit For both eth0 and eth1. Without specifying a burst size, tc reports burst and cburst of 1586b for class 1:2. This results in a maximum of ~43300Kb/s download (or upload) speed. This is far from the achievable 90mbit. When using a burst and cburst of 51kb for class 1:1 and 44kb for class 1:2, the speed increases to ~87600Kb/s - much closer to what is expected.
Hi Thomas, I read the htb code before so I'll show the problem here. When tc comes to calculate buffer & cbuffer, it set lookup get_hz() and set buffer = rate / get_hz() + mtu. But nowadays, packet scheduling (sched) in kernel employ hrtimer so that the old limit of activity only HZ (100) times per second is removed. Also get_hz() returns 10^9 so that tc pretend that sched start 10^9 times per second. So buffer would be set to no more than mtu. But hrtimer doesn't work by this way. So every time htb starts, it can only send about 2 packet and because of sched won't start too frequently, the desired rate can't be reached. I would suggest that buffer should be manually set by user, and converted to 10ms amount of data by default in future version of tc.
What about backward compatibility with older kernels. Maybe the kernel should just be fixed instead.
2012/6/20 Stephen Hemminger <shemminger@vyatta.com>: Good point. tc communicate to htb by the netlink socket. buffer/cbuffer value is set by tc because (old and present version of) htb require it. So that for backward compatibility tc should just add a few checks for example if get_hz() may return 10^9 or 10^6, fallback to 100, which in another word means 10ms.
Hi, I just realized that buffer is converted to time by tc before it's send to HTB. In the old version of HTB it's the limit of how much data measured in time can be sent at once(in 1 time unit). Basicly buffer value is used as fine control of the speed limiting, which define the peak rate measured in a smaller unit of time. So It's still possible just change the kernel code to choose a fine control time unit and then multiply to calculate the amount of data or let user pass this value to the kernel (via tc, however). But then the workaround of "+ mtu" will be a new problem. 2012/6/20 YANG Zhe <yangzhe1990@gmail.com>: