I was recently tasked with setting up QoS on a gentoo box. I didn't know anything about it and now after several days of reading I don't know much more! But I couldn't find a good single source of detailed documentation on HFSC either. After scouring the internet a bit I found a lot of bits here and there. So I decided to put all those bits together here both for my own future reference and for everybody else.
There's apparently several QoS types such as HTB, HFSC, and SFQ? I read that HTB allows you to set min/max bandwidth for packets and set how much a queue can borrow from another. Sounds cool. Then I read about HFSC and how it lets you focus more on latency of packets. This won me over immediately because latency is very important to me.
You will need who knows what enabled in your kernel.. (yeah, helpful, right?) I just compiled all the QoS stuff as modules and let the kernel autoload stuff as needed. Probably not your bag of chips but it works.
You need to emerge/get/install iproute2 and iptables
Hey, I didn't know what the heck this stuff was when I got into this QoS mess. So here's a few terms used and what the heck they are. This also explains how some of the pieces work together.
HFSC has the major advantage compared to HTB that it also allows a proportional distribution of bandwidth as well as control and allocation of latencies. This enables you to better and more efficiently use connections for situations in which both bandwidth intensive data services and interactive services share a single network link. It is particularly interesting for Voice over IP and other real-time connections.
Qdisc is short for Queue Discipline, meaning a specific strategy used to manage a queue. The queue in the post-office and the queue at an emergency room are both queues in the sense they are both lines of “items”, but the strategy (or qdisc) used to manage them is very different.
The qdisc organizes packets into classes, using filters. Filtering can be done using marks. Each class is a queue in its own right, and therefore uses yet another qdisc. You can think of classes as the doors from where the bandwidth pass. You must classify the traffic in the correct door that limits that kind of traffic.
A rate is the amount of bandwidth a qdisc is guaranteed. For example, in an ideal world, an upload rate of 128 kbit/s would mean that the ISP will always give us at least that amount of bandwidth, or more if available.
The root class is the start of the hierarchy and defines the max bandwidth of the interface and the default class of uncategorized packets.
Inner classes are one step below the root class. They define max bandwidth / latency curves for their leaf classes. I think Inner classes are not required as you can have leaf classes under the root class without having them inside inner classes. But an inner class helps separate things out if needed?..
A leaf class is a class that actually has packets assigned to it. You also define the service curve for whatever packets are assigned to this class.
A service curve is a definition of the bandwidth and latency requirements for a class. Below lists the possible combinations of service curves that can be defined for a specific class.
This curve defines the amount of Guaranteed bandwidth / latency. RT SC's are only valid for Leaf classes
I'm a bit fuzzy on LS (and UL). My current understanding is that the LS curve defines the bandwidth that a class can -borrow- from other classes. I've read that if LS is defined it must be >= RT. I'm sure sure why just yet.
This curve defines the upper limit of bandwidth / latency that a class can use. A UL SC cannot be defined for a class unless the LS SC is also defined? I've read that if UL is defined it must be >= LS ⇒ RT
SC is the Service Curve or a SC Service Curve?
Now I'm not sure about this mumbo jumbo.. but.. Here's my attempt at explaining the command-line arguements for tc when implementing hfsc. tc syntax
Classes at the lowest level of the hierarchy can be assigned a real-time curve (rt) as well as a link-sharing curve (ls), where inner classes can only have a link-sharing curve. By using the ul service curve, an upper limit on service actually rendered to each class can be defined. Instead of specifying two identical rt and ls curves, a single sc curve can be specified. A service curve is described by its transmission rate, which correlates with the slope of the curve. If the curve consists of two parts, it can be specified with dmax the maximum delay at a certain transmission rate umax.
So each class you define can either have a rt or ls curve at ul rate. Each curve can be defined via the two displayed methods. From my understanding the first method of describing the service curve is basiclly you saying “I want this much speed for x time then give this much speed for the rest..” While the second method is saying “Do this much work every x often” This is hazy for me.. But documentation seems really sparse on hfsc..
Usage: … hfsc [ [ rt SC ] [ ls SC ] | [ sc SC ] ] [ ul SC ]
* rt = real-time curve
This is the “new” SC format?
Usage … hfsc SC := [ [ m1 BPS ] [ d SEC ] m2 BPS
* m1 = slope of first segment
This is the “old” SC format?
Usage … hfsc SC := [ [ umax BYTE ] dmax SEC ] rate BPS
* umax = maximum unit of work
This example configuration assumes we're applying QoS to eth0 on a connection with a 1024kbit upload/send speed.
Create the HFSC root qdisc and define the default qos class
tc qdisc add dev $DEV root handle 1: hfsc default 14
set the main rate limit class ( defines upload bandwidth of the link )
tc class add dev $DEV parent 1: classid 1:1 hfsc sc rate ${SEND}kbit ul rate ${SEND}kbit
<pre> # Guarantee full uplink for 200ms, then 3/10 tc class add dev eth0 parent 1:1 classid 1:11 hfsc sc m1 1024kbit d 200ms m2 $1)kbit ul rate 1024kbit
# Interactive traffic: guarantee realtime full uplink for 50ms, then 5/10 of the uplink tc class add dev eth0 parent 1:1 classid 1:12 hfsc \
rt m1 1024kbit d 50ms m2 $((5*1024/10))kbit \ ls m1 1024kbit d 50ms m2 $((7*1024/10))kbit \ ul rate 1024kbit
# C3 - Add defination for class 3. # Browsing: Don't guarantee anything for the first second, then guarantee 1/10 tc class add dev eth0 parent 1:1 classid 1:13 hfsc \
sc m1 0 d 1s m2 $((1*1024/10))kbit \ ul rate 1024kbit
# C4 - Add defination for class 4. # Default traffic: don't guarantee anything for the first two seconds, then guarantee 1/20 tc class add dev eth0 parent 1:1 classid 1:14 hfsc \
sc m1 0 d 2s m2 $((1*1024/20))kbit \ ul rate 1024kbit
# C5 - Add defination for class 5. # p2p traffic: don't guarantee anything for the first 10 seconds, # then guarantee 1/20 tc class add dev eth0 parent 1:1 classid 1:6 hfsc \
sc m1 0 d 10s m2 $((1*1024/20))kbit \ ul rate 1024kbit
</pre>
tc qdisc add dev eth0 root handle 1: hfsc
tc class add dev eth0 parent 1: classid 1:1 hfsc sc rate 1000kbit ul rate 1000kbit
tc class add dev eth0 parent 1:1 classid 1:10 hfsc sc rate 500kbit ul rate 1000kbit
tc class add dev eth0 parent 1:1 classid 1:20 hfsc sc rate 500kbit ul rate 1000kbit
tc class add dev eth0 parent 1:10 classid 1:11 hfsc sc umax 1500b dmax 53ms rate 400kbit ul rate 1000kbit
tc class add dev eth0 parent 1:10 classid 1:12 hfsc sc umax 1500b dmax 30ms rate 100kbit ul rate 1000kbit
To delete the tc rules
tc qdisc del dev $dev root
tc -s qdisc show dev vlan1
tc -s class show dev vlan1
tc class del dev eth0 classid 1:1
ooh.. one more thing, would be to add a rule that would match on port ssh AND length greater than say.. 1024 like this:
iptables -t mangle -A MYSHAPER-OUT -p tcp -m length –length 1024: –dport ssh -j MARK –set-mark 26 # large ssh=scp! http://jared.sonicspike.net/pipermail/adsl-qos/2003-April/000405.html