HFSC Scheduling with Linux
© 2005 Klaus Rechert, Patrick McHardy © 2006 Martin A. Brown (translation)
For complex traffic shaping scenarios, hierarchical algorithms are necessary. Current versions of Linux support the algorithms HTB and HFSC. While HTB basically rearranges token bucket filter (TBF) into a hierarchical structure, thereby retaining the principal characteristics of TBF, HFSC allows proportional distribution of bandwidth as well as control and allocation of latencies. This allows for better and more efficient use of a connection for situations in which both bandwidth intensive data services and interactive services share a single network link.
When network access is used by multiple entities or for different services, then some sort of reasonable resource management is required. The assurance of minimum bandwidth for the individual services and users (link-sharing) is one possible solution. For scenarios involving Voice over IP or streaming services, both pure bandwidth allocation and also prevention of high delay times become important.

In one scenario two users share a single Internet connection with a 1000 kbit capacity; each user should have control of at least 500 kbit of that capacity at any given moment. One of the users (party A) uses a maximum of 100 kbit of his bandwidth for Internet telephony and the remainder of the transmission capacity for general data transport. Figure 1 shows the corresponding hierarchy.


Figure 1: Hierarchy of shared network access.
Assume that all packets to be sent conform to a fixed size of 1500 bytes and all classes are sending at maximum rate. Based on the 1000 kbit link capacity, it takes 12ms (8*1500 byte / 1000000 bit/s = 12ms) to send a packet. The Voice over IP application sends at 100kbit which corresponds to 8 packets per second. In order to meet the guaranteed 100kbit rate for this class, the qdisc must send a packet from this class every 120ms, which would mean a maximum [queuing] delay of 132ms per packet. This example illustrates the relationship between bandwidth and delay.

The HFSC algorithm is in a position to deal with both of these resources, bandwidth and delay. For this, the algorithm uses the service curve model for the allocation of resources. A service curve S(t) represents the work achieved (service) in bits at time t. The slope of the curve corresponds to the rate of transmission.

The concept of the interaction with latency resides in the structure of the service curves of the individual classes. By selecting a two-part service curve, each section of which is linear, the transmission delay for the Voice over IP class can be reduced to 30 ms. The first section of the service curve features a 400 kbit slope of 30 ms duration, where the second section exhibits a slope of 100kbit. This gain in decreased delay of approximately 78 ms is earned at the expense of other classes. At no point, though, is the sum of the curves allowed to exceed the service curve of the total link capacity. In our example, the decreased delay for the Voice over IP class occurs at the cost of party A's unspecified data class, whose service curve must be adjusted in order not to to exceed the global limit. As a result, the maximum transmission delay of this class increases from 30ms to a total of 52.5 ms. For bulk data transport, such as FTP, for example, delay simply plays a secondary role in contrast to that of throughput, which isn't impaired by conforming to the service curve.


Figure 2: Scenario with linear and multi-part linear service curves.
The HFSC algorithm differentiates between real-time and link-sharing criteria. A leaf class can be assigned a real-time and a link-sharing curve, where inner classes can only have a link-sharing curve. The real-time criterion can only be applied to leaf classes because only these classes actually hold packets. This real-time oriented criterion is therefore responsible for carrying out the guaranteed service. The link-sharing criterion only concerns itself with relationships to neighboring classes. It is responsible for fair distribution of service rather than absolute guarantees. This separation into two criteria is necessary in order to be able to meet the guaranteed delay times under all circumstances. This also means that a class can send a packet on the basis of its real-time guarantee even if the link-sharing curve of a class higher in the hierarchy is briefly violated, as a result.

Let's say our example data class from party A is already active and sending at its maximum packet rate, 400 kbit. Now, if at any point in time, the Voice over IP class becomes active, it is allowed to send with a higher rate on account of its real-time guarantee (Figure 3). Thus, the service for class A, totals to above 500 kbit, meaning that the link-sharing parameter for this class has been violated in the short term. In order to be able to carry out the link-sharing guarantees over the long term, class A will be "punished" for this brief excess.


Figure 3: Between t1 and t2, exceeds the total maximum allowed capacity.
Each of the classes in the hierarchy is assigned a "virtual time", which corresponds to service actually attained. As soon as it is possible to send a packet, each level of the hierarchy is searched, starting at the root, for the class exhibiting the least attained virtual time. The leaf class found with this method then sends a packet and the virtual time of that class, along with each of its parent classes all the way up to the root, will be increased accordingly. If a class sends based on its real-time parameter, its virtual time will also be increased.
HFSC usage on Linux
The first step to setting up an HFSC qdisc involves assigning a qdisc to a network interface, along with optional specification of a default class:

tc qdisc add dev $dev root handle $ID: hfsc [default $classID ]

In the second step, the class hierarchy is constructed with consecutive class additions. tc add class dev $dev parent parentID classid $ID hfsc [ [ rt SC ] [ ls SC ] | [ sc SC ] ] [ ul SC ]

The particular attributes of each class are configured via the service curves which are described as follows: SC := [ umax bytes dmax ms ] rate BPS

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.

Example
# Example from Figure 1. 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
References
[1] http://trash.net/~kaber/hfsc/

[2] http://developer.osdl.org/dev/iproute2/download/

[3] http://lartc.org/

[4] http://luxik.cdi.cz/~devik/qos/htb/

Translator's Note

The original German article, currently available at http://klaus.geekserver.net/hfsc/hfsc.html, was initially published by Linux Magazin in February 2005 (pages 28-37) in a series of articles on Queueing Disciplines and was later republished in special edition (Sonderheft) number 3, 2006 (pages 74-81).