In this tutorial, we are going to learn how to write/customise a traffic control script.
Let’s take the following traffic control configuration as an example:
# clearing any potentially existing qdisc on eth0
tc qdisc del dev eth0 root
# adding a new qdisc on eth0
tc qdisc add dev eth0 root handle 1: htb default 10
# defining different classes with identical policy
# parent class
tc class add dev eth0 parent 1: classid 1:1 htb rate 90mbps ceil 90mbps
# classid 1:10
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 30mbps ceil 60mbps
# classid 1:11
tc class add dev eth0 parent 1:1 classid 1:11 htb rate 30mbps ceil 60mbps
# classid 1:12
tc class add dev eth0 parent 1:1 classid 1:12 htb rate 30mbps ceil 60mbps
# defining filters and assigning them to the specified classes
# client machine 1 assigned to classid 1:10
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 172.16.5.10 flowid 1:10
# client machine 2 assigned to classid 1:11
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 172.16.5.11 flowid 1:11
# client machine 3 assigned to classid 1:12
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 172.16.5.12 flowid 1:12
Before starting to adjust the parameters of each component there a few concepts you need to understand.
There are 3 main components of Linux Traffic Control: Qdisc, Class, Filter
A qdisc is nothing more than a scheduler. Every output interface needs a scheduler of some kind, and the default scheduler is a FIFO (Fist In First Out). Other qdiscs available under Linux will rearrange the packets entering the scheduler’s queue in accordance with that scheduler’s rules.
The qdisc (queuing discipline) is the most important component of traffic control.
A qdisc can contain classes, and provide a handle to which to attach filters.
For traffic accepted on an interface, the ingress qdisc is traversed.
For traffic sent from an interface, he egress qdisc is traversed.
For a DDP usage, egress qdisc (also called root qdisc) only is being used as it offers much more capabilities and delivers the full power of the traffic control system. An ingress qdisc can only support a policer whereas an egress qdisc fully supports all the functionalities of traffic control.
Below is a short description of the parameters used for declaring a qdisc.
Add a queuing discipline
Specify the device onto which we are attaching the new queuing discipline.
This means “egress” to tc. The word root must be used, however. Another qdisc with limited functionality, the ingress qdisc can be attached to the same device.
The handle is a user-specified number of the form major:minor. The minor number for any queueing discipline handle must always be zero (0). An acceptable shorthand for a qdisc handle is the syntax “1:”, where the minor number is assumed to be zero (0) if not specified.
This is the queuing discipline to attach, HTB in this example. Queuing discipline specific parameters will follow this. In the example here, we add no qdisc-specific parameters.
Classes only exist inside a root (egress) qdisc. Classes are immensely flexible and can always contain either multiple children classes or a single child qdisc.
Any class can also have an arbitrary number of filters attached to it, which allows the selection of a child class or the use of a filter to reclassify or drop traffic entering a particular class.
A leaf class is a terminal class in a qdisc. It contains a qdisc and will never contain a child class.
Any class which contains a child class is called an inner class (or root class).
Below is a short description of the parameters used for declaring a class.
Add a class.
Specify the device onto which we are attaching the new class.
Specify the parent handle to which we are attaching the new class.
This is a unique handle (major:minor) identifying this class. The minor number must be any non-zero (0) number.
Classful qdiscs require that any children classes be classes of the same type as the parent. Thus an HTB qdisc will contain HTB classes.
Used to set the minimum desired speed to which to limit transmitted traffic.
Used to set the maximum desired speed to which to limit the transmitted traffic. This can be considered the equivalent of “burstable bandwidth”.
The filter is the most complex component in the Linux traffic control system. The filter provides a convenient mechanism for gluing together several of the key elements of traffic control. The simplest and most obvious role of the filter is to classify packets. Linux filters allow the user to classify packets into an output queue with either several different filters or a single filter.
A filter must contain a classifier phrase.
A filter may contain a policer phrase.
Filters can be attached either to classful qdiscs or to classes, however the enqueued packet always enters the root qdisc first. After the filter attached to the root qdisc has been traversed, the packet may be directed to any subclasses (which can have their own filters) where the packet may undergo further classification.
Below is a short description of the parameters used for declaring a filter.
Add a filter.
Specify the device onto which we are attaching the new filter.
Specify the parent handle to which we are attaching the new filter.
The prio parameter allows a given filter to be preferred above another. The pref is a synonym.
match ip dst 172.16.5.10:
These are parameters to the classifier. In this case, packets intended to 172.16.5.10 will match.
The flowid specifies the handle of the target class (or qdisc) to which a matching filter should send its selected packets.