Quality of Service (QoS)
Introduction to QoS
Quality of Service (QoS) is a method to divide available bandwidth into classes so that network service quality does not degrade during congestion. In essence, QoS gives different priorities to different applications, users, or data flows so that packets are sent in the proper order. This also means that QoS can guarantee a required bit rate, delay, jitter, or packet dropping probability. Such guarantees are especially important when network capacity is insufficientāreal-time streaming multimedia applications like VoIP (Voice over IP) and IP-TV often require a fixed bit rate and are very sensitive to delays.
Packet Queues
A packet queue determines the order in which packets are sent from a network interface. Packets waiting in the queue are managed by qdisc (queueing discipline) algorithms. These algorithms may drop, delay, or reorder packets. There are two basic types of qdiscs: classless qdisc and classful qdisc.
Classless qdisc
A classless qdisc does not contain other qdiscs. It simply determines whether a packet is classified, delayed, or dropped. Common examples include:
- FIFO ā The simplest qdisc, which operates strictly on a First In First Out basis. It is not very fair or adjustable.
- TBF ā Token Bucket Filter is ideal for throttling traffic to a precise rate. Packets are stored in a ābucketā and released at a steady rate. If the bucket overflows, packets are dropped, helping to smooth out small dropouts.
- SFQ ā Stochastic Fairness Queueing attempts to fairly share transmission opportunities among an arbitrary number of flows by using a hash function to distribute traffic into multiple internal FIFOs that are then dequeued roundārobin. Because the hash function may cause unevenness, it is periodically altered; the perturb parameter controls this periodicity.
- RED ā Random Early Detection simulates congestion by randomly dropping packets as the configured bandwidth allocation nears its limit. This qdisc is useful on backbone networks.
- WRED ā A variant of RED that supports traffic priorities.
If no qdisc type is defined, the system automatically defaults to a FIFO queue. To select a different queue, use the following command:
tc qdisc add dev <device> root <qdisc> <qdisc parameters>To remove a queue, use:
tc qdisc del dev <device> rootClassful qdisc
A classful qdisc can contain other qdiscs (either classless or classful), thereby creating a tree of classes. In such a tree, internal nodes (including the root) contain further classful qdiscs, and the leaves contain classless qdiscs. Each classful qdisc may also have filters that determine to which child qdisc a packet is forwarded. In this way, packets traverse a tree structure until they reach a leaf.
Common classful qdiscs include:
- PRIO ā Creates three classes with priorities 0, 1, and 2. Classes are processed sequentially from the lowest to the highest priority.
- CBQ ā Class Based Queueing implements a hierarchical link-sharing scheme and supports priorities.
- HTB ā Hierarchical Token Bucket is designed as a more intuitive replacement for CBQ. It enables bandwidth guarantees for classes while allowing specification of upper limits on inter-class sharing.
Configuration
Configuration of QoS is performed using the tc (traffic control) utility from the iproute package. Qdisc disciplines are expressed in the number:number formatāthe first number (before the colon) is the qdisc identifier, and the second (after the colon) is the class identifier. These identifiers must be unique for proper identification.
When creating a tree structure, note that the bandwidth of a parent node must exceed the sum of its childrenās guaranteed throughputs. In other words, it is inappropriate for a tree to have many leaves whose guaranteed rates are much lower than the total available throughput.
Shaping
Shaping delays packets in an output queue so that the overall transmission rate meets a desired output rate. This is a common method for bandwidth control.
For example, suppose you have a 1 Mbps connection and wish to share it among three users such that:
- User 1 is guaranteed a minimum of 512 kbps
- Users 2 and 3 are guaranteed 256 kbps each
If any user does not use all of their allocated capacity, the unused bandwidth is redistributed among the others. (Assume the usersā IP addresses are 10.0.0.10, 10.0.0.11, and 10.0.0.12.)
First, create a structure of HTB (Hierarchical Token Bucket) classes. The root class represents the entire link capacity, and three subclasses represent the individual users:
tc qdisc del dev eth0 root
tc qdisc add dev eth0 root handle 1: htb default 1
tc class add dev eth0 parent 1: classid 1:1 htb rate 1024kbit
tc class add dev eth0 parent 1:1 classid 1:11 htb rate 512Kbit ceil 1024kbit
tc class add dev eth0 parent 1:1 classid 1:12 htb rate 256Kbit ceil 1024kbit
tc class add dev eth0 parent 1:1 classid 1:13 htb rate 256Kbit ceil 1024kbitClasses with higher priority are typically listed first. The rate parameter defines the guaranteed throughput (the sum of the childrenās rates should not exceed the parentās rate), and the ceil parameter specifies the maximum throughput for each class (each childās ceil should not exceed the parentās ceil).
Although FIFO is the default queue for a qdisc, it is not very fair. Instead, it is better to use a fair queuing algorithm such as SFQ (Stochastic Fairness Queueing). The perturb parameter in SFQ specifies how often its hashing algorithm should be recalculated:
tc qdisc add dev eth0 parent 1:11 handle 11: sfq perturb 10
tc qdisc add dev eth0 parent 1:12 handle 12: sfq perturb 10
tc qdisc add dev eth0 parent 1:13 handle 13: sfq perturb 10Next, packets must be classified into the appropriate class. When traffic arrives at a class that contains subclasses, it needs to be classified. There are various methods to do this; two common methods are:
Classification Based on Destination IP Address
tc filter add dev eth0 parent 1:1 protocol ip u32 match ip dst 10.0.0.10 flowid 1:11
tc filter add dev eth0 parent 1:1 protocol ip u32 match ip dst 10.0.0.11 flowid 1:12
tc filter add dev eth0 parent 1:1 protocol ip u32 match ip dst 10.0.0.12 flowid 1:13Classification Based on iptables Marking
iptables -t mangle -A FORWARD -d 10.0.0.10 -j MARK --set-mark 10
iptables -t mangle -A FORWARD -d 10.0.0.11 -j MARK --set-mark 11
iptables -t mangle -A FORWARD -d 10.0.0.12 -j MARK --set-mark 12
tc filter add dev eth0 parent 1: protocol ip handle 10 fw flowid 1:11
tc filter add dev eth0 parent 1: protocol ip handle 11 fw flowid 1:12
tc filter add dev eth0 parent 1: protocol ip handle 12 fw flowid 1:13The first method is best suited for simple rules, while the second methodābased on iptables markingācan be used for more complex classifications (for example, based on MAC addresses), though it is slightly slower.